Question

I'm trying to extract boot time by getting current time SYSTEMTIME structure, then converting it to FILETIME which I then convert to ULARGE_INTEGER from which I subtract GetTickCount64() and then proceed on converting everything back to SYSTEMTIME.

I'm comparing this function to 'NET STATISTICS WORKSTATION' and for some reason my output is off by several hours, which don't seem to match any timezone differences.

Here's visual studio example code:

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#define KILOBYTE 1024
#define BUFF KILOBYTE


int _tmain(int argc, _TCHAR* argv[])
{
    ULARGE_INTEGER ticks, ftime;
    SYSTEMTIME current, final;
    FILETIME ft, fout;

    OSVERSIONINFOEX osvi;

    char output[BUFF];
    int retval=0;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    ZeroMemory(&final, sizeof(SYSTEMTIME));
    GetVersionEx((OSVERSIONINFO *) &osvi);

    if (osvi.dwBuildNumber >= 6000) ticks.QuadPart = GetTickCount64();
    else ticks.QuadPart = GetTickCount();
    //Convert miliseconds to 100-nanosecond time intervals
    ticks.QuadPart = ticks.QuadPart * 10000;
    //GetLocalTime(&current); -- //doesn't really fix the problem
    GetSystemTime(&current);
    SystemTimeToFileTime(&current, &ft);
    printf("INITIAL: Filetime lowdatetime %u, highdatetime %u\r\n", ft.dwLowDateTime, ft.dwHighDateTime);
    ftime.LowPart=ft.dwLowDateTime;
    ftime.HighPart=ft.dwHighDateTime;
    //subtract boot time interval from current time
    ftime.QuadPart = ftime.QuadPart - ticks.QuadPart;
    //Convert ULARGE_INT back to FILETIME
    fout.dwLowDateTime = ftime.LowPart;
    fout.dwHighDateTime = ftime.HighPart;
    printf("FINAL: Filetime lowdatetime %u, highdatetime %u\r\n", fout.dwLowDateTime, fout.dwHighDateTime);
    //Convert FILETIME back to system time
    retval = FileTimeToSystemTime(&fout, &final);
    printf("Return value is %d\r\n", retval);
    printf("Current time %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n", current.wYear, current.wMonth, current.wDay,  current.wHour, current.wMinute, current.wSecond);
    printf("Return time %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n", final.wYear, final.wMonth, final.wDay,  final.wHour, final.wMinute, final.wSecond);
    return 0;
}
Was it helpful?

Solution

I ran it and found that it works correctly when using GetLocalTime as opposed to GetSystemTime, which is expressed in UTC. So it would make sense that GetSystemTime would not necessarily match the "clock" on the PC.

Other than that, though, the issue could possibly be the call to GetVersionEx. As written, I think it will always return zeros for all values. You need this line prior to calling it:

osvi.dwOSVersionInfoSize = sizeof( osvi );

Otherwise that dwBuildNumber will be zero and it will call GetTickCount, which is only good for 49 days or so. On the other hand, if that were the case, I think you would get a result with a much larger difference.

I'm not completely sure that (as written) the check is necessary to choose which tick count function to call. If GetTickCount64 doesn't exist, the app would not load due to the missing entrypoint (unless perhaps delay loading was used ... I'm not sure in that case). I believe that it would be necessary to use LoadLibrary and GetProcAddress to make the decision dynamically between those two functions and have it work on an older platform.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top