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 23namespace base { 24namespace 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 32void 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 45bool 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 74bool IsShiftPressed() { 75 return (::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000; 76} 77 78bool IsCtrlPressed() { 79 return (::GetKeyState(VK_CONTROL) & 0x8000) == 0x8000; 80} 81 82bool IsAltPressed() { 83 return (::GetKeyState(VK_MENU) & 0x8000) == 0x8000; 84} 85 86bool 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 103bool 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 125static const char16 kAutoRunKeyPath[] = 126 L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"; 127 128bool 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 135bool 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 140bool 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// 154extern char VisualStudio2005ServicePack1Detection[10]; 155COMPILE_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 \ 164set it as your default include path to build this library. You can grab it by \ 165searching for "download windows sdk 2008" in your favorite web search engine. \ 166Also make sure you register the SDK with Visual Studio, by selecting \ 167"Integrate Windows SDK with Visual Studio 2005" from the Windows SDK \ 168menu (see Start - All Programs - Microsoft Windows SDK - \ 169Visual Studio Registration). 170#endif 171