Juan Lang : rpcrt4: Use pseudo-random numbers to generate UUIDs rather than using the (old, deprecated) MAC-address-and-time generation algorithm.

Alexandre Julliard julliard at winehq.org
Thu Jan 22 08:41:50 CST 2009


Module: wine
Branch: master
Commit: 5e5b53666c852fd4f29a893cef3f0aeb53690a1e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5e5b53666c852fd4f29a893cef3f0aeb53690a1e

Author: Juan Lang <juan.lang at gmail.com>
Date:   Wed Jan 21 10:39:46 2009 -0800

rpcrt4: Use pseudo-random numbers to generate UUIDs rather than using the (old, deprecated) MAC-address-and-time generation algorithm.

---

 dlls/rpcrt4/Makefile.in   |    2 +-
 dlls/rpcrt4/rpcrt4_main.c |  152 +++++----------------------------------------
 dlls/rpcrt4/tests/rpc.c   |    2 -
 3 files changed, 16 insertions(+), 140 deletions(-)

diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in
index 14ee4a3..b44bfb0 100644
--- a/dlls/rpcrt4/Makefile.in
+++ b/dlls/rpcrt4/Makefile.in
@@ -5,7 +5,7 @@ SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = rpcrt4.dll
 IMPORTLIB = rpcrt4
-IMPORTS   = uuid iphlpapi advapi32 kernel32 ntdll
+IMPORTS   = uuid advapi32 kernel32 ntdll
 DELAYIMPORTS = secur32 user32
 
 C_SRCS = \
diff --git a/dlls/rpcrt4/rpcrt4_main.c b/dlls/rpcrt4/rpcrt4_main.c
index 1a6b61d..f1a966f 100644
--- a/dlls/rpcrt4/rpcrt4_main.c
+++ b/dlls/rpcrt4/rpcrt4_main.c
@@ -43,8 +43,7 @@
 #include "winuser.h"
 #include "winnt.h"
 #include "winternl.h"
-#include "iptypes.h"
-#include "iphlpapi.h"
+#include "ntsecapi.h"
 #include "wine/unicode.h"
 #include "rpc.h"
 
@@ -60,15 +59,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(rpc);
 
 static UUID uuid_nil;
 
-static CRITICAL_SECTION uuid_cs;
-static CRITICAL_SECTION_DEBUG critsect_debug =
-{
-    0, 0, &uuid_cs,
-    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
-      0, 0, { (DWORD_PTR)(__FILE__ ": uuid_cs") }
-};
-static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
-
 static CRITICAL_SECTION threaddata_cs;
 static CRITICAL_SECTION_DEBUG threaddata_cs_debug =
 {
@@ -280,61 +270,6 @@ RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
   return RPC_S_OK;
 }
 
-/* Number of 100ns ticks per clock tick. To be safe, assume that the clock
-   resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */
-#define TICKS_PER_CLOCK_TICK 1000
-#define SECSPERDAY  86400
-#define TICKSPERSEC 10000000
-/* UUID system time starts at October 15, 1582 */
-#define SECS_15_OCT_1582_TO_1601  ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
-#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)
-
-static void RPC_UuidGetSystemTime(ULONGLONG *time)
-{
-    FILETIME ft;
-
-    GetSystemTimeAsFileTime(&ft);
-
-    *time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
-    *time += TICKS_15_OCT_1582_TO_1601;
-}
-
-/* Assume that a hardware address is at least 6 bytes long */ 
-#define ADDRESS_BYTES_NEEDED 6
-
-static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
-{
-    int i;
-    DWORD status = RPC_S_OK;
-
-    ULONG buflen = sizeof(IP_ADAPTER_INFO);
-    PIP_ADAPTER_INFO adapter = HeapAlloc(GetProcessHeap(), 0, buflen);
-
-    if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) {
-        HeapFree(GetProcessHeap(), 0, adapter);
-        adapter = HeapAlloc(GetProcessHeap(), 0, buflen);
-    }
-
-    if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) {
-        for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) {
-            address[i] = adapter->Address[i];
-        }
-    }
-    /* We can't get a hardware address, just use random numbers.
-       Set the multicast bit to prevent conflicts with real cards. */
-    else {
-        for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) {
-            address[i] = rand() & 0xff;
-        }
-
-        address[0] |= 0x01;
-        status = RPC_S_UUID_LOCAL_ONLY;
-    }
-
-    HeapFree(GetProcessHeap(), 0, adapter);
-    return status;
-}
-
 /*************************************************************************
  *           UuidCreate   [RPCRT4.@]
  *
@@ -345,83 +280,26 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
  *  RPC_S_OK if successful.
  *  RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
  *
- *  FIXME: No compensation for changes across reloading
- *         this dll or across reboots (e.g. clock going 
- *         backwards and swapped network cards). The RFC
- *         suggests using NVRAM for storing persistent 
- *         values.
+ * NOTES
+ *
+ *  Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
+ *  Truly Random or Pseudo-Random Numbers)
  */
 RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
 {
-    static int initialised, count;
-
-    ULONGLONG time;
-    static ULONGLONG timelast;
-    static WORD sequence;
-
-    static DWORD status;
-    static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH];
-
-    EnterCriticalSection(&uuid_cs);
-
-    if (!initialised) {
-        RPC_UuidGetSystemTime(&timelast);
-        count = TICKS_PER_CLOCK_TICK;
-
-        sequence = ((rand() & 0xff) << 8) + (rand() & 0xff);
-        sequence &= 0x1fff;
-
-        status = RPC_UuidGetNodeAddress(address);
-        initialised = 1;
-    }
-
-    /* Generate time element of the UUID. Account for going faster
-       than our clock as well as the clock going backwards. */
-    while (1) {
-        RPC_UuidGetSystemTime(&time);
-        if (time > timelast) {
-            count = 0;
-            break;
-        }
-        if (time < timelast) {
-            sequence = (sequence + 1) & 0x1fff;
-            count = 0;
-            break;
-        }
-        if (count < TICKS_PER_CLOCK_TICK) {
-            count++;
-            break;
-        }
-    }
-
-    timelast = time;
-    time += count;
-
-    /* Pack the information into the UUID structure. */
-
-    Uuid->Data1  = (unsigned long)(time & 0xffffffff);
-    Uuid->Data2  = (unsigned short)((time >> 32) & 0xffff);
-    Uuid->Data3  = (unsigned short)((time >> 48) & 0x0fff);
-
-    /* This is a version 1 UUID */
-    Uuid->Data3 |= (1 << 12);
-
-    Uuid->Data4[0]  = sequence & 0xff;
-    Uuid->Data4[1]  = (sequence & 0x3f00) >> 8;
-    Uuid->Data4[1] |= 0x80;
-
-    Uuid->Data4[2] = address[0];
-    Uuid->Data4[3] = address[1];
-    Uuid->Data4[4] = address[2];
-    Uuid->Data4[5] = address[3];
-    Uuid->Data4[6] = address[4];
-    Uuid->Data4[7] = address[5];
-
-    LeaveCriticalSection(&uuid_cs);
+    RtlGenRandom(Uuid, sizeof(*Uuid));
+    /* Clear the version bits and set the version (4) */
+    Uuid->Data3 &= 0x0fff;
+    Uuid->Data3 |= (4 << 12);
+    /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
+     * specified in RFC 4122, section 4.4.
+     */
+    Uuid->Data4[0] &= 0x3f;
+    Uuid->Data4[0] |= 0x80;
 
     TRACE("%s\n", debugstr_guid(Uuid));
 
-    return status;
+    return RPC_S_OK;
 }
 
 /*************************************************************************
diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c
index 9ac6d27..e50dcdc 100644
--- a/dlls/rpcrt4/tests/rpc.c
+++ b/dlls/rpcrt4/tests/rpc.c
@@ -780,7 +780,6 @@ static void test_UuidCreate(void)
 
     UuidCreate(&guid);
     version = (guid.Data3 & 0xf000) >> 12;
-    todo_wine
     ok(version == 4 || broken(version == 1), "unexpected version %d\n",
        version);
     if (version == 4)
@@ -826,7 +825,6 @@ static void test_UuidCreate(void)
          * present.  Just check that Data4[0]'s most significant bits are
          * set as expected.
          */
-        todo_wine
         ok((guid.Data4[0] & 0xc0) == 0x80,
            "unexpected value in Data4[0]: %02x\n", guid.Data4[0] & 0xc0);
     }




More information about the wine-cvs mailing list