From edb181c377b88e7b87fe3efeb1eed10d1ed87eb7 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 12 Aug 2022 13:49:22 +0200 Subject: [PATCH] Lazy-link to `bcrypt` Let's not make `bcrypt.dl` a link-time bound library. Instead, load the `BCryptGenRandom()` function dynamically. When needed. If needed. This helps reduce the start-up cost of any mimalloc user because the time spent on loading dynamic libraries is non-negligible. Note: In contrast to how `os.c` loads libraries and obtains function addresses, we cannot call `FreeLibrary(hDll)` here because that would unload the `bcrypt` library before we want to use it. Signed-off-by: Johannes Schindelin --- src/random.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/random.c b/src/random.c index bf7e5b83..7e0bdd9f 100644 --- a/src/random.c +++ b/src/random.c @@ -187,10 +187,27 @@ static bool os_random_buf(void* buf, size_t buf_len) { return (RtlGenRandom(buf, (ULONG)buf_len) != 0); } #else -#pragma comment (lib,"bcrypt.lib") -#include + +#ifndef BCRYPT_USE_SYSTEM_PREFERRED_RNG +#define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002 +#endif + +typedef LONG (NTAPI *PBCryptGenRandom)(HANDLE, PUCHAR, ULONG, ULONG); +static PBCryptGenRandom pBCryptGenRandom = NULL; +static int BCryptGenRandom_is_initialized = 0; + static bool os_random_buf(void* buf, size_t buf_len) { - return (BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)buf_len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0); + if (!BCryptGenRandom_is_initialized) { + HINSTANCE hDll; + hDll = LoadLibrary(TEXT("bcrypt.dll")); + if (hDll != NULL) { + pBCryptGenRandom = (PBCryptGenRandom)(void (*)(void))GetProcAddress(hDll, "BCryptGenRandom"); + } + BCryptGenRandom_is_initialized = 1; + } + if (!pBCryptGenRandom) + return 0; + return (pBCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)buf_len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0); } #endif