📄 ul_wdpnp.c
字号:
// do not have a set of hardware resources from the PnP Manager. // // The PnP Manager is now giving us a set of resources, and // asking us to start the device. // // In this case, we pass the IRP all the way down. When it's // done (and our completion routine is called) we can then // read the list of device resources pointed to in the IRP // Stack Location. // case STATE_STOPPED + IRP_MN_START_DEVICE: case STATE_NEVER_STARTED + IRP_MN_START_DEVICE: uLan_DbgPrint("uLan: DispatchPnp: PROCESSING START_DEVICE\n"); // // The BUS DRIVER handles this IRP before we do // IoCopyCurrentIrpStackLocationToNext(Irp); // // Call PnpComplete() when this IRP is done... // IoSetCompletionRoutine(Irp, PnpComplete, &eventWaitLowerDrivers, TRUE, TRUE, TRUE); // // Send the IRP to the bus driver. Let's see what HE // thinks. // code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp); if (STATUS_PENDING == code) { KeWaitForSingleObject(&eventWaitLowerDrivers, Executive, KernelMode, FALSE, NULL); code = Irp->IoStatus.Status; } // // Can the bus driver do the start? // if (NT_SUCCESS (code)) { // // Yup. Go initialize the device. The CmResourceLists // are pointed to by the IoStackLocation. // // uld_debug_flg|=4; code = StartDevice(devExt, ioStackLocation); // // If the our StartDevice function succeeded, the // device is now "officially" started! // if(NT_SUCCESS(code)) { devExt->State = STATE_STARTED; } } else { // // The bus driver has declined to start the device. // Oh well... //#if DBG uLan_DbgPrint("uLan: DispatchPnp: IoCallDriver() for START fails! 0x%0x \n", code);#endif } // // We must now complete the IRP, since we stopped it in the // completetion routine with MORE_PROCESSING_REQUIRED. // Irp->IoStatus.Status = code; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); break; // // STATE: STARTED // IRP_MN: _QUERY_REMOVE // // We're here because we're running, and the PnP Manager wants // to "nicely" remove our device. This is the orderly way // PnP Manager handles device disconnections (as opposed to // doing a SURPRISE_REMOVAL). // // What we do here is (a) change the state of the device such // that newly arriving requests will be rejected, (b) wait for // all requests to complete on the device, and (c) pass the // request on down. // case STATE_STARTED + IRP_MN_QUERY_REMOVE_DEVICE:#if DBG uLan_DbgPrint("uLan: DispatchPnp: PROCESSING QUERY_REMOVE_DEVICE\n");#endif // // 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. // code = CanRemoveDevice(devExt, Irp); // // Replace status code that's in the IRP to indicate our // opinion about stopping the device. If we're // OK with returning the resources, this will be // STATUS_SUCCESS. // Irp->IoStatus.Status = code; if(!NT_SUCCESS(code)) { // // NOPE. Can't remove the device because, for some // reason (perhaps because we can't return our // resources). Too bad. Tell the PnP Manager that // stopping right now is not an option for us. // // NOTE: NO NEED to pass IRP down if WE can't stop // it doesn't matter if the Bus Driver can. // IoCompleteRequest(Irp, IO_NO_INCREMENT); } else { #if DBG uLan_DbgPrint("uLan: DispatchPnp: Waiting for pending requests to complete. (%d. remain)\n", devExt->OutstandingIO);#endif // // Set new state -- This state results in any new // requests received at our dispatch entry points // being REJECTED... any request still on the queues // are allowed to complete, however. // devExt->State = STATE_REMOVE_PENDING; // // Decrement our reference on the device here, and then // wait until there are no requests active or on the // device's queues. // RequestDecrement(devExt); WaitForRemove(devExt); // // OK. No further requests remain. Let the bus driver // know. // // DECREMENTED REQUEST COUNT above. Return immediately // below. //#if DBG uLan_DbgPrint("uLan: DispatchPnp: Leaving With state: "); PrintState(devExt); uLan_DbgPrint("\n");#endif // // Pass this request on down to the bus driver // IoSkipCurrentIrpStackLocation(Irp); return(IoCallDriver(devExt->DeviceToSendIrpsTo, Irp)); } break; // // STATE: REMOVE_PENDING // IRP_MN: _REMOVE_DEVICE // // We're here because we've previously received notification // of the intention to remove the device in an orderly way. // We return our resources here, and then tear down our device // object. Note that there can be no requests pending at this // point, because we finished them all during QUERY_REMOVE // processing (before entering RemovePending state) // case STATE_REMOVE_PENDING + IRP_MN_REMOVE_DEVICE: // // All queued and active IRPs are complete at this point. // // // Fall through... // // // STATE: SURPRISE_REMOVED // IRP_MN: _REMOVE_DEVICE // // We're here because we've previously received notification // of a "surprise" removal. At this point, we just tear down // our device object // case STATE_SURPRISE_REMOVED + IRP_MN_REMOVE_DEVICE: // // Removing the device at this point is NOT optional. // #if DBG uLan_DbgPrint("uLan: DispatchPnp: REMOVE_DEVICE\n"); #endif // // Device has been removed // devExt->State = STATE_REMOVED; // // Return any resources we're using. // ReturnResources(devExt); // // Decrement our reference on the device here, and then // wait until we can remove the device. Because we would // have gotten a prior warning of this removal (via an // IRP_MN_SUPRISE_REMOVAL or an IRP_MN_QUERY_REMOVE) and // at that time transitioned state appropriately, there // should be no requests outstanding here. // RequestDecrement(devExt); #if DBG uLan_DbgPrint("uLan: DispatchPnp: Waiting for pending requests to complete. %d. remain\n", devExt->OutstandingIO);#endif WaitForRemove(devExt); // // WE process this request first // // Remember next target of IRP targetDevice = devExt->DeviceToSendIrpsTo; // // Remove and return our device object // RemoveDevice(devExt->DeviceObject); // // Indidcate that we've successfully processed the IRP // Irp->IoStatus.Status = STATUS_SUCCESS; // // Pass this request on down to the bus driver // IoSkipCurrentIrpStackLocation(Irp); code = IoCallDriver(targetDevice, Irp); ASSERT(code != STATUS_PENDING); // // IMPORTANT: We decremented our I/O In Progress count // above... We don't want to decrement it again, so we // return right here. //#if DBG uLan_DbgPrint("uLan: DispatchPnp: Leaving with state: STATE_REMOVE\n");#endif return(code); break; // // STATE: STARTED // IRP_MN: _SURPRISE_REMOVAL // // We're here when the device is running, and a device is // forcibly removed. PnP Manager will send us a remove device // IRP when we're supposed to actually return our resources // and the like. // // Note that this is a "best effort" activity. It is quite // possible, due to timing issues etc, that we'll crash the // system because the device is gone. While we'll TRY not // to do this, it is within the rules. // // THIS IRP IS NOT SENT ON Win9x. // case STATE_STARTED + IRP_MN_SURPRISE_REMOVAL: devExt->State = STATE_SURPRISE_REMOVED; // // We handle this request before the bus driver // // // Cancel any pending requests... make sure // the active requests get stopped within a second (with // no hardware access, as a result of setting the state // above). // ClearQueues(devExt); // // We're happy... sort of. Note that it's not "legal" // to fail this request. Afterall, what woudl that MEAN? // Irp->IoStatus.Status = STATUS_SUCCESS; // // Pass this request on down to the bus driver // IoSkipCurrentIrpStackLocation(Irp); code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp); break; // // STATE: STARTED // IRP_MN: _REMOVE_DEVICE // // We're here when the device is running, and a device is // forcibly removed. // // Note that like getting a SUPRISE_REMOVAL IRP on NT trying // to handle a removal directly from started state is a "best // effort" type of activity. We'll do what we can but it's // possible, due to timing issues etc, that we'll crash the // system because the device is gone. While we'll TRY not // to do this, it could be unavoidable. Oh well. // // ON NT, we'd get an IRP_MN_SURPRISE_REMOVAL instead of this // IRP in this state. We get this only on Win9x systems. // case STATE_STARTED + IRP_MN_REMOVE_DEVICE:#if DBG uLan_DbgPrint("uLan: DispatchPnp: REMOVE_DEVICE\n");#endif devExt->State = STATE_REMOVED; // // We handle this request before the bus driver // Note that this is another one of those requests we're // not "allowed" to fail. // // // Cancel any pending requests... make sure // the active requests get stopped within a second (with // no hardware access, as a result of setting the state // above). // ClearQueues(devExt); // // Return any resources we're using. // ReturnResources(devExt); // // Removing the device at this point is NOT optional. // // // Detach from the PDO // IoDetachDevice(devExt->DeviceToSendIrpsTo); targetDevice = devExt->DeviceToSendIrpsTo; devExt->DeviceToSendIrpsTo = NULL; // // Decrement our reference on the device here, and then // wait until we can remove the device. // RequestDecrement(devExt); #if DBG uLan_DbgPrint("uLan: DispatchPnp: Waiting for pending requests to complete. %d. remain\n", devExt->OutstandingIO);#endif WaitForRemove(devExt); // // OK! Now we can return our device object // RemoveDevice(devExt->DeviceObject); // // Tell the underlying driver we're cool // Irp->IoStatus.Status = STATUS_SUCCESS; // // Pass this request on down to the bus driver // IoSkipCurrentIrpStackLocation(Irp); code = IoCallDriver(targetDevice, Irp); ASSERT(code != STATUS_PENDING); // // IMPORTANT: We decremented our I/O In Progress count // above... We don't want to decrement it again, so we // return right here. //#if DBG uLan_DbgPrint("uLan: DispatchPnp: Leaving with state: STATE_REMOVED\n");#endif return(code); break; // // STATE: STARTED // IRP_MN: _QUERY_STOP_DEVICE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -