> Date: Wed, 11 Feb 2015 00:15:32 +0100 > From: Gisle Vanem <[email protected]> > > > Do we still want to support the older Windows NT4 and 9X versions? If > > so, we should try loading Rpcrt4.dll dynamically, with LoadLibrary, > > and if that fails, fall back on the current code. > > Seems this issue is dangling in loose air. It should be fixed > IMHO. > > Eli, do have any code for a dynamic load of "Rpcrt4.dll"?
The patch I suggest is below. It uses the fallback method if Rpcrt4.dll cannot be loaded, or if the functions from that DLL fail for some reason. 2015-02-14 Eli Zaretskii <[email protected]> Gisle Vanem <[email protected]> * 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~2 2015-02-14 11:57:50.242875000 +0200 +++ src/warc.c 2015-02-14 12:52:32.656250000 +0200 @@ -60,6 +60,7 @@ as that of the covered work. */ #ifdef WINDOWS /* we need this on Windows to have O_TEMPORARY defined */ # include <fcntl.h> +# include <rpc.h> #endif #include "warc.h" @@ -623,6 +624,59 @@ warc_uuid_str (char *urn_str) sprintf (urn_str, "<urn:uuid:%s>", 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; + } + } + + 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, "<urn:uuid:%s>", 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.) @@ -638,6 +692,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);
