rpcrt4: Use pseudo-random numbers to generate UUIDs rather than using the (old, deprecated) MAC-address-and-time generation algorithm.
This commit is contained in:
parent
669ced3a67
commit
5e5b53666c
|
@ -5,7 +5,7 @@ SRCDIR = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
MODULE = rpcrt4.dll
|
MODULE = rpcrt4.dll
|
||||||
IMPORTLIB = rpcrt4
|
IMPORTLIB = rpcrt4
|
||||||
IMPORTS = uuid iphlpapi advapi32 kernel32 ntdll
|
IMPORTS = uuid advapi32 kernel32 ntdll
|
||||||
DELAYIMPORTS = secur32 user32
|
DELAYIMPORTS = secur32 user32
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
|
|
|
@ -43,8 +43,7 @@
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
#include "iptypes.h"
|
#include "ntsecapi.h"
|
||||||
#include "iphlpapi.h"
|
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "rpc.h"
|
#include "rpc.h"
|
||||||
|
|
||||||
|
@ -60,15 +59,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(rpc);
|
||||||
|
|
||||||
static UUID uuid_nil;
|
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 threaddata_cs;
|
||||||
static CRITICAL_SECTION_DEBUG threaddata_cs_debug =
|
static CRITICAL_SECTION_DEBUG threaddata_cs_debug =
|
||||||
{
|
{
|
||||||
|
@ -280,61 +270,6 @@ RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
|
||||||
return RPC_S_OK;
|
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.@]
|
* UuidCreate [RPCRT4.@]
|
||||||
*
|
*
|
||||||
|
@ -345,83 +280,26 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
|
||||||
* RPC_S_OK if successful.
|
* RPC_S_OK if successful.
|
||||||
* RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
|
* RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
|
||||||
*
|
*
|
||||||
* FIXME: No compensation for changes across reloading
|
* NOTES
|
||||||
* this dll or across reboots (e.g. clock going
|
*
|
||||||
* backwards and swapped network cards). The RFC
|
* Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
|
||||||
* suggests using NVRAM for storing persistent
|
* Truly Random or Pseudo-Random Numbers)
|
||||||
* values.
|
|
||||||
*/
|
*/
|
||||||
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
|
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
|
||||||
{
|
{
|
||||||
static int initialised, count;
|
RtlGenRandom(Uuid, sizeof(*Uuid));
|
||||||
|
/* Clear the version bits and set the version (4) */
|
||||||
ULONGLONG time;
|
Uuid->Data3 &= 0x0fff;
|
||||||
static ULONGLONG timelast;
|
Uuid->Data3 |= (4 << 12);
|
||||||
static WORD sequence;
|
/* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
|
||||||
|
* specified in RFC 4122, section 4.4.
|
||||||
static DWORD status;
|
*/
|
||||||
static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH];
|
Uuid->Data4[0] &= 0x3f;
|
||||||
|
Uuid->Data4[0] |= 0x80;
|
||||||
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);
|
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_guid(Uuid));
|
TRACE("%s\n", debugstr_guid(Uuid));
|
||||||
|
|
||||||
return status;
|
return RPC_S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
|
@ -780,7 +780,6 @@ static void test_UuidCreate(void)
|
||||||
|
|
||||||
UuidCreate(&guid);
|
UuidCreate(&guid);
|
||||||
version = (guid.Data3 & 0xf000) >> 12;
|
version = (guid.Data3 & 0xf000) >> 12;
|
||||||
todo_wine
|
|
||||||
ok(version == 4 || broken(version == 1), "unexpected version %d\n",
|
ok(version == 4 || broken(version == 1), "unexpected version %d\n",
|
||||||
version);
|
version);
|
||||||
if (version == 4)
|
if (version == 4)
|
||||||
|
@ -826,7 +825,6 @@ static void test_UuidCreate(void)
|
||||||
* present. Just check that Data4[0]'s most significant bits are
|
* present. Just check that Data4[0]'s most significant bits are
|
||||||
* set as expected.
|
* set as expected.
|
||||||
*/
|
*/
|
||||||
todo_wine
|
|
||||||
ok((guid.Data4[0] & 0xc0) == 0x80,
|
ok((guid.Data4[0] & 0xc0) == 0x80,
|
||||||
"unexpected value in Data4[0]: %02x\n", guid.Data4[0] & 0xc0);
|
"unexpected value in Data4[0]: %02x\n", guid.Data4[0] & 0xc0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue