• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FileTimeToUnixTime(const FILETIME & ft,time_t * ut)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(&current_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 
UnixTimeToFileTime(const time_t & ut,FILETIME * ft)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, &current_ul, sizeof(FILETIME));
94 }
95 
Utf8ToWindowsFilename(const std::string & utf8,std::wstring * filename)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 
GetOsVersion(int * major,int * minor,int * build)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 
GetCurrentProcessIntegrityLevel(int * level)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