📄 ul_wdpnp.c
字号:
// // We're here if we're running and the PnP Manager sends us // a QUERY_STOP_DEVICE request. He'll do this if he wants to // rebalance resources, to see if we're willing to give up the // hardware resources that were allocated for us when we got // our IRP_MN_START_DEVICE. // // To proess this QUERY_STOP, we check to see if the stop is // acceptable to us (in this driver it always is), and then // we just transition the device to STOP_PENDING state. In // this state, new requests that arrive are queued. When a // currently in-progress request is completed, a new request // is NOT started. Thus, ON OUR DEVICE, we sort of hope that // between the QUERY_STOP IRP arrive and actual STOP IRP arriving // that any in-progress I/O will complete of its own accord. // We like this scheme, particularly because at least on NT // during startup the device seems to get lots of QUERY_STOP // IRPs, that are just followed by CANCEL_STOP. Thus, we think // it would be unfortunate to do anything radical with the // outstanding requests (like cancel them) when we receive a // QUERY_STOP. // case STATE_STARTED + IRP_MN_QUERY_STOP_DEVICE:#if DBG uLan_DbgPrint("uLan: DispatchPnp: PROCESSING QUERY_STOP_DEVICE\n");#endif // // WE process this request before the BUS DRIVER // // // See if we're OK with stopping 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 = CanStopDevice(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 stop 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 { // // We CAN stop our device and return the resources. // Pass the IRP down to see if the bus driver is // equally ammenable to the request. //#if DBG uLan_DbgPrint("uLan: DispatchPnp: Agreeing to stop device.\n");#endif // // Set new state. This state results in no new // requests being started on the device, but incoming // requests are still allowed and queued. // devExt->State = STATE_STOP_PENDING; // // Pass this request on down to the bus driver // IoSkipCurrentIrpStackLocation(Irp); code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp); } break; // // STATE: STOP_PENDING // IRP_MN: _STOP_DEVICE // // We're in this state because we previously received a // QUERY_STOP_DEVICE, that we agreed that we could grant. // Thus, we're waiting to receive a STOP_DEVICE request. // To process this request, we first wait for any in-progress // requests to complete (note that no NEW requests have been // started since the transition to STOP_PENDING state as a // 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 after we get the START_DEVICE. // case STATE_STOP_PENDING + IRP_MN_STOP_DEVICE:#if DBG uLan_DbgPrint("uLan: DispatchPnp: PROCESSING STOP_DEVICE\n");#endif // // Assume success // devExt->State = STATE_STOPPED; #if DBG uLan_DbgPrint("uLan: DispatchPnp: Waiting for in-progress requests to complete\n");#endif // // We process this request before passing it to the bus // driver // // // Wait until all active requests on the device have // completed... // WaitForStop(devExt); // // There are NO ACTIVE IRPs on the device at this point. // // // Return any resources we're using. // ReturnResources(devExt); // // NOTE: We DO NOT delete our device object here. This is // one difference between a _STOP_DEVICE and _REMOVE_DEVICE. //#if DBG uLan_DbgPrint("uLan: DispatchPnp: Passing along request\n");#endif // // Pass this request on down to the bus driver // IoSkipCurrentIrpStackLocation(Irp); // // We're cool with the stop... // Irp->IoStatus.Status = STATUS_SUCCESS; code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp); break; // // STATE: STOP_PENDING // IRP_MN: _CANCEL_STOP_DEVICE // // We're here because we've already received a QUERY_STOP, // that we've agreed to. We've completed any pending I/O // requests. Now we've received a CANCEL_STOP_DEVICE // IRP, that sort of says "never mind" about that stop. // // We restart our queues and return to Started state. // case STATE_STOP_PENDING + IRP_MN_CANCEL_STOP_DEVICE:#if DBG uLan_DbgPrint("uLan: DispatchPnp: PROCESSING CANCEL_STOP\n");#endif // // fall through... // // // 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 restart our queues and return to Started state. // case STATE_REMOVE_PENDING + IRP_MN_CANCEL_REMOVE_DEVICE:#if DBG if( devExt->State == STATE_REMOVE_PENDING) { uLan_DbgPrint("uLan: DispatchPnp: PROCESSING CANCEL_REMOVE\n"); }#endif // // The Underlying BUS DRIVER must handle these IRPs // before we do... // // // We need to wait for the underlying bus driver to // get restarted, before we can continue processing. // IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, PnpComplete, &eventWaitLowerDrivers, TRUE, TRUE, TRUE); code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp); if(code == STATUS_PENDING) { KeWaitForSingleObject(&eventWaitLowerDrivers, Executive, KernelMode, FALSE, NULL); } // // We're now in STARTED state // devExt->State = STATE_STARTED; // // Go see if there's a request that we can start now // ProcessQueuedRequests(devExt); code = STATUS_SUCCESS; Irp->IoStatus.Status = code; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); break;#ifdef UL_WITH_WIN_PWR // // STATE: QUERY_CAPABILITIES // IRP_MN: IRP_MN_QUERY_CAPABILITIES // case STATE_STARTED + IRP_MN_QUERY_CAPABILITIES:#if DBG uLan_DbgPrint("uLan: DispatchPnp: QUERY_CAPABILITIES\n");#endif IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, PnpComplete, &eventWaitLowerDrivers, TRUE, TRUE, TRUE); code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp); if(code == STATUS_PENDING) { KeWaitForSingleObject(&eventWaitLowerDrivers, Executive, KernelMode, FALSE, NULL); } break; code = STATUS_SUCCESS; Irp->IoStatus.Status = code; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); break;#endif /* UL_WITH_WIN_PWR */ default: // // DEFAULT CASE // Just pass the request to the lower driver //#if DBG uLan_DbgPrint("uLan: DispatchPnp: Default case: Just pass it along...\n");#endif IoSkipCurrentIrpStackLocation (Irp); code = IoCallDriver (devExt->DeviceToSendIrpsTo, Irp); break; } // // Adjust in-progress request count // RequestDecrement(devExt);#if DBG uLan_DbgPrint("uLan: DispatchPnp: Leaving with new state "); PrintState(devExt); uLan_DbgPrint("uLan: DispatchPnp: exit (%d.).\n", devExt->OutstandingIO);#endif // // We always finish our work in this function // ASSERT(code != STATUS_PENDING); return(code);}//// PnpComplete// // This is the completion routine for IRP_MJ_PNP requests//NTSTATUSPnpComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context){ PIO_STACK_LOCATION iostack; PKEVENT pEvent = (PKEVENT) Context; NTSTATUS status = STATUS_SUCCESS;#ifdef UL_WITH_WIN_PWR PULAN_DEVICE_EXTENSION devExt; PDEVICE_CAPABILITIES Capabilities; devExt = (PULAN_DEVICE_EXTENSION)DeviceObject->DeviceExtension;#else UNREFERENCED_PARAMETER (DeviceObject); #endif /* UL_WITH_WIN_PWR */ iostack = IoGetCurrentIrpStackLocation (Irp);//// Driver Writers, please note://// The following code is only necessary IF (a) WE have a completion// routine, AND (b) WE return STATUS_PENDING from our dispatch entry// point after re-claiming the IRP. Since neither of these things// is true... this code does not belong here.//// if (Irp->PendingReturned) {//// IoMarkIrpPending( Irp );//// } switch (iostack->MajorFunction) { case IRP_MJ_PNP:#ifdef UL_WITH_WIN_PWR if (iostack->MinorFunction == IRP_MN_QUERY_CAPABILITIES) { Capabilities = iostack->Parameters.DeviceCapabilities.Capabilities; //Modify the PnP values here as necessary Capabilities->Removable = TRUE; Capabilities->SurpriseRemovalOK = FALSE; //Save the device capabilities int the device extension RtlCopyMemory(&devExt->DeviceCapabilities, Capabilities, sizeof(DEVICE_CAPABILITIES)); PrintCapabilityInfo(&devExt->DeviceCapabilities); }#endif /* UL_WITH_WIN_PWR */ KeSetEvent(pEvent, 0, FALSE); // // Take the IRP back so that we can continue using it during // the IRP_MN_START_DEVICE dispatch routine. // NB: we will have to call IoCompleteRequest // return STATUS_MORE_PROCESSING_REQUIRED; break; case IRP_MJ_POWER: KeSetEvent(pEvent, 1, FALSE); // // Take the IRP back so that we can continue using it during // the IRP_MN_START_DEVICE dispatch routine. // NB: we will have to call IoCompleteRequest // return STATUS_MORE_PROCESSING_REQUIRED; break; default:#if DBG uLan_DbgPrint("uLan: PnpComplete: NOT MJ_PNP or MJ_POWER IRP??\n");#endif break; } return status;}/////////////////////////////////////////////////////////////////////////////////// StartDevice//// This function is called from the DispatchPnp Entry Point to// actually start the hardware.//// INPUTS://// DevExt - Address of our device extension.// IoStackLocation -- Pointer to I/O Stack Location containing// configuration information//// OUTPUTS://// None.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -