Registrando e enfileirando uma rotina CustomTimerDpc
Um driver pode registrar uma rotina CustomTimerDpc chamando as seguintes rotinas, geralmente de sua rotina AddDevice :
KeInitializeDpc para registrar sua rotina
KeInitializeTimer ou KeInitializeTimerEx para configurar um objeto de temporizador
Posteriormente, o driver pode chamar KeSetTimer ou KeSetTimerEx para especificar um tempo de expiração e adicionar o objeto de temporizador à fila do temporizador do sistema. Quando o tempo de expiração é atingido, o sistema desativa o objeto de temporizador e chama a rotina CustomTimerDpc . A figura a seguir ilustra essas chamadas.
Como mostra a figura anterior, o driver deve fornecer armazenamento para um objeto DPC e um objeto de temporizador. A maioria dos drivers fornece o armazenamento para esses objetos em uma extensão de dispositivo ou em outra memória residente alocada por driver.
Na chamada para KeSetTimer, o driver passa ponteiros para os objetos Dpc e Timer , juntamente com um DueTime expresso em unidades de 100 nanossegundos, conforme mostrado na figura anterior. Um valor positivo para DueTime especifica um tempo de expiração absoluto (desde 1º de janeiro de 1601) no qual a rotina CustomTimerDpc deve ser chamada. Um valor negativo para DueTime especifica um tempo de expiração relativo.
Como um temporizador absoluto expira em um momento específico do sistema, a duração de espera de um temporizador absoluto não será afetada se o tempo do sistema for alterado antes que o temporizador expire. Por outro lado, um temporizador relativo sempre expira após o número especificado de unidades de tempo decorrido, independentemente das alterações no tempo absoluto do sistema.
Para invocar uma rotina CustomTimerDpc repetidamente, use KeSetTimerEx para definir o temporizador e especificar um intervalo recorrente no parâmetro Period . KeSetTimerEx é como KeSetTimer , exceto por esse parâmetro adicional.
Conforme mostrado na figura anterior, a chamada para KeSetTimer ou KeSetTimerEx enfileira o objeto de temporizador para um intervalo especificado da seguinte maneira:
Quando o DueTime expira, o objeto de temporizador é desemqueado e definido como o estado Sinalizado.
Se cada processador no computador estiver executando código em um IRQL maior ou igual a DISPATCH_LEVEL, o objeto DPC associado ao objeto de temporizador será colocado em uma fila DPC. Caso contrário, a rotina CustomTimerDpc será chamada.
Se o objeto DPC já estava na fila quando o intervalo DueTime expirou, a rotina CustomTimerDpc é chamada assim que o IRQL em qualquer processador no computador fica abaixo DISPATCH_LEVEL.
Observação
A rotina CustomTimerDpc , como todas as rotinas DPC, é chamada em IRQL = DISPATCH_LEVEL. Enquanto uma rotina DPC é executada, todos os threads são impedidos de serem executados no mesmo processador. Os desenvolvedores de driver devem projetar cuidadosamente suas rotinas CustomTimerDpc para serem executadas o mais breve possível.
O menor intervalo de tempo que pode ser especificado para KeSetTimer e KeSetTimerEx é de aproximadamente dez milissegundos, portanto, um driver pode usar uma rotina CustomTimerDpc ao cronometrar intervalos menores do que uma rotina IoTimer , que é executada uma vez por segundo, pode lidar.
Apenas uma instanciação de um objeto de temporizador específico pode ser enfileirada a qualquer momento. Chamar KeSetTimer ou KeSetTimerEx novamente com o mesmo ponteiro de objeto Timer cancela o objeto de temporizador enfileirado e o redefine.
Configurar uma rotina CustomTimerDpc é exatamente como configurar uma rotina CustomDpc , com uma etapa adicional para inicializar o objeto de temporizador. Na verdade, seus protótipos são idênticos, mas a rotina CustomTimerDpc não pode usar os dois ponteiros SystemArgument declarados em seu protótipo.