Listing 5.4 Wdm1 Pnp.cpp Device Interface code
// Register and enable our device interface
status = IoRegisterDeviceInterface(pdo, &WDM1_GUID, NULL, &dx->ifSymLinkName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(fdo);
return status;
}
IoSetDeviceInterfaceState(&dx->ifSymLinkName, TRUE);
Table 5.3 IoRegisterDeviceInterface function
NTSTATUS IoRegisterDeviceInterface | |
---|---|
Parameter | Description |
IN PDEVICE_OBJECT PhysicalDeviceObject | The device PDO |
IN CONST GUID *InterfaceClassGuid | The GUID being registered |
IN PUNICODE_STRING ReferenceString | Usually NULL. A reference string becomes part of the interface name and so can be used to distinguish between different interfaces to the same device. |
OUT PUNICODE_STRING SymbolicLinkName | The output interface symbolic link name. Do not forget to free the Unicode string buffer using RtlFreeUnicodeString when finished with it. |
The code in
IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
RtlFreeUnicodeString(&dx->ifSytnLinkName);
Device Interface Notes
As mentioned in the last chapter, registering a device interface creates a registry entry in the HKLMSystemCurrentControlSetControlDeviceClasses key. A subkey named after the GUID and further subkeys for each device implements that GUID. Drivers can use
Device interface registrations can be removed from user mode, if necessary.
A driver can register that a device supports more than one device interface if desired.
Behind the scenes, Windows generates a kernel device name for your device. This might be something like devi ce 04059. The symbolic link name generated by IoRegisterDeviceInterface looks like DosDevices 00000000000001c#{c0cf0640…}. The
Win32 Device Interface Access
We are ready — at last — to access a Wdm1 device. The
The source code for the
There are two points to note about the
The GetDeviceViaInterface routine in Wdm1Test.cpp opens a handle to a device, given the device interface's GUID, as shown in Listing 5.5.
The
Listing 5.5 GetDeviceViaInterface
HANDLE GetDeviceViaInterface(GUID* pGuid, DWORD instance) {
// Get handle to relevant device information set
HDEVINFO info = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
if (info==INVALID_HANDLE_VALUE) {
printf('No HDEVINFO available for this GUID
');
return NULL;
}
// Get interface data for the requested instance
SP_INTERFACE_DEVICE_DATA ifdata;
ifdata.cbSize = sizeof(ifdata);
if (!SetupDiEnumDeviceInterfaces(info, NULL, pGuid, instance, &ifdata)) {
printf('No SP_INTERFACE_DEVICE_DATA available for this GUID instance
');
SetupDiDestroyDeviceInfoList(info);
return NULL;
}
// Get size of symbolic link name
DWORD ReqLen;
SetupDiGetDeviceInterfaceDetail(info, &ifdata, NULL, 0, &ReqLen, NULL);
PSP_INTERFACE_DEVICE_DETAIL_DATA ifDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)(new char[ReqLen]);
if (ifDetail==NULL) {
SetupDiDestroyDeviceInfoList(info);
return NULL;
}