Juan Lang : rpcrt4: Implement UuidCreateSequential using the machine' s MAC address, when available.

Alexandre Julliard julliard at winehq.org
Thu Mar 4 11:21:41 CST 2010


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

Author: Juan Lang <juan.lang at gmail.com>
Date:   Wed Mar  3 14:37:40 2010 -0800

rpcrt4: Implement UuidCreateSequential using the machine's MAC address, when available.

---

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

diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in
index fda374c..ce50b36 100644
--- a/dlls/rpcrt4/Makefile.in
+++ b/dlls/rpcrt4/Makefile.in
@@ -6,7 +6,7 @@ VPATH     = @srcdir@
 MODULE    = rpcrt4.dll
 IMPORTLIB = rpcrt4
 IMPORTS   = uuid advapi32 kernel32 ntdll
-DELAYIMPORTS = wininet secur32 user32
+DELAYIMPORTS = iphlpapi wininet secur32 user32
 EXTRALIBS = @SOCKETLIBS@
 
 C_SRCS = \
diff --git a/dlls/rpcrt4/rpcrt4_main.c b/dlls/rpcrt4/rpcrt4_main.c
index a790ccb..344b6d0 100644
--- a/dlls/rpcrt4/rpcrt4_main.c
+++ b/dlls/rpcrt4/rpcrt4_main.c
@@ -44,6 +44,8 @@
 #include "winnt.h"
 #include "winternl.h"
 #include "ntsecapi.h"
+#include "iptypes.h"
+#include "iphlpapi.h"
 #include "wine/unicode.h"
 #include "rpc.h"
 
@@ -60,6 +62,15 @@ 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 =
 {
@@ -305,6 +316,58 @@ RPC_STATUS WINAPI UuidCreate(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 {
+        RtlGenRandom(address, ADDRESS_BYTES_NEEDED);
+        address[0] |= 0x01;
+        status = RPC_S_UUID_LOCAL_ONLY;
+    }
+
+    HeapFree(GetProcessHeap(), 0, adapter);
+    return status;
+}
+
 /*************************************************************************
  *           UuidCreateSequential   [RPCRT4.@]
  *
@@ -315,10 +378,77 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
  *  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.
  */
 RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid)
 {
-   return UuidCreate(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;
+    memcpy(&Uuid->Data4[2], address, ADDRESS_BYTES_NEEDED);
+
+    LeaveCriticalSection(&uuid_cs);
+
+    TRACE("%s\n", debugstr_guid(Uuid));
+
+    return status;
 }
 
 
diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c
index 7bd78ba..bb480e1 100644
--- a/dlls/rpcrt4/tests/rpc.c
+++ b/dlls/rpcrt4/tests/rpc.c
@@ -820,7 +820,6 @@ static void test_UuidCreateSequential(void)
     ok(!ret || ret == RPC_S_UUID_LOCAL_ONLY,
        "expected RPC_S_OK or RPC_S_UUID_LOCAL_ONLY, got %08x\n", ret);
     version = (guid1.Data3 & 0xf000) >> 12;
-    todo_wine
     ok(version == 1, "unexpected version %d\n", version);
     if (version == 1)
     {
@@ -849,7 +848,6 @@ static void test_UuidCreateSequential(void)
         ok(!ret || ret == RPC_S_UUID_LOCAL_ONLY,
            "expected RPC_S_OK or RPC_S_UUID_LOCAL_ONLY, got %08x\n", ret);
         version = (guid2.Data3 & 0xf000) >> 12;
-        todo_wine
         ok(version == 1, "unexpected version %d\n", version);
         ok(!memcmp(guid1.Data4, guid2.Data4, sizeof(guid2.Data4)),
            "unexpected value in MAC address\n");




More information about the wine-cvs mailing list