1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/win32.h" 29 #include <algorithm> 30 31 #include "talk/base/basictypes.h" 32 #include "talk/base/common.h" 33 34 namespace talk_base { 35 36 // 37 // Unix time is in seconds relative to 1/1/1970. So we compute the windows 38 // FILETIME of that time/date, then we add/subtract in appropriate units to 39 // convert to/from unix time. 40 // The units of FILETIME are 100ns intervals, so by multiplying by or dividing 41 // by 10000000, we can convert to/from seconds. 42 // 43 // FileTime = UnixTime*10000000 + FileTime(1970) 44 // UnixTime = (FileTime-FileTime(1970))/10000000 45 // 46 47 void FileTimeToUnixTime(const FILETIME& ft, time_t* ut) { 48 ASSERT(NULL != ut); 49 50 // FILETIME has an earlier date base than time_t (1/1/1970), so subtract off 51 // the difference. 52 SYSTEMTIME base_st; 53 memset(&base_st, 0, sizeof(base_st)); 54 base_st.wDay = 1; 55 base_st.wMonth = 1; 56 base_st.wYear = 1970; 57 58 FILETIME base_ft; 59 SystemTimeToFileTime(&base_st, &base_ft); 60 61 ULARGE_INTEGER base_ul, current_ul; 62 memcpy(&base_ul, &base_ft, sizeof(FILETIME)); 63 memcpy(¤t_ul, &ft, sizeof(FILETIME)); 64 65 // Divide by big number to convert to seconds, then subtract out the 1970 66 // base date value. 67 const ULONGLONG RATIO = 10000000; 68 *ut = static_cast<time_t>((current_ul.QuadPart - base_ul.QuadPart) / RATIO); 69 } 70 71 void UnixTimeToFileTime(const time_t& ut, FILETIME* ft) { 72 ASSERT(NULL != ft); 73 74 // FILETIME has an earlier date base than time_t (1/1/1970), so add in 75 // the difference. 76 SYSTEMTIME base_st; 77 memset(&base_st, 0, sizeof(base_st)); 78 base_st.wDay = 1; 79 base_st.wMonth = 1; 80 base_st.wYear = 1970; 81 82 FILETIME base_ft; 83 SystemTimeToFileTime(&base_st, &base_ft); 84 85 ULARGE_INTEGER base_ul; 86 memcpy(&base_ul, &base_ft, sizeof(FILETIME)); 87 88 // Multiply by big number to convert to 100ns units, then add in the 1970 89 // base date value. 90 const ULONGLONG RATIO = 10000000; 91 ULARGE_INTEGER current_ul; 92 current_ul.QuadPart = base_ul.QuadPart + static_cast<int64>(ut) * RATIO; 93 memcpy(ft, ¤t_ul, sizeof(FILETIME)); 94 } 95 96 bool Utf8ToWindowsFilename(const std::string& utf8, std::wstring* filename) { 97 // TODO: Integrate into fileutils.h 98 // TODO: Handle wide and non-wide cases via TCHAR? 99 // TODO: Skip \\?\ processing if the length is not > MAX_PATH? 100 // TODO: Write unittests 101 102 // Convert to Utf16 103 int wlen = ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.length() + 1, 104 NULL, 0); 105 if (0 == wlen) { 106 return false; 107 } 108 wchar_t* wfilename = STACK_ARRAY(wchar_t, wlen); 109 if (0 == ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.length() + 1, 110 wfilename, wlen)) { 111 return false; 112 } 113 // Replace forward slashes with backslashes 114 std::replace(wfilename, wfilename + wlen, L'/', L'\\'); 115 // Convert to complete filename 116 DWORD full_len = ::GetFullPathName(wfilename, 0, NULL, NULL); 117 if (0 == full_len) { 118 return false; 119 } 120 wchar_t* filepart = NULL; 121 wchar_t* full_filename = STACK_ARRAY(wchar_t, full_len + 6); 122 wchar_t* start = full_filename + 6; 123 if (0 == ::GetFullPathName(wfilename, full_len, start, &filepart)) { 124 return false; 125 } 126 // Add long-path prefix 127 const wchar_t kLongPathPrefix[] = L"\\\\?\\UNC"; 128 if ((start[0] != L'\\') || (start[1] != L'\\')) { 129 // Non-unc path: <pathname> 130 // Becomes: \\?\<pathname> 131 start -= 4; 132 ASSERT(start >= full_filename); 133 memcpy(start, kLongPathPrefix, 4 * sizeof(wchar_t)); 134 } else if (start[2] != L'?') { 135 // Unc path: \\<server>\<pathname> 136 // Becomes: \\?\UNC\<server>\<pathname> 137 start -= 6; 138 ASSERT(start >= full_filename); 139 memcpy(start, kLongPathPrefix, 7 * sizeof(wchar_t)); 140 } else { 141 // Already in long-path form. 142 } 143 filename->assign(start); 144 return true; 145 } 146 147 bool GetOsVersion(int* major, int* minor, int* build) { 148 OSVERSIONINFO info = {0}; 149 info.dwOSVersionInfoSize = sizeof(info); 150 if (GetVersionEx(&info)) { 151 if (major) *major = info.dwMajorVersion; 152 if (minor) *minor = info.dwMinorVersion; 153 if (build) *build = info.dwBuildNumber; 154 return true; 155 } 156 return false; 157 } 158 159 bool GetCurrentProcessIntegrityLevel(int* level) { 160 bool ret = false; 161 HANDLE process = GetCurrentProcess(), token; 162 if (OpenProcessToken(process, TOKEN_QUERY | TOKEN_QUERY_SOURCE, &token)) { 163 DWORD size; 164 if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &size) && 165 GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 166 167 char* buf = STACK_ARRAY(char, size); 168 TOKEN_MANDATORY_LABEL* til = 169 reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buf); 170 if (GetTokenInformation(token, TokenIntegrityLevel, til, size, &size)) { 171 172 DWORD count = *GetSidSubAuthorityCount(til->Label.Sid); 173 *level = *GetSidSubAuthority(til->Label.Sid, count - 1); 174 ret = true; 175 } 176 } 177 CloseHandle(token); 178 } 179 return ret; 180 } 181 182 } // namespace talk_base 183 184