VirtualBox

Changeset 86331 in vbox


Ignore:
Timestamp:
Sep 28, 2020 5:21:43 PM (4 years ago)
Author:
vboxsync
Message:

Main: bugref:9224: Changed the way to enumerate disks by scanning NT\GLOBAL?? in windows.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/HostImpl.h

    r85929 r86331  
    204204#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    205205
     206#ifdef RT_OS_WINDOWS
     207    HRESULT i_getFixedDrivesFromGlobalNamespace(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT;
     208#endif
    206209    HRESULT i_getDrivesPathsList(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT;
    207210
  • trunk/src/VBox/Main/src-server/HostImpl.cpp

    r85937 r86331  
    130130# include <devguid.h>
    131131# include <iprt/win/objbase.h>
    132 //# include <iprt/win/setupapi.h>
    133132# include <iprt/win/shlobj.h>
    134133# include <cfgmgr32.h>
     
    157156#endif
    158157#include <iprt/time.h>
     158#ifdef RT_OS_WINDOWS
     159# include <iprt/dir.h>
     160# include <iprt/vfs.h>
     161#endif
    159162
    160163#ifdef VBOX_WITH_HOSTNETIF_API
     
    38833886}
    38843887
     3888#ifdef RT_OS_WINDOWS
     3889HRESULT Host::i_getFixedDrivesFromGlobalNamespace(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT
     3890{
     3891    RTERRINFOSTATIC  ErrInfo;
     3892    uint32_t         offError;
     3893    RTVFSDIR         hVfsDir;
     3894    int rc = RTVfsChainOpenDir("\\\\:iprtnt:\\GLOBAL??", 0 /*fFlags*/, &hVfsDir, &offError, RTErrInfoInitStatic(&ErrInfo));
     3895    if (RT_FAILURE(rc))
     3896        return setError(E_FAIL, tr("Failed to open NT\\GLOBAL?? (error %Rrc)"), rc);
     3897
     3898    /*
     3899     * Scan whole directory and find any 'PhysicalDiskX' entries. Next, combine with '\\.\'
     3900     * to obtain the harddisk dev path.
     3901     */
     3902    size_t          cbDirEntryAlloced = sizeof(RTDIRENTRYEX);
     3903    PRTDIRENTRYEX   pDirEntry         = (PRTDIRENTRYEX)RTMemTmpAlloc(cbDirEntryAlloced);
     3904    if (!pDirEntry)
     3905    {
     3906        RTVfsDirRelease(hVfsDir);
     3907        return setError(E_OUTOFMEMORY, "Out of memory! (direntry buffer)");
     3908    }
     3909
     3910    HRESULT hrc = S_OK;
     3911    for (;;)
     3912    {
     3913        size_t cbDirEntry = cbDirEntryAlloced;
     3914        rc = RTVfsDirReadEx(hVfsDir, pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING);
     3915        if (RT_FAILURE(rc))
     3916        {
     3917            if (rc == VERR_BUFFER_OVERFLOW)
     3918            {
     3919                RTMemTmpFree(pDirEntry);
     3920                cbDirEntryAlloced = RT_ALIGN_Z(RT_MIN(cbDirEntry, cbDirEntryAlloced) + 64, 64);
     3921                pDirEntry  = (PRTDIRENTRYEX)RTMemTmpAlloc(cbDirEntryAlloced);
     3922                if (pDirEntry)
     3923                    continue;
     3924                hrc = setError(E_OUTOFMEMORY, "Out of memory! (direntry buffer)");
     3925            }
     3926            else if (rc != VERR_NO_MORE_FILES)
     3927                hrc = setError(VBOX_E_IPRT_ERROR, "RTVfsDirReadEx failed: %Rrc", rc);
     3928            break;
     3929        }
     3930        if (RTStrStartsWith(pDirEntry->szName, "PhysicalDrive"))
     3931        {
     3932            char szPhysicalDrive[64];
     3933            RTStrPrintf(szPhysicalDrive, sizeof(szPhysicalDrive), "\\\\.\\%s", pDirEntry->szName);
     3934
     3935            RTFILE hRawFile = NIL_RTFILE;
     3936            int vrc = RTFileOpen(&hRawFile, szPhysicalDrive, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
     3937            if (RT_FAILURE(vrc))
     3938            {
     3939                try
     3940                {
     3941                    aDriveList.push_back(std::pair<com::Utf8Str, com::Utf8Str>(szPhysicalDrive, "Unknown (Access denied)"));
     3942                }
     3943                catch (std::bad_alloc &)
     3944                {
     3945                    hrc = setError(E_OUTOFMEMORY, "Out of memory");
     3946                    break;
     3947                }
     3948                continue;
     3949            }
     3950
     3951            DWORD   cbBytesReturned = 0;
     3952            uint8_t abBuffer[1024];
     3953            RT_ZERO(abBuffer);
     3954
     3955            STORAGE_PROPERTY_QUERY query;
     3956            RT_ZERO(query);
     3957            query.PropertyId = StorageDeviceProperty;
     3958            query.QueryType  = PropertyStandardQuery;
     3959
     3960            BOOL fRc = DeviceIoControl((HANDLE)RTFileToNative(hRawFile),
     3961                                       IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
     3962                                       abBuffer, sizeof(abBuffer), &cbBytesReturned, NULL);
     3963            RTFileClose(hRawFile);
     3964            char szModel[1024];
     3965            if (fRc)
     3966            {
     3967                PSTORAGE_DEVICE_DESCRIPTOR pDevDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)abBuffer;
     3968                char *pszProduct = pDevDescriptor->ProductIdOffset ? (char *)&abBuffer[pDevDescriptor->ProductIdOffset] : NULL;
     3969                if (pszProduct)
     3970                {
     3971                    RTStrPurgeEncoding(pszProduct);
     3972                    if (*pszProduct != '\0')
     3973                    {
     3974                        char *pszVendor = pDevDescriptor->VendorIdOffset  ? (char *)&abBuffer[pDevDescriptor->VendorIdOffset] : NULL;
     3975                        if (pszVendor)
     3976                            RTStrPurgeEncoding(pszVendor);
     3977                        if (pszVendor && *pszVendor)
     3978                            RTStrPrintf(szModel, sizeof(szModel), "%s %s", pszVendor, pszProduct);
     3979                        else
     3980                            RTStrCopy(szModel, sizeof(szModel), pszProduct);
     3981                    }
     3982                }
     3983            }
     3984            try
     3985            {
     3986                aDriveList.push_back(std::pair<com::Utf8Str, com::Utf8Str>(szPhysicalDrive, szModel));
     3987            }
     3988            catch (std::bad_alloc &)
     3989            {
     3990                hrc = setError(E_OUTOFMEMORY, "Out of memory");
     3991                break;
     3992            }
     3993        }
     3994    }
     3995    if (FAILED(hrc))
     3996        aDriveList.clear();
     3997    RTMemTmpFree(pDirEntry);
     3998    RTVfsDirRelease(hVfsDir);
     3999    return hrc;
     4000}
     4001#endif
     4002
    38854003/**
    38864004 * @throws nothing
     
    38894007{
    38904008#ifdef RT_OS_WINDOWS
    3891     /** @todo r=bird: This approach is seriously flawed. The "Count" value refers to
    3892      * the registry entries next to it and as little if anything to do with
    3893      * PhysicalDriveX numbering.  The registry entries doesn't immediately give
    3894      * you the PhysicalDrive address either.
    3895      *
    3896      * One option would be to enumerate the \Device or \GLOBAL?? directories looking
    3897      * for Harddisk* directories and PhysicalDrive* symlinks respectively.  This can
    3898      * be explored using
    3899      *  - "out\win.amd64\debug\bin\tools\RTLs.exe -la \\:iprtnt:\Device"
    3900      *  - "out\win.amd64\debug\bin\tools\RTLs.exe -la \\:iprtnt:\GLOBAL??"
    3901      *  - WinObj from sysinternals.
    3902      *
    3903      * "wmic diskdrive list" somehow gets the info too.   There is more here:
    3904      * https://stackoverflow.com/questions/327718/how-to-list-physical-disks
    3905      *
    3906      * A third option would be to just be to go significantly higher than what
    3907      * "Count" indicates, to span gaps and stuff.
    3908      *
    3909      *
    3910      * How to create gaps in the PhysicalDriveX numbers:
    3911      *      1. Insert 2 USB sticks to you box.
    3912      *      2. Remove the first USB stick you inserted.
    3913      *      3. You've got a gap: RTLs -la \\:iprtnt:\GLOBAL?? | grep PhysicalDrive
    3914      */
    3915     HKEY hKeyEnum = (HKEY)INVALID_HANDLE_VALUE;
    3916     LONG lRc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
    3917                              L"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",
    3918                              0,
    3919                              KEY_READ | KEY_QUERY_VALUE,
    3920                              &hKeyEnum);
    3921     if (lRc != ERROR_SUCCESS)
    3922         return setError(E_FAIL, tr("Failed to open key Disk\\Enum (error %u/%#x)"), lRc, lRc);
    3923 
    3924     DWORD cCount = 0;
    3925     DWORD cBufSize = sizeof(cCount);
    3926     lRc = RegQueryValueExW(hKeyEnum, L"Count", NULL, NULL, (PBYTE)&cCount, &cBufSize);
    3927     RegCloseKey(hKeyEnum);
    3928     if (lRc != ERROR_SUCCESS)
    3929         return setError(E_FAIL, tr("Failed to get physical drives count (error %u/%#x)"), lRc, lRc);
    3930 
    3931     for (uint32_t i = 0; i < cCount; ++i)
    3932     {
    3933         char szPhysicalDrive[64];
    3934         RTStrPrintf(szPhysicalDrive, sizeof(szPhysicalDrive), "\\\\.\\PhysicalDrive%d", i);
    3935 
    3936         /** @todo r=bird: Why RTFILE_O_DENY_WRITE? */
    3937         RTFILE hRawFile = NIL_RTFILE;
    3938         int vrc = RTFileOpen(&hRawFile, szPhysicalDrive, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
    3939         if (RT_FAILURE(vrc))
    3940             continue; /** @todo r=bird: you might not be able to open all disks... */
    3941 
    3942         DWORD   cbBytesReturned = 0;
    3943         uint8_t abBuffer[1024];
    3944         RT_ZERO(abBuffer);
    3945 
    3946         STORAGE_PROPERTY_QUERY query;
    3947         RT_ZERO(query);
    3948         query.PropertyId = StorageDeviceProperty;
    3949         query.QueryType  = PropertyStandardQuery;
    3950 
    3951         BOOL fRc = DeviceIoControl((HANDLE)RTFileToNative(hRawFile),
    3952                                    IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
    3953                                    abBuffer, sizeof(abBuffer), &cbBytesReturned, NULL);
    3954         RTFileClose(hRawFile);
    3955         char szModel[1024];
    3956         if (fRc)
    3957         {
    3958             PSTORAGE_DEVICE_DESCRIPTOR pDevDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)abBuffer;
    3959             char *pszProduct = pDevDescriptor->ProductIdOffset ? (char *)&abBuffer[pDevDescriptor->ProductIdOffset] : NULL;
    3960             if (pszProduct)
    3961             {
    3962                 RTStrPurgeEncoding(pszProduct);
    3963                 if (*pszProduct != '\0')
    3964                 {
    3965                     char *pszVendor = pDevDescriptor->VendorIdOffset  ? (char *)&abBuffer[pDevDescriptor->VendorIdOffset] : NULL;
    3966                     if (pszVendor)
    3967                         RTStrPurgeEncoding(pszVendor);
    3968                     if (pszVendor && *pszVendor)
    3969                         RTStrPrintf(szModel, sizeof(szModel), "%s %s", pszVendor, pszProduct);
    3970                     else
    3971                         RTStrCopy(szModel, sizeof(szModel), pszProduct);
    3972                 }
    3973             }
    3974         }
    3975         try
    3976         {
    3977             aDriveList.push_back(std::pair<com::Utf8Str, com::Utf8Str>(szPhysicalDrive, szModel));
    3978         }
    3979         catch (std::bad_alloc &)
    3980         {
    3981             aDriveList.clear();
    3982             return E_OUTOFMEMORY;
    3983         }
    3984     }
    3985 
    3986     return S_OK;
     4009    return i_getFixedDrivesFromGlobalNamespace(aDriveList);
    39874010
    39884011#elif defined(RT_OS_DARWIN)
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