1
/* crypto/rand/rand_win.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
5
* This package is an SSL implementation written
6
* by Eric Young (eay@cryptsoft.com).
7
* The implementation was written so as to conform with Netscapes SSL.
9
* This library is free for commercial and non-commercial use as long as
10
* the following conditions are aheared to. The following conditions
11
* apply to all code found in this distribution, be it the RC4, RSA,
12
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
13
* included with this distribution is covered by the same copyright terms
14
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
16
* Copyright remains Eric Young's, and as such any Copyright notices in
17
* the code are not to be removed.
18
* If this package is used in a product, Eric Young should be given attribution
19
* as the author of the parts of the library used.
20
* This can be in the form of a textual message at program startup or
21
* in documentation (online or textual) provided with the package.
23
* Redistribution and use in source and binary forms, with or without
24
* modification, are permitted provided that the following conditions
26
* 1. Redistributions of source code must retain the copyright
27
* notice, this list of conditions and the following disclaimer.
28
* 2. Redistributions in binary form must reproduce the above copyright
29
* notice, this list of conditions and the following disclaimer in the
30
* documentation and/or other materials provided with the distribution.
31
* 3. All advertising materials mentioning features or use of this software
32
* must display the following acknowledgement:
33
* "This product includes cryptographic software written by
34
* Eric Young (eay@cryptsoft.com)"
35
* The word 'cryptographic' can be left out if the rouines from the library
36
* being used are not cryptographic related :-).
37
* 4. If you include any Windows specific code (or a derivative thereof) from
38
* the apps directory (application code) you must include an acknowledgement:
39
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
41
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53
* The licence and distribution terms for any publically available version or
54
* derivative of this code cannot be changed. i.e. this code cannot simply be
55
* copied and put under another distribution licence
56
* [including the GNU Public Licence.]
58
/* ====================================================================
59
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
61
* Redistribution and use in source and binary forms, with or without
62
* modification, are permitted provided that the following conditions
65
* 1. Redistributions of source code must retain the above copyright
66
* notice, this list of conditions and the following disclaimer.
68
* 2. Redistributions in binary form must reproduce the above copyright
69
* notice, this list of conditions and the following disclaimer in
70
* the documentation and/or other materials provided with the
73
* 3. All advertising materials mentioning features or use of this
74
* software must display the following acknowledgment:
75
* "This product includes software developed by the OpenSSL Project
76
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
78
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79
* endorse or promote products derived from this software without
80
* prior written permission. For written permission, please contact
81
* openssl-core@openssl.org.
83
* 5. Products derived from this software may not be called "OpenSSL"
84
* nor may "OpenSSL" appear in their names without prior written
85
* permission of the OpenSSL Project.
87
* 6. Redistributions of any form whatsoever must retain the following
89
* "This product includes software developed by the OpenSSL Project
90
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
92
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
96
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103
* OF THE POSSIBILITY OF SUCH DAMAGE.
104
* ====================================================================
106
* This product includes cryptographic software written by Eric Young
107
* (eay@cryptsoft.com). This product includes software written by Tim
108
* Hudson (tjh@cryptsoft.com).
112
#include "cryptlib.h"
113
#include <openssl/rand.h>
114
#include "rand_lcl.h"
116
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
119
# define _WIN32_WINNT 0x0400
121
#include <wincrypt.h>
122
#include <tlhelp32.h>
124
/* Limit the time spent walking through the heap, processes, threads and modules to
125
a maximum of 1000 miliseconds each, unless CryptoGenRandom failed */
126
#define MAXDELAY 1000
128
/* Intel hardware RNG CSP -- available from
129
* http://developer.intel.com/design/security/rng/redist_license.htm
131
#define PROV_INTEL_SEC 22
132
#define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
134
static void readtimer(void);
135
static void readscreen(void);
137
/* It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined
138
when WINVER is 0x0500 and up, which currently only happens on Win2000.
139
Unfortunately, those are typedefs, so they're a little bit difficult to
140
detect properly. On the other hand, the macro CURSOR_SHOWING is defined
141
within the same conditional, so it can be use to detect the absence of said
144
#ifndef CURSOR_SHOWING
146
* Information about the global cursor.
148
typedef struct tagCURSORINFO
154
} CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
156
#define CURSOR_SHOWING 0x00000001
157
#endif /* CURSOR_SHOWING */
159
#if !defined(OPENSSL_SYS_WINCE)
160
typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTW)(HCRYPTPROV *, LPCWSTR, LPCWSTR,
162
typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV, DWORD, BYTE *);
163
typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV, DWORD);
165
typedef HWND (WINAPI *GETFOREGROUNDWINDOW)(VOID);
166
typedef BOOL (WINAPI *GETCURSORINFO)(PCURSORINFO);
167
typedef DWORD (WINAPI *GETQUEUESTATUS)(UINT);
169
typedef HANDLE (WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD);
170
typedef BOOL (WINAPI *CLOSETOOLHELP32SNAPSHOT)(HANDLE);
171
typedef BOOL (WINAPI *HEAP32FIRST)(LPHEAPENTRY32, DWORD, size_t);
172
typedef BOOL (WINAPI *HEAP32NEXT)(LPHEAPENTRY32);
173
typedef BOOL (WINAPI *HEAP32LIST)(HANDLE, LPHEAPLIST32);
174
typedef BOOL (WINAPI *PROCESS32)(HANDLE, LPPROCESSENTRY32);
175
typedef BOOL (WINAPI *THREAD32)(HANDLE, LPTHREADENTRY32);
176
typedef BOOL (WINAPI *MODULE32)(HANDLE, LPMODULEENTRY32);
180
#if 1 /* The NET API is Unicode only. It requires the use of the UNICODE
181
* macro. When UNICODE is defined LPTSTR becomes LPWSTR. LMSTR was
182
* was added to the Platform SDK to allow the NET API to be used in
183
* non-Unicode applications provided that Unicode strings were still
184
* used for input. LMSTR is defined as LPWSTR.
186
typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET)
187
(LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE*);
188
typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE);
190
#endif /* !OPENSSL_SYS_WINCE */
195
HCRYPTPROV hProvider = 0;
199
/* Determine the OS version we are on so we can turn off things
200
* that do not work properly.
202
OSVERSIONINFO osverinfo ;
203
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
204
GetVersionEx( &osverinfo ) ;
206
#if defined(OPENSSL_SYS_WINCE)
207
# if defined(_WIN32_WCE) && _WIN32_WCE>=300
208
/* Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available
209
* in commonly available implementations prior 300... */
212
/* poll the CryptoAPI PRNG */
213
/* The CryptoAPI returns sizeof(buf) bytes of randomness */
214
if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL,
215
CRYPT_VERIFYCONTEXT))
217
if (CryptGenRandom(hProvider, sizeof(buf), buf))
218
RAND_add(buf, sizeof(buf), sizeof(buf));
219
CryptReleaseContext(hProvider, 0);
223
#else /* OPENSSL_SYS_WINCE */
225
* None of below libraries are present on Windows CE, which is
226
* why we #ifndef the whole section. This also excuses us from
227
* handling the GetProcAddress issue. The trouble is that in
228
* real Win32 API GetProcAddress is available in ANSI flavor
229
* only. In WinCE on the other hand GetProcAddress is a macro
230
* most commonly defined as GetProcAddressW, which accepts
231
* Unicode argument. If we were to call GetProcAddress under
232
* WinCE, I'd recommend to either redefine GetProcAddress as
233
* GetProcAddressA (there seem to be one in common CE spec) or
234
* implement own shim routine, which would accept ANSI argument
235
* and expand it to Unicode.
238
/* load functions dynamically - not available on all systems */
239
HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL"));
240
HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL"));
242
HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL"));
243
CRYPTACQUIRECONTEXTW acquire = NULL;
244
CRYPTGENRANDOM gen = NULL;
245
CRYPTRELEASECONTEXT release = NULL;
246
NETSTATGET netstatget = NULL;
247
NETFREE netfree = NULL;
252
netstatget = (NETSTATGET) GetProcAddress(netapi,"NetStatisticsGet");
253
netfree = (NETFREE) GetProcAddress(netapi,"NetApiBufferFree");
256
if (netstatget && netfree)
259
/* NetStatisticsGet() is a Unicode only function
260
* STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0
261
* contains 17 fields. We treat each field as a source of
262
* one byte of entropy.
265
if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0)
267
RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45);
270
if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0)
272
RAND_add(outbuf, sizeof(STAT_SERVER_0), 17);
280
/* It appears like this can cause an exception deep within ADVAPI32.DLL
281
* at random times on Windows 2000. Reported by Jeffrey Altman.
284
/* Wolfgang Marczy <WMarczy@topcall.co.at> reports that
285
* the RegQueryValueEx call below can hang on NT4.0 (SP6).
286
* So we don't use this at all for now. */
288
if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
289
osverinfo.dwMajorVersion < 5)
291
/* Read Performance Statistics from NT/2000 registry
292
* The size of the performance data can vary from call
293
* to call so we must guess the size of the buffer to use
294
* and increase its size if we get an ERROR_MORE_DATA
295
* return instead of ERROR_SUCCESS.
297
LONG rc=ERROR_MORE_DATA;
302
while (rc == ERROR_MORE_DATA)
304
buf = realloc(buf,bufsz+8192);
310
rc = RegQueryValueEx(HKEY_PERFORMANCE_DATA, TEXT("Global"),
311
NULL, NULL, buf, &length);
313
if (rc == ERROR_SUCCESS)
315
/* For entropy count assume only least significant
316
* byte of each DWORD is random.
318
RAND_add(&length, sizeof(length), 0);
319
RAND_add(buf, length, length / 4.0);
321
/* Close the Registry Key to allow Windows to cleanup/close
323
* Note: The 'HKEY_PERFORMANCE_DATA' key is implicitly opened
324
* when the RegQueryValueEx above is done. However, if
325
* it is not explicitly closed, it can cause disk
326
* partition manipulation problems.
328
RegCloseKey(HKEY_PERFORMANCE_DATA);
338
* If it's available, then it's available in both ANSI
339
* and UNICODE flavors even in Win9x, documentation says.
340
* We favor Unicode...
342
acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi,
343
"CryptAcquireContextW");
344
gen = (CRYPTGENRANDOM) GetProcAddress(advapi,
346
release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi,
347
"CryptReleaseContext");
350
if (acquire && gen && release)
352
/* poll the CryptoAPI PRNG */
353
/* The CryptoAPI returns sizeof(buf) bytes of randomness */
354
if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL,
355
CRYPT_VERIFYCONTEXT))
357
if (gen(hProvider, sizeof(buf), buf) != 0)
359
RAND_add(buf, sizeof(buf), 0);
362
printf("randomness from PROV_RSA_FULL\n");
365
release(hProvider, 0);
368
/* poll the Pentium PRG with CryptoAPI */
369
if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0))
371
if (gen(hProvider, sizeof(buf), buf) != 0)
373
RAND_add(buf, sizeof(buf), sizeof(buf));
376
printf("randomness from PROV_INTEL_SEC\n");
379
release(hProvider, 0);
386
if ((osverinfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
387
!OPENSSL_isservice()) &&
388
(user = LoadLibrary(TEXT("USER32.DLL"))))
390
GETCURSORINFO cursor;
391
GETFOREGROUNDWINDOW win;
392
GETQUEUESTATUS queue;
394
win = (GETFOREGROUNDWINDOW) GetProcAddress(user, "GetForegroundWindow");
395
cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo");
396
queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus");
402
RAND_add(&h, sizeof(h), 0);
406
/* unfortunately, its not safe to call GetCursorInfo()
407
* on NT4 even though it exists in SP3 (or SP6) and
410
if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
411
osverinfo.dwMajorVersion < 5)
416
/* cursor position */
417
/* assume 2 bytes of entropy */
419
ci.cbSize = sizeof(CURSORINFO);
421
RAND_add(&ci, ci.cbSize, 2);
426
/* message queue status */
427
/* assume 1 byte of entropy */
428
w = queue(QS_ALLEVENTS);
429
RAND_add(&w, sizeof(w), 1);
435
/* Toolhelp32 snapshot: enumerate processes, threads, modules and heap
436
* http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm
437
* (Win 9x and 2000 only, not available on NT)
439
* This seeding method was proposed in Peter Gutmann, Software
440
* Generation of Practically Strong Random Numbers,
441
* http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html
442
* revised version at http://www.cryptoengines.com/~peter/06_random.pdf
443
* (The assignment of entropy estimates below is arbitrary, but based
444
* on Peter's analysis the full poll appears to be safe. Additional
445
* interactive seeding is encouraged.)
450
CREATETOOLHELP32SNAPSHOT snap;
451
CLOSETOOLHELP32SNAPSHOT close_snap;
454
HEAP32FIRST heap_first;
455
HEAP32NEXT heap_next;
456
HEAP32LIST heaplist_first, heaplist_next;
457
PROCESS32 process_first, process_next;
458
THREAD32 thread_first, thread_next;
459
MODULE32 module_first, module_next;
468
snap = (CREATETOOLHELP32SNAPSHOT)
469
GetProcAddress(kernel, "CreateToolhelp32Snapshot");
470
close_snap = (CLOSETOOLHELP32SNAPSHOT)
471
GetProcAddress(kernel, "CloseToolhelp32Snapshot");
472
heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First");
473
heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next");
474
heaplist_first = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst");
475
heaplist_next = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext");
476
process_first = (PROCESS32) GetProcAddress(kernel, "Process32First");
477
process_next = (PROCESS32) GetProcAddress(kernel, "Process32Next");
478
thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First");
479
thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next");
480
module_first = (MODULE32) GetProcAddress(kernel, "Module32First");
481
module_next = (MODULE32) GetProcAddress(kernel, "Module32Next");
483
if (snap && heap_first && heap_next && heaplist_first &&
484
heaplist_next && process_first && process_next &&
485
thread_first && thread_next && module_first &&
486
module_next && (handle = snap(TH32CS_SNAPALL,0))
487
!= INVALID_HANDLE_VALUE)
489
/* heap list and heap walking */
490
/* HEAPLIST32 contains 3 fields that will change with
491
* each entry. Consider each field a source of 1 byte
493
* HEAPENTRY32 contains 5 fields that will change with
494
* each entry. Consider each field a source of 1 byte
497
ZeroMemory(&hlist, sizeof(HEAPLIST32));
498
hlist.dwSize = sizeof(HEAPLIST32);
499
if (good) starttime = GetTickCount();
501
if (heaplist_first(handle, &hlist))
504
following discussion on dev ML, exception on WinCE (or other Win
505
platform) is theoretically of unknown origin; prevent infinite
506
loop here when this theoretical case occurs; otherwise cope with
507
the expected (MSDN documented) exception-throwing behaviour of
508
Heap32Next() on WinCE.
510
based on patch in original message by Tanguy FautrƩ (2009/03/02)
511
Subject: RAND_poll() and CreateToolhelp32Snapshot() stability
513
int ex_cnt_limit = 42;
516
RAND_add(&hlist, hlist.dwSize, 3);
519
ZeroMemory(&hentry, sizeof(HEAPENTRY32));
520
hentry.dwSize = sizeof(HEAPENTRY32);
521
if (heap_first(&hentry,
529
while (heap_next(&hentry)
530
&& (!good || (GetTickCount()-starttime)<MAXDELAY)
534
__except (EXCEPTION_EXECUTE_HANDLER)
536
/* ignore access violations when walking the heap list */
539
} while (heaplist_next(handle, &hlist)
540
&& (!good || (GetTickCount()-starttime)<MAXDELAY)
541
&& ex_cnt_limit > 0);
545
if (heaplist_first(handle, &hlist))
549
RAND_add(&hlist, hlist.dwSize, 3);
550
hentry.dwSize = sizeof(HEAPENTRY32);
551
if (heap_first(&hentry,
559
while (heap_next(&hentry)
562
} while (heaplist_next(handle, &hlist)
563
&& (!good || (GetTickCount()-starttime)<MAXDELAY));
567
/* process walking */
568
/* PROCESSENTRY32 contains 9 fields that will change
569
* with each entry. Consider each field a source of
572
p.dwSize = sizeof(PROCESSENTRY32);
574
if (good) starttime = GetTickCount();
575
if (process_first(handle, &p))
577
RAND_add(&p, p.dwSize, 9);
578
while (process_next(handle, &p) && (!good || (GetTickCount()-starttime)<MAXDELAY));
581
/* THREADENTRY32 contains 6 fields that will change
582
* with each entry. Consider each field a source of
585
t.dwSize = sizeof(THREADENTRY32);
586
if (good) starttime = GetTickCount();
587
if (thread_first(handle, &t))
589
RAND_add(&t, t.dwSize, 6);
590
while (thread_next(handle, &t) && (!good || (GetTickCount()-starttime)<MAXDELAY));
593
/* MODULEENTRY32 contains 9 fields that will change
594
* with each entry. Consider each field a source of
597
m.dwSize = sizeof(MODULEENTRY32);
598
if (good) starttime = GetTickCount();
599
if (module_first(handle, &m))
601
RAND_add(&m, m.dwSize, 9);
602
while (module_next(handle, &m)
603
&& (!good || (GetTickCount()-starttime)<MAXDELAY));
614
#endif /* !OPENSSL_SYS_WINCE */
619
/* memory usage statistics */
620
GlobalMemoryStatus(&m);
621
RAND_add(&m, sizeof(m), 1);
624
w = GetCurrentProcessId();
625
RAND_add(&w, sizeof(w), 1);
628
printf("Exiting RAND_poll\n");
634
int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
636
double add_entropy=0;
650
static int lastx,lasty,lastdx,lastdy;
657
if (dx != 0 && dy != 0 && dx-lastdx != 0 && dy-lastdy != 0)
660
lastdx=dx, lastdy=dy;
666
RAND_add(&iMsg, sizeof(iMsg), add_entropy);
667
RAND_add(&wParam, sizeof(wParam), 0);
668
RAND_add(&lParam, sizeof(lParam), 0);
670
return (RAND_status());
674
void RAND_screen(void) /* function available for backward compatibility */
681
/* feed timing information to the PRNG */
682
static void readtimer(void)
686
static int have_perfc = 1;
687
#if defined(_MSC_VER) && defined(_M_X86)
688
static int have_tsc = 1;
698
RAND_add(&cyclecount, sizeof(cyclecount), 1);
699
} __except(EXCEPTION_EXECUTE_HANDLER) {
708
if (QueryPerformanceCounter(&l) == 0)
711
RAND_add(&l, sizeof(l), 0);
714
if (!have_tsc && !have_perfc) {
716
RAND_add(&w, sizeof(w), 0);
720
/* feed screen contents to PRNG */
721
/*****************************************************************************
723
* Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V.
726
* <URL:http://support.microsoft.com/default.aspx?scid=kb;[LN];97193>;
727
* the original copyright message is:
729
* (C) Copyright Microsoft Corp. 1993. All rights reserved.
731
* You have a royalty-free right to use, modify, reproduce and
732
* distribute the Sample Files (and/or any modified version) in
733
* any way you find useful, provided that you agree that
734
* Microsoft has no warranty obligations or liability for any
735
* Sample Application Files which are modified.
738
static void readscreen(void)
740
#if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN)
741
HDC hScrDC; /* screen DC */
742
HDC hMemDC; /* memory DC */
743
HBITMAP hBitmap; /* handle for our bitmap */
744
HBITMAP hOldBitmap; /* handle for previous bitmap */
745
BITMAP bm; /* bitmap properties */
746
unsigned int size; /* size of bitmap */
747
char *bmbits; /* contents of bitmap */
748
int w; /* screen width */
749
int h; /* screen height */
750
int y; /* y-coordinate of screen lines to grab */
751
int n = 16; /* number of screen lines to grab at a time */
753
if (GetVersion() < 0x80000000 && OPENSSL_isservice()>0)
756
/* Create a screen DC and a memory DC compatible to screen DC */
757
hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
758
hMemDC = CreateCompatibleDC(hScrDC);
760
/* Get screen resolution */
761
w = GetDeviceCaps(hScrDC, HORZRES);
762
h = GetDeviceCaps(hScrDC, VERTRES);
764
/* Create a bitmap compatible with the screen DC */
765
hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
767
/* Select new bitmap into memory DC */
768
hOldBitmap = SelectObject(hMemDC, hBitmap);
770
/* Get bitmap properties */
771
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
772
size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
774
bmbits = OPENSSL_malloc(size);
776
/* Now go through the whole screen, repeatedly grabbing n lines */
777
for (y = 0; y < h-n; y += n)
779
unsigned char md[MD_DIGEST_LENGTH];
781
/* Bitblt screen DC to memory DC */
782
BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
784
/* Copy bitmap bits from memory DC to bmbits */
785
GetBitmapBits(hBitmap, size, bmbits);
787
/* Get the hash of the bitmap */
790
/* Seed the random generator with the hash value */
791
RAND_add(md, MD_DIGEST_LENGTH, 0);
794
OPENSSL_free(bmbits);
797
/* Select old bitmap back into memory DC */
798
hBitmap = SelectObject(hMemDC, hOldBitmap);
801
DeleteObject(hBitmap);
804
#endif /* !OPENSSL_SYS_WINCE */