2012年12月10日星期一

KeSetTimerEx.C


/*
时间很重要,在现实中如是,在计算机中亦是,如时钟中断。
时间怎能不会,特别是阴阳历转换。
此文展示几种用法,暂命名为KeSetTimerEx.C,
因为IoInitializeTimer需要一个设备对象。
KeSetTimerEx对dpc可有可无,使用更方便。

本文的不足之处,可能是定时器对象的删除等,
不然内存泄露,verifier.exe报错。

made by correy
made at 2012.12.10
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/

#include <ntddk.h>

PVOID g_pkThread;

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    PDEVICE_OBJECT pdoNextDeviceObj;

    KeWaitForSingleObject(g_pkThread, Executive, KernelMode, FALSE, NULL);
    ObDereferenceObject(g_pkThread);

    pdoNextDeviceObj = DriverObject->DeviceObject;//pdoGlobalDrvObj
    //IoDeleteSymbolicLink(&usSymlinkName);//本程序没有创建符号链接。

    while(pdoNextDeviceObj) // Delete all the device objects
    {
        PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
        pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
        IoDeleteDevice(pdoThisDeviceObj);
    }
}

KSTART_ROUTINE ThreadStart;
VOID ThreadStart(__in PVOID  StartContext)
{
    KdPrint(("创建线程的完整规范示例用法,注意卸载的时候!\n"));
    PsTerminateSystemThread(STATUS_SUCCESS);
}

IO_TIMER_ROUTINE IoTimer;
VOID IoTimer(__in PDEVICE_OBJECT DeviceObject, __in_opt PVOID  Context)
{
    DbgPrint("i am in IoTimer!\n");
    KeSetEvent((PKEVENT)Context, 0, FALSE);
}

KDEFERRED_ROUTINE CustomDpc;
VOID CustomDpc(
               __in struct _KDPC  *Dpc,
               __in_opt PVOID  DeferredContext,
               __in_opt PVOID  SystemArgument1,
               __in_opt PVOID  SystemArgument2)
{
    DbgPrint("i am in CustomDpc!\n");
    KeSetEvent((PKEVENT)DeferredContext, IO_NO_INCREMENT, FALSE);//结束。
    //还可以再调用KeSetTimer,但是要注意次数,和参数。  特别注意时间。  
}

DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    LARGE_INTEGER   li;
    HANDLE  ThreadHandle;
    UNICODE_STRING usDeviceName;
    PDEVICE_OBJECT pdoDeviceObj = 0;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    KEVENT  ke;
    KTIMER kt;
    BOOLEAN b;
    KDPC  dpc;
    int i;

    //KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
    DriverObject->DriverUnload = Unload;

    //////////////////////////////////////////////////////////////////////////

    KdPrint(("暂停5秒:KeStallExecutionProcessor\n"));
    KeStallExecutionProcessor(5000000);//5秒钟。

    //////////////////////////////////////////////////////////////////////////
    KdPrint(("暂停5秒:KeDelayExecutionThread\n"));
    li.QuadPart = (5 * (((-10) * 1000) * 1000)); //负数是暂停5秒钟。
    status = KeDelayExecutionThread(KernelMode, FALSE, &li);
    if (status != STATUS_SUCCESS)
    {
        KdPrint(("KeDelayExecutionThread return:%d\n", status));
        //return r;
    }
    //////////////////////////////////////////////////////////////////////////
    RtlInitUnicodeString(&usDeviceName, L"\\Device\\correy"); //必须创建设备。
    status = IoCreateDevice(DriverObject, 0, &usDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pdoDeviceObj);
    if(!NT_SUCCESS(status))
    {
        return status;
    }

    KeInitializeEvent(&ke, NotificationEvent, FALSE);

    IoInitializeTimer(pdoDeviceObj, IoTimer, &ke);//感觉和WorkItem差不多,只不过把方法改名为开始和结束。
    IoStartTimer(pdoDeviceObj);

    KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);
    IoStopTimer(pdoDeviceObj);
    //////////////////////////////////////////////////////////////////////////
    KeInitializeTimerEx(&kt, SynchronizationTimer);

    li.QuadPart = (5 * (((-10) * 1000) * 1000));

    //第三个参数,如果是负数,会失败,并且蓝屏。并且不能大于#define MAXLONG     0x7fffffff  // winnt
    b = KeSetTimerEx(&kt, li, 5000000, 0);//其实有5个参数。如kmdkit里面的用法,ida里面也是的。
    if (b == 1)
    {
        KdPrint(("the timer object was already in the system timer queue\n"));
        //继续前进,千万不要退出。注意,注意,再注意。
    }

    for (i = 0; i < 3; i++)
    {
        KeWaitForSingleObject(&kt, Executive, KernelMode, FALSE, NULL);
        KdPrint(("KeSetTimer:5秒%d次\n", i+1));
        KeSetTimerEx(&kt, li, 5000000, 0);
    }

    b = KeCancelTimer(&kt);
    if (b == 0)
    {
        return b;
    }
    //////////////////////////////////////////////////////////////////////////
    KeResetEvent(&ke);
    KeInitializeTimerEx(&kt, SynchronizationTimer);
    KeInitializeDpc(&dpc, CustomDpc, &ke);//最后一个参数是传递用的。

    li.QuadPart = (5 * (((-10) * 1000) * 1000));

    KdPrint(("5秒后调用CustomDpc函数\n", i));

    //第三个参数,如果是负数,会失败,并且蓝屏。并且不能大于#define MAXLONG     0x7fffffff  // winnt
    b = KeSetTimerEx(&kt, li, 5000000, &dpc);//其实有5个参数。
    if (b == 1)
    {
        KdPrint(("the timer object was already in the system timer queue\n"));
        //继续前进,千万不要退出。注意,注意,再注意。
    }

    KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);

    b = KeCancelTimer(&kt);
    if (b == 0)
    {
        return b;
    }

    KeClearEvent(&ke);
    KeCancelTimer(&kt);
    //////////////////////////////////////////////////////////////////////////
    status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadStart, NULL);
    if (status != STATUS_SUCCESS)
    {
        KdPrint(("PsCreateSystemThread return:%d\n", status));
        //return r;
    }
    else
    {
        ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &g_pkThread, NULL);
        ZwClose(ThreadHandle);
    }
    //////////////////////////////////////////////////////////////////////////

    return 0;
}

没有评论:

发表评论