Changeset 86331 in vbox
- Timestamp:
- Sep 28, 2020 5:21:43 PM (4 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/HostImpl.h
r85929 r86331 204 204 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ 205 205 206 #ifdef RT_OS_WINDOWS 207 HRESULT i_getFixedDrivesFromGlobalNamespace(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT; 208 #endif 206 209 HRESULT i_getDrivesPathsList(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT; 207 210 -
trunk/src/VBox/Main/src-server/HostImpl.cpp
r85937 r86331 130 130 # include <devguid.h> 131 131 # include <iprt/win/objbase.h> 132 //# include <iprt/win/setupapi.h>133 132 # include <iprt/win/shlobj.h> 134 133 # include <cfgmgr32.h> … … 157 156 #endif 158 157 #include <iprt/time.h> 158 #ifdef RT_OS_WINDOWS 159 # include <iprt/dir.h> 160 # include <iprt/vfs.h> 161 #endif 159 162 160 163 #ifdef VBOX_WITH_HOSTNETIF_API … … 3883 3886 } 3884 3887 3888 #ifdef RT_OS_WINDOWS 3889 HRESULT 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 3885 4003 /** 3886 4004 * @throws nothing … … 3889 4007 { 3890 4008 #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); 3987 4010 3988 4011 #elif defined(RT_OS_DARWIN)
Note:
See TracChangeset
for help on using the changeset viewer.