WDM
(Windows Driver Model)
Y.C. Hua
2005-04-29
1
Requirements
• Familiar with c, c++ programming
• Somewhat familiar with windows programming
2
Driver Model used on various OS
• NT4
KMD (Kernel Model Driver)
• Win95
VxD (Virtual Device Driver)
• Win98/Me
VxD, WDM
• Win2000/XP
KMD, WDM
3
Use driver to access hardware
User mode application
Kernel mode driver
hardware I/O port Physical memory
4
Driver building environment
• Visual studio 6
compiler, linker, editor
• Win98/Me/2000/XP DDK
library, header file for driver
5
Driver loading
• Static load, boot-time load
- Load driver when os booting
- Win98/Me only
• Dynamic load, run-time load
- Load driver when application open driver
- Win2k/Xp can static or dynamic
6
Static load
1. Copy driver to <windir>\system32\drivers
98/Me/XP <windir> = c:\windows, 2k <windir> = c:\winnt
2. Add Registry key
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TESTDRV
3. Add Registry value under added TESTDRV key
ErrorControl = 1 (DWORD)
Type = 1 (DWORD)
Start = 1 (DWORD)
4. Restart computer
7
Service
• Only on win2k/xp.
• Service is a special program independent from multi-user
session.
• It can be running before user login.
• 2 kind of service. Application service and driver service.
• Driver service is for dynamic load.
8
Application call driver
main()
{
CreateDriverService(); // for dynamic load only
HANDLE h=OpenDriver();
DeviceIoControl(h,,,); // ask driver do something
CloseHandle(h);
DeleteDriverService(); // for dynamic load only
}
Green color is Win32 API.
Yellow color is sub function.
9
DeviceIoControl()
BOOL DeviceIoControl(
HANDLE hDevice, // in - handle to device
DWORD dwIoControlCode, // in - operation control code
LPVOID lpInBuffer, // in - input data buffer
DWORD nInBufferSize, // in - size of input data buffer
LPVOID lpOutBuffer, // out - output data buffer
DWORD nOutBufferSize, // in - size of output data buffer
LPDWORD lpBytesReturned, // out - byte count
LPOVERLAPPED lpOverlapped // in - overlapped information
);
Control code : ask driver to do different work
Input buffer : data for driver
Output buffer : result return from driver
Bytes returned : result byte count return from driver
10
Prepare driver file
• makefile : same for all drivers
• sources
• driver source code
11
Build driver
• Launch Build Environment of DDK
• Change to the folder containing driver source files
• Type 'build'.
12
Launch build environment of DDK
13
Type ‘build’ command
14
Contains of sources
TARGETNAME=TESTDRV
TARGETTYPE=DRIVER
DRIVERTYPE=WDM
TARGETPATH=.
SOURCES = [Link]
Check documents or samples of DDK for more detailed information.
15
Control code in devio.h
#define CTL_CODE( DeviceType,Function,Method,Access ) \
(((DeviceType) << 16) | ((Access) << 14) | \
((Function) << 2) | (Method))
#define DEVIO_CallInt15 CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
0x801, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define DEVIO_Test CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
0x802, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
16
DriverEntry (main of the driver)
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
1. Create device
2. Create symbolic link
3. Set major function
}
17
Create device/symbolic link in DriverEntry
UNICODE_STRING uniNtNameString;
UNICODE_STRING uniWin32NameString;
// create device
RtlInitUnicodeString(&uniNtNameString, L"\\Device\\TESTDRV");
IoCreateDevice(DriverObject, 0, &uniNtNameString,
FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);
// create symbolic link
RtlInitUnicodeString(&uniWin32NameString,
L"\\DosDevices\\TESTDRV");
IoCreateSymbolicLink(&uniWin32NameString, &uniNtNameString);
18
Set major function in DriverEntry
// set major function
DriverObject->MajorFunction[IRP_MJ_CREATE] = A::Create;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
A::DeviceControl;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = A::Close;
DriverObject->DriverUnload = A::Unload;
OS load driver DriverEntry
application open driver A::Create
application call DeviceIoControl A::DeviceControl
application close driver A::Close
OS unload driver A::Unload
19
Unload function
UNICODE_STRING uniWin32NameString;
RtlInitUnicodeString(&uniWin32NameString,
L"\\DosDevices\\TESTDRV");
IoDeleteSymbolicLink( &uniWin32NameString );
IoDeleteDevice( DriverObject->DeviceObject );
20
DeviceControl funciton
NTSTATUS A::DeviceControl(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(irp);
ULONG ControlCode = irpStack->[Link];
ULONG InputLength = irpStack->
[Link];
ULONG OutputLength = irpStack->
[Link];
PVOID WorkBuffer = (PVOID)irp->[Link];
switch(ControlCode)
{
case DEVIO_CallInt15: return DoCallInt15(irp);
case DEVIO_Test: return DoTest(irp);
default:
irp->[Link] = STATUS_INVALID_DEVICE_REQUEST;
irp->[Link] = 0; // return byte information
IoCompleteRequest(irp,IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
}
21
Buffer flow
User mode Kernel mode
Application
Input buffer
Driver
Work buffer
Application
Output buffer
22
Last
• Can not use run-time library in Driver
• The sample is in [Link]
[Link]
23