1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/win/win_util.h"
6
7 #include <aclapi.h>
8 #include <shobjidl.h> // Must be before propkey.
9 #include <propkey.h>
10 #include <propvarutil.h>
11 #include <sddl.h>
12 #include <shlobj.h>
13
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/win/registry.h"
17 #include "base/string_util.h"
18 #include "base/stringprintf.h"
19 #include "base/threading/thread_restrictions.h"
20 #include "base/win/scoped_handle.h"
21 #include "base/win/windows_version.h"
22
23 namespace base {
24 namespace win {
25
26 #define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(struct_name, member) \
27 offsetof(struct_name, member) + \
28 (sizeof static_cast<struct_name*>(NULL)->member)
29 #define NONCLIENTMETRICS_SIZE_PRE_VISTA \
30 SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
31
GetNonClientMetrics(NONCLIENTMETRICS * metrics)32 void GetNonClientMetrics(NONCLIENTMETRICS* metrics) {
33 DCHECK(metrics);
34
35 static const UINT SIZEOF_NONCLIENTMETRICS =
36 (base::win::GetVersion() >= base::win::VERSION_VISTA) ?
37 sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
38 metrics->cbSize = SIZEOF_NONCLIENTMETRICS;
39 const bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
40 SIZEOF_NONCLIENTMETRICS, metrics,
41 0);
42 DCHECK(success);
43 }
44
GetUserSidString(std::wstring * user_sid)45 bool GetUserSidString(std::wstring* user_sid) {
46 // Get the current token.
47 HANDLE token = NULL;
48 if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token))
49 return false;
50 base::win::ScopedHandle token_scoped(token);
51
52 DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
53 scoped_array<BYTE> user_bytes(new BYTE[size]);
54 TOKEN_USER* user = reinterpret_cast<TOKEN_USER*>(user_bytes.get());
55
56 if (!::GetTokenInformation(token, TokenUser, user, size, &size))
57 return false;
58
59 if (!user->User.Sid)
60 return false;
61
62 // Convert the data to a string.
63 wchar_t* sid_string;
64 if (!::ConvertSidToStringSid(user->User.Sid, &sid_string))
65 return false;
66
67 *user_sid = sid_string;
68
69 ::LocalFree(sid_string);
70
71 return true;
72 }
73
IsShiftPressed()74 bool IsShiftPressed() {
75 return (::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000;
76 }
77
IsCtrlPressed()78 bool IsCtrlPressed() {
79 return (::GetKeyState(VK_CONTROL) & 0x8000) == 0x8000;
80 }
81
IsAltPressed()82 bool IsAltPressed() {
83 return (::GetKeyState(VK_MENU) & 0x8000) == 0x8000;
84 }
85
UserAccountControlIsEnabled()86 bool UserAccountControlIsEnabled() {
87 // This can be slow if Windows ends up going to disk. Should watch this key
88 // for changes and only read it once, preferably on the file thread.
89 // http://code.google.com/p/chromium/issues/detail?id=61644
90 base::ThreadRestrictions::ScopedAllowIO allow_io;
91
92 base::win::RegKey key(HKEY_LOCAL_MACHINE,
93 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
94 KEY_READ);
95 DWORD uac_enabled;
96 if (key.ReadValueDW(L"EnableLUA", &uac_enabled) != ERROR_SUCCESS)
97 return true;
98 // Users can set the EnableLUA value to something arbitrary, like 2, which
99 // Vista will treat as UAC enabled, so we make sure it is not set to 0.
100 return (uac_enabled != 0);
101 }
102
SetAppIdForPropertyStore(IPropertyStore * property_store,const wchar_t * app_id)103 bool SetAppIdForPropertyStore(IPropertyStore* property_store,
104 const wchar_t* app_id) {
105 DCHECK(property_store);
106
107 // App id should be less than 128 chars and contain no space. And recommended
108 // format is CompanyName.ProductName[.SubProduct.ProductNumber].
109 // See http://msdn.microsoft.com/en-us/library/dd378459%28VS.85%29.aspx
110 DCHECK(lstrlen(app_id) < 128 && wcschr(app_id, L' ') == NULL);
111
112 PROPVARIANT property_value;
113 if (FAILED(InitPropVariantFromString(app_id, &property_value)))
114 return false;
115
116 HRESULT result = property_store->SetValue(PKEY_AppUserModel_ID,
117 property_value);
118 if (S_OK == result)
119 result = property_store->Commit();
120
121 PropVariantClear(&property_value);
122 return SUCCEEDED(result);
123 }
124
125 static const char16 kAutoRunKeyPath[] =
126 L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
127
AddCommandToAutoRun(HKEY root_key,const string16 & name,const string16 & command)128 bool AddCommandToAutoRun(HKEY root_key, const string16& name,
129 const string16& command) {
130 base::win::RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE);
131 return (autorun_key.WriteValue(name.c_str(), command.c_str()) ==
132 ERROR_SUCCESS);
133 }
134
RemoveCommandFromAutoRun(HKEY root_key,const string16 & name)135 bool RemoveCommandFromAutoRun(HKEY root_key, const string16& name) {
136 base::win::RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE);
137 return (autorun_key.DeleteValue(name.c_str()) == ERROR_SUCCESS);
138 }
139
ReadCommandFromAutoRun(HKEY root_key,const string16 & name,string16 * command)140 bool ReadCommandFromAutoRun(HKEY root_key,
141 const string16& name,
142 string16* command) {
143 base::win::RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_QUERY_VALUE);
144 return (autorun_key.ReadValue(name.c_str(), command) == ERROR_SUCCESS);
145 }
146
147 } // namespace win
148 } // namespace base
149
150 #ifdef _MSC_VER
151 //
152 // If the ASSERT below fails, please install Visual Studio 2005 Service Pack 1.
153 //
154 extern char VisualStudio2005ServicePack1Detection[10];
155 COMPILE_ASSERT(sizeof(&VisualStudio2005ServicePack1Detection) == sizeof(void*),
156 VS2005SP1Detect);
157 //
158 // Chrome requires at least Service Pack 1 for Visual Studio 2005.
159 //
160 #endif // _MSC_VER
161
162 #ifndef COPY_FILE_COPY_SYMLINK
163 #error You must install the Windows 2008 or Vista Software Development Kit and \
164 set it as your default include path to build this library. You can grab it by \
165 searching for "download windows sdk 2008" in your favorite web search engine. \
166 Also make sure you register the SDK with Visual Studio, by selecting \
167 "Integrate Windows SDK with Visual Studio 2005" from the Windows SDK \
168 menu (see Start - All Programs - Microsoft Windows SDK - \
169 Visual Studio Registration).
170 #endif
171