WinIo.c
上传用户:ason123
上传日期:2010-03-31
资源大小:177k
文件大小:12k
源码类别:

并口编程

开发平台:

C++ Builder

  1. // ---------------------------------------------------- //
  2. //                      WinIo v2.0                      //
  3. //  Direct Hardware Access Under Windows 9x/NT/2000/XP  //
  4. //           Copyright 1998-2002 Yariv Kaplan           //
  5. //               http://www.internals.com               //
  6. // ---------------------------------------------------- //
  7. #include <ntddk.h>
  8. #include "winio_nt.h"
  9. #define OutputDebugString
  10. #define IOPM_SIZE 0x2000
  11. typedef char IOPM[IOPM_SIZE];
  12. IOPM *pIOPM = NULL;
  13. // Function definition section
  14. // -----------------------------------------------------------------
  15. NTSTATUS WinIoDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  16. void WinIoUnload(IN PDRIVER_OBJECT DriverObject);
  17. NTSTATUS UnmapPhysicalMemory(HANDLE PhysicalMemoryHandle, PVOID pPhysMemLin);
  18. NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress,
  19.                                         ULONG PhysMemSizeInBytes,
  20.                                         PVOID *ppPhysMemLin,
  21.                                         HANDLE *pPhysicalMemoryHandle);
  22. void Ke386SetIoAccessMap(int, IOPM *);
  23. void Ke386QueryIoAccessMap(int, IOPM *);
  24. void Ke386IoSetAccessProcess(PEPROCESS, int);
  25. // -----------------------------------------------------------------
  26. // Installable driver initialization entry point.
  27. // This entry point is called directly by the I/O system.
  28. NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,
  29.                       IN PUNICODE_STRING RegistryPath)
  30. {
  31.   UNICODE_STRING  DeviceNameUnicodeString;
  32.   UNICODE_STRING  DeviceLinkUnicodeString;
  33.   NTSTATUS        ntStatus;
  34.   PDEVICE_OBJECT  DeviceObject = NULL;
  35.   OutputDebugString ("Entering DriverEntry");
  36.   RtlInitUnicodeString (&DeviceNameUnicodeString, L"\Device\WinIo");
  37.   // Create an EXCLUSIVE device object (only 1 thread at a time
  38.   // can make requests to this device).
  39.   ntStatus = IoCreateDevice (DriverObject,
  40.                              0,
  41.                              &DeviceNameUnicodeString,
  42.                              FILE_DEVICE_WINIO,
  43.                              0,
  44.                              TRUE,
  45.                              &DeviceObject);
  46.   if (NT_SUCCESS(ntStatus))
  47.   {
  48.     // Create dispatch points for device control, create, close.
  49.     DriverObject->MajorFunction[IRP_MJ_CREATE]         =
  50.     DriverObject->MajorFunction[IRP_MJ_CLOSE]          =
  51.     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WinIoDispatch;
  52.     DriverObject->DriverUnload                         = WinIoUnload;
  53.     // Create a symbolic link, e.g. a name that a Win32 app can specify
  54.     // to open the device.
  55.     RtlInitUnicodeString (&DeviceLinkUnicodeString, L"\DosDevices\WinIo");
  56.     ntStatus = IoCreateSymbolicLink (&DeviceLinkUnicodeString,
  57.                                      &DeviceNameUnicodeString);
  58.     if (!NT_SUCCESS(ntStatus))
  59.     {
  60.       // Symbolic link creation failed- note this & then delete the
  61.       // device object (it's useless if a Win32 app can't get at it).
  62.       OutputDebugString ("ERROR: IoCreateSymbolicLink failed");
  63.       IoDeleteDevice (DeviceObject);
  64.     }
  65.   }
  66.   else
  67.   {
  68.     OutputDebugString ("ERROR: IoCreateDevice failed");
  69.   }
  70.   OutputDebugString ("Leaving DriverEntry");
  71.   return ntStatus;
  72. }
  73. // Process the IRPs sent to this device
  74. NTSTATUS WinIoDispatch(IN PDEVICE_OBJECT DeviceObject,
  75.                        IN PIRP Irp)
  76. {
  77.   PIO_STACK_LOCATION IrpStack;
  78.   ULONG              dwInputBufferLength;
  79.   ULONG              dwOutputBufferLength;
  80.   ULONG              dwIoControlCode;
  81.   PVOID              pvIOBuffer;
  82.   NTSTATUS           ntStatus;
  83.   struct             tagPhys32Struct Phys32Struct;
  84.   OutputDebugString ("Entering WinIoDispatch");
  85.   // Init to default settings
  86.   Irp->IoStatus.Status      = STATUS_SUCCESS;
  87.   Irp->IoStatus.Information = 0;
  88.   
  89.   IrpStack = IoGetCurrentIrpStackLocation(Irp);
  90.   // Get the pointer to the input/output buffer and it's length
  91.   pvIOBuffer           = Irp->AssociatedIrp.SystemBuffer;
  92.   dwInputBufferLength  = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  93.   dwOutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  94.   switch (IrpStack->MajorFunction)
  95.   {
  96.     case IRP_MJ_CREATE:
  97.       OutputDebugString("IRP_MJ_CREATE");
  98.     break;
  99.     case IRP_MJ_CLOSE:
  100.       OutputDebugString("IRP_MJ_CLOSE");
  101.     break;
  102.     case IRP_MJ_DEVICE_CONTROL:
  103.       OutputDebugString("IRP_MJ_DEVICE_CONTROL");
  104.       dwIoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  105.       switch (dwIoControlCode)
  106.       {
  107.         case IOCTL_WINIO_ENABLEDIRECTIO:
  108.           OutputDebugString("IOCTL_WINIO_ENABLEDIRECTIO");
  109.           pIOPM = MmAllocateNonCachedMemory(sizeof(IOPM));
  110.           if (pIOPM)
  111.           {
  112.             RtlZeroMemory(pIOPM, sizeof(IOPM));
  113.             Ke386IoSetAccessProcess(PsGetCurrentProcess(), 1);
  114.             Ke386SetIoAccessMap(1, pIOPM);
  115.           }
  116.           else
  117.             Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  118.         break;
  119.         case IOCTL_WINIO_DISABLEDIRECTIO:
  120.           OutputDebugString("IOCTL_WINIO_DISABLEDIRECTIO");
  121.           if (pIOPM)
  122.           {
  123.             Ke386IoSetAccessProcess(PsGetCurrentProcess(), 0);
  124.             Ke386SetIoAccessMap(1, pIOPM);
  125.             MmFreeNonCachedMemory(pIOPM, sizeof(IOPM));
  126.             pIOPM = NULL;
  127.           }
  128.         break;
  129.         case IOCTL_WINIO_MAPPHYSTOLIN:
  130.           OutputDebugString("IOCTL_WINIO_MAPPHYSTOLIN");
  131.           if (dwInputBufferLength)
  132.           {
  133.             memcpy (&Phys32Struct, pvIOBuffer, dwInputBufferLength);
  134.             ntStatus = MapPhysicalMemoryToLinearSpace(Phys32Struct.pvPhysAddress,
  135.                                                       Phys32Struct.dwPhysMemSizeInBytes,
  136.                                                       &Phys32Struct.pvPhysMemLin,
  137.                                                       &Phys32Struct.PhysicalMemoryHandle);
  138.             if (NT_SUCCESS(ntStatus))
  139.             {
  140.               memcpy (pvIOBuffer, &Phys32Struct, dwInputBufferLength);
  141.               Irp->IoStatus.Information = dwInputBufferLength;
  142.             }
  143.             Irp->IoStatus.Status = ntStatus;
  144.           }
  145.           else
  146.             Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  147.         break;
  148.         case IOCTL_WINIO_UNMAPPHYSADDR:
  149.           OutputDebugString("IOCTL_WINIO_UNMAPPHYSADDR");
  150.           if (dwInputBufferLength)
  151.           {
  152.             memcpy (&Phys32Struct, pvIOBuffer, dwInputBufferLength);
  153.             ntStatus = UnmapPhysicalMemory(Phys32Struct.PhysicalMemoryHandle, Phys32Struct.pvPhysMemLin);
  154.             Irp->IoStatus.Status = ntStatus;
  155.           }
  156.           else
  157.             Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  158.         break;
  159.  
  160.         default:
  161.           OutputDebugString("ERROR: Unknown IRP_MJ_DEVICE_CONTROL");
  162.           Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  163.         break;
  164.       }
  165.     break;
  166.   }
  167.   // DON'T get cute and try to use the status field of the irp in the
  168.   // return status.  That IRP IS GONE as soon as you call IoCompleteRequest.
  169.   ntStatus = Irp->IoStatus.Status;
  170.   IoCompleteRequest (Irp, IO_NO_INCREMENT);
  171.   // We never have pending operation so always return the status code.
  172.   OutputDebugString("Leaving WinIoDispatch");
  173.   return ntStatus;
  174. }
  175. // Delete the associated device and return
  176. void WinIoUnload(IN PDRIVER_OBJECT DriverObject)
  177. {
  178.   UNICODE_STRING DeviceLinkUnicodeString;
  179.   NTSTATUS ntStatus;
  180.   OutputDebugString ("Entering WinIoUnload");
  181.   RtlInitUnicodeString (&DeviceLinkUnicodeString, L"\DosDevices\WinIo");
  182.   
  183.   ntStatus = IoDeleteSymbolicLink (&DeviceLinkUnicodeString);
  184.   if (NT_SUCCESS(ntStatus))
  185.   {
  186.     IoDeleteDevice (DriverObject->DeviceObject);
  187.   }
  188.   else
  189.   {
  190.     OutputDebugString ("ERROR: IoDeleteSymbolicLink");
  191.   }
  192.   OutputDebugString ("Leaving WinIoUnload");
  193. }
  194. NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress,
  195.                                         ULONG PhysMemSizeInBytes,
  196.                                         PVOID *ppPhysMemLin,
  197.                                         HANDLE *pPhysicalMemoryHandle)
  198. {
  199.   UNICODE_STRING     PhysicalMemoryUnicodeString;
  200.   PVOID              PhysicalMemorySection = NULL;
  201.   OBJECT_ATTRIBUTES  ObjectAttributes;
  202.   PHYSICAL_ADDRESS   ViewBase;
  203.   NTSTATUS           ntStatus;
  204.   PHYSICAL_ADDRESS   pStartPhysAddress;
  205.   PHYSICAL_ADDRESS   pEndPhysAddress;
  206.   PHYSICAL_ADDRESS   MappingLength;
  207.   BOOLEAN            Result1, Result2;
  208.   ULONG              IsIOSpace;
  209.   unsigned char     *pbPhysMemLin = NULL;
  210.   OutputDebugString ("Entering MapPhysicalMemoryToLinearSpace");
  211.   RtlInitUnicodeString (&PhysicalMemoryUnicodeString,
  212.                         L"\Device\PhysicalMemory");
  213.   InitializeObjectAttributes (&ObjectAttributes,
  214.                               &PhysicalMemoryUnicodeString,
  215.                               OBJ_CASE_INSENSITIVE,
  216.                               (HANDLE) NULL,
  217.                               (PSECURITY_DESCRIPTOR) NULL);
  218.   *pPhysicalMemoryHandle = NULL;
  219.   ntStatus = ZwOpenSection (pPhysicalMemoryHandle,
  220.                             SECTION_ALL_ACCESS,
  221.                             &ObjectAttributes);
  222.   if (NT_SUCCESS(ntStatus))
  223.   {
  224.     ntStatus = ObReferenceObjectByHandle (*pPhysicalMemoryHandle,
  225.                                           SECTION_ALL_ACCESS,
  226.                                           (POBJECT_TYPE) NULL,
  227.                                           KernelMode,
  228.                                           &PhysicalMemorySection,
  229.                                           (POBJECT_HANDLE_INFORMATION) NULL);
  230.     if (NT_SUCCESS(ntStatus))
  231.     {
  232.       pStartPhysAddress.QuadPart = (ULONGLONG)pPhysAddress;
  233.       pEndPhysAddress = RtlLargeIntegerAdd (pStartPhysAddress,
  234.                                             RtlConvertUlongToLargeInteger(PhysMemSizeInBytes));
  235.       IsIOSpace = 0;
  236.       Result1 = HalTranslateBusAddress (1, 0, pStartPhysAddress, &IsIOSpace, &pStartPhysAddress);
  237.       IsIOSpace = 0;
  238.       Result2 = HalTranslateBusAddress (1, 0, pEndPhysAddress, &IsIOSpace, &pEndPhysAddress);
  239.       if (Result1 && Result2)
  240.       {
  241.         MappingLength = RtlLargeIntegerSubtract (pEndPhysAddress, pStartPhysAddress);
  242.         if (MappingLength.LowPart)
  243.         {
  244.         
  245.           // Let ZwMapViewOfSection pick a linear address
  246.           PhysMemSizeInBytes = MappingLength.LowPart;
  247.           ViewBase = pStartPhysAddress;
  248.           ntStatus = ZwMapViewOfSection (*pPhysicalMemoryHandle,
  249.                                          (HANDLE) -1,
  250.                                          &pbPhysMemLin,
  251.                                          0L,
  252.                                          PhysMemSizeInBytes,
  253.                                          &ViewBase,
  254.                                          &PhysMemSizeInBytes,
  255.                                          ViewShare,
  256.                                          0,
  257.                                          PAGE_READWRITE | PAGE_NOCACHE);
  258.           if (!NT_SUCCESS(ntStatus))
  259.             OutputDebugString ("ERROR: ZwMapViewOfSection failed");
  260.           else
  261.           {
  262.             pbPhysMemLin += (ULONG)pStartPhysAddress.LowPart - (ULONG)ViewBase.LowPart;
  263.             *ppPhysMemLin = pbPhysMemLin;
  264.           }  
  265.         }
  266.         else
  267.           OutputDebugString ("ERROR: RtlLargeIntegerSubtract failed");
  268.       }
  269.       else
  270.         OutputDebugString ("ERROR: MappingLength = 0");
  271.     }
  272.     else
  273.       OutputDebugString ("ERROR: ObReferenceObjectByHandle failed");
  274.   }
  275.   else
  276.     OutputDebugString ("ERROR: ZwOpenSection failed");
  277.     
  278.   if (!NT_SUCCESS(ntStatus))
  279.     ZwClose(*pPhysicalMemoryHandle);
  280.   
  281.   OutputDebugString ("Leaving MapPhysicalMemoryToLinearSpace");
  282.   return ntStatus;
  283. }
  284. NTSTATUS UnmapPhysicalMemory(HANDLE PhysicalMemoryHandle, PVOID pPhysMemLin)
  285. {
  286.   NTSTATUS ntStatus;
  287.   OutputDebugString ("Entering UnmapPhysicalMemory");
  288.   ntStatus = ZwUnmapViewOfSection((HANDLE)-1, pPhysMemLin);
  289.   if (!NT_SUCCESS(ntStatus))
  290.     OutputDebugString ("ERROR: UnmapViewOfSection failed");
  291.   ZwClose(PhysicalMemoryHandle);
  292.   OutputDebugString ("Leaving UnmapPhysicalMemory");
  293.   return ntStatus;
  294. }