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 Wdm1Pnp to handle device removal has to be altered, as well. First, the device interface has to be disabled. Then, it must free the memory buffer allocated for the interface symbolic link name. It does not have to Unregister the device interface.

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 IoOpenDeviceInterfaceRegistryKey to open a handle to this registry key. For example, you might want to add a FriendlyName value to this key using an INF file AddInterface section, as described in Chapter 11. Win32 applications can use SetupDiOpenDeviceInterfaceRegKey to open this same key and retrieve the friendly name.

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.

IoGetDeviceInterfaces can be used by a driver to find a list of symbolic links to devices that support a specific device interface.

Behind the scenes, Windows generates a kernel device name for your device. This might be something like devi ce04059. The symbolic link name generated by IoRegisterDeviceInterface looks like DosDevices00000000000001c#{c0cf0640…}. The WinObj entry for the symbolic link looks like ??Root#UNKN0WN#0000#{C0CF0640…}.

Win32 Device Interface Access

We are ready — at last — to access a Wdm1 device. The Wdm1Test program opens a connection to the Wdm1 driver and puts it through its paces. Remember that all the calls in this section are to Win32 routines, not to the kernel.

The source code for the Wdm1Test program is in the Wdm1exe directory. The book software has a Visual Studio WDM Book workspace, which includes a project for the Wdm1Test program. The Wdm1Test code in Wdm1Test.cpp is listed at the end of the chapter.

Wdm1Test is a standard Win32 console application. When run, it appears in a DOS box. As it is a standard Win32 program, you can debug it in Visual Studio as normal (e.g., step through the code).

There are two points to note about the Wdm1Test project. The first is that it includes the c:98ddkincwin98setupapi.h header file. The VC++ 5 version of this file is seriously out of date, so the code specifically includes the Windows 98 DDK version. The second special setting required is to ensure that c:98ddklibi386freesetupapi.lib is listed in the Link property page Output/library modules section of the Project settings.

Getting a Device's Interface Name

The GetDeviceViaInterface routine in Wdm1Test.cpp opens a handle to a device, given the device interface's GUID, as shown in Listing 5.5. GetDeviceViaInterface has a second parameter, instance, which is the zero-based index into the count of available devices. The total number of devices cannot be determined in advance; simply call GetDeviceViaInterface until NULL is returned.

The Wdm1Test main function calls GetDeviceViaInterface with WDM1_GUID and 0 as parameters to open the first available Wdm1 device. Special steps must be taken again to ensure that WDM1_GUID is declared properly. In one module #include 'initguid.h' before including the GUID header file.

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;

 }

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату