Visual Assist X Options -> Projects -> C/C++ Directories -> Platform: Custom, Show Directories for: Stable include files . Click Ins or on the icon to add a new directory and in the appeared line, if you have Windows XP enter %WXPBASE%\inc\ddk\wxp .| DDK version | Variable name | Default path |
|---|---|---|
| Windows XP DDK | WXPBASE | C: \ WINDDK \ 2600 |
| Windows 2003 Server DDK | WNETBASE | C: \ WINDDK \ 3790.1830 |
| Windows Vista / Windows 2008 Server WDK | WLHBASE | |
| Windows 7 / Windows 2008 Server R2 WDK | W7BASE |
DriverEntry and AddDevice .IRP is a structure that drivers use to exchange data. __asm { lock dec «, » } __asm { lock inc «, » } lock prefix allows you to safely execute the command following it. It blocks the remaining processors while the command is executed. extern "C" { #include "ntddk.h" } #include "ntddkbd.h" DEVICE_EXTENSION typedef struct _DEVICE_EXTENSION{ PDEVICE_OBJECT pLowerDO; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; pLowerDO object is a device object that is below us on the stack. We need it in order to know who else to send IRP packets to. int gnRequests; extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING ustrRegistryPath) theDriverObject is a driver object that contains pointers to all functions necessary for the operating system, which we will need to initialize.ustrRegistryPath is the name of the section in the registry where information about this driver is stored. gnRequests = 0; NTSTATUS status = {0}; for (int i = 0; i<IRP_MJ_MAXIMUM_FUNCTION; ++i) { theDriverObject->MajorFunction[i] = DispatchThru; } theDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead; theDriverObject->DriverUnload = DriverUnload; DispatchRead function will handle read requests. It will be called when the keyboard key is pressed or released.DriverUnload function DriverUnload called when the driver is no longer needed and can be unloaded from memory, or when the user unloads the driver. In this function, “stripping” should be performed, i.e. the resources used by the driver are released, all pending requests are completed, etc.DispatchThru function is a stub function. All it does is transfer the IRP packet to the next driver (the driver that is under our stack, i.e. pLowerDO from DEVICE_EXTENSION ). status = InstallFilter(theDriverObject); status , in which, if the InstallFilter function was InstallFilter , the value STATUS_SUCCESS is stored.InstallFilter function. Here is its prototype: NTSTATUS InstallFilter(IN PDRIVER_OBJECT theDO); \\Device\\KeyboardClass0 PDEVICE_OBJECT pKeyboardDevice; NTSTATUS status = {0}; pKeyboardDevice is the device object we need to create.IoCreateDevice to create a new device. status = IoCreateDevice(theDO, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &pKeyboardDevice); pKeyboardDevice->Flags = pKeyboardDevice->Flags | (DO_BUFFERED_IO | DO_POWER_PAGABLE); pKeyboardDevice->Flags = pKeyboardDevice->Flags & ~DO_DEVICE_INITIALIZING; CCHAR cName[40] = "\\Device\\KeyboardClass0"; STRING strName; UNICODE_STRING ustrDeviceName; RtlInitAnsiString(&strName, cName); RtlAnsiStringToUnicodeString(&ustrDeviceName, &strName, TRUE); IoAttachDevice function injects our device onto the stack. The object of the next (lower) device will be stored in pdx->pLowerDO . IoAttachDevice(pKeyboardDevice, &ustrDeviceName, &pdx->pLowerDO); RtlFreeUnicodeString(&ustrDeviceName); DispatchRead with the prototype: NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp); __asm { lock inc gnRequests } IoCopyCurrentIrpStackLocationToNext copies the memory location that belongs to the current driver to the memory area of ​​the next driver. IoCopyCurrentIrpStackLocationToNext(theIrp); When a request goes down the stack, it still does not have the data we need, so we need to specify a function that will be called when the request goes up the stack with the data we need. IoSetCompletionRoutine(theIrp, ReadCompletionRoutine, pDeviceObject, TRUE, TRUE, TRUE) ReadCompletionRoutine our function.IRP following driver: return IoCallDriver(((PDEVICE_EXTENSION) pDeviceObject->DeviceExtension)->pLowerDO ,theIrp); IRP completed. Prototype: NTSTATUS ReadCompletionRoutine(IN PDEVICE_OBJECT pDeviceObject, IN PIRP theIrp, IN PVOID Context); DEVICE_EXTENSION : PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension; PKEYBOARD_INPUT_DATA structure PKEYBOARD_INPUT_DATA used to describe the key pressed. PKEYBOARD_INPUT_DATA kidData; if (NT_SUCCESS(theIrp->IoStatus.Status)) KEYBOARD_INPUT_DATA structure, you need to refer to the system IRP packet buffer. kidData = (PKEYBOARD_INPUT_DATA)theIrp->AssociatedIrp.SystemBuffer; int n = theIrp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA); for(int i = 0; i<n; ++i) DbgPrint("Code: %x\n", kidData[i].MakeCode); __asm { lock dec gnRequests } return theIrp->IoStatus.Status; VOID DriverUnload(IN PDRIVER_OBJECT theDO); DEVICE_EXTENSION : PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)theDO->DeviceObject->DeviceExtension; IoDetachDevice(pdx->pLowerDO); IoDeleteDevice(theDO->DeviceObject); if (gnRequests != 0) { KTIMER ktTimer; LARGE_INTEGER liTimeout; liTimeout.QuadPart = 1000000; KeInitializeTimer(&ktTimer); , while(gnRequests > 0) { KeSetTimer(&ktTimer, liTimeout, NULL); // KeWaitForSingleObject(&ktTimer, Executive, KernelMode, FALSE, NULL); // } } extern "C" { #include "ntddk.h" } #include "ntddkbd.h" typedef struct _DEVICE_EXTENSION{ PDEVICE_OBJECT pLowerDO; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; int gnRequests; NTSTATUS DispatchThru(PDEVICE_OBJECT theDeviceObject, PIRP theIrp) { IoSkipCurrentIrpStackLocation(theIrp); return IoCallDriver(((PDEVICE_EXTENSION) theDeviceObject->DeviceExtension)->pLowerDO ,theIrp); } NTSTATUS InstallFilter(IN PDRIVER_OBJECT theDO) { PDEVICE_OBJECT pKeyboardDevice; NTSTATUS status = {0}; status = IoCreateDevice(theDO, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &pKeyboardDevice); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateDevice error.."); return status; } pKeyboardDevice->Flags = pKeyboardDevice->Flags | (DO_BUFFERED_IO | DO_POWER_PAGABLE); pKeyboardDevice->Flags = pKeyboardDevice->Flags & ~DO_DEVICE_INITIALIZING; RtlZeroMemory(pKeyboardDevice->DeviceExtension, sizeof(DEVICE_EXTENSION)); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pKeyboardDevice->DeviceExtension; CCHAR cName[40] = "\\Device\\KeyboardClass0"; STRING strName; UNICODE_STRING ustrDeviceName; RtlInitAnsiString(&strName, cName); RtlAnsiStringToUnicodeString(&ustrDeviceName, &strName, TRUE); IoAttachDevice(pKeyboardDevice, &ustrDeviceName, &pdx->pLowerDO); //DbgPrint("After IoAttachDevice"); RtlFreeUnicodeString(&ustrDeviceName); return status; } VOID DriverUnload(IN PDRIVER_OBJECT theDO) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)theDO->DeviceObject->DeviceExtension; IoDetachDevice(pdx->pLowerDO); IoDeleteDevice(theDO->DeviceObject); if (gnRequests != 0) { KTIMER ktTimer; LARGE_INTEGER liTimeout; liTimeout.QuadPart = 1000000; KeInitializeTimer(&ktTimer); while(gnRequests > 0) { KeSetTimer(&ktTimer, liTimeout, NULL); KeWaitForSingleObject(&ktTimer, Executive, KernelMode, FALSE, NULL); } } } NTSTATUS ReadCompletionRoutine(IN PDEVICE_OBJECT pDeviceObject, IN PIRP theIrp, IN PVOID Context) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension; PKEYBOARD_INPUT_DATA kidData; if (NT_SUCCESS(theIrp->IoStatus.Status)) { kidData = (PKEYBOARD_INPUT_DATA)theIrp->AssociatedIrp.SystemBuffer; int n = theIrp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA); for(int i = 0; i<n; ++i) { DbgPrint("Code: %x\n", kidData[i].MakeCode); } } if(theIrp->PendingReturned) IoMarkIrpPending(theIrp); __asm{ lock dec gnRequests } return theIrp->IoStatus.Status; } NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP theIrp) { __asm{ lock inc gnRequests } IoCopyCurrentIrpStackLocationToNext(theIrp); IoSetCompletionRoutine(theIrp, ReadCompletionRoutine, pDeviceObject, TRUE, TRUE, TRUE); return IoCallDriver(((PDEVICE_EXTENSION) pDeviceObject->DeviceExtension)->pLowerDO ,theIrp); } extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = {0}; gnRequests = 0; for (int i = 0; i<IRP_MJ_MAXIMUM_FUNCTION; ++i) { theDriverObject->MajorFunction[i] = DispatchThru; } theDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead; status = InstallFilter(theDriverObject); theDriverObject->DriverUnload = DriverUnload; return status; } # # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source # file to this component. This file merely indirects to the real make file # that is shared by all the driver components of the Windows NT DDK # !INCLUDE $(NTMAKEENV)\makefile.def TARGETNAME=sysfile TARGETPATH=BIN TARGETTYPE=DRIVER SOURCES = DriverMain.cpp Source: https://habr.com/ru/post/146071/
All Articles