1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/win/win_util.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <objbase.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <initguid.h>
10*6777b538SAndroid Build Coastguard Worker #include <shobjidl.h>
11*6777b538SAndroid Build Coastguard Worker #include <tchar.h>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include <aclapi.h>
14*6777b538SAndroid Build Coastguard Worker #include <cfgmgr32.h>
15*6777b538SAndroid Build Coastguard Worker #include <inspectable.h>
16*6777b538SAndroid Build Coastguard Worker #include <lm.h>
17*6777b538SAndroid Build Coastguard Worker #include <mdmregistration.h>
18*6777b538SAndroid Build Coastguard Worker #include <powrprof.h>
19*6777b538SAndroid Build Coastguard Worker #include <propkey.h>
20*6777b538SAndroid Build Coastguard Worker #include <psapi.h>
21*6777b538SAndroid Build Coastguard Worker #include <roapi.h>
22*6777b538SAndroid Build Coastguard Worker #include <sddl.h>
23*6777b538SAndroid Build Coastguard Worker #include <setupapi.h>
24*6777b538SAndroid Build Coastguard Worker #include <shellscalingapi.h>
25*6777b538SAndroid Build Coastguard Worker #include <signal.h>
26*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
27*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
28*6777b538SAndroid Build Coastguard Worker #include <strsafe.h>
29*6777b538SAndroid Build Coastguard Worker #include <tpcshrd.h>
30*6777b538SAndroid Build Coastguard Worker #include <uiviewsettingsinterop.h>
31*6777b538SAndroid Build Coastguard Worker #include <windows.ui.viewmanagement.h>
32*6777b538SAndroid Build Coastguard Worker #include <winstring.h>
33*6777b538SAndroid Build Coastguard Worker #include <wrl/client.h>
34*6777b538SAndroid Build Coastguard Worker #include <wrl/wrappers/corewrappers.h>
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker #include <limits>
37*6777b538SAndroid Build Coastguard Worker #include <memory>
38*6777b538SAndroid Build Coastguard Worker #include <optional>
39*6777b538SAndroid Build Coastguard Worker #include <string_view>
40*6777b538SAndroid Build Coastguard Worker #include <utility>
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker #include "base/base_switches.h"
43*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
44*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
45*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
46*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
47*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
48*6777b538SAndroid Build Coastguard Worker #include "base/scoped_native_library.h"
49*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
50*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util_win.h"
51*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
52*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_thread_priority.h"
53*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
54*6777b538SAndroid Build Coastguard Worker #include "base/timer/elapsed_timer.h"
55*6777b538SAndroid Build Coastguard Worker #include "base/win/access_token.h"
56*6777b538SAndroid Build Coastguard Worker #include "base/win/core_winrt_util.h"
57*6777b538SAndroid Build Coastguard Worker #include "base/win/propvarutil.h"
58*6777b538SAndroid Build Coastguard Worker #include "base/win/registry.h"
59*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_co_mem.h"
60*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_handle.h"
61*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_hstring.h"
62*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_propvariant.h"
63*6777b538SAndroid Build Coastguard Worker #include "base/win/shlwapi.h"
64*6777b538SAndroid Build Coastguard Worker #include "base/win/static_constants.h"
65*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_version.h"
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker namespace base {
68*6777b538SAndroid Build Coastguard Worker namespace win {
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Worker namespace {
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker // Sets the value of |property_key| to |property_value| in |property_store|.
SetPropVariantValueForPropertyStore(IPropertyStore * property_store,const PROPERTYKEY & property_key,const ScopedPropVariant & property_value)73*6777b538SAndroid Build Coastguard Worker bool SetPropVariantValueForPropertyStore(
74*6777b538SAndroid Build Coastguard Worker IPropertyStore* property_store,
75*6777b538SAndroid Build Coastguard Worker const PROPERTYKEY& property_key,
76*6777b538SAndroid Build Coastguard Worker const ScopedPropVariant& property_value) {
77*6777b538SAndroid Build Coastguard Worker DCHECK(property_store);
78*6777b538SAndroid Build Coastguard Worker
79*6777b538SAndroid Build Coastguard Worker HRESULT result = property_store->SetValue(property_key, property_value.get());
80*6777b538SAndroid Build Coastguard Worker if (result == S_OK)
81*6777b538SAndroid Build Coastguard Worker result = property_store->Commit();
82*6777b538SAndroid Build Coastguard Worker if (SUCCEEDED(result))
83*6777b538SAndroid Build Coastguard Worker return true;
84*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
85*6777b538SAndroid Build Coastguard Worker if (HRESULT_FACILITY(result) == FACILITY_WIN32)
86*6777b538SAndroid Build Coastguard Worker ::SetLastError(HRESULT_CODE(result));
87*6777b538SAndroid Build Coastguard Worker // See third_party/perl/c/i686-w64-mingw32/include/propkey.h for GUID and
88*6777b538SAndroid Build Coastguard Worker // PID definitions.
89*6777b538SAndroid Build Coastguard Worker DPLOG(ERROR) << "Failed to set property with GUID "
90*6777b538SAndroid Build Coastguard Worker << WStringFromGUID(property_key.fmtid) << " PID "
91*6777b538SAndroid Build Coastguard Worker << property_key.pid;
92*6777b538SAndroid Build Coastguard Worker #endif
93*6777b538SAndroid Build Coastguard Worker return false;
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
ForceCrashOnSigAbort(int)96*6777b538SAndroid Build Coastguard Worker void __cdecl ForceCrashOnSigAbort(int) {
97*6777b538SAndroid Build Coastguard Worker *((volatile int*)nullptr) = 0x1337;
98*6777b538SAndroid Build Coastguard Worker }
99*6777b538SAndroid Build Coastguard Worker
100*6777b538SAndroid Build Coastguard Worker // Returns the current platform role. We use the PowerDeterminePlatformRoleEx
101*6777b538SAndroid Build Coastguard Worker // API for that.
GetPlatformRole()102*6777b538SAndroid Build Coastguard Worker POWER_PLATFORM_ROLE GetPlatformRole() {
103*6777b538SAndroid Build Coastguard Worker return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2);
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker // Enable V2 per-monitor high-DPI support for the process. This will cause
107*6777b538SAndroid Build Coastguard Worker // Windows to scale dialogs, comctl32 controls, context menus, and non-client
108*6777b538SAndroid Build Coastguard Worker // area owned by this process on a per-monitor basis. If per-monitor V2 is not
109*6777b538SAndroid Build Coastguard Worker // available (i.e., prior to Windows 10 1703) or fails, returns false.
110*6777b538SAndroid Build Coastguard Worker // https://docs.microsoft.com/en-us/windows/desktop/hidpi/dpi-awareness-context
EnablePerMonitorV2()111*6777b538SAndroid Build Coastguard Worker bool EnablePerMonitorV2() {
112*6777b538SAndroid Build Coastguard Worker if (!IsUser32AndGdi32Available())
113*6777b538SAndroid Build Coastguard Worker return false;
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker static const auto set_process_dpi_awareness_context_func =
116*6777b538SAndroid Build Coastguard Worker reinterpret_cast<decltype(&::SetProcessDpiAwarenessContext)>(
117*6777b538SAndroid Build Coastguard Worker GetUser32FunctionPointer("SetProcessDpiAwarenessContext"));
118*6777b538SAndroid Build Coastguard Worker if (set_process_dpi_awareness_context_func) {
119*6777b538SAndroid Build Coastguard Worker return set_process_dpi_awareness_context_func(
120*6777b538SAndroid Build Coastguard Worker DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
121*6777b538SAndroid Build Coastguard Worker }
122*6777b538SAndroid Build Coastguard Worker
123*6777b538SAndroid Build Coastguard Worker DCHECK_LT(GetVersion(), Version::WIN10_RS2)
124*6777b538SAndroid Build Coastguard Worker << "SetProcessDpiAwarenessContext should be available on all platforms"
125*6777b538SAndroid Build Coastguard Worker " >= Windows 10 Redstone 2";
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Worker return false;
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker
GetDomainEnrollmentStateStorage()130*6777b538SAndroid Build Coastguard Worker bool* GetDomainEnrollmentStateStorage() {
131*6777b538SAndroid Build Coastguard Worker static bool state = IsOS(OS_DOMAINMEMBER);
132*6777b538SAndroid Build Coastguard Worker return &state;
133*6777b538SAndroid Build Coastguard Worker }
134*6777b538SAndroid Build Coastguard Worker
GetRegisteredWithManagementStateStorage()135*6777b538SAndroid Build Coastguard Worker bool* GetRegisteredWithManagementStateStorage() {
136*6777b538SAndroid Build Coastguard Worker static bool state = []() {
137*6777b538SAndroid Build Coastguard Worker // Mitigate the issues caused by loading DLLs on a background thread
138*6777b538SAndroid Build Coastguard Worker // (http://crbug/973868).
139*6777b538SAndroid Build Coastguard Worker SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker ScopedNativeLibrary library(
142*6777b538SAndroid Build Coastguard Worker FilePath(FILE_PATH_LITERAL("MDMRegistration.dll")));
143*6777b538SAndroid Build Coastguard Worker if (!library.is_valid())
144*6777b538SAndroid Build Coastguard Worker return false;
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker using IsDeviceRegisteredWithManagementFunction =
147*6777b538SAndroid Build Coastguard Worker decltype(&::IsDeviceRegisteredWithManagement);
148*6777b538SAndroid Build Coastguard Worker IsDeviceRegisteredWithManagementFunction
149*6777b538SAndroid Build Coastguard Worker is_device_registered_with_management_function =
150*6777b538SAndroid Build Coastguard Worker reinterpret_cast<IsDeviceRegisteredWithManagementFunction>(
151*6777b538SAndroid Build Coastguard Worker library.GetFunctionPointer("IsDeviceRegisteredWithManagement"));
152*6777b538SAndroid Build Coastguard Worker if (!is_device_registered_with_management_function)
153*6777b538SAndroid Build Coastguard Worker return false;
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker BOOL is_managed = FALSE;
156*6777b538SAndroid Build Coastguard Worker HRESULT hr =
157*6777b538SAndroid Build Coastguard Worker is_device_registered_with_management_function(&is_managed, 0, nullptr);
158*6777b538SAndroid Build Coastguard Worker return SUCCEEDED(hr) && is_managed;
159*6777b538SAndroid Build Coastguard Worker }();
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Worker return &state;
162*6777b538SAndroid Build Coastguard Worker }
163*6777b538SAndroid Build Coastguard Worker
164*6777b538SAndroid Build Coastguard Worker // TODO (crbug/1300219): return a DSREG_JOIN_TYPE* instead of bool*.
GetAzureADJoinStateStorage()165*6777b538SAndroid Build Coastguard Worker bool* GetAzureADJoinStateStorage() {
166*6777b538SAndroid Build Coastguard Worker static bool state = []() {
167*6777b538SAndroid Build Coastguard Worker base::ElapsedTimer timer;
168*6777b538SAndroid Build Coastguard Worker
169*6777b538SAndroid Build Coastguard Worker // Mitigate the issues caused by loading DLLs on a background thread
170*6777b538SAndroid Build Coastguard Worker // (http://crbug/973868).
171*6777b538SAndroid Build Coastguard Worker SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
172*6777b538SAndroid Build Coastguard Worker
173*6777b538SAndroid Build Coastguard Worker ScopedNativeLibrary netapi32(
174*6777b538SAndroid Build Coastguard Worker base::LoadSystemLibrary(FILE_PATH_LITERAL("netapi32.dll")));
175*6777b538SAndroid Build Coastguard Worker if (!netapi32.is_valid())
176*6777b538SAndroid Build Coastguard Worker return false;
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker const auto net_get_aad_join_information_function =
179*6777b538SAndroid Build Coastguard Worker reinterpret_cast<decltype(&::NetGetAadJoinInformation)>(
180*6777b538SAndroid Build Coastguard Worker netapi32.GetFunctionPointer("NetGetAadJoinInformation"));
181*6777b538SAndroid Build Coastguard Worker if (!net_get_aad_join_information_function)
182*6777b538SAndroid Build Coastguard Worker return false;
183*6777b538SAndroid Build Coastguard Worker
184*6777b538SAndroid Build Coastguard Worker const auto net_free_aad_join_information_function =
185*6777b538SAndroid Build Coastguard Worker reinterpret_cast<decltype(&::NetFreeAadJoinInformation)>(
186*6777b538SAndroid Build Coastguard Worker netapi32.GetFunctionPointer("NetFreeAadJoinInformation"));
187*6777b538SAndroid Build Coastguard Worker DPCHECK(net_free_aad_join_information_function);
188*6777b538SAndroid Build Coastguard Worker
189*6777b538SAndroid Build Coastguard Worker DSREG_JOIN_INFO* join_info = nullptr;
190*6777b538SAndroid Build Coastguard Worker HRESULT hr = net_get_aad_join_information_function(/*pcszTenantId=*/nullptr,
191*6777b538SAndroid Build Coastguard Worker &join_info);
192*6777b538SAndroid Build Coastguard Worker const bool is_aad_joined = SUCCEEDED(hr) && join_info;
193*6777b538SAndroid Build Coastguard Worker if (join_info) {
194*6777b538SAndroid Build Coastguard Worker net_free_aad_join_information_function(join_info);
195*6777b538SAndroid Build Coastguard Worker }
196*6777b538SAndroid Build Coastguard Worker
197*6777b538SAndroid Build Coastguard Worker base::UmaHistogramTimes("EnterpriseCheck.AzureADJoinStatusCheckTime",
198*6777b538SAndroid Build Coastguard Worker timer.Elapsed());
199*6777b538SAndroid Build Coastguard Worker return is_aad_joined;
200*6777b538SAndroid Build Coastguard Worker }();
201*6777b538SAndroid Build Coastguard Worker return &state;
202*6777b538SAndroid Build Coastguard Worker }
203*6777b538SAndroid Build Coastguard Worker
PinUser32Internal(NativeLibraryLoadError * error)204*6777b538SAndroid Build Coastguard Worker NativeLibrary PinUser32Internal(NativeLibraryLoadError* error) {
205*6777b538SAndroid Build Coastguard Worker static NativeLibraryLoadError load_error;
206*6777b538SAndroid Build Coastguard Worker static const NativeLibrary user32_module =
207*6777b538SAndroid Build Coastguard Worker PinSystemLibrary(FILE_PATH_LITERAL("user32.dll"), &load_error);
208*6777b538SAndroid Build Coastguard Worker if (!user32_module && error)
209*6777b538SAndroid Build Coastguard Worker error->code = load_error.code;
210*6777b538SAndroid Build Coastguard Worker return user32_module;
211*6777b538SAndroid Build Coastguard Worker }
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker } // namespace
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker // Uses the Windows 10 WRL API's to query the current system state. The API's
216*6777b538SAndroid Build Coastguard Worker // we are using in the function below are supported in Win32 apps as per msdn.
217*6777b538SAndroid Build Coastguard Worker // It looks like the API implementation is buggy at least on Surface 4 causing
218*6777b538SAndroid Build Coastguard Worker // it to always return UserInteractionMode_Touch which as per documentation
219*6777b538SAndroid Build Coastguard Worker // indicates tablet mode.
IsWindows10OrGreaterTabletMode(HWND hwnd)220*6777b538SAndroid Build Coastguard Worker bool IsWindows10OrGreaterTabletMode(HWND hwnd) {
221*6777b538SAndroid Build Coastguard Worker if (GetVersion() >= Version::WIN11) {
222*6777b538SAndroid Build Coastguard Worker // Only Win10 supports explicit tablet mode. On Win11,
223*6777b538SAndroid Build Coastguard Worker // get_UserInteractionMode always returns UserInteractionMode_Mouse, so
224*6777b538SAndroid Build Coastguard Worker // instead we check if we're in slate mode or not - 0 value means slate
225*6777b538SAndroid Build Coastguard Worker // mode. See
226*6777b538SAndroid Build Coastguard Worker // https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-gpiobuttons-convertibleslatemode
227*6777b538SAndroid Build Coastguard Worker
228*6777b538SAndroid Build Coastguard Worker constexpr int kKeyboardPresent = 1;
229*6777b538SAndroid Build Coastguard Worker base::win::RegKey registry_key(
230*6777b538SAndroid Build Coastguard Worker HKEY_LOCAL_MACHINE,
231*6777b538SAndroid Build Coastguard Worker L"System\\CurrentControlSet\\Control\\PriorityControl", KEY_READ);
232*6777b538SAndroid Build Coastguard Worker DWORD slate_mode = 0;
233*6777b538SAndroid Build Coastguard Worker bool value_exists = registry_key.ReadValueDW(L"ConvertibleSlateMode",
234*6777b538SAndroid Build Coastguard Worker &slate_mode) == ERROR_SUCCESS;
235*6777b538SAndroid Build Coastguard Worker // Some devices don't set the reg key to 1 for keyboard-only devices, so
236*6777b538SAndroid Build Coastguard Worker // also check if the device is used as a tablet if it is not 1. Some devices
237*6777b538SAndroid Build Coastguard Worker // don't set the registry key at all; fall back to checking if the device
238*6777b538SAndroid Build Coastguard Worker // is used as a tablet for them as well.
239*6777b538SAndroid Build Coastguard Worker return !(value_exists && slate_mode == kKeyboardPresent) &&
240*6777b538SAndroid Build Coastguard Worker IsDeviceUsedAsATablet(/*reason=*/nullptr);
241*6777b538SAndroid Build Coastguard Worker }
242*6777b538SAndroid Build Coastguard Worker
243*6777b538SAndroid Build Coastguard Worker ScopedHString view_settings_guid = ScopedHString::Create(
244*6777b538SAndroid Build Coastguard Worker RuntimeClass_Windows_UI_ViewManagement_UIViewSettings);
245*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<IUIViewSettingsInterop> view_settings_interop;
246*6777b538SAndroid Build Coastguard Worker HRESULT hr = ::RoGetActivationFactory(view_settings_guid.get(),
247*6777b538SAndroid Build Coastguard Worker IID_PPV_ARGS(&view_settings_interop));
248*6777b538SAndroid Build Coastguard Worker if (FAILED(hr))
249*6777b538SAndroid Build Coastguard Worker return false;
250*6777b538SAndroid Build Coastguard Worker
251*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<ABI::Windows::UI::ViewManagement::IUIViewSettings>
252*6777b538SAndroid Build Coastguard Worker view_settings;
253*6777b538SAndroid Build Coastguard Worker hr = view_settings_interop->GetForWindow(hwnd, IID_PPV_ARGS(&view_settings));
254*6777b538SAndroid Build Coastguard Worker if (FAILED(hr))
255*6777b538SAndroid Build Coastguard Worker return false;
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Worker ABI::Windows::UI::ViewManagement::UserInteractionMode mode =
258*6777b538SAndroid Build Coastguard Worker ABI::Windows::UI::ViewManagement::UserInteractionMode_Mouse;
259*6777b538SAndroid Build Coastguard Worker view_settings->get_UserInteractionMode(&mode);
260*6777b538SAndroid Build Coastguard Worker return mode == ABI::Windows::UI::ViewManagement::UserInteractionMode_Touch;
261*6777b538SAndroid Build Coastguard Worker }
262*6777b538SAndroid Build Coastguard Worker
263*6777b538SAndroid Build Coastguard Worker // Returns true if a physical keyboard is detected on Windows 8 and up.
264*6777b538SAndroid Build Coastguard Worker // Uses the Setup APIs to enumerate the attached keyboards and returns true
265*6777b538SAndroid Build Coastguard Worker // if the keyboard count is 1 or more.. While this will work in most cases
266*6777b538SAndroid Build Coastguard Worker // it won't work if there are devices which expose keyboard interfaces which
267*6777b538SAndroid Build Coastguard Worker // are attached to the machine.
IsKeyboardPresentOnSlate(HWND hwnd,std::string * reason)268*6777b538SAndroid Build Coastguard Worker bool IsKeyboardPresentOnSlate(HWND hwnd, std::string* reason) {
269*6777b538SAndroid Build Coastguard Worker bool result = false;
270*6777b538SAndroid Build Coastguard Worker
271*6777b538SAndroid Build Coastguard Worker if (CommandLine::ForCurrentProcess()->HasSwitch(
272*6777b538SAndroid Build Coastguard Worker switches::kDisableUsbKeyboardDetect)) {
273*6777b538SAndroid Build Coastguard Worker if (reason) {
274*6777b538SAndroid Build Coastguard Worker *reason = "Detection disabled";
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker return false;
277*6777b538SAndroid Build Coastguard Worker }
278*6777b538SAndroid Build Coastguard Worker
279*6777b538SAndroid Build Coastguard Worker // This function should be only invoked for machines with touch screens.
280*6777b538SAndroid Build Coastguard Worker if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) !=
281*6777b538SAndroid Build Coastguard Worker NID_INTEGRATED_TOUCH) {
282*6777b538SAndroid Build Coastguard Worker if (!reason) {
283*6777b538SAndroid Build Coastguard Worker return true;
284*6777b538SAndroid Build Coastguard Worker }
285*6777b538SAndroid Build Coastguard Worker
286*6777b538SAndroid Build Coastguard Worker *reason += "NID_INTEGRATED_TOUCH\n";
287*6777b538SAndroid Build Coastguard Worker result = true;
288*6777b538SAndroid Build Coastguard Worker }
289*6777b538SAndroid Build Coastguard Worker
290*6777b538SAndroid Build Coastguard Worker // If it is a tablet device we assume that there is no keyboard attached.
291*6777b538SAndroid Build Coastguard Worker if (IsTabletDevice(reason, hwnd)) {
292*6777b538SAndroid Build Coastguard Worker if (reason) {
293*6777b538SAndroid Build Coastguard Worker *reason += "Tablet device.\n";
294*6777b538SAndroid Build Coastguard Worker }
295*6777b538SAndroid Build Coastguard Worker return false;
296*6777b538SAndroid Build Coastguard Worker }
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker if (!reason) {
299*6777b538SAndroid Build Coastguard Worker return true;
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker
302*6777b538SAndroid Build Coastguard Worker *reason += "Not a tablet device";
303*6777b538SAndroid Build Coastguard Worker result = true;
304*6777b538SAndroid Build Coastguard Worker
305*6777b538SAndroid Build Coastguard Worker // To determine whether a keyboard is present on the device, we do the
306*6777b538SAndroid Build Coastguard Worker // following:-
307*6777b538SAndroid Build Coastguard Worker // 1. Check whether the device supports auto rotation. If it does then
308*6777b538SAndroid Build Coastguard Worker // it possibly supports flipping from laptop to slate mode. If it
309*6777b538SAndroid Build Coastguard Worker // does not support auto rotation, then we assume it is a desktop
310*6777b538SAndroid Build Coastguard Worker // or a normal laptop and assume that there is a keyboard.
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker // 2. If the device supports auto rotation, then we get its platform role
313*6777b538SAndroid Build Coastguard Worker // and check the system metric SM_CONVERTIBLESLATEMODE to see if it is
314*6777b538SAndroid Build Coastguard Worker // being used in slate mode. If yes then we return false here to ensure
315*6777b538SAndroid Build Coastguard Worker // that the OSK is displayed.
316*6777b538SAndroid Build Coastguard Worker
317*6777b538SAndroid Build Coastguard Worker // 3. If step 1 and 2 fail then we check attached keyboards and return true
318*6777b538SAndroid Build Coastguard Worker // if we find ACPI\* or HID\VID* keyboards.
319*6777b538SAndroid Build Coastguard Worker
320*6777b538SAndroid Build Coastguard Worker using GetAutoRotationState = decltype(&::GetAutoRotationState);
321*6777b538SAndroid Build Coastguard Worker static const auto get_rotation_state = reinterpret_cast<GetAutoRotationState>(
322*6777b538SAndroid Build Coastguard Worker GetUser32FunctionPointer("GetAutoRotationState"));
323*6777b538SAndroid Build Coastguard Worker if (get_rotation_state) {
324*6777b538SAndroid Build Coastguard Worker AR_STATE auto_rotation_state = AR_ENABLED;
325*6777b538SAndroid Build Coastguard Worker get_rotation_state(&auto_rotation_state);
326*6777b538SAndroid Build Coastguard Worker if ((auto_rotation_state & AR_NOSENSOR) ||
327*6777b538SAndroid Build Coastguard Worker (auto_rotation_state & AR_NOT_SUPPORTED)) {
328*6777b538SAndroid Build Coastguard Worker // If there is no auto rotation sensor or rotation is not supported in
329*6777b538SAndroid Build Coastguard Worker // the current configuration, then we can assume that this is a desktop
330*6777b538SAndroid Build Coastguard Worker // or a traditional laptop.
331*6777b538SAndroid Build Coastguard Worker if (!reason) {
332*6777b538SAndroid Build Coastguard Worker return true;
333*6777b538SAndroid Build Coastguard Worker }
334*6777b538SAndroid Build Coastguard Worker
335*6777b538SAndroid Build Coastguard Worker *reason += (auto_rotation_state & AR_NOSENSOR) ? "AR_NOSENSOR\n"
336*6777b538SAndroid Build Coastguard Worker : "AR_NOT_SUPPORTED\n";
337*6777b538SAndroid Build Coastguard Worker result = true;
338*6777b538SAndroid Build Coastguard Worker }
339*6777b538SAndroid Build Coastguard Worker }
340*6777b538SAndroid Build Coastguard Worker
341*6777b538SAndroid Build Coastguard Worker const GUID KEYBOARD_CLASS_GUID = {
342*6777b538SAndroid Build Coastguard Worker 0x4D36E96B,
343*6777b538SAndroid Build Coastguard Worker 0xE325,
344*6777b538SAndroid Build Coastguard Worker 0x11CE,
345*6777b538SAndroid Build Coastguard Worker {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}};
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker // Query for all the keyboard devices.
348*6777b538SAndroid Build Coastguard Worker HDEVINFO device_info = SetupDiGetClassDevs(&KEYBOARD_CLASS_GUID, nullptr,
349*6777b538SAndroid Build Coastguard Worker nullptr, DIGCF_PRESENT);
350*6777b538SAndroid Build Coastguard Worker if (device_info == INVALID_HANDLE_VALUE) {
351*6777b538SAndroid Build Coastguard Worker if (reason) {
352*6777b538SAndroid Build Coastguard Worker *reason += "No keyboard info\n";
353*6777b538SAndroid Build Coastguard Worker }
354*6777b538SAndroid Build Coastguard Worker return result;
355*6777b538SAndroid Build Coastguard Worker }
356*6777b538SAndroid Build Coastguard Worker
357*6777b538SAndroid Build Coastguard Worker // Enumerate all keyboards and look for ACPI\PNP and HID\VID devices. If
358*6777b538SAndroid Build Coastguard Worker // the count is more than 1 we assume that a keyboard is present. This is
359*6777b538SAndroid Build Coastguard Worker // under the assumption that there will always be one keyboard device.
360*6777b538SAndroid Build Coastguard Worker for (DWORD i = 0;; ++i) {
361*6777b538SAndroid Build Coastguard Worker SP_DEVINFO_DATA device_info_data = {0};
362*6777b538SAndroid Build Coastguard Worker device_info_data.cbSize = sizeof(device_info_data);
363*6777b538SAndroid Build Coastguard Worker if (!SetupDiEnumDeviceInfo(device_info, i, &device_info_data))
364*6777b538SAndroid Build Coastguard Worker break;
365*6777b538SAndroid Build Coastguard Worker
366*6777b538SAndroid Build Coastguard Worker // Get the device ID.
367*6777b538SAndroid Build Coastguard Worker wchar_t device_id[MAX_DEVICE_ID_LEN];
368*6777b538SAndroid Build Coastguard Worker CONFIGRET status = CM_Get_Device_ID(device_info_data.DevInst, device_id,
369*6777b538SAndroid Build Coastguard Worker MAX_DEVICE_ID_LEN, 0);
370*6777b538SAndroid Build Coastguard Worker if (status == CR_SUCCESS) {
371*6777b538SAndroid Build Coastguard Worker // To reduce the scope of the hack we only look for ACPI and HID\\VID
372*6777b538SAndroid Build Coastguard Worker // prefixes in the keyboard device ids.
373*6777b538SAndroid Build Coastguard Worker if (StartsWith(device_id, L"ACPI", CompareCase::INSENSITIVE_ASCII) ||
374*6777b538SAndroid Build Coastguard Worker StartsWith(device_id, L"HID\\VID", CompareCase::INSENSITIVE_ASCII)) {
375*6777b538SAndroid Build Coastguard Worker if (reason) {
376*6777b538SAndroid Build Coastguard Worker *reason += "device: ";
377*6777b538SAndroid Build Coastguard Worker *reason += WideToUTF8(device_id);
378*6777b538SAndroid Build Coastguard Worker *reason += '\n';
379*6777b538SAndroid Build Coastguard Worker }
380*6777b538SAndroid Build Coastguard Worker // The heuristic we are using is to check the count of keyboards and
381*6777b538SAndroid Build Coastguard Worker // return true if the API's report one or more keyboards. Please note
382*6777b538SAndroid Build Coastguard Worker // that this will break for non keyboard devices which expose a
383*6777b538SAndroid Build Coastguard Worker // keyboard PDO.
384*6777b538SAndroid Build Coastguard Worker result = true;
385*6777b538SAndroid Build Coastguard Worker }
386*6777b538SAndroid Build Coastguard Worker }
387*6777b538SAndroid Build Coastguard Worker }
388*6777b538SAndroid Build Coastguard Worker return result;
389*6777b538SAndroid Build Coastguard Worker }
390*6777b538SAndroid Build Coastguard Worker
391*6777b538SAndroid Build Coastguard Worker static bool g_crash_on_process_detach = false;
392*6777b538SAndroid Build Coastguard Worker
GetUserSidString(std::wstring * user_sid)393*6777b538SAndroid Build Coastguard Worker bool GetUserSidString(std::wstring* user_sid) {
394*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> token = AccessToken::FromCurrentProcess();
395*6777b538SAndroid Build Coastguard Worker if (!token)
396*6777b538SAndroid Build Coastguard Worker return false;
397*6777b538SAndroid Build Coastguard Worker std::optional<std::wstring> sid_string = token->User().ToSddlString();
398*6777b538SAndroid Build Coastguard Worker if (!sid_string)
399*6777b538SAndroid Build Coastguard Worker return false;
400*6777b538SAndroid Build Coastguard Worker *user_sid = *sid_string;
401*6777b538SAndroid Build Coastguard Worker return true;
402*6777b538SAndroid Build Coastguard Worker }
403*6777b538SAndroid Build Coastguard Worker
404*6777b538SAndroid Build Coastguard Worker class ScopedAllowBlockingForUserAccountControl : public ScopedAllowBlocking {};
405*6777b538SAndroid Build Coastguard Worker
UserAccountControlIsEnabled()406*6777b538SAndroid Build Coastguard Worker bool UserAccountControlIsEnabled() {
407*6777b538SAndroid Build Coastguard Worker // This can be slow if Windows ends up going to disk. Should watch this key
408*6777b538SAndroid Build Coastguard Worker // for changes and only read it once, preferably on the file thread.
409*6777b538SAndroid Build Coastguard Worker // http://code.google.com/p/chromium/issues/detail?id=61644
410*6777b538SAndroid Build Coastguard Worker ScopedAllowBlockingForUserAccountControl allow_blocking;
411*6777b538SAndroid Build Coastguard Worker
412*6777b538SAndroid Build Coastguard Worker RegKey key(HKEY_LOCAL_MACHINE,
413*6777b538SAndroid Build Coastguard Worker L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
414*6777b538SAndroid Build Coastguard Worker KEY_READ);
415*6777b538SAndroid Build Coastguard Worker DWORD uac_enabled;
416*6777b538SAndroid Build Coastguard Worker if (key.ReadValueDW(L"EnableLUA", &uac_enabled) != ERROR_SUCCESS) {
417*6777b538SAndroid Build Coastguard Worker return true;
418*6777b538SAndroid Build Coastguard Worker }
419*6777b538SAndroid Build Coastguard Worker // Users can set the EnableLUA value to something arbitrary, like 2, which
420*6777b538SAndroid Build Coastguard Worker // Vista will treat as UAC enabled, so we make sure it is not set to 0.
421*6777b538SAndroid Build Coastguard Worker return (uac_enabled != 0);
422*6777b538SAndroid Build Coastguard Worker }
423*6777b538SAndroid Build Coastguard Worker
SetBooleanValueForPropertyStore(IPropertyStore * property_store,const PROPERTYKEY & property_key,bool property_bool_value)424*6777b538SAndroid Build Coastguard Worker bool SetBooleanValueForPropertyStore(IPropertyStore* property_store,
425*6777b538SAndroid Build Coastguard Worker const PROPERTYKEY& property_key,
426*6777b538SAndroid Build Coastguard Worker bool property_bool_value) {
427*6777b538SAndroid Build Coastguard Worker ScopedPropVariant property_value;
428*6777b538SAndroid Build Coastguard Worker if (FAILED(InitPropVariantFromBoolean(property_bool_value,
429*6777b538SAndroid Build Coastguard Worker property_value.Receive()))) {
430*6777b538SAndroid Build Coastguard Worker return false;
431*6777b538SAndroid Build Coastguard Worker }
432*6777b538SAndroid Build Coastguard Worker
433*6777b538SAndroid Build Coastguard Worker return SetPropVariantValueForPropertyStore(property_store, property_key,
434*6777b538SAndroid Build Coastguard Worker property_value);
435*6777b538SAndroid Build Coastguard Worker }
436*6777b538SAndroid Build Coastguard Worker
SetStringValueForPropertyStore(IPropertyStore * property_store,const PROPERTYKEY & property_key,const wchar_t * property_string_value)437*6777b538SAndroid Build Coastguard Worker bool SetStringValueForPropertyStore(IPropertyStore* property_store,
438*6777b538SAndroid Build Coastguard Worker const PROPERTYKEY& property_key,
439*6777b538SAndroid Build Coastguard Worker const wchar_t* property_string_value) {
440*6777b538SAndroid Build Coastguard Worker ScopedPropVariant property_value;
441*6777b538SAndroid Build Coastguard Worker if (FAILED(InitPropVariantFromString(property_string_value,
442*6777b538SAndroid Build Coastguard Worker property_value.Receive()))) {
443*6777b538SAndroid Build Coastguard Worker return false;
444*6777b538SAndroid Build Coastguard Worker }
445*6777b538SAndroid Build Coastguard Worker
446*6777b538SAndroid Build Coastguard Worker return SetPropVariantValueForPropertyStore(property_store, property_key,
447*6777b538SAndroid Build Coastguard Worker property_value);
448*6777b538SAndroid Build Coastguard Worker }
449*6777b538SAndroid Build Coastguard Worker
SetClsidForPropertyStore(IPropertyStore * property_store,const PROPERTYKEY & property_key,const CLSID & property_clsid_value)450*6777b538SAndroid Build Coastguard Worker bool SetClsidForPropertyStore(IPropertyStore* property_store,
451*6777b538SAndroid Build Coastguard Worker const PROPERTYKEY& property_key,
452*6777b538SAndroid Build Coastguard Worker const CLSID& property_clsid_value) {
453*6777b538SAndroid Build Coastguard Worker ScopedPropVariant property_value;
454*6777b538SAndroid Build Coastguard Worker if (FAILED(InitPropVariantFromCLSID(property_clsid_value,
455*6777b538SAndroid Build Coastguard Worker property_value.Receive()))) {
456*6777b538SAndroid Build Coastguard Worker return false;
457*6777b538SAndroid Build Coastguard Worker }
458*6777b538SAndroid Build Coastguard Worker
459*6777b538SAndroid Build Coastguard Worker return SetPropVariantValueForPropertyStore(property_store, property_key,
460*6777b538SAndroid Build Coastguard Worker property_value);
461*6777b538SAndroid Build Coastguard Worker }
462*6777b538SAndroid Build Coastguard Worker
SetAppIdForPropertyStore(IPropertyStore * property_store,const wchar_t * app_id)463*6777b538SAndroid Build Coastguard Worker bool SetAppIdForPropertyStore(IPropertyStore* property_store,
464*6777b538SAndroid Build Coastguard Worker const wchar_t* app_id) {
465*6777b538SAndroid Build Coastguard Worker // App id should be less than 128 chars and contain no space. And recommended
466*6777b538SAndroid Build Coastguard Worker // format is CompanyName.ProductName[.SubProduct.ProductNumber].
467*6777b538SAndroid Build Coastguard Worker // See
468*6777b538SAndroid Build Coastguard Worker // https://docs.microsoft.com/en-us/windows/win32/shell/appids#how-to-form-an-application-defined-appusermodelid
469*6777b538SAndroid Build Coastguard Worker DCHECK_LT(lstrlen(app_id), 128);
470*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(wcschr(app_id, L' '), nullptr);
471*6777b538SAndroid Build Coastguard Worker
472*6777b538SAndroid Build Coastguard Worker return SetStringValueForPropertyStore(property_store, PKEY_AppUserModel_ID,
473*6777b538SAndroid Build Coastguard Worker app_id);
474*6777b538SAndroid Build Coastguard Worker }
475*6777b538SAndroid Build Coastguard Worker
476*6777b538SAndroid Build Coastguard Worker static const wchar_t kAutoRunKeyPath[] =
477*6777b538SAndroid Build Coastguard Worker L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
478*6777b538SAndroid Build Coastguard Worker
AddCommandToAutoRun(HKEY root_key,const std::wstring & name,const std::wstring & command)479*6777b538SAndroid Build Coastguard Worker bool AddCommandToAutoRun(HKEY root_key,
480*6777b538SAndroid Build Coastguard Worker const std::wstring& name,
481*6777b538SAndroid Build Coastguard Worker const std::wstring& command) {
482*6777b538SAndroid Build Coastguard Worker RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE);
483*6777b538SAndroid Build Coastguard Worker return (autorun_key.WriteValue(name.c_str(), command.c_str()) ==
484*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
485*6777b538SAndroid Build Coastguard Worker }
486*6777b538SAndroid Build Coastguard Worker
RemoveCommandFromAutoRun(HKEY root_key,const std::wstring & name)487*6777b538SAndroid Build Coastguard Worker bool RemoveCommandFromAutoRun(HKEY root_key, const std::wstring& name) {
488*6777b538SAndroid Build Coastguard Worker RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE);
489*6777b538SAndroid Build Coastguard Worker return (autorun_key.DeleteValue(name.c_str()) == ERROR_SUCCESS);
490*6777b538SAndroid Build Coastguard Worker }
491*6777b538SAndroid Build Coastguard Worker
ReadCommandFromAutoRun(HKEY root_key,const std::wstring & name,std::wstring * command)492*6777b538SAndroid Build Coastguard Worker bool ReadCommandFromAutoRun(HKEY root_key,
493*6777b538SAndroid Build Coastguard Worker const std::wstring& name,
494*6777b538SAndroid Build Coastguard Worker std::wstring* command) {
495*6777b538SAndroid Build Coastguard Worker RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_QUERY_VALUE);
496*6777b538SAndroid Build Coastguard Worker return (autorun_key.ReadValue(name.c_str(), command) == ERROR_SUCCESS);
497*6777b538SAndroid Build Coastguard Worker }
498*6777b538SAndroid Build Coastguard Worker
SetShouldCrashOnProcessDetach(bool crash)499*6777b538SAndroid Build Coastguard Worker void SetShouldCrashOnProcessDetach(bool crash) {
500*6777b538SAndroid Build Coastguard Worker g_crash_on_process_detach = crash;
501*6777b538SAndroid Build Coastguard Worker }
502*6777b538SAndroid Build Coastguard Worker
ShouldCrashOnProcessDetach()503*6777b538SAndroid Build Coastguard Worker bool ShouldCrashOnProcessDetach() {
504*6777b538SAndroid Build Coastguard Worker return g_crash_on_process_detach;
505*6777b538SAndroid Build Coastguard Worker }
506*6777b538SAndroid Build Coastguard Worker
SetAbortBehaviorForCrashReporting()507*6777b538SAndroid Build Coastguard Worker void SetAbortBehaviorForCrashReporting() {
508*6777b538SAndroid Build Coastguard Worker // Prevent CRT's abort code from prompting a dialog or trying to "report" it.
509*6777b538SAndroid Build Coastguard Worker // Disabling the _CALL_REPORTFAULT behavior is important since otherwise it
510*6777b538SAndroid Build Coastguard Worker // has the sideffect of clearing our exception filter, which means we
511*6777b538SAndroid Build Coastguard Worker // don't get any crash.
512*6777b538SAndroid Build Coastguard Worker _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
513*6777b538SAndroid Build Coastguard Worker
514*6777b538SAndroid Build Coastguard Worker // Set a SIGABRT handler for good measure. We will crash even if the default
515*6777b538SAndroid Build Coastguard Worker // is left in place, however this allows us to crash earlier. And it also
516*6777b538SAndroid Build Coastguard Worker // lets us crash in response to code which might directly call raise(SIGABRT)
517*6777b538SAndroid Build Coastguard Worker signal(SIGABRT, ForceCrashOnSigAbort);
518*6777b538SAndroid Build Coastguard Worker }
519*6777b538SAndroid Build Coastguard Worker
IsTabletDevice(std::string * reason,HWND hwnd)520*6777b538SAndroid Build Coastguard Worker bool IsTabletDevice(std::string* reason, HWND hwnd) {
521*6777b538SAndroid Build Coastguard Worker if (IsWindows10OrGreaterTabletMode(hwnd))
522*6777b538SAndroid Build Coastguard Worker return true;
523*6777b538SAndroid Build Coastguard Worker
524*6777b538SAndroid Build Coastguard Worker return IsDeviceUsedAsATablet(reason);
525*6777b538SAndroid Build Coastguard Worker }
526*6777b538SAndroid Build Coastguard Worker
527*6777b538SAndroid Build Coastguard Worker // This method is used to set the right interactions media queries,
528*6777b538SAndroid Build Coastguard Worker // see https://drafts.csswg.org/mediaqueries-4/#mf-interaction. It doesn't
529*6777b538SAndroid Build Coastguard Worker // check the Windows 10 tablet mode because it doesn't reflect the actual
530*6777b538SAndroid Build Coastguard Worker // input configuration of the device and can be manually triggered by the user
531*6777b538SAndroid Build Coastguard Worker // independently from the hardware state.
IsDeviceUsedAsATablet(std::string * reason)532*6777b538SAndroid Build Coastguard Worker bool IsDeviceUsedAsATablet(std::string* reason) {
533*6777b538SAndroid Build Coastguard Worker // Once this is set, it shouldn't be overridden, and it should be the ultimate
534*6777b538SAndroid Build Coastguard Worker // return value, so that this method returns the same result whether or not
535*6777b538SAndroid Build Coastguard Worker // reason is NULL.
536*6777b538SAndroid Build Coastguard Worker std::optional<bool> ret;
537*6777b538SAndroid Build Coastguard Worker
538*6777b538SAndroid Build Coastguard Worker if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) {
539*6777b538SAndroid Build Coastguard Worker if (!reason) {
540*6777b538SAndroid Build Coastguard Worker return false;
541*6777b538SAndroid Build Coastguard Worker }
542*6777b538SAndroid Build Coastguard Worker
543*6777b538SAndroid Build Coastguard Worker *reason += "Device does not support touch.\n";
544*6777b538SAndroid Build Coastguard Worker ret = false;
545*6777b538SAndroid Build Coastguard Worker }
546*6777b538SAndroid Build Coastguard Worker
547*6777b538SAndroid Build Coastguard Worker // If the device is docked, the user is treating the device as a PC.
548*6777b538SAndroid Build Coastguard Worker if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) {
549*6777b538SAndroid Build Coastguard Worker if (!reason) {
550*6777b538SAndroid Build Coastguard Worker return false;
551*6777b538SAndroid Build Coastguard Worker }
552*6777b538SAndroid Build Coastguard Worker
553*6777b538SAndroid Build Coastguard Worker *reason += "SM_SYSTEMDOCKED\n";
554*6777b538SAndroid Build Coastguard Worker if (!ret.has_value()) {
555*6777b538SAndroid Build Coastguard Worker ret = false;
556*6777b538SAndroid Build Coastguard Worker }
557*6777b538SAndroid Build Coastguard Worker }
558*6777b538SAndroid Build Coastguard Worker
559*6777b538SAndroid Build Coastguard Worker // If the device is not supporting rotation, it's unlikely to be a tablet,
560*6777b538SAndroid Build Coastguard Worker // a convertible or a detachable.
561*6777b538SAndroid Build Coastguard Worker // See
562*6777b538SAndroid Build Coastguard Worker // https://msdn.microsoft.com/en-us/library/windows/desktop/dn629263(v=vs.85).aspx
563*6777b538SAndroid Build Coastguard Worker using GetAutoRotationStateType = decltype(GetAutoRotationState)*;
564*6777b538SAndroid Build Coastguard Worker static const auto get_auto_rotation_state_func =
565*6777b538SAndroid Build Coastguard Worker reinterpret_cast<GetAutoRotationStateType>(
566*6777b538SAndroid Build Coastguard Worker GetUser32FunctionPointer("GetAutoRotationState"));
567*6777b538SAndroid Build Coastguard Worker if (get_auto_rotation_state_func) {
568*6777b538SAndroid Build Coastguard Worker AR_STATE rotation_state = AR_ENABLED;
569*6777b538SAndroid Build Coastguard Worker if (get_auto_rotation_state_func(&rotation_state) &&
570*6777b538SAndroid Build Coastguard Worker (rotation_state & (AR_NOT_SUPPORTED | AR_LAPTOP | AR_NOSENSOR)) != 0) {
571*6777b538SAndroid Build Coastguard Worker return ret.value_or(false);
572*6777b538SAndroid Build Coastguard Worker }
573*6777b538SAndroid Build Coastguard Worker }
574*6777b538SAndroid Build Coastguard Worker
575*6777b538SAndroid Build Coastguard Worker // PlatformRoleSlate was added in Windows 8+.
576*6777b538SAndroid Build Coastguard Worker POWER_PLATFORM_ROLE role = GetPlatformRole();
577*6777b538SAndroid Build Coastguard Worker bool is_tablet = false;
578*6777b538SAndroid Build Coastguard Worker if (role == PlatformRoleMobile || role == PlatformRoleSlate) {
579*6777b538SAndroid Build Coastguard Worker is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE);
580*6777b538SAndroid Build Coastguard Worker if (!is_tablet) {
581*6777b538SAndroid Build Coastguard Worker if (!reason) {
582*6777b538SAndroid Build Coastguard Worker return false;
583*6777b538SAndroid Build Coastguard Worker }
584*6777b538SAndroid Build Coastguard Worker
585*6777b538SAndroid Build Coastguard Worker *reason += "Not in slate mode.\n";
586*6777b538SAndroid Build Coastguard Worker if (!ret.has_value()) {
587*6777b538SAndroid Build Coastguard Worker ret = false;
588*6777b538SAndroid Build Coastguard Worker }
589*6777b538SAndroid Build Coastguard Worker } else if (reason) {
590*6777b538SAndroid Build Coastguard Worker *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n"
591*6777b538SAndroid Build Coastguard Worker : "PlatformRoleSlate\n";
592*6777b538SAndroid Build Coastguard Worker }
593*6777b538SAndroid Build Coastguard Worker } else if (reason) {
594*6777b538SAndroid Build Coastguard Worker *reason += "Device role is not mobile or slate.\n";
595*6777b538SAndroid Build Coastguard Worker }
596*6777b538SAndroid Build Coastguard Worker return ret.value_or(is_tablet);
597*6777b538SAndroid Build Coastguard Worker }
598*6777b538SAndroid Build Coastguard Worker
IsEnrolledToDomain()599*6777b538SAndroid Build Coastguard Worker bool IsEnrolledToDomain() {
600*6777b538SAndroid Build Coastguard Worker return *GetDomainEnrollmentStateStorage();
601*6777b538SAndroid Build Coastguard Worker }
602*6777b538SAndroid Build Coastguard Worker
IsDeviceRegisteredWithManagement()603*6777b538SAndroid Build Coastguard Worker bool IsDeviceRegisteredWithManagement() {
604*6777b538SAndroid Build Coastguard Worker // GetRegisteredWithManagementStateStorage() can be true for devices running
605*6777b538SAndroid Build Coastguard Worker // the Home sku, however the Home sku does not allow for management of the web
606*6777b538SAndroid Build Coastguard Worker // browser. As such, we automatically exclude devices running the Home sku.
607*6777b538SAndroid Build Coastguard Worker if (OSInfo::GetInstance()->version_type() == SUITE_HOME)
608*6777b538SAndroid Build Coastguard Worker return false;
609*6777b538SAndroid Build Coastguard Worker return *GetRegisteredWithManagementStateStorage();
610*6777b538SAndroid Build Coastguard Worker }
611*6777b538SAndroid Build Coastguard Worker
IsJoinedToAzureAD()612*6777b538SAndroid Build Coastguard Worker bool IsJoinedToAzureAD() {
613*6777b538SAndroid Build Coastguard Worker return *GetAzureADJoinStateStorage();
614*6777b538SAndroid Build Coastguard Worker }
615*6777b538SAndroid Build Coastguard Worker
IsUser32AndGdi32Available()616*6777b538SAndroid Build Coastguard Worker bool IsUser32AndGdi32Available() {
617*6777b538SAndroid Build Coastguard Worker static const bool is_user32_and_gdi32_available = []() {
618*6777b538SAndroid Build Coastguard Worker // If win32k syscalls aren't disabled, then user32 and gdi32 are available.
619*6777b538SAndroid Build Coastguard Worker PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {};
620*6777b538SAndroid Build Coastguard Worker if (::GetProcessMitigationPolicy(GetCurrentProcess(),
621*6777b538SAndroid Build Coastguard Worker ProcessSystemCallDisablePolicy, &policy,
622*6777b538SAndroid Build Coastguard Worker sizeof(policy))) {
623*6777b538SAndroid Build Coastguard Worker return policy.DisallowWin32kSystemCalls == 0;
624*6777b538SAndroid Build Coastguard Worker }
625*6777b538SAndroid Build Coastguard Worker
626*6777b538SAndroid Build Coastguard Worker return true;
627*6777b538SAndroid Build Coastguard Worker }();
628*6777b538SAndroid Build Coastguard Worker return is_user32_and_gdi32_available;
629*6777b538SAndroid Build Coastguard Worker }
630*6777b538SAndroid Build Coastguard Worker
GetLoadedModulesSnapshot(HANDLE process,std::vector<HMODULE> * snapshot)631*6777b538SAndroid Build Coastguard Worker bool GetLoadedModulesSnapshot(HANDLE process, std::vector<HMODULE>* snapshot) {
632*6777b538SAndroid Build Coastguard Worker DCHECK(snapshot);
633*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(0u, snapshot->size());
634*6777b538SAndroid Build Coastguard Worker snapshot->resize(128);
635*6777b538SAndroid Build Coastguard Worker
636*6777b538SAndroid Build Coastguard Worker // We will retry at least once after first determining |bytes_required|. If
637*6777b538SAndroid Build Coastguard Worker // the list of modules changes after we receive |bytes_required| we may retry
638*6777b538SAndroid Build Coastguard Worker // more than once.
639*6777b538SAndroid Build Coastguard Worker int retries_remaining = 5;
640*6777b538SAndroid Build Coastguard Worker do {
641*6777b538SAndroid Build Coastguard Worker DWORD bytes_required = 0;
642*6777b538SAndroid Build Coastguard Worker // EnumProcessModules returns 'success' even if the buffer size is too
643*6777b538SAndroid Build Coastguard Worker // small.
644*6777b538SAndroid Build Coastguard Worker DCHECK_GE(std::numeric_limits<DWORD>::max(),
645*6777b538SAndroid Build Coastguard Worker snapshot->size() * sizeof(HMODULE));
646*6777b538SAndroid Build Coastguard Worker if (!::EnumProcessModules(
647*6777b538SAndroid Build Coastguard Worker process, &(*snapshot)[0],
648*6777b538SAndroid Build Coastguard Worker static_cast<DWORD>(snapshot->size() * sizeof(HMODULE)),
649*6777b538SAndroid Build Coastguard Worker &bytes_required)) {
650*6777b538SAndroid Build Coastguard Worker DPLOG(ERROR) << "::EnumProcessModules failed.";
651*6777b538SAndroid Build Coastguard Worker return false;
652*6777b538SAndroid Build Coastguard Worker }
653*6777b538SAndroid Build Coastguard Worker
654*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(0u, bytes_required % sizeof(HMODULE));
655*6777b538SAndroid Build Coastguard Worker size_t num_modules = bytes_required / sizeof(HMODULE);
656*6777b538SAndroid Build Coastguard Worker if (num_modules <= snapshot->size()) {
657*6777b538SAndroid Build Coastguard Worker // Buffer size was too big, presumably because a module was unloaded.
658*6777b538SAndroid Build Coastguard Worker snapshot->erase(snapshot->begin() + static_cast<ptrdiff_t>(num_modules),
659*6777b538SAndroid Build Coastguard Worker snapshot->end());
660*6777b538SAndroid Build Coastguard Worker return true;
661*6777b538SAndroid Build Coastguard Worker }
662*6777b538SAndroid Build Coastguard Worker
663*6777b538SAndroid Build Coastguard Worker if (num_modules == 0) {
664*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << "Can't determine the module list size.";
665*6777b538SAndroid Build Coastguard Worker return false;
666*6777b538SAndroid Build Coastguard Worker }
667*6777b538SAndroid Build Coastguard Worker
668*6777b538SAndroid Build Coastguard Worker // Buffer size was too small. Try again with a larger buffer. A little
669*6777b538SAndroid Build Coastguard Worker // more room is given to avoid multiple expensive calls to
670*6777b538SAndroid Build Coastguard Worker // ::EnumProcessModules() just because one module has been added.
671*6777b538SAndroid Build Coastguard Worker snapshot->resize(num_modules + 8, nullptr);
672*6777b538SAndroid Build Coastguard Worker } while (--retries_remaining);
673*6777b538SAndroid Build Coastguard Worker
674*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << "Failed to enumerate modules.";
675*6777b538SAndroid Build Coastguard Worker return false;
676*6777b538SAndroid Build Coastguard Worker }
677*6777b538SAndroid Build Coastguard Worker
EnableFlicks(HWND hwnd)678*6777b538SAndroid Build Coastguard Worker void EnableFlicks(HWND hwnd) {
679*6777b538SAndroid Build Coastguard Worker ::RemoveProp(hwnd, MICROSOFT_TABLETPENSERVICE_PROPERTY);
680*6777b538SAndroid Build Coastguard Worker }
681*6777b538SAndroid Build Coastguard Worker
DisableFlicks(HWND hwnd)682*6777b538SAndroid Build Coastguard Worker void DisableFlicks(HWND hwnd) {
683*6777b538SAndroid Build Coastguard Worker ::SetProp(hwnd, MICROSOFT_TABLETPENSERVICE_PROPERTY,
684*6777b538SAndroid Build Coastguard Worker reinterpret_cast<HANDLE>(TABLET_DISABLE_FLICKS |
685*6777b538SAndroid Build Coastguard Worker TABLET_DISABLE_FLICKFALLBACKKEYS));
686*6777b538SAndroid Build Coastguard Worker }
687*6777b538SAndroid Build Coastguard Worker
EnableHighDPISupport()688*6777b538SAndroid Build Coastguard Worker void EnableHighDPISupport() {
689*6777b538SAndroid Build Coastguard Worker if (!IsUser32AndGdi32Available())
690*6777b538SAndroid Build Coastguard Worker return;
691*6777b538SAndroid Build Coastguard Worker
692*6777b538SAndroid Build Coastguard Worker // Enable per-monitor V2 if it is available (Win10 1703 or later).
693*6777b538SAndroid Build Coastguard Worker if (EnablePerMonitorV2())
694*6777b538SAndroid Build Coastguard Worker return;
695*6777b538SAndroid Build Coastguard Worker
696*6777b538SAndroid Build Coastguard Worker // Fall back to per-monitor DPI for older versions of Win10.
697*6777b538SAndroid Build Coastguard Worker PROCESS_DPI_AWARENESS process_dpi_awareness = PROCESS_PER_MONITOR_DPI_AWARE;
698*6777b538SAndroid Build Coastguard Worker if (!::SetProcessDpiAwareness(process_dpi_awareness)) {
699*6777b538SAndroid Build Coastguard Worker // For windows versions where SetProcessDpiAwareness fails, try its
700*6777b538SAndroid Build Coastguard Worker // predecessor.
701*6777b538SAndroid Build Coastguard Worker BOOL result = ::SetProcessDPIAware();
702*6777b538SAndroid Build Coastguard Worker DCHECK(result) << "SetProcessDPIAware failed.";
703*6777b538SAndroid Build Coastguard Worker }
704*6777b538SAndroid Build Coastguard Worker }
705*6777b538SAndroid Build Coastguard Worker
WStringFromGUID(const::GUID & rguid)706*6777b538SAndroid Build Coastguard Worker std::wstring WStringFromGUID(const ::GUID& rguid) {
707*6777b538SAndroid Build Coastguard Worker // This constant counts the number of characters in the formatted string,
708*6777b538SAndroid Build Coastguard Worker // including the null termination character.
709*6777b538SAndroid Build Coastguard Worker constexpr int kGuidStringCharacters =
710*6777b538SAndroid Build Coastguard Worker 1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1;
711*6777b538SAndroid Build Coastguard Worker wchar_t guid_string[kGuidStringCharacters];
712*6777b538SAndroid Build Coastguard Worker CHECK(SUCCEEDED(StringCchPrintfW(
713*6777b538SAndroid Build Coastguard Worker guid_string, kGuidStringCharacters,
714*6777b538SAndroid Build Coastguard Worker L"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", rguid.Data1,
715*6777b538SAndroid Build Coastguard Worker rguid.Data2, rguid.Data3, rguid.Data4[0], rguid.Data4[1], rguid.Data4[2],
716*6777b538SAndroid Build Coastguard Worker rguid.Data4[3], rguid.Data4[4], rguid.Data4[5], rguid.Data4[6],
717*6777b538SAndroid Build Coastguard Worker rguid.Data4[7])));
718*6777b538SAndroid Build Coastguard Worker return std::wstring(guid_string, kGuidStringCharacters - 1);
719*6777b538SAndroid Build Coastguard Worker }
720*6777b538SAndroid Build Coastguard Worker
PinUser32(NativeLibraryLoadError * error)721*6777b538SAndroid Build Coastguard Worker bool PinUser32(NativeLibraryLoadError* error) {
722*6777b538SAndroid Build Coastguard Worker return PinUser32Internal(error) != nullptr;
723*6777b538SAndroid Build Coastguard Worker }
724*6777b538SAndroid Build Coastguard Worker
GetUser32FunctionPointer(const char * function_name,NativeLibraryLoadError * error)725*6777b538SAndroid Build Coastguard Worker void* GetUser32FunctionPointer(const char* function_name,
726*6777b538SAndroid Build Coastguard Worker NativeLibraryLoadError* error) {
727*6777b538SAndroid Build Coastguard Worker NativeLibrary user32_module = PinUser32Internal(error);
728*6777b538SAndroid Build Coastguard Worker if (user32_module)
729*6777b538SAndroid Build Coastguard Worker return GetFunctionPointerFromNativeLibrary(user32_module, function_name);
730*6777b538SAndroid Build Coastguard Worker return nullptr;
731*6777b538SAndroid Build Coastguard Worker }
732*6777b538SAndroid Build Coastguard Worker
GetWindowObjectName(HANDLE handle)733*6777b538SAndroid Build Coastguard Worker std::wstring GetWindowObjectName(HANDLE handle) {
734*6777b538SAndroid Build Coastguard Worker // Get the size of the name.
735*6777b538SAndroid Build Coastguard Worker std::wstring object_name;
736*6777b538SAndroid Build Coastguard Worker
737*6777b538SAndroid Build Coastguard Worker DWORD size = 0;
738*6777b538SAndroid Build Coastguard Worker ::GetUserObjectInformation(handle, UOI_NAME, nullptr, 0, &size);
739*6777b538SAndroid Build Coastguard Worker if (!size) {
740*6777b538SAndroid Build Coastguard Worker DPCHECK(false);
741*6777b538SAndroid Build Coastguard Worker return object_name;
742*6777b538SAndroid Build Coastguard Worker }
743*6777b538SAndroid Build Coastguard Worker
744*6777b538SAndroid Build Coastguard Worker LOG_ASSERT(size % sizeof(wchar_t) == 0u);
745*6777b538SAndroid Build Coastguard Worker
746*6777b538SAndroid Build Coastguard Worker // Query the name of the object.
747*6777b538SAndroid Build Coastguard Worker if (!::GetUserObjectInformation(
748*6777b538SAndroid Build Coastguard Worker handle, UOI_NAME, WriteInto(&object_name, size / sizeof(wchar_t)),
749*6777b538SAndroid Build Coastguard Worker size, &size)) {
750*6777b538SAndroid Build Coastguard Worker DPCHECK(false);
751*6777b538SAndroid Build Coastguard Worker }
752*6777b538SAndroid Build Coastguard Worker
753*6777b538SAndroid Build Coastguard Worker return object_name;
754*6777b538SAndroid Build Coastguard Worker }
755*6777b538SAndroid Build Coastguard Worker
GetPointerDevice(HANDLE device,POINTER_DEVICE_INFO & result)756*6777b538SAndroid Build Coastguard Worker bool GetPointerDevice(HANDLE device, POINTER_DEVICE_INFO& result) {
757*6777b538SAndroid Build Coastguard Worker return ::GetPointerDevice(device, &result);
758*6777b538SAndroid Build Coastguard Worker }
759*6777b538SAndroid Build Coastguard Worker
GetPointerDevices()760*6777b538SAndroid Build Coastguard Worker std::optional<std::vector<POINTER_DEVICE_INFO>> GetPointerDevices() {
761*6777b538SAndroid Build Coastguard Worker uint32_t device_count;
762*6777b538SAndroid Build Coastguard Worker if (!::GetPointerDevices(&device_count, nullptr)) {
763*6777b538SAndroid Build Coastguard Worker return std::nullopt;
764*6777b538SAndroid Build Coastguard Worker }
765*6777b538SAndroid Build Coastguard Worker
766*6777b538SAndroid Build Coastguard Worker std::vector<POINTER_DEVICE_INFO> pointer_devices(device_count);
767*6777b538SAndroid Build Coastguard Worker if (!::GetPointerDevices(&device_count, pointer_devices.data())) {
768*6777b538SAndroid Build Coastguard Worker return std::nullopt;
769*6777b538SAndroid Build Coastguard Worker }
770*6777b538SAndroid Build Coastguard Worker return pointer_devices;
771*6777b538SAndroid Build Coastguard Worker }
772*6777b538SAndroid Build Coastguard Worker
RegisterPointerDeviceNotifications(HWND hwnd,bool notify_proximity_changes)773*6777b538SAndroid Build Coastguard Worker bool RegisterPointerDeviceNotifications(HWND hwnd,
774*6777b538SAndroid Build Coastguard Worker bool notify_proximity_changes) {
775*6777b538SAndroid Build Coastguard Worker return ::RegisterPointerDeviceNotifications(hwnd, notify_proximity_changes);
776*6777b538SAndroid Build Coastguard Worker }
777*6777b538SAndroid Build Coastguard Worker
IsRunningUnderDesktopName(std::wstring_view desktop_name)778*6777b538SAndroid Build Coastguard Worker bool IsRunningUnderDesktopName(std::wstring_view desktop_name) {
779*6777b538SAndroid Build Coastguard Worker HDESK thread_desktop = ::GetThreadDesktop(::GetCurrentThreadId());
780*6777b538SAndroid Build Coastguard Worker if (!thread_desktop)
781*6777b538SAndroid Build Coastguard Worker return false;
782*6777b538SAndroid Build Coastguard Worker
783*6777b538SAndroid Build Coastguard Worker std::wstring current_desktop_name = GetWindowObjectName(thread_desktop);
784*6777b538SAndroid Build Coastguard Worker return EqualsCaseInsensitiveASCII(AsStringPiece16(current_desktop_name),
785*6777b538SAndroid Build Coastguard Worker AsStringPiece16(desktop_name));
786*6777b538SAndroid Build Coastguard Worker }
787*6777b538SAndroid Build Coastguard Worker
788*6777b538SAndroid Build Coastguard Worker // This method is used to detect whether current session is a remote session.
789*6777b538SAndroid Build Coastguard Worker // See:
790*6777b538SAndroid Build Coastguard Worker // https://docs.microsoft.com/en-us/windows/desktop/TermServ/detecting-the-terminal-services-environment
IsCurrentSessionRemote()791*6777b538SAndroid Build Coastguard Worker bool IsCurrentSessionRemote() {
792*6777b538SAndroid Build Coastguard Worker if (::GetSystemMetrics(SM_REMOTESESSION))
793*6777b538SAndroid Build Coastguard Worker return true;
794*6777b538SAndroid Build Coastguard Worker
795*6777b538SAndroid Build Coastguard Worker DWORD current_session_id = 0;
796*6777b538SAndroid Build Coastguard Worker
797*6777b538SAndroid Build Coastguard Worker if (!::ProcessIdToSessionId(::GetCurrentProcessId(), ¤t_session_id))
798*6777b538SAndroid Build Coastguard Worker return false;
799*6777b538SAndroid Build Coastguard Worker
800*6777b538SAndroid Build Coastguard Worker static constexpr wchar_t kRdpSettingsKeyName[] =
801*6777b538SAndroid Build Coastguard Worker L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server";
802*6777b538SAndroid Build Coastguard Worker RegKey key(HKEY_LOCAL_MACHINE, kRdpSettingsKeyName, KEY_READ);
803*6777b538SAndroid Build Coastguard Worker if (!key.Valid())
804*6777b538SAndroid Build Coastguard Worker return false;
805*6777b538SAndroid Build Coastguard Worker
806*6777b538SAndroid Build Coastguard Worker static constexpr wchar_t kGlassSessionIdValueName[] = L"GlassSessionId";
807*6777b538SAndroid Build Coastguard Worker DWORD glass_session_id = 0;
808*6777b538SAndroid Build Coastguard Worker if (key.ReadValueDW(kGlassSessionIdValueName, &glass_session_id) !=
809*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS) {
810*6777b538SAndroid Build Coastguard Worker return false;
811*6777b538SAndroid Build Coastguard Worker }
812*6777b538SAndroid Build Coastguard Worker
813*6777b538SAndroid Build Coastguard Worker return current_session_id != glass_session_id;
814*6777b538SAndroid Build Coastguard Worker }
815*6777b538SAndroid Build Coastguard Worker
IsAppVerifierLoaded()816*6777b538SAndroid Build Coastguard Worker bool IsAppVerifierLoaded() {
817*6777b538SAndroid Build Coastguard Worker return GetModuleHandleA(kApplicationVerifierDllName);
818*6777b538SAndroid Build Coastguard Worker }
819*6777b538SAndroid Build Coastguard Worker
ScopedDomainStateForTesting(bool state)820*6777b538SAndroid Build Coastguard Worker ScopedDomainStateForTesting::ScopedDomainStateForTesting(bool state)
821*6777b538SAndroid Build Coastguard Worker : initial_state_(IsEnrolledToDomain()) {
822*6777b538SAndroid Build Coastguard Worker *GetDomainEnrollmentStateStorage() = state;
823*6777b538SAndroid Build Coastguard Worker }
824*6777b538SAndroid Build Coastguard Worker
~ScopedDomainStateForTesting()825*6777b538SAndroid Build Coastguard Worker ScopedDomainStateForTesting::~ScopedDomainStateForTesting() {
826*6777b538SAndroid Build Coastguard Worker *GetDomainEnrollmentStateStorage() = initial_state_;
827*6777b538SAndroid Build Coastguard Worker }
828*6777b538SAndroid Build Coastguard Worker
829*6777b538SAndroid Build Coastguard Worker ScopedDeviceRegisteredWithManagementForTesting::
ScopedDeviceRegisteredWithManagementForTesting(bool state)830*6777b538SAndroid Build Coastguard Worker ScopedDeviceRegisteredWithManagementForTesting(bool state)
831*6777b538SAndroid Build Coastguard Worker : initial_state_(IsDeviceRegisteredWithManagement()) {
832*6777b538SAndroid Build Coastguard Worker *GetRegisteredWithManagementStateStorage() = state;
833*6777b538SAndroid Build Coastguard Worker }
834*6777b538SAndroid Build Coastguard Worker
835*6777b538SAndroid Build Coastguard Worker ScopedDeviceRegisteredWithManagementForTesting::
~ScopedDeviceRegisteredWithManagementForTesting()836*6777b538SAndroid Build Coastguard Worker ~ScopedDeviceRegisteredWithManagementForTesting() {
837*6777b538SAndroid Build Coastguard Worker *GetRegisteredWithManagementStateStorage() = initial_state_;
838*6777b538SAndroid Build Coastguard Worker }
839*6777b538SAndroid Build Coastguard Worker
ScopedAzureADJoinStateForTesting(bool state)840*6777b538SAndroid Build Coastguard Worker ScopedAzureADJoinStateForTesting::ScopedAzureADJoinStateForTesting(bool state)
841*6777b538SAndroid Build Coastguard Worker : initial_state_(std::exchange(*GetAzureADJoinStateStorage(), state)) {}
842*6777b538SAndroid Build Coastguard Worker
~ScopedAzureADJoinStateForTesting()843*6777b538SAndroid Build Coastguard Worker ScopedAzureADJoinStateForTesting::~ScopedAzureADJoinStateForTesting() {
844*6777b538SAndroid Build Coastguard Worker *GetAzureADJoinStateStorage() = initial_state_;
845*6777b538SAndroid Build Coastguard Worker }
846*6777b538SAndroid Build Coastguard Worker
847*6777b538SAndroid Build Coastguard Worker } // namespace win
848*6777b538SAndroid Build Coastguard Worker } // namespace base
849