www.pudn.com > porttalk22.zip > porttalk.c


/******************************************************************************/ 
/*                                                                            */ 
/*                    PortTalk Driver for Windows NT/2000/XP                  */ 
/*                        Version 2.0, 12th January 2002                      */ 
/*                          http://www.beyondlogic.org                        */ 
/*                                                                            */ 
/* Copyright © 2002 Craig Peacock. Craig.Peacock@beyondlogic.org              */ 
/* Any publication or distribution of this code in source form is prohibited  */ 
/* without prior written permission of the copyright holder. This source code */ 
/* is provided "as is", without any guarantee made as to its suitability or   */ 
/* fitness for any particular use. Permission is herby granted to modify or   */ 
/* enhance this sample code to produce a derivative program which may only be */ 
/* distributed in compiled object form only.                                  */ 
/******************************************************************************/ 
 
#include  
#include  
 
#define    IOPM_SIZE    0x2000 
 
typedef UCHAR IOPM[IOPM_SIZE]; 
 
IOPM *IOPM_local = 0; 
 
void Ke386SetIoAccessMap(int, IOPM *); 
void Ke386QueryIoAccessMap(int, IOPM *); 
void Ke386IoSetAccessProcess(PEPROCESS, int); 
 
NTSTATUS PortTalkDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 
NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId,OUT struct _EPROCESS ** pEProcess); 
VOID PortTalkUnload(IN PDRIVER_OBJECT DriverObject); 
 
NTSTATUS PortTalkCreateDispatch( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
{ 
    Irp->IoStatus.Information = 0; 
    Irp->IoStatus.Status = STATUS_SUCCESS; 
    IoCompleteRequest(Irp, IO_NO_INCREMENT); 
    return STATUS_SUCCESS; 
} 
 
NTSTATUS DriverEntry( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PUNICODE_STRING RegistryPath 
    ) 
{ 
    PDEVICE_OBJECT deviceObject; 
    NTSTATUS status; 
    WCHAR NameBuffer[] = L"\\Device\\PortTalk"; 
    WCHAR DOSNameBuffer[] = L"\\DosDevices\\PortTalk"; 
    UNICODE_STRING uniNameString, uniDOSString; 
 
    KdPrint( ("PORTTALK: Porttalk V2.0 12/01/2002 has Loaded") ); 
 
    IOPM_local = MmAllocateNonCachedMemory(sizeof(IOPM)); 
    if(IOPM_local == 0) return STATUS_INSUFFICIENT_RESOURCES; 
 
    RtlFillMemory(IOPM_local, sizeof(IOPM), 0xFF); 
 
    KdPrint( ("PORTTALK: Memory Allocated at %X\n",IOPM_local) ); 
 
    RtlInitUnicodeString(&uniNameString, NameBuffer); 
    RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); 
 
    status = IoCreateDevice(DriverObject,  
                            0, 
                            &uniNameString, 
                            FILE_DEVICE_UNKNOWN, 
                            0,  
                            FALSE,  
                            &deviceObject); 
 
    if(!NT_SUCCESS(status)) 
        return status; 
 
    status = IoCreateSymbolicLink (&uniDOSString, &uniNameString); 
 
    if (!NT_SUCCESS(status)) 
        return status; 
 
    DriverObject->MajorFunction[IRP_MJ_CREATE] = PortTalkCreateDispatch; 
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PortTalkDeviceControl; 
    DriverObject->DriverUnload = PortTalkUnload; 
 
    return STATUS_SUCCESS; 
} 
 
NTSTATUS 
PortTalkDeviceControl( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP pIrp 
    ) 
 
{ 
    PIO_STACK_LOCATION  irpSp; 
    NTSTATUS            ntStatus = STATUS_SUCCESS;    
 
    ULONG               inBufLength;   /* Input buffer length */ 
    ULONG               outBufLength;  /* Output buffer length */ 
    ULONG               inBuf;         /* Pointer to Input and output buffer */ 
 
    PUCHAR              CharBuffer;  
    PUSHORT             ShortBuffer; 
    PULONG              LongBuffer; 
    PVOID               ioBuffer; 
 
    USHORT Offset; 
    UCHAR Value; 
  
    ULONG ProcessID;     
    struct _EPROCESS *Process; 
 
    irpSp = IoGetCurrentIrpStackLocation( pIrp ); 
    inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; 
    outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; 
 
    ioBuffer    = pIrp->AssociatedIrp.SystemBuffer; 
 
    CharBuffer  = (PUCHAR) ioBuffer; 
    ShortBuffer = (PUSHORT) ioBuffer; 
    LongBuffer  = (PULONG) ioBuffer; 
 
    switch ( irpSp->Parameters.DeviceIoControl.IoControlCode ) 
     { 
      case IOCTL_IOPM_RESTRICT_ALL_ACCESS: 
 
            KdPrint( ("PORTTALK: IOCTL_IOPM_RESTRICT_ALL_ACCESS - RTLFillMemory") ); 
            RtlFillMemory(IOPM_local, sizeof(IOPM), 0xFF); 
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */ 
            ntStatus = STATUS_SUCCESS; 
            break; 
 
      case IOCTL_IOPM_ALLOW_EXCUSIVE_ACCESS: 
 
            KdPrint( ("PORTTALK: IOCTL_IOPM_ALLOW_EXCUSIVE_ACCESS - RTLZeroMemory") ); 
            RtlZeroMemory(IOPM_local, sizeof(IOPM)); 
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */ 
            ntStatus = STATUS_SUCCESS; 
            break; 
 
      case IOCTL_SET_IOPM:  
 
            KdPrint( ("PORTTALK: IOCTL_SET_IOPM - Set IO Permission Bitmap") ); 
            if (inBufLength >= 3) { 
                Offset = ShortBuffer[0]; 
                if (Offset >= 0x2000) { 
                      ntStatus = STATUS_ARRAY_BOUNDS_EXCEEDED; 
                      break; 
                     } 
                Value  = CharBuffer[2]; 
                KdPrint( ("PORTTALK: Offset = %X, Value = %X\n",Offset,Value) ); 
                *(*IOPM_local + Offset) = Value; 
                ntStatus = STATUS_SUCCESS; 
            } else ntStatus = STATUS_BUFFER_TOO_SMALL; 
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */ 
            ntStatus = STATUS_SUCCESS; 
            break; 
 
      case IOCTL_ENABLE_IOPM_ON_PROCESSID:  
 
            KdPrint( ("PORTTALK: IOCTL_ENABLE_IOPM_ON_PROCESSID") ); 
            if (inBufLength >= 4) { 
                ProcessID = LongBuffer[0]; 
                KdPrint( ("PORTTALK: ProcessID Received is %d\n",ProcessID) ); 
                PsLookupProcessByProcessId(ProcessID, &Process); 
                KdPrint( ("PORTTALK: Pointer to Process is %X\n",Process) ); 
                KdPrint( ("PORTTALK: Address = %X\n",*(*IOPM_local + 0x6F) ) ); 
                Ke386SetIoAccessMap(1, IOPM_local); 
                Ke386IoSetAccessProcess(Process, 1); 
                ntStatus = STATUS_SUCCESS; 
            } else ntStatus = STATUS_BUFFER_TOO_SMALL; 
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */ 
            ntStatus = STATUS_SUCCESS; 
            break; 
         
      case IOCTL_READ_PORT_UCHAR: 
  
            if ((inBufLength >= 2) && (outBufLength >= 1)) { 
                KdPrint( ("PORTTALK: IOCTL_READ_PORT_UCHAR 0x%X",ShortBuffer[0]) ); 
                (UCHAR)Value = READ_PORT_UCHAR((PUCHAR)ShortBuffer[0]); 
                KdPrint( ("PORTTALK: Value Read %X",Value) ); 
                CharBuffer[0] = Value; 
            } else ntStatus = STATUS_BUFFER_TOO_SMALL; 
            pIrp->IoStatus.Information = 1; /* Output Buffer Size */ 
            ntStatus = STATUS_SUCCESS; 
            break; 
 
      case IOCTL_WRITE_PORT_UCHAR: 
            if (inBufLength >= 3) { 
                KdPrint( ("PORTTALK: IOCTL_WRITE_PORT_UCHAR(0x%X,0x%X)",ShortBuffer[0], CharBuffer[2]) ); 
                WRITE_PORT_UCHAR((PUCHAR)ShortBuffer[0], CharBuffer[2]); 
            } else ntStatus = STATUS_BUFFER_TOO_SMALL; 
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */ 
            ntStatus = STATUS_SUCCESS; 
            break; 
 
      default: 
            KdPrint( ("PORTTALK: Unsupported IOCTL Call\n") ); 
            ntStatus = STATUS_UNSUCCESSFUL; 
            pIrp->IoStatus.Information = 0; 
            break; 
 
    } 
    pIrp->IoStatus.Status = ntStatus; 
    IoCompleteRequest( pIrp, IO_NO_INCREMENT ); 
    return ntStatus; 
} 
 
VOID PortTalkUnload(IN PDRIVER_OBJECT DriverObject) 
{ 
    WCHAR DOSNameBuffer[] = L"\\DosDevices\\PortTalk"; 
    UNICODE_STRING uniDOSString; 
 
    KdPrint( ("PORTTALK: PortTalk is Unloading . .\n") ); 
 
    if(IOPM_local) MmFreeNonCachedMemory(IOPM_local, sizeof(IOPM)); 
    RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); 
    IoDeleteSymbolicLink (&uniDOSString); 
    IoDeleteDevice(DriverObject->DeviceObject); 
}