📄 usbfx2lk_pnp.cpp
字号:
// result of receiving the QUERY_STOP IRP). After all in-
// progress requests are complete, we return our resources
// and wait for further instructions from the PnP Manager (
// which better include a START_DEVICE someplace down the line!).
//
// While in this state, any IRPs we receive will be queued
// for processing until we get A START_DEVICE.
//
case (STATE_STOP_PENDING + IRP_MN_STOP_DEVICE): {
//
// We're stopped...
//
OsrUpdateDeviceState(devExt, STATE_STOPPED);
//
// We need to cancel our outstanding wait wake operation if there
// is one
//
if(devExt->WaitWakeEnable) {
CancelWaitWake(devExt);
}
//
// Return any allocated resources...
//
OsrReturnResources(devExt);
//
// Indicate that we've successfully processed the IRP.
// Note that we can't fail it (we agreed to the
// stop in the QUERY_STOP case)...
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// Don't wait for the Irp to finish, don't set a completion
// routine and don't complete the Irp! Just foist it off to the
// PDO and propogate the returned status
//
IoSkipCurrentIrpStackLocation(Irp);
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_PNP_INFO,
("OsrPnp: Finished! Leaving with state %s\n",
OsrPrintState(devExt)));
status = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
return status;
}
//
// STATE: STARTED
// IRP_MN: _QUERY_REMOVE
//
// We're here because the PnP Manager wants to "nicely"
// remove our device. This is the orderly way the PnP Manager
// handles device disconnections (as opposed to doing a
// SURPRISE_REMOVAL).
//
// If we decide it's OK to remove the device, what we do here
// is (a) change the state of the device such that newly arriving
// requests will be rejected, (b) stall the queues so no new I/O
// with be started and wait for all in progress I/O to complete on
// the device, and (c) pass the request on down.
//
case (STATE_STARTED + IRP_MN_QUERY_REMOVE_DEVICE): {
//
// WE process this request FIRST
//
//
// See if we're OK with removing the device at this point.
// We do NOT actually RETURN the resources here... we
// just affirm or deny that we're OK with returning them.
//
status = OsrCanRemoveDevice(devExt, Irp);
if (!NT_SUCCESS(status)) {
//
// Nope...We can't remove the device
// so there's no need to pass it
// down to see if anyone else can remove.
// Just complete the Irp and return...
//
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_PNP_INFO,
("OsrPnp: Finished! Leaving with state %s\n",
OsrPrintState(devExt)));
return status;
}
//
// We're cool with being removed...
//
//
// We handle this request before the bus driver
//
//
// Power the device up if it isn't already.
// Do this before changing the device's
// PnP state.
//
SSPowerDeviceIfSuspended(devExt);
//
// If enabled, disable selective suspend. We'll
// enable again if we get a cancel
//
DisableSelectiveSuspend(devExt);
//
// Set new state -- This state results in any new
// requests received at our dispath entry points
// being QUEUED
//
OsrUpdateDeviceState(devExt, STATE_REMOVE_PENDING);
//
// Wait for any in progress I/O to finish.
// Note that even though this is called
// OsrWaitForStop, it is the right function
// to call here because it waits for any
// in progress I/O to finish, but having
// I/O in the queues is fine. This is what
// we want since we might get a CANCEL_REMOVE,
// in which case we'll go back and process any
// queued up requests...
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrWaitForStop(devExt);
//
// Replace status code that's in the IRP to indicate our
// opinion about stopping the device. If we're
// OK with being removed this HAS to be
// STATUS_SUCCESS.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// Pass this request on down to the next driver
//
IoSkipCurrentIrpStackLocation(Irp);
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_PNP_INFO,
("OsrPnp: Finished! Leaving with state %s\n",
OsrPrintState(devExt)));
status = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp);
//
// We're done with this request
//
return status;
}
//
// STATE: REMOVE_PENDING
// IRP_MN: _CANCEL_REMOVE_DEVICE
//
// We're here because we've already received a QUERY_REMOVE,
// that we've agreed to. We've completed any pending I/O
// requests. Now we've received a CANCEL_REMOVE_DEVICE
// IRP, that sort of says "never mind" about that remove.
//
// We (hopefully) restart our queues and return to the Started
// state
//
case (STATE_REMOVE_PENDING + IRP_MN_CANCEL_REMOVE_DEVICE): {
//
// This is a BUS FIRST Irp.
//
status = OsrForwardIrpSynchronous(devExt,Irp);
if (NT_SUCCESS(status)) {
//
// We're now back to a STARTED state
//
OsrUpdateDeviceState(devExt, STATE_STARTED);
//
// Go and start any I/O that may have been
// queued while in the REMOVE_PENDING
// state...
//
OsrProcessQueuedRequests(devExt);
} else {
//
// If we're here one of the drivers below us is
// busted, you can never fail this Irp. We'll just
// stay right where we are and break into a debugger
// if possible
//
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("OsrPnp: Lower level device FAILED CANCEL_REMOVE?? Returned status 0x%8.8x (%s)\n",
Irp->IoStatus.Status, OsrNtStatusToString(Irp->IoStatus.Status)));
//
// Use KdBreakPoint instead of DbgBreakPoint so that
// we only break in the checked build...
//
KdBreakPoint();
}
//
// Enable selective suspend again (if enabled)
//
EnableSelectiveSuspend(devExt);
//
// Complete the Irp with whatever status the lower driver returned
//
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
//
// OsrForwardIrpSynchronous is just a nice little
// wrapper that sets a completion routine, calls
// the next lowest driver, waits, and then reclaims the Irp
// for us in the completion routine by returning
// STATUS_MORE_PROCESSING_REQUIRED (or calls
// IoForwardIrpSynchronously to do all of that if
// we're built for XP and later). Just as if we
// had carried these steps out by ourselves, we now
// own the Irp and need to call IoCompleteRequest on it
// to finish processing.
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_PNP_INFO,
("OsrPnp: Finished! Leaving with state %s\n",
OsrPrintState(devExt)));
return status;
}
//
// STATE: STOPPED, STARTED, _STOP_PENDING, or _REMOVE_PENDING
// IRP_MN: _SURPRISE_REMOVAL
//
// We're here when the device is forcibly removed. The PnP
// Manager will send us a remove device IRP when all open handles
// are close and when we're supposed to actually detach and
// delete the device object
//
case (STATE_STARTED + IRP_MN_SURPRISE_REMOVAL):
case (STATE_STOPPED + IRP_MN_SURPRISE_REMOVAL):
case (STATE_STOP_PENDING + IRP_MN_SURPRISE_REMOVAL):
case (STATE_REMOVE_PENDING + IRP_MN_SURPRISE_REMOVAL): {
//
// A surprise removed device must still handle subsequent
// close, clean-up, power and PnP requests. A removed device
// handles NO subsequent requests
//
//
// Power the device up if it isn't already.
// Do this before changing the device's
// PnP state.
//
// Though the device doesn't exist anymore, we're
// doing this to indicate to the hub that it
// should power the port that the device
// was plugged into.
//
SSPowerDeviceIfSuspended(devExt);
//
// If enabled, disable selective suspend
//
DisableSelectiveSuspend(devExt);
//
// Update our Device State
//
OsrUpdateDeviceState(devExt, STATE_SURPRISE_REMOVED);
//
// Because we registered a device interface we need to disable
// it now...
//
status = IoSetDeviceInterfaceState(&devExt->InterfaceName,
FALSE);
if (!NT_SUCCESS(status)) {
//
// Eh, big deal. Just print out some info and
// keep going...
//
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("OsrPnp: IoSetDeviceInterfaceState failed! Returned status 0x%8.8x (%s)\n",
status, OsrNtStatusToString(status)));
}
//
// Fail any queued I/O requests...
//
OsrClearQueues(devExt);
//
// Tell the thread that we have out there to terminate itself
//
KeSetEvent(&devExt->SSSubmissionThreadTerminateEvent,
EVENT_INCREMENT, FALSE);
//
// And wait for the thread to terminate
//
(VOID)OsrWaitForSingleObject(devExt->SSSubmissionThreadObject);
//
// Close the HANDLE that we opened to the thread
//
ZwClose(devExt->SSSubmissionThread);
//
// And drop our reference to the object
//
ObDereferenceObject(devExt->SSSubmissionThreadObject);
//
// We need to cancel our outstanding wait wake operation if there
// is one
//
if(devExt->WaitWakeEnable) {
CancelWaitWake(devExt);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -