• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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