From 33c5d979ce47943d931bd75bdbb6fc019d4c6e1d Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 23 Feb 2015 23:32:33 +0100 Subject: [PATCH] warc.c: native uuid generation on Windows * warc.c (windows_uuid_str) [WINDOWS]: New function specific to MS-Windows. (warc_uuid_str) [WINDOWS]: If windows_uuid_str succeeds, use its result; otherwise use the fallback method. --- src/warc.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/warc.c b/src/warc.c index 5ae21a51..55884e0b 100644 --- a/src/warc.c +++ b/src/warc.c @@ -60,7 +60,8 @@ as that of the covered work. */ #ifdef WINDOWS /* we need this on Windows to have O_TEMPORARY defined */ -#include +# include +# include #endif #ifndef O_TEMPORARY @@ -632,6 +633,61 @@ warc_uuid_str (char *urn_str) xfree (uuid_str); } #else +# ifdef WINDOWS + +typedef RPC_STATUS (RPC_ENTRY * UuidCreate_proc) (UUID *); +typedef RPC_STATUS (RPC_ENTRY * UuidToString_proc) (UUID *, unsigned char **); +typedef RPC_STATUS (RPC_ENTRY * RpcStringFree_proc) (unsigned char **); + +static int +windows_uuid_str (char *urn_str) +{ + static UuidCreate_proc pfn_UuidCreate = NULL; + static UuidToString_proc pfn_UuidToString = NULL; + static RpcStringFree_proc pfn_RpcStringFree = NULL; + static int rpc_uuid_avail = -1; + + /* Rpcrt4.dll is not available on older versions of Windows, so we + need to test its availability at run time. */ + if (rpc_uuid_avail == -1) + { + HMODULE hm_rpcrt4 = LoadLibrary ("Rpcrt4.dll"); + + if (hm_rpcrt4) + { + pfn_UuidCreate = + (UuidCreate_proc) GetProcAddress (hm_rpcrt4, "UuidCreate"); + pfn_UuidToString = + (UuidToString_proc) GetProcAddress (hm_rpcrt4, "UuidToStringA"); + pfn_RpcStringFree = + (RpcStringFree_proc) GetProcAddress (hm_rpcrt4, "RpcStringFreeA"); + if (pfn_UuidCreate && pfn_UuidToString && pfn_RpcStringFree) + rpc_uuid_avail = 1; + else + rpc_uuid_avail = 0; + } + else + rpc_uuid_avail = 0; + } + + if (rpc_uuid_avail) + { + BYTE *uuid_str; + UUID uuid; + + if (pfn_UuidCreate (&uuid) == RPC_S_OK) + { + if (pfn_UuidToString (&uuid, &uuid_str) == RPC_S_OK) + { + sprintf (urn_str, "", uuid_str); + pfn_RpcStringFree (&uuid_str); + return 1; + } + } + } + return 0; +} +#endif /* Fills urn_str with a UUID based on random numbers in the format required for the WARC-Record-Id header. (See RFC 4122, UUID version 4.) @@ -647,6 +703,14 @@ warc_uuid_str (char *urn_str) unsigned char uuid_data[16]; int i; + +#ifdef WINDOWS + /* If the native method fails (expected on older Windows versions), + use the fallback below. */ + if (windows_uuid_str (urn_str)) + return; +#endif + for (i=0; i<16; i++) uuid_data[i] = random_number (255);