9
#pragma comment(lib, "ws2_32")
13
#include <netinet/in.h>
23
#define MD5_Final MD5Final
24
#define MD5_Init MD5Init
25
#define MD5_Update MD5Update
27
#define SHA1_Final SHA1Result
28
#define SHA1_Init SHA1Reset
29
#define SHA1_Update SHA1Input
31
////////////////////////////////////////////////////////////////
32
//// Begin system dependent
33
//// system dependent call to get IEEE node ID.
34
//// This sample implementation generates a random node ID.
35
////////////////////////////////////////////////////////////////
37
// See: http://xml.resource.org/public/rfc/html/rfc4122.html
40
/* set the following to the number of 100ns ticks of the actual
41
resolution of your system's clock */
42
#define UUIDS_PER_TICK 1024
44
/* Set the following to a calls to get and release a global lock */
49
/* Set this to what your compiler uses for 64-bit data type */
51
#define unsigned64_t t_u64
54
#define unsigned64_t unsigned long long
57
#define unsigned64_t t_u64
61
typedef unsigned64_t uuid_time_t;
63
unsigned char nodeID[6];
66
void get_ieee_node_identifier(uuid_node_t *node);
67
void get_system_time(uuid_time_t *uuid_time);
68
void get_random_info(char seed[16]);
71
/* uuid_create -- generate a UUID version 1 */
72
int uuid_create(uuid_t * uuid);
75
uuid_create_md5_from_name -- create a version 3 (MD5) UUID using a
76
"name" from a "name space"
78
void uuid_create_md5_from_name(
79
uuid_t *uuid, /* resulting UUID */
80
uuid_t nsid, /* UUID of the namespace */
81
void *name, /* the name from which to generate a UUID */
82
int namelen /* the length of the name */
86
uuid_create_sha1_from_name -- create a version 5 (SHA-1) UUID
87
using a "name" from a "name space"
89
void uuid_create_sha1_from_name(
91
uuid_t *uuid, /* resulting UUID */
92
uuid_t nsid, /* UUID of the namespace */
93
void *name, /* the name from which to generate a UUID */
94
int namelen /* the length of the name */
97
/* uuid_compare -- Compare two UUID's "lexically" and return
98
-1 u1 is lexically before u2
100
1 u1 is lexically after u2
101
Note that lexical ordering is not temporal ordering!
103
int uuid_compare(uuid_t *u1, uuid_t *u2);
106
void get_ieee_node_identifier(uuid_node_t *node)
108
static int inited = 0;
109
static uuid_node_t saved_node;
115
#if (defined INL_VISUAL_STUDIO_2005) || (defined INL_VISUAL_STUDIO_2008)
116
fopen_s(&fp, "nodeid", "rb");
118
fp = fopen("nodeid", "rb");
122
fread(&saved_node, sizeof(saved_node), 1, fp);
127
get_random_info(seed);
129
memcpy(&saved_node, seed, sizeof(saved_node));
130
#if (defined INL_VISUAL_STUDIO_2005) || (defined INL_VISUAL_STUDIO_2008)
131
fopen_s(&fp, "nodeid", "wb");
133
fp = fopen("nodeid", "wb");
137
fwrite(&saved_node, sizeof(saved_node), 1, fp);
147
/* system dependent call to get the current system time. Returned as
148
100ns ticks since UUID epoch, but resolution may be less than
152
void get_system_time(uuid_time_t *uuid_time)
156
/* NT keeps time in FILETIME format which is 100ns ticks since
157
Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
158
The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
159
+ 18 years and 5 leap days. */
160
GetSystemTimeAsFileTime((FILETIME *)&time);
163
(unsigned __int64) (1000*1000*10) // seconds
164
* (unsigned __int64) (60 * 60 * 24) // days
165
* (unsigned __int64) (17+30+31+365*18+5); // # of days
166
*uuid_time = time.QuadPart;
169
/* Sample code, not for use in production; see RFC 1750 */
170
void get_random_info(char seed[16])
180
TCHAR hostname[MAX_COMPUTERNAME_LENGTH + 1];
184
GlobalMemoryStatus(&r.m);
186
GetSystemTimeAsFileTime(&r.t);
187
QueryPerformanceCounter(&r.pc);
188
r.tc = GetTickCount();
191
r.l = MAX_COMPUTERNAME_LENGTH + 1;
192
GetComputerName(r.hostname, &r.l);
193
MD5_Update(&c, (unsigned char*)&r, sizeof r);
195
memcpy((void*)&(seed[0]), (void*)&(c.digest[0]), 16);
200
void get_system_time(uuid_time_t *uuid_time)
205
gettimeofday(&tp, (struct timezone *)0);
207
// Offset between UUID formatted times and Unix formatted times. UUID UTC base time is October 15, 1582.
208
// Unix base time is January 1, 1970.
209
*uuid_time = ((unsigned64)tp.tv_sec * 10000000) + ((unsigned64)tp.tv_usec * 10) + I64(0x01B21DD213814000LL);
215
/* Sample code, not for use in production; see RFC 1750 */
216
void get_random_info(char seed[16])
228
gettimeofday(&r.t, (struct timezone *)0);
229
gethostname(r.hostname, 256);
230
MD5_Update(&c, &r, sizeof r);
240
////////////////////////////////////////////////////////////////
241
//// End system dependent
242
////////////////////////////////////////////////////////////////
244
/* various forward declarations */
245
static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp,
247
static void write_state(unsigned16 clockseq, uuid_time_t timestamp,
249
static void format_uuid_v1(uuid_t *uuid, unsigned16 clockseq,
250
uuid_time_t timestamp, uuid_node_t node);
252
static void format_uuid_v3or5(uuid_t *uuid, unsigned char hash[16],
254
static void get_current_time(uuid_time_t *timestamp);
255
static unsigned16 true_random(void);
257
// uuid_create -- generator a UUID
258
// Using IEEE 802 MAC addresses as a source of uniqueness.
259
// UUID version 1 values are computed using the MAC address of the host.
260
int GenerateUUID1(uuid_t *uuid)
262
uuid_time_t timestamp, last_time;
265
uuid_node_t last_node;
268
// acquire system-wide lock so we're alone
270
// get time, node ID, saved state from non-volatile storage
272
// The timestap is a 60 bit value, representing the number of 100 nanosecond intervals since 15 October 1582 00:00:000000000.
273
get_current_time(×tamp);
274
get_ieee_node_identifier(&node);
275
// The clock ID is a 14 bit value
276
f = read_state(&clockseq, &last_time, &last_node);
278
// if no NV (non-volatile) state, or if clock went backwards, or node ID changed (e.g., new network card) change clockseq
279
if (!f || memcmp(&node, &last_node, sizeof(node)))
280
clockseq = true_random();
281
else if (timestamp < last_time)
284
// save the state for next time
285
write_state(clockseq, timestamp, node);
289
// stuff fields into the UUID
290
format_uuid_v1(uuid, clockseq, timestamp, node);
294
// This class defines a UUID (Universally Unique IDentifier), also
295
// known as GUIDs (Globally Unique IDentifier). A UUID is 128 bits
296
// long, and if generated according to this algorithm, is either
297
// guaranteed to be different from all other UUIDs/GUIDs generated
298
// until 3400 A.D. or extremely likely to be different. UUIDs were
299
// originally used in the Network Computing System (NCS) and
300
// later in the Open Software Foundation's (OSF) Distributed Computing
301
// Environment (DCE).
303
// Structure of universal unique IDs (UUIDs).
305
// Depending on the network data representation, the multi-
306
// octet unsigned integer fields are subject to byte swapping
307
// when communicated between dissimilar endian machines.
310
// Field Data Type Octet Note
312
// time_low unsigned 32 bit integer 0-3 The low field of the timestamp
313
// time_mid unsigned 16 bit integer 4-5 The middle field of the timestamp
314
// time_hi_and_version unsigned 16 bit integer 6-7 The high field of the timestamp multiplexed with the version number
315
// clock_seq_hi_and_reserved unsigned 8 bit integer 8 The high field of the clock sequence multiplexed with the variant
316
// clock_seq_low unsigned 8 bit integer 9 The low field of the clock sequence
317
// node unsigned 48 bit integer 10-15 The spatially unique node identifier
320
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
321
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
323
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
324
// | time_mid | time_hi_and_version |
325
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
326
// |clk_seq_hi_res | clk_seq_low | node (0-1) |
327
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
329
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
331
// The version number is in the most significant 4 bits of the time_hi_and_version field.
332
// Msb0 Msb1 Msb2 Msb3 Version Description
333
// 0 0 0 1 1 The time-based version specified in this document.
334
// 0 0 1 0 2 DCE Security version, with embedded POSIX UIDs.
335
// 0 0 1 1 3 The name-based version specified in this document that uses MD5 hashing.
336
// 0 1 0 0 4 The randomly or pseudo-randomly generated version specified in this document.
337
// 0 1 0 1 5 The name-based version specified in this document that uses SHA-1 hashing.
340
// format_uuid_v1 -- make a UUID from the timestamp, clockseq, and node ID
341
void format_uuid_v1(uuid_t* uuid, unsigned16 clock_seq, uuid_time_t timestamp, uuid_node_t node)
343
// Construct a version 1 uuid with the information we've gathered plus a few constants.
344
uuid->time_low = (unsigned long)(timestamp & 0xFFFFFFFF);
345
uuid->time_mid = (unsigned short)((timestamp >> 32) & 0xFFFF);
346
uuid->time_hi_and_version = (unsigned short)((timestamp >> 48) & 0x0FFF);
349
uuid->time_hi_and_version |= (1 << 12);
350
uuid->clock_seq_low = clock_seq & 0xFF;
351
uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8;
352
uuid->clock_seq_hi_and_reserved |= 0x80;
353
memcpy(&uuid->node, &node, sizeof(uuid->node));
356
/* data type for UUID generator persistent state */
359
uuid_time_t ts; /* saved timestamp */
360
uuid_node_t node; /* saved node ID */
361
unsigned16 cs; /* saved clock sequence */
364
static uuid_state st;
366
// read_state -- read UUID generator state from non-volatile store
367
int read_state(unsigned16 *clockseq, uuid_time_t *timestamp,
370
static int inited = 0;
373
/* only need to read state once per boot */
376
#if (defined INL_VISUAL_STUDIO_2005) || (defined INL_VISUAL_STUDIO_2008)
377
fopen_s(&fp, "state", "rb");
379
fp = fopen("state", "rb");
383
fread(&st, sizeof st, 1, fp);
393
// write_state -- save UUID generator state back to non-volatile storage
394
void write_state(unsigned16 clockseq, uuid_time_t timestamp,
397
static int inited = 0;
398
static uuid_time_t next_save;
401
next_save = timestamp;
405
/* always save state to volatile shared state */
409
if (timestamp >= next_save)
411
#if (defined INL_VISUAL_STUDIO_2005) || (defined INL_VISUAL_STUDIO_2008)
412
fopen_s(&fp, "state", "wb");
414
fp = fopen("state", "wb");
416
fwrite(&st, sizeof st, 1, fp);
418
/* schedule next save for 10 seconds from now */
419
next_save = timestamp + (10 * 10 * 1000 * 1000);
423
// get-current_time -- get time as 60-bit 100ns ticks since UUID epoch.
424
// Compensate for the fact that real clock resolution is
426
void get_current_time(uuid_time_t *timestamp)
428
static int inited = 0;
429
static uuid_time_t time_last;
430
static unsigned16 uuids_this_tick;
431
uuid_time_t time_now;
434
get_system_time(&time_now);
435
uuids_this_tick = UUIDS_PER_TICK;
440
get_system_time(&time_now);
442
/* if clock reading changed since last UUID generated, */
443
if (time_last != time_now) {
444
/* reset count of uuids gen'd with this clock reading */
446
time_last = time_now;
449
if (uuids_this_tick < UUIDS_PER_TICK) {
453
/* going too fast for our clock; spin */
455
/* add the count of uuids to low order bits of the clock reading */
456
*timestamp = time_now + uuids_this_tick;
459
// true_random -- generate a crypto-quality random number. This sample doesn't do that.
460
static unsigned16 true_random(void)
462
static int inited = 0;
463
uuid_time_t time_now;
466
get_system_time(&time_now);
467
time_now = time_now / UUIDS_PER_TICK;
469
(((time_now >> 32) ^ time_now) & 0xffffffff));
476
// create a version 3 (MD5) UUID using a "name" from a "name space"
477
void uuid_create_md5_from_name(uuid_t *uuid, uuid_t nsid, void *name, int namelen)
480
unsigned char hash[16];
483
/* put name space ID in network byte order so it hashes the same
484
no matter what endian machine we're on */
486
net_nsid.time_low = htonl(net_nsid.time_low);
487
net_nsid.time_mid = htons(net_nsid.time_mid);
488
net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version);
491
MD5_Update(&c, (unsigned char*)&net_nsid, sizeof net_nsid);
492
MD5_Update(&c, (unsigned char*)name, namelen);
494
memcpy((void*)&(hash[0]), (void*)&(c.digest[0]), 16);
496
/* the hash is in network byte order at this point */
497
format_uuid_v3or5(uuid, hash, 3);
500
void GenerateUUID3(uuid_t *uuid, uuid_t nsid, void *name, int namelen)
502
uuid_create_md5_from_name(uuid, nsid, name, namelen);
505
#define SHA_CTX SHA1Context
507
// format_uuid_v3or5 -- make a UUID from a (pseudo)random 128-bit number
508
void format_uuid_v3or5(uuid_t *uuid, unsigned char hash[16], int version)
510
/* convert UUID to local byte order */
511
memcpy(uuid, hash, sizeof *uuid);
512
uuid->time_low = ntohl(uuid->time_low);
513
uuid->time_mid = ntohs(uuid->time_mid);
514
uuid->time_hi_and_version = ntohs(uuid->time_hi_and_version);
516
/* put in the variant and version bits */
517
uuid->time_hi_and_version &= 0x0FFF;
518
uuid->time_hi_and_version |= (version << 12);
519
uuid->clock_seq_hi_and_reserved &= 0x3F;
520
uuid->clock_seq_hi_and_reserved |= 0x80;
523
// Create a version 5 (SHA-1) UUID using a "name" from a "name space"
524
void uuid_create_sha1_from_name(uuid_t *uuid, uuid_t nsid, void *name, int namelen)
527
unsigned char hash[20];
530
/* put name space ID in network byte order so it hashes the same
531
no matter what endian machine we're on */
533
net_nsid.time_low = htonl(net_nsid.time_low);
534
net_nsid.time_mid = htons(net_nsid.time_mid);
535
net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version);
538
SHA1_Update(&c, (const unsigned char*)&net_nsid, sizeof net_nsid);
539
SHA1_Update(&c, (const unsigned char*)name, namelen);
540
SHA1_Final(/*hash,*/ &c);
541
memcpy((void*)&(hash[0]), (void*)&(c.Message_Digest[0]), 16);
543
/* the hash is in network byte order at this point */
544
format_uuid_v3or5(uuid, hash, 5);
547
void GenerateUUID5(uuid_t *uuid, uuid_t nsid, void *name, int namelen)
549
uuid_create_sha1_from_name(uuid, nsid, name, namelen);
552
// uuid_compare -- Compare two UUID's "lexically" and return 0 if they are identical
553
#define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
554
int uuid_compare(uuid_t *u1, uuid_t *u2)
558
CHECK(u1->time_low, u2->time_low);
559
CHECK(u1->time_mid, u2->time_mid);
560
CHECK(u1->time_hi_and_version, u2->time_hi_and_version);
561
CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved);
562
CHECK(u1->clock_seq_low, u2->clock_seq_low)
563
for (i = 0; i < 6; i++)
565
if (u1->node[i] < u2->node[i])
567
if (u1->node[i] > u2->node[i])