Sprawdzenie uptime systemu w Windows XP Home

Opisałem już, w jaki sposób sprawdzić w systemie Windows XP Professional uptime systemu (przy okazji opisu sprawdzenia daty instalacji systemu). Wersje Home oraz Media Center nie posiadają jednak tej możliwości. Ponieważ mnie osobiście trochę to irytowało, postanowiłem napisać sobie stosowny program.

Jak sobie założyłem, tak też zrobiłem i powstało z tego coś takiego (C++):

/* $Id: uptime.c,v 1.10 2007/12/27 00:06:58 josh Exp $
 * uptime.c -- Michal Zimniak
 */

#include <windows.h>
#include <stdio.h>

/* define some C99 types for windows */
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int64 uint64_t;
typedef unsigned __int8 uint8_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
typedef __int64 int64_t;
typedef __int8 int8_t;

static char msgstr[4096];
static int users = 0;

#define KEY_SYSTEM    L"2"
#define IDX_UPTIME    674
#define IDX_PROCQUEUE    44

static void get_boottime(ULARGE_INTEGER *boottime,
             ULARGE_INTEGER *nowtime,
             uint32_t *procqueue)
{
    BYTE pbuf[4096];
    PPERF_DATA_BLOCK ppdb = (PPERF_DATA_BLOCK) pbuf;
    DWORD psz = sizeof(pbuf);
    PPERF_OBJECT_TYPE ppot;
    PPERF_COUNTER_DEFINITION ppcd;
    PPERF_COUNTER_BLOCK ppcb;
    DWORD i;

    memset(pbuf, 0, psz);
    nowtime->QuadPart = boottime->QuadPart = 0;    /* 0 = error */

    /* get current 64-bit boottime in 100ns units */
    RegQueryValueExW(HKEY_PERFORMANCE_DATA, KEY_SYSTEM,
        NULL, NULL, pbuf, &psz);
    RegCloseKey(HKEY_PERFORMANCE_DATA);

    if(memcmp(pbuf, L"PERF", 8)) {
        /* PERF_DATA_BLOCK signature not present */
        return;
    }

    /* parse returned performance data */
    ppot = (PPERF_OBJECT_TYPE) &pbuf[ppdb->HeaderLength];

    ppcd = (PPERF_COUNTER_DEFINITION)
        &pbuf[ppdb->HeaderLength + ppot->HeaderLength];

    ppcb = (PPERF_COUNTER_BLOCK)
        &(((uint8_t *)ppot)[ppot->DefinitionLength]);

    nowtime->QuadPart = ppdb->PerfTime100nSec.QuadPart;

    /* get uptime and processor queue length */
    for (i = 0; i < ppot->NumCounters; i++) {
        if (ppcd->CounterNameTitleIndex == IDX_UPTIME) {
            boottime->QuadPart = (int64_t) *(uint64_t *)
                &(((uint8_t *)ppcb)[ppcd->CounterOffset]);
        }
        if (ppcd->CounterNameTitleIndex == IDX_PROCQUEUE) {
            *procqueue = (int32_t) *(uint32_t *)
                &(((uint8_t *)ppcb)[ppcd->CounterOffset]);
        }
        ppcd++;
    }
}

static BOOL CALLBACK ewsproc(LPTSTR lpszWindowStation, LPARAM lParam)
{
    users++;
    return TRUE;
}

static void uptime(void)
{
    ULARGE_INTEGER bt, nt, ut;
    uint32_t procqueue, days;
    SYSTEMTIME bst, nst, ust;
    TCHAR btstr[128], ntstr[128], bdstr[128];

    get_boottime(&bt, &nt, &procqueue);
    ut.QuadPart = nt.QuadPart - bt.QuadPart;
    FileTimeToSystemTime((FILETIME *) &bt, &bst);
    FileTimeToSystemTime((FILETIME *) &nt, &nst);
    FileTimeToSystemTime((FILETIME *) &ut, &ust);
    SystemTimeToTzSpecificLocalTime(NULL, &bst, &bst);
    SystemTimeToTzSpecificLocalTime(NULL, &nst, &nst);
    GetTimeFormat(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &bst, NULL,
              btstr, sizeof(btstr));
    GetTimeFormat(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &nst, NULL,
              ntstr, sizeof(ntstr));
    GetDateFormat(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP,
              &bst, NULL, bdstr, sizeof(bdstr));
    sprintf(msgstr, " %s  up ", ntstr);
    ut.QuadPart /= 864000000000;

    days = (uint32_t) ut.QuadPart;
    if (days > 1) {
        sprintf(&msgstr[strlen(msgstr)], "%d days, ", days);
    } else if (days == 1) {
        sprintf(&msgstr[strlen(msgstr)], "1 day, ");
    }
    sprintf(&msgstr[strlen(msgstr)], "%02d:%02d:%02d, ",
        ust.wHour, ust.wMinute, ust.wSecond);

    sprintf(&msgstr[strlen(msgstr)], "%d user%s, ", users,
        users == 1 ? "" : "s");

    sprintf(&msgstr[strlen(msgstr)], "boot %s %s, "
        "load: %d", bdstr, btstr, procqueue);
    printf(msgstr);
}

int main(int argc, char **argv)
{
    int count = atoi(argv[argc - 1]);

    EnumWindowStations(ewsproc, 0);
    uptime();
    if (count==0) printf("\r\n"); else printf("\r");
    fflush(stdout);
    for (; count > 0; count--) {
        Sleep(1000);
        printf("\r");
        uptime();
        if (count == 1) {
            printf("\r\n");
        }
        fflush(stdout);
    }
    return 0;
}
/* EOF */

Wynik działania programu:

Do ściągniecia:

Plik skompilowany

Źródło