Windows 内核获取开机所用时间及当前系统时间

获取开机时间并不像应用层简单的调用一个 API 就搞定了,在内核需要 GetTickCount 获取一个滴答数,然后把这个滴答数转为毫秒,再进行运算即可得出开的时间。以下是获取开机多少分钟和当前系统时间的结果,代码在下方:

tick count = 2 minutes.
time = 2016-04-01 00:39:26

实现代码

#include <ntddk.h>
#include <ntstrsafe.h>

// 获取系统开机一共经历过的时间(毫秒)
void MyGetTickCount(PULONG msec)
{
    LARGE_INTEGER tick_count;
    ULONG myinc = KeQueryTimeIncrement();
    KeQueryTickCount(&tick_count);
    tick_count.QuadPart *= myinc;
    tick_count.QuadPart /= 10000;
    *msec = tick_count.LowPart;
}

PWCHAR MyCurTimeStr()
{
    LARGE_INTEGER snow, now;
    TIME_FIELDS now_fields;
    static WCHAR time_str[32] = { 0 };
    // 获取格林威治时间
    KeQuerySystemTime(&snow);
    // 转为本地时间
    ExSystemTimeToLocalTime(&snow, &now);
    // 转为时间的结构体
    RtlTimeToTimeFields(&now, &now_fields);
    // 将结构体信息拼接起来
    RtlStringCchPrintfW(
        time_str,
        32,
        L"%4d-%02d-%02d %02d:%02d:%02d",
        now_fields.Year, now_fields.Month, now_fields.Day,
        now_fields.Hour, now_fields.Minute, now_fields.Second);

    return time_str;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    ULONG           msec;
    UNICODE_STRING  uTime;
    PWCHAR          time_str;

    MyGetTickCount(&msec);
    KdPrint(("tick count = %ld minutes.\r\n", msec / 1000 / 60));

    time_str = MyCurTimeStr();
    RtlInitEmptyUnicodeString(&uTime, time_str, wcslen(time_str) * sizeof(WCHAR));
    uTime.Length = wcslen(time_str) * sizeof(WCHAR);
    KdPrint(("time = %wZ\r\n", &uTime));

    return STATUS_UNSUCCESSFUL;
}

发表评论