VirtualBox

Changeset 70615 in vbox for trunk/src/VBox/Runtime/r3/win


Ignore:
Timestamp:
Jan 17, 2018 8:28:16 PM (7 years ago)
Author:
vboxsync
Message:

RTSystemShutdown/win: More reliable power off, I hope.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/RTSystemShutdown-win.cpp

    r69111 r70615  
    4444    AssertReturn(!(fFlags & ~RTSYSTEM_SHUTDOWN_VALID_MASK), VERR_INVALID_PARAMETER);
    4545
     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     */
    4691    PRTUTF16 pwszLogMsg;
    4792    int rc = RTStrToUtf16(pszLogMsg, &pwszLogMsg);
     
    4994        return rc;
    5095    DWORD cSecsTimeout = (cMsDelay + 499) / 1000;
    51     BOOL  fRebootAfterShutdown = (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) == RTSYSTEM_SHUTDOWN_REBOOT
    52                                ? TRUE : FALSE;
    53     BOOL  fForceAppsClosed = fFlags & RTSYSTEM_SHUTDOWN_FORCE ? TRUE : FALSE;
    5496
    5597    /*
    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.
    57104     */
    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)
    65108    {
    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)
    71113        {
    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)
    79120            {
    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);
    90123            }
    91 
    92             if (dwErr == NO_ERROR)
     124            if (dwErr == ERROR_SUCCESS)
    93125            {
    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;
    124128            }
    125129        }
     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);
    126166    }
    127167
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette