diff options
author | Adam Borowski <kilobyte@angband.pl> | 2010-12-31 22:34:05 +0100 |
---|---|---|
committer | Adam Borowski <kilobyte@angband.pl> | 2010-12-31 22:38:32 +0100 |
commit | 36d5f39f50a77da3c7bd2b4fddeb498ee26abd9e (patch) | |
tree | 01c7897872b170eeddecc78a9c6e8811e58c0c73 /crawl-ref/source/syscalls.cc | |
parent | 0980a63ef14ad60078493d2e909b2ec1e142f326 (diff) | |
download | crawl-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.cc | 41 |
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 |