📄 ul_wdpnp.c
字号:
return STATUS_SUCCESS;}/////////////////////////////////////////////////////////////////////////////////// CanRemoveDevice//// This routine determines if the device cab be safely removed. In our case// we'll assume you can always remove the device. A device might not be able to// be removed, for example, if it has opened handles or removing the device would// result in the lost of data.//// INPUTS://// devExt - Address of our device extension.// Irp - Address of the input IRP.//// OUTPUTS://// None.//// RETURNS://// STATUS_SUCCESS;//// IRQL:////// NOTES:///////////////////////////////////////////////////////////////////////////////////NTSTATUS CanRemoveDevice(PULAN_DEVICE_EXTENSION devExt, PIRP Irp){ UNREFERENCED_PARAMETER(devExt); UNREFERENCED_PARAMETER(Irp); return STATUS_SUCCESS;}/////////////////////////////////////////////////////////////////////////////////// ReturnResources//// This function is called to return any hardware resources which// have been allocated for the device. In our case, these are// the Interrupt Object, and any ports we might have mapped through// memory. Note that we do NOT return our Device Object here.//// INPUTS://// devExt - Address of our device extension.// Irp - Address of the input IRP.//// OUTPUTS://// None.//// RETURNS://// VOID//// IRQL:////// NOTES:///////////////////////////////////////////////////////////////////////////////////VOIDReturnResources(PULAN_DEVICE_EXTENSION devExt){ // // Stop port activity // ul_drv_done_ext(devExt); if (devExt->usb_bus && devExt->dev) { // // Destroy USB device // usb_destroy_dev(((usb_device*)devExt->dev)); devExt->dev=NULL; } // // Disconnect from any interrupts // if (devExt->InterruptObject) { // // Disconnect from the interrupt // IoDisconnectInterrupt(devExt->InterruptObject); devExt->InterruptObject = NULL; } KeCancelTimer(&devExt->wd_timer); KeRemoveQueueDpc(&devExt->wd_timer_dpc); KeRemoveQueueDpc(&devExt->bottom_dpc); // // Unmap any ports that were mapped // if (devExt->MappedPorts) { MmUnmapIoSpace((PVOID)devExt->port, DEF_PORT_RANGE); devExt->MappedPorts = FALSE; devExt->port = 0; }}/////////////////////////////////////////////////////////////////////////////////// RemoveDevice//// This function is called ater ReturnResources to destroy and// remove uLan DeviceObject. Again resources must be already// returned before this call//// INPUTS://// devExt - Address of our device extension.//// OUTPUTS://// None.//// RETURNS://// VOID//// IRQL:////// NOTES:///////////////////////////////////////////////////////////////////////////////////VOID RemoveDevice(IN PDEVICE_OBJECT devObj){ PULAN_DEVICE_EXTENSION devExt; devExt=(PULAN_DEVICE_EXTENSION)devObj->DeviceExtension; // // Detach from the PDO // if(devExt->DeviceToSendIrpsTo) IoDetachDevice(devExt->DeviceToSendIrpsTo); devExt->DeviceToSendIrpsTo = NULL; // Delete Symbolic Link if(devExt->link_name.Length&&devExt->link_name.Buffer) IoDeleteSymbolicLink(&devExt->link_name); if(devExt->link_name.Buffer) ExFreePool(devExt->link_name.Buffer); if(devExt->ntdev_name.Buffer) ExFreePool(devExt->ntdev_name.Buffer); // Destroy DeviceObject IoDeleteDevice(devObj);}/////////////////////////////////////////////////////////////////////////////////// RequestIncrement// RequestDecrement//// These functions are used to track the number of requests that// are presently queued the device indicated by the passed// Device Extension.//// This code is based heavily on the PnP Sample Driver in the// \General directory of the NTDDK.//// INPUTS://// devExt - Address of our device extension.//// OUTPUTS://// None.//// RETURNS://// STATUS_SUCCESS;//// IRQL:////// NOTES:///////////////////////////////////////////////////////////////////////////////////VOIDRequestIncrement(PULAN_DEVICE_EXTENSION devExt){ LONG result; result = InterlockedIncrement(&devExt->OutstandingIO); ASSERT(result >= 0); // // Need to clear Remove // if (result == 1) { // // The remove event is cleared when the first request is // added to the queue. // KeClearEvent(&devExt->RemoveEvent); } return;}VOIDRequestDecrement(PULAN_DEVICE_EXTENSION devExt){ LONG result; result = InterlockedDecrement(&devExt->OutstandingIO); ASSERT(result >= 0); if (result == 0) { // // The remove event is set when the queue is totally EMPTY. // KeSetEvent(&devExt->RemoveEvent, IO_NO_INCREMENT, FALSE); }}/////////////////////////////////////////////////////////////////////////////////// WaitForStop//// Using the event set by the RequestIncrement() and // RequestDecrement() functions, this function waits until// the device can be stopped.//// On our device, STOP implies there are no active requests on// the device, even though there are queued requests.//// INPUTS://// devExt - Address of our device extension.//// OUTPUTS://// None.//// RETURNS://// STATUS_SUCCESS;//// IRQL:////// NOTES:///////////////////////////////////////////////////////////////////////////////////VOIDWaitForStop(PULAN_DEVICE_EXTENSION devExt){ #if 0 /* No need to wait for end of IO */ devExt->HoldNewRequests = TRUE; ASSERT(devExt->State != STATE_STARTED); KeWaitForSingleObject(&devExt->StopEvent, Executive, KernelMode, FALSE, NULL); #endif}/////////////////////////////////////////////////////////////////////////////////// WaitForRemove//// Using the event set by the RequestIncrement() and // RequestDecrement() functions, this function waits until// the device can be removed.//// On our device, REMOVE implies there are no active or queued// requests on the device.//// INPUTS://// devExt - Address of our device extension.//// OUTPUTS://// None.//// RETURNS://// STATUS_SUCCESS;//// IRQL:////// NOTES:///////////////////////////////////////////////////////////////////////////////////VOIDWaitForRemove(PULAN_DEVICE_EXTENSION devExt){#if DBG LARGE_INTEGER timeout; NTSTATUS status; timeout.QuadPart = -5*10*1000*1000; // 5 seconds#endif ///devExt->Removed = TRUE; ASSERT(devExt->State < STATE_ALL_BELOW_FAIL);#if DBGwait_again: status = KeWaitForSingleObject(&devExt->RemoveEvent, Executive, KernelMode, FALSE, &timeout); if(status == STATUS_TIMEOUT) { uLan_DbgPrint("uLan: *** Still Waiting for activity to stop on device?? %d. requests reamin\n", devExt->OutstandingIO); goto wait_again; } if(status != STATUS_SUCCESS) { uLan_DbgPrint("uLan: *** Wait not ended with success, and not with timeout?? Status = 0x%0x\n", status); }#else KeWaitForSingleObject(&devExt->RemoveEvent, Executive, KernelMode, FALSE, NULL);#endif}/////////////////////////////////////////////////////////////////////////////////// DispatchSystemControl//// This dispatch entry point is used to pass any WMI IRPs that we// receive on to the underlying bus driver.//// INPUTS:///// DriverObject - Pointer to driver object.// Irp - Address of the input IRP.//// OUTPUTS://// None.//// RETURNS://// VOID//// IRQL:////// NOTES:///////////////////////////////////////////////////////////////////////////////////NTSTATUS DispatchSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp){ // // Since we don't play WMI, pass this request on down to the // driver below us... // IoSkipCurrentIrpStackLocation(Irp); return(IoCallDriver(((PULAN_DEVICE_EXTENSION)(DeviceObject->DeviceExtension))->DeviceToSendIrpsTo, Irp));}VOIDPrintState(PULAN_DEVICE_EXTENSION devExt){ if(devExt->State == STATE_REMOVED) { uLan_DbgPrint("uLan: STATE_REMOVED\n"); return; } if(devExt->State == STATE_STARTED) { uLan_DbgPrint("uLan: STATE_STARTED\n"); return; } if(devExt->State == STATE_REMOVE_PENDING) { uLan_DbgPrint("uLan: STATE_REMOVE_PENDING\n"); return; } if(devExt->State == STATE_SURPRISE_REMOVED) { uLan_DbgPrint("uLan: STATE_SURPRISE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -