Home | History | Annotate | Download | only in win
      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 
     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 
     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 
     74 bool IsShiftPressed() {
     75   return (::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000;
     76 }
     77 
     78 bool IsCtrlPressed() {
     79   return (::GetKeyState(VK_CONTROL) & 0x8000) == 0x8000;
     80 }
     81 
     82 bool IsAltPressed() {
     83   return (::GetKeyState(VK_MENU) & 0x8000) == 0x8000;
     84 }
     85 
     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 
    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 
    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 
    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 
    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