Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/win/win_util.h" | 5 #include "base/win/win_util.h" |
| 6 | 6 |
| 7 #include <aclapi.h> | 7 #include <aclapi.h> |
| 8 #include <cfgmgr32.h> | 8 #include <cfgmgr32.h> |
| 9 #include <hstring.h> | |
| 9 #include <lm.h> | 10 #include <lm.h> |
| 10 #include <powrprof.h> | 11 #include <powrprof.h> |
| 11 #include <shellapi.h> | 12 #include <shellapi.h> |
| 12 #include <shlobj.h> | 13 #include <shlobj.h> |
| 13 #include <shobjidl.h> // Must be before propkey. | 14 #include <shobjidl.h> // Must be before propkey. |
| 14 #include <initguid.h> | 15 #include <initguid.h> |
| 16 #include <inspectable.h> | |
| 15 #include <propkey.h> | 17 #include <propkey.h> |
| 16 #include <propvarutil.h> | 18 #include <propvarutil.h> |
| 17 #include <psapi.h> | 19 #include <psapi.h> |
| 20 #include <roapi.h> | |
| 18 #include <sddl.h> | 21 #include <sddl.h> |
| 19 #include <setupapi.h> | 22 #include <setupapi.h> |
| 20 #include <signal.h> | 23 #include <signal.h> |
| 21 #include <stddef.h> | 24 #include <stddef.h> |
| 22 #include <stdlib.h> | 25 #include <stdlib.h> |
| 26 #include <winstring.h> | |
| 23 | 27 |
| 24 #include "base/base_switches.h" | 28 #include "base/base_switches.h" |
| 25 #include "base/command_line.h" | 29 #include "base/command_line.h" |
| 26 #include "base/lazy_instance.h" | 30 #include "base/lazy_instance.h" |
| 27 #include "base/logging.h" | 31 #include "base/logging.h" |
| 28 #include "base/macros.h" | 32 #include "base/macros.h" |
| 29 #include "base/memory/scoped_ptr.h" | 33 #include "base/memory/scoped_ptr.h" |
| 30 #include "base/strings/string_util.h" | 34 #include "base/strings/string_util.h" |
| 31 #include "base/strings/stringprintf.h" | 35 #include "base/strings/stringprintf.h" |
| 32 #include "base/strings/utf_string_conversions.h" | 36 #include "base/strings/utf_string_conversions.h" |
| 33 #include "base/threading/thread_restrictions.h" | 37 #include "base/threading/thread_restrictions.h" |
| 34 #include "base/win/registry.h" | 38 #include "base/win/registry.h" |
| 35 #include "base/win/scoped_co_mem.h" | 39 #include "base/win/scoped_co_mem.h" |
| 40 #include "base/win/scoped_comptr.h" | |
| 36 #include "base/win/scoped_handle.h" | 41 #include "base/win/scoped_handle.h" |
| 37 #include "base/win/scoped_propvariant.h" | 42 #include "base/win/scoped_propvariant.h" |
| 38 #include "base/win/windows_version.h" | 43 #include "base/win/windows_version.h" |
| 39 | 44 |
| 40 namespace base { | 45 namespace base { |
| 41 namespace win { | 46 namespace win { |
| 42 | 47 |
| 43 namespace { | 48 namespace { |
| 44 | 49 |
| 45 // Sets the value of |property_key| to |property_value| in |property_store|. | 50 // Sets the value of |property_key| to |property_value| in |property_store|. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 const wchar_t kWindows8OSKRegPath[] = | 105 const wchar_t kWindows8OSKRegPath[] = |
| 101 L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" | 106 L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" |
| 102 L"\\LocalServer32"; | 107 L"\\LocalServer32"; |
| 103 | 108 |
| 104 // Returns the current platform role. We use the PowerDeterminePlatformRoleEx | 109 // Returns the current platform role. We use the PowerDeterminePlatformRoleEx |
| 105 // API for that. | 110 // API for that. |
| 106 POWER_PLATFORM_ROLE GetPlatformRole() { | 111 POWER_PLATFORM_ROLE GetPlatformRole() { |
| 107 return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); | 112 return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); |
| 108 } | 113 } |
| 109 | 114 |
| 115 // Windows 10 stuff defined while we wait for Windows 10 headers. | |
| 116 // These definitions need to be removed once we have the new headers. | |
|
jschuh
2016/03/11 22:01:44
How close are we to landing the Win10 SDK? Because
Will Harris
2016/03/11 22:05:06
I thought we had landed Win10 SDK since it was nee
ananta
2016/03/11 23:14:14
Removed these definitions. Thanks to Will for lett
| |
| 117 namespace ABI { | |
| 118 namespace Windows { | |
| 119 namespace UI { | |
| 120 namespace ViewManagement { | |
| 121 | |
| 122 enum UserInteractionMode { | |
| 123 UserInteractionMode_Mouse = 0, | |
| 124 UserInteractionMode_Touch = 1 | |
| 125 }; | |
| 126 | |
| 127 interface __declspec(uuid("C63657F6-8850-470D-88F8-455E16EA2C26")) | |
| 128 IUIViewSettings : public IInspectable { | |
| 129 public: | |
| 130 virtual HRESULT STDMETHODCALLTYPE get_UserInteractionMode( | |
| 131 UserInteractionMode* value) = 0; | |
| 132 }; | |
| 133 | |
| 134 extern const __declspec(selectany) IID & IID_IUIViewSettings = | |
| 135 __uuidof(IUIViewSettings); | |
| 136 | |
| 137 } // namespace ViewManagement | |
| 138 } // namespace UI | |
| 139 } // namespace Windows | |
| 140 } // namespace ABI | |
| 141 | |
| 142 interface __declspec(uuid("3694dbf9-8f68-44be-8ff5-195c98ede8a6")) | |
| 143 IUIViewSettingsInterop : public IInspectable { | |
| 144 public: | |
| 145 virtual HRESULT STDMETHODCALLTYPE GetForWindow(HWND window, REFIID riid, | |
| 146 void** ppv) = 0; | |
| 147 }; | |
| 148 | |
| 149 // Uses the Windows 10 WRL API's to query the current system state. The API's | |
| 150 // we are using in the function below are supported in Win32 apps as per msdn. | |
| 151 // It looks like the API implementation is buggy at least on Surface 4 causing | |
| 152 // it to always return UserInteractionMode_Touch which as per documentation | |
| 153 // indicates tablet mode. | |
| 154 bool IsWindows10TabletDevice() { | |
| 155 if (GetVersion() < VERSION_WIN10) | |
| 156 return false; | |
| 157 | |
| 158 typedef HRESULT (WINAPI* GetActivationFactory)(HSTRING class_id, | |
|
jschuh
2016/03/11 22:01:45
ROGetActivationFactoryFunction
Will Harris
2016/03/11 22:05:06
consider using typedef decltype if the prototype i
ananta
2016/03/11 23:14:14
Thanks. Removed these
| |
| 159 REFIID iid, | |
| 160 void** factory); | |
| 161 | |
| 162 typedef HRESULT (WINAPI* CreateString)(LPCWSTR source, | |
|
jschuh
2016/03/11 22:01:45
WindowsCreateStringFunction
ananta
2016/03/11 23:14:14
Done
| |
| 163 UINT32 length, | |
| 164 HSTRING* target); | |
| 165 | |
| 166 static GetActivationFactory get_factory = nullptr; | |
| 167 static CreateString create_string = nullptr; | |
| 168 | |
| 169 if (!get_factory) { | |
| 170 DCHECK_EQ(create_string, static_cast<CreateString>(nullptr)); | |
| 171 | |
| 172 HMODULE combase_dll = ::LoadLibrary(L"combase.dll"); | |
| 173 if (!combase_dll) | |
| 174 return false; | |
| 175 | |
| 176 get_factory = reinterpret_cast<GetActivationFactory>( | |
| 177 ::GetProcAddress(combase_dll, "RoGetActivationFactory")); | |
| 178 if (!get_factory) { | |
| 179 CHECK(false); | |
| 180 return false; | |
| 181 } | |
| 182 | |
| 183 create_string = reinterpret_cast<CreateString>( | |
| 184 ::GetProcAddress(combase_dll, "WindowsCreateString")); | |
| 185 if (!create_string) { | |
| 186 CHECK(false); | |
| 187 return false; | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 HRESULT hr = E_FAIL; | |
| 192 // This HSTRING is allocated on the heap and is leaked. | |
| 193 static HSTRING view_settings_guid = NULL; | |
|
jschuh
2016/03/11 22:01:45
Is there a race here where you could allocate the
ananta
2016/03/11 23:14:14
No. This only gets called from the UI thread
| |
| 194 if (!view_settings_guid) { | |
| 195 hr = create_string(L"Windows.UI.ViewManagement.UIViewSettings", | |
| 196 static_cast<UINT32>( | |
| 197 wcslen(L"Windows.UI.ViewManagement.UIViewSettings")), | |
|
jschuh
2016/03/11 22:01:45
Declare this as a static constant so you don't hav
ananta
2016/03/11 23:14:14
We use the defined constant from the include file
| |
| 198 &view_settings_guid); | |
| 199 if (FAILED(hr)) | |
| 200 return false; | |
| 201 } | |
| 202 | |
| 203 base::win::ScopedComPtr<IUIViewSettingsInterop> view_settings_interop; | |
| 204 hr = get_factory(view_settings_guid, | |
| 205 __uuidof(IUIViewSettingsInterop), | |
| 206 view_settings_interop.ReceiveVoid()); | |
| 207 if (FAILED(hr)) | |
| 208 return false; | |
| 209 | |
| 210 base::win::ScopedComPtr<ABI::Windows::UI::ViewManagement::IUIViewSettings> | |
| 211 view_settings; | |
| 212 // TODO(ananta) | |
| 213 // Avoid using GetForegroundWindow here and pass in the HWND of the window | |
| 214 // intiating the request to display the keyboard. | |
| 215 hr = view_settings_interop->GetForWindow( | |
| 216 ::GetForegroundWindow(), | |
| 217 __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings), | |
| 218 view_settings.ReceiveVoid()); | |
| 219 if (FAILED(hr)) | |
| 220 return false; | |
| 221 | |
| 222 ABI::Windows::UI::ViewManagement::UserInteractionMode mode = | |
| 223 ABI::Windows::UI::ViewManagement::UserInteractionMode_Mouse; | |
| 224 view_settings->get_UserInteractionMode(&mode); | |
|
jschuh
2016/03/11 22:01:45
Are we sure the overhead is acceptable in doing th
ananta
2016/03/11 23:14:14
There should not be much overhead here. The functi
jschuh
2016/03/11 23:50:26
Okay. It just seems like we keep piling more logic
| |
| 225 return mode == ABI::Windows::UI::ViewManagement::UserInteractionMode_Touch; | |
| 226 } | |
| 227 | |
| 110 } // namespace | 228 } // namespace |
| 111 | 229 |
| 112 // Returns true if a physical keyboard is detected on Windows 8 and up. | 230 // Returns true if a physical keyboard is detected on Windows 8 and up. |
| 113 // Uses the Setup APIs to enumerate the attached keyboards and returns true | 231 // Uses the Setup APIs to enumerate the attached keyboards and returns true |
| 114 // if the keyboard count is 1 or more.. While this will work in most cases | 232 // if the keyboard count is 1 or more.. While this will work in most cases |
| 115 // it won't work if there are devices which expose keyboard interfaces which | 233 // it won't work if there are devices which expose keyboard interfaces which |
| 116 // are attached to the machine. | 234 // are attached to the machine. |
| 117 bool IsKeyboardPresentOnSlate(std::string* reason) { | 235 bool IsKeyboardPresentOnSlate(std::string* reason) { |
| 118 bool result = false; | 236 bool result = false; |
| 119 | 237 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 134 if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) | 252 if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) |
| 135 != NID_INTEGRATED_TOUCH) { | 253 != NID_INTEGRATED_TOUCH) { |
| 136 if (reason) { | 254 if (reason) { |
| 137 *reason += "NID_INTEGRATED_TOUCH\n"; | 255 *reason += "NID_INTEGRATED_TOUCH\n"; |
| 138 result = true; | 256 result = true; |
| 139 } else { | 257 } else { |
| 140 return true; | 258 return true; |
| 141 } | 259 } |
| 142 } | 260 } |
| 143 | 261 |
| 262 // If it is a tablet device we assume that there is no keyboard attached. | |
| 144 if (IsTabletDevice(reason)) { | 263 if (IsTabletDevice(reason)) { |
| 145 if (reason) | 264 if (reason) |
| 146 *reason += "Tablet device.\n"; | 265 *reason += "Tablet device.\n"; |
| 147 return true; | 266 return false; |
| 148 } else { | 267 } else { |
| 149 if (reason) { | 268 if (reason) { |
| 150 *reason += "Not a tablet device"; | 269 *reason += "Not a tablet device"; |
| 151 result = true; | 270 result = true; |
| 152 } else { | 271 } else { |
| 153 return true; | 272 return true; |
| 154 } | 273 } |
| 155 } | 274 } |
| 156 | 275 |
| 157 // To determine whether a keyboard is present on the device, we do the | 276 // To determine whether a keyboard is present on the device, we do the |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 384 signal(SIGABRT, ForceCrashOnSigAbort); | 503 signal(SIGABRT, ForceCrashOnSigAbort); |
| 385 } | 504 } |
| 386 | 505 |
| 387 bool IsTabletDevice(std::string* reason) { | 506 bool IsTabletDevice(std::string* reason) { |
| 388 if (GetVersion() < VERSION_WIN8) { | 507 if (GetVersion() < VERSION_WIN8) { |
| 389 if (reason) | 508 if (reason) |
| 390 *reason = "Tablet device detection not supported below Windows 8\n"; | 509 *reason = "Tablet device detection not supported below Windows 8\n"; |
| 391 return false; | 510 return false; |
| 392 } | 511 } |
| 393 | 512 |
| 513 if (IsWindows10TabletDevice()) | |
| 514 return true; | |
| 515 | |
| 394 if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { | 516 if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { |
| 395 if (reason) { | 517 if (reason) { |
| 396 *reason += "Device does not support touch.\n"; | 518 *reason += "Device does not support touch.\n"; |
| 397 } else { | 519 } else { |
| 398 return false; | 520 return false; |
| 399 } | 521 } |
| 400 } | 522 } |
| 401 | 523 |
| 402 // If the device is docked, the user is treating the device as a PC. | 524 // If the device is docked, the user is treating the device as a PC. |
| 403 if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { | 525 if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { |
| 404 if (reason) { | 526 if (reason) { |
| 405 *reason += "SM_SYSTEMDOCKED\n"; | 527 *reason += "SM_SYSTEMDOCKED\n"; |
| 406 } else { | 528 } else { |
| 407 return false; | 529 return false; |
| 408 } | 530 } |
| 409 } | 531 } |
| 410 | 532 |
| 411 // PlatformRoleSlate was added in Windows 8+. | 533 // PlatformRoleSlate was added in Windows 8+. |
| 412 POWER_PLATFORM_ROLE role = GetPlatformRole(); | 534 POWER_PLATFORM_ROLE role = GetPlatformRole(); |
| 413 bool mobile_power_profile = (role == PlatformRoleMobile); | 535 bool mobile_power_profile = (role == PlatformRoleMobile); |
| 414 bool slate_power_profile = (role == PlatformRoleSlate); | 536 bool slate_power_profile = (role == PlatformRoleSlate); |
| 415 | 537 |
| 416 bool is_tablet = false; | 538 bool is_tablet = false; |
| 417 | 539 bool is_tablet_pc = false; |
| 418 if (mobile_power_profile || slate_power_profile) { | 540 if (mobile_power_profile || slate_power_profile) { |
| 541 is_tablet_pc = !GetSystemMetrics(SM_TABLETPC); | |
| 419 is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); | 542 is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); |
| 420 if (!is_tablet) { | 543 if (!is_tablet) { |
| 421 if (reason) { | 544 if (reason) { |
| 422 *reason += "Not in slate mode.\n"; | 545 *reason += "Not in slate mode.\n"; |
| 423 } else { | 546 } else { |
| 424 return false; | 547 return false; |
| 425 } | 548 } |
| 426 } else { | 549 } else { |
| 427 if (reason) { | 550 if (reason) { |
| 428 *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : | 551 *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : |
| 429 "PlatformRoleSlate\n"; | 552 "PlatformRoleSlate\n"; |
| 430 } | 553 } |
| 431 } | 554 } |
| 432 } else { | 555 } else { |
| 433 if (reason) | 556 if (reason) |
| 434 *reason += "Device role is not mobile or slate.\n"; | 557 *reason += "Device role is not mobile or slate.\n"; |
| 435 } | 558 } |
| 436 return is_tablet; | 559 return is_tablet && is_tablet_pc; |
| 437 } | 560 } |
| 438 | 561 |
| 439 bool DisplayVirtualKeyboard() { | 562 bool DisplayVirtualKeyboard() { |
| 440 if (GetVersion() < VERSION_WIN8) | 563 if (GetVersion() < VERSION_WIN8) |
| 441 return false; | 564 return false; |
| 442 | 565 |
| 443 if (IsKeyboardPresentOnSlate(nullptr)) | 566 if (IsKeyboardPresentOnSlate(nullptr)) |
| 444 return false; | 567 return false; |
| 445 | 568 |
| 446 static LazyInstance<string16>::Leaky osk_path = LAZY_INSTANCE_INITIALIZER; | 569 static LazyInstance<string16>::Leaky osk_path = LAZY_INSTANCE_INITIALIZER; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 601 snapshot->resize(num_modules + 8, NULL); | 724 snapshot->resize(num_modules + 8, NULL); |
| 602 } | 725 } |
| 603 } while (--retries_remaining); | 726 } while (--retries_remaining); |
| 604 | 727 |
| 605 DLOG(ERROR) << "Failed to enumerate modules."; | 728 DLOG(ERROR) << "Failed to enumerate modules."; |
| 606 return false; | 729 return false; |
| 607 } | 730 } |
| 608 | 731 |
| 609 } // namespace win | 732 } // namespace win |
| 610 } // namespace base | 733 } // namespace base |
| OLD | NEW |