210 likes | 370 Views
Introduction to writing device drivers for Windows. Ben Bernstein. bbern@microsoft.com. Device Drivers. Why do we need them ? The only way to connect IO devices to windows (hence the name). The only way to inject code into the windows kernel. Doing stuff in an utmost low level Firewall.
E N D
Introduction to writing device drivers for Windows Ben Bernstein bbern@microsoft.com
Device Drivers • Why do we need them ? • The only way to connect IO devices to windows (hence the name). • The only way to inject code into the windows kernel. • Doing stuff in an utmost low level • Firewall. • AV. • ID.
Device Drivers • Why I hate them • Mostly undocumented, very few web resources. • Very primitive dev tools. • No GUI – I cannot impress anyone. • The kernel never quite seems to forgives my bugs. • Lots of technical details – it’s a little boring. • So much cryptic knowledge we cannot cover the whole subject in two hours.
Windows IO • Windows uses the same mechanism for communicating with files, and communicating with devices. • CreateFile • CloseHandle • WriteFile • ReadFile • DeviceIoControl • Extension – Specific for every device. • Main() example
Windows IO - IRPs • Every IO request from a file or a device gets to the kernel – the IO manager. • The IO manager creates an IRP and dispatches it to the proper driver(s) of the device. • The drivers may decide to make the request pending and answer it after a while. • The driver may decide to pass the IRP to another driver. • A user-mode program may decide to call IO functions asynchronously or synchronously.
PDO FDO FiDO PDO, FDO, Device Enumaration Plug & Play
Device Driver Code #include "ntddk.h" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { // // I wish I could hello world you // return STATUS_SUCCESS; } • A code that runs inside the kernel of windows. • It’s a C/C+/C++ program!
#include "ntddk.h" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { // // I wish I could hello world you // return STATUS_SUCCESS; } Few questions?!(The MS driver rules) • You have to order the DDK. • Compiling: • No IDE - just BUILD.EXE. • no Makefile – just dirs, sources,. • DBG/FRE dos build environments • The .SYS files • Export and import, DriverEntry is the entry point • Weird types • UNICODE_STRING, NTSTATUS, some undocumented.
#include "ntddk.h" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { // // I wish I could hello world you // return STATUS_SUCCESS; } DriverEntry • The DriverEntry RegistryPath parameter. • Points to the registry. • The registry info is usually created by an INF file • The DriverEntry DriverObject parameter. • Used to return callbacks to the OS. #include "ntddk.h" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { // // I wish I could hello world you // return STATUS_SUCCESS; }
Device Driver – Initializing Callbacks NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { DriverObject->DriverUnload = MyUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyClose; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MyCleanup; DriverObject->MajorFunction[IRP_MJ_READ] = MyRead; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=MyCtrl; DriverObject->DriverExtension->AddDevice = MyPnpAddDevice IoCreateDevice( … , “device name”, …) … return STATUS_SUCCESS;}
Device Driver – Dispatch Functions • IOCtrl dispatch function • All in the form of: NTSTATUS MyDispatchFunc( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) • Enables the user of the driver to communicate with the driver. • Filemon Example • DriverUnload dispatch • Does driver cleanup • One can support some and set other to NULL. • DriverExtension->AddDevice vs. DriverEntry
Device Driver – Dispatch Functions • What can the driver functions do ? Call the kernel apis for instance. • Ex ( Executive) • Mm (Memory manager) • Rtl (Run time library) • FsRtl (File system runtime library) • Ob ( Object management) • Io (I/O) • Hal (Hardware abstraction level) • Zw (File & Registry) • Ke (General kernel) • Use DMA to talk to the device
Device Driver - Interrupts • Interrupts – The way the actual device “dispatches” the OS. • In order to register to a certain Interrupt one uses the IoConnectInterrupt API. • Easier with PNP support. • A completion function is passed to the IoConnectInterrupt .
Device Driver - Interrupts • Usually looking like this: BOOLEAN InterruptIsr(IN PKINTERRUPT Interrupt, IN OUT PVOID Context) { … (few commands if any) IoRequestDpc(DeviceObject, DeviceObject->CurrentIrp, NULL); return TRUE; }
Device Driver - Interrupts • What is a DPC? • Deffered procedure call. • Used to postpone the driver calculation to enable receiving other interrupts. • The DPC is processed only after all interrupt are processed. • All interrupts service routines do almost nothing other then queuing DPCs. • Each device object has a DPC inside it, A driver can allocate more DPCs if he believes he’ll get lots of interrupts. • Interrupt Example
Other important issues (that were not quite covered) • IRQL & Interrupts. • DDK API calls and IRQL • Class Filter driver • Spin locks • NPP • WinDBG/SoftIce • FastIoDispatch • IFS • Filter Drivers • PNP dispatch functions.
Bibliography • http://www.sysinternals.com/ - Mark Russinovich • MS DDK. • http://www.beyondlogic.org • Inside Windows 2000.