NTSTATUS dispatch_pnp(libusb_device_t *dev, IRP *irp) { NTSTATUS status = STATUS_SUCCESS; IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp); UNICODE_STRING symbolic_link_name; WCHAR tmp_name[128]; status = remove_lock_acquire(dev); if(!NT_SUCCESS(status)) { return complete_irp(irp, status, 0); } DEBUG_PRINT_NL(); switch(stack_location->MinorFunction) { case IRP_MN_REMOVE_DEVICE: DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_REMOVE_DEVICE"); dev->is_started = FALSE; /* wait until all outstanding requests are finished */ remove_lock_release_and_wait(dev); status = pass_irp_down(dev, irp, NULL, NULL); DEBUG_MESSAGE("dispatch_pnp(): deleting device #%d", dev->id); _snwprintf(tmp_name, sizeof(tmp_name)/sizeof(WCHAR), L"%s%04d", LIBUSB_SYMBOLIC_LINK_NAME, dev->id); /* delete the symbolic link */ RtlInitUnicodeString(&symbolic_link_name, tmp_name); IoDeleteSymbolicLink(&symbolic_link_name); /* delete the device object */ IoDetachDevice(dev->next_stack_device); IoDeleteDevice(dev->self); return status; case IRP_MN_SURPRISE_REMOVAL: DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_SURPRISE_REMOVAL"); dev->is_started = FALSE; break; case IRP_MN_START_DEVICE: DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_START_DEVICE"); /* if(!NT_SUCCESS(set_configuration(dev, 1, 1000))) */ /* { */ /* DEBUG_ERROR("dispatch_pnp(): IRP_MN_START_DEVICE: selecting " */ /* "configuration failed"); */ /* } */ /* report device state to Power Manager */ /* power_state.DeviceState has been set to D0 by add_device() */ PoSetPowerState(dev->self, DevicePowerState, dev->power_state); return pass_irp_down(dev, irp, on_start_complete, NULL); case IRP_MN_STOP_DEVICE: dev->is_started = FALSE; DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_STOP_DEVICE"); break; case IRP_MN_DEVICE_USAGE_NOTIFICATION: DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_DEVICE_USAGE_NOTIFICATION"); if(!dev->self->AttachedDevice || (dev->self->AttachedDevice->Flags & DO_POWER_PAGABLE)) { dev->self->Flags |= DO_POWER_PAGABLE; } return pass_irp_down(dev, irp, on_device_usage_notification_complete, NULL); case IRP_MN_QUERY_CAPABILITIES: DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_QUERY_CAPABILITIES"); if(!dev->is_filter) { /* apply registry setting */ stack_location->Parameters.DeviceCapabilities.Capabilities ->SurpriseRemovalOK = dev->surprise_removal_ok; } return pass_irp_down(dev, irp, on_query_capabilities_complete, NULL); default: ; } remove_lock_release(dev); return pass_irp_down(dev, irp, NULL, NULL); }
NTSTATUS DDKAPI dispatch(DEVICE_OBJECT *device_object, IRP *irp) { libusb_device_t *dev = device_object->DeviceExtension; IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp); switch (stack_location->MajorFunction) { case IRP_MJ_PNP: return dispatch_pnp(dev, irp); case IRP_MJ_POWER: // ID: 2960644 (farthen) // You can't set the power state if the device is not handled at all if(!dev->next_stack_device) { return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0); } return dispatch_power(dev, irp); } /* since this driver may run as an upper filter we have to check whether */ /* the IRP is sent to this device object or to the lower one */ if (accept_irp(dev, irp)) { switch (stack_location->MajorFunction) { case IRP_MJ_DEVICE_CONTROL: if (dev->is_started) { return dispatch_ioctl(dev, irp); } else /* not started yet */ { return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0); } case IRP_MJ_CREATE: if (dev->is_started) { // only one driver can act as power policy owner and // power_set_device_state() can only be issued by the PPO. // disallow_power_control is set to true for drivers which // we know cause a BSOD on any attempt to request power irps. if (dev->power_state.DeviceState != PowerDeviceD0 && !dev->disallow_power_control) { /* power up the device, block until the call */ /* completes */ power_set_device_state(dev, PowerDeviceD0, TRUE); } return complete_irp(irp, STATUS_SUCCESS, 0); } else /* not started yet */ { return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0); } case IRP_MJ_CLOSE: /* release all interfaces bound to this file object */ release_all_interfaces(dev, stack_location->FileObject); return complete_irp(irp, STATUS_SUCCESS, 0); case IRP_MJ_CLEANUP: return complete_irp(irp, STATUS_SUCCESS, 0); default: return complete_irp(irp, STATUS_NOT_SUPPORTED, 0); } } else /* the IRP is for the lower device object */ { return pass_irp_down(dev, irp, NULL, NULL); } }
NTSTATUS DDKAPI dispatch(DEVICE_OBJECT *device_object, IRP *irp) { libusb_device_t *dev = device_object->DeviceExtension; switch(IoGetCurrentIrpStackLocation(irp)->MajorFunction) { case IRP_MJ_PNP: return dispatch_pnp(dev, irp); case IRP_MJ_POWER: return dispatch_power(dev, irp); } /* since this driver may run as an upper filter we have to check whether */ /* the IRP is sent to this device object or to the lower one */ if(accept_irp(dev, irp)) { switch(IoGetCurrentIrpStackLocation(irp)->MajorFunction) { case IRP_MJ_DEVICE_CONTROL: if(dev->is_started) { return dispatch_ioctl(dev, irp); } else /* not started yet */ { return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0); } case IRP_MJ_CREATE: if(dev->is_started) { if(InterlockedIncrement(&dev->ref_count) == 1) { if(dev->power_state.DeviceState != PowerDeviceD0) { /* power up the device, block until the call */ /* completes */ power_set_device_state(dev, PowerDeviceD0, TRUE); } } return complete_irp(irp, STATUS_SUCCESS, 0); } else /* not started yet */ { return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0); } case IRP_MJ_CLOSE: if(!InterlockedDecrement(&dev->ref_count)) { /* release all interfaces when the last handle is closed */ release_all_interfaces(dev); } return complete_irp(irp, STATUS_SUCCESS, 0); case IRP_MJ_CLEANUP: return complete_irp(irp, STATUS_SUCCESS, 0); default: return complete_irp(irp, STATUS_NOT_SUPPORTED, 0); } } else /* the IRP is for the lower device object */ { return pass_irp_down(dev, irp, NULL, NULL); } }