Example #1
0
/* [trobinso MOD 4/16/2010]
 * If running as a filter, do not act as power policy owner.
 */
NTSTATUS dispatch_power(libusb_device_t *dev, IRP *irp)
{
    IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
    POWER_STATE power_state;
    NTSTATUS status;

    status = remove_lock_acquire(dev);

    if (!NT_SUCCESS(status))
    {
        irp->IoStatus.Status = status;
        PoStartNextPowerIrp(irp);
        IoCompleteRequest(irp, IO_NO_INCREMENT);
        return status;
    }

    if (stack_location->MinorFunction == IRP_MN_SET_POWER)
    {
        power_state = stack_location->Parameters.Power.State;

        if (stack_location->Parameters.Power.Type == SystemPowerState)
        {
            USBMSG("IRP_MN_SET_POWER: S%d %s\n",
				power_state.SystemState - PowerSystemWorking, dev->device_id);
        }
        else
        {
            USBMSG("IRP_MN_SET_POWER: D%d %s\n",
				power_state.DeviceState - PowerDeviceD0, dev->device_id);

            if (power_state.DeviceState > dev->power_state.DeviceState)
            {
                /* device is powered down, report device state to the */
                /* Power Manager before sending the IRP down */
                /* (power up is handled by the completion routine) */
                PoSetPowerState(dev->self, DevicePowerState, power_state);
            }
        }

        /* TODO: should PoStartNextPowerIrp() be called here or from the */
        /* completion routine? */
        PoStartNextPowerIrp(irp);

        IoCopyCurrentIrpStackLocationToNext(irp);
        if (!dev->is_filter && !dev->disallow_power_control)
        {
            IoSetCompletionRoutine(irp,
                                   on_power_state_complete,
                                   dev,
                                   TRUE, /* on success */
                                   TRUE, /* on error   */
                                   TRUE);/* on cancel  */
        }
        else
        {
            IoSetCompletionRoutine(irp,
                                   on_filter_power_state_complete,
                                   dev,
                                   TRUE, /* on success */
                                   TRUE, /* on error   */
                                   TRUE);/* on cancel  */
        }

        return PoCallDriver(dev->next_stack_device, irp);
    }
    else
    {
		/* pass all other power IRPs down without setting a completion routine */
        PoStartNextPowerIrp(irp);
        IoSkipCurrentIrpStackLocation(irp);
        status = PoCallDriver(dev->next_stack_device, irp);
        remove_lock_release(dev);

        return status;
    }
}
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);
}