Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: base/win_util.cc

Issue 3823002: Move windows version-related stuff out of base/win_util and into base/win/win... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/win_util.h" 5 #include "base/win_util.h"
6 6
7 #include <aclapi.h> 7 #include <aclapi.h>
8 #include <shobjidl.h> // Must be before propkey.
9 #include <propkey.h>
8 #include <propvarutil.h> 10 #include <propvarutil.h>
9 #include <sddl.h> 11 #include <sddl.h>
10 #include <shlobj.h> 12 #include <shlobj.h>
11 13
12 #include "base/logging.h" 14 #include "base/logging.h"
13 #include "base/registry.h" 15 #include "base/registry.h"
14 #include "base/scoped_handle.h" 16 #include "base/scoped_handle.h"
15 #include "base/scoped_ptr.h" 17 #include "base/scoped_ptr.h"
16 #include "base/string_util.h" 18 #include "base/string_util.h"
17 #include "base/stringprintf.h" 19 #include "base/stringprintf.h"
20 #include "base/win/windows_version.h"
18 21
19 namespace win_util { 22 namespace win_util {
20 23
21 #define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(struct_name, member) \ 24 #define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(struct_name, member) \
22 offsetof(struct_name, member) + \ 25 offsetof(struct_name, member) + \
23 (sizeof static_cast<struct_name*>(NULL)->member) 26 (sizeof static_cast<struct_name*>(NULL)->member)
24 #define NONCLIENTMETRICS_SIZE_PRE_VISTA \ 27 #define NONCLIENTMETRICS_SIZE_PRE_VISTA \
25 SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont) 28 SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
26 29
27 const PROPERTYKEY kPKEYAppUserModelID =
28 { { 0x9F4C2855, 0x9F79, 0x4B39,
29 { 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, } }, 5 };
30
31 void GetNonClientMetrics(NONCLIENTMETRICS* metrics) { 30 void GetNonClientMetrics(NONCLIENTMETRICS* metrics) {
32 DCHECK(metrics); 31 DCHECK(metrics);
33 32
34 static const UINT SIZEOF_NONCLIENTMETRICS = 33 static const UINT SIZEOF_NONCLIENTMETRICS =
35 (GetWinVersion() >= WINVERSION_VISTA) ? 34 (base::win::GetVersion() >= base::win::VERSION_VISTA) ?
36 sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA; 35 sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
37 metrics->cbSize = SIZEOF_NONCLIENTMETRICS; 36 metrics->cbSize = SIZEOF_NONCLIENTMETRICS;
38 const bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 37 const bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
39 SIZEOF_NONCLIENTMETRICS, metrics, 38 SIZEOF_NONCLIENTMETRICS, metrics,
40 0); 39 0);
41 DCHECK(success); 40 DCHECK(success);
42 } 41 }
43 42
44 WinVersion GetWinVersion() {
45 static bool checked_version = false;
46 static WinVersion win_version = WINVERSION_PRE_2000;
47 if (!checked_version) {
48 OSVERSIONINFOEX version_info;
49 version_info.dwOSVersionInfoSize = sizeof version_info;
50 GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
51 if (version_info.dwMajorVersion == 5) {
52 switch (version_info.dwMinorVersion) {
53 case 0:
54 win_version = WINVERSION_2000;
55 break;
56 case 1:
57 win_version = WINVERSION_XP;
58 break;
59 case 2:
60 default:
61 win_version = WINVERSION_SERVER_2003;
62 break;
63 }
64 } else if (version_info.dwMajorVersion == 6) {
65 if (version_info.wProductType != VER_NT_WORKSTATION) {
66 // 2008 is 6.0, and 2008 R2 is 6.1.
67 win_version = WINVERSION_2008;
68 } else {
69 if (version_info.dwMinorVersion == 0) {
70 win_version = WINVERSION_VISTA;
71 } else {
72 win_version = WINVERSION_WIN7;
73 }
74 }
75 } else if (version_info.dwMajorVersion > 6) {
76 win_version = WINVERSION_WIN7;
77 }
78 checked_version = true;
79 }
80 return win_version;
81 }
82
83 void GetServicePackLevel(int* major, int* minor) {
84 DCHECK(major && minor);
85 static bool checked_version = false;
86 static int service_pack_major = -1;
87 static int service_pack_minor = -1;
88 if (!checked_version) {
89 OSVERSIONINFOEX version_info = {0};
90 version_info.dwOSVersionInfoSize = sizeof(version_info);
91 GetVersionEx(reinterpret_cast<OSVERSIONINFOW*>(&version_info));
92 service_pack_major = version_info.wServicePackMajor;
93 service_pack_minor = version_info.wServicePackMinor;
94 checked_version = true;
95 }
96
97 *major = service_pack_major;
98 *minor = service_pack_minor;
99 }
100
101 bool AddAccessToKernelObject(HANDLE handle, WELL_KNOWN_SID_TYPE known_sid,
102 ACCESS_MASK access) {
103 PSECURITY_DESCRIPTOR descriptor = NULL;
104 PACL old_dacl = NULL;
105 PACL new_dacl = NULL;
106
107 if (ERROR_SUCCESS != GetSecurityInfo(handle, SE_KERNEL_OBJECT,
108 DACL_SECURITY_INFORMATION, NULL, NULL, &old_dacl, NULL,
109 &descriptor))
110 return false;
111
112 BYTE sid[SECURITY_MAX_SID_SIZE] = {0};
113 DWORD size_sid = SECURITY_MAX_SID_SIZE;
114
115 if (known_sid == WinSelfSid) {
116 // We hijack WinSelfSid when we want to add the current user instead of
117 // a known sid.
118 HANDLE token = NULL;
119 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)) {
120 LocalFree(descriptor);
121 return false;
122 }
123
124 DWORD size = sizeof(TOKEN_USER) + size_sid;
125 scoped_array<BYTE> token_user_bytes(new BYTE[size]);
126 TOKEN_USER* token_user =
127 reinterpret_cast<TOKEN_USER*>(token_user_bytes.get());
128 BOOL ret = GetTokenInformation(token, TokenUser, token_user, size, &size);
129
130 CloseHandle(token);
131
132 if (!ret) {
133 LocalFree(descriptor);
134 return false;
135 }
136 memcpy(sid, token_user->User.Sid, size_sid);
137 } else {
138 if (!CreateWellKnownSid(known_sid , NULL, sid, &size_sid)) {
139 LocalFree(descriptor);
140 return false;
141 }
142 }
143
144 EXPLICIT_ACCESS new_access = {0};
145 new_access.grfAccessMode = GRANT_ACCESS;
146 new_access.grfAccessPermissions = access;
147 new_access.grfInheritance = NO_INHERITANCE;
148
149 new_access.Trustee.pMultipleTrustee = NULL;
150 new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
151 new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
152 new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(&sid);
153
154 if (ERROR_SUCCESS != SetEntriesInAcl(1, &new_access, old_dacl, &new_dacl)) {
155 LocalFree(descriptor);
156 return false;
157 }
158
159 DWORD result = SetSecurityInfo(handle, SE_KERNEL_OBJECT,
160 DACL_SECURITY_INFORMATION, NULL, NULL,
161 new_dacl, NULL);
162
163 LocalFree(new_dacl);
164 LocalFree(descriptor);
165
166 if (ERROR_SUCCESS != result)
167 return false;
168
169 return true;
170 }
171
172 bool GetUserSidString(std::wstring* user_sid) { 43 bool GetUserSidString(std::wstring* user_sid) {
173 // Get the current token. 44 // Get the current token.
174 HANDLE token = NULL; 45 HANDLE token = NULL;
175 if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token)) 46 if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token))
176 return false; 47 return false;
177 ScopedHandle token_scoped(token); 48 ScopedHandle token_scoped(token);
178 49
179 DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; 50 DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
180 scoped_array<BYTE> user_bytes(new BYTE[size]); 51 scoped_array<BYTE> user_bytes(new BYTE[size]);
181 TOKEN_USER* user = reinterpret_cast<TOKEN_USER*>(user_bytes.get()); 52 TOKEN_USER* user = reinterpret_cast<TOKEN_USER*>(user_bytes.get());
182 53
183 if (!::GetTokenInformation(token, TokenUser, user, size, &size)) 54 if (!::GetTokenInformation(token, TokenUser, user, size, &size))
184 return false; 55 return false;
185 56
186 if (!user->User.Sid) 57 if (!user->User.Sid)
187 return false; 58 return false;
188 59
189 // Convert the data to a string. 60 // Convert the data to a string.
190 wchar_t* sid_string; 61 wchar_t* sid_string;
191 if (!::ConvertSidToStringSid(user->User.Sid, &sid_string)) 62 if (!::ConvertSidToStringSid(user->User.Sid, &sid_string))
192 return false; 63 return false;
193 64
194 *user_sid = sid_string; 65 *user_sid = sid_string;
195 66
196 ::LocalFree(sid_string); 67 ::LocalFree(sid_string);
197 68
198 return true; 69 return true;
199 } 70 }
200 71
201 bool GetLogonSessionOnlyDACL(SECURITY_DESCRIPTOR** security_descriptor) {
202 // Get the current token.
203 HANDLE token = NULL;
204 if (!OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token))
205 return false;
206 ScopedHandle token_scoped(token);
207
208 // Get the size of the TokenGroups structure.
209 DWORD size = 0;
210 BOOL result = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
211 if (result != FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
212 return false;
213
214 // Get the data.
215 scoped_array<char> token_groups_chars(new char[size]);
216 TOKEN_GROUPS* token_groups =
217 reinterpret_cast<TOKEN_GROUPS*>(token_groups_chars.get());
218
219 if (!GetTokenInformation(token, TokenGroups, token_groups, size, &size))
220 return false;
221
222 // Look for the logon sid.
223 SID* logon_sid = NULL;
224 for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
225 if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) != 0) {
226 logon_sid = static_cast<SID*>(token_groups->Groups[i].Sid);
227 break;
228 }
229 }
230
231 if (!logon_sid)
232 return false;
233
234 // Convert the data to a string.
235 wchar_t* sid_string;
236 if (!ConvertSidToStringSid(logon_sid, &sid_string))
237 return false;
238
239 static const wchar_t dacl_format[] = L"D:(A;OICI;GA;;;%ls)";
240 wchar_t dacl[SECURITY_MAX_SID_SIZE + arraysize(dacl_format) + 1] = {0};
241 wsprintf(dacl, dacl_format, sid_string);
242
243 LocalFree(sid_string);
244
245 // Convert the string to a security descriptor
246 if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
247 dacl,
248 SDDL_REVISION_1,
249 reinterpret_cast<PSECURITY_DESCRIPTOR*>(security_descriptor),
250 NULL)) {
251 return false;
252 }
253
254 return true;
255 }
256
257 #pragma warning(push) 72 #pragma warning(push)
258 #pragma warning(disable:4312 4244) 73 #pragma warning(disable:4312 4244)
259 WNDPROC SetWindowProc(HWND hwnd, WNDPROC proc) { 74 WNDPROC SetWindowProc(HWND hwnd, WNDPROC proc) {
260 // The reason we don't return the SetwindowLongPtr() value is that it returns 75 // The reason we don't return the SetwindowLongPtr() value is that it returns
261 // the orignal window procedure and not the current one. I don't know if it is 76 // the orignal window procedure and not the current one. I don't know if it is
262 // a bug or an intended feature. 77 // a bug or an intended feature.
263 WNDPROC oldwindow_proc = 78 WNDPROC oldwindow_proc =
264 reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC)); 79 reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC));
265 SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(proc)); 80 SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(proc));
266 return oldwindow_proc; 81 return oldwindow_proc;
267 } 82 }
268 83
269 void* SetWindowUserData(HWND hwnd, void* user_data) { 84 void* SetWindowUserData(HWND hwnd, void* user_data) {
270 return 85 return
271 reinterpret_cast<void*>(SetWindowLongPtr(hwnd, GWLP_USERDATA, 86 reinterpret_cast<void*>(SetWindowLongPtr(hwnd, GWLP_USERDATA,
272 reinterpret_cast<LONG_PTR>(user_data))); 87 reinterpret_cast<LONG_PTR>(user_data)));
273 } 88 }
274 89
275 void* GetWindowUserData(HWND hwnd) { 90 void* GetWindowUserData(HWND hwnd) {
276 return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); 91 return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
277 } 92 }
278 93
279 // Maps to the WNDPROC for a window that was active before the subclass was
280 // installed.
281 static const wchar_t* const kHandlerKey = L"__ORIGINAL_MESSAGE_HANDLER__";
282
283 bool IsSubclassed(HWND window, WNDPROC subclass_proc) {
284 WNDPROC original_handler =
285 reinterpret_cast<WNDPROC>(GetWindowLongPtr(window, GWLP_WNDPROC));
286 return original_handler == subclass_proc;
287 }
288
289 bool Subclass(HWND window, WNDPROC subclass_proc) {
290 WNDPROC original_handler =
291 reinterpret_cast<WNDPROC>(GetWindowLongPtr(window, GWLP_WNDPROC));
292 if (original_handler != subclass_proc) {
293 win_util::SetWindowProc(window, subclass_proc);
294 SetProp(window, kHandlerKey, original_handler);
295 return true;
296 }
297 return false;
298 }
299
300 bool Unsubclass(HWND window, WNDPROC subclass_proc) {
301 WNDPROC current_handler =
302 reinterpret_cast<WNDPROC>(GetWindowLongPtr(window, GWLP_WNDPROC));
303 if (current_handler == subclass_proc) {
304 HANDLE original_handler = GetProp(window, kHandlerKey);
305 if (original_handler) {
306 RemoveProp(window, kHandlerKey);
307 win_util::SetWindowProc(window,
308 reinterpret_cast<WNDPROC>(original_handler));
309 return true;
310 }
311 }
312 return false;
313 }
314
315 WNDPROC GetSuperclassWNDPROC(HWND window) {
316 return reinterpret_cast<WNDPROC>(GetProp(window, kHandlerKey));
317 }
318
319 #pragma warning(pop) 94 #pragma warning(pop)
320 95
321 bool IsShiftPressed() { 96 bool IsShiftPressed() {
322 return (::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000; 97 return (::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000;
323 } 98 }
324 99
325 bool IsCtrlPressed() { 100 bool IsCtrlPressed() {
326 return (::GetKeyState(VK_CONTROL) & 0x8000) == 0x8000; 101 return (::GetKeyState(VK_CONTROL) & 0x8000) == 0x8000;
327 } 102 }
328 103
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 166
392 // App id should be less than 128 chars and contain no space. And recommended 167 // App id should be less than 128 chars and contain no space. And recommended
393 // format is CompanyName.ProductName[.SubProduct.ProductNumber]. 168 // format is CompanyName.ProductName[.SubProduct.ProductNumber].
394 // See http://msdn.microsoft.com/en-us/library/dd378459%28VS.85%29.aspx 169 // See http://msdn.microsoft.com/en-us/library/dd378459%28VS.85%29.aspx
395 DCHECK(lstrlen(app_id) < 128 && wcschr(app_id, L' ') == NULL); 170 DCHECK(lstrlen(app_id) < 128 && wcschr(app_id, L' ') == NULL);
396 171
397 PROPVARIANT property_value; 172 PROPVARIANT property_value;
398 if (FAILED(InitPropVariantFromString(app_id, &property_value))) 173 if (FAILED(InitPropVariantFromString(app_id, &property_value)))
399 return false; 174 return false;
400 175
401 HRESULT result = property_store->SetValue(kPKEYAppUserModelID, 176 HRESULT result = property_store->SetValue(PKEY_AppUserModel_ID,
402 property_value); 177 property_value);
403 if (S_OK == result) 178 if (S_OK == result)
404 result = property_store->Commit(); 179 result = property_store->Commit();
405 180
406 PropVariantClear(&property_value); 181 PropVariantClear(&property_value);
407 return SUCCEEDED(result); 182 return SUCCEEDED(result);
408 } 183 }
409 184
410 static const char16 kAutoRunKeyPath[] = 185 static const char16 kAutoRunKeyPath[] =
411 L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"; 186 L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
(...skipping 25 matching lines...) Expand all
437 212
438 #ifndef COPY_FILE_COPY_SYMLINK 213 #ifndef COPY_FILE_COPY_SYMLINK
439 #error You must install the Windows 2008 or Vista Software Development Kit and \ 214 #error You must install the Windows 2008 or Vista Software Development Kit and \
440 set it as your default include path to build this library. You can grab it by \ 215 set it as your default include path to build this library. You can grab it by \
441 searching for "download windows sdk 2008" in your favorite web search engine. \ 216 searching for "download windows sdk 2008" in your favorite web search engine. \
442 Also make sure you register the SDK with Visual Studio, by selecting \ 217 Also make sure you register the SDK with Visual Studio, by selecting \
443 "Integrate Windows SDK with Visual Studio 2005" from the Windows SDK \ 218 "Integrate Windows SDK with Visual Studio 2005" from the Windows SDK \
444 menu (see Start - All Programs - Microsoft Windows SDK - \ 219 menu (see Start - All Programs - Microsoft Windows SDK - \
445 Visual Studio Registration). 220 Visual Studio Registration).
446 #endif 221 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698