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 ,