Let’s create a WDM driver and some application to call it (e.g. MFC)
WDM’s source.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
#include "ntddk.h" #define DEVICE_SEND CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA) #define DEVICE_REC CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_READ_DATA) UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\drv_call_wdm"); UNICODE_STRING SymLinkName = RTL_CONSTANT_STRING(L"\\??\\drv_call_wdm_link"); // UNICODE_STRING SymLinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\drv_call_wdm_link"); PDEVICE_OBJECT DeviceObject = NULL; VOID Unload(IN PDRIVER_OBJECT DriverObject) { IoDeleteSymbolicLink(&SymLinkName); IoDeleteDevice(DeviceObject); DbgPrint("Driver unload\r\n"); } NTSTATUS DispatchPassThru(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp); NTSTATUS status = STATUS_SUCCESS; switch (irpsp->MajorFunction) { case IRP_MJ_CREATE: DbgPrint("Create request\r\n"); /*KdPrint(("Create request\r\n"));*/ break; case IRP_MJ_CLOSE: DbgPrint("Close request\r\n"); /*KdPrint(("Close request\r\n"));*/ break; //case IRP_MJ_READ: // DbgPrint("Read request\r\n"); // KdPrint(("Read request\r\n")); // break; default: status = STATUS_INVALID_PARAMETER; break; } Irp->IoStatus.Information = 0; Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } NTSTATUS DispathDevCTL(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp); NTSTATUS status = STATUS_SUCCESS; ULONG returnLength = 0; PVOID buffer = Irp->AssociatedIrp.SystemBuffer; ULONG inLength = irpsp->Parameters.DeviceIoControl.InputBufferLength; ULONG outLength = irpsp->Parameters.DeviceIoControl.OutputBufferLength; WCHAR *demo = L"sample return from driver"; switch (irpsp->Parameters.DeviceIoControl.IoControlCode) { case DEVICE_SEND: DbgPrint("Send data is %ws \r\n", buffer); returnLength = (wcsnlen(buffer, 511) + 1) * 2; break; case DEVICE_REC: wcsncpy(buffer, demo, 511); returnLength = (wcsnlen(buffer, 511) + 1) * 2; DbgPrint("receive data is %ws \r\n", buffer); break; default: status = STATUS_INVALID_PARAMETER; } Irp->IoStatus.Status = status; Irp->IoStatus.Information = returnLength; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) // main { DriverObject->DriverUnload = Unload; UNICODE_STRING string = RTL_CONSTANT_STRING(L"hello driver\r\n"); DbgPrint("%wZ", &string); // printf() NTSTATUS status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("Create device failed\r\n"); return status; } status = IoCreateSymbolicLink(&SymLinkName, &DeviceName); if (!NT_SUCCESS(status)) { DbgPrint("create symbolic link failed\r\n"); IoDeleteDevice(DeviceObject); return status; } for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) { DriverObject->MajorFunction[i] = DispatchPassThru; } DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispathDevCTL; DbgPrint("Driver load\r\n"); return STATUS_SUCCESS; } |