Cancelando um IRP de espera/ativação
Somente o driver que enviou um IRP de espera/ativação pode cancelar esse IRP.
Um driver pode precisar cancelar um IRP de espera/ativação pendente nas seguintes circunstâncias:
O driver recebe uma solicitação PnP IRP_MN_STOP_DEVICE, IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_REMOVE_DEVICE ou IRP_MN_SURPRISE_REMOVAL para o dispositivo. O driver deve reemissar o IRP de espera/ativação (PoRequestPowerIrp) depois que o dispositivo for reiniciado.
O sistema vai entrar em suspensão, mas o dispositivo não deve ser habilitado para ativar o sistema.
Por exemplo, o driver de hub USB pode enviar uma solicitação de IRP_MN_WAIT_WAKE na inicialização do dispositivo caso posteriormente coloque um de seus dispositivos de entrada em um estado de suspensão. Enquanto o sistema está no estado de trabalho, um sinal de ativação do dispositivo retorna o dispositivo para o estado de trabalho (mas não tem efeito sobre o estado de energia do sistema). Quando o sistema se prepara para desligar, o driver do hub USB cancela esse IRP se o dispositivo não tiver permissão para despertar o sistema.
O sistema está entrando em um estado de suspensão do qual o dispositivo não pode despertá-lo. Ou seja, ele está inserindo um estado menos alimentado do que o valor SystemWake especificado em sua estrutura de DEVICE_CAPABILITIES .
O dispositivo está entrando em um estado de energia do qual não pode responder a um sinal de ativação. Ou seja, ele está inserindo um estado menos alimentado do que o valor DeviceWake especificado em sua estrutura DEVICE_CAPABILITIES .
Para cancelar um IRP de espera/ativação, o driver que enviou o IRP chama IoCancelIrp, passando o ponteiro para o IRP que foi retornado anteriormente quando o driver chamou PoRequestPowerIrp.
Um driver não deve cancelar um IRP de espera/ativação que ele não enviou.
Cancelar rotinas para IRPs de espera/ativação
Muitos motoristas de barramento e função devem definir Rotinas de cancelamento para IRPs de espera/ativação pendentes; os seguintes tipos de drivers devem definir essas rotinas:
Drivers que alteram as configurações do dispositivo para habilitar ou desabilitar a ativação.
Drivers que enviam IRP_MN_WAIT_WAKE solicitações para drivers de dispositivos pai.
Uma rotina Cancelar permite que um driver desabilite a ativação de seu dispositivo e limpo todos os dados relacionados ao IRP de espera/ativação pendente. Os drivers que solicitam IRPs de espera/ativação para dispositivos pai também podem cancelar esses IRPs.
Em sua rotina de cancelamento de espera/ativação, um driver deve executar as seguintes etapas:
Chame IoSetCancelRoutine para redefinir a rotina Cancelar do IRP para NULL.
Chame IoReleaseCancelSpinLock, passando o CancelIRQL especificado no IRP para liberar o bloqueio de rotação de cancelamento para o IRP.
Redefina todos os campos relevantes na extensão do dispositivo. Por exemplo, quando um IRP de espera/ativação está pendente, a maioria dos drivers define um sinalizador e mantém um ponteiro para o IRP na extensão do dispositivo.
Observe que é possível que um driver receba um IRP de espera/ativação enquanto está cancelando outro IRP desse tipo. O driver deve marcar para ver se ele já tem um IRP sob proteção de bloqueio de rotação (ou seu equivalente). Nesse caso, o driver deve sincronizar cuidadosamente sua manipulação para garantir que cancele o IRP correto. Para obter mais informações sobre como usar bloqueios de rotação em Cancelar rotinas, consulte Cancelando IRPs.
Altere as configurações de dispositivo necessárias. Por exemplo, um driver de modem desabilitaria a configuração de ativação do dispositivo.
Defina Irp-IoStatus.Status> como STATUS_CANCELLED.
Chame IoCompleteRequest para concluir o IRP de espera/ativação, especificando IO_NO_INCREMENT.
Se o driver solicitou anteriormente uma IRP_MN_WAIT_WAKE relacionada para um dispositivo pai, o driver deve cancelar esse IRP de dentro de sua rotina Cancelar . O driver deve liberar o bloqueio de rotação de cancelamento antes de cancelar o IRP do pai.
Por exemplo, um motorista que atua como um motorista de ônibus para um dispositivo e possui o driver de política de energia para seu pai deve cancelar um IRP de espera/ativação relacionado que ele enviou anteriormente para seu pai. Chamar IoCancelIrp invocaria a rotina Cancelar do pai e assim por diante na pilha do dispositivo.