Title: Windows NT driverek fejleszt
1Windows NT driverek fejlesztése Egyszeru
driverek készítése
9
- eloadás
- dr. Robu Judit
- szeminárium
- drd. Lukács Sándor
2006
2Driver objektumok (DRIVER_OBJECT)
- typedef struct _DRIVER_OBJECT
- // The following links all of the devices
created by a single driver together on a - // list, and the Flags word provides an
extensible flag location for driver objects. - PDEVICE_OBJECT DeviceObject // de DEVICE
objektum lista elso eleme - ULONG Flags
- // The following section describes where the
driver is loaded. - PVOID DriverStart // a driver
bináris képének kezdocíme - ULONG DriverSize
- PVOID DriverSection
- ...
- // The driver name field is used by the error
log thread - // determine the name of the driver that an
I/O request is/was bound. - UNICODE_STRING DriverName
- ...
- // The following section describes the entry
points to this particular driver. - PDRIVER_INITIALIZE DriverInit //
DriverEntry kezdocíme
3Device objektumok (DEVICE_OBJECT)
- typedef struct _DEVICE_OBJECT
- LONG ReferenceCount
- struct _DRIVER_OBJECT DriverObject
- struct _DEVICE_OBJECT NextDevice
- ...
- struct _IRP CurrentIrp // csak StartIo
rutinnal párhuzamosan használt, - // NULL ha nincs
aktuális IRP feldolgozás alatt - ...
- ULONG Flags // DO_BUFFERED_IO,
DO_DIRECT_IO, - I/O típus -
DO_BUS_ENUMERATED_DEVICE, - PDO -
DO_DEVICE_INITIALIZING, ... - inicializálás
aktív - ULONG Characteristics //
FILE_DEVICE_IS_MOUNTED, -
FILE_READ_ONLY_DEVICE, -
FILE_REMOVABLE_MEDIA, -
FILE_VIRTUAL_VOLUME, ... - ...
- PVOID DeviceExtension // programozó
által definált - DEVICE_TYPE DeviceType //
FILE_DEVICE_CD_ROM, FILE_DEVICE_DISK, -
FILE_DEVICE_FILE_SYSTEM,
4Standard I/O muvelet feldolgozás
DISPATCH
COMPLETION
- (az ábra Walter Oney Programming the Microsoft
Windows Driver Model, Microsoft Press, 1999
alapján készült)
5I/O muvelet típusok
- több I/O típus van
- állomány alapú / jellegu I/O
- támogatja a Read / Write / Seek stb. jellegu
muveleteket - nagyon állományrendszer specifikus
- device / FS kontroll I/O kérések
- explicit, eszköz specifikus I/O kérések küldése
- vannak FS specifikus kérések is
- további kommunikációs csatornák
- Filter Manager specifikus kommunikációs portok
- szinkron / aszinkron támogatás, kétírányú
kezdeményezés - speciális esetben osztott memória
- minden driver az elvárásoknak és a támogatott
eszköz tulajdonságainak megfeleloen támogat egy
vagy több típust
6IRP dispatch kérések 1
- IRP_MJ_CREATE ZwCreateFile
- device objektumok vagy állományok megnyítása
- egy FILE_OBJECT objektumot inicializál
- IRP_MJ_CLEANUP ZwClose, 1 lépés
- a FILE_OBJECT-re mutató utolsó handle bezárásakor
hívódik meg - IRP_MJ_CLOSE ZwClose, 2 lépés
- az utolsó I/O muvelet elvégzése után hívódik meg
- IRP_MJ_READ ZwReadFile
- IRP_MJ_WRITE ZwWriteFile
- állományok vagy lemezegységek írása / olvasása
- IRP_MJ_FLUSH_BUFFERS ZwFlushBuffersFile
- egy ilyen kérés esetén egy driver kiurití az
össze átementi cachet - IRP_MJ_DIRECTORY_CONTROL ZwQueryDirectoryFile
- könyvtár lekérdezések esetén hívódik meg (pl.
FindFirst, FindNext)
7IRP dispatch kérések 2
- IRP_MJ_QUERY_INFORMATION ZwQueryInformationFile
- IRP_MJ_SET_INFORMATION ZwSetInformationFile
- állományokkal kapcsolatos információk lekérdezése
/ beállítása - FileBasicInformation create time, file
attributes etc. - FileNameInformation állomány neve
- FileStandardInformation állomány mérete, hard
linkek száma, könyvtár-e?, az állomány törlödik-e
bezárások (delete pending) - FilePositionInformation állomány pozíció
- IRP_MJ_QUERY_VOLUME_INFORMATION
ZwQueryVolumeInformationFile - IRP_MJ_SET_VOLUME_INFORMATION
ZwSetVolumeInformationFile - lemezegységekkel kapcsolatos információk
lekérdezése / beállítása - FileFsDeviceInformation CD-ROM, HDD, floppy,
read-only stb. - FileFsFullSizeInformation a lemezegység mérete,
szabad blokkok stb. - FileFsVolumeInformation lemezegyés neve, serial
number stb. - IRP_MJ_FILE_SYSTEM_CONTROL ZwFsControlFile
- IRP_MJ_DEVICE_CONTROL ZwDeviceIoControlFile
- FSCTL és IOCTL kérések végrehajtása
- speciális kérések/parancsok a hardver egységek és
FS driverek számára(pl. IOCTL_CDROM_DISC_INFO,
IOCTL_CDROM_GET_DRIVE_GEOMETRY,
IOCTL_CDROM_RAW_READ, FSCTL_DISMOUNT_VOLUME,
FSCTL_SET_SPARSE, FSCTL_GET_VOLUME_BITMAP,
FSCTL_MOVE_FILE etc.)
8Driver, device és I/O stack függoség
COMPLETION
DISPATCH
- (az ábra Walter Oney Programming the Microsoft
Windows Driver Model, Microsoft Press, 1999
alapján készült)
9IRP paraméterek 1
- typedef struct _IO_STACK_LOCATION
- UCHAR MajorFunction
- UCHAR MinorFunction
- UCHAR Flags
- UCHAR Control
- union
- // System service parameters for
NtCreateFile - struct
- PIO_SECURITY_CONTEXT SecurityContext
- ULONG Options
- USHORT POINTER_ALIGNMENT
FileAttributes - USHORT ShareAccess
- ULONG POINTER_ALIGNMENT EaLength
- Create
- // System service parameters for
NtReadFile - struct
- ULONG Length
- ULONG POINTER_ALIGNMENT Key
- LARGE_INTEGER ByteOffset
10IRP paraméterek 2
- // Save a pointer to this device driver's
device object for this request - // so it can be passed to the completion
routine if needed. - PDEVICE_OBJECT DeviceObject
- // The following location contains a pointer
to the file object for this request. - PFILE_OBJECT FileObject
- // The following routine is invoked depending
on the flags in the above flags field. - PIO_COMPLETION_ROUTINE CompletionRoutine
- // The following is used to store the address
of the context parameter - // that should be passed to the
CompletionRoutine. - PVOID Context
- IO_STACK_LOCATION, PIO_STACK_LOCATION
- egy IRP feldolgozása során minden driver számára
le van foglalva egy IRPSP struktúra - irpSp IoGetCurrentIrpStackLocation(Irp) a
jelenlegi driver szintjén lévo IRPSP struktúra
címe
11I/O bufferek kezelése
- egy I/O kérés végrehajtársa különbözo processz
kontextusokban történhet - pl. egy READ/WRITE kérés végrehajtása a hívó fél
(gyakran user módbeli alkalmazás) kontextusában
kezdodig, majd miután a hardver végrehajtotta a
kérést és egy megaszkítást generál, egy
tetszoleges rendszer kontextusban folyatódik és
fejezodik be - a legtöbb esetben a memória mutatók, bufferek
stb. NEM használhatók tetszoleges kontextusban - három alapveto I/O buffer kezelési módszer
- Buffered I/O az I/O manager elkészít egy, a
hívó bufferrel azonos méretu NonPaged rendszer
buffert és ebbe másolja az adatokat átmenetileg - READ esetén a completion rutinban kernel
nonpaged ? alkalmazás - WRITE esetén a dispatch turinban alkalmazás ?
kernel nonpaged - Direct I/O az I/O manager rögzíti a memóriába
az alkalmazás bufferének megfelelo fizikai
lapokat, elkészít egy, ezeket a lapokat leíró
MDL-t, majd ezt az MDL-t továbbítja a drivernek
amely tetszolegesen betukrözi a lapokat a
rendszer virtuális címterületére (új laptábla
bemenetekkel) - Neither I/O az I/O manager nem végez semmilyen
buffer és cím átalakítást, közvetlenül a hívó
buffer eredeti címét adja át a drivernek
12Buffered I/O
- ha DEVICE_OBJECT Flags mezoje tartalmazza a
DO_BUFFERED_IO-t - ha az IOCTL kód buffered I/O-t kér
13Direct I/O, PIO feldolgozással
- ha DEVICE_OBJECT Flags mezoje tartalmazza a
DO_DIRECT_IO-t - ha az IOCTL kód buffered I/O-t kér
- PIO programmed I/O
14Direct I/O, DMA feldolgozással
- ha DEVICE_OBJECT Flags mezoje tartalmazza a
DO_DIRECT_IO-t - ha az IOCTL kód buffered I/O-t kér
- DMA direct memory access
15IRP_MJ_CREATE
- amikor egy új állományt vagy könyvtárat hozunk
létre,vagy egy már létezo állományt, könyvtárat,
partíciót vagy eszközt akarunk megnyítni - paraméterek
- DeviceObject a device amelyen a muveletet végre
kell hajtani - Options IrpSp-gtParameters.Create.Options
FILE_VALID_OPTION_FLAGS - Disposition (IrpSp-gtParameters.Create.Options
gtgt 24) 0xFF - CREATE_NEW, OPEN_EXISTING, CREATE_ALWAYS, ...
- IrpSp-gtParameters.Create.FileAttributes
- IrpSp-gtParameters.Create.ShareAccess
- IrpSp-gtFileObject-gtFileName
- IrpSp-gtFileObject-gtRelatedFileObject ha nem
abszolút path-el dolgozunk - IrpSp-gtFileObject-gtFlags
- FO_SYNCHRONOUS_IO, FO_NO_INTERMEDIATE_BUFFERING
- kimenet
- IrpSp-gtFileObject-gtFsContext, IrpSp-gtFileObject-gtF
sContext2 - FS driver specifikus, bármilyen saját információ
vagy pointer - Irp-gtIoStatus.Status
- STATUS_SUCCESS, STATUS_OBJECT_NAME_NOT_FOUND,
STATUS_ACCESS_DENIED - Irp-gtIoStatus.Information
- FILE_OPENED, FILE_DOES_NOT_EXIST
16IRP_MJ_CLEANUP
- amikor egy file objektum handle referencia
számlálója nullára vált (az utolsó handelt is
bezárátk) - paraméterek
- DeviceObject a device amelyen a muveletet végre
kell hajtani - IrpSp-gtFileObject
- az IrpSp-gtFileObject-gtFileName NEM érvényes
- IrpSp-gtFileObject-gtFsContext, IrpSp-gtFileObject-gtF
sContext2 - kimenet
- IrpSp-gtFileObject-gtFlags FO_CLEANUP_COMPLETE
- ezt mindig el kell végezni a cleanup végén
- Irp-gtIoStatus.Status
- STATUS_SUCCESS
- Irp-gtIoStatus.Information
- 0
17IRP_MJ_CLOSE
- amikor egy file objektum referencia számlálója
nullára vált (már egyetlen pointer vagy handel
sem mutat a file objektumra) - paraméterek
- DeviceObject a device amelyen a muveletet végre
kell hajtani - IrpSp-gtFileObject
- az IrpSp-gtFileObject-gtFileName NEM érvényes
- IrpSp-gtFileObject-gtFsContext, IrpSp-gtFileObject-gtF
sContext2 - kimenet
- fel kell szabadítani minden file specifikus
eroforrást - ezt mindig el kell végezni a close végén
- Irp-gtIoStatus.Status
- STATUS_SUCCESS
- Irp-gtIoStatus.Information
- 0
18IRP_MJ_READ
- több aleset van, ezek közül az IRP_MN_xxx
kódokkal teszünk különbséget - IRP_MN_NORMAL klasszikus olvasás
- paraméterek
- DeviceObject a device amelyen a muveletet végre
kell hajtani - IrpSp-gtFileObject-gtFsContext, IrpSp-gtFileObject-gtF
sContext2 - IrpSp-gtParameters.Read.ByteOffset.QuadPart
- IrpSp-gtParameters.Read.Length
- Irp-gtAssociatedIrp.SystemBuffer BUFFERED I/O
esetén - Irp-gtMdlAddress DIRECT I/O esetén
- Irp-gtUserBuffer NEITHER I/O esetén
- kimenet
- Irp-gtIoStatus.Status
- Irp-gtIoStatus.Information BytesReaded
- sikeres végrehajtás és FO_SYNCHRONOUS_IO kérés
esetén mindig updatelni kell az aktuális file
pozíciót - IrpSp-gtFileObject-gtCurrentByteOffset.QuadPart
19IRP_MJ_DEVICE_CONTROL
- a legtöbb esetben egy felhasználói alkalmazás
vagy egy 3rd party kernel komponens IOCTL kérése
estén küldodik - paramétrek
- DeviceObject a device amelyen a muveletet végre
kell hajtani - Irp-gtAssociatedIrp.SystemBuffer BUFFERED I/O
esetén - Irp-gtMdlAddress DIRECT I/O esetén
- Irp-gtUserBuffer NEITHER I/O esetén
- IrpSp-gtParameters.DeviceIoControl.InputBufferLengt
h - IrpSp-gtParameters.DeviceIoControl.IoControlCode
- IrpSp-gtParameters.DeviceIoControl.OutputBufferLeng
th - kimenet
- Irp-gtIoStatus.Status
- Irp-gtIoStatus.Information kimeneti adatok mérete
20Egy összeadó driver implementálása
- minimális driver, amely...
- létrehoz egy device objektumot
- ezt elérhetové teszi a user mód számára is
szimbolikus link által - megengedi a device objektum megnyítását (CREATE),
azért, hogy lehessen kéreseket küldeni a driver
fele egy handel-nek a segítségével - természetesen szükséges CLEANUP és CLOSE is
- a device specifikus I/O kommunikációt
felhasználva (IOCTL) elfogad és végrehajt egy
speciális kérést - két bemeno egész értéket összead, és az eredményt
egy kimeneti értékbe helyezi - az adatok átadását BUFFERED I/O módszerrel oldjuk
meg
21Általános definíciók
- // driver and device name
- define DRIVER_NAME "sumdriver.sys"
- define DEVICE_NAME L"\\sumdriver"
- define DOS_DEVICE_NAME L"\\dosdevices\\sumdev
ice" - // driver specific I/O structures
- typedef struct _IOCTL_SUM
-
- __int32 a
- __int32 b
- __int32 c
- IOCTL_SUM, PIOCTL_SUM
- // driver global data
- extern DRV_GLOBAL_DATA DrvGlobalData
- // IOCTL codes
- define IOCTL_DRV_SUM_TWO_INTS
\ - (ULONG)CTL_CODE( FILE_DEVICE_UNKNOWN,
0x0981, METHOD_BUFFERED,
FILE_ANY_ACCESS)
typedef struct _DRV_GLOBAL_DATA
PDRIVER_OBJECT DriverObject
PDEVICE_OBJECT DeviceObject
UNICODE_STRING DeviceName UNICODE_STRING
DosDeviceName DRV_GLOBAL_DATA,
PDRV_GLOBAL_DATA
22DriverEntry 1
- NTSTATUS DriverEntry(
- __in PDRIVER_OBJECT DriverObject, __in
PUNICODE_STRING RegistryPath ) - ...
- // clear global data area
- RtlZeroMemory(DrvGlobalData,
sizeof(DRV_GLOBAL_DATA)) - // get DriverObject into global data
- DrvGlobalData.DriverObject DriverObject
- // setup unload routine
- DrvGlobalData.DriverObject-gtDriverUnload
DriverUnload - // initialize the dispatch entry points
- DriverObject-gtMajorFunctionIRP_MJ_CREATE
Drv_MJ_CREATE - DriverObject-gtMajorFunctionIRP_MJ_CLEANUP
Drv_MJ_CLEANUP - DriverObject-gtMajorFunctionIRP_MJ_CLOSE
Drv_MJ_CLOSE - DriverObject-gtMajorFunctionIRP_MJ_DEVICE_CONT
ROL Drv_MJ_DEVICE_CONTROL -
23DriverEntry 2
- // create the main device object
- RtlInitUnicodeString((DrvGlobalData.DeviceName),
DEVICE_NAME) - status IoCreateDevice(DriverObject, 0,
DrvGlobalData.DeviceName, - FILE_DEVICE_UNKNOWN, 0, FALSE,
DrvGlobalData.DeviceObject) - if (!NT_SUCCESS(status))
-
- ExKdPrint((" DriverEntry - error loading
driver\n")) - return status
-
- // clear DO_DEVICE_INITIALIZING
- DrvGlobalData.DeviceObject-gtFlags
DO_DEVICE_INITIALIZING - // create symbolic link
- RtlInitUnicodeString((DrvGlobalData.DosDeviceName
), DOS_DEVICE_NAME) - IoCreateSymbolicLink((DrvGlobalData.DosDeviceName
), (DrvGlobalData.DeviceName)) - return status
24DriverUnload
- VOID DriverUnload(__in PDRIVER_OBJECT
DriverObject) -
- UNREFERENCED_PARAMETER(DriverObject)
- ExKdPrint(("try to unload driver\n"))
- // break into kernel debugger if enabled
- // DbgBreakPointWithStatus(0x12345678)
- // delete symbolic link
- IoDeleteSymbolicLink((DrvGlobalData.DosDevice
Name)) - // delete main device object
- IoDeleteDevice(DrvGlobalData.DeviceObject)
- ExKdPrint(("...GAME OVER!\n"))
25Drv_MJ_xxx vázCREATE, CLEANUP, CLOSE,
DEVICE_CONTROL számára
- NTSTATUS Drv_MJ_xxx(__in PDEVICE_OBJECT
DeviceObject, __in PIRP Irp) -
- NTSTATUS status
- PIO_STACK_LOCATION irpSp
- status STATUS_UNSUCCESSFUL
- irpSp IoGetCurrentIrpStackLocation(Irp)
- __try
- __try
- // ... ide kerul az IRP MJ specifikus
kód - status STATUS_SUCCESS
// csak ha sikeres volt a végrehajtás -
- __except(EXCEPTION_EXECUTE_HANDLER)
- status GetExceptionCode()
- ExKdPrint(("EXCEPTION - d - s -
d\n", status, __FILE__, __LINE__)) -
-
- __finally
26Drv_MJ_xxx kódok 1
- Drv_MJ_CREATE
- // request to open the device?
- if (DeviceObject DrvGlobalData.DeviceObject)
-
- Irp-gtIoStatus.Information FILE_OPENED
- status STATUS_SUCCESS
-
- else
-
- Irp-gtIoStatus.Information
FILE_DOES_NOT_EXIST - status STATUS_OBJECT_NAME_NOT_FOUND
-
- Drv_MJ_CLEANUP
- // signal on FOB that we have done our work
- fileObject irpSp-gtFileObject
- fileObject-gtFlags FO_CLEANUP_COMPLETE
- status STATUS_SUCCESS
27Drv_MJ_xxx kódok 2
- Drv_MJ_CLOSE
- status STATUS_SUCCESS
- Drv_MJ_DEVICE_CONTROL
- ioctlCode irpSp-gtParameters.DeviceIoControl.IoCo
ntrolCode - switch (ioctlCode)
-
- case IOCTL_DRV_SUM_TWO_INTS
-
- status Drv_IOCTL_DRV_SUM_TWO_INTS(Irp,
irpSp) - break
-
- default
-
- ExKdPrint(("unhandled IOCTL 0x08x\n",
ioctlCode)) - status STATUS_INVALID_PARAMETER
-
28Drv_IOCTL_DRV_SUM_TWO_INTS
- NTSTATUS Drv_IOCTL_DRV_SUM_TWO_INTS(__in PIRP
Irp, __in PIO_STACK_LOCATION IrpSp) -
- NTSTATUS status
- PIOCTL_SUM sum
- UNREFERENCED_PARAMETER(IrpSp)
- ExKdPrint(("Drv_IOCTL_DRV_SUM_TWO_INTS\n"))
- status STATUS_UNSUCCESSFUL
- // get user buffer pointer
- sum (PIOCTL_SUM)(Irp-gtAssociatedIrp.SystemBu
ffer) - // calculate sum and set return data length
and status - sum-gtc sum-gta sum-gtb
- Irp-gtIoStatus.Information
sizeof(IOCTL_SUM) - status STATUS_SUCCESS
- return status
29User módbeli vezérlo alkalmazás 1
- define FILE_DEVICE_UNKNOWN
0x00000022 - define METHOD_BUFFERED 0
- define FILE_ANY_ACCESS 0
- define FILE_READ_ACCESS (0x0001) //
file pipe - define FILE_WRITE_ACCESS (0x0002) //
file pipe - define CTL_CODE(DeviceType, Function, Method,
Access) \ - (((DeviceType)ltlt16)((Access)ltlt14)((Function)
ltlt2)(Method)) - define IOCTL_DRV_SUM_TWO_INTS
\ - (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0981,
\ - METHOD_BUFFERED,
FILE_ANY_ACCESS) - typedef struct _IOCTL_SUM // driver
specifikus adat struktúra amely - // segítségével
történik a kommunikáció a - __int32 a // driver és az
alkalmazás között - __int32 b // a kérés és
válasz számára lehet - __int32 c // két különbözo
struktúrát is használni - IOCTL_SUM, PIOCTL_SUM
30User módbeli vezérlo alkalmazás 2
- // global kernel device handle
- HANDLE DevHandle
- ...
- int main(void)
-
- __int32 a,b,c
- DevHandle CreateFile(L"\\\\?\\sumdevice",
0, 0, 0, - OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, 0) - if (DevHandle INVALID_HANDLE_VALUE)
-
- printf("invalid handle, can't open
device\n") - return -1
-
- a 10 b 20
- SumTwoInts(a, b, c)
- printf("d d d\n", a, b, c)
31User módbeli vezérlo alkalmazás 3
- int SumTwoInts(__int32 a, __int32 b, __int32 c)
-
- IOCTL_SUM inout // adatstruktúra,
amelyet a kommunikációra felhasználunk - // ez
mindig azonosan kell legyen deklarálva a driver
és az - inout.a a // alkalmazás
kódjában - inout.b b
- if (DeviceIoControl(DevHandle,
IOCTL_DRV_SUM_TWO_INTS, - inout, sizeof(IOCTL_SUM), inout,
sizeof(IOCTL_SUM), b, NULL)) - // itt
lehet a BE- és KI-menetnek különbozo buffert
megadni - c inout.c
- return 1
-
- else
-
- printf("last error d\n",
GetLastError()) - return 0
-
32Egy I/O kérés végrehajtása
33