Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -81,10 +81,14 @@ extern struct Stret OFForward_stret(id, SEL, ...); #else # define OFForward OFMethodNotFound # define OFForward_stret OFMethodNotFound_stret #endif + +#ifdef OF_WINDOWS +BOOLEAN (*RtlGenRandomFuncPtr)(PVOID, ULONG); +#endif struct PreIvars { #ifdef OF_MSDOS ptrdiff_t offset; #endif @@ -190,15 +194,27 @@ free((void *)((uintptr_t)ptr - offset)); } #endif -#if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_GETRANDOM) +#if (!defined(HAVE_ARC4RANDOM) && !defined(HAVE_GETRANDOM)) || \ + defined(OF_WINDOWS) +static OFOnceControl randomOnceControl = OFOnceControlInitValue; + static void initRandom(void) { struct timeval tv; + +# ifdef OF_WINDOWS + HANDLE handle; + + if ((handle = GetModuleHandleA("advapi32.dll")) != NULL && + (RtlGenRandomFuncPtr = (BOOLEAN (*)(PVOID, ULONG)) + GetProcAddress(handle, "SystemFunction036")) != NULL) + return; +# endif # ifdef HAVE_RANDOM gettimeofday(&tv, NULL); srandom((unsigned)(tv.tv_sec ^ tv.tv_usec)); # else @@ -218,12 +234,20 @@ OFEnsure(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); return buffer; #else - static OFOnceControl onceControl = OFOnceControlInitValue; - OFOnce(&onceControl, initRandom); + OFOnce(&randomOnceControl, initRandom); + +# ifdef OF_WINDOWS + if (RtlGenRandomFuncPtr != NULL) { + uint16_t buffer; + OFEnsure(RtlGenRandomFuncPtr(&buffer, sizeof(buffer))); + return buffer; + } +# endif + # ifdef HAVE_RANDOM return random() & 0xFFFF; # else return rand() & 0xFFFF; # endif @@ -240,10 +264,20 @@ OFEnsure(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); return buffer; #else +# ifdef OF_WINDOWS + OFOnce(&randomOnceControl, initRandom); + + if (RtlGenRandomFuncPtr != NULL) { + uint32_t buffer; + OFEnsure(RtlGenRandomFuncPtr(&buffer, sizeof(buffer))); + return buffer; + } +# endif + return ((uint32_t)OFRandom16() << 16) | OFRandom16(); #endif } uint64_t @@ -260,10 +294,20 @@ OFEnsure(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); return buffer; #else +# ifdef OF_WINDOWS + OFOnce(&randomOnceControl, initRandom); + + if (RtlGenRandomFuncPtr != NULL) { + uint64_t buffer; + OFEnsure(RtlGenRandomFuncPtr(&buffer, sizeof(buffer))); + return buffer; + } +# endif + return ((uint64_t)OFRandom32() << 32) | OFRandom32(); #endif } void