使用WDM驱动实现在NT下读取物理端口,特殊寄存器,物理内存的代码(Win32汇编源代码)

时间:2022-08-01 01:00:49
在WinNT下Ring3级应用程序不能直接访问硬件I/O和物理内存,需要调用驱动在Ring0下间接访问。本代码在MASM10 + KmdKit v1.8下编译通过。
comment *
  libmio.asm -- Using driver to implement hardware access for Windows.
                allows the ring3 applications to access I/O port,MSR,PMC,PCI bus,Physical memory.
  2011/08/15 Perry<ppsoft268@gmail.com>
*


.586
.model flat, stdcall
 option casemap :none
KmdKit头文件。
include                   w2k\ntddk.inc
include                   w2k\ntstatus.inc
include                   w2k\ntoskrnl.inc
include                   w2k\hal.inc
include                   Strings.mac
KmdKit库文件。
includelib                \masm32\lib\w2k\ntoskrnl.lib
includelib                \masm32\lib\w2k\hal.lib
驱动入口函数声明。
DriverEntry               PROTO :PDRIVER_OBJECT,:PUNICODE_STRING
驱动I/O例程调用函数声明。
OnUnrealized              PROTO :PDEVICE_OBJECT,:PIRP
OnIoControl               PROTO :PDEVICE_OBJECT,:PIRP
OnCreate                  PROTO :PDEVICE_OBJECT,:PIRP
OnClose                   PROTO :PDEVICE_OBJECT,:PIRP
OnUnload                  PROTO :PDRIVER_OBJECT
物理内存读写函数声明。
MmMapPhysical             PROTO :DWORD,:DWORD,:DWORD
MmUnmapPhysical           PROTO :DWORD
本驱动版本常数。
LIBMIO_MAJOR_VERSION      equ 1h
LIBMIO_MINOR_VERSION      equ 0h
LIBMIO_REVISION           equ 0h
LIBMIO_RELESE             equ 2h
内核内存分配标记。
MM_ALLOC_POOL_TAG         equ 6d62696ch
接受DeviceIoControl的常量定义。
IOCTL_GET_DRIVER_REFCOUNT equ CTL_CODE(FILE_DEVICE_UNKNOWN, 8FFh, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_GET_DRIVER_VERSION  equ CTL_CODE(FILE_DEVICE_UNKNOWN, 900h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_READ_MSR            equ CTL_CODE(FILE_DEVICE_UNKNOWN, 901h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_WRITE_MSR           equ CTL_CODE(FILE_DEVICE_UNKNOWN, 902h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_READ_PMC            equ CTL_CODE(FILE_DEVICE_UNKNOWN, 903h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_HALT                equ CTL_CODE(FILE_DEVICE_UNKNOWN, 904h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_READ_PORT           equ CTL_CODE(FILE_DEVICE_UNKNOWN, 905h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_READ_PORT_BYTE      equ CTL_CODE(FILE_DEVICE_UNKNOWN, 906h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_READ_PORT_WORD      equ CTL_CODE(FILE_DEVICE_UNKNOWN, 907h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_READ_PORT_DWORD     equ CTL_CODE(FILE_DEVICE_UNKNOWN, 908h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_WRITE_PORT          equ CTL_CODE(FILE_DEVICE_UNKNOWN, 909h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_WRITE_PORT_BYTE     equ CTL_CODE(FILE_DEVICE_UNKNOWN, 90Ah, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_WRITE_PORT_WORD     equ CTL_CODE(FILE_DEVICE_UNKNOWN, 90Bh, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_WRITE_PORT_DWORD    equ CTL_CODE(FILE_DEVICE_UNKNOWN, 90Ch, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_PCI_READ_CONFIG     equ CTL_CODE(FILE_DEVICE_UNKNOWN, 90Dh, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_PCI_WRITE_CONFIG    equ CTL_CODE(FILE_DEVICE_UNKNOWN, 90Eh, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_MAP_PHY_MEMORY      equ CTL_CODE(FILE_DEVICE_UNKNOWN, 90Fh, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_UNMAP_PHY_MEMORY    equ CTL_CODE(FILE_DEVICE_UNKNOWN, 910h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_READ_PHY_MEMORY     equ CTL_CODE(FILE_DEVICE_UNKNOWN, 911h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_WRITE_PHY_MEMORY    equ CTL_CODE(FILE_DEVICE_UNKNOWN, 912h, METHOD_BUFFERED, FILE_ANY_ACCESS)
物理内存分配信息结构定义。
_MAP_NODE struct
       node   SINGLE_LIST_ENTRY <?>
        pid   dd ?
       pMdl   dd ?
     ppAddr   dd ?
     pvKenl   dd ?
     pvUser   dd ?
     cbSize   dd ?
_MAP_NODE ends

MAP_NODE typedef _MAP_NODE
PMAP_NODE typedef PTR _MAP_NODE
Windows驱动符号定义。
.const
CCOUNTED_UNICODE_STRING   "\\Device\\libmio", uzWinDeviceName, 4
CCOUNTED_UNICODE_STRING   "\\DosDevices\\libmio", uzDosDeviceName, 4

.data?
MapList                   SINGLE_LIST_ENTRY <?>

.data
dwLibmioVersion           db LIBMIO_RELESE
                          db LIBMIO_REVISION
                          db LIBMIO_MINOR_VERSION
                          db LIBMIO_MAJOR_VERSION
dwRefCount                dd 0
mmnode                    MAP_NODE <<?>,0,0,0,0,0,0>
入口函数。
.code

  ; This function is called by the system.
  ; initialize some resource and create a new device object.
  ; Arguments:
  ;   DriverObject - Pointer to the object that represents our driver.
  ;   RegistryPath - Pointer to the unicode string for the registry path of driver.
  ; Return Value:
  ;   STATUS_SUCCESS if the driver initialized correctly, otherwise an erroror
  ;   indicating the reason for failure.
  DriverEntry proc DriverObject:PDRIVER_OBJECT, RegistryPath:PUNICODE_STRING
    LOCAL pDeviceObject :PDEVICE_OBJECT
    LOCAL ntStatus :NTSTATUS
    
      INVOKE    DbgPrint, $CTA0("DriverEntry: Enter...\n")
      
      ; protect register
      pushad
      
         lea    esi, MapList
      assume    esi: PSINGLE_LIST_ENTRY
         mov    [esi].Next, NULL
      assume    esi: nothing
      
         mov    esi, DriverObject
      assume    esi: PDRIVER_OBJECT
         
         mov    pDeviceObject, NULL
      
      ; create a new DeviceObject
      INVOKE    IoCreateDevice, esi, 0h, addr uzWinDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, 0, addr pDeviceObject
         mov    ntStatus, eax
      INVOKE    DbgPrint, $CTA0("DriverEntry: IoCreateDevice(%08X)\n"), ntStatus
         cmp    ntStatus, STATUS_SUCCESS
         jnz    @F

         mov    [esi].MajorFunction[(sizeof PVOID) * IRP_MJ_CLOSE], offset OnClose
         mov    [esi].MajorFunction[(sizeof PVOID) * IRP_MJ_CREATE], offset OnCreate
         mov    [esi].MajorFunction[(sizeof PVOID) * IRP_MJ_DEVICE_CONTROL], offset OnIoControl
         
         mov    eax, offset OnUnrealized
         mov    [esi].MajorFunction[(sizeof PVOID) * IRP_MJ_INTERNAL_DEVICE_CONTROL], eax
         mov    [esi].MajorFunction[(sizeof PVOID) * IRP_MJ_SYSTEM_CONTROL], eax
         mov    [esi].MajorFunction[(sizeof PVOID) * IRP_MJ_POWER], eax
         mov    [esi].MajorFunction[(sizeof PVOID) * IRP_MJ_PNP], eax
          
         mov    [esi].DriverUnload, offset OnUnload
         
      ; link the pDeviceObject
      INVOKE    IoCreateSymbolicLink, addr uzDosDeviceName, addr uzWinDeviceName
         mov    ntStatus, eax
      INVOKE    DbgPrint, $CTA0("DriverEntry: IoCreateSymbolicLink(%08X)\n"), ntStatus
         cmp    ntStatus, STATUS_SUCCESS
          jz    @F
          
      ; if the IoCreateSymbolicLink was have not succeed.
      ; We need to delete the pDeviceObject for created by IoCreateDevice.
      INVOKE    IoDeleteDevice, pDeviceObject
      INVOKE    DbgPrint, $CTA0("DriverEntry: IoDeleteDevice()\n")

         @@:      
      assume    esi: nothing
       popad
         
      INVOKE    DbgPrint, $CTA0("DriverEntry: Leave...\n\n")
         mov    eax, ntStatus
         ret
  DriverEntry endp
未处理的例程。
  ; other IRP.
  ; Arguments:
  ;   DeviceObject - Pointer to device object.
  ;   pIrp - Pointer to the current IRP.
  ; Return Value:
  ;   STATUS_SUCCESS if the IRP was processed successfully, otherwise an erroror
  ;   indicating the reason for failure.
  OnUnrealized proc uses esi pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
      INVOKE    DbgPrint, $CTA0("OnUnrealized: Enter...\n")
         
        push    esi
         mov    esi, pIrp
      assume    esi :PIRP
         
         mov    [esi].IoStatus.Status, STATUS_SUCCESS
         mov    [esi].IoStatus.Information, 0h
         
      assume    esi :nothing
         pop    esi

    fastcall    IofCompleteRequest, pIrp, IO_NO_INCREMENT
      INVOKE    DbgPrint, $CTA0("OnUnrealized: IoCompleteRequest()\n") 
      
      INVOKE    DbgPrint, $CTA0("OnUnrealized: Leave...\n\n")
         mov    eax, STATUS_SUCCESS
         ret
  OnUnrealized endp
处理应用程式发送的DeviceIoControl例程。
  ; IRP_MJ_DEVICE_CONTROL.
  ; Arguments:
  ;   DeviceObject - Pointer to device object.
  ;   pIrp - Pointer to the current IRP.
  ; Return Value:
  ;   STATUS_SUCCESS if the IRP was processed successfully, otherwise an erroror
  ;   indicating the reason for failure.
  OnIoControl proc uses esi edi ebx pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
    LOCAL ntStatus :NTSTATUS
           
      INVOKE    DbgPrint, $CTA0("OnIoControl: Enter...\n")
         mov    ntStatus, STATUS_INVALID_DEVICE_REQUEST
         
         mov    esi, pIrp
      assume    esi :PIRP
         
         mov    [esi].IoStatus.Information, 0h
         
                IoGetCurrentIrpStackLocation esi               
         mov    edi, eax
      assume    edi :PIO_STACK_LOCATION
获取驱动被调用的实例数量,使驱动能被多个Ring3应用程序调用。
    .if [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DRIVER_REFCOUNT
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_GET_DRIVER_REFCOUNT\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 4h
          jb    @F
         mov    eax, [esi].AssociatedIrp.SystemBuffer
         mov    ecx, dwRefCount
         mov    [eax], ecx
         mov    [esi].IoStatus.Information, 4h
         mov    ntStatus, STATUS_SUCCESS
         @@:
获取驱动内部版本号。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DRIVER_VERSION
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_GET_DRIVER_VERSION\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 4h
          jb    @F
         mov    eax, [esi].AssociatedIrp.SystemBuffer
         lea    ebx, dwLibmioVersion
         mov    ecx, [ebx]
         mov    [eax], ecx
         mov    [esi].IoStatus.Information, 4h
         mov    ntStatus, STATUS_SUCCESS
         @@:
读取MSR寄存器。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_READ_MSR
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_READ_MSR\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 4h
          jb    @F
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 8h
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    ecx, [ebx]
       rdmsr
         mov    [ebx], eax
         mov    [ebx + 4h], edx
         mov    [esi].IoStatus.Information, 8h
         mov    ntStatus, STATUS_SUCCESS
         @@:
写MSR寄存器。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_WRITE_MSR
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_WRITE_MSR\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 0Ch
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    ecx, [ebx]
         mov    eax, [ebx + 4h]
         mov    edx, [ebx + 8h]
       wrmsr
         mov    ntStatus, STATUS_SUCCESS
         @@:
读取PMC信息。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_READ_PMC
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_READ_PMC\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 4h
          jb    @F
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 8h
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    ecx, [ebx]
       rdpmc
         mov    [ebx], eax
         mov    [ebx + 4h], edx
         mov    [esi].IoStatus.Information, 8h
         mov    ntStatus, STATUS_SUCCESS
         @@:
调用Halt特权指令。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_HALT
         hlt
         mov    ntStatus, STATUS_SUCCESS
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_READ_PORT
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_READ_PORT\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 2h
          jb    @F
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 0h
          jz    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    dx, [ebx]
         cli
      .if [edi].Parameters.DeviceIoControl.OutputBufferLength >= 4h
          in    eax, dx
         mov    [ebx], eax
         mov    [esi].IoStatus.Information, 4h
      .else
        .if [edi].Parameters.DeviceIoControl.OutputBufferLength >= 2h
          in    ax, dx
         mov    [ebx], ax
         mov    [esi].IoStatus.Information, 2h
        .else
          in    al, dx
         mov    [ebx], al
         mov    [esi].IoStatus.Information, 1h
        .endif
      .endif
         sti
         mov    ntStatus, STATUS_SUCCESS
         @@:
一次读取I/O端口一个字节。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_READ_PORT_BYTE
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_READ_PORT_BYTE\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 2h
          jb    @F
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 0h
          jz    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
        push    ebx
         xor    eax, eax
         mov    ax, [ebx]
      INVOKE    READ_PORT_UCHAR, eax
         pop    ebx
         mov    [ebx], al
         mov    [esi].IoStatus.Information, 1h
         mov    ntStatus, STATUS_SUCCESS
         @@:
一次读取I/O端口两个字节。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_READ_PORT_WORD
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_READ_PORT_WORD\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 2h
          jb    @F
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 2h
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
        push    ebx
         xor    eax, eax
         mov    ax, [ebx]
      INVOKE    READ_PORT_USHORT, eax
         pop    ebx
         mov    [ebx], ax
         mov    [esi].IoStatus.Information, 2h
         mov    ntStatus, STATUS_SUCCESS
         @@:
一次读取I/O端口四个字节。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_READ_PORT_DWORD
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_READ_PORT_DWORD\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 2h
          jb    @F
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 4h
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
        push    ebx
         xor    eax, eax
         mov    ax, [ebx]
      INVOKE    READ_PORT_ULONG, eax
         pop    ebx
         mov    [ebx], eax
         mov    [esi].IoStatus.Information, 4h
         mov    ntStatus, STATUS_SUCCESS
         @@:
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_WRITE_PORT
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_WRITE_PORT\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 3h
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    dx, [ebx]
         cli
      .if [edi].Parameters.DeviceIoControl.InputBufferLength >= 6h
         mov    eax, [ebx + 2h]
         out    dx, eax
      .else
        .if [edi].Parameters.DeviceIoControl.InputBufferLength >= 4h
         mov    ax, [ebx + 2h]
         out    dx, ax
        .else
         mov    al, [ebx + 2h]
         out    dx, al
        .endif
      .endif
         sti
         mov    ntStatus, STATUS_SUCCESS
         @@:
一次写I/O端口一个字节。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_WRITE_PORT_BYTE
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_WRITE_PORT_BYTE\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 8h
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    eax, [ebx]
         mov    ecx, [ebx + 4h]
      INVOKE    WRITE_PORT_UCHAR, eax, ecx
         mov    ntStatus, STATUS_SUCCESS
         @@:
一次写I/O端口两个字节。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_WRITE_PORT_WORD
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_WRITE_PORT_WORD\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 8h
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    eax, [ebx]
         mov    ecx, [ebx + 4h]
      INVOKE    WRITE_PORT_USHORT, eax, ecx
         mov    ntStatus, STATUS_SUCCESS
         @@:
一次写I/O端口四字节。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_WRITE_PORT_DWORD
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_WRITE_PORT_DWORD\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 8h
          jb    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    eax, [ebx]
         mov    ecx, [ebx + 4h]
      INVOKE    WRITE_PORT_ULONG, eax, ecx
         mov    ntStatus, STATUS_SUCCESS
         @@:
读写PCI配置信息。
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_PCI_READ_CONFIG
      ; SystemBuffer for input.
      ;   DWORD[0] = bus number.
      ;   DWORD[1] = slot number.
      ;   DWORD[2] = offset.
      ; SystemBuffer for output.
      ;   DWORD    = data output.
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_PCI_READ_CONFIG\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 0Ch
          jb    @F
         cmp    [edi].Parameters.DeviceIoControl.OutputBufferLength, 0h
          jz    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    eax, [edi].Parameters.DeviceIoControl.OutputBufferLength
      INVOKE    HalGetBusDataByOffset, PCIConfiguration, [ebx], [ebx + 4h], ebx, [ebx + 8h], eax
      .if eax != [edi].Parameters.DeviceIoControl.OutputBufferLength
         mov    [esi].IoStatus.Information, 0h
         mov    ntStatus, STATUS_INVALID_PARAMETER      
      .else
         mov    [esi].IoStatus.Information, eax
         mov    ntStatus, STATUS_SUCCESS   
      .endif
         @@:
    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_PCI_WRITE_CONFIG
      ; SystemBuffer for input.
      ;   DWORD[0] = bus number.
      ;   DWORD[1] = slot number.
      ;   DWORD[2] = offset.
      ;   DWORD[3] = data length.
      INVOKE    DbgPrint, $CTA0("OnIoControl: $IOCTL_PCI_WRITE_CONFIG\n")
         mov    ntStatus, STATUS_BUFFER_TOO_SMALL
         cmp    [edi].Parameters.DeviceIoControl.InputBufferLength, 10h
         jbe    @F
         mov    ebx, [esi].AssociatedIrp.SystemBuffer
         mov    eax, ebx
         add    eax, 10h
        push    [ebx + 0Ch]
      INVOKE    HalSetBusDataByOffset, PCIConfiguration, [ebx], [ebx + 4h], eax, [ebx + 8h], [ebx + 0Ch]
         pop    ebx
      .if eax != ebx
         mov    [esi].IoStatus.Information, 0h
         mov    ntStatus, STATUS_INVALID_PARAMETER      
      .else
         mov    [esi].IoStatus.Information, eax
         mov    ntStatus, STATUS_SUCCESS   
      .endif
         @@:
    .endif
         
        push    ntStatus
         pop    [esi].IoStatus.Status
    
      assume    edi :nothing
      assume    esi :nothing
         
    fastcall    IofCompleteRequest, pIrp, IO_NO_INCREMENT
      INVOKE    DbgPrint, $CTA0("OnIoControl: IoCompleteRequest()\n")  
      
      INVOKE    DbgPrint, $CTA0("OnIoControl: Leave...\n\n")
         mov    eax, ntStatus
         ret
  OnIoControl endp
处理应用程序调用CreateFile的例程。
  ; IRP_MJ_CREATE.
  ; Arguments:
  ;   DeviceObject - Pointer to device object.
  ;   pIrp - Pointer to the current IRP.
  ; Return Value:
  ;   STATUS_SUCCESS if the IRP was processed successfully, otherwise an erroror
  ;   indicating the reason for failure.
  OnCreate proc uses esi pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
      INVOKE    DbgPrint, $CTA0("OnCreate: Enter...\n")
         
         inc    dwRefCount
         
        push    esi
         mov    esi, pIrp
      assume    esi :PIRP
         
         mov    [esi].IoStatus.Status, STATUS_SUCCESS
         mov    [esi].IoStatus.Information, 0h
         
      assume    esi :nothing
         pop    esi

    fastcall    IofCompleteRequest, pIrp, IO_NO_INCREMENT
      INVOKE    DbgPrint, $CTA0("OnCreate: IoCompleteRequest()\n")  
      INVOKE    DbgPrint, $CTA0("OnCreate: Leave...\n\n")
         mov    eax, STATUS_SUCCESS
         ret
  OnCreate endp
处理应用程序调用CloseHandle的例程。
  ; IRP_MJ_CLOSE.
  ; Arguments:
  ;   DeviceObject - Pointer to device object.
  ;   pIrp - Pointer to the current IRP.
  ; Return Value:
  ;   STATUS_SUCCESS if the IRP was processed successfully, otherwise an erroror
  ;   indicating the reason for failure.
  OnClose proc uses esi pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
      INVOKE    DbgPrint, $CTA0("OnClose: Enter...\n")
         
         cmp    dwRefCount, 0h
          jz    @F
         dec    dwRefCount
         @@:
         
        push    esi
         mov    esi, pIrp
      assume    esi :PIRP
         
         mov    [esi].IoStatus.Status, STATUS_SUCCESS
         mov    [esi].IoStatus.Information, 0h
         
      assume    esi :nothing
         pop    esi

    fastcall    IofCompleteRequest, pIrp, IO_NO_INCREMENT
      INVOKE    DbgPrint, $CTA0("OnClose: IoCompleteRequest()\n")      
      INVOKE    DbgPrint, $CTA0("OnClose: Leave...\n\n")
         mov    eax, STATUS_SUCCESS
         ret
  OnClose endp
处理系统调用或当应用程序调用DeleteService,ControlService时的例程。
  ; This routine is called by the I/O system to unload the driver.
  ; Any resources previously allocated must be freed.
  ; Arguments:
  ;   DriverObject - Pointer to the object that represents our driver.
  ; Return Value:
  ;   None
  OnUnload proc DriverObject:PDRIVER_OBJECT  
      INVOKE    DbgPrint, $CTA0("OnUnload: Enter...\n")
      
      ; delete the link from our device name to a name in the Win32 namespace.
      INVOKE    IoDeleteSymbolicLink, addr uzDosDeviceName
      INVOKE    DbgPrint, $CTA0("OnUnload: IoDeleteSymbolicLink(%08X)\n"), eax
       
      ; delete the pDeviceObject
         mov    eax, DriverObject
      INVOKE    IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject
      INVOKE    DbgPrint, $CTA0("OnUnload: IoDeleteDevice()\n")
         
      INVOKE    DbgPrint, $CTA0("OnUnload: Leave...\n\n")
         ret
  OnUnload endp