Annotation of truecrypt/common/random.c, revision 1.1

1.1     ! root        1: /* Copyright (C) 2004 TrueCrypt Team, truecrypt.org
        !             2:    This product uses components written by Paul Le Roux <[email protected]> */
        !             3: 
        !             4: #include "TCdefs.h"
        !             5: 
        !             6: #include <tlhelp32.h>
        !             7: 
        !             8: #include "crypto.h"
        !             9: #include "crc.h"
        !            10: #include "random.h"
        !            11: #include "apidrvr.h"
        !            12: #include "dlgcode.h"
        !            13: 
        !            14: 
        !            15: /* random management defines & pool pointers */
        !            16: #define POOLSIZE 256
        !            17: #define RANDOMPOOL_ALLOCSIZE   ( ( POOLSIZE + SHA_DIGESTSIZE - 1 ) \
        !            18:        / SHA_DIGESTSIZE ) * SHA_DIGESTSIZE
        !            19: 
        !            20: unsigned char *pRandPool = NULL;
        !            21: int nRandIndex = 0;
        !            22: 
        !            23: /* Macro to add a single byte to the pool */
        !            24: #define RandaddByte(x) {\
        !            25:        if (nRandIndex==POOLSIZE) nRandIndex = 0;\
        !            26:        pRandPool[nRandIndex] = (unsigned char) ((unsigned char)x + pRandPool[nRandIndex]); \
        !            27:        nRandIndex++; \
        !            28:        Randmix(); \
        !            29:        }
        !            30: 
        !            31: /* Macro to add four bytes to the pool */
        !            32: #define RandaddLong(x) _RandaddLong((unsigned long)x);
        !            33: 
        !            34: #pragma warning( disable : 4710 ) /* inline func. not expanded warning */
        !            35: 
        !            36: _inline void _RandaddLong(unsigned long x)
        !            37: {
        !            38:        RandaddByte(x); 
        !            39:        RandaddByte((x >> 8)); 
        !            40:        RandaddByte((x >> 16));
        !            41:        RandaddByte((x >> 24));
        !            42: }
        !            43: 
        !            44: HHOOK hMouse = NULL;           /* Mouse hook for the random number generator */
        !            45: HHOOK hKeyboard = NULL;                /* Keyboard hook for the random number
        !            46:                                   generator */
        !            47: 
        !            48: /* Variables for thread control, the thread is used to gather up info about
        !            49:    the system in in the background */
        !            50: CRITICAL_SECTION critRandProt; /* The critical section */
        !            51: BOOL volatile bThreadTerminate = FALSE;        /* This variable is shared among
        !            52:                                           thread's so its made volatile */
        !            53: BOOL bDidSlowPoll = FALSE;     /* We do the slow poll only once */
        !            54: 
        !            55: /* Network library handle for the slowPollWinNT function */
        !            56: HANDLE hNetAPI32 = NULL;
        !            57: 
        !            58: BOOL bRandDidInit = FALSE;
        !            59: 
        !            60: /* Init the random number generator, setup the hooks, and start the thread */
        !            61: int
        !            62: Randinit ()
        !            63: {
        !            64:        HANDLE threadID;
        !            65: 
        !            66:        if(bRandDidInit == TRUE) return 0;
        !            67: 
        !            68:        InitializeCriticalSection (&critRandProt);
        !            69: 
        !            70:        bRandDidInit = TRUE;
        !            71: 
        !            72:        pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE);
        !            73:        if (pRandPool == NULL)
        !            74:                goto error;
        !            75:        else
        !            76:                memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE);
        !            77: 
        !            78:        hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ());
        !            79:        hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ());
        !            80:        if (hMouse == 0 || hKeyboard == 0)
        !            81:                goto error;
        !            82: 
        !            83:        threadID = (HANDLE) _beginthread (ThreadSafeThreadFunction, 8192, NULL);
        !            84:        if (threadID == (HANDLE) - 1)
        !            85:                goto error;
        !            86: 
        !            87:        return 0;
        !            88: 
        !            89:       error:
        !            90:        Randfree ();
        !            91:        return 1;
        !            92: }
        !            93: 
        !            94: /* Close everything down, including the thread which is closed down by
        !            95:    setting a flag which eventually causes the thread function to exit */
        !            96: void
        !            97: Randfree ()
        !            98: {
        !            99:        if (bRandDidInit == FALSE)
        !           100:                return;
        !           101: 
        !           102:        EnterCriticalSection (&critRandProt);
        !           103: 
        !           104:        if (hMouse != 0)
        !           105:                UnhookWindowsHookEx (hMouse);
        !           106:        if (hKeyboard != 0)
        !           107:                UnhookWindowsHookEx (hKeyboard);
        !           108: 
        !           109:        bThreadTerminate = TRUE;
        !           110: 
        !           111:        LeaveCriticalSection (&critRandProt);
        !           112: 
        !           113:        for (;;)
        !           114:        {
        !           115:                Sleep (250);
        !           116:                EnterCriticalSection (&critRandProt);
        !           117:                if (bThreadTerminate == FALSE)
        !           118:                {
        !           119:                        LeaveCriticalSection (&critRandProt);
        !           120:                        break;
        !           121:                }
        !           122:                LeaveCriticalSection (&critRandProt);
        !           123:        }
        !           124: 
        !           125:        if (pRandPool != NULL)
        !           126:        {
        !           127:                burn (pRandPool, RANDOMPOOL_ALLOCSIZE);
        !           128:                TCfree (pRandPool);
        !           129:                pRandPool = NULL;
        !           130:        }
        !           131: 
        !           132:        if (hNetAPI32 != 0)
        !           133:        {
        !           134:                FreeLibrary (hNetAPI32);
        !           135:                hNetAPI32 = NULL;
        !           136:        }
        !           137: 
        !           138:        hMouse = NULL;
        !           139:        hKeyboard = NULL;
        !           140:        nRandIndex = 0;
        !           141:        bThreadTerminate = FALSE;
        !           142:        DeleteCriticalSection (&critRandProt);
        !           143:        bRandDidInit = FALSE;
        !           144: }
        !           145: 
        !           146: /* Mix random pool with the hash function */
        !           147: void
        !           148: Randmix ()
        !           149: {
        !           150:        int i;
        !           151: 
        !           152:        for (i = 0; i < POOLSIZE; i += SHA_DIGESTSIZE)
        !           153:        {
        !           154:                unsigned char inputBuffer[SHA_BLOCKSIZE];
        !           155:                int j;
        !           156: 
        !           157:                /* Copy SHA_BLOCKSIZE bytes from the circular buffer into the
        !           158:                   hash data buffer, hash the data, and copy the result back
        !           159:                   into the random pool */
        !           160:                for (j = 0; j < SHA_BLOCKSIZE; j++)
        !           161:                        inputBuffer[j] = pRandPool[(i + j) % POOLSIZE];
        !           162:                SHA1TRANSFORM ((unsigned long *) (pRandPool + i), inputBuffer);
        !           163:                memset (inputBuffer, 0, SHA_BLOCKSIZE);
        !           164:        }
        !           165: }
        !           166: 
        !           167: /* Add a buffer to the pool */
        !           168: void
        !           169: RandaddBuf (void *buf, int len)
        !           170: {
        !           171:        int i;
        !           172:        for (i = 0; i < len; i++)
        !           173:        {
        !           174:                RandaddByte (((unsigned char *) buf)[i]);
        !           175:        }
        !           176: }
        !           177: 
        !           178: void
        !           179: RandpeekBytes (char *buf, int len)
        !           180: {
        !           181:        EnterCriticalSection (&critRandProt);
        !           182:        memcpy (buf, pRandPool, len);
        !           183:        LeaveCriticalSection (&critRandProt);
        !           184: }
        !           185: 
        !           186: /* Get a certain amount of true random bytes from the pool */
        !           187: void
        !           188: RandgetBytes (char *buf, int len)
        !           189: {
        !           190:        int i;
        !           191: 
        !           192:        EnterCriticalSection (&critRandProt);
        !           193: 
        !           194:        FastPoll ();
        !           195: 
        !           196:        if (bDidSlowPoll == FALSE)
        !           197:        {
        !           198:                bDidSlowPoll = TRUE;
        !           199: 
        !           200: #ifndef _DEBUG
        !           201:                if (nCurrentOS == WIN_NT)
        !           202:                        SlowPollWinNT ();
        !           203:                else
        !           204:                        SlowPollWin9x ();
        !           205: #endif
        !           206:        }
        !           207:        /* Then mix the pool */
        !           208:        Randmix ();
        !           209: 
        !           210:        /* There's never more than POOLSIZE worth of randomess */
        !           211:        if (len > POOLSIZE)
        !           212:                len = POOLSIZE;
        !           213: 
        !           214:        /* Extract out the random bytes needed */
        !           215:        memcpy (buf, pRandPool, len);
        !           216: 
        !           217:        /* Now invert the pool */
        !           218:        for (i = 0; i < POOLSIZE / 4; i++)
        !           219:        {
        !           220:                ((unsigned long *) pRandPool)[i] = ~((unsigned long *) pRandPool)[i];
        !           221:        }
        !           222: 
        !           223:        /* Now remix the pool, creating the new pool */
        !           224:        Randmix ();
        !           225: 
        !           226:        LeaveCriticalSection (&critRandProt);
        !           227: }
        !           228: 
        !           229: /* Capture the mouse, and as long as the event is not the same as the last
        !           230:    two events :- add a crc of the event, and a crc of the time difference
        !           231:    between this event and the last + the current time to the pool */
        !           232: LRESULT CALLBACK
        !           233: MouseProc (int nCode, WPARAM wParam, LPARAM lParam)
        !           234: {
        !           235:        static DWORD dwLastTimer;
        !           236:        static unsigned long lastCrc, lastCrc2;
        !           237:        MOUSEHOOKSTRUCT *lpMouse = (MOUSEHOOKSTRUCT *) lParam;
        !           238: 
        !           239:        if (nCode < 0)
        !           240:                return CallNextHookEx (hMouse, nCode, wParam, lParam);
        !           241:        else
        !           242:        {
        !           243:                DWORD dwTimer = GetTickCount ();
        !           244:                DWORD j = dwLastTimer - dwTimer;
        !           245:                unsigned long crc = 0L;
        !           246:                int i;
        !           247: 
        !           248:                dwLastTimer = dwTimer;
        !           249: 
        !           250:                for (i = 0; i < sizeof (MOUSEHOOKSTRUCT); i++)
        !           251:                {
        !           252:                        crc = UPDC32 (((unsigned char *) lpMouse)[i], crc);
        !           253:                }
        !           254: 
        !           255:                if (crc != lastCrc && crc != lastCrc2)
        !           256:                {
        !           257:                        unsigned long timeCrc = 0L;
        !           258: 
        !           259:                        for (i = 0; i < 4; i++)
        !           260:                        {
        !           261:                                timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc);
        !           262:                        }
        !           263: 
        !           264:                        for (i = 0; i < 4; i++)
        !           265:                        {
        !           266:                                timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc);
        !           267:                        }
        !           268: 
        !           269:                        EnterCriticalSection (&critRandProt);
        !           270:                        RandaddLong (timeCrc);
        !           271:                        RandaddLong (crc);
        !           272:                        LeaveCriticalSection (&critRandProt);
        !           273:                }
        !           274:                lastCrc2 = lastCrc;
        !           275:                lastCrc = crc;
        !           276: 
        !           277:        }
        !           278:        return 0;
        !           279: }
        !           280: 
        !           281: /* Capture the keyboard, as long as the event is not the same as the last two
        !           282:    events :- add a crc of the event to the pool along with a crc of the time
        !           283:    difference between this event and the last */
        !           284: LRESULT CALLBACK
        !           285: KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam)
        !           286: {
        !           287:        static int lLastKey, lLastKey2;
        !           288:        static DWORD dwLastTimer;
        !           289:        int nKey = (lParam & 0x00ff0000) >> 16;
        !           290:        int nCapture = 0;
        !           291: 
        !           292:        if (nCode < 0)
        !           293:                return CallNextHookEx (hMouse, nCode, wParam, lParam);
        !           294: 
        !           295:        if ((lParam & 0x0000ffff) == 1 && !(lParam & 0x20000000) &&
        !           296:            (lParam & 0x80000000))
        !           297:        {
        !           298:                if (nKey != lLastKey)
        !           299:                        nCapture = 1;   /* Capture this key */
        !           300:                else if (nKey != lLastKey2)
        !           301:                        nCapture = 1;   /* Allow for one repeat */
        !           302:        }
        !           303:        if (nCapture)
        !           304:        {
        !           305:                DWORD dwTimer = GetTickCount ();
        !           306:                DWORD j = dwLastTimer - dwTimer;
        !           307:                unsigned long timeCrc = 0L;
        !           308:                int i;
        !           309: 
        !           310:                dwLastTimer = dwTimer;
        !           311:                lLastKey2 = lLastKey;
        !           312:                lLastKey = nKey;
        !           313: 
        !           314:                for (i = 0; i < 4; i++)
        !           315:                {
        !           316:                        timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc);
        !           317:                }
        !           318: 
        !           319:                for (i = 0; i < 4; i++)
        !           320:                {
        !           321:                        timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc);
        !           322:                }
        !           323: 
        !           324:                EnterCriticalSection (&critRandProt);
        !           325:                RandaddLong (lParam);
        !           326:                RandaddLong (timeCrc);
        !           327:                LeaveCriticalSection (&critRandProt);
        !           328:        }
        !           329:        return 0;
        !           330: }
        !           331: 
        !           332: /* This is the thread function which will poll the system for randomness */
        !           333: void
        !           334: ThreadSafeThreadFunction (void *dummy)
        !           335: {
        !           336:        if (dummy);             /* Remove unused parameter warning */
        !           337: 
        !           338:        for (;;)
        !           339:        {
        !           340:                EnterCriticalSection (&critRandProt);
        !           341: 
        !           342:                if (bThreadTerminate == TRUE)
        !           343:                {
        !           344:                        bThreadTerminate = FALSE;
        !           345:                        LeaveCriticalSection (&critRandProt);
        !           346:                        _endthread ();
        !           347:                }
        !           348:                else
        !           349:                {
        !           350:                        FastPoll ();
        !           351:                }
        !           352: 
        !           353:                LeaveCriticalSection (&critRandProt);
        !           354: 
        !           355:                Sleep (250);
        !           356:        }
        !           357: }
        !           358: 
        !           359: /* Type definitions for function pointers to call NetAPI32 functions */
        !           360: 
        !           361: typedef
        !           362:   DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService,
        !           363:                                     DWORD dwLevel, DWORD dwOptions,
        !           364:                                     LPBYTE * lpBuffer);
        !           365: typedef
        !           366:   DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer);
        !           367: typedef
        !           368:   DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer);
        !           369: 
        !           370: NETSTATISTICSGET pNetStatisticsGet = NULL;
        !           371: NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
        !           372: NETAPIBUFFERFREE pNetApiBufferFree = NULL;
        !           373: 
        !           374: /* This is the slowpoll function which gathers up network/hard drive
        !           375:    performance data for the random pool */
        !           376: void
        !           377: SlowPollWinNT (void)
        !           378: {
        !           379:        static int isWorkstation = -1;
        !           380:        PPERF_DATA_BLOCK pPerfData;
        !           381:        static int cbPerfData = 0x10000;
        !           382:        HANDLE hDevice;
        !           383:        LPBYTE lpBuffer;
        !           384:        DWORD dwSize, status;
        !           385:        LPWSTR lpszLanW, lpszLanS;
        !           386:        int nDrive;
        !           387: 
        !           388:        /* Find out whether this is an NT server or workstation if necessary */
        !           389:        if (isWorkstation == -1)
        !           390:        {
        !           391:                HKEY hKey;
        !           392: 
        !           393:                if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
        !           394:                       "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
        !           395:                                  0, KEY_READ, &hKey) == ERROR_SUCCESS)
        !           396:                {
        !           397:                        unsigned char szValue[32];
        !           398:                        dwSize = sizeof (szValue);
        !           399: 
        !           400:                        isWorkstation = TRUE;
        !           401:                        status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
        !           402:                                                  szValue, &dwSize);
        !           403: 
        !           404:                        if (status == ERROR_SUCCESS && _stricmp ((char *) szValue, "WinNT"))
        !           405:                                /* Note: There are (at least) three cases for
        !           406:                                   ProductType: WinNT = NT Workstation,
        !           407:                                   ServerNT = NT Server, LanmanNT = NT Server
        !           408:                                   acting as a Domain Controller */
        !           409:                                isWorkstation = FALSE;
        !           410: 
        !           411:                        RegCloseKey (hKey);
        !           412:                }
        !           413:        }
        !           414:        /* Initialize the NetAPI32 function pointers if necessary */
        !           415:        if (hNetAPI32 == NULL)
        !           416:        {
        !           417:                /* Obtain a handle to the module containing the Lan Manager
        !           418:                   functions */
        !           419:                hNetAPI32 = LoadLibrary ("NETAPI32.DLL");
        !           420:                if (hNetAPI32 != NULL)
        !           421:                {
        !           422:                        /* Now get pointers to the functions */
        !           423:                        pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32,
        !           424:                                                        "NetStatisticsGet");
        !           425:                        pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32,
        !           426:                                                        "NetApiBufferSize");
        !           427:                        pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32,
        !           428:                                                        "NetApiBufferFree");
        !           429: 
        !           430:                        /* Make sure we got valid pointers for every NetAPI32
        !           431:                           function */
        !           432:                        if (pNetStatisticsGet == NULL ||
        !           433:                            pNetApiBufferSize == NULL ||
        !           434:                            pNetApiBufferFree == NULL)
        !           435:                        {
        !           436:                                /* Free the library reference and reset the
        !           437:                                   static handle */
        !           438:                                FreeLibrary (hNetAPI32);
        !           439:                                hNetAPI32 = NULL;
        !           440:                        }
        !           441:                }
        !           442:        }
        !           443: 
        !           444:        /* Get network statistics.  Note: Both NT Workstation and NT Server
        !           445:           by default will be running both the workstation and server
        !           446:           services.  The heuristic below is probably useful though on the
        !           447:           assumption that the majority of the network traffic will be via
        !           448:           the appropriate service */
        !           449:        lpszLanW = (LPWSTR) WIDE ("LanmanWorkstation");
        !           450:        lpszLanS = (LPWSTR) WIDE ("LanmanServer");
        !           451:        if (hNetAPI32 &&
        !           452:            pNetStatisticsGet (NULL,
        !           453:                               isWorkstation ? lpszLanW : lpszLanS,
        !           454:                               0, 0, &lpBuffer) == 0)
        !           455:        {
        !           456:                pNetApiBufferSize (lpBuffer, &dwSize);
        !           457:                RandaddBuf ((unsigned char *) lpBuffer, dwSize);
        !           458:                pNetApiBufferFree (lpBuffer);
        !           459:        }
        !           460: 
        !           461:        /* Get disk I/O statistics for all the hard drives */
        !           462:        for (nDrive = 0;; nDrive++)
        !           463:        {
        !           464:                DISK_PERFORMANCE diskPerformance;
        !           465:                char szDevice[24];
        !           466: 
        !           467:                /* Check whether we can access this device */
        !           468:                sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive);
        !           469:                hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
        !           470:                                      NULL, OPEN_EXISTING, 0, NULL);
        !           471:                if (hDevice == INVALID_HANDLE_VALUE)
        !           472:                        break;
        !           473: 
        !           474: 
        !           475:                /* Note: This only works if you have turned on the disk
        !           476:                   performance counters with 'diskperf -y'.  These counters
        !           477:                   are off by default */
        !           478:                if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
        !           479:                                &diskPerformance, sizeof (DISK_PERFORMANCE),
        !           480:                                     &dwSize, NULL))
        !           481:                {
        !           482:                        RandaddBuf ((unsigned char *) &diskPerformance, dwSize);
        !           483:                }
        !           484:                CloseHandle (hDevice);
        !           485:        }
        !           486: 
        !           487:        /* Get the performance counters */
        !           488:        pPerfData = (PPERF_DATA_BLOCK) TCalloc (cbPerfData);
        !           489:        while (pPerfData)
        !           490:        {
        !           491:                dwSize = cbPerfData;
        !           492:                status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
        !           493:                                          NULL, (LPBYTE) pPerfData, &dwSize);
        !           494: 
        !           495:                if (status == ERROR_SUCCESS)
        !           496:                {
        !           497:                        RegCloseKey (HKEY_PERFORMANCE_DATA);
        !           498:                        if (memcmp (pPerfData->Signature, WIDE ("PERF"), 8) == 0)
        !           499:                                RandaddBuf (pPerfData, dwSize);
        !           500:                        TCfree (pPerfData);
        !           501:                        pPerfData = NULL;
        !           502:                }
        !           503:                else if (status == ERROR_MORE_DATA)
        !           504:                {
        !           505:                        cbPerfData += 4096;
        !           506:                        pPerfData = (PPERF_DATA_BLOCK) realloc (pPerfData, cbPerfData);
        !           507:                }
        !           508:        }
        !           509: }
        !           510: 
        !           511: 
        !           512: /* Win9x typedefs and variables for toolhelp32 use */
        !           513: typedef BOOL (WINAPI * MODULEWALK) (HANDLE hSnapshot, LPMODULEENTRY32 lpme);
        !           514: typedef BOOL (WINAPI * THREADWALK) (HANDLE hSnapshot, LPTHREADENTRY32 lpte);
        !           515: typedef BOOL (WINAPI * PROCESSWALK) (HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
        !           516: typedef BOOL (WINAPI * HEAPLISTWALK) (HANDLE hSnapshot, LPHEAPLIST32 lphl);
        !           517: typedef BOOL (WINAPI * HEAPFIRST) (LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID);
        !           518: typedef BOOL (WINAPI * HEAPNEXT) (LPHEAPENTRY32 lphe);
        !           519: typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID);
        !           520: CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
        !           521: MODULEWALK pModule32First = NULL;
        !           522: MODULEWALK pModule32Next = NULL;
        !           523: PROCESSWALK pProcess32First = NULL;
        !           524: PROCESSWALK pProcess32Next = NULL;
        !           525: THREADWALK pThread32First = NULL;
        !           526: THREADWALK pThread32Next = NULL;
        !           527: HEAPLISTWALK pHeap32ListFirst = NULL;
        !           528: HEAPLISTWALK pHeap32ListNext = NULL;
        !           529: HEAPFIRST pHeap32First = NULL;
        !           530: HEAPNEXT pHeap32Next = NULL;
        !           531: 
        !           532: void
        !           533: SlowPollWin9x (void)
        !           534: {
        !           535:        PROCESSENTRY32 pe32;
        !           536:        THREADENTRY32 te32;
        !           537:        MODULEENTRY32 me32;
        !           538:        HEAPLIST32 hl32;
        !           539:        HANDLE hSnapshot;
        !           540: 
        !           541:        /* Initialize the Toolhelp32 function pointers if necessary */
        !           542:        if (pCreateToolhelp32Snapshot == NULL)
        !           543:        {
        !           544:                HANDLE hKernel = NULL;
        !           545: 
        !           546:                /* Obtain the module handle of the kernel to retrieve the
        !           547:                   addresses of the Toolhelp32 functions */
        !           548:                if ((hKernel = GetModuleHandle ("KERNEL32.DLL")) == NULL)
        !           549:                        return;
        !           550: 
        !           551:                /* Now get pointers to the functions */
        !           552:                pCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress (hKernel,
        !           553:                                                "CreateToolhelp32Snapshot");
        !           554:                pModule32First = (MODULEWALK) GetProcAddress (hKernel,
        !           555:                                                           "Module32First");
        !           556:                pModule32Next = (MODULEWALK) GetProcAddress (hKernel,
        !           557:                                                             "Module32Next");
        !           558:                pProcess32First = (PROCESSWALK) GetProcAddress (hKernel,
        !           559:                                                          "Process32First");
        !           560:                pProcess32Next = (PROCESSWALK) GetProcAddress (hKernel,
        !           561:                                                           "Process32Next");
        !           562:                pThread32First = (THREADWALK) GetProcAddress (hKernel,
        !           563:                                                           "Thread32First");
        !           564:                pThread32Next = (THREADWALK) GetProcAddress (hKernel,
        !           565:                                                             "Thread32Next");
        !           566:                pHeap32ListFirst = (HEAPLISTWALK) GetProcAddress (hKernel,
        !           567:                                                         "Heap32ListFirst");
        !           568:                pHeap32ListNext = (HEAPLISTWALK) GetProcAddress (hKernel,
        !           569:                                                          "Heap32ListNext");
        !           570:                pHeap32First = (HEAPFIRST) GetProcAddress (hKernel,
        !           571:                                                           "Heap32First");
        !           572:                pHeap32Next = (HEAPNEXT) GetProcAddress (hKernel,
        !           573:                                                         "Heap32Next");
        !           574: 
        !           575:                /* Make sure we got valid pointers for every Toolhelp32
        !           576:                   function */
        !           577:                if (pModule32First == NULL || pModule32Next == NULL || \
        !           578:                    pProcess32First == NULL || pProcess32Next == NULL || \
        !           579:                    pThread32First == NULL || pThread32Next == NULL || \
        !           580:                    pHeap32ListFirst == NULL || pHeap32ListNext == NULL || \
        !           581:                    pHeap32First == NULL || pHeap32Next == NULL || \
        !           582:                    pCreateToolhelp32Snapshot == NULL)
        !           583:                {
        !           584:                        /* Mark the main function as unavailable in case for
        !           585:                           future reference */
        !           586:                        pCreateToolhelp32Snapshot = NULL;
        !           587:                        return;
        !           588:                }
        !           589:        }
        !           590: 
        !           591:        /* Take a snapshot of everything we can get to which is currently in
        !           592:           the system */
        !           593:        hSnapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPALL, 0);
        !           594:        if (!hSnapshot)
        !           595:                return;
        !           596: 
        !           597:        /* Walk through the local heap */
        !           598:        hl32.dwSize = sizeof (HEAPLIST32);
        !           599:        if (pHeap32ListFirst (hSnapshot, &hl32))
        !           600:                do
        !           601:                {
        !           602:                        HEAPENTRY32 he32;
        !           603: 
        !           604:                        /* First add the information from the basic
        !           605:                           Heaplist32 structure */
        !           606:                        RandaddBuf ((BYTE *) & hl32, sizeof (HEAPLIST32));
        !           607: 
        !           608:                        /* Now walk through the heap blocks getting
        !           609:                           information on each of them */
        !           610:                        he32.dwSize = sizeof (HEAPENTRY32);
        !           611:                        if (pHeap32First (&he32, hl32.th32ProcessID, hl32.th32HeapID))
        !           612:                                do
        !           613:                                {
        !           614:                                        RandaddBuf ((BYTE *) & he32, sizeof (HEAPENTRY32));
        !           615:                                }
        !           616:                                while (pHeap32Next (&he32));
        !           617:                }
        !           618:                while (pHeap32ListNext (hSnapshot, &hl32));
        !           619: 
        !           620:        /* Walk through all processes */
        !           621:        pe32.dwSize = sizeof (PROCESSENTRY32);
        !           622:        if (pProcess32First (hSnapshot, &pe32))
        !           623:                do
        !           624:                {
        !           625:                        RandaddBuf ((BYTE *) & pe32, sizeof (PROCESSENTRY32));
        !           626:                }
        !           627:                while (pProcess32Next (hSnapshot, &pe32));
        !           628: 
        !           629:        /* Walk through all threads */
        !           630:        te32.dwSize = sizeof (THREADENTRY32);
        !           631:        if (pThread32First (hSnapshot, &te32))
        !           632:                do
        !           633:                {
        !           634:                        RandaddBuf ((BYTE *) & te32, sizeof (THREADENTRY32));
        !           635:                }
        !           636:                while (pThread32Next (hSnapshot, &te32));
        !           637: 
        !           638:        /* Walk through all modules associated with the process */
        !           639:        me32.dwSize = sizeof (MODULEENTRY32);
        !           640:        if (pModule32First (hSnapshot, &me32))
        !           641:                do
        !           642:                {
        !           643:                        RandaddBuf ((BYTE *) & me32, sizeof (MODULEENTRY32));
        !           644:                }
        !           645:                while (pModule32Next (hSnapshot, &me32));
        !           646: 
        !           647:        /* Clean up the snapshot */
        !           648:        CloseHandle (hSnapshot);
        !           649: }
        !           650: 
        !           651: 
        !           652: 
        !           653: /* This is the fastpoll function which gathers up info by calling various
        !           654:    api's */
        !           655: void
        !           656: FastPoll (void)
        !           657: {
        !           658:        static BOOL addedFixedItems = FALSE;
        !           659:        FILETIME creationTime, exitTime, kernelTime, userTime;
        !           660:        DWORD minimumWorkingSetSize, maximumWorkingSetSize;
        !           661:        LARGE_INTEGER performanceCount;
        !           662:        MEMORYSTATUS memoryStatus;
        !           663:        HANDLE handle;
        !           664:        POINT point;
        !           665: 
        !           666:        /* Get various basic pieces of system information */
        !           667:        RandaddLong (GetActiveWindow ());       /* Handle of active window */
        !           668:        RandaddLong (GetCapture ());    /* Handle of window with mouse
        !           669:                                           capture */
        !           670:        RandaddLong (GetClipboardOwner ());     /* Handle of clipboard owner */
        !           671:        RandaddLong (GetClipboardViewer ());    /* Handle of start of
        !           672:                                                   clpbd.viewer list */
        !           673:        RandaddLong (GetCurrentProcess ());     /* Pseudohandle of current
        !           674:                                                   process */
        !           675:        RandaddLong (GetCurrentProcessId ());   /* Current process ID */
        !           676:        RandaddLong (GetCurrentThread ());      /* Pseudohandle of current
        !           677:                                                   thread */
        !           678:        RandaddLong (GetCurrentThreadId ());    /* Current thread ID */
        !           679:        RandaddLong (GetCurrentTime ());        /* Milliseconds since Windows
        !           680:                                                   started */
        !           681:        RandaddLong (GetDesktopWindow ());      /* Handle of desktop window */
        !           682:        RandaddLong (GetFocus ());      /* Handle of window with kb.focus */
        !           683:        RandaddLong (GetInputState ()); /* Whether sys.queue has any events */
        !           684:        RandaddLong (GetMessagePos ()); /* Cursor pos.for last message */
        !           685:        RandaddLong (GetMessageTime ());        /* 1 ms time for last message */
        !           686:        RandaddLong (GetOpenClipboardWindow ());        /* Handle of window with
        !           687:                                                           clpbd.open */
        !           688:        RandaddLong (GetProcessHeap ());        /* Handle of process heap */
        !           689:        RandaddLong (GetProcessWindowStation ());       /* Handle of procs
        !           690:                                                           window station */
        !           691:        RandaddLong (GetQueueStatus (QS_ALLEVENTS));    /* Types of events in
        !           692:                                                           input queue */
        !           693: 
        !           694:        /* Get multiword system information */
        !           695:        GetCaretPos (&point);   /* Current caret position */
        !           696:        RandaddBuf ((unsigned char *) &point, sizeof (POINT));
        !           697:        GetCursorPos (&point);  /* Current mouse cursor position */
        !           698:        RandaddBuf ((unsigned char *) &point, sizeof (POINT));
        !           699: 
        !           700:        /* Get percent of memory in use, bytes of physical memory, bytes of
        !           701:           free physical memory, bytes in paging file, free bytes in paging
        !           702:           file, user bytes of address space, and free user bytes */
        !           703:        memoryStatus.dwLength = sizeof (MEMORYSTATUS);
        !           704:        GlobalMemoryStatus (&memoryStatus);
        !           705:        RandaddBuf ((unsigned char *) &memoryStatus, sizeof (MEMORYSTATUS));
        !           706: 
        !           707:        /* Get thread and process creation time, exit time, time in kernel
        !           708:           mode, and time in user mode in 100ns intervals */
        !           709:        handle = GetCurrentThread ();
        !           710:        GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime);
        !           711:        RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME));
        !           712:        RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME));
        !           713:        RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME));
        !           714:        RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME));
        !           715:        handle = GetCurrentProcess ();
        !           716:        GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime);
        !           717:        RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME));
        !           718:        RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME));
        !           719:        RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME));
        !           720:        RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME));
        !           721: 
        !           722:        /* Get the minimum and maximum working set size for the current
        !           723:           process */
        !           724:        GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
        !           725:                                  &maximumWorkingSetSize);
        !           726:        RandaddLong (minimumWorkingSetSize);
        !           727:        RandaddLong (maximumWorkingSetSize);
        !           728: 
        !           729:        /* The following are fixed for the lifetime of the process so we only
        !           730:           add them once */
        !           731:        if (addedFixedItems == 0)
        !           732:        {
        !           733:                STARTUPINFO startupInfo;
        !           734: 
        !           735:                /* Get name of desktop, console window title, new window
        !           736:                   position and size, window flags, and handles for stdin,
        !           737:                   stdout, and stderr */
        !           738:                startupInfo.cb = sizeof (STARTUPINFO);
        !           739:                GetStartupInfo (&startupInfo);
        !           740:                RandaddBuf ((unsigned char *) &startupInfo, sizeof (STARTUPINFO));
        !           741:                addedFixedItems = TRUE;
        !           742:        }
        !           743:        /* The docs say QPC can fail if appropriate hardware is not
        !           744:           available. It works on 486 & Pentium boxes, but hasn't been tested
        !           745:           for 386 or RISC boxes */
        !           746:        if (QueryPerformanceCounter (&performanceCount))
        !           747:                RandaddBuf ((unsigned char *) &performanceCount, sizeof (LARGE_INTEGER));
        !           748:        else
        !           749:        {
        !           750:                /* Millisecond accuracy at best... */
        !           751:                DWORD dwTicks = GetTickCount ();
        !           752:                RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks));
        !           753:        }
        !           754: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.