1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
LPCWSTR filePath = L"H:";
HANDLE volumeHandle = NULL;
HANDLE driveHandle = NULL;
// Récupère le nom du volume
TCHAR volumePath[MAX_PATH]; // for expository purposes
bool res = GetVolumePathName(filePath, volumePath, ARRAYSIZE(volumePath));
wprintf(L"%s \n", volumePath);
/*
Récupère le GUID (ne marche pas si c'est pas un disque dur local) \\?\Volume{guid}\
*/
TCHAR volumeName[MAX_PATH]; // for expository purposes
GetVolumeNameForVolumeMountPoint(volumePath, volumeName, ARRAYSIZE(volumeName));
wprintf(L"%s \n", volumeName);
/*
If you pass that path to the CreateFile function with the trailing backslash intact, then you are opening a handle to the root
directory of the volume.
If you pass that path to the CreateFile function with the trailing backslash removed, then you are opening a handle
to the volume itself.
*/
// In our case, we want to open a handle to the volume itself, so we need to remove that trailing backslash.The call to CreateFile looks like this:
CString test = volumeName;
test.TrimRight('\\');
LPCWSTR volumeNameWithoutTrailingBackslash = test;
/// Handle sur le volume (en retirant le dernier \)
volumeHandle = CreateFile(volumeNameWithoutTrailingBackslash,
0, /* no special access requested */
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, /* no custom security */
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
nullptr); /* template */
// --- Récupération du disque dur physique contenant le volume
/*
On demande au volume ses disques étendus, en cas de volume installé sur plusieurs disques, la première fois va dire la taille de la
structure dont on a besoin, et la seconde donnera la structure.
Puisque la plupart des volumes n'ont qu'une bande (voir raid), on peut optimiser légèrement pour ce cas par passer un buffer initial
assez gros pour contenir une seule bande. Si ça fonctionne, c'est qu'il n'y a pas besoin d'essayer une seconde fois.
(Raymond Chen)
*/
VOLUME_DISK_EXTENTS* extents = nullptr;
// Anticipate common case where there is only one extent.
VOLUME_DISK_EXTENTS singleExtent;
// But also have a place to manage allocated data.
std::unique_ptr<BYTE[]> lifetime;
DWORD bytesWritten;
if (DeviceIoControl(volumeHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nullptr, 0,
&singleExtent, sizeof(singleExtent),
&bytesWritten,
nullptr))
{
// Worked on the first try. Use the preallocated buffer.
extents = &singleExtent;
}
else
{
VOLUME_DISK_EXTENTS* lastQuery = &singleExtent;
while (GetLastError() == ERROR_MORE_DATA)
{
// Evaluation de la requête
assert(RTL_CONTAINS_FIELD(lastQuery, bytesWritten, NumberOfDiskExtents));
DWORD extentCount = lastQuery->NumberOfDiskExtents;
DWORD allocatedSize = FIELD_OFFSET(VOLUME_DISK_EXTENTS, Extents[extentCount]);
lifetime.reset(new BYTE[allocatedSize]);
lastQuery = (VOLUME_DISK_EXTENTS*)lifetime.get();
if (DeviceIoControl(volumeHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nullptr, 0,
lastQuery, allocatedSize,
&bytesWritten,
nullptr)) {
extents = lastQuery;
break;
}
}
}
/*
The extents tell you which physical drives the volume draws its storage from, and which bytes on those physical drives are devoted
to the volume. But for this exercise, we just want the physical drives.
*/
if (extents)
{
// process the extents
int physicalDriveNumber = extents->Extents->DiskNumber;
/*
Once you have the physical drive numbers, you can convert them to physical drive handles by building a path of the form
\\.\PhysicalDrive# where the # is the decimal expansion of the drive number.
*/
wchar_t physicalDrivePath[80];
swprintf_s(physicalDrivePath, L"\\\\.\\PhysicalDrive%d", physicalDriveNumber);
driveHandle = CreateFile(physicalDrivePath,
0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, 0, nullptr);
STORAGE_PROPERTY_QUERY query{};
query.PropertyId = StorageAdapterProperty;
query.QueryType = PropertyStandardQuery;
DWORD bytesWritten;
STORAGE_ADAPTER_DESCRIPTOR result{};
if (DeviceIoControl(driveHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(query),
&result, sizeof(result),
&bytesWritten, nullptr))
{
// type 7 = usb
printf("Interface type: %d", result.BusType);
}
}
CloseHandle(volumeHandle);
CloseHandle(driveHandle); |