[libcxx] random_device for Windows needs more storage

I’m trying to implement random_device for Windows using the CryptGenRandom API, as in the attached non-working code.

The trouble is, I need to store a crypto handle sized 64 bits in random_device whereas it has only an int (likely less than 64 bits) private member for storage.

Is it OK to modify the private member _f type from int to uint64_t?

A uint64_t it can hold both the crypto handle on Windows and file handles on Linux.


random.cpp (1.92 KB)

In article <CANa4zJo+YND+HH3vz1Y-JymaLCjR2-QJkdLgFCWW27AYbP0YyA@mail.gmail.com>,
    Yaron Keren <yaron.keren@gmail.com> writes:

Is it OK to modify the private member __f_ type from int to uint64_t?

Wouldn't intptr_t or uintptr_t be more appropriate?

"Handles" in Windows are more likely to be pointers masquerading as an
integer for opacity purposes.

The actual data type is typedef ULONG_PTR HCRYPTPROV;
I found two conflicting descriptions in microsoft.com for ULONG_PTR:

The first http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx says it’s always 64 bits:

#if defined(_WIN64)
 typedef unsigned __int64 ULONG_PTR;
 typedef unsigned long ULONG_PTR;

There's no need for CryptGenRandom and its overhead here. RtlGenRandom is just fine for random_device. MSVCRT does the same.


Nick, I have seen RtlGenRandom, but I didn’t initally use it since Microsoft is recommending to use CryptGenRandom instead:


[The RtlGenRandom function is available for use in the operating systems specified in the Requirements section. It may be altered or unavailable in subsequent versions. Instead, use the CryptGenRandom function.]

Due to backward compatibility it’s very low chance RtlGenRandom will actually go away, I’ll use it.


I don't believe we should be using this function. Technically, the
documentation states this is available for use with the operating
systems listed in the Requirements section, which only lists XP and
Server 2003. Relying on this outside of those platforms is not only
bad form, but to boot, in order to use them, you need to dynamically
load SystemFunction036 from AdvApi32.dll.



Just found out both Visual C++ and MingW supply the rand_s() function (implemented in MSVCRT), which wraps one of the above functions in a very easy to use and version:


Microsoft own random_device uses it,


rand_s() is a much better solution. :slight_smile:


For newer SDKs, when targeting XP and up (_WIN32_WINNT >= 0x0501), ntsecapi.h defines it as a macro to SystemFunction036 so it works without any additional steps. And the documentation lists the minimum required OS version.


Did I miss something? Long is 32-bits on win32 (and on win64, which breaks a lot of code that assumes that you can round trip pointers through long, because even though the standard has never guaranteed this it's been possible on pretty much every system that isn't an IBM mainframe for decades). On Win32, long is the size of a pointer, on Win64, __int64 is the size of a pointer.


Hi David,

You are correct, I was under the wrong impression that longs are 64 bit on Win32. So indeed all references above map (with differing typdefs) HCRYPTPROV to 32 bits on Win32 and 64 bits on Win64.

In any case, I submitted a patch using rand_s() from MSVCRT.


unsigned long is always 32 bits on Microsoft’s compiler. Sebastian

Thanks, Sebastian, David Chisnall corrected me.
random_device() was finally implemented based on rand_s() from MSVCRT.