Bring objects.pl output even closer to new format.
[openssl.git] / crypto / rand / rand_win.c
index 3584842224c079f9d80cd8115b5bb44becac433e..0c616c4c57271de018d345faba1422842b91a0a2 100644 (file)
@@ -5,21 +5,21 @@
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
- * 
+ *
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
+ *
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
+ * 4. If you include any Windows specific code (or a derivative thereof) from
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -49,7 +49,7 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- * 
+ *
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
@@ -63,7 +63,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
 #include "rand_lcl.h"
 
 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
-#include <windows.h>
-#ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0400
-#endif
-#include <wincrypt.h>
-#include <tlhelp32.h>
+# include <windows.h>
+# ifndef _WIN32_WINNT
+#  define _WIN32_WINNT 0x0400
+# endif
+# include <wincrypt.h>
+# include <tlhelp32.h>
+
+/*
+ * Limit the time spent walking through the heap, processes, threads and
+ * modules to a maximum of 1000 miliseconds each, unless CryptoGenRandom
+ * failed
+ */
+# define MAXDELAY 1000
 
-/* Intel hardware RNG CSP -- available from
+/*
+ * Intel hardware RNG CSP -- available from
  * http://developer.intel.com/design/security/rng/redist_license.htm
  */
-#define PROV_INTEL_SEC 22
-#define INTEL_DEF_PROV TEXT("Intel Hardware Cryptographic Service Provider")
+# define PROV_INTEL_SEC 22
+# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
 
 static void readtimer(void);
 static void readscreen(void);
 
-/* It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined
-   when WINVER is 0x0500 and up, which currently only happens on Win2000.
-   Unfortunately, those are typedefs, so they're a little bit difficult to
-   detect properly.  On the other hand, the macro CURSOR_SHOWING is defined
-   within the same conditional, so it can be use to detect the absence of said
-   typedefs. */
+/*
+ * It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined
+ * when WINVER is 0x0500 and up, which currently only happens on Win2000.
+ * Unfortunately, those are typedefs, so they're a little bit difficult to
+ * detect properly.  On the other hand, the macro CURSOR_SHOWING is defined
+ * within the same conditional, so it can be use to detect the absence of
+ * said typedefs.
+ */
 
-#ifndef CURSOR_SHOWING
+# ifndef CURSOR_SHOWING
 /*
  * Information about the global cursor.
  */
-typedef struct tagCURSORINFO
-{
-    DWORD   cbSize;
-    DWORD   flags;
+typedef struct tagCURSORINFO {
+    DWORD cbSize;
+    DWORD flags;
     HCURSOR hCursor;
-    POINT   ptScreenPos;
+    POINT ptScreenPos;
 } CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
 
-#define CURSOR_SHOWING     0x00000001
-#endif /* CURSOR_SHOWING */
-
-typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *, LPCTSTR, LPCTSTR,
-                                   DWORD, DWORD);
-typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV, DWORD, BYTE *);
-typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV, DWORD);
-
-typedef HWND (WINAPI *GETFOREGROUNDWINDOW)(VOID);
-typedef BOOL (WINAPI *GETCURSORINFO)(PCURSORINFO);
-typedef DWORD (WINAPI *GETQUEUESTATUS)(UINT);
-
-typedef HANDLE (WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD);
-typedef BOOL (WINAPI *CLOSETOOLHELP32SNAPSHOT)(HANDLE);
-typedef BOOL (WINAPI *HEAP32FIRST)(LPHEAPENTRY32, DWORD, DWORD);
-typedef BOOL (WINAPI *HEAP32NEXT)(LPHEAPENTRY32);
-typedef BOOL (WINAPI *HEAP32LIST)(HANDLE, LPHEAPLIST32);
-typedef BOOL (WINAPI *PROCESS32)(HANDLE, LPPROCESSENTRY32);
-typedef BOOL (WINAPI *THREAD32)(HANDLE, LPTHREADENTRY32);
-typedef BOOL (WINAPI *MODULE32)(HANDLE, LPMODULEENTRY32);
-
-#include <lmcons.h>
-#ifndef OPENSSL_SYS_WINCE
-#include <lmstats.h>
-#endif
-#if 1 /* The NET API is Unicode only.  It requires the use of the UNICODE
-       * macro.  When UNICODE is defined LPTSTR becomes LPWSTR.  LMSTR was
-       * was added to the Platform SDK to allow the NET API to be used in
-       * non-Unicode applications provided that Unicode strings were still
-       * used for input.  LMSTR is defined as LPWSTR.
-       */
-typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET)
-        (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE*);
-typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE);
-#endif /* 1 */
+#  define CURSOR_SHOWING     0x00000001
+# endif                         /* CURSOR_SHOWING */
+
+# if !defined(OPENSSL_SYS_WINCE)
+typedef BOOL(WINAPI *CRYPTACQUIRECONTEXTW) (HCRYPTPROV *, LPCWSTR, LPCWSTR,
+                                            DWORD, DWORD);
+typedef BOOL(WINAPI *CRYPTGENRANDOM) (HCRYPTPROV, DWORD, BYTE *);
+typedef BOOL(WINAPI *CRYPTRELEASECONTEXT) (HCRYPTPROV, DWORD);
+
+typedef HWND(WINAPI *GETFOREGROUNDWINDOW) (VOID);
+typedef BOOL(WINAPI *GETCURSORINFO) (PCURSORINFO);
+typedef DWORD(WINAPI *GETQUEUESTATUS) (UINT);
+
+typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
+typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
+typedef BOOL(WINAPI *HEAP32FIRST) (LPHEAPENTRY32, DWORD, size_t);
+typedef BOOL(WINAPI *HEAP32NEXT) (LPHEAPENTRY32);
+typedef BOOL(WINAPI *HEAP32LIST) (HANDLE, LPHEAPLIST32);
+typedef BOOL(WINAPI *PROCESS32) (HANDLE, LPPROCESSENTRY32);
+typedef BOOL(WINAPI *THREAD32) (HANDLE, LPTHREADENTRY32);
+typedef BOOL(WINAPI *MODULE32) (HANDLE, LPMODULEENTRY32);
+
+#  include <lmcons.h>
+#  include <lmstats.h>
+#  if 1
+/*
+ * The NET API is Unicode only.  It requires the use of the UNICODE macro.
+ * When UNICODE is defined LPTSTR becomes LPWSTR.  LMSTR was was added to the
+ * Platform SDK to allow the NET API to be used in non-Unicode applications
+ * provided that Unicode strings were still used for input.  LMSTR is defined
+ * as LPWSTR.
+ */
+typedef NET_API_STATUS(NET_API_FUNCTION *NETSTATGET)
+ (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE *);
+typedef NET_API_STATUS(NET_API_FUNCTION *NETFREE) (LPBYTE);
+#  endif                        /* 1 */
+# endif                         /* !OPENSSL_SYS_WINCE */
 
 int RAND_poll(void)
 {
-       MEMORYSTATUS m;
-       HCRYPTPROV hProvider = 0;
-       BYTE buf[64];
-       DWORD w;
-       HWND h;
-
-       HMODULE advapi, kernel, user, netapi;
-       CRYPTACQUIRECONTEXT acquire = 0;
-       CRYPTGENRANDOM gen = 0;
-       CRYPTRELEASECONTEXT release = 0;
-#if 1 /* There was previously a problem with NETSTATGET.  Currently, this
-       * section is still experimental, but if all goes well, this conditional
-       * will be removed
-       */
-       NETSTATGET netstatget = 0;
-       NETFREE netfree = 0;
-#endif /* 1 */
-
-       /* Determine the OS version we are on so we can turn off things 
-        * that do not work properly.
-        */
-        OSVERSIONINFO osverinfo ;
-        osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
-        GetVersionEx( &osverinfo ) ;
-
-#if defined(OPENSSL_SYS_WINCE) && WCEPLATFORM!=MS_HPC_PRO
-       /* poll the CryptoAPI PRNG */
-       /* The CryptoAPI returns sizeof(buf) bytes of randomness */
-       if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
-               {
-               if (CryptGenRandom(hProvider, sizeof(buf), buf))
-                       RAND_add(buf, sizeof(buf), sizeof(buf));
-               CryptReleaseContext(hProvider, 0); 
-               }
-#endif
-
-       /* load functions dynamically - not available on all systems */
-       advapi = LoadLibrary(TEXT("ADVAPI32.DLL"));
-       kernel = LoadLibrary(TEXT("KERNEL32.DLL"));
-       user = LoadLibrary(TEXT("USER32.DLL"));
-       netapi = LoadLibrary(TEXT("NETAPI32.DLL"));
-
-#ifndef OPENSSL_SYS_WINCE
-#if 1 /* There was previously a problem with NETSTATGET.  Currently, this
-       * section is still experimental, but if all goes well, this conditional
-       * will be removed
-       */
-       if (netapi)
-               {
-               netstatget = (NETSTATGET) GetProcAddress(netapi,TEXT("NetStatisticsGet"));
-               netfree = (NETFREE) GetProcAddress(netapi,TEXT("NetApiBufferFree"));
-               }
-
-       if (netstatget && netfree)
-               {
-               LPBYTE outbuf;
-               /* NetStatisticsGet() is a Unicode only function
-                * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0
-                * contains 17 fields.  We treat each field as a source of
-                * one byte of entropy.
-                 */
-
-               if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0)
-                       {
-                       RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45);
-                       netfree(outbuf);
-                       }
-               if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0)
-                       {
-                       RAND_add(outbuf, sizeof(STAT_SERVER_0), 17);
-                       netfree(outbuf);
-                       }
-               }
-
-       if (netapi)
-               FreeLibrary(netapi);
-#endif /* 1 */
-#endif /* !OPENSSL_SYS_WINCE */
-#ifndef OPENSSL_SYS_WINCE
-        /* It appears like this can cause an exception deep within ADVAPI32.DLL
-         * at random times on Windows 2000.  Reported by Jeffrey Altman.  
-         * Only use it on NT.
-        */
-       /* Wolfgang Marczy <WMarczy@topcall.co.at> reports that
-        * the RegQueryValueEx call below can hang on NT4.0 (SP6).
-        * So we don't use this at all for now. */
-#if 0
-        if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
-               osverinfo.dwMajorVersion < 5)
-               {
-               /* Read Performance Statistics from NT/2000 registry
-                * The size of the performance data can vary from call
-                * to call so we must guess the size of the buffer to use
-                * and increase its size if we get an ERROR_MORE_DATA
-                * return instead of ERROR_SUCCESS.
-                */
-               LONG   rc=ERROR_MORE_DATA;
-               char * buf=NULL;
-               DWORD bufsz=0;
-               DWORD length;
-
-               while (rc == ERROR_MORE_DATA)
-                       {
-                       buf = realloc(buf,bufsz+8192);
-                       if (!buf)
-                               break;
-                       bufsz += 8192;
-
-                       length = bufsz;
-                       rc = RegQueryValueEx(HKEY_PERFORMANCE_DATA, TEXT("Global"),
-                               NULL, NULL, buf, &length);
-                       }
-               if (rc == ERROR_SUCCESS)
-                       {
-                        /* For entropy count assume only least significant
-                        * byte of each DWORD is random.
-                        */
-                       RAND_add(&length, sizeof(length), 0);
-                       RAND_add(buf, length, length / 4.0);
-
-                       /* Close the Registry Key to allow Windows to cleanup/close
-                        * the open handle
-                        * Note: The 'HKEY_PERFORMANCE_DATA' key is implicitly opened
-                        *       when the RegQueryValueEx above is done.  However, if
-                        *       it is not explicitly closed, it can cause disk
-                        *       partition manipulation problems.
-                        */
-                       RegCloseKey(HKEY_PERFORMANCE_DATA);
-                       }
-               if (buf)
-                       free(buf);
-               }
-#endif
-#endif /* !OPENSSL_SYS_WINCE */
-
-       if (advapi)
-               {
-               acquire = (CRYPTACQUIRECONTEXT) GetProcAddress(advapi,
-                       TEXT("CryptAcquireContextA"));
-               gen = (CRYPTGENRANDOM) GetProcAddress(advapi,
-                       TEXT("CryptGenRandom"));
-               release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi,
-                       TEXT("CryptReleaseContext"));
-               }
-
-       if (acquire && gen && release)
-               {
-               /* poll the CryptoAPI PRNG */
-                /* The CryptoAPI returns sizeof(buf) bytes of randomness */
-               if (acquire(&hProvider, 0, 0, PROV_RSA_FULL,
-                       CRYPT_VERIFYCONTEXT))
-                       {
-                       if (gen(hProvider, sizeof(buf), buf) != 0)
-                               {
-                               RAND_add(buf, sizeof(buf), 0);
-#if 0
-                               printf("randomness from PROV_RSA_FULL\n");
-#endif
-                               }
-                       release(hProvider, 0); 
-                       }
-               
-               /* poll the Pentium PRG with CryptoAPI */
-               if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0))
-                       {
-                       if (gen(hProvider, sizeof(buf), buf) != 0)
-                               {
-                               RAND_add(buf, sizeof(buf), sizeof(buf));
-#if 0
-                               printf("randomness from PROV_INTEL_SEC\n");
-#endif
-                               }
-                       release(hProvider, 0);
-                       }
-               }
+    MEMORYSTATUS m;
+    HCRYPTPROV hProvider = 0;
+    DWORD w;
+    int good = 0;
+
+# if defined(OPENSSL_SYS_WINCE)
+#  if defined(_WIN32_WCE) && _WIN32_WCE>=300
+    /*
+     * Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available
+     * in commonly available implementations prior 300...
+     */
+    {
+        BYTE buf[64];
+        /* poll the CryptoAPI PRNG */
+        /* The CryptoAPI returns sizeof(buf) bytes of randomness */
+        if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL,
+                                 CRYPT_VERIFYCONTEXT)) {
+            if (CryptGenRandom(hProvider, sizeof(buf), buf))
+                RAND_add(buf, sizeof(buf), sizeof(buf));
+            CryptReleaseContext(hProvider, 0);
+        }
+    }
+#  endif
+# else                          /* OPENSSL_SYS_WINCE */
+    /*
+     * None of below libraries are present on Windows CE, which is
+     * why we #ifndef the whole section. This also excuses us from
+     * handling the GetProcAddress issue. The trouble is that in
+     * real Win32 API GetProcAddress is available in ANSI flavor
+     * only. In WinCE on the other hand GetProcAddress is a macro
+     * most commonly defined as GetProcAddressW, which accepts
+     * Unicode argument. If we were to call GetProcAddress under
+     * WinCE, I'd recommend to either redefine GetProcAddress as
+     * GetProcAddressA (there seem to be one in common CE spec) or
+     * implement own shim routine, which would accept ANSI argument
+     * and expand it to Unicode.
+     */
+    {
+        /* load functions dynamically - not available on all systems */
+        HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL"));
+        HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL"));
+        HMODULE user = NULL;
+        HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL"));
+        CRYPTACQUIRECONTEXTW acquire = NULL;
+        CRYPTGENRANDOM gen = NULL;
+        CRYPTRELEASECONTEXT release = NULL;
+        NETSTATGET netstatget = NULL;
+        NETFREE netfree = NULL;
+        BYTE buf[64];
+
+        if (netapi) {
+            netstatget =
+                (NETSTATGET) GetProcAddress(netapi, "NetStatisticsGet");
+            netfree = (NETFREE) GetProcAddress(netapi, "NetApiBufferFree");
+        }
+
+        if (netstatget && netfree) {
+            LPBYTE outbuf;
+            /*
+             * NetStatisticsGet() is a Unicode only function
+             * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0
+             * contains 17 fields.  We treat each field as a source of one
+             * byte of entropy.
+             */
+
+            if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0) {
+                RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45);
+                netfree(outbuf);
+            }
+            if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0) {
+                RAND_add(outbuf, sizeof(STAT_SERVER_0), 17);
+                netfree(outbuf);
+            }
+        }
+
+        if (netapi)
+            FreeLibrary(netapi);
+
+        /*
+         * It appears like this can cause an exception deep within
+         * ADVAPI32.DLL at random times on Windows 2000.  Reported by Jeffrey
+         * Altman. Only use it on NT.
+         */
+
+        if (advapi) {
+            /*
+             * If it's available, then it's available in both ANSI
+             * and UNICODE flavors even in Win9x, documentation says.
+             * We favor Unicode...
+             */
+            acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi,
+                                                            "CryptAcquireContextW");
+            gen = (CRYPTGENRANDOM) GetProcAddress(advapi, "CryptGenRandom");
+            release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi,
+                                                           "CryptReleaseContext");
+        }
+
+        if (acquire && gen && release) {
+            /* poll the CryptoAPI PRNG */
+            /* The CryptoAPI returns sizeof(buf) bytes of randomness */
+            if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL,
+                        CRYPT_VERIFYCONTEXT)) {
+                if (gen(hProvider, sizeof(buf), buf) != 0) {
+                    RAND_add(buf, sizeof(buf), 0);
+                    good = 1;
+#  if 0
+                    printf("randomness from PROV_RSA_FULL\n");
+#  endif
+                }
+                release(hProvider, 0);
+            }
+
+            /* poll the Pentium PRG with CryptoAPI */
+            if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0)) {
+                if (gen(hProvider, sizeof(buf), buf) != 0) {
+                    RAND_add(buf, sizeof(buf), sizeof(buf));
+                    good = 1;
+#  if 0
+                    printf("randomness from PROV_INTEL_SEC\n");
+#  endif
+                }
+                release(hProvider, 0);
+            }
+        }
 
         if (advapi)
-               FreeLibrary(advapi);
-
-       /* timer data */
-       readtimer();
-       
-       /* memory usage statistics */
-       GlobalMemoryStatus(&m);
-       RAND_add(&m, sizeof(m), 1);
-
-       /* process ID */
-       w = GetCurrentProcessId();
-       RAND_add(&w, sizeof(w), 1);
-
-       if (user)
-               {
-               GETCURSORINFO cursor;
-               GETFOREGROUNDWINDOW win;
-               GETQUEUESTATUS queue;
-
-               win = (GETFOREGROUNDWINDOW) GetProcAddress(user, TEXT("GetForegroundWindow"));
-               cursor = (GETCURSORINFO) GetProcAddress(user, TEXT("GetCursorInfo"));
-               queue = (GETQUEUESTATUS) GetProcAddress(user, TEXT("GetQueueStatus"));
-
-               if (win)
-                       {
-                       /* window handle */
-                       h = win();
-                       RAND_add(&h, sizeof(h), 0);
-                       }
-               if (cursor)
-                       {
-                       /* unfortunately, its not safe to call GetCursorInfo()
-                        * on NT4 even though it exists in SP3 (or SP6) and
-                        * higher.
-                        */
-                       if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
-                               osverinfo.dwMajorVersion < 5)
-                               cursor = 0;
-                       }
-               if (cursor)
-                       {
-                       /* cursor position */
-                        /* assume 2 bytes of entropy */
-                       CURSORINFO ci;
-                       ci.cbSize = sizeof(CURSORINFO);
-                       if (cursor(&ci))
-                               RAND_add(&ci, ci.cbSize, 2);
-                       }
-
-               if (queue)
-                       {
-                       /* message queue status */
-                        /* assume 1 byte of entropy */
-                       w = queue(QS_ALLEVENTS);
-                       RAND_add(&w, sizeof(w), 1);
-                       }
-
-               FreeLibrary(user);
-               }
-
-       /* Toolhelp32 snapshot: enumerate processes, threads, modules and heap
-        * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm
-        * (Win 9x and 2000 only, not available on NT)
-        *
-        * This seeding method was proposed in Peter Gutmann, Software
-        * Generation of Practically Strong Random Numbers,
-        * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html
-        * revised version at http://www.cryptoengines.com/~peter/06_random.pdf
-        * (The assignment of entropy estimates below is arbitrary, but based
-        * on Peter's analysis the full poll appears to be safe. Additional
-        * interactive seeding is encouraged.)
-        */
-
-       if (kernel)
-               {
-               CREATETOOLHELP32SNAPSHOT snap;
-               CLOSETOOLHELP32SNAPSHOT close_snap;
-               HANDLE handle;
-
-               HEAP32FIRST heap_first;
-               HEAP32NEXT heap_next;
-               HEAP32LIST heaplist_first, heaplist_next;
-               PROCESS32 process_first, process_next;
-               THREAD32 thread_first, thread_next;
-               MODULE32 module_first, module_next;
-
-               HEAPLIST32 hlist;
-               HEAPENTRY32 hentry;
-               PROCESSENTRY32 p;
-               THREADENTRY32 t;
-               MODULEENTRY32 m;
-
-               snap = (CREATETOOLHELP32SNAPSHOT)
-                       GetProcAddress(kernel, TEXT("CreateToolhelp32Snapshot"));
-               close_snap = (CLOSETOOLHELP32SNAPSHOT)
-                       GetProcAddress(kernel, TEXT("CloseToolhelp32Snapshot"));
-               heap_first = (HEAP32FIRST) GetProcAddress(kernel, TEXT("Heap32First"));
-               heap_next = (HEAP32NEXT) GetProcAddress(kernel, TEXT("Heap32Next"));
-               heaplist_first = (HEAP32LIST) GetProcAddress(kernel, TEXT("Heap32ListFirst"));
-               heaplist_next = (HEAP32LIST) GetProcAddress(kernel, TEXT("Heap32ListNext"));
-               process_first = (PROCESS32) GetProcAddress(kernel, TEXT("Process32First"));
-               process_next = (PROCESS32) GetProcAddress(kernel, TEXT("Process32Next"));
-               thread_first = (THREAD32) GetProcAddress(kernel, TEXT("Thread32First"));
-               thread_next = (THREAD32) GetProcAddress(kernel, TEXT("Thread32Next"));
-               module_first = (MODULE32) GetProcAddress(kernel, TEXT("Module32First"));
-               module_next = (MODULE32) GetProcAddress(kernel, TEXT("Module32Next"));
-
-               if (snap && heap_first && heap_next && heaplist_first &&
-                       heaplist_next && process_first && process_next &&
-                       thread_first && thread_next && module_first &&
-                       module_next && (handle = snap(TH32CS_SNAPALL,0))
-                       != INVALID_HANDLE_VALUE)
-                       {
-                       /* heap list and heap walking */
-                        /* HEAPLIST32 contains 3 fields that will change with
-                         * each entry.  Consider each field a source of 1 byte
-                         * of entropy.
-                         * HEAPENTRY32 contains 5 fields that will change with 
-                         * each entry.  Consider each field a source of 1 byte
-                         * of entropy.
-                         */
-                       hlist.dwSize = sizeof(HEAPLIST32);              
-                       if (heaplist_first(handle, &hlist))
-                               do
-                                       {
-                                       RAND_add(&hlist, hlist.dwSize, 3);
-                                       hentry.dwSize = sizeof(HEAPENTRY32);
-                                       if (heap_first(&hentry,
-                                               hlist.th32ProcessID,
-                                               hlist.th32HeapID))
-                                               {
-                                               int entrycnt = 80;
-                                               do
-                                                       RAND_add(&hentry,
-                                                               hentry.dwSize, 5);
-                                               while (heap_next(&hentry)
-                                                       && --entrycnt > 0);
-                                               }
-                                       } while (heaplist_next(handle,
-                                               &hlist));
-                       
-                       /* process walking */
-                        /* PROCESSENTRY32 contains 9 fields that will change
-                         * with each entry.  Consider each field a source of
-                         * 1 byte of entropy.
-                         */
-                       p.dwSize = sizeof(PROCESSENTRY32);
-                       if (process_first(handle, &p))
-                               do
-                                       RAND_add(&p, p.dwSize, 9);
-                               while (process_next(handle, &p));
-
-                       /* thread walking */
-                        /* THREADENTRY32 contains 6 fields that will change
-                         * with each entry.  Consider each field a source of
-                         * 1 byte of entropy.
-                         */
-                       t.dwSize = sizeof(THREADENTRY32);
-                       if (thread_first(handle, &t))
-                               do
-                                       RAND_add(&t, t.dwSize, 6);
-                               while (thread_next(handle, &t));
-
-                       /* module walking */
-                        /* MODULEENTRY32 contains 9 fields that will change
-                         * with each entry.  Consider each field a source of
-                         * 1 byte of entropy.
-                         */
-                       m.dwSize = sizeof(MODULEENTRY32);
-                       if (module_first(handle, &m))
-                               do
-                                       RAND_add(&m, m.dwSize, 9);
-                               while (module_next(handle, &m));
-                       if (close_snap)
-                               close_snap(handle);
-                       else
-                               CloseHandle(handle);
-                       }
-
-               FreeLibrary(kernel);
-               }
-
-#if 0
-       printf("Exiting RAND_poll\n");
-#endif
-
-       return(1);
-}
-
-int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
-        {
-        double add_entropy=0;
-
-        switch (iMsg)
-                {
-        case WM_KEYDOWN:
-                        {
-                        static WPARAM key;
-                        if (key != wParam)
-                                add_entropy = 0.05;
-                        key = wParam;
+            FreeLibrary(advapi);
+
+        if ((!check_winnt() ||
+             !OPENSSL_isservice()) &&
+            (user = LoadLibrary(TEXT("USER32.DLL")))) {
+            GETCURSORINFO cursor;
+            GETFOREGROUNDWINDOW win;
+            GETQUEUESTATUS queue;
+
+            win =
+                (GETFOREGROUNDWINDOW) GetProcAddress(user,
+                                                     "GetForegroundWindow");
+            cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo");
+            queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus");
+
+            if (win) {
+                /* window handle */
+                HWND h = win();
+                RAND_add(&h, sizeof(h), 0);
+            }
+            if (cursor) {
+                /*
+                 * unfortunately, its not safe to call GetCursorInfo() on NT4
+                 * even though it exists in SP3 (or SP6) and higher.
+                 */
+                if (check_winnt() && !check_win_minplat(5))
+                    cursor = 0;
+            }
+            if (cursor) {
+                /* cursor position */
+                /* assume 2 bytes of entropy */
+                CURSORINFO ci;
+                ci.cbSize = sizeof(CURSORINFO);
+                if (cursor(&ci))
+                    RAND_add(&ci, ci.cbSize, 2);
+            }
+
+            if (queue) {
+                /* message queue status */
+                /* assume 1 byte of entropy */
+                w = queue(QS_ALLEVENTS);
+                RAND_add(&w, sizeof(w), 1);
+            }
+
+            FreeLibrary(user);
+        }
+
+        /*-
+         * Toolhelp32 snapshot: enumerate processes, threads, modules and heap
+         * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm
+         * (Win 9x and 2000 only, not available on NT)
+         *
+         * This seeding method was proposed in Peter Gutmann, Software
+         * Generation of Practically Strong Random Numbers,
+         * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html
+         * revised version at http://www.cryptoengines.com/~peter/06_random.pdf
+         * (The assignment of entropy estimates below is arbitrary, but based
+         * on Peter's analysis the full poll appears to be safe. Additional
+         * interactive seeding is encouraged.)
+         */
+
+        if (kernel) {
+            CREATETOOLHELP32SNAPSHOT snap;
+            CLOSETOOLHELP32SNAPSHOT close_snap;
+            HANDLE handle;
+
+            HEAP32FIRST heap_first;
+            HEAP32NEXT heap_next;
+            HEAP32LIST heaplist_first, heaplist_next;
+            PROCESS32 process_first, process_next;
+            THREAD32 thread_first, thread_next;
+            MODULE32 module_first, module_next;
+
+            HEAPLIST32 hlist;
+            HEAPENTRY32 hentry;
+            PROCESSENTRY32 p;
+            THREADENTRY32 t;
+            MODULEENTRY32 m;
+            DWORD starttime = 0;
+
+            snap = (CREATETOOLHELP32SNAPSHOT)
+                GetProcAddress(kernel, "CreateToolhelp32Snapshot");
+            close_snap = (CLOSETOOLHELP32SNAPSHOT)
+                GetProcAddress(kernel, "CloseToolhelp32Snapshot");
+            heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First");
+            heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next");
+            heaplist_first =
+                (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst");
+            heaplist_next =
+                (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext");
+            process_first =
+                (PROCESS32) GetProcAddress(kernel, "Process32First");
+            process_next =
+                (PROCESS32) GetProcAddress(kernel, "Process32Next");
+            thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First");
+            thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next");
+            module_first = (MODULE32) GetProcAddress(kernel, "Module32First");
+            module_next = (MODULE32) GetProcAddress(kernel, "Module32Next");
+
+            if (snap && heap_first && heap_next && heaplist_first &&
+                heaplist_next && process_first && process_next &&
+                thread_first && thread_next && module_first &&
+                module_next && (handle = snap(TH32CS_SNAPALL, 0))
+                != INVALID_HANDLE_VALUE) {
+                /* heap list and heap walking */
+                /*
+                 * HEAPLIST32 contains 3 fields that will change with each
+                 * entry.  Consider each field a source of 1 byte of entropy.
+                 * HEAPENTRY32 contains 5 fields that will change with each
+                 * entry.  Consider each field a source of 1 byte of entropy.
+                 */
+                ZeroMemory(&hlist, sizeof(HEAPLIST32));
+                hlist.dwSize = sizeof(HEAPLIST32);
+                if (good)
+                    starttime = GetTickCount();
+#  ifdef _MSC_VER
+                if (heaplist_first(handle, &hlist)) {
+                    /*
+                     * following discussion on dev ML, exception on WinCE (or
+                     * other Win platform) is theoretically of unknown
+                     * origin; prevent infinite loop here when this
+                     * theoretical case occurs; otherwise cope with the
+                     * expected (MSDN documented) exception-throwing
+                     * behaviour of Heap32Next() on WinCE.
+                     *
+                     * based on patch in original message by Tanguy Fautré
+                     * (2009/03/02) Subject: RAND_poll() and
+                     * CreateToolhelp32Snapshot() stability
+                     */
+                    int ex_cnt_limit = 42;
+                    do {
+                        RAND_add(&hlist, hlist.dwSize, 3);
+                        __try {
+                            ZeroMemory(&hentry, sizeof(HEAPENTRY32));
+                            hentry.dwSize = sizeof(HEAPENTRY32);
+                            if (heap_first(&hentry,
+                                           hlist.th32ProcessID,
+                                           hlist.th32HeapID)) {
+                                int entrycnt = 80;
+                                do
+                                    RAND_add(&hentry, hentry.dwSize, 5);
+                                while (heap_next(&hentry)
+                                       && (!good
+                                           || (GetTickCount() - starttime) <
+                                           MAXDELAY)
+                                       && --entrycnt > 0);
+                            }
                         }
-                        break;
-       case WM_MOUSEMOVE:
-                        {
-                        static int lastx,lasty,lastdx,lastdy;
-                        int x,y,dx,dy;
-
-                        x=LOWORD(lParam);
-                        y=HIWORD(lParam);
-                        dx=lastx-x;
-                        dy=lasty-y;
-                        if (dx != 0 && dy != 0 && dx-lastdx != 0 && dy-lastdy != 0)
-                                add_entropy=.2;
-                        lastx=x, lasty=y;
-                        lastdx=dx, lastdy=dy;
+                        __except(EXCEPTION_EXECUTE_HANDLER) {
+                            /*
+                             * ignore access violations when walking the heap
+                             * list
+                             */
+                            ex_cnt_limit--;
                         }
-               break;
-               }
-
-       readtimer();
-        RAND_add(&iMsg, sizeof(iMsg), add_entropy);
-       RAND_add(&wParam, sizeof(wParam), 0);
-       RAND_add(&lParam, sizeof(lParam), 0);
-       return (RAND_status());
-       }
-
+                    } while (heaplist_next(handle, &hlist)
+                             && (!good
+                                 || (GetTickCount() - starttime) < MAXDELAY)
+                             && ex_cnt_limit > 0);
+                }
+#  else
+                if (heaplist_first(handle, &hlist)) {
+                    do {
+                        RAND_add(&hlist, hlist.dwSize, 3);
+                        hentry.dwSize = sizeof(HEAPENTRY32);
+                        if (heap_first(&hentry,
+                                       hlist.th32ProcessID,
+                                       hlist.th32HeapID)) {
+                            int entrycnt = 80;
+                            do
+                                RAND_add(&hentry, hentry.dwSize, 5);
+                            while (heap_next(&hentry)
+                                   && --entrycnt > 0);
+                        }
+                    } while (heaplist_next(handle, &hlist)
+                             && (!good
+                                 || (GetTickCount() - starttime) < MAXDELAY));
+                }
+#  endif
+
+                /* process walking */
+                /*
+                 * PROCESSENTRY32 contains 9 fields that will change with
+                 * each entry.  Consider each field a source of 1 byte of
+                 * entropy.
+                 */
+                p.dwSize = sizeof(PROCESSENTRY32);
+
+                if (good)
+                    starttime = GetTickCount();
+                if (process_first(handle, &p))
+                    do
+                        RAND_add(&p, p.dwSize, 9);
+                    while (process_next(handle, &p)
+                           && (!good
+                               || (GetTickCount() - starttime) < MAXDELAY));
+
+                /* thread walking */
+                /*
+                 * THREADENTRY32 contains 6 fields that will change with each
+                 * entry.  Consider each field a source of 1 byte of entropy.
+                 */
+                t.dwSize = sizeof(THREADENTRY32);
+                if (good)
+                    starttime = GetTickCount();
+                if (thread_first(handle, &t))
+                    do
+                        RAND_add(&t, t.dwSize, 6);
+                    while (thread_next(handle, &t)
+                           && (!good
+                               || (GetTickCount() - starttime) < MAXDELAY));
+
+                /* module walking */
+                /*
+                 * MODULEENTRY32 contains 9 fields that will change with each
+                 * entry.  Consider each field a source of 1 byte of entropy.
+                 */
+                m.dwSize = sizeof(MODULEENTRY32);
+                if (good)
+                    starttime = GetTickCount();
+                if (module_first(handle, &m))
+                    do
+                        RAND_add(&m, m.dwSize, 9);
+                    while (module_next(handle, &m)
+                           && (!good
+                               || (GetTickCount() - starttime) < MAXDELAY));
+                if (close_snap)
+                    close_snap(handle);
+                else
+                    CloseHandle(handle);
+
+            }
+
+            FreeLibrary(kernel);
+        }
+    }
+# endif                         /* !OPENSSL_SYS_WINCE */
+
+    /* timer data */
+    readtimer();
+
+    /* memory usage statistics */
+    GlobalMemoryStatus(&m);
+    RAND_add(&m, sizeof(m), 1);
+
+    /* process ID */
+    w = GetCurrentProcessId();
+    RAND_add(&w, sizeof(w), 1);
+
+# if 0
+    printf("Exiting RAND_poll\n");
+# endif
+
+    return (1);
+}
 
-void RAND_screen(void) /* function available for backward compatibility */
+int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
 {
-       RAND_poll();
-       readscreen();
+    double add_entropy = 0;
+
+    switch (iMsg) {
+    case WM_KEYDOWN:
+        {
+            static WPARAM key;
+            if (key != wParam)
+                add_entropy = 0.05;
+            key = wParam;
+        }
+        break;
+    case WM_MOUSEMOVE:
+        {
+            static int lastx, lasty, lastdx, lastdy;
+            int x, y, dx, dy;
+
+            x = LOWORD(lParam);
+            y = HIWORD(lParam);
+            dx = lastx - x;
+            dy = lasty - y;
+            if (dx != 0 && dy != 0 && dx - lastdx != 0 && dy - lastdy != 0)
+                add_entropy = .2;
+            lastx = x, lasty = y;
+            lastdx = dx, lastdy = dy;
+        }
+        break;
+    }
+
+    readtimer();
+    RAND_add(&iMsg, sizeof(iMsg), add_entropy);
+    RAND_add(&wParam, sizeof(wParam), 0);
+    RAND_add(&lParam, sizeof(lParam), 0);
+
+    return (RAND_status());
 }
 
+void RAND_screen(void)
+{                               /* function available for backward
+                                 * compatibility */
+    RAND_poll();
+    readscreen();
+}
 
 /* feed timing information to the PRNG */
 static void readtimer(void)
 {
-       DWORD w;
-       LARGE_INTEGER l;
-       static int have_perfc = 1;
-#if defined(_MSC_VER) && !defined(OPENSSL_SYS_WINCE)
-       static int have_tsc = 1;
-       DWORD cyclecount;
-
-       if (have_tsc) {
-         __try {
-           __asm {
-             _emit 0x0f
-             _emit 0x31
-             mov cyclecount, eax
-             }
-           RAND_add(&cyclecount, sizeof(cyclecount), 1);
-         } __except(EXCEPTION_EXECUTE_HANDLER) {
-           have_tsc = 0;
-         }
-       }
-#else
-# define have_tsc 0
-#endif
-
-       if (have_perfc) {
-         if (QueryPerformanceCounter(&l) == 0)
-           have_perfc = 0;
-         else
-           RAND_add(&l, sizeof(l), 0);
-       }
-
-       if (!have_tsc && !have_perfc) {
-         w = GetTickCount();
-         RAND_add(&w, sizeof(w), 0);
-       }
+    DWORD w;
+    LARGE_INTEGER l;
+    static int have_perfc = 1;
+# if defined(_MSC_VER) && defined(_M_X86)
+    static int have_tsc = 1;
+    DWORD cyclecount;
+
+    if (have_tsc) {
+        __try {
+            __asm {
+            _emit 0x0f _emit 0x31 mov cyclecount, eax}
+            RAND_add(&cyclecount, sizeof(cyclecount), 1);
+        }
+        __except(EXCEPTION_EXECUTE_HANDLER) {
+            have_tsc = 0;
+        }
+    }
+# else
+#  define have_tsc 0
+# endif
+
+    if (have_perfc) {
+        if (QueryPerformanceCounter(&l) == 0)
+            have_perfc = 0;
+        else
+            RAND_add(&l, sizeof(l), 0);
+    }
+
+    if (!have_tsc && !have_perfc) {
+        w = GetTickCount();
+        RAND_add(&w, sizeof(w), 0);
+    }
 }
 
 /* feed screen contents to PRNG */
@@ -660,68 +682,70 @@ static void readtimer(void)
 
 static void readscreen(void)
 {
-#ifndef OPENSSL_SYS_WINCE
-  HDC          hScrDC;         /* screen DC */
-  HDC          hMemDC;         /* memory DC */
-  HBITMAP      hBitmap;        /* handle for our bitmap */
-  HBITMAP      hOldBitmap;     /* handle for previous bitmap */
-  BITMAP       bm;             /* bitmap properties */
-  unsigned int size;           /* size of bitmap */
-  char         *bmbits;        /* contents of bitmap */
-  int          w;              /* screen width */
-  int          h;              /* screen height */
-  int          y;              /* y-coordinate of screen lines to grab */
-  int          n = 16;         /* number of screen lines to grab at a time */
-
-  /* Create a screen DC and a memory DC compatible to screen DC */
-  hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
-  hMemDC = CreateCompatibleDC(hScrDC);
-
-  /* Get screen resolution */
-  w = GetDeviceCaps(hScrDC, HORZRES);
-  h = GetDeviceCaps(hScrDC, VERTRES);
-
-  /* Create a bitmap compatible with the screen DC */
-  hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
-
-  /* Select new bitmap into memory DC */
-  hOldBitmap = SelectObject(hMemDC, hBitmap);
-
-  /* Get bitmap properties */
-  GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
-  size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
-
-  bmbits = OPENSSL_malloc(size);
-  if (bmbits) {
-    /* Now go through the whole screen, repeatedly grabbing n lines */
-    for (y = 0; y < h-n; y += n)
-       {
-       unsigned char md[MD_DIGEST_LENGTH];
-
-       /* Bitblt screen DC to memory DC */
-       BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
-
-       /* Copy bitmap bits from memory DC to bmbits */
-       GetBitmapBits(hBitmap, size, bmbits);
-
-       /* Get the hash of the bitmap */
-       MD(bmbits,size,md);
-
-       /* Seed the random generator with the hash value */
-       RAND_add(md, MD_DIGEST_LENGTH, 0);
-       }
-
-    OPENSSL_free(bmbits);
-  }
-
-  /* Select old bitmap back into memory DC */
-  hBitmap = SelectObject(hMemDC, hOldBitmap);
-
-  /* Clean up */
-  DeleteObject(hBitmap);
-  DeleteDC(hMemDC);
-  DeleteDC(hScrDC);
-#endif /* !OPENSSL_SYS_WINCE */
+# if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN)
+    HDC hScrDC;                 /* screen DC */
+    HDC hMemDC;                 /* memory DC */
+    HBITMAP hBitmap;            /* handle for our bitmap */
+    HBITMAP hOldBitmap;         /* handle for previous bitmap */
+    BITMAP bm;                  /* bitmap properties */
+    unsigned int size;          /* size of bitmap */
+    char *bmbits;               /* contents of bitmap */
+    int w;                      /* screen width */
+    int h;                      /* screen height */
+    int y;                      /* y-coordinate of screen lines to grab */
+    int n = 16;                 /* number of screen lines to grab at a time */
+
+    if (check_winnt() && OPENSSL_isservice() > 0)
+        return;
+
+    /* Create a screen DC and a memory DC compatible to screen DC */
+    hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
+    hMemDC = CreateCompatibleDC(hScrDC);
+
+    /* Get screen resolution */
+    w = GetDeviceCaps(hScrDC, HORZRES);
+    h = GetDeviceCaps(hScrDC, VERTRES);
+
+    /* Create a bitmap compatible with the screen DC */
+    hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
+
+    /* Select new bitmap into memory DC */
+    hOldBitmap = SelectObject(hMemDC, hBitmap);
+
+    /* Get bitmap properties */
+    GetObject(hBitmap, sizeof(BITMAP), (LPSTR) & bm);
+    size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
+
+    bmbits = OPENSSL_malloc(size);
+    if (bmbits) {
+        /* Now go through the whole screen, repeatedly grabbing n lines */
+        for (y = 0; y < h - n; y += n) {
+            unsigned char md[MD_DIGEST_LENGTH];
+
+            /* Bitblt screen DC to memory DC */
+            BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
+
+            /* Copy bitmap bits from memory DC to bmbits */
+            GetBitmapBits(hBitmap, size, bmbits);
+
+            /* Get the hash of the bitmap */
+            MD(bmbits, size, md);
+
+            /* Seed the random generator with the hash value */
+            RAND_add(md, MD_DIGEST_LENGTH, 0);
+        }
+
+        OPENSSL_free(bmbits);
+    }
+
+    /* Select old bitmap back into memory DC */
+    hBitmap = SelectObject(hMemDC, hOldBitmap);
+
+    /* Clean up */
+    DeleteObject(hBitmap);
+    DeleteDC(hMemDC);
+    DeleteDC(hScrDC);
+# endif                         /* !OPENSSL_SYS_WINCE */
 }
 
 #endif