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