+#include <wincrypt.h>
+#include <tlhelp32.h>
+
+/* 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 "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. */
+
+#ifndef CURSOR_SHOWING
+/*
+ * Information about the global cursor.
+ */
+typedef struct tagCURSORINFO
+{
+ DWORD cbSize;
+ DWORD flags;
+ HCURSOR hCursor;
+ 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 *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>
+#include <lmstats.h>
+typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET)
+ (LMSTR, LMSTR, DWORD, DWORD, LPBYTE*);
+typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE);
+
+int RAND_poll(void)
+{
+ MEMORYSTATUS m;
+ HCRYPTPROV hProvider = 0;
+ BYTE buf[64];
+ DWORD w;
+ HWND h;
+
+ HMODULE advapi, kernel, user, netapi;
+ CRYPTACQUIRECONTEXT acquire;
+ CRYPTGENRANDOM gen;
+ CRYPTRELEASECONTEXT release;
+ NETSTATGET netstatget;
+ NETFREE netfree;
+
+ /* load functions dynamically - not available on all systems */
+ advapi = GetModuleHandle("ADVAPI32.DLL");
+ kernel = GetModuleHandle("KERNEL32.DLL");
+ user = GetModuleHandle("USER32.DLL");
+ netapi = GetModuleHandle("NETAPI32.DLL");
+
+ if (netapi)
+ {
+ netstatget = (NETSTATGET) GetProcAddress(netapi,"NetStatisticsGet");
+ netfree = (NETFREE) GetProcAddress(netapi,"NetApiBufferFree");
+ }
+
+ if (netstatget && netfree)
+ {
+ LPBYTE outbuf;
+ /* NetStatisticsGet() is a Unicode only function */
+ if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0)
+ {
+ RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 0);
+ netfree(outbuf);
+ }
+ if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0)
+ {
+ RAND_add(outbuf, sizeof(STAT_SERVER_0), 0);
+ netfree(outbuf);
+ }
+ }
+
+ /* 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, "Global",
+ NULL, NULL, buf, &length);
+ }
+ if (rc == ERROR_SUCCESS)
+ {
+ RAND_add(&length, sizeof(length), 0);
+ RAND_add(buf, length, 0);
+ }
+ if ( buf )
+ free(buf);
+ }
+
+ if (advapi)
+ {
+ acquire = (CRYPTACQUIRECONTEXT) GetProcAddress(advapi,
+ "CryptAcquireContextA");
+ gen = (CRYPTGENRANDOM) GetProcAddress(advapi,
+ "CryptGenRandom");
+ release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi,
+ "CryptReleaseContext");
+ }
+
+ if (acquire && gen && release)
+ {
+ /* poll the CryptoAPI PRNG */
+ if (acquire(&hProvider, 0, 0, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ {
+ if (gen(hProvider, sizeof(buf), buf) != 0)
+ {
+ RAND_add(buf, sizeof(buf), 0);
+#ifdef DEBUG
+ 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), 0);
+#ifdef DEBUG
+ printf("randomness from PROV_INTEL_SEC\n");