📄 enum.c
字号:
return;
}
//
// Save off the old settings
//
status = Serenum_IoSyncIoctlEx(IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS, TRUE,
FdoData->TopOfStack, &event, &IoStatusBlock,
NULL, 0, &basicSettings,
sizeof(basicSettings));
if (status == STATUS_SUCCESS) {
restoreSettings = TRUE;
} else {
Serenum_IoSyncIoctlEx(IOCTL_SERIAL_GET_TIMEOUTS, FALSE,
FdoData->TopOfStack, &event, &IoStatusBlock,
NULL, 0, &timeouts, sizeof(timeouts));
RtlZeroMemory(&newTimeouts, sizeof(newTimeouts));
Serenum_IoSyncIoctlEx(IOCTL_SERIAL_SET_TIMEOUTS, FALSE,
FdoData->TopOfStack, &event, &IoStatusBlock,
&newTimeouts, sizeof(newTimeouts), NULL, 0);
}
//
// Set DTR - for mice that need to echo DTR back for DSR
//
Serenum_IoSyncIoctl(IOCTL_SERIAL_SET_DTR, FALSE, FdoData->TopOfStack, &event,
&IoStatusBlock);
//
// Set a timer for 200 ms to give time for DTR to propagate through
//
KeInitializeTimer(&timer);
Serenum_Wait(&timer, RtlConvertLongToLargeInteger(-2000000));
//
// Poll DSR
//
status = Serenum_IoSyncIoctlEx(IOCTL_SERIAL_GET_MODEMSTATUS, FALSE,
FdoData->TopOfStack, &event, &IoStatusBlock,
NULL, 0, &bitMask, sizeof(ULONG));
if (!NT_SUCCESS(status)) {
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
("Polling the serial port for DSR failed. FDO: %x\n",
FdoData->Self));
} else {
if (SERIAL_DSR_STATE & bitMask) {
//
// DSR is set - there is a powered PNP device on the serial port
//
if (!FdoData->AttachedPDO) {
Serenum_KdPrint(FdoData, SER_DBG_SS_INFO,
("Device status has changed.\n"));
IoInvalidateDeviceRelations(FdoData->UnderlyingPDO, BusRelations);
}
} else {
//
// DSR isn't set - Check for a legacy mouse
// Set RTS
//
Serenum_IoSyncIoctl(IOCTL_SERIAL_SET_RTS, FALSE, FdoData->TopOfStack,
&event, &IoStatusBlock);
//
// Read one byte from the serial port
//
nActual = 0;
status = Serenum_ReadSerialPort(&ReadBuffer, 1, 200, &nActual,
&IoStatusBlock, FdoData);
if (NT_SUCCESS(status) && nActual) {
//
// Check for 'M' or 'B'! - The only legacy devices we
// dynamically detect are serial mice!
//
if (ReadBuffer == 'M' || ReadBuffer == 'B') {
if (!FdoData->AttachedPDO ||
(FdoData->AttachedPDO && !FdoData->PDOLegacyEnumerated)) {
Serenum_KdPrint(FdoData, SER_DBG_SS_INFO,
("Device status has changed.\n"));
IoInvalidateDeviceRelations(FdoData->UnderlyingPDO,
BusRelations);
}
}
} else if (FdoData->AttachedPDO) {
Serenum_KdPrint(FdoData, SER_DBG_SS_INFO,
("Device status has changed.\n"));
IoInvalidateDeviceRelations(FdoData->UnderlyingPDO, BusRelations);
}
}
}
//
// CLEANUP and then Close
//
if (restoreSettings) {
Serenum_IoSyncIoctlEx(IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS, TRUE,
FdoData->TopOfStack, &event, &IoStatusBlock,
&basicSettings, sizeof(basicSettings), NULL, 0);
} else {
Serenum_IoSyncIoctlEx(IOCTL_SERIAL_SET_TIMEOUTS, FALSE,
FdoData->TopOfStack, &event, &IoStatusBlock,
&timeouts, sizeof(timeouts), NULL, 0);
}
status = Serenum_IoSyncReqWithIrp(Irp, IRP_MJ_CLEANUP, &event,
FdoData->TopOfStack);
if (!NT_SUCCESS(status)) {
Serenum_KdPrint(FdoData, SER_DBG_SS_INFO,
("Failed to cleanup the serial port while polling DSR"
"\n"));
//
// Don't return. Try to close.
//
}
//
// Close the Serial port after everything is done
//
status = Serenum_IoSyncReqWithIrp(Irp, IRP_MJ_CLOSE, &event,
FdoData->TopOfStack);
if (!NT_SUCCESS(status)) {
Serenum_KdPrint(FdoData, SER_DBG_SS_INFO,
("Failed to close the serial port while polling DSR\n"));
//
// Don't return. Still have to set the polling event.
//
}
IoFreeIrp(Irp);
KeSetEvent(&FdoData->PollingEvent, 1, FALSE);
}
void
Serenum_StopPolling(PFDO_DEVICE_DATA FdoData, BOOLEAN PollingLock)
{
UNREFERENCED_PARAMETER(PollingLock);
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Serenum_StopPolling for "
"0x%x\n", FdoData));
//
// Wait for permission to enter
//
KeWaitForSingleObject(&FdoData->PollStateEvent, Executive, KernelMode,
FALSE, NULL);
if (FdoData->Polling == 0) {
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Serenum_StopPolling "
"leaving -- not polling on"
"0x%x\n", FdoData));
KeSetEvent(&FdoData->PollStateEvent, 1, FALSE);
return;
}
KeWaitForSingleObject(&FdoData->PollingEvent, Executive, KernelMode,
FALSE, NULL);
if(!KeCancelTimer( &FdoData->PollingTimer )) {
Serenum_KdPrint (FdoData, SER_DBG_SS_TRACE, ("The timer wasn't in the "
"system queue: %x\n",
FdoData->PollingTimer));
}
FdoData->Polling = 0;
KeSetEvent(&FdoData->PollStateEvent, 1, FALSE);
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Leaving Serenum_StopPolling "
"for 0x%x\n", FdoData));
}
void
Serenum_StartPolling(PFDO_DEVICE_DATA FdoData, BOOLEAN PollingLock)
{
HANDLE keyHandle;
NTSTATUS status;
UNICODE_STRING keyName;
UNREFERENCED_PARAMETER(PollingLock);
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Serenum_StartPolling for "
"0x%x\n", FdoData));
#if 0
//
// Wait for permission to enter
//
KeWaitForSingleObject(&FdoData->PollStateEvent, Executive, KernelMode,
FALSE, NULL);
if (FdoData->Polling != 0) {
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Already polling for "
"0x%x\n", FdoData));
KeSetEvent(&FdoData->PollStateEvent, 1, FALSE);
return;
}
KeInitializeTimerEx(&FdoData->PollingTimer, NotificationTimer);
//
// Open the device registry key and use the symbolic name the PnP
// manager is recommending for us.
//
status = IoOpenDeviceRegistryKey(FdoData->UnderlyingPDO,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_READ, &keyHandle);
if (!NT_SUCCESS(status)) {
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
("IoOpenDeviceRegistryKey failed - %x \n", status));
FdoData->PollingPeriod = 0;
FdoData->Polling = 0;
} else {
status = Serenum_GetRegistryKeyValue(keyHandle, L"PollingPeriod",
sizeof(L"PollingPeriod"),
&FdoData->PollingPeriod,
sizeof(ULONG), NULL);
ZwClose (keyHandle);
if (!NT_SUCCESS(status)) {
Serenum_KdPrint (FdoData, SER_DBG_SS_INFO,
("Failed to get polling period from registry - %x \n",
status));
FdoData->PollingPeriod = 0;
FdoData->Polling = 0;
}
}
if (FdoData->AttachedPDO) {
status = IoOpenDeviceRegistryKey(FdoData->AttachedPDO,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_WRITE, &keyHandle);
if (!NT_SUCCESS(status)) {
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
("IoOpenDeviceRegistryKey failed - %x \n", status));
} else {
RtlInitUnicodeString(&keyName, L"DeviceDetectionTimeout");
//
// Doesn't matter whether this works or not.
//
ZwSetValueKey(keyHandle, &keyName, 0, REG_DWORD,
&FdoData->PollingPeriod, sizeof(ULONG));
ZwClose(keyHandle);
}
}
if (FdoData->PollingPeriod && FdoData->PollingPeriod != (ULONG)-1) {
//
// Start the polling timer
//
if (KeSetTimerEx(&FdoData->PollingTimer,
RtlConvertLongToLargeInteger(-(LONG)
(FdoData->PollingPeriod
* 1000000)),
FdoData->PollingPeriod * 100, &FdoData->DPCPolling)) {
Serenum_KdPrint(FdoData, SER_DBG_SS_INFO,
("The timer was already in the system queue: %x\n",
FdoData->PollingTimer));
}
FdoData->Polling = 1;
KeSetEvent(&FdoData->PollingEvent, 1, FALSE);
}
KeSetEvent(&FdoData->PollStateEvent, 1, FALSE);
#else
FdoData->Polling = 0;
FdoData->PollingPeriod = 0;
#endif
}
NTSTATUS
Serenum_GetRegistryKeyValue(IN HANDLE Handle, IN PWCHAR KeyNameString,
IN ULONG KeyNameStringLength, IN PVOID Data,
IN ULONG DataLength, OUT PULONG ActualLength)
/*++
Routine Description:
Reads a registry key value from an already opened registry key.
Arguments:
Handle Handle to the opened registry key
KeyNameString ANSI string to the desired key
KeyNameStringLength Length of the KeyNameString
Data Buffer to place the key value in
DataLength Length of the data buffer
Return Value:
STATUS_SUCCESS if all works, otherwise status of system call that
went wrong.
--*/
{
UNICODE_STRING keyName;
ULONG length;
PKEY_VALUE_FULL_INFORMATION fullInfo;
NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
RtlInitUnicodeString (&keyName, KeyNameString);
length = sizeof(KEY_VALUE_FULL_INFORMATION) + KeyNameStringLength
+ DataLength;
fullInfo = ExAllocatePool(PagedPool, length);
if (ActualLength != NULL) {
*ActualLength = 0;
}
if (fullInfo) {
ntStatus = ZwQueryValueKey (Handle,
&keyName,
KeyValueFullInformation,
fullInfo,
length,
&length);
if (NT_SUCCESS(ntStatus)) {
//
// If there is enough room in the data buffer, copy the output
//
if (DataLength >= fullInfo->DataLength) {
RtlCopyMemory(Data, ((PUCHAR)fullInfo) + fullInfo->DataOffset,
fullInfo->DataLength);
if (ActualLength != NULL) {
*ActualLength = fullInfo->DataLength;
}
}
}
ExFreePool(fullInfo);
}
if (!NT_SUCCESS(ntStatus) && !NT_ERROR(ntStatus)) {
if (ntStatus == STATUS_BUFFER_OVERFLOW) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
} else {
ntStatus = STATUS_UNSUCCESSFUL;
}
}
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -