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