|
Pointer Member (DriverObject->xxx) |
Brief Description |
|
DriverExtension->AddDevice |
Initialize to handle a new device |
|
DriverInit |
Initialize driver |
|
DriverStartIo |
Begin processing the next queued request |
|
DriverUnload |
Cleanup when driver unloaded after all of its devices are removed |
|
MajorFunction[IRP_MJ_xxx] |
Handle I/O request of type xxx |
Figure 5 Driver.H and AddDevice
DRIVER.H
#ifndef DRIVER_H
#define DRIVER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <wdm.h>
#ifdef __cplusplus
} // extern "C"
#endif
#define arraysize(p) (sizeof(p)/sizeof((p)[0]))
typedef struct tagDEVICE_EXTENSION {
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT LowerDeviceObject;
UNICODE_STRING ifname;
LONG usage;
KEVENT evRemove;
PULONG idle;
BOOLEAN started;
BOOLEAN enabled;
BOOLEAN iospace;
BOOLEAN mappedport;
BOOLEAN removing;
DEVICE_POWER_STATE power;
ULONG nports;
PUCHAR base;
PKINTERRUPT InterruptObject;
PUCHAR buffer;
ULONG nbytes;
ULONG numxfer;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define SIMPLE_IDLE_CONSERVATION 30
#define SIMPLE_IDLE_PERFORMANCE 600
NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG info);
VOID DpcForIsr(IN PKDPC Dpc, IN PDEVICE_OBJECT fdo, IN PIRP Irp,
IN PVOID Context);
NTSTATUS ForwardAndWait(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
BOOLEAN LockDevice(IN PDEVICE_EXTENSION pdx);
BOOLEAN LockDevice(IN PDEVICE_OBJECT fdo);
NTSTATUS OnRequestComplete(IN PDEVICE_OBJECT fdo, IN PIRP Irp,
IN PKEVENT pev);
NTSTATUS SendDeviceSetPower(IN PDEVICE_OBJECT fdo,
IN DEVICE_POWER_STATE state, ULONG context);
VOID SetPowerState(IN PDEVICE_OBJECT fdo, IN DEVICE_POWER_STATE state);
VOID RemoveDevice(IN PDEVICE_OBJECT fdo);
NTSTATUS StartDevice(PDEVICE_OBJECT fdo, PCM_PARTIAL_RESOURCE_LIST list);
VOID StopDevice(PDEVICE_OBJECT fdo);
VOID StartIo(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
void UnlockDevice(IN PDEVICE_EXTENSION pdx);
void UnlockDevice(IN PDEVICE_OBJECT fdo);
// I/O request handlers
NTSTATUS RequestCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS RequestClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS RequestControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS RequestPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS RequestPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS RequestWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
// {3d93c5c0-0085-11d1-821e-0080c88327ab}
#ifndef FAR
#define FAR
#endif
DEFINE_GUID(GUID_SIMPLE, 0x3d93c5c0, 0x0085, 0x11d1, 0x82, 0x1e, 0x00,
0x80, 0xc8, 0x83, 0x27, 0xab);
#endif // DRIVER_H
DRIVERENTRY.CPP (Excerpt)
NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
{ // AddDevice
NTSTATUS status;
PDEVICE_OBJECT fdo;
status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL,
FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);
if (!NT_SUCCESS(status))
return status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
pdx->DeviceObject = fdo;
pdx->usage = 1; // locked until RemoveDevice
KeInitializeEvent(&pdx->evRemove, NotificationEvent, FALSE);
status = IoRegisterDeviceInterface(pdo, &GUID_SIMPLE, NULL,
&pdx->ifname);
if (!NT_SUCCESS(status))
{ // unable to register interface
IoDeleteDevice(fdo);
return status;
} // unable to register interface
IoSetDeviceInterfaceState(&pdx->ifname, TRUE);
pdx->LowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
IoInitializeDpcRequest(fdo, DpcForIsr);
fdo->Flags |= DO_BUFFERED_IO;
pdx->power = PowerDeviceD0; // device starts in full power state
pdx->idle = PoRegisterDeviceForIdleDetection(pdo,
SIMPLE_IDLE_CONSERVATION, SIMPLE_IDLE_PERFORMANCE, PowerDeviceD3);
return STATUS_SUCCESS;
} // AddDevice
Figure 7 Test Program for SIMPLE.SYS
// TEST.CPP
#include <windows.h>
#include <stdio.h>
#include <winioctl.h>
#include <setupapi.h>
#include "SimpleIoctl.h"
// {3d93c5c0-0085-11d1-821e-0080c88327ab}
#include <initguid.h>
DEFINE_GUID(GUID_SIMPLE, 0x3d93c5c0, 0x0085, 0x11d1, 0x82, 0x1e, 0x00,
0x80, 0xc8, 0x83, 0x27, 0xab);
#define Not_VxD
#include "myvxd.h"
void main(int argc, char* argv[])
{ // main
HDEVINFO info = SetupDiGetClassDevs((LPGUID) &GUID_SIMPLE, NULL, NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
if (info == INVALID_HANDLE_VALUE)
{
printf("Error %d trying to open enumeration handle for " "GUID_SIMPLE\n",
GetLastError());
exit(1);
}
SP_INTERFACE_DEVICE_DATA ifdata;
ifdata.cbSize = sizeof(ifdata);
if (!SetupDiEnumInterfaceDevice(info, NULL, (LPGUID) &GUID_SIMPLE,
0, &ifdata))
{
printf("Error %d trying to enumerate interfaces\n",
GetLastError());
SetupDiDestroyDeviceInfoList(info);
exit(1);
}
DWORD needed;
SetupDiGetInterfaceDeviceDetail(info, &ifdata, NULL, 0, &needed, NULL);
PSP_INTERFACE_DEVICE_DETAIL_DATA detail =
(PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(needed);
if (!detail)
{
printf("Error %d trying to get memory for interface detail\n",
GetLastError());
SetupDiDestroyDeviceInfoList(info);
exit(1);
}
detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
if (!SetupDiGetInterfaceDeviceDetail(info, &ifdata, detail, needed,
NULL, NULL))
{
printf("Error %d getting interface detail\n", GetLastError());
free((PVOID) detail);
SetupDiDestroyDeviceInfoList(info);
exit(1);
}
char name[MAX_PATH];
strncpy(name, detail->DevicePath, sizeof(name));
free((PVOID) detail);
SetupDiDestroyDeviceInfoList(info);
HANDLE hfile = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
printf("Error %d trying to open %s\n", GetLastError(), name);
exit(1);
}
//The code above is a partial listing of Test.cpp. The complete
//listing will be published in the second article of this two part
//series. In addition the entire listing is available on the MSJ
//web site, http://microsoft.com/msj .
}