Disable the net statistics gathering code, since different compilers
[openssl.git] / crypto / rand / rand_win.c
index 017ce2a9fce003b14f128e59e9a94b23a22599cd..2a4f76781305036e847ca96217abc211b0a79656 100644 (file)
 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 *);
@@ -147,6 +169,16 @@ 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 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;
@@ -155,15 +187,83 @@ int RAND_poll(void)
        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)
                {
@@ -205,6 +305,9 @@ int RAND_poll(void)
                        }
                }
 
+        if (advapi)
+               FreeLibrary(advapi);
+
        /* timer data */
        readtimer();
        
@@ -233,11 +336,28 @@ int RAND_poll(void)
                        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(buf);
-                       RAND_add(buf, sizeof(buf), 0);
+                       CURSORINFO ci;
+                       ci.cbSize = sizeof(CURSORINFO);
+                       if (cursor(&ci))
+                               RAND_add(&ci, ci.cbSize, 0);
                        }
 
                if (queue)
@@ -246,15 +366,18 @@ int RAND_poll(void)
                        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,
-        * http://www.cs.auckland.ac.nz/~pgut001/pubs/random2.pdf
+        * 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.)
@@ -307,10 +430,14 @@ int RAND_poll(void)
                                        if (heap_first(&hentry,
                                                hlist.th32ProcessID,
                                                hlist.th32HeapID))
+                                               {
+                                               int entrycnt = 50;
                                                do
                                                        RAND_add(&hentry,
                                                                hentry.dwSize, 0);
-                                               while (heap_next(&hentry));
+                                               while (heap_next(&hentry)
+                                                       && --entrycnt > 0);
+                                               }
                                        } while (heaplist_next(handle,
                                                &hlist));
 
@@ -337,6 +464,8 @@ int RAND_poll(void)
                        
                        CloseHandle(handle);
                        }
+
+               FreeLibrary(kernel);
                }
 
 #ifdef DEBUG