📄 enum.c
字号:
sizeof(PDO_DEVICE_DATA), &pdoUniName,
FILE_DEVICE_UNKNOWN,
FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &pdo);
if (!NT_SUCCESS(status)) {
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Create device failed\n"));
Irp->AssociatedIrp.SystemBuffer = stack->Parameters.Others.Argument1;
return status;
}
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
("Created PDO on top of filter: %x\n",pdo));
pdoData = pdo->DeviceExtension;
//
// Initialize the rest of the device object
//
// Set this to potential, not found, since this is used for dynamic
// detection using the DSR bit. There could be a broken pnp device
// attached that isn't able to set DSR.
//
FdoData->PDOLegacyEnumerated = legacyPotential;
//
// Copy our temp buffers over to the DevExt
//
pdoData->HardwareIDs = HardwareIDs;
pdoData->CompIDs = CompIDs;
pdoData->DeviceIDs = DeviceIDs;
pdoData->DevDesc = DevDesc;
Serenum_InitPDO(pdo, FdoData);
}
// TODO: Poll
ExitReenumerate:;
stack = IoGetCurrentIrpStackLocation(Irp);
Irp->AssociatedIrp.SystemBuffer = stack->Parameters.Others.Argument1;
return STATUS_SUCCESS;
}
void
Serenum_PDO_EnumMarkMissing(PFDO_DEVICE_DATA FdoData, PPDO_DEVICE_DATA PdoData)
/*++
Routine Description:
Removes the attached pdo from the fdo's list of children.
NOTE: THIS FUNCTION CAN ONLY BE CALLED DURING AN ENUMERATION. If called
outside of enumeration, Serenum might delete it's PDO before PnP has
been told the PDO is gone.
Arguments:
FdoData - Pointer to the fdo's device extension
PdoData - Pointer to the pdo's device extension
Return value:
none
--*/
{
Serenum_KdPrint (FdoData, SER_DBG_SS_TRACE, ("Removing Pdo %x\n",
PdoData->Self));
ASSERT(PdoData->Attached);
PdoData->Attached = FALSE;
FdoData->AttachedPDO = NULL;
FdoData->PdoData = NULL;
FdoData->NumPDOs = 0;
FdoData->PDOForcedRemove = FALSE;
}
NTSTATUS
Serenum_IoSyncReqWithIrp(PIRP PIrp, UCHAR MajorFunction, PKEVENT PEvent,
PDEVICE_OBJECT PDevObj )
/*++
Routine Description:
Performs a synchronous IO request by waiting on the event object
passed to it. The IRP isn't deallocated after this call.
Arguments:
PIrp - The IRP to be used for this request
MajorFunction - The major function
PEvent - An event used to wait for the IRP
PDevObj - The object that we're performing the IO request upon
Return value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION stack;
NTSTATUS status;
stack = IoGetNextIrpStackLocation(PIrp);
stack->MajorFunction = MajorFunction;
KeClearEvent(PEvent);
IoSetCompletionRoutine(PIrp, Serenum_EnumComplete, PEvent, TRUE,
TRUE, TRUE);
status = Serenum_IoSyncReq(PDevObj, PIrp, PEvent);
if (status == STATUS_SUCCESS) {
status = PIrp->IoStatus.Status;
}
return status;
}
NTSTATUS
Serenum_IoSyncIoctlEx(ULONG Ioctl, BOOLEAN Internal, PDEVICE_OBJECT PDevObj,
PKEVENT PEvent, PIO_STATUS_BLOCK PIoStatusBlock,
PVOID PInBuffer, ULONG InBufferLen, PVOID POutBuffer, // output buffer - optional
ULONG OutBufferLen)
/*++
Routine Description:
Performs a synchronous IO control request by waiting on the event object
passed to it. The IRP is deallocated by the IO system when finished.
Return value:
NTSTATUS
--*/
{
PIRP pIrp;
NTSTATUS status;
KeClearEvent(PEvent);
// Allocate an IRP - No need to release
// When the next-lower driver completes this IRP, the IO Mgr releases it.
pIrp = IoBuildDeviceIoControlRequest(Ioctl, PDevObj, PInBuffer, InBufferLen,
POutBuffer, OutBufferLen, Internal,
PEvent, PIoStatusBlock);
if (pIrp == NULL) {
Serenum_KdPrint_Def (SER_DBG_SS_ERROR, ("Failed to allocate IRP\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
status = Serenum_IoSyncReq(PDevObj, pIrp, PEvent);
if (status == STATUS_SUCCESS) {
status = PIoStatusBlock->Status;
}
return status;
}
NTSTATUS
Serenum_IoSyncReq(PDEVICE_OBJECT PDevObj, IN PIRP PIrp, PKEVENT PEvent)
/*++
Routine Description:
Performs a synchronous IO request by waiting on the event object
passed to it. The IRP is deallocated by the IO system when finished.
Return value:
NTSTATUS
--*/
{
NTSTATUS status;
status = IoCallDriver(PDevObj, PIrp);
if (status == STATUS_PENDING) {
// wait for it...
status = KeWaitForSingleObject(PEvent, Executive, KernelMode, FALSE,
NULL);
}
return status;
}
NTSTATUS
Serenum_Wait(IN PKTIMER Timer, IN LARGE_INTEGER DueTime)
/*++
Routine Description:
Performs a wait for the specified time.
NB: Negative time is relative to the current time. Positive time
represents an absolute time to wait until.
Return value:
NTSTATUS
--*/
{
if (KeSetTimer(Timer, DueTime, NULL)) {
Serenum_KdPrint_Def(SER_DBG_SS_INFO, ("Timer already set: %x\n", Timer));
}
return KeWaitForSingleObject(Timer, Executive, KernelMode, FALSE, NULL);
}
NTSTATUS
Serenum_EnumComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
A completion routine for use when calling the lower device objects to
which our bus (FDO) is attached. It sets the event for the synchronous
calls done.
--*/
{
UNREFERENCED_PARAMETER (DeviceObject);
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
KeSetEvent ((PKEVENT) Context, 1, FALSE);
// No special priority
// No Wait
return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
}
NTSTATUS
Serenum_ReadSerialPort(OUT PCHAR PReadBuffer, IN USHORT Buflen,
IN ULONG Timeout, OUT PUSHORT nActual,
OUT PIO_STATUS_BLOCK PIoStatusBlock,
IN const PFDO_DEVICE_DATA FdoData)
{
NTSTATUS status;
PIRP pIrp;
LARGE_INTEGER startingOffset = RtlConvertLongToLargeInteger(0);
KEVENT event;
SERIAL_TIMEOUTS timeouts;
IO_STATUS_BLOCK statusBlock;
ULONG i;
//
// Set the proper timeouts for the read
//
timeouts.ReadIntervalTimeout = MAXULONG;
timeouts.ReadTotalTimeoutMultiplier = MAXULONG;
timeouts.ReadTotalTimeoutConstant = Timeout;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
KeInitializeEvent(&event, NotificationEvent, FALSE);
status = Serenum_IoSyncIoctlEx(IOCTL_SERIAL_SET_TIMEOUTS, FALSE,
FdoData->TopOfStack, &event, &statusBlock,
&timeouts, sizeof(timeouts), NULL, 0);
if (!NT_SUCCESS(status)) {
return status;
}
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Read pending...\n"));
*nActual = 0;
while (*nActual < Buflen) {
KeClearEvent(&event);
pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, FdoData->TopOfStack,
PReadBuffer, 1, &startingOffset,
&event, PIoStatusBlock);
if (pIrp == NULL) {
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Failed to allocate IRP"
"\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(FdoData->TopOfStack, pIrp);
if (status == STATUS_PENDING) {
//
// Wait for the IRP
//
status = KeWaitForSingleObject(&event, Executive, KernelMode,
FALSE, NULL);
if (status == STATUS_SUCCESS) {
status = PIoStatusBlock->Status;
}
}
if (!NT_SUCCESS(status) || status == STATUS_TIMEOUT) {
Serenum_KdPrint (FdoData, SER_DBG_SS_ERROR,
("IO Call failed with status %x\n", status));
return status;
}
*nActual += (USHORT)PIoStatusBlock->Information;
PReadBuffer += (USHORT)PIoStatusBlock->Information;
}
return status;
}
void
Serenum_PollingTimerRoutine (IN PKDPC Dpc, IN PFDO_DEVICE_DATA FdoData,
IN PVOID SystemArgument1, IN PVOID SystemArgument2)
{
UNREFERENCED_PARAMETER (Dpc);
UNREFERENCED_PARAMETER (SystemArgument1);
UNREFERENCED_PARAMETER (SystemArgument2);
//
// Make sure we are allowed to poll
//
if (KeResetEvent(&FdoData->PollingEvent) == 0) {
return;
}
IoQueueWorkItem(FdoData->PollingWorker,
(PIO_WORKITEM_ROUTINE)Serenum_PollingRoutine,
DelayedWorkQueue, FdoData);
}
void
Serenum_PollingRoutine(PDEVICE_OBJECT PDevObj, PFDO_DEVICE_DATA FdoData)
{
ULONG bitMask;
KEVENT event;
KTIMER timer;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS status;
PIRP Irp;
CHAR ReadBuffer = '\0';
USHORT nActual = 0;
SERIAL_BASIC_SETTINGS basicSettings;
BOOLEAN restoreSettings = FALSE;
SERIAL_TIMEOUTS timeouts, newTimeouts;
UNREFERENCED_PARAMETER(PDevObj);
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Serenum_PollingRoutine for "
"0x%x\n", FdoData));
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Open the serial port before doing anything
//
if (NULL == (Irp = IoAllocateIrp(FdoData->Self->StackSize, FALSE))) {
Serenum_KdPrint (FdoData, SER_DBG_SS_ERROR, ("Failed to allocate IRP\n"));
KeSetEvent(&FdoData->PollingEvent, 1, FALSE);
return;
}
Irp->UserIosb = &IoStatusBlock;
status = Serenum_IoSyncReqWithIrp(Irp, IRP_MJ_CREATE, &event,
FdoData->TopOfStack);
if (!NT_SUCCESS(status)) {
Serenum_KdPrint (FdoData, SER_DBG_SS_INFO,
("Failed to open the serial port while polling DSR\n"));
IoFreeIrp(Irp);
KeSetEvent(&FdoData->PollingEvent, 1, FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -