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