📄 pnp.c
字号:
//
if (!IoCancelIrp(DeviceExtension->ReadIrp)) {
//
// Wait for the read irp to complete
//
Print(DeviceExtension, DBG_PNP_INFO, ("Waiting for stop event\n"));
KeWaitForSingleObject(&DeviceExtension->StopEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Print(DeviceExtension, DBG_PNP_INFO, ("Done waiting for stop event\n"));
}
}
}
NTSTATUS
SerialMousePnP (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these this filter driver will completely ignore.
In all cases it must pass on the IRP to the lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION stack;
HANDLE keyHandle;
NTSTATUS status;
KIRQL oldIrql;
BOOLEAN skipIt = FALSE;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
stack = IoGetCurrentIrpStackLocation(Irp);
status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS(status)) {
//
// Someone gave us a pnp irp after a remove. Unthinkable!
//
ASSERT(FALSE);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
Print(deviceExtension, DBG_PNP_TRACE,
("PnP Enter (min func=0x%x)\n", stack->MinorFunction));
switch (stack->MinorFunction) {
case IRP_MN_START_DEVICE:
//
// Send the actual start down the stack
//
status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
Irp,
TRUE);
if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
PIO_STACK_LOCATION nextStack;
//
// If a create has not been sent down the stack yet, then send one
// now. The serial port driver reequires a create before
// any reads or IOCTLS are to be sent.
//
if (InterlockedIncrement(&deviceExtension->EnableCount) == 1) {
NTSTATUS prevStatus;
ULONG_PTR prevInformation;
//
// No previous create has been sent, send one now
//
prevStatus = Irp->IoStatus.Status;
prevInformation = Irp->IoStatus.Information;
nextStack = IoGetNextIrpStackLocation (Irp);
RtlZeroMemory(nextStack, sizeof(IO_STACK_LOCATION));
nextStack->MajorFunction = IRP_MJ_CREATE;
status =
SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
Irp,
FALSE);
Print(deviceExtension, DBG_PNP_NOISE,
("Create for start 0x%x\n", status));
if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
Irp->IoStatus.Status = prevStatus;
Irp->IoStatus.Information = prevInformation;
}
else {
Print(deviceExtension, DBG_CC_ERROR | DBG_PNP_ERROR,
("Create for start failed, 0x%x!\n", status));
goto SerialMouseStartFinished;
}
}
//
// Open the device registry key and read the devnode stored values
//
status = IoOpenDeviceRegistryKey(deviceExtension->PDO,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_READ,
&keyHandle);
if (NT_SUCCESS(status)) {
SerialMouseServiceParameters(deviceExtension, keyHandle);
ZwClose(keyHandle);
}
//
// Handle the transition from start to stop to start correctly
//
SerialMouseHandleStartStopStart(deviceExtension);
//
// Initialize the device to make sure we can start it and report
// data from it
//
status = SerialMouseInitializeDevice(deviceExtension);
Print(deviceExtension, DBG_PNP_INFO,
("Start InitializeDevice 0x%x\n", status));
if (InterlockedDecrement(&deviceExtension->EnableCount) == 0) {
//
// We will start the read loop when we receive a "real" create
// from the raw input thread. We do not keep our own create
// around after the start device because it will mess up the
// logic for handling QUERY_REMOVE (our "fake" create will still
// be in effect and the QUERY_REMOVE will fail).
//
Print(deviceExtension, DBG_PNP_NOISE,
("sending close for start\n"));
SerialMouseClosePort(deviceExtension, Irp);
}
else {
//
// We already have an outstanding create, just spin up the read
// loop again
//
ASSERT(deviceExtension->EnableCount >= 1);
Print(deviceExtension, DBG_PNP_INFO,
("spinning up read in start\n"));
status = SerialMouseSpinUpRead(deviceExtension);
}
}
SerialMouseStartFinished:
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_STOP_DEVICE:
//
// After the start IRP has been sent to the lower driver object, the
// bus may NOT send any more IRPS down ``touch'' until another START
// has occured.
// What ever access is required must be done before the Irp is passed
// on.
//
SerialMouseStopDevice(deviceExtension);
//
// We don't need a completion routine so fire and forget.
//
skipIt = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
SerialMouseRemoveDevice(deviceExtension, Irp);
skipIt = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
//
// The PlugPlay system has dictacted the removal of this device. We
// have no choise but to detach and delete the device objecct.
// (If we wanted to express and interest in preventing this removal,
// we should have filtered the query remove and query stop routines.)
//
// Note! we might receive a remove WITHOUT first receiving a stop.
//
Print(deviceExtension, DBG_PNP_TRACE, ("enter RemoveDevice \n"));
deviceExtension->Removed = TRUE;
SerialMouseRemoveDevice(deviceExtension, Irp);
//
// Send on the remove IRP
//
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceExtension->TopOfStack, Irp);
//
// Wait for the remove lock to free.
//
IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);
//
// Free the associated memory.
//
IoFreeIrp(deviceExtension->ReadIrp);
deviceExtension->ReadIrp = NULL;
if (deviceExtension->DetectionIrp) {
IoFreeIrp(deviceExtension->DetectionIrp);
deviceExtension->DetectionIrp = NULL;
}
Print(deviceExtension, DBG_PNP_NOISE, ("remove and wait done\n"));
IoDetachDevice(deviceExtension->TopOfStack);
IoDeleteDevice(deviceExtension->Self);
return status;
case IRP_MN_QUERY_CAPABILITIES:
status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
Irp,
TRUE);
if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
PDEVICE_CAPABILITIES devCaps;
devCaps = stack->Parameters.DeviceCapabilities.Capabilities;
if (devCaps) {
SYSTEM_POWER_STATE i;
//
// We do not want to show up in the hot plug removal applet
//
devCaps->SurpriseRemovalOK = TRUE;
//
// While the underlying serial bus might be able to wake the
// machine from low power (via wake on ring), the mouse cannot.
//
devCaps->SystemWake = PowerSystemUnspecified;
devCaps->DeviceWake = PowerDeviceUnspecified;
devCaps->WakeFromD0 =
devCaps->WakeFromD1 =
devCaps->WakeFromD2 =
devCaps->WakeFromD3 = FALSE;
devCaps->DeviceState[PowerSystemWorking] = PowerDeviceD0;
for (i = PowerSystemSleeping1; i < PowerSystemMaximum; i++) {
devCaps->DeviceState[i] = PowerDeviceD3;
}
}
}
//
// status, Irp->IoStatus.Status set above
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_PNP_DEVICE_STATE:
status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
Irp,
TRUE);
//
// If the lower filter does not support this Irp, this is
// OK, we can ignore this error
//
if (status == STATUS_NOT_SUPPORTED ||
status == STATUS_INVALID_DEVICE_REQUEST) {
status = STATUS_SUCCESS;
}
if (NT_SUCCESS(status) && deviceExtension->RemovalDetected) {
(PNP_DEVICE_STATE) Irp->IoStatus.Information |= PNP_DEVICE_REMOVED;
}
if (!NT_SUCCESS(status)) {
Print(deviceExtension, DBG_PNP_ERROR,
("error pending query pnp device state event (0x%x)\n",
status
));
}
//
// Irp->IoStatus.Information will contain the new i/o resource
// requirements list so leave it alone
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -