当前位置:编程学习 > Delphi >>

Delphi研究之驱动开发篇(三)--一个完整的驱动程序示例(下)

以上就是用户模式下的控制程序了,下面来看看我们的驱动程序。

代码:unit VirtToPhys;

interface

uses
    nt_status, ntoskrnl, ntutils;

function _DriverEntry(pDriverObject:PDRIVER_OBJECT; pusRegistryPath:PUNICODE_STRING): NTSTATUS; stdcall;

implementation

const
    NUM_DATA_ENTRY = 4;
    DATA_SIZE = sizeof(DWORD) * NUM_DATA_ENTRY;

var
    g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING;

function DispatchCreateClose(p_DeviceObject:PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall;
begin
    p_Irp^.IoStatus.Status := STATUS_SUCCESS;
    p_Irp^.IoStatus.Information := 0;

    IofCompleteRequest(p_Irp, IO_NO_INCREMENT);
    result := STATUS_SUCCESS;
end;

function DispatchControl(p_DeviceObject: PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall;
var
    status:NTSTATUS;
    dwBytesReturned:DWORD;
    psl:PIO_STACK_LOCATION;
    IOCTL_GET_PHYS_ADDRESS: DWORD;
    pSystemBuffer: PULONG;
    iCnt: DWORD;
    liPhysicalAddress: PHYSICAL_ADDRESS;
begin
    dwBytesReturned := 0;

    IOCTL_GET_PHYS_ADDRESS := CTL_CODE(FILE_DEVICE_UNKNOWN,
      $800, METHOD_BUFFERED, FILE_READ_ACCESS + FILE_WRITE_ACCESS);

    psl := IoGetCurrentIrpStackLocation(p_Irp);

    if psl^.Parameters.DeviceIoControl.IoControlCode = IOCTL_GET_PHYS_ADDRESS then
    begin
      if (psl^.Parameters.DeviceIoControl.OutputBufferLength >= DATA_SIZE)
         and (psl^.Parameters.DeviceIoControl.InputBufferLength >= DATA_SIZE) then
      begin
        pSystemBuffer := p_Irp^.AssociatedIrp.SystemBuffer;
        iCnt := 0;
        for iCnt := 1 to NUM_DATA_ENTRY do
        begin
          liPhysicalAddress := MmGetPhysicalAddress(PVOID(pSystemBuffer^));
          pSystemBuffer^ := liPhysicalAddress.LowPart;
          inc(pSystemBuffer);
        end;
        dwBytesReturned := DATA_SIZE;
        status := STATUS_SUCCESS;
      end else
      begin
        status := STATUS_BUFFER_TOO_SMALL;
      end;
    end else
    begin
      status := STATUS_INVALID_DEVICE_REQUEST;
    end;
    
    p_Irp^.IoStatus.Status := status;
    p_Irp^.IoStatus.Information := dwBytesReturned;

    IofCompleteRequest(p_Irp, IO_NO_INCREMENT);
    result := status;
end;

procedure DriverUnload(p_DriverObject:PDRIVER_OBJECT); stdcall;
begin
    IoDeleteSymbolicLink(@g_usSymbolicLinkName);
    IoDeleteDevice(p_DriverObject^.DeviceObject);
end;

function _DriverEntry(pDriverObject:PDRIVER_OBJECT; pusRegistryPath:PUNICODE_STRING): NTSTATUS;
var
    status:NTSTATUS;
    pDeviceObject:TDeviceObject;
begin
    status := STATUS_DEVICE_CONFIGURATION_ERROR;
    RtlInitUnicodeString(g_usDeviceName, DevicedevVirtToPhys);
    RtlInitUnicodeString(g_usSymbolicLinkName, ??slVirtToPhys);

    if (IoCreateDevice(pDriverObject, 0, @g_usDeviceName,
                       FILE_DEVICE_UNKNOWN, 0, FALSE,
                       pDeviceObject) = STATUS_SUCCESS) then
    begin
      if (IoCreateSymbolicLink(@g_usSymbolicLinkName,
                               @g_usDeviceName) = STATUS_SUCCESS) then
      begin
        pDriverObject^.MajorFunction[IRP_MJ_Create] := @DispatchCreateClose;
        pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @DispatchCreateClose;
        pDriverObject^.MajorFunction[IRP_MJ_DEVICE_CONTROL] := @DispatchControl;
        pDriverObject^.DriverUnload := @DriverUnload;

        status := STATUS_SUCCESS;
      end else
      begin
        IoDeleteDevice(@pDeviceObject);
      end;
    end;
    result := status;
end;

end.
   程序很简单,所以一行注释也没加^_^。既然驱动程序的主要作用是用于控制一些设备,包括物理设备、虚拟设备或者逻辑设备,那么我们首先必须将这些设备创建起来(本例中是虚拟设备),这可以通过调用IoCreateDevice函数来完成,函数将创建并初始化一个由驱动程序使用的设备对象(DEVICE_OBJECT结构),其原型如下:
   代码:function IoCreateDevice(DriverObject: PDRIVER_OBJECT;
                          DeviceExtensionSize: ULONG;
                          DeviceName: PUNICODE_STRING;
                          DeviceType: DEVICE_TYPE;
                          DeviceCharacteristics: ULONG;
                          Exclusive: 
补充:软件开发 , Delphi ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,