封装定时器
参考:天书夜读_从汇编语言到Windows内核编程
结构体:
typedef struct _TIMER_INFO //定时器结构体
{
KDPC dpc;
KTIMER timer;
PKDEFERRED_ROUTINE timerFunc;
PVOID privateInfo; //用来传递数据
} TIMER_INFO, * PTIMER_INFO;
初始化一个定时器:
void TimerInit(PTIMER_INFO timerInfo, PKDEFERRED_ROUTINE timerFunc)
{
//初始化DPC
KeInitializeDpc(&(timerInfo->dpc), timerFunc, (PVOID)timerInfo);
timerInfo->timerFunc = timerFunc;
//初始化定时器
KeInitializeTimer(&(timerInfo->timer));
}
设置定时器:
这个定时器要一直通过循环调用这个来实现:
BOOLEAN TimerSet(PTIMER_INFO timerInfo, ULONG msec, PVOID privateInfo)
{
LARGE_INTEGER due;
BOOLEAN bRet = FALSE;
//转换时间
due.QuadPart = -10000 * msec;
//设置上下文
timerInfo->privateInfo = privateInfo;
//设置定时器
bRet = KeSetTimer(&(timerInfo->timer), due, &(timerInfo->dpc));
return bRet;
}
停止定时器:
void TimerDestroy(PTIMER_INFO timerInfo)
{
KeCancelTimer(&(timerInfo->timer));
}
使用例子
定义一个定时器的回调函数格式都是这样的:
//函数名字可以修改
void OnTimer(IN struct _KDPC* Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
例子:
void OnTimer(IN struct _KDPC* Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
PTIMER_INFO timer = (PTIMER_INFO)DeferredContext;
PVOID privateInfo = timer->privateInfo;
DbgPrint("过去1秒! \n");
//打印我传入的参数
DbgPrint("CurrentTime = %ws \n", (PWCHAR)privateInfo);
//再次调用,
TimerSet(timer, 1000, privateInfo);
//用于测试,再次掉用 TimerSet 是否会导致和递归一样内存一直被占用没有通过函数结束释放
DbgPrint("过去2秒! \n");
}
//一个全局的定时器
PTIMER_INFO g_TimeTimerInfo;
//驱动入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) //返回一个地址、返回驱动被注册到注册表的某个地方
{
DbgPrint("pdriver = %wZ, , %x\n", pReg, pDriver);
//随便传个参数
WCHAR szTime[32] = L"1111";
//设定定时器
g_TimeTimerInfo = (PTIMER_INFO)ExAllocatePool(PagedPool, sizeof(TIMER_INFO));
RtlZeroMemory(g_TimeTimerInfo, sizeof(TIMER_INFO));
TimerInit(g_TimeTimerInfo, OnTimer);
TimerSet(g_TimeTimerInfo, 1000, (PVOID)szTime); //1000毫秒
return STATUS_SUCCESS;
}