#tutorials.de RSS-Feed tutorials.de - CMS RSS-Feed tutorials.de - User helfen Usern __________________________________________________________________ * Startseite + PHP + Java + C/C++ + .NET + Datenbanken & XML + Sonstige Sprachen + tutorials.de Redaktion * Forum * Bild, 3D, Video & Audio * Webmaster & Internet * Programming * Computer & Devices ____________________ [search.png]-Submit * Suche * Startseite * Startseite * Programming * C/C++ * [Driver] v0.2 -Windows [7] - IOCTL __________________________________________________________________ * * [Driver] v0.2 -Windows [7] - IOCTL von 3Cyb3r Artikel bewerten + (*) Hervorragend + ( ) Gut + ( ) Durchschnittlich + ( ) Schlecht + ( ) Schrecklich + Jetzt abstimmen Veröffentlicht: 27.10.11 19:07 Seitenaufrufe: 3899 0 Kommentare Kommentare Tutorial 1 Tutorial 2 || Einführung in die Gerätetreiberprogrammierung unter Windows von Niklas Bartz Es geht um die Kommunikation eines Treibers mit einem User-Programm. Willkomen zum zweiten Treiber Tutorial. Diesmal werden wir die Kommunikation zwischen einem Treiber und einem Programm im User-Mode behandeln. Um mit einem anderen Programm zu kommunizieren muss ein Treiber I/O Request Packets (IRP) benutzen. Dies ist eine einfach Datenstruktur, welche Puffer mit Daten enthält. Das ganze funktioniert, wie sollte es auch anders sein unter Windows, mit Datei-Handles. Wenn also nun ein User-Programm ein String in das Datei-Handle des Treibers schreibt, dann wird vom Kernel ein IRP erzeugt, welches diesen String enthält. Um nun IRPs verarbeiten zu können muss unser Kerneltreiber eine Funktion zur verarbeitung bereitstellen. Dies funktioniert genau so wie mit der Endladeroutine. Es wird einfach der zugehörige Funktionszeiger gesetzt. Alle Hauptfunktionen sind in einem Array namens MajorFunction gespeichert. Es sind Werte definiert wodurch man die Funktionen setzten kann. Code c: 1 2 3 4 5 theDriverObject->MajorFunction[IRP_MJ_CREATE] = CreateProcessing; theDriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseProcessing; theDriverObject->MajorFunction[IRP_MJ_READ] = ReadProcessing; theDriverObject->MajorFunction[IRP_MJ_WRITE] = WriteProcessing; theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoControl; Die einzelnen Funktionen werden durch folgenden Methoden der Windows-API aufgerufen: Code c: 1 2 3 4 5 CreateFile() CloseHandle() ReadFile() WriteFile() DeviceIoControl() Diese Funktionen könnte man nun alle ausformulieren Code c: 1 2 3 4 5 6 7 8 NTSTATUS CreateProcessing( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { // Mache irgendetwas //... return STATUS_SUCCESS; } // u.s.w. //... Abbildung 1: Ein Kerneltreiber kann für jede Hauptfunktion eine eigene Callbackfuntkion definieren Man sollte sich im klaren seien, dass man ohne ein Request von dem User-Mode-Programm nichts vom Treiber senden kann oder habt ihr schonmal eine Nachricht von einer Datei empfangen? Also jede Kommunikation erfolgt vom User-Programm aus. Wenn man nun dafür sorgen möchte, dass der Treiber einem immer etwas senden kann, dann muss man immer genügend Request bereitstellen, bevor diese verbraucht sind. Man sendet also ein Request an den Treiber welches dieses erst verwendet, wenn er Daten zu übermitteln hat. Dann reagiert er auf das Request und sendet etwas an das Programm zurück. Um nun von einem Programm im User-Mode aus einen Treiber zu verwenden, muss dieses Programm ein Handle zum Treiber öffen. Dies geht jedoch nur, wenn der Treiber zuvor ein Gerät registriert hat. Danach kann man mit dem User-Programm das Gerät öffnen und darauf zugreifen, als sei es eine Datei. So ähnlich ist es in der Regel auch bei UNIX-Systemen. So wollen wir mal mit unserem Kerneltreiber ein Gerät registrieren: Code c: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #define FILE_DEVICE_TESTDEVICE 0x00008001 const WCHAR deviceNameBuffer[] = L"\\Device\\vicesys"; const WCHAR symbolicLinkNameBuffer[] = L"\\DosDevices\\vicesys"; PDEVICE_OBJECT g_testDevice; // global pointer on the driverdevice NTSTATUS DriverEntry (IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING theRegi stryPath) { NTSTATUS ntStatus; UNICODE_STRING deviceNameUni; UNICODE_STRING symbolicLinkNameUni; // name and symbolic link init. RtlInitUnicodeString( &deviceNameUni, deviceNameBuffer ); RtlInitUnicodeString( &symbolicLinkNameUni, symbolicLinkNameBuffer ); // device init ntStatus = IoCreateDevice ( DriverObject, 0, // device extension &deviceNameUni, FILE_DEVICE_TESTDEVICE, 0, TRUE, &g_TestDevice ); if(NT_SUCCESS(ntStatus)) { DbgPrint("IoDevice built"); ntStatus = IoCreateSymbolicLink( &symbolicLinkNameUni, &deviceNameUni ); if (NT_SUCCESS(ntStatus)) { DbgPrint("Symbolic Link created"); } else { DbgPrint("Symbolic link creation failed"); } } else { DbgPrint("Cant't create a IoDevice"); } /* ... */ Wem es entfallen ist: Durch das Präfix L wird ein String als Unicode definiert. Durch IoCreateDevice() wird ein Gerät registriert und von da an kann man im User-Programm auf den Treiber zugreifen. Da wir jedoch ein Stück kompfortabler auf den Treiber zugreifen wollen erstellen wir noch einen Symbolische-Link. Da wir einen sybolischen Link erstellt haben, kann ein User-Programm ein Handle für die Datei über den String \\.\vicesys öffnen: Code c: 1 2 3 4 5 6 7 8 9 10 11 12 13 hDevice = CreateFile("\\\\.\\vicesys", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDevice == ((HANDLE)-1)) { cout<<"Device Handle konnte nicht erstellt werden"<IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); } /* _____________________________________________________________________________ . CreateProcessing is called, if the user-mode programm calls create file. . . HANDLE WINAPI CreateFile( . __in LPCTSTR lpFileName, . __in DWORD dwDesiredAccess, . __in DWORD dwShareMode, . __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, . __in DWORD dwCreationDisposition, . __in DWORD dwFlagsAndAttributes, . __in_opt HANDLE hTemplateFile . ); . _____________________________________________________________________________ */ NTSTATUS CreateProcessing (IN PDEVICE_OBJECT deviceObject, IN PIRP irp) { OnDispatchRoutine(irp); DbgPrint("CreateProcessing called\n"); return STATUS_SUCCESS; } /* _____________________________________________________________________________ . CloseProcessing is called, if the user-mode programm calls close handle. . . BOOL WINAPI CloseHandle( . __in HANDLE hObject . ); . _____________________________________________________________________________ */ NTSTATUS CloseProcessing (IN PDEVICE_OBJECT deviceObject, IN PIRP irp) { OnDispatchRoutine(irp); DbgPrint("CloseProcessing called\n"); return STATUS_SUCCESS; } /* _____________________________________________________________________________ . IoControl is called, if the user-mode programm calls device io control. . . BOOL WINAPI DeviceIoControl( . __in HANDLE hDevice, . __in DWORD dwIoControlCode, . __in_opt LPVOID lpInBuffer, . __in DWORD nInBufferSize, . __out_opt LPVOID lpOutBuffer, . __in DWORD nOutBufferSize, . __out_opt LPDWORD lpBytesReturned, . __inout_opt LPOVERLAPPED lpOverlapped . ); . _____________________________________________________________________________ */ NTSTATUS IoControl (IN PDEVICE_OBJECT deviceObject, IN PIRP irp) { PIO_STACK_LOCATION irpSp; ULONG functionCode; HANDLE hEvent; OBJECT_HANDLE_INFORMATION objHandleInfo; LONG* outBuffer; NTSTATUS status = STATUS_SUCCESS; irpSp = IoGetCurrentIrpStackLocation(irp); functionCode = irpSp->Parameters.DeviceIoControl.IoControlCode; switch (functionCode) { case IO_REFERENCE_EVENT: hEvent = (HANDLE) irpSp->Parameters.DeviceIoControl.Type3InputBuffer; status = ObReferenceObjectByHandle( hEvent, GENERIC_ALL, NULL, KernelMode, &g_pEventObject, &objHandleInfo); if(status != STATUS_SUCCESS) { DbgPrint("ObReferenceObjectByHandle failed! ERROR: %x\n", status); break; } DbgPrint("ReferenceObject complete\n"); break; case IO_DEREFERENCE_EVENT: if(g_pEventObject) { ObDereferenceObject(g_pEventObject); } DbgPrint("DereferenceObject complete\n"); break; case IO_SET_EVENT: KeSetEvent(g_pEventObject, 0, FALSE); DbgPrint("KeSetEvent complete\n"); break; case IO_CLEAR_EVENT: KeClearEvent(g_pEventObject); DbgPrint("KeClearEvent complete\n"); break; case IO_QUERY_EVENT_STATE: outBuffer = (LONG*) irp->UserBuffer; *outBuffer = KeReadStateEvent(g_pEventObject); DbgPrint("KeReadStateEvent complete\n"); irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = sizeof(LONG); IoCompleteRequest(irp, IO_NO_INCREMENT); return status; default: break; } OnDispatchRoutine(irp); DbgPrint("IoControl called\n"); return STATUS_SUCCESS; } /* _____________________________________________________________________________ . OnUnload is called, if the driver is unloading . free all used memorie . _____________________________________________________________________________ */ VOID OnUnload (IN PDRIVER_OBJECT driverObject) { UNICODE_STRING symbolicLinkName; RtlInitUnicodeString( &symbolicLinkName, symbolicLinkNameBuffer ); IoDeleteSymbolicLink(&symbolicLinkName); IoDeleteDevice(g_testDevice); DbgPrint("Driver unloaded\n"); } NTSTATUS DriverEntry (IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING theRegi stryPath) { NTSTATUS ntStatus; UNICODE_STRING deviceNameUni; UNICODE_STRING symbolicLinkNameUni; // name and symbolic link init. RtlInitUnicodeString( &deviceNameUni, deviceNameBuffer ); RtlInitUnicodeString( &symbolicLinkNameUni, symbolicLinkNameBuffer ); // device init ntStatus = IoCreateDevice ( driverObject, sizeof(DEVICE_EXT), // d evice extension &deviceNameUni, FILE_DEVICE_TESTDEVICE, 0, TRUE, &g_testDevice ); if(NT_SUCCESS(ntStatus)) { DbgPrint("IoDevice built"); ntStatus = IoCreateSymbolicLink( &symbolicLinkNameUni, &deviceNameUni ); if (NT_SUCCESS(ntStatus)) { DbgPrint("Symbolic Link created"); } else { DbgPrint("Symbolic link creation failed"); } } else { DbgPrint("Cant't create a IoDevice"); } // set the pointer for the unload function // in our driver object driverObject->DriverUnload = OnUnload; // IOCTL init. driverObject->MajorFunction[IRP_MJ_CREATE] = CreateProcessing; driverObject->MajorFunction[IRP_MJ_CLOSE] = CloseProcessing; driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoControl; DbgPrint("Driver loaded!\n"); return STATUS_SUCCESS; } Testanwendung User_Programm.cpp Code cpp: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 #include #include #include "IOAccess.h" using namespace std; int main(int argc, char* argv[]) { IOAccess *pIO = NULL; int eingabe = 99; cout<<"________ Menu ________\n"<> eingabe; switch(eingabe) { case 1: cout<<"OPEN DEVICE"<queryEvent(); } break; case 4: cout<<"SET EVENT"<setEvent(); } break; case 5: cout<<"CLEAR EVENT"<clearEvent(); } break; default: break; } } return 0; } IoAccess.h Code cpp: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #ifndef __IO_ACCESS_H__ #define __IO_ACCESS_H__ #include class IOAccess { private: HANDLE hDevice; HANDLE hEvent; DWORD dwBytesReturned; public: IOAccess(); ~IOAccess(); bool openDriver(); void closeDriver(); void queryEvent(); void clearEvent(); void setEvent(); }; #endif // #ifndef __IO_ACCESS_H__ IoAccess.cpp Code cpp: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 #include "IOAccess.h" #include #include #include "..\inc\IOCTL.h" IOAccess::IOAccess() { hDevice = NULL; hEvent = NULL; openDriver(); } IOAccess::~IOAccess() { closeDriver(); } bool IOAccess::openDriver() { hDevice = CreateFile("\\\\.\\vicesys", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hDevice) { printf("Device Handle konnte nicht erstellt werden\n"); return FALSE; } printf("Device Handle erstellt\n"); hEvent = CreateEvent(NULL, false, false, NULL); //download event object to device driver DeviceIoControl(hDevice, IO_REFERENCE_EVENT, (LPVOID) hEvent, 0, NULL, 0, &dwBytesReturned, NULL); return TRUE; } void IOAccess::closeDriver() { if(hDevice) { if(hEvent) { DeviceIoControl(hDevice, IO_DEREFERENCE_EVENT, NULL,0, NULL,0, &dwBytesReturned, NULL); CloseHandle(hEvent); } CloseHandle(hDevice); } printf("Device Handle geschlossen\n"); } void IOAccess::queryEvent() { ULONG dwState; if(hEvent) { DeviceIoControl(hDevice, IO_QUERY_EVENT_STATE, NULL, 0, (LPVOID) &dwState, sizeof(dwState), &dwBytesReturned, NULL); if(dwState) { printf("Event signaled state\n"); } else { printf("Event not signaled state\n"); } } } void IOAccess::clearEvent() { if(hEvent) { DeviceIoControl(hDevice, IO_CLEAR_EVENT, NULL, 0, NULL, 0, &dwBytesReturned, NULL); } } void IOAccess::setEvent() { if(hEvent) { DeviceIoControl(hDevice, IO_SET_EVENT, NULL, 0, NULL, 0, &dwBytesReturned, NULL); } } Ok was ist noch zu erwähnen. Vielleicht folgendes: g_pEventObject ist ein PRKEVENT Objekt, damit kann man KeEvent... undKeWaitFor... benutzen. Code c: 1 2 3 //User-Mode WaitForSingleObject(hEvent, INFINITE); // Nach dieser Funktion ist das Event auf "not signaled" gesetzt. Den folgenden Code benutzen, wenn das Objekt Event eingetreten ist: Code c: 1 2 // Dirver KeSetEvent(g_pEventObject, 0, FALSE); So das wars auch schon wieder ich hoffe es hat gefallen und bis zum nächsten mal. Es wird schon bald weiter gehen und dort werde ich zeigen wie man mit einem User-Programm seinen eigenen Treiber läd und wieder entläd. MFG Cyb3r Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken content/attachments/58610-kerneltreiber-callback-funktionen.jpg.htm l Angehängte Dateien Angehängte Dateien + [Driver] v0.2 -Windows [7] - IOCTL.rar (3,21 MB, 196x aufgerufen) ______________________________________________________________ 1. Kategorien: 2. Tutorials, 3. Programming-Tutorials, 4. C/C++ Lowlevel Stichworte : ddk, driver, treiber, wdk, windows * Login Benutzerna Kennwort__ __________ [X] Angemeldet bleiben? Anmelden Kostenlos registrieren Bereiche * Tutorials * Bild, 3D, Video & Audio + Bildbearbeitung + Fotografie + 3D-Grafik + Video + Audio + Vektorgrafik + Typografie & DTP + Inspiration * Webmaster & Internet + Web-News + CMS + Web-Entwicklung * Programming + PHP + Java + C/C++ + .NET + Datenbanken & XML + Sonstige Sprachen * Computer & Devices + Betriebssysteme + Server + Software + Hardware * Buch-Empfehlungen Tutorials Bild, 3D, Video & Audio Bildbearbeitung Fotografie 3D-Grafik Video Audio Vektorgrafik Typografie & DTP Inspiration Webmaster & Internet Web-News CMS Web-Entwicklung Programming PHP Java C/C++ .NET Datenbanken & XML Sonstige Sprachen Computer & Devices Betriebssysteme Server Software Hardware Buch-Empfehlungen Kategorien Boost (0) C++ Grundlagen (16) C/C++ Algorithmen (3) C/C++ Lowlevel (9) C/C++ Sonstiges (15) DirectX & OpenGL (5) Events & Contests (38) Programming-News (10) Programming-Tutorials (346) Qt (1) Tutorials (805) tutorials.de intern (69) Videotutorials (214) Visual Studio & MFC (2) Werkzeuge / IDEs (24) Forum - Programming AW: 2 Variablen nach 1 sortieren PHP-Code: array(15) { [0]=> array(4) { ["name"]=> string(8) "Facebook" ["number"] => int(85364233) ["talking"]=> TheSchmidey 23.01.13, 17:22 Gehe zum letzten Beitrag AW: Uhrzeit differenz ausrechnen Ist ok jetzt funktioniert es ja. Computerfreak90 23.01.13, 17:16 Gehe zum letzten Beitrag AW: Erweiterte Statistiken Hm.. du hast mich da auf ein paar gute Ideen gebracht. Die frage, welche Seite wurde genau wie oft vor 6 Monaten aufgerufen ist sehr uninteressant. String 23.01.13, 16:50 Gehe zum letzten Beitrag VBA: Werte "flexibel" aus Mappe 1 nach Mappe 2 kopiren ... ... ohne Mappe 1 zu öffnen Hallo, bei nachfolgendem Code hänge ich schon den ganzen Tag fest. Der Code stammt nicht _opiWahn_ 23.01.13, 16:38 Gehe zum letzten Beitrag AW: 2 Variablen nach 1 sortieren mach mal ein var_dump() vor dem Funktionsaufruf auf $myVars und poste das Resultat hier. Yaslaw 23.01.13, 15:44 Gehe zum letzten Beitrag Newsletter @ tutorials.de Sobald es etwas Interessantes - wie z.B. unsere beliebten Buch-Verschenkaktionen - gibt, erhältst du unseren regelmäßig erscheinenden Newsletter. Natürlich kostenlos und jederzeit abbestellbar! E-Mail: email@adresse.xy_______ Los (*) Abonnieren ( ) Abbestellen * Kontakt * tutorials.de - User helfen Usern * Nach oben Powered by vBulletin® Version 4.2.0 (Deutsch) - Copyright ©2013 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten. SEO by vBSEO 3.6.0 ©2011, Crawlability, Inc. tut orials.de tut informieren tut dir helfen tut kooperieren ©2000-2013 tutorials.de Alle Rechte vorbehalten tutorials.de @ Twitter tutorials.de @ Facebook tutorials.de @ Youtube * » Impressum * » Nutzungsregeln * » Netiquette * » Team * » Redaktion * » Tutorials * » Videotutorials * » Showroom * » Events & Contests * » Chat * » RSS-Feed * » der-webdesigner.net * » DesignerInAction * » Design Nation * » Directorforum * » Flashhilfe * » PHP-Resource * » PHPwelt * » PSD-Tutorials * » Terrashop