static void readtimer(void);
static void readscreen(void);
-/* It appears like PCURSORINFO is only defined when WINVER is 0x0500 and up,
- which currently only happens on Win2000. Unfortunately, that is a typedef,
- so it's 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 PCURSORINFO. */
+/* 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
-typedef void *PCURSORINFO;
-#endif
+/*
+ * 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 *THREAD32)(HANDLE, LPTHREADENTRY32);
typedef BOOL (WINAPI *MODULE32)(HANDLE, LPMODULEENTRY32);
+#include <lmcons.h>
+#include <lmstats.h>
+#if 0 /* Some compilers use LMSTR, others (VC6, for example) use LPTSTR.
+ * This part is disabled until a fix is found.
+ */
+typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET)
+ (LMSTR, LMSTR, DWORD, DWORD, LPBYTE*);
+typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE);
+#endif
+
int RAND_poll(void)
{
MEMORYSTATUS m;
DWORD w;
HWND h;
- HMODULE advapi, kernel, user;
- CRYPTACQUIRECONTEXT acquire;
- CRYPTGENRANDOM gen;
- CRYPTRELEASECONTEXT release;
+ HMODULE advapi, kernel, user, netapi;
+ CRYPTACQUIRECONTEXT acquire = 0;
+ CRYPTGENRANDOM gen = 0;
+ CRYPTRELEASECONTEXT release = 0;
+#if 0 /* This part is disabled until a fix for the problem with the
+ * definition of NETSTATGET is found.
+ */
+ NETSTATGET netstatget = 0;
+ NETFREE netfree = 0;
+#endif
/* load functions dynamically - not available on all systems */
- advapi = GetModuleHandle("ADVAPI32.DLL");
- kernel = GetModuleHandle("KERNEL32.DLL");
- user = GetModuleHandle("USER32.DLL");
+ advapi = LoadLibrary("ADVAPI32.DLL");
+ kernel = LoadLibrary("KERNEL32.DLL");
+ user = LoadLibrary("USER32.DLL");
+ netapi = LoadLibrary("NETAPI32.DLL");
+
+#if 0 /* This part is disabled until a fix for the problem with the
+ * definition of NETSTATGET is found. Also, note that VC6 doesn't
+ * understand strings starting with L".
+ */
+ 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);
+ }
+ }
+
+ if (netapi)
+ FreeLibrary(netapi);
+#endif
+
+ /* 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)
{
}
}
+ if (advapi)
+ FreeLibrary(advapi);
+
/* timer data */
readtimer();
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.
+ */
+ OSVERSIONINFO osverinfo ;
+ osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
+ GetVersionEx( &osverinfo ) ;
+
+ if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+ osverinfo.dwMajorVersion < 5)
+ cursor = 0;
+ }
+
if (cursor)
{
/* cursor position */
- cursor((PCURSORINFO)buf);
- RAND_add(buf, sizeof(buf), 0);
+ CURSORINFO ci;
+ ci.cbSize = sizeof(CURSORINFO);
+ if (cursor(&ci))
+ RAND_add(&ci, ci.cbSize, 0);
}
if (queue)
w = queue(QS_ALLEVENTS);
RAND_add(&w, sizeof(w), 0);
}
+
+ FreeLibrary(user);
}
/* Toolhelp32 snapshot: enumerate processes, threads, modules and heap
* http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm
- * (Win 9x only, not available on NT)
+ * (Win 9x and 2000 only, not available on NT)
*
* This seeding method was proposed in Peter Gutmann, Software
* Generation of Practically Strong Random Numbers,
CloseHandle(handle);
}
+
+ FreeLibrary(kernel);
}
#ifdef DEBUG
/* feed timing information to the PRNG */
static void readtimer(void)
{
- DWORD w, cyclecount;
+ DWORD w;
LARGE_INTEGER l;
static int have_perfc = 1;
#ifndef __GNUC__
static int have_tsc = 1;
+ DWORD cyclecount;
if (have_tsc) {
__try {