Reboot.cpp (4190B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "AppInstallerLogging.h" 5 #include "AppInstallerStrings.h" 6 #include "Public/winget/Reboot.h" 7 #include "Public/winget/Registry.h" 8 #include <AppInstallerRuntime.h> 9 #include <Windows.h> 10 11 using namespace AppInstaller::Registry; 12 13 namespace AppInstaller::Reboot 14 { 15 namespace 16 { 17 constexpr std::wstring_view s_RunOnceRegistry = L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce"; 18 } 19 20 #ifndef AICLI_DISABLE_TEST_HOOKS 21 static bool* s_InitiateRebootResult_TestHook_Override = nullptr; 22 23 void TestHook_SetInitiateRebootResult_Override(bool* status) 24 { 25 s_InitiateRebootResult_TestHook_Override = status; 26 } 27 28 static bool* s_RegisterForRestartResult_TestHook_Override = nullptr; 29 30 void TestHook_SetRegisterForRestartResult_Override(bool* status) 31 { 32 s_RegisterForRestartResult_TestHook_Override = status; 33 } 34 #endif 35 36 bool InitiateReboot() 37 { 38 #ifndef AICLI_DISABLE_TEST_HOOKS 39 if (s_InitiateRebootResult_TestHook_Override) 40 { 41 return *s_InitiateRebootResult_TestHook_Override; 42 } 43 #endif 44 45 wil::unique_handle hToken; 46 TOKEN_PRIVILEGES pTokenPrivileges; 47 48 // Get a token for this process. 49 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 50 { 51 AICLI_LOG(Core, Error, << "OpenProcessToken error: " << GetLastError()); 52 return false; 53 } 54 55 // Shutdown privilege must be enabled for this process. 56 if (!LookupPrivilegeValueW(NULL, SE_SHUTDOWN_NAME, &pTokenPrivileges.Privileges[0].Luid)) 57 { 58 AICLI_LOG(Core, Error, << "LookupPrivilegeValue error: " << GetLastError()); 59 return false; 60 } 61 62 pTokenPrivileges.PrivilegeCount = 1; 63 pTokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 64 65 if (!AdjustTokenPrivileges(hToken.get(), FALSE, &pTokenPrivileges, 0, (PTOKEN_PRIVILEGES)NULL, 0)) 66 { 67 AICLI_LOG(Core, Error, << "AdjustTokenPrivilege error: " << GetLastError()); 68 return false; 69 } 70 71 AICLI_LOG(Core, Info, << "Initiating reboot."); 72 return ExitWindowsEx(EWX_RESTARTAPPS, SHTDN_REASON_MINOR_INSTALLATION); 73 } 74 75 bool RegisterRestartForWER(const std::string& commandLineArgs) 76 { 77 #ifndef AICLI_DISABLE_TEST_HOOKS 78 if (s_RegisterForRestartResult_TestHook_Override) 79 { 80 return *s_RegisterForRestartResult_TestHook_Override; 81 } 82 #endif 83 84 HRESULT result = RegisterApplicationRestart(AppInstaller::Utility::ConvertToUTF16(commandLineArgs).c_str(), 0 /* Always restart process */); 85 86 if (FAILED(result)) 87 { 88 AICLI_LOG(Core, Error, << "RegisterApplicationRestart failed with hr: " << result); 89 return false; 90 } 91 else 92 { 93 AICLI_LOG(CLI, Info, << "Register for restart with command line args: " << commandLineArgs); 94 return true; 95 } 96 } 97 98 bool UnregisterRestartForWER() 99 { 100 HRESULT result = UnregisterApplicationRestart(); 101 AICLI_LOG(CLI, Info, << "Application unregistered for restart."); 102 103 if (FAILED(result)) 104 { 105 AICLI_LOG(Core, Error, << "RegisterApplicationRestart failed with hr: " << result); 106 return false; 107 } 108 else 109 { 110 return true; 111 } 112 } 113 114 void WriteToRunOnceRegistry(const std::string& resumeId, const std::string& commandLine) 115 { 116 THROW_HR_IF(E_UNEXPECTED, commandLine.size() > MAX_PATH); 117 118 HKEY root = AppInstaller::Runtime::IsRunningAsAdmin() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 119 std::wstring subKey = std::wstring{ s_RunOnceRegistry }; 120 Key key = Key::OpenIfExists(root, subKey, 0, KEY_ALL_ACCESS); 121 122 if (!key) 123 { 124 key = Key::Create(root, subKey); 125 } 126 127 key.SetValue(Utility::ConvertToUTF16("WingetResume-" + resumeId), Utility::ConvertToUTF16(commandLine), REG_SZ); 128 AICLI_LOG(CLI, Info, << "Set RunOnce registry with value: " << commandLine); 129 } 130 }