Vous pouvez aussi avoir un traitement cyclique ou déclenché à une date
donnée en déclarant une dpc timer utilisant le timer disponible au niveau
driver.
Une date peut être spécifiée en unité de 100 ns et une période en ms.
Dans la pratique on constate une résolution de 10 ms. La cadence maximale est
donc de 100 hz sauf si vous avez déclaré quelque part un multimédia
timer ce qui vous permet alors mystérieusement de monter à 1000 hz.
//
// dpc accrochée au timer
//
VOID
DPCtimer(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
Installer une dpc timer
unsigned long SetDpcTimer(unsigned long newPeriodeMs)
{
_LARGE_INTEGER next;
unsigned long unite100ns,uniteMs;
// double integer, fraction, rapport;
if(!DeviceTimerInstalled)
{
KeInitializeTimerEx(&DeviceTimer,SynchronizationTimer);
KeInitializeDpc(&DeviceDPCTimer,DPCtimer,DeviceObject);
DeviceTimerInstalled = true;
PC_timer_resolution_ms = 0;
}
// demande de l'unite en principe en 100ns
unite100ns = KeQueryTimeIncrement();
// arrondir cette unite en ms en principe 10 ms
uniteMs = (unite100ns+5000)/10000;
// précaution si on tombe sur des systèmes inférieurs à la ms
if(uniteMs==0)
uniteMs = 1;
// pour avoir un système régulier prendre le multiple le plus proche
newPeriodeMs = newPeriodeMs / uniteMs * uniteMs;
if(newPeriodeMs<uniteMs)
newPeriodeMs = uniteMs;
if(newPeriodeMs==0)
newPeriodeMs = 1;
// changer l'intervalle
if(newPeriodeMs!=PC_timer_resolution_ms)
{
next.QuadPart = -10;
PC_timer_resolution_ms = newPeriodeMs;
DbgPrint("cycle %d ms,unite timer=%d us\n",PC_timer_resolution_ms,unite100ns/10);
KeSetTimerEx(&DeviceTimer,
next, // activation dans 10*100ns
PC_timer_resolution_ms, // periode en ms
&DeviceDPCTimer);
// les messages seront placés en tête de file de dpc
KeSetImportanceDpc (&DeviceDPCTimer,HighImportance);
}
return PC_timer_resolution_ms;
}
Désinstaller
// annulation du timer
void ResetDpcTimer(void)
{
KeCancelTimer(&DeviceTimer);
DeviceTimerInstalled = false;
}