source: trunk/src/rpcrt4/uuid.cpp@ 10366

Last change on this file since 10366 was 3325, checked in by bird, 25 years ago

Build error correction <toolkit version issue>.

  • gettimeofday renamed to gettimeofday
  • #defined TCPV40HDRS to force usage of version 4.0 TCPIP headerfiles.
File size: 17.2 KB
Line 
1/* $Id: uuid.cpp,v 1.3 2000-04-06 11:54:03 bird Exp $ */
2/*
3 * RPCRT4 library
4 * UUID manipulation
5 * Partially based on OSF sources (see below)
6 *
7 * 2000/02/05
8 *
9 * Copyright 2000 David J. Raison
10 * 2000 Edgar Buerkle
11 *
12 * Project Odin Software License can be found in LICENSE.TXT
13 *
14 */
15/*
16 *
17 * (c) Copyright 1989 OPEN SOFTWARE FOUNDATION, INC.
18 * (c) Copyright 1989 HEWLETT-PACKARD COMPANY
19 * (c) Copyright 1989 DIGITAL EQUIPMENT CORPORATION
20 * To anyone who acknowledges that this file is provided "AS IS"
21 * without any express or implied warranty:
22 * permission to use, copy, modify, and distribute this
23 * file for any purpose is hereby granted without fee, provided that
24 * the above copyright notices and this notice appears in all source
25 * code copies, and that none of the names of Open Software
26 * Foundation, Inc., Hewlett-Packard Company, or Digital Equipment
27 * Corporation be used in advertising or publicity pertaining to
28 * distribution of the software without specific, written prior
29 * permission. Neither Open Software Foundation, Inc., Hewlett-
30 * Packard Company, nor Digital Equipment Corporation makes any
31 * representations about the suitability of this software for any
32 * purpose.
33 *
34 */
35
36
37#define TCPV40HDRS
38#include "rpcrt4.h"
39#include "uuidp.h"
40
41#include "io.h"
42#include "sys\timeb.h"
43
44#include <sys\socket.h>
45#include <sys\ioctl.h>
46#include <netdb.h>
47#include <netinet\in.h>
48#include <netinet\tcp.h>
49#undef interface
50#include <net\if.h>
51#include <netinet\if_ether.h>
52#include <nerrno.h>
53#include <sys\time.h>
54
55ULONG WINAPI RtlExtendedIntegerMultiply(LARGE_INTEGER factor1, INT factor2);
56ULONG WINAPI RtlLargeIntegerAdd(LARGE_INTEGER arg1, LARGE_INTEGER arg2);
57
58extern "C" ULONG getEAX();
59extern "C" ULONG getEDX();
60
61static UUID uuid_nil = { 0 };
62static unsigned char uuid_addr[6];
63
64// ----------------------------------------------------------------------
65// UuidInit
66// Init the Uuid subsystem (i.e. retrieve & cache the eth. addr)
67// ----------------------------------------------------------------------
68extern void UuidInit(void )
69{
70 struct ifmib ifm = {0};
71 int fFound = FALSE;
72 int sd;
73 int ii;
74
75 // Ensure that uuid_nil is initialised.
76 memset(&uuid_nil, 0, sizeof(uuid_nil));
77
78 // retrieve & cache the eth. addr
79
80 /* BSD 4.4 defines the size of an ifreq to be
81 * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
82 * However, under earlier systems, sa_len isn't present, so
83 * the size is just sizeof(struct ifreq)
84 */
85 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
86 if (sd > 0)
87 {
88 if (ioctl(sd, SIOSTATIF42, (char *)&ifm, sizeof(ifm)) >= 0)
89 {
90 for(ii = 0; ii < ifm.ifNumber; ii++)
91 {
92 if (!ifm.iftable[ii].ifPhysAddr[0] && !ifm.iftable[ii].ifPhysAddr[1] &&
93 !ifm.iftable[ii].ifPhysAddr[2] && !ifm.iftable[ii].ifPhysAddr[3] &&
94 !ifm.iftable[ii].ifPhysAddr[4] && !ifm.iftable[ii].ifPhysAddr[5])
95 continue;
96 fFound = TRUE;
97 memcpy(uuid_addr, (unsigned char *)&ifm.iftable[ii].ifPhysAddr, 6);
98 }
99 }
100 close(sd);
101 }
102
103 if (!fFound)
104 {
105 /* if we can't find the physical net address use random numbers */
106 /* set the multicast bit to prevent conflicts with real cards */
107
108 uuid_addr[0] = (rand() & 0xff) | 0x80;
109 uuid_addr[1] = rand() & 0xff;
110 uuid_addr[2] = rand() & 0xff;
111 uuid_addr[3] = rand() & 0xff;
112 uuid_addr[4] = rand() & 0xff;
113 uuid_addr[5] = rand() & 0xff;
114 }
115}
116
117// ----------------------------------------------------------------------
118// gettimeofday
119// ----------------------------------------------------------------------
120static int
121__gettimeofday(struct timeval* tp, void* tzp)
122{
123 struct timeb tb;
124
125 ftime(&tb);
126 tp->tv_sec = tb.time;
127 tp->tv_usec = tb.millitm * 1000;
128
129 return 0;
130}
131
132// ----------------------------------------------------------------------
133// UuidCreate
134// Implemented according the DCE specification for UUID generation.
135// Code is based upon uuid library in e2fsprogs by Theodore Ts'o.
136// Copyright (C) 1996, 1997 Theodore Ts'o.
137//
138// Returns
139// S_OK if successful.
140// ----------------------------------------------------------------------
141RPCRTAPI RPC_STATUS RPC_ENTRY
142UuidCreate (
143 OUT UUID __RPC_FAR * pUuid
144 )
145{
146 static int adjustment = 0;
147 static struct timeval last = {0, 0};
148 static UINT16 clock_seq;
149 struct timeval tv;
150 LARGE_INTEGER clock_reg={0};
151 LARGE_INTEGER clock_reg_tmp={0};
152 UINT clock_high;
153 UINT clock_low;
154 UINT16 temp_clock_seq;
155 UINT16 temp_clock_mid;
156 UINT16 temp_clock_hi_and_version;
157 BOOL got_no_time;
158
159 dprintf(("RPCRT4: %s", __FUNCTION__));
160
161 /* The OS/2 gettimeofday has a >1ms granularity (~17 bps) */
162 #define MAX_ADJUSTMENT 10000
163
164 do
165 {
166 got_no_time = FALSE;
167
168 __gettimeofday(&tv, 0);
169 if ((last.tv_sec == 0) && (last.tv_usec == 0))
170 {
171 clock_seq = ((rand() & 0xff) << 8) + (rand() & 0xff);
172 clock_seq &= 0x1FFF;
173 last = tv;
174 last.tv_sec--;
175 }
176 if ((tv.tv_sec < last.tv_sec) || ((tv.tv_sec == last.tv_sec) &&
177 (tv.tv_usec < last.tv_usec)))
178 {
179 clock_seq = (clock_seq+1) & 0x1FFF;
180 adjustment = 0;
181 }
182 else if ((tv.tv_sec == last.tv_sec) && (tv.tv_usec == last.tv_usec))
183 {
184 if (adjustment >= MAX_ADJUSTMENT)
185 {
186 got_no_time = TRUE;
187 Sleep(1); // Allow someone else to run.
188 }
189 else
190 adjustment++;
191 }
192 else
193 {
194 adjustment = 0;
195 last = tv; // ><EB missing in wine and maybe(not tested) in ef2prog
196 }
197
198 } while(got_no_time);
199
200 clock_reg_tmp.LowPart = tv.tv_usec*10 + adjustment;
201 clock_reg_tmp.HighPart = tv.tv_sec;
202
203 RtlExtendedIntegerMultiply(clock_reg_tmp, 10000000);
204 clock_reg.LowPart = getEAX();
205 clock_reg.HighPart = getEDX();
206
207 RtlLargeIntegerAdd(clock_reg, clock_reg_tmp );
208 clock_reg.LowPart = getEAX();
209 clock_reg.HighPart = getEDX();
210
211 clock_reg_tmp.LowPart = 0x13814000;
212 clock_reg_tmp.HighPart = 0x01B21DD2;
213 RtlLargeIntegerAdd(clock_reg, clock_reg_tmp );
214 clock_reg.LowPart = getEAX();
215 clock_reg.HighPart = getEDX();
216
217 clock_high = clock_reg.HighPart;
218 clock_low = clock_reg.LowPart;
219
220 temp_clock_seq = clock_seq | 0x8000;
221 temp_clock_mid = (UINT16)clock_high;
222 temp_clock_hi_and_version = (clock_high >> 16) | 0x1000;
223
224 /* pack the information into the GUID structure */
225 ((unsigned char*)&pUuid->Data1)[3] = (unsigned char)clock_low;
226 clock_low >>= 8;
227 ((unsigned char*)&pUuid->Data1)[2] = (unsigned char)clock_low;
228 clock_low >>= 8;
229 ((unsigned char*)&pUuid->Data1)[1] = (unsigned char)clock_low;
230 clock_low >>= 8;
231 ((unsigned char*)&pUuid->Data1)[0] = (unsigned char)clock_low;
232
233 ((unsigned char*)&pUuid->Data2)[1] = (unsigned char)temp_clock_mid;
234 temp_clock_mid >>= 8;
235 ((unsigned char*)&pUuid->Data2)[0] = (unsigned char)temp_clock_mid;
236
237 ((unsigned char*)&pUuid->Data3)[1] = (unsigned char)temp_clock_hi_and_version;
238 temp_clock_hi_and_version >>= 8;
239 ((unsigned char*)&pUuid->Data3)[0] = (unsigned char)temp_clock_hi_and_version;
240
241 ((unsigned char*)pUuid->Data4)[1] = (unsigned char)temp_clock_seq;
242 temp_clock_seq >>= 8;
243 ((unsigned char*)pUuid->Data4)[0] = (unsigned char)temp_clock_seq;
244
245 ((unsigned char*)pUuid->Data4)[2] = uuid_addr[0];
246 ((unsigned char*)pUuid->Data4)[3] = uuid_addr[1];
247 ((unsigned char*)pUuid->Data4)[4] = uuid_addr[2];
248 ((unsigned char*)pUuid->Data4)[5] = uuid_addr[3];
249 ((unsigned char*)pUuid->Data4)[6] = uuid_addr[4];
250 ((unsigned char*)pUuid->Data4)[7] = uuid_addr[5];
251
252 return S_OK;
253}
254
255// ----------------------------------------------------------------------
256// UuidCreateNil
257// ----------------------------------------------------------------------
258RPCRTAPI RPC_STATUS RPC_ENTRY
259UuidCreateNil (
260 OUT UUID __RPC_FAR * NilUuid
261 )
262{
263 dprintf(("RPCRT4: %s", __FUNCTION__));
264
265 memset (NilUuid, 0, sizeof (uuid_t));
266
267 return RPC_S_OK;
268}
269
270
271// ----------------------------------------------------------------------
272// UuidToStringA
273// Memory allocated here should be released via RpcStringFreeA
274// ----------------------------------------------------------------------
275RPCRTAPI RPC_STATUS RPC_ENTRY
276UuidToStringA (
277 IN UUID __RPC_FAR * Uuid,
278 OUT unsigned char __RPC_FAR * __RPC_FAR * StringUuid
279 )
280{
281 char * pString;
282
283 dprintf(("RPCRT4: %s", __FUNCTION__));
284
285 // jic
286 *StringUuid = 0;
287
288 if ((pString = (char *)HeapAlloc(GetProcessHeap(), 0, 40)) == NULL)
289 return RPC_S_OUT_OF_MEMORY;
290
291 // Setup new string...
292 sprintf(pString, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
293 Uuid->Data1,
294 Uuid->Data2,
295 Uuid->Data3,
296 Uuid->Data4[0],
297 Uuid->Data4[1],
298 Uuid->Data4[2],
299 Uuid->Data4[3],
300 Uuid->Data4[4],
301 Uuid->Data4[5],
302 Uuid->Data4[6],
303 Uuid->Data4[7]);
304
305 *StringUuid = (unsigned char *)pString;
306
307 return RPC_S_OK;
308}
309
310
311// ----------------------------------------------------------------------
312// UuidFromStringA
313// ----------------------------------------------------------------------
314RPCRTAPI RPC_STATUS RPC_ENTRY
315UuidFromStringA (
316 IN unsigned char __RPC_FAR * StringUuid,
317 OUT UUID __RPC_FAR * Uuid
318 )
319{
320 dprintf(("RPCRT4: %s", __FUNCTION__));
321
322 // Convert to binary CLSID
323 char *s = (char *) StringUuid;
324 char *p;
325 int i;
326 char table[256];
327
328 /* quick lookup table */
329 memset(table, 0, 256);
330
331 for (i = 0; i < 10; i++)
332 {
333 table['0' + i] = i;
334 }
335 for (i = 0; i < 6; i++)
336 {
337 table['A' + i] = i+10;
338 table['a' + i] = i+10;
339 }
340
341 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
342
343 if (lstrlenA(s) != 38)
344 return RPC_S_INVALID_STRING_UUID;
345
346 p = (char *) Uuid;
347
348 s++; /* skip leading brace */
349 for (i = 0; i < 4; i++)
350 {
351 p[3 - i] = table[*s]<<4 | table[*(s+1)];
352 s += 2;
353 }
354 p += 4;
355 s++; /* skip - */
356
357 for (i = 0; i < 2; i++)
358 {
359 p[1-i] = table[*s]<<4 | table[*(s+1)];
360 s += 2;
361 }
362 p += 2;
363 s++; /* skip - */
364
365 for (i = 0; i < 2; i++)
366 {
367 p[1-i] = table[*s]<<4 | table[*(s+1)];
368 s += 2;
369 }
370 p += 2;
371 s++; /* skip - */
372
373 /* these are just sequential bytes */
374 for (i = 0; i < 2; i++)
375 {
376 *p++ = table[*s]<<4 | table[*(s+1)];
377 s += 2;
378 }
379 s++; /* skip - */
380
381 for (i = 0; i < 6; i++)
382 {
383 *p++ = table[*s]<<4 | table[*(s+1)];
384 s += 2;
385 }
386
387 return RPC_S_OK;
388}
389
390
391// ----------------------------------------------------------------------
392// UuidToStringW
393// Memory allocated here should be released via RpcStringFreeW
394// ----------------------------------------------------------------------
395RPCRTAPI RPC_STATUS RPC_ENTRY
396UuidToStringW (
397 IN UUID __RPC_FAR * Uuid,
398 OUT unsigned short __RPC_FAR * __RPC_FAR * StringUuid
399 )
400{
401 RPC_STATUS rc;
402 unsigned char * pStringA;
403 WCHAR * pStringW;
404 size_t strLen;
405
406 dprintf(("RPCRT4: %s", __FUNCTION__));
407
408 // jic
409 *StringUuid = 0;
410
411 // Setup new string...
412 if ((rc = UuidToStringA(Uuid, &pStringA)) != RPC_S_OK)
413 return rc; // Boom...
414
415 strLen = strlen((char *)pStringA);
416
417 // Grab buffer for string...
418 if ((pStringW = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, (strLen + 1) * sizeof(WCHAR))) == NULL)
419 rc = RPC_S_OUT_OF_MEMORY;
420 else
421 {
422 AsciiToUnicode((char *)pStringA, pStringW);
423 *StringUuid = (LPOLESTR)pStringW;
424 rc = RPC_S_OK;
425 }
426
427 // Free the ASCII string
428 RpcStringFreeA(&pStringA);
429
430 return rc;
431}
432
433
434// ----------------------------------------------------------------------
435// UuidFromStringW
436// ----------------------------------------------------------------------
437RPCRTAPI RPC_STATUS RPC_ENTRY
438UuidFromStringW (
439 IN unsigned short __RPC_FAR * StringUuid,
440 OUT UUID __RPC_FAR * Uuid
441 )
442{
443 unsigned char tmp[40];
444
445 dprintf(("RPCRT4: %s", __FUNCTION__));
446
447 UnicodeToAscii((LPWSTR)StringUuid, (char *)tmp);
448 return UuidFromStringA(tmp, Uuid);
449}
450
451
452// ----------------------------------------------------------------------
453// UuidCompare
454// ----------------------------------------------------------------------
455RPCRTAPI signed int RPC_ENTRY
456UuidCompare (
457 IN UUID __RPC_FAR * Uuid1,
458 IN UUID __RPC_FAR * Uuid2,
459 OUT RPC_STATUS __RPC_FAR * Status
460 )
461{
462 int ii;
463
464 dprintf(("RPCRT4: %s", __FUNCTION__));
465
466 /*
467 * check to see if either of the arguments is a NULL pointer
468 * - if so, compare the other argument to the nil Uuid
469 */
470 if (Uuid1 == NULL)
471 {
472 /*
473 * if both arguments are NULL, so is this routine
474 */
475 if (Uuid2 == NULL)
476 {
477 *Status = RPC_S_OK;
478 return (0);
479 }
480
481 return (UuidIsNil (Uuid2, Status) ? 0 : -1);
482 }
483
484 if (Uuid2 == NULL)
485 {
486 return (UuidIsNil (Uuid1, Status) ? 0 : 1);
487 }
488 *Status = RPC_S_OK;
489
490 if (Uuid1->Data1 == Uuid2->Data1)
491 {
492 if (Uuid1->Data2 == Uuid2->Data2)
493 {
494 if (Uuid1->Data3 == Uuid2->Data3)
495 {
496 if (Uuid1->Data4[0] == Uuid2->Data4[0])
497 {
498 if (Uuid1->Data4[1] == Uuid2->Data4[1])
499 {
500 for (ii = 2; ii < 8; ii++)
501 {
502 if (Uuid1->Data4[ii] < Uuid2->Data4[ii])
503 return (-1);
504 if (Uuid1->Data4[ii] > Uuid2->Data4[ii])
505 return (1);
506 }
507 return (0);
508 } /* end if - clock_seq_low */
509 else
510 {
511 if (Uuid1->Data4[1] < Uuid2->Data4[1])
512 return (-1);
513 else
514 return (1);
515 } /* end else - clock_seq_low */
516 } /* end if - clock_seq_hi_and_reserved */
517 else
518 {
519 if (Uuid1->Data4[0] < Uuid2->Data4[0])
520 return (-1);
521 else
522 return (1);
523 } /* end else - clock_seq_hi_and_reserved */
524 } /* end if - time_hi_and_version */
525 else
526 {
527 if (Uuid1->Data3 < Uuid2->Data3)
528 return (-1);
529 else
530 return (1);
531 } /* end else - time_hi_and_version */
532 } /* end if - time_mid */
533 else
534 {
535 if (Uuid1->Data2 < Uuid2->Data2)
536 return (-1);
537 else
538 return (1);
539 } /* end else - time_mid */
540 } /* end if - time_low */
541 else
542 {
543 if (Uuid1->Data1 < Uuid2->Data1)
544 return (-1);
545 else
546 return (1);
547 } /* end else - time_low */
548}
549
550
551// ----------------------------------------------------------------------
552// UuidEqual
553// ----------------------------------------------------------------------
554RPCRTAPI int RPC_ENTRY
555UuidEqual (
556 IN UUID __RPC_FAR * Uuid1,
557 IN UUID __RPC_FAR * Uuid2,
558 OUT RPC_STATUS __RPC_FAR * Status
559 )
560{
561 dprintf(("RPCRT4: %s", __FUNCTION__));
562 *Status = RPC_S_OK;
563 return IsEqualGUID(Uuid1, Uuid2);
564}
565
566
567// ----------------------------------------------------------------------
568// UuidHash
569// ----------------------------------------------------------------------
570RPCRTAPI unsigned short RPC_ENTRY
571UuidHash (
572 IN UUID __RPC_FAR * Uuid,
573 OUT RPC_STATUS __RPC_FAR * Status
574 )
575{
576 dprintf(("RPCRT4: %s", __FUNCTION__));
577
578 short c0, c1;
579 short x, y;
580 char * next_uuid;
581
582 /*
583 * initialize counters
584 */
585 c0 = c1 = 0;
586 next_uuid = (char *) Uuid;
587
588 /*
589 * For speed lets unroll the following loop:
590 *
591 * for (i = 0; i < UUID_K_LENGTH; i++)
592 * {
593 * c0 = c0 + *next_uuid++;
594 * c1 = c1 + c0;
595 * }
596 */
597 c0 = c0 + *next_uuid++;
598 c1 = c1 + c0;
599 c0 = c0 + *next_uuid++;
600 c1 = c1 + c0;
601 c0 = c0 + *next_uuid++;
602 c1 = c1 + c0;
603 c0 = c0 + *next_uuid++;
604 c1 = c1 + c0;
605
606 c0 = c0 + *next_uuid++;
607 c1 = c1 + c0;
608 c0 = c0 + *next_uuid++;
609 c1 = c1 + c0;
610 c0 = c0 + *next_uuid++;
611 c1 = c1 + c0;
612 c0 = c0 + *next_uuid++;
613 c1 = c1 + c0;
614
615 c0 = c0 + *next_uuid++;
616 c1 = c1 + c0;
617 c0 = c0 + *next_uuid++;
618 c1 = c1 + c0;
619 c0 = c0 + *next_uuid++;
620 c1 = c1 + c0;
621 c0 = c0 + *next_uuid++;
622 c1 = c1 + c0;
623
624 c0 = c0 + *next_uuid++;
625 c1 = c1 + c0;
626 c0 = c0 + *next_uuid++;
627 c1 = c1 + c0;
628 c0 = c0 + *next_uuid++;
629 c1 = c1 + c0;
630 c0 = c0 + *next_uuid++;
631 c1 = c1 + c0;
632
633 /*
634 * Calculate the value for "First octet" of the hash
635 */
636 x = -c1 % 255;
637 if (x < 0)
638 {
639 x = x + 255;
640 }
641
642 /*
643 * Calculate the value for "second octet" of the hash
644 */
645 y = (c1 - c0) % 255;
646 if (y < 0)
647 {
648 y = y + 255;
649 }
650
651 /*
652 * return the pieces put together
653 */
654 *Status = RPC_S_OK;
655
656 return ((y * 256) + x);
657}
658
659
660// ----------------------------------------------------------------------
661// UuidIsNil
662// ----------------------------------------------------------------------
663RPCRTAPI int RPC_ENTRY
664UuidIsNil (
665 IN UUID __RPC_FAR * Uuid,
666 OUT RPC_STATUS __RPC_FAR * Status
667 )
668{
669 dprintf(("RPCRT4: %s", __FUNCTION__));
670
671 *Status = RPC_S_OK;
672
673 return IsEqualGUID(Uuid, &uuid_nil);
674}
675
Note: See TracBrowser for help on using the repository browser.