summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/syscalls.cc
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2010-12-31 22:34:05 +0100
committerAdam Borowski <kilobyte@angband.pl>2010-12-31 22:38:32 +0100
commit36d5f39f50a77da3c7bd2b4fddeb498ee26abd9e (patch)
tree01c7897872b170eeddecc78a9c6e8811e58c0c73 /crawl-ref/source/syscalls.cc
parent0980a63ef14ad60078493d2e909b2ec1e142f326 (diff)
downloadcrawl-ref-36d5f39f50a77da3c7bd2b4fddeb498ee26abd9e.tar.gz
crawl-ref-36d5f39f50a77da3c7bd2b4fddeb498ee26abd9e.zip
Use the Windows equivalent of /dev/urandom there.
Without it, starting Crawl twice in the same second produced identical seeds. It doesn't matter for real games (no DGL on Windows...), but can be surprising when doing automated tests or playing with layout generators.
Diffstat (limited to 'crawl-ref/source/syscalls.cc')
-rw-r--r--crawl-ref/source/syscalls.cc41
1 files changed, 41 insertions, 0 deletions
diff --git a/crawl-ref/source/syscalls.cc b/crawl-ref/source/syscalls.cc
index 61d4b56876..f80dedb076 100644
--- a/crawl-ref/source/syscalls.cc
+++ b/crawl-ref/source/syscalls.cc
@@ -13,6 +13,8 @@
// charset handling comes).
#undef rename
+#include <windows.h>
+#include <wincrypt.h>
#include <io.h>
#else
#include <unistd.h>
@@ -58,6 +60,45 @@ bool unlock_file(int fd)
#endif
}
+bool read_urandom(char *buf, int len)
+{
+#ifdef TARGET_OS_WINDOWS
+ HCRYPTPROV hProvider = 0;
+
+ if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ {
+ return false;
+ }
+
+ if (!CryptGenRandom(hProvider, len, (BYTE*)buf))
+ {
+ CryptReleaseContext(hProvider, 0);
+ return false;
+ }
+
+ CryptReleaseContext(hProvider, 0);
+ return true;
+#else
+ /* Try opening from various system provided (hopefully) CSPRNGs */
+ FILE* seed_f = fopen("/dev/urandom", "rb");
+ if (!seed_f)
+ seed_f = fopen("/dev/random", "rb");
+ if (!seed_f)
+ seed_f = fopen("/dev/srandom", "rb");
+ if (!seed_f)
+ seed_f = fopen("/dev/arandom", "rb");
+ if (seed_f)
+ {
+ int res = fread(buf, 1, len, seed_f);
+ fclose(seed_f);
+ return (res == len);
+ }
+
+ return false;
+#endif
+}
+
#ifdef TARGET_OS_WINDOWS
# ifndef UNIX
// implementation by Richard W.M. Jones