        .486
        .model flat, stdcall
        option casemap :none
;===============================================================================
        STATUS_INSUFFICIENT_RESOURCES   EQU 0c000009ah
        STATUS_SUCCESS                  EQU 0
        FALSE                           EQU 0
        IO_NO_INCREMENT                 EQU 0
        FILE_DEVICE_UNKNOWN             EQU 22h
;===============================================================================
PVOID   typedef DWORD
PCHAR   typedef DWORD
WCHAR   typedef DWORD
;-------------------------------------------------------------------------------
        Ke386IoSetAccessProcess     PROTO ProcessID:DWORD, OnFlag:DWORD
        Ke386SetIoAccessMap         PROTO Flag:DWORD, IOPM:PVOID
        IoGetCurrentProcess         PROTO
        MmFreeNonCachedMemory       PROTO IOPM:PVOID, Count:DWORD
        RtlInitUnicodeString        PROTO uniCode:PCHAR, AWideString:WCHAR
        IoDeleteSymbolicLink        PROTO uniCode:PCHAR
        IoDeleteDevice              PROTO DeviceObj:PVOID
        MmAllocateNonCachedMemory   PROTO Count:DWORD
        IoCreateDevice              PROTO DriverObj:PVOID, DevExtSize:DWORD,
                                          DevName:PCHAR, DevType:DWORD,
                                          DevCharact:DWORD, Exclusiv:DWORD,
                                          DeviceObj:PVOID
        IoCreateSymbolicLink        PROTO uniCode:PCHAR, uniName:PCHAR
;-------------------------------------------------------------------------------
extern Ke386IoSetAccessProcess@8(Ke386IoSetAccessProcess):proc
extern Ke386SetIoAccessMap@8(Ke386SetIoAccessMap):proc
extern IoGetCurrentProcess@0(IoGetCurrentProcess):proc
extern MmFreeNonCachedMemory@8(MmFreeNonCachedMemory):proc
extern RtlInitUnicodeString@8(RtlInitUnicodeString):proc
extern IoDeleteSymbolicLink@4(IoDeleteSymbolicLink):proc
extern IoDeleteDevice@4(IoDeleteDevice):proc
extern MmAllocateNonCachedMemory@4(MmAllocateNonCachedMemory):proc
extern IoCreateDevice@28(IoCreateDevice):proc
extern IoCreateSymbolicLink@8(IoCreateSymbolicLink):proc
extern syscall @IofCompleteRequest@8:proc
;-------------------------------------------------------------------------------
MEMCOPY macro   Source:REQ,Dest:REQ,Count:REQ
        lea     esi,Source
        lea     edi,Dest
        mov     ecx,Count
        rep     movsw
        endm
;-------------------------------------------------------------------------------
FILLD   macro   Count:REQ
        mov     ecx,Count
        rep     stosd
        endm
;-------------------------------------------------------------------------------
WIDESTR macro   AVar:REQ, AStr:REQ
        local   txt, arg
        txt     textequ <>
        forc    arg, <AStr>
          txt     CATSTR txt, <'>, <arg>, <'!,>
        endm
        txt     CATSTR  txt, <0>
        AVar    WORD &txt
        endm
;===============================================================================
.data
        IOPM_local  DWORD       0
        WIDESTR DeviceName,     <\Device\expro>
        WIDESTR DeviceDOSName,  <\DosDevices\expro>
;===============================================================================
.code
ExproCreateDispatch proc DeviceObject:DWORD, PIrp:DWORD

                invoke  IoGetCurrentProcess
                invoke  Ke386IoSetAccessProcess,eax,1
                invoke  Ke386SetIoAccessMap,1,IOPM_local
                mov     ecx,PIrp
                xor     eax,eax
                xor     edx,edx
                mov     [ecx+1ch],eax       ; Irp->IoStatus.Information
                mov     [ecx+18h],edx       ; Irp->IoStatus.Status
                call    @IofCompleteRequest@8
                xor     eax,eax             ; STATUS_SUCCESS
;
                ret
                
ExproCreateDispatch endp
;===============================================================================
ExproUnload proc USES esi edi,DriverObject:DWORD
                 LOCAL uniDOSString:QWORD
                 LOCAL DOSNameBuffer[40]:BYTE

                MEMCOPY DeviceDOSName,DOSNameBuffer,18
;-------------------------------------------------------------------------------
    .IF IOPM_local != 0
                invoke  MmFreeNonCachedMemory,IOPM_local,2000h
    .ENDIF
;-------------------------------------------------------------------------------
                lea     eax,DOSNameBuffer
                lea     ecx,uniDOSString
                invoke  RtlInitUnicodeString,ecx,eax
;-------------------------------------------------------------------------------
                lea     eax,uniDOSString
                invoke  IoDeleteSymbolicLink,eax
;-------------------------------------------------------------------------------
                mov     eax,DriverObject
                invoke  IoDeleteDevice,[eax+4]  ; DriverObject->DeviceObject
;
                ret
                
ExproUnload endp
;===============================================================================
DriverEntry proc PUBLIC USES esi edi,DriverObject:DWORD, RegistryPath:DWORD
                 LOCAL deviceObject:DWORD
                 LOCAL uniNameString:QWORD,uniDOSString:QWord
                 LOCAL NameBuffer[32]:BYTE
                 LOCAL DOSNameBuffer[40]:BYTE

;-------------------------------------------------------------------------------
                MEMCOPY DeviceName,NameBuffer,14
                MEMCOPY DeviceDOSName,DOSNameBuffer,18
;-------------------------------------------------------------------------------
                invoke  MmAllocateNonCachedMemory,2000h
                mov     IOPM_local,eax
    .IF eax == 0
                mov     eax,STATUS_INSUFFICIENT_RESOURCES
    .ELSE
;-------------------------------------------------------------------------------
                stc
                sbb     eax,eax                 ; EAX = 0ffffffffh
                mov     edi,IOPM_local
                FILLD   16                      ; disable ports 0..1FFh
                inc     eax                     ; EAX = 0
                FILLD   7                       ; enable ports 200h..2DFh
                dec     eax                     ; EAX = 0ffffffffh
                FILLD   07e9h                   ; disable ports 2E0h..FFFFh
;-------------------------------------------------------------------------------
                lea     eax,NameBuffer
                lea     ecx,uniNameString
                invoke  RtlInitUnicodeString,ecx,eax
;-------------------------------------------------------------------------------
                lea     eax,DOSNameBuffer
                lea     ecx,uniDOSString
                invoke  RtlInitUnicodeString,ecx,eax
;-------------------------------------------------------------------------------
                lea     ecx,deviceObject
                lea     edx,uniNameString
                mov     esi,DriverObject
                invoke  IoCreateDevice,esi,0,edx,FILE_DEVICE_UNKNOWN,0,FALSE,ecx
      .IF eax == 0
;-------------------------------------------------------------------------------
                lea     eax,uniNameString
                lea     ecx,uniDOSString
                invoke  IoCreateSymbolicLink,ecx,eax
        .IF eax == 0
;-------------------------------------------------------------------------------
;               DriverObject->MajorFunction[IRP_MJ_CREATE]
;
                mov     dword ptr [esi+38h],offset ExproCreateDispatch
;
;               DriverObject->DriverUnload
;
                mov     dword ptr [esi+34h],offset ExproUnload
                xor     eax,eax
        .ENDIF
      .ENDIF
   .ENDIF
                ret

DriverEntry endp

end