| /* |
| * libjingle |
| * Copyright 2004--2005, Google Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "talk/base/win32.h" |
| #include <algorithm> |
| |
| #include "talk/base/basictypes.h" |
| #include "talk/base/common.h" |
| |
| namespace talk_base { |
| |
| // |
| // Unix time is in seconds relative to 1/1/1970. So we compute the windows |
| // FILETIME of that time/date, then we add/subtract in appropriate units to |
| // convert to/from unix time. |
| // The units of FILETIME are 100ns intervals, so by multiplying by or dividing |
| // by 10000000, we can convert to/from seconds. |
| // |
| // FileTime = UnixTime*10000000 + FileTime(1970) |
| // UnixTime = (FileTime-FileTime(1970))/10000000 |
| // |
| |
| void FileTimeToUnixTime(const FILETIME& ft, time_t* ut) { |
| ASSERT(NULL != ut); |
| |
| // FILETIME has an earlier date base than time_t (1/1/1970), so subtract off |
| // the difference. |
| SYSTEMTIME base_st; |
| memset(&base_st, 0, sizeof(base_st)); |
| base_st.wDay = 1; |
| base_st.wMonth = 1; |
| base_st.wYear = 1970; |
| |
| FILETIME base_ft; |
| SystemTimeToFileTime(&base_st, &base_ft); |
| |
| ULARGE_INTEGER base_ul, current_ul; |
| memcpy(&base_ul, &base_ft, sizeof(FILETIME)); |
| memcpy(¤t_ul, &ft, sizeof(FILETIME)); |
| |
| // Divide by big number to convert to seconds, then subtract out the 1970 |
| // base date value. |
| const ULONGLONG RATIO = 10000000; |
| *ut = static_cast<time_t>((current_ul.QuadPart - base_ul.QuadPart) / RATIO); |
| } |
| |
| void UnixTimeToFileTime(const time_t& ut, FILETIME* ft) { |
| ASSERT(NULL != ft); |
| |
| // FILETIME has an earlier date base than time_t (1/1/1970), so add in |
| // the difference. |
| SYSTEMTIME base_st; |
| memset(&base_st, 0, sizeof(base_st)); |
| base_st.wDay = 1; |
| base_st.wMonth = 1; |
| base_st.wYear = 1970; |
| |
| FILETIME base_ft; |
| SystemTimeToFileTime(&base_st, &base_ft); |
| |
| ULARGE_INTEGER base_ul; |
| memcpy(&base_ul, &base_ft, sizeof(FILETIME)); |
| |
| // Multiply by big number to convert to 100ns units, then add in the 1970 |
| // base date value. |
| const ULONGLONG RATIO = 10000000; |
| ULARGE_INTEGER current_ul; |
| current_ul.QuadPart = base_ul.QuadPart + static_cast<int64>(ut) * RATIO; |
| memcpy(ft, ¤t_ul, sizeof(FILETIME)); |
| } |
| |
| bool Utf8ToWindowsFilename(const std::string& utf8, std::wstring* filename) { |
| // TODO: Integrate into fileutils.h |
| // TODO: Handle wide and non-wide cases via TCHAR? |
| // TODO: Skip \\?\ processing if the length is not > MAX_PATH? |
| // TODO: Write unittests |
| |
| // Convert to Utf16 |
| int wlen = ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.length() + 1, |
| NULL, 0); |
| if (0 == wlen) { |
| return false; |
| } |
| wchar_t* wfilename = STACK_ARRAY(wchar_t, wlen); |
| if (0 == ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.length() + 1, |
| wfilename, wlen)) { |
| return false; |
| } |
| // Replace forward slashes with backslashes |
| std::replace(wfilename, wfilename + wlen, L'/', L'\\'); |
| // Convert to complete filename |
| DWORD full_len = ::GetFullPathName(wfilename, 0, NULL, NULL); |
| if (0 == full_len) { |
| return false; |
| } |
| wchar_t* filepart = NULL; |
| wchar_t* full_filename = STACK_ARRAY(wchar_t, full_len + 6); |
| wchar_t* start = full_filename + 6; |
| if (0 == ::GetFullPathName(wfilename, full_len, start, &filepart)) { |
| return false; |
| } |
| // Add long-path prefix |
| const wchar_t kLongPathPrefix[] = L"\\\\?\\UNC"; |
| if ((start[0] != L'\\') || (start[1] != L'\\')) { |
| // Non-unc path: <pathname> |
| // Becomes: \\?\<pathname> |
| start -= 4; |
| ASSERT(start >= full_filename); |
| memcpy(start, kLongPathPrefix, 4 * sizeof(wchar_t)); |
| } else if (start[2] != L'?') { |
| // Unc path: \\<server>\<pathname> |
| // Becomes: \\?\UNC\<server>\<pathname> |
| start -= 6; |
| ASSERT(start >= full_filename); |
| memcpy(start, kLongPathPrefix, 7 * sizeof(wchar_t)); |
| } else { |
| // Already in long-path form. |
| } |
| filename->assign(start); |
| return true; |
| } |
| |
| bool GetOsVersion(int* major, int* minor, int* build) { |
| OSVERSIONINFO info = {0}; |
| info.dwOSVersionInfoSize = sizeof(info); |
| if (GetVersionEx(&info)) { |
| if (major) *major = info.dwMajorVersion; |
| if (minor) *minor = info.dwMinorVersion; |
| if (build) *build = info.dwBuildNumber; |
| return true; |
| } |
| return false; |
| } |
| |
| bool GetCurrentProcessIntegrityLevel(int* level) { |
| bool ret = false; |
| HANDLE process = ::GetCurrentProcess(), token; |
| if (OpenProcessToken(process, TOKEN_QUERY | TOKEN_QUERY_SOURCE, &token)) { |
| DWORD size; |
| if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &size) && |
| GetLastError() == ERROR_INSUFFICIENT_BUFFER) { |
| |
| char* buf = STACK_ARRAY(char, size); |
| TOKEN_MANDATORY_LABEL* til = |
| reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buf); |
| if (GetTokenInformation(token, TokenIntegrityLevel, til, size, &size)) { |
| |
| DWORD count = *GetSidSubAuthorityCount(til->Label.Sid); |
| *level = *GetSidSubAuthority(til->Label.Sid, count - 1); |
| ret = true; |
| } |
| } |
| CloseHandle(token); |
| } |
| return ret; |
| } |
| |
| } // namespace talk_base |
| |