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

Last change on this file since 3317 was 3317, checked in by davidr, 25 years ago

Added more stubs; updated .def

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