Listing 2: wdj.c A simple NT device driver
// wdj.c #include "ntddk.h" #include "ntdddisk.h" #include "wdj.h" typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT NextDeviceObject; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; NTSTATUS WdjDrvDispatch(IN PDEVICE_OBJECT, IN PIRP); VOID WdjDrvUnload(IN PDRIVER_OBJECT); NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject = NULL; UNICODE_STRING deviceName, dosName, floppyName; PDEVICE_EXTENSION deviceExt = NULL; PFILE_OBJECT fileObject = NULL; // // Create an EXCLUSIVE device object. // RtlInitUnicodeString(&deviceName, L"\\Device\\WdjDrv"); status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &deviceName, FILE_DEVICE_WDJDRV, 0, TRUE, &deviceObject); if (!NT_SUCCESS(status)) { return STATUS_UNSUCCESSFUL; } // // Create a symbolic link that Win32 apps can specify to gain // access to this driver/device // RtlInitUnicodeString(&dosName, L"\\DosDevices\\WDJDRV"); status = IoCreateSymbolicLink(&dosName, &deviceName); if (!NT_SUCCESS(status)) { DbgPrint("WDJ.SYS: create symbolic link failed\n"); IoDeleteDevice(deviceObject); return STATUS_UNSUCCESSFUL; } deviceExt = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; // // Get a device object pointer to floppy device 0 and save it in // the device extension for use later. // RtlInitUnicodeString(&floppyName, L"\\Device\\Floppy0"); status = IoGetDeviceObjectPointer(&floppyName, FILE_ANY_ACCESS, &fileObject, &deviceExt->NextDeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("WDJ.SYS: get device object failed\n"); IoDeleteSymbolicLink(&dosName); IoDeleteDevice(deviceObject); return STATUS_UNSUCCESSFUL; } ObDereferenceObject(fileObject); // // Create dispatch points for device control, create, close. // DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WdjDrvDispatch; DriverObject->DriverUnload = WdjDrvUnload; return status; } // DriverEntry NTSTATUS WdjDrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExt; PVOID ioBuffer; ULONG inLength; ULONG outLength; ULONG ioctl; irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExt = DeviceObject->DeviceExtension; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; // // Get the pointer to the input/output buffer and it's length // ioBuffer = Irp->AssociatedIrp.SystemBuffer; inLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: DbgPrint("WDJ.SYS: IRP_MJ_CREATE\n"); break; case IRP_MJ_CLOSE: DbgPrint("WDJ.SYS: IRP_MJ_CLOSE\n"); break; case IRP_MJ_DEVICE_CONTROL: DbgPrint("WDJ.SYS: IRP_MJ_DEVICE_CONTROL\n"); ioctl = irpStack->Parameters.DeviceIoControl.IoControlCode; switch (ioctl) { case IOCTL_WDJ_REQUEST: { PIRP NewIrp; IO_STATUS_BLOCK IoStatusBlock; KEVENT Event; ULONG media = 0xFFFFFFFF; // unknown if (outLength < sizeof(ULONG)) { Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; break; } KeInitializeEvent(&Event, SynchronizationEvent, FALSE); NewIrp = IoBuildDeviceIoControlRequest( IOCTL_DISK_CHECK_VERIFY, deviceExt->NextDeviceObject, NULL, 0, NULL, 0, FALSE, &Event, &IoStatusBlock); if (NewIrp == NULL) { Irp->IoStatus.Status = IoStatusBlock.Status; break; } status = IoCallDriver(deviceExt->NextDeviceObject, NewIrp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&Event, UserRequest, UserMode, TRUE, NULL); } if (IoStatusBlock.Status == STATUS_NO_MEDIA_IN_DEVICE) { media = FALSE; } else if (IoStatusBlock.Status == STATUS_SUCCESS) { media = TRUE; } RtlCopyMemory(ioBuffer, &media, sizeof(ULONG)); Irp->IoStatus.Information = sizeof(ULONG); break; } default: DbgPrint("WDJ.SYS: unknown IOCTL\n"); Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; } break; } status = Irp->IoStatus.Status; // save before releasing irp IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; // no pending ops, return status } // WdjDrvDispatch VOID WdjDrvUnload(IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING unicodeString; // // Delete the symbolic link and the device object. // RtlInitUnicodeString(&unicodeString, L"\\DosDevices\\WDJDRV"); IoDeleteSymbolicLink(&unicodeString); IoDeleteDevice(DriverObject->DeviceObject); } // WdjUnload /* End of File */