Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
GUID_DEVINTERFACE_DISK identificeert de interfaceklasse van het schijfapparaat. De door het systeem geleverde schijfklassestuurprogramma's registreren exemplaren van deze klasse voor de schijven die ze beschikbaar maken. Het inventariseren van de ingeschakelde instanties is de stack-agnostische manier om paden voor schijfapparaten te detecteren: zowel de verouderde stack als de systeemeigen NVMe-stack maken deze interfaceklasse beschikbaar.
Daarom moet u de interface-GUID opsommen in plaats van een GUID van de installatieklasse op te geven, zoals GUID_DEVCLASS_DISKDRIVE, wat niet gegarandeerd stack-agnostisch is.
Interface-GUID tegenover GUID van de apparaatklasse
GUID_DEVINTERFACE_DISK en GUID_DEVCLASS_DISKDRIVE beantwoorden verschillende vragen en zijn niet uitwisselbaar:
-
GUID_DEVINTERFACE_DISKidentificeert een interfaceklasse, niet een afzonderlijk apparaatpad. Wanneer de ingeschakelde instanties worden opgesomd, worden paden van symbolische koppelingen geretourneerd die toepassingen kunnen doorgeven aan CreateFileW. De resulterende handle kan worden gebruikt voor bewerkingen die worden ondersteund door de doelschijf, afhankelijk van de aangevraagde toegangsrechten en toepasselijke machtigingen. Een opgesomd pad is geen garantie dat het openen van de schijf slaagt: het apparaat kan worden verwijderd of niet meer beschikbaar zijn voordat de open aanvraag is voltooid. -
GUID_DEVCLASS_DISKDRIVEis een apparaatinstallatieklasse die door PnP/SetupAPI wordt gebruikt voor installatie en classificatie van apparaten, zoals installatie van stuurprogramma's, Apparaatbeheer groeperen, INF-overeenkomsten en vergelijkbare onderhoudstaken. Een apparaatexemplaar dat tot deze installatieklasse behoort, biedt mogelijk geen interface aan die u kunt openen, en opsommen op installatieklasse zegt niets over welke functionele interfaces, als die er zijn, het apparaatexemplaar momenteel aanbiedt. - De verouderde schijfstack (
disk.sys/classpnp.sys) maakt gebruik van deGUID_DEVCLASS_DISKDRIVEinstallatieklasse, terwijl de systeemeigen NVMe-stack (nvmedisk.sys) een eigen, andere installatieklasse gebruikt,{75416e63-5912-4dfa-ae8f-3efaccaffb14}. AlleenGUID_DEVCLASS_DISKDRIVEopsommen zou daarom elke schijf missen die wordt beheerd door de systeemeigen NVMe-stack.GUID_DEVINTERFACE_DISKheeft dit verschil niet, omdat beide stacks dezelfde interface registreren voor elke schijf die ze beheren.
Opsommingsbereik
Deze voorbeeldcode voert een eenmalige enumeratie uit van momenteel actieve schijfapparaatinterfaces. Er worden geen volumes of stationsletters opgesomd en de geretourneerde lijst is geen continu onderhouden inventaris.
CM_GET_DEVICE_INTERFACE_LIST_PRESENT selecteert aanwezige/ingeschakelde interfaces. Er wordt niet aangegeven of een schijf online is in Schijfbeheer.
Voor een langlopende toepassing die aankomsten en verwijderingen bijhoudt, registreert u apparaatinterfacemeldingen bij CM_Register_Notification voordat u de eerste opsomming uitvoert. Meldingen afstemmen met de eerste lijst en duplicaten afhandelen, omdat een binnenkomende interface in beide kan worden weergegeven. Geef de registratie van meldingen vrij met CM_Unregister_Notification wanneer u klaar bent. Apparaatverwijdering kan nog steeds gelijktijdig optreden met het openen van een pad of het uitvoeren van I/O.
Voorbeeldcode: schijven opsommen
Note
Het opnieuw proberen verwerkt wijzigingen tussen de groottequery en het ophalen van de lijst; het garandeert geen uiteindelijk succes of een voortdurende beschikbaarheid van de geretourneerde apparaten. Het voorbeeld probeert het opnieuw CR_BUFFER_SMALL zonder een pogingslimiet, zodat herhaalde binnenkomende interface-gebeurtenissen het theoretisch voor onbepaalde tijd opnieuw kunnen laten proberen. Andere fouten worden gerapporteerd en leiden tot beëindiging van de opsomming.
#define INITGUID
#include <windows.h>
#include <ntddstor.h> // GUID_DEVINTERFACE_DISK
#include <cfgmgr32.h>
#include <stdio.h>
#include <stdlib.h> // malloc, free
#include <wchar.h> // wcslen
#pragma comment(lib, "cfgmgr32.lib")
//
// Opens and closes the disk using its device interface path.
// Zero desired access is intentional: this sample does not read or write data.
// When extending it, request the access required by the intended operation:
// GENERIC_READ for reads, GENERIC_WRITE for writes, and the access required
// by the specific IOCTL. Applicable device permissions also apply.
//
static void
ProcessDisk(
const wchar_t* DevicePath
)
{
HANDLE handle;
handle = CreateFileW(
DevicePath,
0, // No data read/write access requested.
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (handle == INVALID_HANDLE_VALUE)
{
wprintf(L" open failed (%lu): %s\n", GetLastError(), DevicePath);
return;
}
// TODO: perform a supported query whose access requirements are satisfied
// by this handle. Adjust the CreateFileW access argument before adding
// operations that require read or write access.
CloseHandle(handle);
}
int
wmain(
void
)
{
wchar_t* list;
CONFIGRET cr;
ULONG len;
DWORD index;
len = 0;
RetryEnumeration:
//
// Select currently enabled disk device interfaces.
// This does not indicate the disk's online/offline state.
//
cr = CM_Get_Device_Interface_List_SizeW(
&len,
(LPGUID)&GUID_DEVINTERFACE_DISK,
NULL,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT
);
if (cr != CR_SUCCESS || len == 0)
{
wprintf(L"CM_Get_Device_Interface_List_SizeW failed: 0x%lx\n", cr);
return 1;
}
//
// The result is a REG_MULTI_SZ style buffer: a contiguous run of
// NUL-terminated device paths, terminated by an extra empty string.
// 'len' is expressed in characters (including all NULs), so size the
// allocation in wchar_t units, not bytes.
//
list = (wchar_t*)malloc((size_t)len * sizeof(wchar_t));
if (list == NULL)
{
wprintf(L"Out of memory allocating %lu characters\n", len);
return 1;
}
cr = CM_Get_Device_Interface_ListW(
(LPGUID)&GUID_DEVINTERFACE_DISK,
NULL,
list,
len,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT
);
if (cr == CR_BUFFER_SMALL)
{
// An interface may have arrived after the size query.
free(list);
goto RetryEnumeration;
}
if (cr != CR_SUCCESS)
{
wprintf(L"CM_Get_Device_Interface_ListW failed: 0x%lx\n", cr);
free(list);
return 1;
}
//
// Walk the multi-string buffer, one NUL-terminated device path per
// iteration, stopping at the empty string that terminates the list.
// 'list' is guaranteed NUL-terminated by the API contract, so this
// cannot run past the allocation.
//
index = 0;
for (wchar_t* current = list; *current != L'\0'; current += wcslen(current) + 1)
{
wprintf(L"[%lu] %s\n", index, current);
ProcessDisk(current);
index++;
}
free(list);
return 0;
}
Verwante onderwerpen
- Geïnstalleerde apparaatinterfaces inventariseren
- CM_Get_Device_Interface_ListW
- CM_Get_Device_Interface_List_SizeW
- IOCTL_STORAGE_GET_DEVICE_NUMBER
- IOCTL_STORAGE_QUERY_PROPERTY
- GUID_DEVINTERFACE_DISK
- IoGetDeviceInterfaces (kernelmodus-equivalent)
- CreateFileW: aangevraagde toegangsrechten
- I/O-besturingscodes definiëren: richtlijnen voor het instellen van de Access-bits
- CM_Register_Notification: registratievolgorde en initiële enumeratie