summaryrefslogtreecommitdiffabout
path: root/pwmanager/libcrypt/cipher/rndw32.c
Unidiff
Diffstat (limited to 'pwmanager/libcrypt/cipher/rndw32.c') (more/less context) (show whitespace changes)
-rw-r--r--pwmanager/libcrypt/cipher/rndw32.c682
1 files changed, 682 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/rndw32.c b/pwmanager/libcrypt/cipher/rndw32.c
new file mode 100644
index 0000000..870eec6
--- a/dev/null
+++ b/pwmanager/libcrypt/cipher/rndw32.c
@@ -0,0 +1,682 @@
1 /* rndw32.c -W32 entropy gatherer
2 *Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
3 *Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-1999
4 *
5 * This file is part of Libgcrypt.
6 *
7 *************************************************************************
8 * The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann.
9 * Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this
10 * copyright notice:
11 *
12 * This module is part of the cryptlib continuously seeded pseudorandom
13 * number generator. For usage conditions, see lib_rand.c
14 *
15 * [Here is the notice from lib_rand.c, which is now called dev_sys.c]
16 *
17 * This module and the misc/rnd*.c modules represent the cryptlib
18 * continuously seeded pseudorandom number generator (CSPRNG) as described in
19 * my 1998 Usenix Security Symposium paper "The generation of random numbers
20 * for cryptographic purposes".
21 *
22 * The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
23 * 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
24 * modules and use in source and binary forms, with or without modification,
25 * are permitted provided that the following conditions are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright notice
28 * and this permission notice in its entirety.
29 *
30 * 2. Redistributions in binary form must reproduce the copyright notice in
31 * the documentation and/or other materials provided with the distribution.
32 *
33 * 3. A copy of any bugfixes or enhancements made must be provided to the
34 * author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
35 * baseline version of the code.
36 *
37 * ALTERNATIVELY, the code may be distributed under the terms of the GNU
38 * General Public License, version 2 or any later version published by the
39 * Free Software Foundation, in which case the provisions of the GNU GPL are
40 * required INSTEAD OF the above restrictions.
41 *
42 * Although not required under the terms of the GPL, it would still be nice if
43 * you could make any changes available to the author to allow a consistent
44 * code base to be maintained
45 *************************************************************************
46 */
47
48#include <config.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <assert.h>
52#include <errno.h>
53#include <string.h>
54
55#include <windows.h>
56
57
58#include "types.h"
59#include "g10lib.h"
60#include "rand-internal.h"
61
62
63static int debug_me;
64
65/*
66 * Definitions which are missing from the current GNU Windows32Api
67 */
68
69#ifndef TH32CS_SNAPHEAPLIST
70#define TH32CS_SNAPHEAPLIST 1
71#define TH32CS_SNAPPROCESS 2
72#define TH32CS_SNAPTHREAD 4
73#define TH32CS_SNAPMODULE 8
74 #define TH32CS_SNAPALL (1|2|4|8)
75 #define TH32CS_INHERIT 0x80000000
76#endif /*TH32CS_SNAPHEAPLIST*/
77
78#ifndef IOCTL_DISK_PERFORMANCE
79 #define IOCTL_DISK_PERFORMANCE0x00070020
80#endif
81#ifndef VER_PLATFORM_WIN32_WINDOWS
82#define VER_PLATFORM_WIN32_WINDOWS 1
83#endif
84
85/* This used to be (6*8+5*4+8*2), but Peter Gutmann figured a larger
86 value in a newer release. So we use a far larger value. */
87#define SIZEOF_DISK_PERFORMANCE_STRUCT 256
88
89
90typedef struct {
91 DWORD dwSize;
92 DWORD th32ProcessID;
93 DWORD th32HeapID;
94 DWORD dwFlags;
95} HEAPLIST32;
96
97typedef struct {
98 DWORD dwSize;
99 HANDLE hHandle;
100 DWORD dwAddress;
101 DWORD dwBlockSize;
102 DWORD dwFlags;
103 DWORD dwLockCount;
104 DWORD dwResvd;
105 DWORD th32ProcessID;
106 DWORD th32HeapID;
107} HEAPENTRY32;
108
109typedef struct {
110 DWORD dwSize;
111 DWORD cntUsage;
112 DWORD th32ProcessID;
113 DWORD th32DefaultHeapID;
114 DWORD th32ModuleID;
115 DWORD cntThreads;
116 DWORD th32ParentProcessID;
117 LONG pcPriClassBase;
118 DWORD dwFlags;
119 char szExeFile[260];
120} PROCESSENTRY32;
121
122typedef struct {
123 DWORD dwSize;
124 DWORD cntUsage;
125 DWORD th32ThreadID;
126 DWORD th32OwnerProcessID;
127 LONG tpBasePri;
128 LONG tpDeltaPri;
129 DWORD dwFlags;
130} THREADENTRY32;
131
132typedef struct {
133 DWORD dwSize;
134 DWORD th32ModuleID;
135 DWORD th32ProcessID;
136 DWORD GlblcntUsage;
137 DWORD ProccntUsage;
138 BYTE *modBaseAddr;
139 DWORD modBaseSize;
140 HMODULE hModule;
141 char szModule[256];
142 char szExePath[260];
143} MODULEENTRY32;
144
145
146
147/* Type definitions for function pointers to call Toolhelp32 functions
148 * used with the windows95 gatherer */
149typedef BOOL (WINAPI * MODULEWALK) (HANDLE hSnapshot, MODULEENTRY32 *lpme);
150typedef BOOL (WINAPI * THREADWALK) (HANDLE hSnapshot, THREADENTRY32 *lpte);
151typedef BOOL (WINAPI * PROCESSWALK) (HANDLE hSnapshot, PROCESSENTRY32 *lppe);
152typedef BOOL (WINAPI * HEAPLISTWALK) (HANDLE hSnapshot, HEAPLIST32 *lphl);
153typedef BOOL (WINAPI * HEAPFIRST) (HEAPENTRY32 *lphe, DWORD th32ProcessID,
154 DWORD th32HeapID);
155typedef BOOL (WINAPI * HEAPNEXT) (HEAPENTRY32 *lphe);
156typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID);
157
158/* Type definitions for function pointers to call NetAPI32 functions */
159typedef DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService,
160 DWORD dwLevel, DWORD dwOptions,
161 LPBYTE * lpBuffer);
162typedef DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer);
163typedef DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer);
164
165
166/* When we query the performance counters, we allocate an initial buffer and
167 * then reallocate it as required until RegQueryValueEx() stops returning
168 * ERROR_MORE_DATA. The following values define the initial buffer size and
169 * step size by which the buffer is increased
170 */
171 #define PERFORMANCE_BUFFER_SIZE 65536/* Start at 64K */
172 #define PERFORMANCE_BUFFER_STEP 16384/* Step by 16K */
173
174
175static void
176slow_gatherer_windows95( void (*add)(const void*, size_t, int), int requester )
177{
178 static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
179 static MODULEWALK pModule32First = NULL;
180 static MODULEWALK pModule32Next = NULL;
181 static PROCESSWALK pProcess32First = NULL;
182 static PROCESSWALK pProcess32Next = NULL;
183 static THREADWALK pThread32First = NULL;
184 static THREADWALK pThread32Next = NULL;
185 static HEAPLISTWALK pHeap32ListFirst = NULL;
186 static HEAPLISTWALK pHeap32ListNext = NULL;
187 static HEAPFIRST pHeap32First = NULL;
188 static HEAPNEXT pHeap32Next = NULL;
189 HANDLE hSnapshot;
190
191
192 /* initialize the Toolhelp32 function pointers */
193 if ( !pCreateToolhelp32Snapshot ) {
194 HANDLE hKernel;
195
196 if ( debug_me )
197 log_debug ("rndw32#slow_gatherer_95: init toolkit\n" );
198
199 /* Obtain the module handle of the kernel to retrieve the addresses
200 * of the Toolhelp32 functions */
201 if ( ( !(hKernel = GetModuleHandle ("KERNEL32.DLL"))) ) {
202 log_fatal ( "rndw32: can't get module handle\n" );
203 }
204
205 /* Now get pointers to the functions */
206 pCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress (hKernel,
207 "CreateToolhelp32Snapshot");
208 pModule32First = (MODULEWALK) GetProcAddress (hKernel, "Module32First");
209 pModule32Next = (MODULEWALK) GetProcAddress (hKernel, "Module32Next");
210 pProcess32First = (PROCESSWALK) GetProcAddress (hKernel,
211 "Process32First");
212 pProcess32Next = (PROCESSWALK) GetProcAddress (hKernel,
213 "Process32Next");
214 pThread32First = (THREADWALK) GetProcAddress (hKernel, "Thread32First");
215 pThread32Next = (THREADWALK) GetProcAddress (hKernel, "Thread32Next");
216 pHeap32ListFirst = (HEAPLISTWALK) GetProcAddress (hKernel,
217 "Heap32ListFirst");
218 pHeap32ListNext = (HEAPLISTWALK) GetProcAddress (hKernel,
219 "Heap32ListNext");
220 pHeap32First = (HEAPFIRST) GetProcAddress (hKernel, "Heap32First");
221 pHeap32Next = (HEAPNEXT) GetProcAddress (hKernel, "Heap32Next");
222
223 if (!pCreateToolhelp32Snapshot
224 || !pModule32First || !pModule32Next
225 || !pProcess32First || !pProcess32Next
226 || !pThread32First || !pThread32Next
227 || !pHeap32ListFirst || !pHeap32ListNext
228 || !pHeap32First || !pHeap32Next ) {
229 log_fatal ( "rndw32: failed to get a toolhelp function\n" );
230 }
231 }
232
233 /* Take a snapshot of everything we can get to which is currently
234 *in the system */
235 if ( !(hSnapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPALL, 0)) ) {
236 log_fatal ( "rndw32: failed to take a toolhelp snapshot\n" );
237 }
238
239 /* Walk through the local heap */
240 {HEAPLIST32 hl32;
241 hl32.dwSize = sizeof (HEAPLIST32);
242 if (pHeap32ListFirst (hSnapshot, &hl32)) {
243 if ( debug_me )
244 log_debug ("rndw32#slow_gatherer_95: walk heap\n" );
245 do {
246 HEAPENTRY32 he32;
247
248 /* First add the information from the basic Heaplist32 struct */
249 (*add) ( &hl32, sizeof (hl32), requester );
250
251 /* Now walk through the heap blocks getting information
252 * on each of them */
253 he32.dwSize = sizeof (HEAPENTRY32);
254 if (pHeap32First (&he32, hl32.th32ProcessID, hl32.th32HeapID)){
255 do {
256 (*add) ( &he32, sizeof (he32), requester );
257 } while (pHeap32Next (&he32));
258 }
259 } while (pHeap32ListNext (hSnapshot, &hl32));
260 }
261 }
262
263
264 /* Walk through all processes */
265 {PROCESSENTRY32 pe32;
266 pe32.dwSize = sizeof (PROCESSENTRY32);
267 if (pProcess32First (hSnapshot, &pe32)) {
268 if ( debug_me )
269 log_debug ("rndw32#slow_gatherer_95: walk processes\n" );
270 do {
271 (*add) ( &pe32, sizeof (pe32), requester );
272 } while (pProcess32Next (hSnapshot, &pe32));
273 }
274 }
275
276 /* Walk through all threads */
277 {THREADENTRY32 te32;
278 te32.dwSize = sizeof (THREADENTRY32);
279 if (pThread32First (hSnapshot, &te32)) {
280 if ( debug_me )
281 log_debug ("rndw32#slow_gatherer_95: walk threads\n" );
282 do {
283 (*add) ( &te32, sizeof (te32), requester );
284 } while (pThread32Next (hSnapshot, &te32));
285 }
286 }
287
288 /* Walk through all modules associated with the process */
289 {MODULEENTRY32 me32;
290 me32.dwSize = sizeof (MODULEENTRY32);
291 if (pModule32First (hSnapshot, &me32)) {
292 if ( debug_me )
293 log_debug ("rndw32#slow_gatherer_95: walk modules\n" );
294 do {
295 (*add) ( &me32, sizeof (me32), requester );
296 } while (pModule32Next (hSnapshot, &me32));
297 }
298 }
299
300 CloseHandle (hSnapshot);
301}
302
303
304
305static void
306slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester )
307{
308 static int is_initialized = 0;
309 static NETSTATISTICSGET pNetStatisticsGet = NULL;
310 static NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
311 static NETAPIBUFFERFREE pNetApiBufferFree = NULL;
312 static int is_workstation = 1;
313
314 static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
315 PERF_DATA_BLOCK *pPerfData;
316 HANDLE hDevice, hNetAPI32 = NULL;
317 DWORD dwSize, status;
318 int nDrive;
319
320 if ( !is_initialized ) {
321 HKEY hKey;
322
323 if ( debug_me )
324 log_debug ("rndw32#slow_gatherer_nt: init toolkit\n" );
325 /* Find out whether this is an NT server or workstation if necessary */
326 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
327 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
328 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
329 BYTE szValue[32];
330 dwSize = sizeof (szValue);
331
332 if ( debug_me )
333 log_debug ("rndw32#slow_gatherer_nt: check product options\n" );
334 status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
335 szValue, &dwSize);
336 if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT")) {
337 /* Note: There are (at least) three cases for ProductType:
338 * WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
339 * NT Server acting as a Domain Controller */
340 is_workstation = 0;
341 if ( debug_me )
342 log_debug ("rndw32: this is a NT server\n");
343 }
344 RegCloseKey (hKey);
345 }
346
347 /* Initialize the NetAPI32 function pointers if necessary */
348 if ( (hNetAPI32 = LoadLibrary ("NETAPI32.DLL")) ) {
349 if ( debug_me )
350 log_debug ("rndw32#slow_gatherer_nt: netapi32 loaded\n" );
351 pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32,
352 "NetStatisticsGet");
353 pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32,
354 "NetApiBufferSize");
355 pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32,
356 "NetApiBufferFree");
357
358 if ( !pNetStatisticsGet
359 || !pNetApiBufferSize || !pNetApiBufferFree ) {
360 FreeLibrary (hNetAPI32);
361 hNetAPI32 = NULL;
362 log_debug ("rndw32: No NETAPI found\n" );
363 }
364 }
365
366 is_initialized = 1;
367 }
368
369 /* Get network statistics.Note: Both NT Workstation and NT Server by
370 * default will be running both the workstation and server services. The
371 * heuristic below is probably useful though on the assumption that the
372 * majority of the network traffic will be via the appropriate service.
373 * In any case the network statistics return almost no randomness */
374 {LPBYTE lpBuffer;
375 if (hNetAPI32 && !pNetStatisticsGet (NULL,
376 is_workstation ? L"LanmanWorkstation" :
377 L"LanmanServer", 0, 0, &lpBuffer) ) {
378 if ( debug_me )
379 log_debug ("rndw32#slow_gatherer_nt: get netstats\n" );
380 pNetApiBufferSize (lpBuffer, &dwSize);
381 (*add) ( lpBuffer, dwSize,requester );
382 pNetApiBufferFree (lpBuffer);
383 }
384 }
385
386 /* Get disk I/O statistics for all the hard drives */
387 for (nDrive = 0;; nDrive++) {
388 char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT];
389 char szDevice[50];
390
391 /* Check whether we can access this device */
392 sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive);
393 hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
394 NULL, OPEN_EXISTING, 0, NULL);
395 if (hDevice == INVALID_HANDLE_VALUE)
396 break;
397
398 /* Note: This only works if you have turned on the disk performance
399 * counters with 'diskperf -y'. These counters are off by default */
400 if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
401 &diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT,
402 &dwSize, NULL))
403 {
404 if ( debug_me )
405 log_debug ("rndw32#slow_gatherer_nt: iostats drive %d\n",
406 nDrive );
407 (*add) (diskPerformance, dwSize, requester );
408 }
409 else {
410 log_info ("NOTE: you should run 'diskperf -y' "
411 "to enable the disk statistics\n");
412 }
413 CloseHandle (hDevice);
414 }
415
416#if 0 /* we don't need this in GnuPG */
417 /* Wait for any async keyset driver binding to complete. You may be
418 * wondering what this call is doing here... the reason it's necessary is
419 * because RegQueryValueEx() will hang indefinitely if the async driver
420 * bind is in progress. The problem occurs in the dynamic loading and
421 * linking of driver DLL's, which work as follows:
422 *
423 * hDriver = LoadLibrary( DRIVERNAME );
424 * pFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 );
425 * pFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 );
426 *
427 * If RegQueryValueEx() is called while the GetProcAddress()'s are in
428 * progress, it will hang indefinitely. This is probably due to some
429 * synchronisation problem in the NT kernel where the GetProcAddress()
430 * calls affect something like a module reference count or function
431 * reference count while RegQueryValueEx() is trying to take a snapshot
432 * of the statistics, which include the reference counts. Because of
433 * this, we have to wait until any async driver bind has completed
434 * before we can call RegQueryValueEx() */
435 waitSemaphore (SEMAPHORE_DRIVERBIND);
436#endif
437
438 /* Get information from the system performance counters. This can take
439 * a few seconds to do. In some environments the call to
440 * RegQueryValueEx() can produce an access violation at some random time
441 * in the future, adding a short delay after the following code block
442 * makes the problem go away. This problem is extremely difficult to
443 * reproduce, I haven't been able to get it to occur despite running it
444 * on a number of machines. The best explanation for the problem is that
445 * on the machine where it did occur, it was caused by an external driver
446 * or other program which adds its own values under the
447 * HKEY_PERFORMANCE_DATA key. The NT kernel calls the required external
448 * modules to map in the data, if there's a synchronisation problem the
449 * external module would write its data at an inappropriate moment,
450 * causing the access violation. A low-level memory checker indicated
451 * that ExpandEnvironmentStrings() in KERNEL32.DLL, called an
452 * interminable number of calls down inside RegQueryValueEx(), was
453 * overwriting memory (it wrote twice the allocated size of a buffer to a
454 * buffer allocated by the NT kernel). This may be what's causing the
455 * problem, but since it's in the kernel there isn't much which can be
456 * done.
457 *
458 * In addition to these problems the code in RegQueryValueEx() which
459 * estimates the amount of memory required to return the performance
460 * counter information isn't very accurate, since it always returns a
461 * worst-case estimate which is usually nowhere near the actual amount
462 * required. For example it may report that 128K of memory is required,
463 * but only return 64K of data */
464 {pPerfData = gcry_xmalloc (cbPerfData);
465 for (;;) {
466 dwSize = cbPerfData;
467 if ( debug_me )
468 log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
469 status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
470 NULL, (LPBYTE) pPerfData, &dwSize);
471 if (status == ERROR_SUCCESS) {
472 if (!memcmp (pPerfData->Signature, L"PERF", 8)) {
473 (*add) ( pPerfData, dwSize, requester );
474 }
475 else
476 log_debug ( "rndw32: no PERF signature\n");
477 break;
478 }
479 else if (status == ERROR_MORE_DATA) {
480 cbPerfData += PERFORMANCE_BUFFER_STEP;
481 pPerfData = gcry_realloc (pPerfData, cbPerfData);
482 }
483 else {
484 log_debug ( "rndw32: get performance data problem\n");
485 break;
486 }
487 }
488 gcry_free (pPerfData);
489 }
490 /* Although this isn't documented in the Win32 API docs, it's necessary
491 to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
492 implicitly opened on the first call to RegQueryValueEx()). If this
493 isn't done then any system components which provide performance data
494 can't be removed or changed while the handle remains active */
495 RegCloseKey (HKEY_PERFORMANCE_DATA);
496}
497
498
499int
500_gcry_rndw32_gather_random( void (*add)(const void*, size_t, int),
501 int requester,
502 size_t length, int level )
503{
504 static int is_initialized;
505 static int is_windowsNT, has_toolhelp;
506
507
508 if( !level )
509 return 0;
510 /* We don't differentiate between level 1 and 2 here because
511 * there is no internal entropy pool as a scary resource. It may
512 * all work slower, but because our entropy source will never
513 * block but deliver some not easy to measure entropy, we assume level 2
514 */
515
516
517 if ( !is_initialized ) {
518 OSVERSIONINFO osvi = { sizeof( osvi ) };
519 DWORD platform;
520
521 GetVersionEx( &osvi );
522 platform = osvi.dwPlatformId;
523 is_windowsNT = platform == VER_PLATFORM_WIN32_NT;
524 has_toolhelp = (platform == VER_PLATFORM_WIN32_WINDOWS
525 || (is_windowsNT && osvi.dwMajorVersion >= 5));
526
527 if ( platform == VER_PLATFORM_WIN32s ) {
528 log_fatal("can't run on a W32s platform\n" );
529 }
530 is_initialized = 1;
531 if ( debug_me )
532 log_debug ("rndw32#gather_random: platform=%d\n", (int)platform );
533 }
534
535
536 if ( debug_me )
537 log_debug ("rndw32#gather_random: req=%d len=%u lvl=%d\n",
538 requester, (unsigned int)length, level );
539
540 if ( has_toolhelp ) {
541 slow_gatherer_windows95 ( add, requester );
542 }
543 if ( is_windowsNT ) {
544 slow_gatherer_windowsNT ( add, requester );
545 }
546
547 return 0;
548}
549
550
551int
552_gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, int),
553 int requester )
554{
555 static int addedFixedItems = 0;
556
557 if ( debug_me )
558 log_debug ("rndw32#gather_random_fast: req=%d\n", requester );
559
560 /* Get various basic pieces of system information: Handle of active
561 * window, handle of window with mouse capture, handle of clipboard owner
562 * handle of start of clpboard viewer list, pseudohandle of current
563 * process, current process ID, pseudohandle of current thread, current
564 * thread ID, handle of desktop window, handle of window with keyboard
565 * focus, whether system queue has any events, cursor position for last
566 * message, 1 ms time for last message, handle of window with clipboard
567 * open, handle of process heap, handle of procs window station, types of
568 * events in input queue, and milliseconds since Windows was started */
569 {byte buffer[20*sizeof(ulong)], *bufptr;
570 bufptr = buffer;
571 #define ADD(f) do { ulong along = (ulong)(f); \
572 memcpy (bufptr, &along, sizeof (along) ); \
573 bufptr += sizeof (along); } while (0)
574 ADD ( GetActiveWindow ());
575 ADD ( GetCapture ());
576 ADD ( GetClipboardOwner ());
577 ADD ( GetClipboardViewer ());
578 ADD ( GetCurrentProcess ());
579 ADD ( GetCurrentProcessId ());
580 ADD ( GetCurrentThread ());
581 ADD ( GetCurrentThreadId ());
582 ADD ( GetDesktopWindow ());
583 ADD ( GetFocus ());
584 ADD ( GetInputState ());
585 ADD ( GetMessagePos ());
586 ADD ( GetMessageTime ());
587 ADD ( GetOpenClipboardWindow ());
588 ADD ( GetProcessHeap ());
589 ADD ( GetProcessWindowStation ());
590 ADD ( GetQueueStatus (QS_ALLEVENTS));
591 ADD ( GetTickCount ());
592
593 assert ( bufptr-buffer < sizeof (buffer) );
594 (*add) ( buffer, bufptr-buffer, requester );
595#undef ADD
596 }
597
598 /* Get multiword system information: Current caret position, current
599 * mouse cursor position */
600 {POINT point;
601 GetCaretPos (&point);
602 (*add) ( &point, sizeof (point), requester );
603 GetCursorPos (&point);
604 (*add) ( &point, sizeof (point), requester );
605 }
606
607 /* Get percent of memory in use, bytes of physical memory, bytes of free
608 * physical memory, bytes in paging file, free bytes in paging file, user
609 * bytes of address space, and free user bytes */
610 {MEMORYSTATUS memoryStatus;
611 memoryStatus.dwLength = sizeof (MEMORYSTATUS);
612 GlobalMemoryStatus (&memoryStatus);
613 (*add) ( &memoryStatus, sizeof (memoryStatus), requester );
614 }
615
616 /* Get thread and process creation time, exit time, time in kernel mode,
617 and time in user mode in 100ns intervals */
618 {HANDLE handle;
619 FILETIME creationTime, exitTime, kernelTime, userTime;
620 DWORD minimumWorkingSetSize, maximumWorkingSetSize;
621
622 handle = GetCurrentThread ();
623 GetThreadTimes (handle, &creationTime, &exitTime,
624 &kernelTime, &userTime);
625 (*add) ( &creationTime, sizeof (creationTime), requester );
626 (*add) ( &exitTime, sizeof (exitTime), requester );
627 (*add) ( &kernelTime, sizeof (kernelTime), requester );
628 (*add) ( &userTime, sizeof (userTime), requester );
629
630 handle = GetCurrentProcess ();
631 GetProcessTimes (handle, &creationTime, &exitTime,
632 &kernelTime, &userTime);
633 (*add) ( &creationTime, sizeof (creationTime), requester );
634 (*add) ( &exitTime, sizeof (exitTime), requester );
635 (*add) ( &kernelTime, sizeof (kernelTime), requester );
636 (*add) ( &userTime, sizeof (userTime), requester );
637
638 /* Get the minimum and maximum working set size for the current process */
639 GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
640 &maximumWorkingSetSize);
641 (*add) ( &minimumWorkingSetSize,
642 sizeof (&minimumWorkingSetSize), requester );
643 (*add) ( &maximumWorkingSetSize,
644 sizeof (&maximumWorkingSetSize), requester );
645 }
646
647
648 /* The following are fixed for the lifetime of the process so we only
649 * add them once */
650 if (!addedFixedItems) {
651 STARTUPINFO startupInfo;
652
653 /* Get name of desktop, console window title, new window position and
654 * size, window flags, and handles for stdin, stdout, and stderr */
655 startupInfo.cb = sizeof (STARTUPINFO);
656 GetStartupInfo (&startupInfo);
657 (*add) ( &startupInfo, sizeof (STARTUPINFO), requester );
658 addedFixedItems = 1;
659 }
660
661 /* The performance of QPC varies depending on the architecture it's
662 * running on and on the OS. Under NT it reads the CPU's 64-bit timestamp
663 * counter (at least on a Pentium and newer '486's, it hasn't been tested
664 * on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC
665 * timer. There are vague mumblings in the docs that it may fail if the
666 * appropriate hardware isn't available (possibly '386's or MIPS machines
667 * running NT), but who's going to run NT on a '386? */
668 {LARGE_INTEGER performanceCount;
669 if (QueryPerformanceCounter (&performanceCount)) {
670 if ( debug_me )
671 log_debug ("rndw32#gather_random_fast: perf data\n");
672 (*add) (&performanceCount, sizeof (&performanceCount), requester);
673 }
674 else { /* Millisecond accuracy at best... */
675 DWORD aword = GetTickCount ();
676 (*add) (&aword, sizeof (aword), requester );
677 }
678 }
679
680 return 0;
681}
682