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