- // Keep it open for the duration of the program
- static File randomDevice("/dev/urandom");
- auto bytesRead = readFull(randomDevice.fd(), data, size);
+#ifdef _MSC_VER
+ static folly::once_flag flag;
+ static HCRYPTPROV cryptoProv;
+ folly::call_once(flag, [&] {
+ if (!CryptAcquireContext(
+ &cryptoProv,
+ nullptr,
+ nullptr,
+ PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT)) {
+ if (GetLastError() == NTE_BAD_KEYSET) {
+ // Mostly likely cause of this is that no key container
+ // exists yet, so try to create one.
+ PCHECK(CryptAcquireContext(
+ &cryptoProv, nullptr, nullptr, PROV_RSA_FULL, CRYPT_NEWKEYSET));
+ } else {
+ LOG(FATAL) << "Failed to acquire the default crypto context.";
+ }
+ }
+ });
+ CHECK(size <= std::numeric_limits<DWORD>::max());
+ PCHECK(CryptGenRandom(cryptoProv, (DWORD)size, (BYTE*)data));
+#else
+ // Keep the random device open for the duration of the program.
+ static int randomFd = ::open("/dev/urandom", O_RDONLY);
+ PCHECK(randomFd >= 0);
+ auto bytesRead = readFull(randomFd, data, size);