NTSTATUS HelloDDKDeviceIOControl(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { NTSTATUS status = STATUS_SUCCESS; KdPrint(("Enter HelloDDKDeviceIOControl\n")); //得到当前堆栈 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); //得到输入缓冲区大小 ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength; //得到输出缓冲区大小 ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength; //得到IOCTL码 ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; ULONG info = 0; switch (code) { // process request case IOCTL_ENABLEDIRECTIO: { KdPrint(("IOCTL_ENABLEDIRECTIO\n")); pIOPM = (UCHAR*)MmAllocateNonCachedMemory(IOPM_SIZE); if (pIOPM) { RtlZeroMemory(pIOPM, IOPM_SIZE); Ke386IoSetAccessProcess(PsGetCurrentProcess(), 1); Ke386SetIoAccessMap(1, pIOPM); } else pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; } case IOCTL_DISABLEDIRECTIO: { KdPrint(("IOCTL_DISABLEDIRECTIO\n")); if (pIOPM) { Ke386IoSetAccessProcess(PsGetCurrentProcess(), 0); Ke386SetIoAccessMap(1, pIOPM); MmFreeNonCachedMemory(pIOPM, IOPM_SIZE); pIOPM = NULL; } } default: status = STATUS_INVALID_VARIANT; } // 完成IRP pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = info; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("Leave HelloDDKDeviceIOControl\n")); return status; }
// This is where the magic happens... when the driver is loaded we // call the magic undocumented kernel functions and write over the // I/O Permission Map (IOPM). NTSTATUS DriverCreateDispatch( IN PDEVICE_OBJECT deviceObject, IN PIRP irp) { NTSTATUS result = STATUS_SUCCESS; Ke386IoSetAccessProcess(PsGetCurrentProcess(), 1); Ke386SetIoAccessMap(1, ioMap); irp->IoStatus.Information = 0; irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); return result; }
NTSTATUS WinIoDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpStack; ULONG dwInputBufferLength; ULONG dwOutputBufferLength; ULONG dwIoControlCode; PVOID pvIOBuffer; NTSTATUS ntStatus; struct tagPhys32Struct Phys32Struct; OutputDebugString ("Entering WinIoDispatch"); // Init to default settings Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IrpStack = IoGetCurrentIrpStackLocation(Irp); // Get the pointer to the input/output buffer and it's length pvIOBuffer = Irp->AssociatedIrp.SystemBuffer; dwInputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; dwOutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch (IrpStack->MajorFunction) { case IRP_MJ_CREATE: OutputDebugString("IRP_MJ_CREATE"); break; case IRP_MJ_CLOSE: OutputDebugString("IRP_MJ_CLOSE"); break; case IRP_MJ_DEVICE_CONTROL: OutputDebugString("IRP_MJ_DEVICE_CONTROL"); dwIoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; switch (dwIoControlCode) { case IOCTL_WINIO_ENABLEDIRECTIO: OutputDebugString("IOCTL_WINIO_ENABLEDIRECTIO"); pIOPM = MmAllocateNonCachedMemory(sizeof(IOPM)); if (pIOPM) { RtlZeroMemory(pIOPM, sizeof(IOPM)); Ke386IoSetAccessProcess(PsGetCurrentProcess(), 1); Ke386SetIoAccessMap(1, pIOPM); } else Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; break; case IOCTL_WINIO_DISABLEDIRECTIO: OutputDebugString("IOCTL_WINIO_DISABLEDIRECTIO"); if (pIOPM) { Ke386IoSetAccessProcess(PsGetCurrentProcess(), 0); Ke386SetIoAccessMap(1, pIOPM); MmFreeNonCachedMemory(pIOPM, sizeof(IOPM)); pIOPM = NULL; } break; case IOCTL_WINIO_MAPPHYSTOLIN: OutputDebugString("IOCTL_WINIO_MAPPHYSTOLIN"); if (dwInputBufferLength) { memcpy (&Phys32Struct, pvIOBuffer, dwInputBufferLength); ntStatus = MapPhysicalMemoryToLinearSpace(Phys32Struct.pvPhysAddress, Phys32Struct.dwPhysMemSizeInBytes, &Phys32Struct.pvPhysMemLin, &Phys32Struct.PhysicalMemoryHandle); if (NT_SUCCESS(ntStatus)) { memcpy (pvIOBuffer, &Phys32Struct, dwInputBufferLength); Irp->IoStatus.Information = dwInputBufferLength; } Irp->IoStatus.Status = ntStatus; } else Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; case IOCTL_WINIO_UNMAPPHYSADDR: OutputDebugString("IOCTL_WINIO_UNMAPPHYSADDR"); if (dwInputBufferLength) { memcpy (&Phys32Struct, pvIOBuffer, dwInputBufferLength); ntStatus = UnmapPhysicalMemory(Phys32Struct.PhysicalMemoryHandle, Phys32Struct.pvPhysMemLin); Irp->IoStatus.Status = ntStatus; } else Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; default: OutputDebugString("ERROR: Unknown IRP_MJ_DEVICE_CONTROL"); Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; } break; } // DON'T get cute and try to use the status field of the irp in the // return status. That IRP IS GONE as soon as you call IoCompleteRequest. ntStatus = Irp->IoStatus.Status; IoCompleteRequest (Irp, IO_NO_INCREMENT); // We never have pending operation so always return the status code. OutputDebugString("Leaving WinIoDispatch"); return ntStatus; }
/********************************************************************* Set the IOPM (I/O permission map) of the calling process so that it is given full I/O access. Our IOPM_local[] array is all zeros, so the IOPM will be all zeros. If OnFlag is 1, the process is given I/O access. If it is 0, access is removed. *********************************************************************/ VOID SetIOPermissionMap(int OnFlag) { Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag); Ke386SetIoAccessMap(1, IOPM_local); }