Changeset 70615 in vbox for trunk/src/VBox/Runtime/r3/win
- Timestamp:
- Jan 17, 2018 8:28:16 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/win/RTSystemShutdown-win.cpp
r69111 r70615 44 44 AssertReturn(!(fFlags & ~RTSYSTEM_SHUTDOWN_VALID_MASK), VERR_INVALID_PARAMETER); 45 45 46 /* 47 * Before we start, try grant the necessary privileges. 48 */ 49 DWORD dwErr; 50 HANDLE hToken = NULL; 51 if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE /*OpenAsSelf*/, &hToken)) 52 dwErr = NO_ERROR; 53 else 54 { 55 dwErr = GetLastError(); 56 if (dwErr == ERROR_NO_TOKEN) 57 { 58 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) 59 dwErr = NO_ERROR; 60 else 61 dwErr = GetLastError(); 62 } 63 } 64 if (dwErr == NO_ERROR) 65 { 66 union 67 { 68 TOKEN_PRIVILEGES TokenPriv; 69 char ab[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)]; 70 } u; 71 u.TokenPriv.PrivilegeCount = 1; 72 u.TokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 73 if (LookupPrivilegeValue(NULL /*localhost*/, SE_SHUTDOWN_NAME, &u.TokenPriv.Privileges[0].Luid)) 74 { 75 if (!AdjustTokenPrivileges(hToken, 76 FALSE /*DisableAllPrivileges*/, 77 &u.TokenPriv, 78 RT_OFFSETOF(TOKEN_PRIVILEGES, Privileges[1]), 79 NULL, 80 NULL) ) 81 dwErr = GetLastError(); 82 } 83 else 84 dwErr = GetLastError(); 85 CloseHandle(hToken); 86 } 87 88 /* 89 * Do some parameter conversion. 90 */ 46 91 PRTUTF16 pwszLogMsg; 47 92 int rc = RTStrToUtf16(pszLogMsg, &pwszLogMsg); … … 49 94 return rc; 50 95 DWORD cSecsTimeout = (cMsDelay + 499) / 1000; 51 BOOL fRebootAfterShutdown = (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) == RTSYSTEM_SHUTDOWN_REBOOT52 ? TRUE : FALSE;53 BOOL fForceAppsClosed = fFlags & RTSYSTEM_SHUTDOWN_FORCE ? TRUE : FALSE;54 96 55 97 /* 56 * Do the 98 * If we're told to power off the system, we should try use InitiateShutdownW (6.0+) 99 * or ExitWindowsEx (3.50) rather than InitiateSystemShutdownW, because these other 100 * APIs allows us to explicitly specify that we want to power off. 101 * 102 * Note! For NT version 4, 3.51, and 3.50 the system may instaed reboot since the 103 * x86 HALs typically didn't know how to perform a power off. 57 104 */ 58 if (InitiateSystemShutdownW(NULL /*pwszMachineName = NULL = localhost*/, 59 pwszLogMsg, 60 cSecsTimeout, 61 fForceAppsClosed, 62 fRebootAfterShutdown)) 63 rc = (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) == RTSYSTEM_SHUTDOWN_HALT ? VINF_SYS_MAY_POWER_OFF : VINF_SUCCESS; 64 else 105 bool fDone = false; 106 if ( (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) == RTSYSTEM_SHUTDOWN_POWER_OFF 107 || (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) == RTSYSTEM_SHUTDOWN_POWER_OFF_HALT) 65 108 { 66 /* If we failed because of missing privileges, try get the right to 67 shut down the system and call the api again. */ 68 DWORD dwErr = GetLastError(); 69 rc = RTErrConvertFromWin32(dwErr); 70 if (dwErr == ERROR_ACCESS_DENIED) 109 /* This API has the grace period thing. */ 110 decltype(InitiateShutdownW) *pfnInitiateShutdownW; 111 pfnInitiateShutdownW = (decltype(InitiateShutdownW) *)GetProcAddress(GetModuleHandleW(L"ADVAPI32.DLL"), "InitiateShutdownW"); 112 if (pfnInitiateShutdownW) 71 113 { 72 HANDLE hToken = NULL; 73 if (OpenThreadToken(GetCurrentThread(), 74 TOKEN_ADJUST_PRIVILEGES, 75 TRUE /*OpenAsSelf*/, 76 &hToken)) 77 dwErr = NO_ERROR; 78 else 114 DWORD fShutdownFlags = SHUTDOWN_POWEROFF; 115 if (fFlags & RTSYSTEM_SHUTDOWN_FORCE) 116 fShutdownFlags |= SHUTDOWN_FORCE_OTHERS | SHUTDOWN_FORCE_SELF; 117 DWORD fReason = SHTDN_REASON_MAJOR_OTHER | (fFlags & RTSYSTEM_SHUTDOWN_PLANNED ? SHTDN_REASON_FLAG_PLANNED : 0); 118 dwErr = pfnInitiateShutdownW(NULL /*pwszMachineName*/, pwszLogMsg, cSecsTimeout, fShutdownFlags, fReason); 119 if (dwErr == ERROR_INVALID_PARAMETER) 79 120 { 80 dwErr = GetLastError(); 81 if (dwErr == ERROR_NO_TOKEN) 82 { 83 if (OpenProcessToken(GetCurrentProcess(), 84 TOKEN_ADJUST_PRIVILEGES, 85 &hToken)) 86 dwErr = NO_ERROR; 87 else 88 dwErr = GetLastError(); 89 } 121 fReason &= ~SHTDN_REASON_FLAG_PLANNED; /* just in case... */ 122 dwErr = pfnInitiateShutdownW(NULL /*pwszMachineName*/, pwszLogMsg, cSecsTimeout, fShutdownFlags, fReason); 90 123 } 91 92 if (dwErr == NO_ERROR) 124 if (dwErr == ERROR_SUCCESS) 93 125 { 94 union 95 { 96 TOKEN_PRIVILEGES TokenPriv; 97 char ab[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)]; 98 } u; 99 u.TokenPriv.PrivilegeCount = 1; 100 u.TokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 101 if (LookupPrivilegeValue(NULL /*localhost*/, SE_SHUTDOWN_NAME, &u.TokenPriv.Privileges[0].Luid)) 102 { 103 if (AdjustTokenPrivileges(hToken, 104 FALSE /*DisableAllPrivileges*/, 105 &u.TokenPriv, 106 RT_OFFSETOF(TOKEN_PRIVILEGES, Privileges[1]), 107 NULL, 108 NULL) ) 109 { 110 if (InitiateSystemShutdownW(NULL /*pwszMachineName = NULL = localhost*/, 111 pwszLogMsg, 112 cSecsTimeout, 113 fForceAppsClosed, 114 fRebootAfterShutdown)) 115 rc = (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) == RTSYSTEM_SHUTDOWN_HALT ? VINF_SYS_MAY_POWER_OFF : VINF_SUCCESS; 116 else 117 { 118 dwErr = GetLastError(); 119 rc = RTErrConvertFromWin32(dwErr); 120 } 121 } 122 CloseHandle(hToken); 123 } 126 rc = VINF_SUCCESS; 127 fDone = true; 124 128 } 125 129 } 130 131 if (!fDone) 132 { 133 /* No grace period here, too bad. */ 134 decltype(ExitWindowsEx) *pfnExitWindowsEx; 135 pfnExitWindowsEx = (decltype(ExitWindowsEx) *)GetProcAddress(GetModuleHandleW(L"USER32.DLL"), "ExitWindowsEx"); 136 if (pfnExitWindowsEx) 137 { 138 DWORD fExitWindows = EWX_POWEROFF | EWX_SHUTDOWN; 139 if (fFlags & RTSYSTEM_SHUTDOWN_FORCE) 140 fExitWindows |= EWX_FORCE | EWX_FORCEIFHUNG; 141 142 if (pfnExitWindowsEx(fExitWindows, SHTDN_REASON_MAJOR_OTHER)) 143 fDone = true; 144 else if (pfnExitWindowsEx(fExitWindows & ~EWX_FORCEIFHUNG, SHTDN_REASON_MAJOR_OTHER)) 145 fDone = true; 146 } 147 } 148 } 149 150 /* 151 * Fall back on the oldest API. 152 */ 153 if (!fDone) 154 { 155 BOOL fRebootAfterShutdown = (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) == RTSYSTEM_SHUTDOWN_REBOOT 156 ? TRUE : FALSE; 157 BOOL fForceAppsClosed = fFlags & RTSYSTEM_SHUTDOWN_FORCE ? TRUE : FALSE; 158 if (InitiateSystemShutdownW(NULL /*pwszMachineName = NULL = localhost*/, 159 pwszLogMsg, 160 cSecsTimeout, 161 fForceAppsClosed, 162 fRebootAfterShutdown)) 163 rc = (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) == RTSYSTEM_SHUTDOWN_HALT ? VINF_SYS_MAY_POWER_OFF : VINF_SUCCESS; 164 else 165 rc = RTErrConvertFromWin32(dwErr); 126 166 } 127 167
Note:
See TracChangeset
for help on using the changeset viewer.