VirtualBox

Changeset 105766 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Aug 21, 2024 1:35:37 PM (6 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
164478
Message:

IPRT: Made RTSystemQueryFirmwareType() + RTSystemQueryFirmwareBoolean() a bit more compatible when running on older Windows OSes or less privileges. Also should help working around on VERR_PRIVILEGE_NOT_HELD errors in the VBox.log when querying the secure boot state.

File:
1 edited

Legend:

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

    r98103 r105766  
    129129
    130130
     131/**
     132 * Queries a DWORD value from a Windows registry key, Unicode (wide char) version.
     133 *
     134 * @returns IPRT status code.
     135 * @retval  VERR_FILE_NOT_FOUND if the value has not been found.
     136 * @param   hKey                    Registry handle to use.
     137 * @param   pwszKey                 Registry key to query \a pwszName in.
     138 * @param   pwszName                Name of the value to query.
     139 * @param   pdwValue                Where to return the actual value on success.
     140 */
     141static int rtSystemWinRegistryGetDWORDW(HKEY hKey, LPCWSTR pwszKey, LPCWSTR pwszName, DWORD *pdwValue)
     142{
     143    LONG lErr = RegOpenKeyExW(hKey, pwszKey, 0, KEY_QUERY_VALUE, &hKey);
     144    if (lErr != ERROR_SUCCESS)
     145        return RTErrConvertFromWin32(lErr);
     146
     147    int rc = VINF_SUCCESS;
     148
     149    DWORD cbType = sizeof(DWORD);
     150    DWORD dwType = 0;
     151    DWORD dwValue;
     152    lErr = RegQueryValueExW(hKey, pwszName, NULL, &dwType, (BYTE *)&dwValue, &cbType);
     153    if (lErr == ERROR_SUCCESS)
     154    {
     155        if (cbType == sizeof(DWORD))
     156        {
     157            if (dwType == REG_DWORD)
     158            {
     159                *pdwValue = dwValue;
     160            }
     161            else
     162                rc = VERR_WRONG_TYPE;
     163        }
     164        else
     165            rc = VERR_MISMATCH;
     166    }
     167    else
     168        rc = RTErrConvertFromWin32(lErr);
     169
     170    RegCloseKey(hKey);
     171
     172    return rc;
     173}
     174
     175
     176/**
     177 * Queries a DWORD value from a Windows registry key.
     178 *
     179 * @returns IPRT status code.
     180 * @retval  VERR_FILE_NOT_FOUND if the value has not been found.
     181 * @param   hKey                    Registry handle to use.
     182 * @param   pszKey                  Registry key to query \a pszName in.
     183 * @param   pszName                 Name of the value to query.
     184 * @param   pdwValue                Where to return the actual value on success.
     185 */
     186static int rtSystemRegistryGetDWORDA(HKEY hKey, const char *pszKey, const char *pszName, DWORD *pdwValue)
     187{
     188    PRTUTF16 pwszKey;
     189    int rc = RTStrToUtf16Ex(pszKey, RTSTR_MAX, &pwszKey, 0, NULL);
     190    if (RT_SUCCESS(rc))
     191    {
     192        PRTUTF16 pwszName;
     193        rc = RTStrToUtf16Ex(pszName, RTSTR_MAX, &pwszName, 0, NULL);
     194        if (RT_SUCCESS(rc))
     195        {
     196            rc = rtSystemWinRegistryGetDWORDW(hKey, pwszKey, pwszName, pdwValue);
     197            RTUtf16Free(pwszName);
     198        }
     199        RTUtf16Free(pwszKey);
     200    }
     201
     202    return rc;
     203}
     204
     205
    131206RTDECL(int) RTSystemQueryFirmwareType(PRTSYSFWTYPE penmFirmwareType)
    132207{
     
    139214    int rc = VERR_NOT_SUPPORTED;
    140215
    141     /* GetFirmwareType is Windows 8 and later. */
     216    /* GetFirmwareType is Windows 8 and later.
     217     * Note: Requires elevated privileges and will return VERR_PRIVILEGE_NOT_HELD otherwise. */
    142218    if (g_pfnGetFirmwareType)
    143219    {
     
    163239            rc = RTErrConvertFromWin32(GetLastError());
    164240    }
    165     /* GetFirmwareEnvironmentVariableW is XP and later. */
    166     else if (g_pfnGetFirmwareEnvironmentVariableW)
     241
     242    /* Try using GetFirmwareEnvironmentVariableW() next if the above call wasn't able to resolve the firmware type.
     243     * GetFirmwareEnvironmentVariableW is XP and later. */
     244    if (   *penmFirmwareType == RTSYSFWTYPE_INVALID
     245        && g_pfnGetFirmwareEnvironmentVariableW)
    167246    {
    168247        rtSystemFirmwareGetPrivileges(SE_SYSTEM_ENVIRONMENT_NAME);
     
    174253        SetLastError(0);
    175254        uint8_t abWhatever[64];
    176         DWORD cbRet = g_pfnGetFirmwareEnvironmentVariableW(L"", VBOX_UEFI_UUID_DUMMY, abWhatever, sizeof(abWhatever));
    177         DWORD dwErr = GetLastError();
     255        DWORD const cbRet = g_pfnGetFirmwareEnvironmentVariableW(L"", VBOX_UEFI_UUID_DUMMY, abWhatever, sizeof(abWhatever));
     256        DWORD const dwErr = GetLastError();
    178257        *penmFirmwareType = cbRet != 0 || dwErr != ERROR_INVALID_FUNCTION ? RTSYSFWTYPE_UEFI : RTSYSFWTYPE_BIOS;
    179258        rc = VINF_SUCCESS;
    180259    }
     260    else if (*penmFirmwareType == RTSYSFWTYPE_INVALID) /* For very old systems (such as DOS / Win2K we safely can assume BIOS. */
     261        *penmFirmwareType = RTSYSFWTYPE_BIOS;
     262
    181263    return rc;
    182264}
     
    202284    }
    203285
     286    int rc;
     287
    204288    /*
    205289     * Do the query.
    206      * Note! This will typically fail with access denied unless we're in an elevated process.
    207290     */
    208     if (!g_pfnGetFirmwareEnvironmentVariableW)
    209         return VERR_NOT_SUPPORTED;
    210     rtSystemFirmwareGetPrivileges(SE_SYSTEM_ENVIRONMENT_NAME);
    211 
    212     uint8_t bValue = 0;
    213     DWORD cbRet = g_pfnGetFirmwareEnvironmentVariableW(pwszName, VBOX_UEFI_UUID_GLOBALS, &bValue, sizeof(bValue));
    214     *pfValue = cbRet != 0 && bValue != 0;
    215     if (cbRet != 0)
    216         return VINF_SUCCESS;
    217     DWORD dwErr = GetLastError();
    218     if (   dwErr == ERROR_INVALID_FUNCTION
    219         || dwErr == ERROR_ENVVAR_NOT_FOUND)
    220         return VINF_SUCCESS;
    221     return RTErrConvertFromWin32(dwErr);
    222 }
    223 
     291    if (g_pfnGetFirmwareEnvironmentVariableW)
     292    {
     293        rtSystemFirmwareGetPrivileges(SE_SYSTEM_ENVIRONMENT_NAME);
     294
     295        /* Note! This will typically fail with access denied unless we're in an elevated process. */
     296        uint8_t bValue = 0;
     297        DWORD cbRet = g_pfnGetFirmwareEnvironmentVariableW(pwszName, VBOX_UEFI_UUID_GLOBALS, &bValue, sizeof(bValue));
     298        *pfValue = cbRet != 0 && bValue != 0;
     299        if (cbRet != 0)
     300            return VINF_SUCCESS;
     301        rc = RTErrConvertFromWin32(GetLastError());
     302        if (rc == VERR_ENV_VAR_NOT_FOUND)
     303            return VINF_SUCCESS;
     304    }
     305
     306    /* If the above call failed because of missing privileges, try the registry as a fallback (if available for the type). */
     307    switch (enmBoolean)
     308    {
     309        case RTSYSFWBOOL_SECURE_BOOT:
     310        {
     311            DWORD dwEnabled;
     312            rc = rtSystemRegistryGetDWORDA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\SecureBoot\\State",
     313                                           "UEFISecureBootEnabled", &dwEnabled);
     314            if (RT_SUCCESS(rc))
     315            {
     316                *pfValue = RT_BOOL(dwEnabled);
     317            }
     318            else if (rc == VERR_FILE_NOT_FOUND)
     319                rc = VERR_NOT_SUPPORTED;
     320            break;
     321        }
     322
     323        default:
     324            rc = VERR_NOT_SUPPORTED;
     325            break;
     326    }
     327
     328    return rc;
     329}
     330
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