// Control.cpp -- IOCTL handlers for AIOWDM driver #include "stddcls.h" #include "driver.h" #include "ioctls.h" #ifdef _WIN64 typedef ULONGLONG UNATIVE; #else typedef ULONG UNATIVE; #endif VOID DoIOAction(PUCHAR Base, IOACTION Action); void ForgetIRP(PIRP IRP); VOID IRQGenCancelIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); /////////////////////////////////////////////////////////////////////////////// #pragma PAGEDCODE void DumpRegBinary(PWCHAR Nom, unsigned long Len, PVOID pValue) { PAGED_CODE(); PKEY_VALUE_PARTIAL_INFORMATION pKVPI; HANDLE Key; OBJECT_ATTRIBUTES Attr; //PWSTR KeyBuffer = L"\\Registry\\Machine\\Software\\PCIFind\\"; UNICODE_STRING EKey, ValueName; //RtlInitUnicodeString(&EKey, KeyBuffer); RtlInitUnicodeString(&ValueName, Nom); InitializeObjectAttributes(&Attr, &servkey, 0, NULL, NULL); NTSTATUS status = ZwOpenKey(&Key, KEY_QUERY_VALUE, &Attr); if (!NT_SUCCESS(status)) return ; ZwSetValueKey(Key, &ValueName, 0, REG_BINARY, pValue, Len); ZwClose(Key); } /////////////////////////////////////////////////////////////////////////////// #pragma PAGEDCODE NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp) { // DispatchControl PAGED_CODE(); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; if ( pdx->bRealDevice ) { status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp); if (!NT_SUCCESS(status)) return CompleteRequest(Irp, status, 0) ; } ULONG info = 0; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength; ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength; ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; switch (code) { // process request case IOCTL_QUERY_INFO: // code == 0x800 { // IOCTL_QUERY_INFO if ( ! pdx->bRealDevice ) { status = STATUS_OBJECT_TYPE_MISMATCH; break; } if (cbout < sizeof(TCARDINFO)) { status = STATUS_INVALID_PARAMETER; break; } PCARDINFO CIBuf = PCARDINFO(Irp->AssociatedIrp.SystemBuffer); CIBuf->DeviceID = pdx->DeviceID; CIBuf->BaseAddress = pdx->UnmappedBase; info = sizeof(TCARDINFO); status = STATUS_SUCCESS; break; } // IOCTL_QUERY_INFO case IOCTL_QUERY_BAR_BASE: // code == 0x801 { // IOCTL_QUERY_BAR_BASE if ( ! pdx->bRealDevice ) { status = STATUS_OBJECT_TYPE_MISMATCH; break; } if (cbout < sizeof(ULONG)) { status = STATUS_INVALID_PARAMETER; break; } PULONG pBuf = PULONG(Irp->AssociatedIrp.SystemBuffer); if ( *pBuf == 2 ) *pBuf = pdx->UnmappedBase; else if ( *pBuf == 3 ) *pBuf = pdx->UnmappedAuxBase; else *pBuf = 0 ; info = sizeof(*pBuf); status = STATUS_SUCCESS; break; } // IOCTL_QUERY_BAR_BASE case IOCTL_PORT_IN: // code == 0x820 { // IOCTL_PORT_IN if ( (cbin < sizeof(TPORTOP)) || cbout < sizeof(TPORTOP) ) { status = STATUS_INVALID_PARAMETER; break; } PPORTOP POBuf = PPORTOP(Irp->AssociatedIrp.SystemBuffer); if ( POBuf->Flags & POF_RELATIVE ) POBuf->Address += (USHORT)pdx->portbase; switch(POBuf->Size) { case 1: POBuf->Data8 = READ_PORT_UCHAR((PUCHAR)(UNATIVE)POBuf->Address); break; case 2: POBuf->Data16 = READ_PORT_USHORT((PUSHORT)(UNATIVE)POBuf->Address); break; case 4: POBuf->Data32 = READ_PORT_ULONG((PULONG)(UNATIVE)POBuf->Address); break; } info = sizeof(TPORTOP); status = STATUS_SUCCESS; break; } // IOCTL_PORT_IN case IOCTL_PORT_OUT: // code == 0x822 { // IOCTL_PORT_OUT if (cbout < sizeof(TPORTOP)) { status = STATUS_INVALID_PARAMETER; break; } PPORTOP POBuf = PPORTOP(Irp->AssociatedIrp.SystemBuffer); if ( POBuf->Flags & POF_RELATIVE ) POBuf->Address += (USHORT)pdx->portbase; switch(POBuf->Size) { case 1: WRITE_PORT_UCHAR((PUCHAR)(UNATIVE)POBuf->Address, (UCHAR)POBuf->Data8); break; case 2: WRITE_PORT_USHORT((PUSHORT)(UNATIVE)POBuf->Address, (USHORT)POBuf->Data16); break; case 4: WRITE_PORT_ULONG((PULONG)(UNATIVE)POBuf->Address, (ULONG)POBuf->Data32); break; } info = 0; status = STATUS_SUCCESS; break; } // IOCTL_PORT_OUT case IOCTL_IRQ_WAIT_BEGIN: // code == 0x810 { // IOCTL_IRQ_WAIT_BEGIN if ( ! pdx->bRealDevice ) { status = STATUS_OBJECT_TYPE_MISMATCH; break; } if (pdx->InterruptRequested) { status = STATUS_INVALID_DEVICE_REQUEST; } else if (pdx->InterruptOccurred) { pdx->InterruptOccurred = FALSE; if ( cbout ) { for ( ULONG I = 0; I < cbout; ++I ) PUCHAR(Irp->AssociatedIrp.SystemBuffer)[I] = READ_PORT_UCHAR((PUCHAR)pdx->portbase + I + (I / 3)); info = cbout; } status = STATUS_SUCCESS; } else { pdx->COSSize = cbout; pdx->PendingIrp = Irp; pdx->HasPendingIrp = TRUE; IoMarkIrpPending(Irp); IoSetCancelRoutine(Irp, IRQGenCancelIrp); pdx->InterruptRequested = TRUE; status = STATUS_PENDING; // do not complete Irp of course } break; } // IOCTL_IRQ_WAIT_BEGIN case IOCTL_IRQ_WAIT_ABORT: // code == 0x812 { if ( ! pdx->bRealDevice ) { status = STATUS_OBJECT_TYPE_MISMATCH; break; } if (!pdx->InterruptRequested) status = STATUS_INVALID_DEVICE_REQUEST; else { pdx->InterruptOccurred = FALSE; pdx->InterruptRequested = FALSE; pdx->HasPendingIrp = FALSE; pdx->PendingIrp->IoStatus.Status = STATUS_CANCELLED; pdx->PendingIrp->IoStatus.Information = 0; IoSetCancelRoutine(pdx->PendingIrp, NULL); IoCompleteRequest(pdx->PendingIrp, IO_SERIAL_INCREMENT); status = STATUS_SUCCESS; } break; } case IOCTL_FORGET_IRP: //code == 0x880 { if ( ! pdx->bRealDevice ) status = STATUS_OBJECT_TYPE_MISMATCH; else if ( ! pdx->InterruptRequested ) status = STATUS_NO_SUCH_FILE; else { pdx->InterruptRequested = FALSE; pdx->HasPendingIrp = FALSE; ForgetIRP(pdx->PendingIrp); pdx->PendingIrp = NULL; status = STATUS_SUCCESS; } break; } case IOCTL_IRQ_POLL: // code == 0x814 { if ( ! pdx->bRealDevice ) { status = STATUS_OBJECT_TYPE_MISMATCH; break; } //if ( InterlockedExchange(PLONG(&(pdx->InterruptOccurred)), 0) ) if ( pdx->InterruptOccurred ) { pdx->InterruptOccurred = 0; status = STATUS_SUCCESS; } else status = STATUS_NO_MORE_FILES ; break; } case IOCTL_GET_BENCH: // code == 0x830 { if ( ! pdx->bRealDevice ) { status = STATUS_OBJECT_TYPE_MISMATCH; break; } if (cbout < 4) { status = STATUS_INVALID_PARAMETER; break; } info = 4; *PULONG(Irp->AssociatedIrp.SystemBuffer) = pdx->Bench; pdx->Bench = 0; status = STATUS_SUCCESS; break; } default: DbgPrint("Unknown IOCTL = %08LX\n", code); status = STATUS_INVALID_DEVICE_REQUEST; break; } // process request if ( pdx->bRealDevice ) IoReleaseRemoveLock(&pdx->RemoveLock, Irp); if (status == STATUS_PENDING) return status; else return CompleteRequest(Irp, status, info); } // DispatchControl /********************************************************************************* * CANCEL IRP **********************************************************************************/ VOID IRQGenCancelIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; Irp->IoStatus.Information = 0; if (Irp == extension->PendingIrp) { extension->HasPendingIrp = FALSE; Irp->IoStatus.Information = 1; } IoReleaseCancelSpinLock( Irp->CancelIrql ); Irp->IoStatus.Status = STATUS_CANCELLED; IoCompleteRequest(Irp, IO_NO_INCREMENT); }