程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi研究之驅動開發篇(三)--一個完整的驅動程序示例(上)

Delphi研究之驅動開發篇(三)--一個完整的驅動程序示例(上)

編輯:Delphi

作 者: mickeylan
時 間: 2008-01-14,20:58
鏈 接: http://bbs.pediy.com/showthread.php?t=58301

Delphi研究之驅動開發篇(三)

     (注:本篇的原理部分均摘自羅雲彬大俠翻譯的驅動開發教程)
      在前面的兩篇教程中我們寫了三個玩具驅動程序,為什麼說是玩具驅動呢?因為它們確確實實是驅動程序,而且也能完成一些有趣的功能,但是它們都不完整,沒有同用戶交流的功能,這一篇就讓我們來完成一個簡單的全功能驅動程序。
     在寫程序之前,我們有必要了解一些基礎知識。
在用戶模式下,我們可以通過訪問某個地址來直接調用dll中的函數,但是在內核模式下,從系統的穩定性考慮,這樣做是非常危險的。所以,系統提供了和內核模式通訊的媒介--I/O管理器,它是I/O子系統的部件之一。I/O管理器將應用程序、系統部件和設備連接起來,並定義了一個架構來支持設備驅動程序。
     一般來說,用戶模式的操作都被轉換成了對具體硬件設備的I/O操作,僅對於某些設備,設備由驅動程序來創建和控制,這些設備就是虛擬設備。當然,創建這些設備並不意味著你創造了什麼硬件,而僅僅是在內存中創建了一個新的對象而已。每個對象和一個物理設備或者邏輯設備對應,用於描述它們的特征。
     創建設備後,驅動程序告訴I/O管理器:“這裡有個我控制的設備,如果你收到了操作這個設備的I/O請求的話,直接發給我好了,剩下的由我來搞定!”。驅動程序知道如何對自己管理的設備進行I/O操作,I/O管理器唯一的職責在於創建I/O請求並把它發送給適當的設備驅動程序。用戶模式的代碼不知道(也不必知道)其中的細節,也不用知道究竟是哪個驅動程序在管理哪個設備。
下面先讓我們來看一下用戶模式下的控制程序:
代碼:program VirToPhys;

{$APPTYPE CONSOLE}

uses
    SysUtils, Windows, WinSvc, Dialogs, nt_status;

const
    NUM_DATA_ENTRY =4;
    DATA_SIZE = sizeof(DWORD) * NUM_DATA_ENTRY;
    _Delete = $10000;

var
    hSCManager:THANDLE;
    hService:THANDLE;
    acModulePath: array [0..MAX_PATH] of char;
    _ss:SERVICE_STATUS;
    hDevice:THANDLE;

    adwInBuffer: array [0..NUM_DATA_ENTRY] of DWORD;
    adwOutBuffer: array [0..NUM_DATA_ENTRY] of DWORD;
    dwBytesReturned:DWORD;
    IOCTL_GET_PHYS_ADDRESS: DWORD;
    lpTemp: PChar;
    iRetValue: boolean;

{生成控制碼}    
function CTL_CODE(DeviceType, Func, Method, Access: DWORD): DWORD;
begin
    result := (((DeviceType) SHL 16) or ((Access) SHL 14) or ((Func) SHL 2) or (Method));
end;

begin
    IOCTL_GET_PHYS_ADDRESS := CTL_CODE(FILE_DEVICE_UNKNOWN,
                              $800, METHOD_BUFFERED,
                              FILE_READ_ACCESS + FILE_WRITE_ACCESS);
    hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
    if hSCManager <> 0 then
    begin
      GetFullPathName(PChar(VirtToPhys.sys), sizeof(acModulePath), acModulePath, lpTemp);
      hService := CreateService(hSCManager, VirtToPhys, Virtual To Physical Address Converter,
                                SERVICE_START + SERVICE_STOP + _Delete, SERVICE_KERNEL_DRIVER,
                                SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, acModulePath,
                                nil, nil, nil, nil, nil);
      if hService <> 0 then
      begin
        {驅動程序的DriverEntry過程將被調用}
        if StartService(hService, 0, lpTemp) = true then
        begin
          {驅動程序將接收IRP_MJ_Create I/O請求包(IRP)}
          hDevice := CreateFile(\.slVirtToPhys, GENERIC_READ+GENERIC_WRITE,
                                0, nil, OPEN_EXISTING, 0, 0);
          if hDevice <> INVALID_HANDLE_VALUE    then
          begin
            {准備送往驅動程序的數據包}
            adwInBuffer[0] := GetModuleHandle(nil);
            adwInBuffer[1] := GetModuleHandle(kernel32.dll);
            adwInBuffer[2] := GetModuleHandle(user32.dll);

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved