Partilhar via


Manipulando uma solicitação de IRP_MN_QUERY_STOP_DEVICE (Windows 2000 e posterior)

Uma solicitação de IRP_MN_QUERY_STOP_DEVICE é tratada primeiro pelo driver superior na pilha do dispositivo e, em seguida, por cada driver inferior próximo. Um driver lida com a parada de IRPs em sua rotina DispatchPnP .

Em resposta a um IRP_MN_QUERY_STOP_DEVICE, um driver deve fazer o seguinte:

  1. Determine se o dispositivo pode ser interrompido e seus recursos de hardware liberados, sem efeitos adversos.

    Um driver deverá falhar em um IRP de parada de consulta se qualquer um dos seguintes itens for verdadeiro:

    • Um driver foi notificado (por meio de IRP_MN_DEVICE_USAGE_NOTIFICATION) de que o dispositivo está no caminho de um arquivo de paginação, hibernação ou despejo de memória.

    • Os recursos de hardware do dispositivo não podem ser liberados.

    Um driver poderá falhar em um IRP de parada de consulta se o seguinte for verdadeiro:

    • O driver não deve descartar solicitações de E/S e não tem um mecanismo para enfileirar IRPs.

      Enquanto o dispositivo está no estado parado, um driver deve conter IRPs que exigem acesso ao dispositivo. Se um driver não enfileirar IRPs, ele não deverá permitir que o dispositivo seja interrompido e, portanto, deve falhar em um IRP de parada de consulta.

      A exceção a essa regra é um dispositivo que tem permissão para remover E/S. Os drivers de um dispositivo desse tipo podem ter êxito na parada de consulta e parar solicitações sem enfileirar IRPs.

  2. Se o dispositivo não puder ser interrompido, falhe o IRP de parada de consulta.

    Defina Irp-IoStatus.Status> como um erro apropriado status, chame IoCompleteRequest com IO_NO_INCREMENT e retorne da rotina DispatchPnP do driver. Não passe o IRP para o próximo driver inferior.

  3. Se o dispositivo puder ser interrompido e o driver enfileirar IRPs, defina o sinalizador HOLD_NEW_REQUESTS na extensão do dispositivo para que IRPs subsequentes sejam enfileirados (consulte Segurando IRPs de entrada quando um dispositivo estiver em pausa).

    Como alternativa, os drivers de um dispositivo podem adiar completamente a pausa do dispositivo até que os drivers recebam a solicitação de IRP_MN_STOP_DEVICE subsequente. Esses drivers, no entanto, devem enfileirar todas as solicitações que os impeçam de ter êxito imediato na parada do IRP quando ele chegar. Até que o dispositivo seja reiniciado, esses drivers devem enfileirar solicitações, como o seguinte:

    • IRP_MN_DEVICE_USAGE_NOTIFICATION solicitações (por exemplo, para colocar um arquivo de paginação no dispositivo).

    • Solicitações de transferências isócronas.

    • Crie solicitações que impeçam que os drivers tenham êxito em parar o IRP.

  4. Se o dispositivo não puder ter um IRP em andamento falhar, verifique se todas as solicitações pendentes que foram passadas para outras rotinas de driver e para drivers inferiores foram concluídas.

    Uma maneira de um driver conseguir isso é usar uma contagem de referência e um evento para garantir que todas as solicitações tenham sido concluídas:

    • Em sua rotina AddDevice , o driver define uma contagem de referência de E/S na extensão do dispositivo e inicializa a contagem para um.

    • Também em sua rotina AddDevice , o driver cria um evento com KeInitializeEvent e inicializa o evento para o estado Not-Signaled com KeClearEvent.

    • Sempre que processa um IRP, o driver incrementa a contagem de referência com InterlockedIncrement.

    • Sempre que ele conclui uma solicitação, o driver diminui a contagem de referência com InterlockedDecrement.

      O driver diminui a contagem de referência na rotina IoCompletion , se a solicitação tiver uma ou logo após a chamada para IoCallDriver se o driver não usar nenhuma rotina IoCompletion para a solicitação .

    • Quando o driver recebe um IRP_MN_QUERY_STOP_DEVICE, ele diminui a contagem de referência com InterlockedDecrement. Se não houver nenhuma solicitação pendente, isso reduzirá a contagem de referência para zero.

    • Quando a contagem de referência atinge zero, o driver define o evento com KeSetEvent sinalizando que o código de parada de consulta pode continuar.

    Como alternativa ao procedimento acima, um driver pode serializar o IRP IRP_MN_QUERY_STOP_DEVICE atrás de qualquer IRPs em andamento.

  5. Execute todas as outras etapas necessárias para colocar o dispositivo no estado de parada pendente.

    Depois que um driver tiver êxito em um IRP de parada de consulta, ele deverá estar pronto para ter êxito em um IRP_MN_STOP_DEVICE.

  6. Conclua o IRP.

    Em uma função ou driver de filtro:

    • Defina Irp-IoStatus.Status> como STATUS_SUCCESS.

    • Configure o próximo local de pilha com IoSkipCurrentIrpStackLocation e passe o IRP para o próximo driver inferior com IoCallDriver.

    • Propagar a status de IoCallDriver como a status de retorno da rotina DispatchPnP.

    • Não conclua o IRP.

    Em um motorista de ônibus:

    • Defina Irp-IoStatus.Status> como STATUS_SUCCESS.

      Se, no entanto, os dispositivos no barramento usarem recursos de hardware, reavaliar os requisitos de recursos do barramento e dos dispositivos filho. Se algum dos requisitos tiver sido alterado, retorne STATUS_RESOURCE_REQUIREMENTS_CHANGED em vez de STATUS_SUCCESS. Esse status indica êxito, mas solicita que o gerente PnP exiba seus recursos antes de enviar o IRP de parada.

    • Conclua o IRP (IoCompleteRequest) com IO_NO_INCREMENT.

    • Retorne da rotina DispatchPnP .

Se algum driver na pilha do dispositivo falhar no IRP_MN_QUERY_STOP_DEVICE, o gerenciador PnP enviará um IRP_MN_CANCEL_STOP_DEVICE para a pilha do dispositivo. Isso impede que os drivers exijam uma rotina IoCompletion para um IRP de parada de consulta para detectar se um driver inferior falhou no IRP.