0x00 函数
KeInitializeDpc() //初始化DPC
KeInitializeTimer() //初始化计时器
KeSetTimer() //将计时器与DPC进行绑定,待计时器过期时,执行DPC
KeCancelTimer)() //在计时器间隔(如果有的话)到期之前将计时器对象排出队列
0x01 代码
#include <wdm.h>
KTIMER Timer = { 0 };
KDPC Dpc = { 0 };
LARGE_INTEGER DueTime = { 0 };
LARGE_INTEGER Timeout = { 0 };
LARGE_INTEGER Timeout2 = { 0 };
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
//在计时器间隔(如果有的话)到期之前将计时器对象排出队列
KeCancelTimer(&Timer);
DbgPrint("DriverUnload");
return;
}
void KdeferredRoutine(PRKDPC Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2)
{
DbgPrint("KdeferredRoutine");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
DriverObject->DriverUnload = DriverUnload;
//https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/timer-objects-and-dpcs
//初始化DPC,也可以通过 KeInsertQueueDpc 来执行DPC
KeInitializeDpc(&Dpc, KdeferredRoutine, 0);
//初始化计时器
//KTIME结构体,第一个成员为 DISPATCHER_HEADER Header; 可以调用KeWaitForSingleObject
KeInitializeTimer(&Timer);
//计时器间隔
DueTime.QuadPart = -10 * 1000 * 1000 * 5; //5秒 -> 单位为100纳秒,*10 = 微秒,*10*1000 = 毫秒,*10*1000*1000 = 秒
//将计时器与DPC进行绑定,待计时器过期时,执行DPC
//KeSetTimer总是设置一个只过期一次的计时器。KeSetTimerEx接受一个可选的句点参数,该参数指定定期计时器间隔。
//KeSetTimerEx可以设置循环执行DPC
KeSetTimer(&Timer, DueTime, &Dpc);
//测试计时器信号
Timeout.QuadPart = -10 * 1000 * 1000 * 3;
status = KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, &Timeout);
if (status == STATUS_TIMEOUT)
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: 1 is STATUS_TIMEOUT");
}
else if (status == STATUS_SUCCESS)
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: 1 is STATUS_SUCCESS");
}
else
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: 1 is other");
}
status = KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
if (status == STATUS_TIMEOUT)
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: 2 is STATUS_TIMEOUT");
}
else if (status == STATUS_SUCCESS)
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: 2 is STATUS_SUCCESS");
}
else
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: 2 is other");
}
Timeout.QuadPart = -10 * 1000 * 1000 * 2;
for (int i = 3; i < 6; i++)
{
status = KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, &Timeout2);
if (status == STATUS_TIMEOUT)
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: %d is STATUS_TIMEOUT",i);
}
else if (status == STATUS_SUCCESS)
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: %d is STATUS_SUCCESS", i);
}
else
{
DbgPrint("DriverEntry -> KeWaitForSingleObject: %d is other", i);
}
}
//测试结果 :
//0 计时器设置为5秒
//1 当设置等待超时设置为3秒 -> 打印[DriverEntry -> KeWaitForSingleObject: First is STATUS_TIMEOUT]. 此时计时器倒计时还未结束,DPC未执行,KTIMER为无信号
//2 当不设置等待超时 -> 先打印[KdeferredRoutine],在打印[DriverEntry -> KeWaitForSingleObject: Second is STATUS_SUCCESS]. 此时计时器超时,DPC执行,然后将KTIMER为无信号设置为有信号
//3 for循环 -> 打印[DriverEntry -> KeWaitForSingleObject: %d is STATUS_SUCCESS]. -> 当计时器超时执行DPC后,计时器一直为有信号
DbgPrint("DriverEntry Success");
return status;
}