当前位置:编程学习 > 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);
补充:软件开发 , Delphi ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,