📄 phantomeppsrlapi.c
字号:
ucb.m_SoftwareTimerEnabled = TRUE;
// Fix Me:
// The following hardcoded values miraculously work, even without
// setting ExSetTimerResolution. These values are based on a 1024 Hz clock.
if (SoftwareTimerPeriodMs == 1)
{
ucb.m_SoftwareTimerDueTime.QuadPart = 9765;
}
else if (SoftwareTimerPeriodMs == 2)
{
ucb.m_SoftwareTimerDueTime.QuadPart = 19530;
}
else
{
status = STATUS_UNSUCCESSFUL;
goto FINISH;
}
//RtPrintf("Setting software timer: %d\n", ucb.m_SoftwareTimerDueTime.QuadPart);
RtSetTimerRelative(ucb.m_SoftwareTimer, &ucb.m_SoftwareTimerDueTime,NULL);
FINISH:
//KeReleaseSpinLock(&pDeviceExtension->m_SpinLock, restoreIrql);
return status;
}
DWORD EnableTimerEvent(HANDLE hEvent)
{
HANDLE pEventObject = NULL;
DWORD status = STATUS_SUCCESS;
// Don't proceed if the previous timer event has not been disabled
if (ucb.m_SignalEventObject != NULL)
{
//RtPrintf("PHANTOMEPP:utilityEnableTimerEvent: Need to disable previous event first\n");
return STATUS_UNSUCCESSFUL;
}
// First attempt to grab a reference to the requisite object handle
//ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
//status = ObReferenceObjectByHandle(
// hEvent,
// OBJECT_TYPE_ALL_ACCESS,
// NULL,
// KernelMode,
// &pEventObject,
// NULL);
//if (!status)
//{
// //RtPrintf("PHANTOMEPP:utilityEnableTimerEvent: Failed to reference event by handle\n");
// return status;
//}
//if (pEventObject == NULL)
//{
// //RtPrintf("PHANTOMEPP:utilityEnableTimerEvent: Null event object\n");
// return STATUS_UNSUCCESSFUL;
//}
// Now we can raise IRQL and manage the assignment
//KeAcquireSpinLock(&pDeviceExtension->m_SpinLock, &restoreIrql);
// Now assign the new event handle and event object
ucb.m_SignalEventHandle = hEvent;
ucb.m_SignalEventObject = hEvent;
ucb.m_SignalEventCount = 0;
//RtPrintf("Signal event object set\n");
//KeReleaseSpinLock(&pDeviceExtension->m_SpinLock, restoreIrql);
return status;
}
int RTFCNDCL DriverSoftwareTimerDPCRoutine(PVOID unused)
{
//KeAcquireSpinLockAtDpcLevel(&pDeviceExtension->m_SpinLock);
if (ucb.m_SignalEventObject != NULL)
{
////RtPrintf("PHANTOMEPP: set timer event signaled.\n");
RtSetEvent(ucb.m_SignalEventObject);
}
// Increment a running counter of the number of times the event has been signalled
ucb.m_SignalEventCount++;
if (ucb.m_SoftwareTimerEnabled)
{
////RtPrintf("PHANTOMEPP: set next timer event relative.\n");
RtSetTimerRelative(ucb.m_SoftwareTimer,&ucb.m_SoftwareTimerDueTime,NULL);
}
//KeReleaseSpinLockFromDpcLevel(&pDeviceExtension->m_SpinLock);
return STATUS_SUCCESS;
}
DWORD DisableTimerEvent()
{
//KIRQL restoreIrql;
// Now we can raise IRQL and manage the assignment
//KeAcquireSpinLock(&pDeviceExtension->m_SpinLock, &restoreIrql);
// First deference any previous event object
if (ucb.m_SignalEventObject != NULL)
{
//ObDereferenceObject(pDeviceExtension->m_SignalEventObject);
}
// Now clear the event handle and event object
ucb.m_SignalEventHandle = NULL;
ucb.m_SignalEventObject = NULL;
//KeReleaseSpinLock(&pDeviceExtension->m_SpinLock, restoreIrql);
return STATUS_SUCCESS;
}
DWORD DisableSoftwareTimerEvent()
{
//KIRQL restoreIrql;
DWORD Timeout;
LARGE_INTEGER TimeRemaining;
// Now we can raise IRQL and manage the assignment
//KeAcquireSpinLock(&pDeviceExtension->m_SpinLock, &restoreIrql);
if (ucb.m_SoftwareTimerEnabled)
{
ucb.m_SoftwareTimerEnabled = FALSE;
//RtPrintf("PHANTOMEPP: cancel timer.\n");
RtCancelTimer(ucb.m_SoftwareTimer,&TimeRemaining);
// Wait for the timer DPC to finish executing
Timeout = 10000; // 1 ms
RtWaitForSingleObject(ucb.m_SignalEventObject,Timeout);
}
//KeReleaseSpinLock(&pDeviceExtension->m_SpinLock, restoreIrql);
// Complete the disabling process by dereferencing the timer event
return DisableTimerEvent();
}
DWORD EnableInterrupts()
{
DWORD status = STATUS_SUCCESS;
PUCHAR nPortBase = ucb.baseAddress;
if (ucb.m_ParPortInterruptAllocated == TRUE)
{
//RtPrintf("PHANTOMEPP:utilityEnableInterrupts interrupt already allocated\n");
return STATUS_SUCCESS;
}
//RtPrintf("PHANTOMEPP:Connecting interrupt to ParPort\n");
// Make sure that interrupts are allowed by the port. Microsoft disables
// this by default.
status = RegistryEnableInterrupts(&ucb.m_RegistryEnableInterruptsChanged);
if (!status)
{
//RtPrintf("PHANTOMEPP:RegistryEnableInterrupts Failed\n");
goto FINISH;
}
// Connect to the ParPort interrupt line
//.....
// Enable parallel port IRQ via ACK line
WriteControl(nPortBase, ReadControl(nPortBase) | 0x10);
ucb.m_ParPortInterruptAllocated = TRUE;
FINISH:
return status;
}
DWORD DisableInterrupts()
{
DWORD status = STATUS_SUCCESS;
PUCHAR nPortBase = ucb.baseAddress;
if(ucb.m_ParPortInterruptAllocated == TRUE)
{
//RtPrintf("PHANTOMEPP:Disconnect interrupt from ParPort\n");
// Disable parallel port IRQ via ACK line
WriteControl(nPortBase, ReadControl(nPortBase) & ~0x10);
//status = utilityBusIoControl(pDeviceExtension->m_ParPortDeviceObject,
// IOCTL_INTERNAL_PARALLEL_DISCONNECT_INTERRUPT,
// &pDeviceExtension->m_ParPortInterruptServiceRoutine,
// sizeof(pDeviceExtension->m_ParPortInterruptServiceRoutine),
// NULL,
// 0);
if (status == STATUS_SUCCESS)
{
ucb.m_ParPortInterruptAllocated = FALSE;
}
else
{
//RtPrintf("PHANTOMEPP:Unexpected failure in Disconnect Interrupt\n");
}
}
return status;
}
DWORD RegistryEnableInterrupts(BOOLEAN* pWasChanged)
{
DWORD status = STATUS_SUCCESS;
return status;
}
BOOLEAN DriverInterruptServiceRoutine()
{
BOOLEAN interruptHandled = TRUE;
return(interruptHandled);
}
#define COUNTER_TIMEOUT (100)
// Wait for ACK line to go low in the status byte
BOOLEAN HandleInterrupt()
{
int i;
UCHAR status;
PUCHAR nPortBase = ucb.baseAddress;
BOOLEAN bInterruptHandled;
for (i = 0; i < COUNTER_TIMEOUT; i++)
{
status = ReadStatus(nPortBase);
bInterruptHandled = (status & 0x40) == 0;
if (bInterruptHandled)
break;
// Write to the address register to suppress the interrupt line
WriteAddress(nPortBase, 0x0);
}
// If the ACK line failed to be pulled low, set a flag to acknowledge that
// the device was disconnected
if (!bInterruptHandled)
{
//RtPrintf("PHANTOMEPP:Interrupt line not suppressed.\n");
}
// Interrupt was handled by us if the line was taken low (will fail if
// device is not physically connected)
return bInterruptHandled;
}
int RTFCNDCL DriverTimeoutDPCRoutine(PVOID unused)
{
DWORD status;
//RtPrintf("PHANTOMEPP:Software watchdog invoked. Refreshing device(s).\n");
// Update the Phantom using the most recent read/write buffers
status = ReadWritePhantom();
if (status == STATUS_SUCCESS)
{
// Set the timeout callback used for the software watchdog
if (ucb.m_EnableSoftwareWatchdog &&
ucb.m_TimeoutCount < 100)
{
SetWatchdogTimeout();
}
}
else
{
// Failed to update the device, so bail on future attempts
ucb.m_EnableSoftwareWatchdog = FALSE;
}
// Provides notification that the DPC is done executing
RtSetEvent(ucb.m_TimeoutEvent);
return 0;
}
int RTFCNDCL DriverInterruptDPCRoutine(PVOID unused)
{
// Increment a running counter of the number of times the event has been signaled
ucb.m_SignalEventCount++;
if(ucb.m_SignalEventObject != NULL)
{
RtSetEvent(ucb.m_SignalEventObject);
}
return 0;
}
DWORD DriverCloseDispatch()
{
HANDLE hAppEvent;
DWORD status = STATUS_SUCCESS;
//RtPrintf("PHANTOMEPP:CloseHandle() call\n");
// Perform a cleanup pass when the last file handle is closed
if (--ucb.m_nFileCount == 0)
{
// Disable the software watchdog timer, clear the pending watchdog timeout
// and wait for the DPC to be flushed out
ucb.m_EnableSoftwareWatchdog = FALSE;
ClearWatchdogTimeout(TRUE);
// Make sure that timer events are disabled
if (ucb.m_SoftwareTimerEnabled)
{
status = DisableSoftwareTimerEvent();
}
else
{
status = DisableTimerEvent();
if (status == STATUS_SUCCESS)
{
status = DisableInterrupts();
}
}
// Make sure the ParPort is freed
if (status == STATUS_SUCCESS)
{
status = FreeParPort();
}
}
// Delete the timer and event
RtResetEvent(ucb.m_TimeoutEvent);
// Reset the app event
hAppEvent = RtdDriverGetEvent(hDriver);
RtResetEvent(hAppEvent);
//IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return(status);
}
DWORD FreeParPort()
{
DWORD status = STATUS_SUCCESS;
// Finally release the ParPort
if (ucb.m_ParPortAllocated == TRUE)
{
//RtPrintf("PHANTOMEPP:Freeing ParPort\n");
//status = utilityBusIoControl(pDeviceExtension->m_ParPortDeviceObject,
// IOCTL_INTERNAL_PARALLEL_PORT_FREE,
// NULL,
// 0,
// NULL,
// 0);
//if (!NT_SUCCESS (status))
//{
// utilityLogError(pDeviceExtension->m_DeviceObject,
// PHANTOMEPP_PARALLEL_PORT_FREE_FAILED,
// PHANTOMEPP_ERROR_VALUE_BASE + 130,
// status,
// NULL, 0);
// KdPrint("PHANTOMEPP:Unexpected failure in Free Parallel Port\n"));
//}
ucb.m_ParPortAllocated = FALSE;
}
return status;
}
VOID DriverUnload()
{
//DWORD status;
//WCHAR IndexBuffer[8];
//WCHAR Win32DeviceBuffer[DEVICE_NAME_BUFFER_SIZE];
//UNICODE_STRING uniIndex = {0, sizeof(IndexBuffer)/sizeof(WCHAR), IndexBuffer};
//UNICODE_STRING uniWin32Device = {0, sizeof(Win32DeviceBuffer)/sizeof(WCHAR), Win32DeviceBuffer};
//CurrentDevice = pDriverObject->DeviceObject;
//while( CurrentDevice )
{
//pDeviceExtension = CurrentDevice->DeviceExtension;
//RtPrintf("PHANTOMEPP:Unloading Device %d, DeviceObject %x.\n",ucb.m_DeviceIndex);
// Disable the event timer if it's still being used
if (ucb.m_SoftwareTimerEnabled)
{
DisableSoftwareTimerEvent();
}
else
{
DisableTimerEvent();
DisableInterrupts();
}
// Disable the software watchdog timer, clear the pending watchdog timeout
// and wait for the DPC to be flushed out
ucb.m_EnableSoftwareWatchdog = FALSE;
ClearWatchdogTimeout(TRUE);
// Make sure the ParPort is freed
FreeParPort();
// Convert Device Index to Unicode String
//uniIndex.Length = 0;
//uniWin32Device.Length = 0;
//RtlIntegerToUnicodeString(pDeviceExtension->m_DeviceIndex, 10, &uniIndex);
//RtlAppendUnicodeToString(&uniWin32Device, WIN32_DEVICE_NAME);
//RtlAppendUnicodeStringToString(&uniWin32Device, &uniIndex);
//RtPrintf("PHANTOMEPP:Delete symbolic link.\n");
//IoDeleteSymbolicLink (&uniWin32Device);
//IoDeleteDevice(CurrentDevice);
//CurrentDevice = pDriverObject->DeviceObject;
}
}
DWORD DriverShutdown(PTRP Irp)
{
// Delete the timer and event
RtDeleteTimer(ucb.m_SoftwareTimer);
RtDeleteTimer(ucb.m_TimeoutTimer);
RtCloseHandle(ucb.m_TimeoutEvent);
ucb.m_SoftwareTimer = NULL;
ucb.m_TimeoutTimer = NULL;
ucb.m_TimeoutEvent = NULL;
//IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -