chxuuid.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:49k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer and/or licensor of the Original Code and owns the copyrights 
  21.  * in the portions it created.  
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. //
  36. // CHXuuid class implementation
  37. //
  38. //
  39. //  This code derives from uuid.c from OSF DCE source
  40. /*
  41.  * 
  42.  * (c) Copyright 1989 OPEN SOFTWARE FOUNDATION, INC.
  43.  * (c) Copyright 1989 HEWLETT-PACKARD COMPANY
  44.  * (c) Copyright 1989 DIGITAL EQUIPMENT CORPORATION
  45.  * To anyone who acknowledges that this file is provided "AS IS"
  46.  * without any express or implied warranty:
  47.  *                 permission to use, copy, modify, and distribute this
  48.  * file for any purpose is hereby granted without fee, provided that
  49.  * the above copyright notices and this notice appears in all source
  50.  * code copies, and that none of the names of Open Software
  51.  * Foundation, Inc., Hewlett-Packard Company, or Digital Equipment
  52.  * Corporation be used in advertising or publicity pertaining to
  53.  * distribution of the software without specific, written prior
  54.  * permission.  Neither Open Software Foundation, Inc., Hewlett-
  55.  * Packard Company, nor Digital Equipment Corporation makes any
  56.  * representations about the suitability of this software for any
  57.  * purpose.
  58.  * 
  59.  */
  60.  
  61. #include "hxtypes.h"
  62. #ifdef _WINDOWS
  63. #define WIN32_LEAN_AND_MEAN
  64. #include <windows.h> // for HX_GET_TICK_COUNT
  65. #endif
  66. #include "hlxclib/string.h"
  67. // #include "hlxclib/stdio.h"
  68. #include "safestring.h"
  69. #include "hxstring.h"
  70. #include "hxresult.h"
  71. #include "hxassert.h"
  72. #include "hxrand.h"
  73. #include "chxuuid.h"
  74. #include "hxtick.h"
  75. #include "hxtime.h"
  76. #include "netbyte.h"
  77. #include "md5.h"
  78. #include <ctype.h>
  79. #if !defined(_VXWORKS) && !defined(_SYMBIAN) && !defined(_OPENWAVE)
  80. #include <memory.h>
  81. #endif
  82. #include <stdarg.h>
  83. #ifdef _WIN16
  84. #include <ctype.h>
  85. #include <memory.h>
  86. #endif
  87. #ifdef _WIN32
  88. #include <objbase.h>
  89. #endif
  90. #include "hxheap.h"
  91. #ifdef _DEBUG
  92. #undef HX_THIS_FILE
  93. static const char HX_THIS_FILE[] = __FILE__;
  94. #endif
  95. #if defined(_WIN16)
  96. // global definitons (scope: wsscanf.c)
  97. #ifdef ALLOW_RANGE
  98.    char szSBrackSet[] = " t-r]" ;  // use range-style list
  99. #else
  100.    char szSBrackSet[] = "tnvfr]" ;  // chars defined by isspace 
  101. #endif
  102. char szCBrackSet[] = "]" ;
  103. // constant definitions
  104. #define ALLOW_RANGE                        // allow "%[a-z]" - style 
  105.                                            // scansets
  106. #define LEFT_BRACKET  ('[' | ('a' - 'A'))  // 'lowercase' version
  107. #define ASCII         32                   // # of bytes needed to 
  108.                                            // hold 256 bits
  109. // macro definitions
  110. #define INC()            (++nCharCount, Inc( (LPSTR FAR *) &lpPtrBuffer ))
  111. #define UN_INC( chr )    (--nCharCount, UnInc( chr, (LPSTR FAR *) &lpPtrBuffer ))
  112. #define EAT_WHITE()      WhiteOut( (int FAR *) &nCharCount, (LPSTR FAR *) &lpPtrBuffer )
  113. #define HEXTODEC( chr )  HexToDec( chr )
  114. #define MUL10(x)         ( (((x)<<2) + (x))<<1 )
  115. typedef char _far *wva_list ;
  116. #define wva_start( ap, v )  (ap = (wva_list) &v + sizeof( v ))
  117. #define wva_arg( ap, t )    (((t _far *)(ap += sizeof( t )))[-1])
  118. #define wva_end( ap )       (ap = NULL)
  119. /************************************************************************
  120.  *  char NEAR HexToDec( char chChar )
  121.  *
  122.  *  Description:
  123.  *     HexToDec() convert hexadecimal to decimal equivalent.
  124.  *
  125.  ************************************************************************/
  126. char NEAR HexToDec( char chChar )
  127. {
  128.    return (isdigit( chChar ) ? chChar : (char) ((chChar & ~('a' - 'A')) - 'A' + 10 + '0')) ;
  129. } /* end of HexToDec() */
  130. /************************************************************************
  131.  *  char NEAR Inc( LPSTR FAR *lpPtrBuffer )
  132.  *
  133.  *  Description:
  134.  *     "Pops" a character from the buffer.
  135.  *
  136.  ************************************************************************/
  137. char NEAR Inc( LPSTR FAR *lpPtrBuffer )
  138. {
  139.    char  ch ;
  140.    ch = *((LPSTR) *lpPtrBuffer) ;
  141.    ((LPSTR&)(*lpPtrBuffer))++ ;
  142.    return ( ch ) ;
  143. } /* end of Inc() */
  144. /************************************************************************
  145.  *  VOID NEAR UnInc( char chChar, LPSTR FAR *lpPtrBuffer )
  146.  *
  147.  *  Description:
  148.  *     "Pushes" a characters back into the buffer.
  149.  *
  150.  ************************************************************************/
  151. VOID NEAR UnInc( char chChar, LPSTR FAR *lpPtrBuffer )
  152. {
  153.    ((LPSTR&)(*lpPtrBuffer))-- ;
  154.    *((LPSTR) *lpPtrBuffer) = chChar ;
  155.    
  156. } /* end of UnInc() */
  157. /************************************************************************
  158.  *  char NEAR WhiteOut( int *lpnCounter, LPSTR FAR *lpPtrBuffer )
  159.  *
  160.  *  Description:
  161.  *     Increments the string pointer while in white space.
  162.  *
  163.  ************************************************************************/
  164. char NEAR WhiteOut( int FAR *lpnCounter, LPSTR FAR *lpPtrBuffer )
  165. {
  166.    char  ch ;
  167.    while (isspace(ch = (++*lpnCounter, Inc( lpPtrBuffer )))) ;
  168.    return ( ch ) ;
  169. } /* end of WhiteOut() */
  170. /************************************************************************
  171.  *  int FAR _cdecl wsscanf( LPSTR lpBuffer, LPSTR lpFormat,
  172.  *                          LPSTR lpParms, ... )
  173.  *
  174.  *  Description:
  175.  *     Replacement function for sscanf().   Useable in DLLs (all
  176.  *     parameters are passed as FAR pointers.
  177.  *
  178.  ************************************************************************/
  179. int FAR _cdecl wsscanf( char* lpBuffer, char* lpFormat, ... )
  180. {
  181.    BYTE          bCoerceShort, bDoneFlag, bLongOne, bMatch, bNegative,
  182.                  bReject, bSuppress ;
  183.    BYTE FAR *    lpPtrScan ;
  184.    DWORD         dwNumber ;
  185.    LPSTR         lpPtrFormat, lpPtrBuffer ;
  186.    LPVOID FAR *  lpArgList;
  187.    LPVOID        lpPointer, lpStart ;
  188.    WORD          wHoldSeg ;
  189.    char          ch, chCom, chLast, chPrev, chRange, szTable[ ASCII ] ; /* Flawfinder: ignore */
  190.    int           nCount, nCharCount, nWidth, nWidthSet, nStarted ;
  191.    wva_list  lpParms;
  192.    
  193.    wva_start(lpParms, lpFormat);
  194.    lpArgList = (LPVOID FAR *) &lpParms ;
  195.    nCount = nCharCount = 0 ;
  196.    bMatch = FALSE ;
  197.    lpPtrFormat = lpFormat ;
  198.    lpPtrBuffer = lpBuffer ;
  199.    while (*lpPtrFormat)
  200.    {
  201.       if (isspace( *lpPtrFormat ))
  202.       {
  203.          UN_INC( EAT_WHITE() ) ;  // put first non-space char back
  204.          while (isspace(*++lpPtrFormat)) ;
  205.       }
  206.       if ('%' == *lpPtrFormat)
  207.       {
  208.          bCoerceShort = bDoneFlag = bLongOne = bNegative =
  209.          bReject = bSuppress = FALSE ;
  210.          nWidth = nWidthSet = nStarted = 0 ;
  211.          dwNumber = 0 ;
  212.          chPrev = 0 ;
  213.    
  214.          while (!bDoneFlag)
  215.          {
  216.             if (isdigit( chCom = *++lpPtrFormat ))
  217.             {
  218.                ++nWidthSet ;
  219.                nWidth = MUL10( nWidth ) + (chCom - '0') ;
  220.             }
  221.             else
  222.                switch (chCom)
  223.                {
  224.                   case 'F':
  225.                   case 'N':
  226.                      // FAR is only type of pointer in DLLs
  227.                      break ;
  228.    
  229.                   case 'h':
  230.                      ++bCoerceShort ;
  231.                      break ;
  232.             
  233.                   case 'l':
  234.                      ++bLongOne ;
  235.                      break ;
  236.    
  237.                   case '*':
  238.                      ++bSuppress ;
  239.                      break ;
  240.    
  241.                   default:
  242.                      ++bDoneFlag ;
  243.                      break ;
  244.                }
  245.          }
  246.    
  247.          if (!bSuppress)
  248.             /* ALL pointers are pushed as FAR */
  249.             lpPointer = (LPVOID) *lpArgList++ ;
  250.    
  251.          bDoneFlag = FALSE ;
  252.    
  253.          if ('n' != (chCom = (char)(*lpPtrFormat | ('a' - 'A'))))
  254.          {
  255.             if ('c' != chCom && LEFT_BRACKET != chCom)
  256.                ch = EAT_WHITE() ;
  257.             else
  258.                ch = INC() ;
  259.          }
  260.    
  261.          if (!nWidthSet || nWidth)
  262.          {
  263.             switch (chCom)
  264.             {
  265.                case 'c':
  266.                   if (!nWidthSet)
  267.                   {
  268.                      ++nWidthSet ;
  269.                      ++nWidth ;
  270.                   }
  271.                   lpPtrScan = (BYTE FAR *) szCBrackSet  ;
  272.                   --bReject ;
  273.                   goto ScanIt2 ;
  274.    
  275.                case 's':
  276.                   lpPtrScan = (BYTE FAR *) szSBrackSet ;
  277.                   --bReject ;
  278.                   goto ScanIt2 ;
  279.    
  280.                case LEFT_BRACKET:
  281.                   lpPtrScan = (BYTE FAR *) (++lpPtrFormat) ;
  282.                   if ('^' == *lpPtrScan)
  283.                   {
  284.                      ++lpPtrScan ;
  285.                      --bReject ;
  286.                   }
  287. ScanIt2:
  288.                   _fmemset( szTable, 0, ASCII ) ;
  289.    
  290. #ifdef ALLOW_RANGE
  291.                   if (LEFT_BRACKET == chCom)
  292.                      if (']' == *lpPtrScan)
  293.                      {
  294.                         chPrev = ']' ;
  295.                         ++lpPtrScan ;
  296.                         szTable[ ']' >> 3 ] = 1 << (']' & 7 ) ;
  297.                      }
  298.                   while (']' != *lpPtrScan)
  299.                   {
  300.                      chRange = *lpPtrScan++ ;
  301.                      if ('-' != chRange || !chPrev || ']' == *lpPtrScan)
  302.                         szTable[(chPrev = chRange) >> 3] |= 1 << (chRange & 7) ;
  303.                      else
  304.                      {
  305.                         // handle a-z type set
  306.                         chRange = *lpPtrScan++ ;
  307.                         if (chPrev < chRange)
  308.                            chLast = chRange ;
  309.                         else
  310.                         {
  311.                            chLast = chPrev ;
  312.                            chPrev = chRange ;
  313.                         }
  314.                         for (chRange = chPrev; chRange <= chLast; ++chRange)
  315.                            szTable[chRange >> 3] |= 1 << (chRange & 7) ;
  316.                         chPrev = 0 ;
  317.                      }
  318.                   }
  319. #else
  320.                   if (LEFT_BRACKET == chCom)
  321.                      if (']'  == *lpPtrScan)
  322.                      {
  323.                         ++lpPtrScan;
  324.                         szTable[(chPrev = ']') >> 3] |= 1 << (']' & 7) ;
  325.                      }
  326.                   while (']' != *lpPtrScan)
  327.                      szTable[ *lpPtrScan >> 3] |= 1 << (*lpPtrScan & 7) ;
  328. #endif
  329.                   if (!*lpPtrScan)
  330.                      goto ErrorReturn ;
  331.          
  332.                   if (LEFT_BRACKET == chCom)
  333.                      lpPtrFormat = (LPSTR)lpPtrScan ;
  334.             
  335.                   lpStart = lpPointer ;
  336.                   while ((!nWidthSet || nWidth--) &&
  337.                          ((szTable[ ch >> 3 ] ^ bReject) & (1 << (ch & 7))))
  338.                   {
  339.                      if (!bSuppress)
  340.                      {
  341.                         *(LPSTR)lpPointer = (char) ch ;
  342.                         ++((LPSTR&)lpPointer) ;
  343.                      }
  344.                      else
  345.                         // just indicate a match
  346.                         ++((LPSTR&)lpStart) ;
  347.                      ch = INC() ;
  348.                   }
  349.                   UN_INC( ch )  ;
  350.                   // make sure something has been match and, if assignment
  351.                   // is not suppressed, null-terminate output string if
  352.                   // chCom != c
  353.                   if (lpStart != lpPointer)
  354.                   {
  355.                      if (!bSuppress)
  356.                      {
  357.                         nCount++ ;
  358.                         if ('c' != chCom)
  359.                            // NULL terminate strings
  360.                            *(LPSTR) lpPointer = NULL ;
  361.                      }
  362.                   }
  363.                   else
  364.                      goto ErrorReturn ;
  365.                   break ;
  366.                case 'i':
  367.                   chCom = 'd' ;  // use 'd' as default
  368.          
  369.                case 'x':
  370.                   if ('-' == ch)
  371.                   {
  372.                      ++bNegative ;
  373.                      goto XIncWidth ;
  374.                   }
  375.                   else if ('+' == ch)
  376.                   {
  377. XIncWidth:
  378.                      if (!--nWidth && nWidthSet)
  379.                         ++bDoneFlag ;
  380.                      else
  381.                         ch = INC() ;
  382.                   }
  383.                   if ('0' == ch)
  384.                   {
  385.                      if ('x' == ((char) (ch = INC())) || 'X' == (char) ch)
  386.                      {
  387.                         ch = INC() ;
  388.                         chCom = 'x' ;
  389.                      }
  390.                      else
  391.                      {
  392.                         // scanning a hex number that starts with 0
  393.                         // push back the character currently in ch
  394.                         // and restore the 0
  395.    
  396.                         UN_INC( ch ) ;
  397.                         ch = '0' ;
  398.                      }
  399.                   }
  400.                   goto GetNum ;
  401.    
  402.                case 'p':
  403.                   // ALL pointers are FAR
  404.                   if (!bCoerceShort)
  405.                   {
  406.                      ++bLongOne ;
  407.                      chCom = 'F' ;  // indicates FAR
  408.                   }
  409.    
  410.                case 'o':
  411.                case 'u':
  412.                case 'd':
  413.                   if ('-' == ch)
  414.                   {
  415.                      ++bNegative ;
  416.                      goto dIncWidth ;
  417.                   }
  418.                   else if ('+' == ch)
  419.                   {
  420. dIncWidth:
  421.                      if (!--nWidth && nWidthSet)
  422.                         ++bDoneFlag ;
  423.                      else
  424.                         ch = INC() ;
  425.                   }
  426. GetNum:
  427.                   while (!bDoneFlag)
  428.                   {
  429.                      if ('x' == chCom || 'p' == chCom || 'F' == chCom)
  430.                      {
  431.                         if (isxdigit(ch))
  432.                         {
  433.                            dwNumber = (dwNumber << 4) ;
  434.                            ch = HEXTODEC( ch ) ;
  435.                         }
  436.                         else if ('F' == chCom)
  437.                         {
  438.                            if (nStarted)
  439.                            {
  440.                               if (':' == ch)
  441.                               {
  442.                                  wHoldSeg = LOWORD( dwNumber ) ;
  443.                                  dwNumber = 0 ;
  444.                                  nStarted = -1 ;
  445.                                  chCom = 'p' ; // switch to offset
  446.                                  ch = '0' ; // don't add ':'
  447.                               }
  448.                               else
  449.                               {
  450.                                  nStarted = 0 ;
  451.                                  ++bDoneFlag ;
  452.                               }
  453.                            }
  454.                            else
  455.                               ++bDoneFlag ;
  456.                         }
  457.                         else
  458.                            ++bDoneFlag ;
  459.                      }
  460.                      else if (isdigit( ch ))
  461.                      {
  462.                         if ('o' == chCom)
  463.                         {
  464.                            if ('8' > ch)
  465.                               dwNumber = (dwNumber << 3) ;
  466.                            else
  467.                               ++bDoneFlag ;
  468.                         }
  469.                         else
  470.                            // 'd' == chCom
  471.                            dwNumber = MUL10( dwNumber ) ;
  472.                      } 
  473.                      else
  474.                         ++bDoneFlag ;
  475.                      if (!bDoneFlag)
  476.                      {
  477.                         ++nStarted ;
  478.                         dwNumber += ch - '0' ;
  479.                         if (nWidthSet && !--nWidth)
  480.                            ++bDoneFlag ;
  481.                         else
  482.                            ch = INC() ;
  483.                      }
  484.                      else
  485.                         UN_INC( ch ) ;
  486.                   } // end of while
  487.    
  488.                   if ('p' == chCom && bLongOne)
  489.                      dwNumber = (dwNumber & (DWORD) 0x0000FFFF) |
  490.                                  ((DWORD) wHoldSeg) << 16 ;
  491. #if _WIN16   
  492. #pragma warning(disable : 4146) 
  493. #endif   
  494.                   if (bNegative)
  495.                      dwNumber = -dwNumber ;
  496. #if _WIN16   
  497. #pragma warning(default : 4146) 
  498. #endif
  499.                   if ('F' == chCom)
  500.                      nStarted = 0 ;
  501.                   if (nStarted)
  502.                   {
  503.                      if (!bSuppress)
  504.                      {
  505.                         ++nCount ;
  506. AssignNum:
  507.                         if (bLongOne)
  508.                            *(DWORD FAR *)lpPointer = dwNumber ;
  509.                         else
  510.                            *(WORD FAR *)lpPointer = LOWORD( dwNumber ) ;
  511.                      }
  512.                   }
  513.                   else
  514.                      goto ErrorReturn ;
  515.    
  516.                   break ;
  517.    
  518.                case 'n':
  519.                   dwNumber = nCharCount ;
  520.                   goto AssignNum ;
  521.    
  522.                default:
  523.                   if ((char)*lpPtrFormat != ch)
  524.                   {
  525.                      UN_INC( ch ) ;
  526.                      goto ErrorReturn ;
  527.                   }
  528.                   else
  529.                      bMatch-- ;
  530.    
  531.                   if (!bSuppress)
  532.                      // ALL pointers are FAR pointers
  533.                      --lpArgList ;
  534.    
  535.             } // end of switch
  536.             bMatch++ ;
  537.          } // end of while
  538.          else
  539.          {
  540.             UN_INC( ch ) ;
  541.             goto ErrorReturn ;
  542.          }
  543.          ++lpPtrFormat ;
  544.       }
  545.       else
  546.       {
  547.          // ('%' != *lpPtrFormat)
  548.          if ((char) *lpPtrFormat++ != (ch = INC()))
  549.          {
  550.             UN_INC( ch ) ;
  551.             goto ErrorReturn ;
  552.          }
  553.       }
  554.    } // end while (*lpPtrFormat)
  555. ErrorReturn:
  556.    wva_end(lpParms);
  557.    return nCount ;
  558. } /* end of wsscanf() */
  559. #endif // _WIN16
  560.  /*
  561.  * Internal structure of universal unique IDs (UUIDs).
  562.  *
  563.  * There are three "variants" of UUIDs that this code knows about.  The
  564.  * variant #0 is what was defined in the 1989 HP/Apollo Network Computing
  565.  * Architecture (NCA) specification and implemented in NCS 1.x and DECrpc
  566.  * v1.  Variant #1 is what was defined for the joint HP/DEC specification
  567.  * for the OSF (in DEC's "UID Architecture Functional Specification Version
  568.  * X1.0.4") and implemented in NCS 2.0, DECrpc v2, and OSF 1.0 DCE RPC.
  569.  * Variant #2 is defined by Microsoft.
  570.  *
  571.  * This code creates only variant #1 UUIDs.
  572.  * 
  573.  * The three UUID variants can exist on the same wire because they have
  574.  * distinct values in the 3 MSB bits of octet 8 (see table below).  Do
  575.  * NOT confuse the version number with these 3 bits.  (Note the distinct
  576.  * use of the terms "version" and "variant".) Variant #0 had no version
  577.  * field in it.  Changes to variant #1 (should any ever need to be made)
  578.  * can be accomodated using the current form's 4 bit version field.
  579.  * 
  580.  * The UUID record structure MUST NOT contain padding between fields.
  581.  * The total size = 128 bits.
  582.  *
  583.  * To minimize confusion about bit assignment within octets, the UUID
  584.  * record definition is defined only in terms of fields that are integral
  585.  * numbers of octets.
  586.  *
  587.  * Depending on the network data representation, the multi-octet unsigned
  588.  * integer fields are subject to byte swapping when communicated between
  589.  * dissimilar endian machines.  Note that all three UUID variants have
  590.  * the same record structure; this allows this byte swapping to occur.
  591.  * (The ways in which the contents of the fields are generated can and
  592.  * do vary.)
  593.  *
  594.  * The following information applies to variant #1 UUIDs:
  595.  *
  596.  * The lowest addressed octet contains the global/local bit and the
  597.  * unicast/multicast bit, and is the first octet of the address transmitted
  598.  * on an 802.3 LAN.
  599.  *
  600.  *  NOTE:  In the PN version the node field may not be the 802.3 NIC ID
  601.  * But is a machine ID generated on construction if not specified.
  602.  * The method for generating the machine ID may vary and is documented
  603.  * in the GenerateMachineID method.
  604.  *
  605.  * The adjusted time stamp is split into three fields, and the clockSeq
  606.  * is split into two fields.
  607.  *
  608.  * |<------------------------- 32 bits -------------------------->|
  609.  *
  610.  * +--------------------------------------------------------------+
  611.  * |                     low 32 bits of time                      |  0-3  .time_low
  612.  * +-------------------------------+-------------------------------
  613.  * |     mid 16 bits of time       |  4-5               .time_mid
  614.  * +-------+-----------------------+
  615.  * | vers. |   hi 12 bits of time  |  6-7               .time_hi_and_version
  616.  * +-------+-------+---------------+
  617.  * |Res|  clkSeqHi |  8                                 .clock_seq_hi_and_reserved
  618.  * +---------------+
  619.  * |   clkSeqLow   |  9                                 .clock_seq_low
  620.  * +---------------+----------...-----+
  621.  * |            node ID               |  8-16           .node
  622.  * +--------------------------...-----+
  623.  *
  624.  * --------------------------------------------------------------------------
  625.  *
  626.  * The structure layout of all three UUID variants is fixed for all time.
  627.  * I.e., the layout consists of a 32 bit int, 2 16 bit ints, and 8 8
  628.  * bit ints.  The current form version field does NOT determine/affect
  629.  * the layout.  This enables us to do certain operations safely on the
  630.  * variants of UUIDs without regard to variant; this increases the utility
  631.  * of this code even as the version number changes (i.e., this code does
  632.  * NOT need to check the version field).
  633.  *
  634.  * The "Res" field in the octet #8 is the so-called "reserved" bit-field
  635.  * and determines whether or not the uuid is a old, current or other
  636.  * UUID as follows:
  637.  *
  638.  *      MS-bit  2MS-bit  3MS-bit      Variant
  639.  *      ---------------------------------------------
  640.  *         0       x        x       0 (NCS 1.5)
  641.  *         1       0        x       1 (DCE 1.0 RPC)
  642.  *         1       1        0       2 (Microsoft)
  643.  *         1       1        1       unspecified
  644.  *
  645.  *  NOTE:   To identify the PN version from other versions we use the 
  646.  * 111 unspecified variant.
  647.  *
  648.  * --------------------------------------------------------------------------
  649.  *
  650.  */
  651. /****************************************************************************
  652.  *
  653.  * global data declarations
  654.  *
  655.  ****************************************************************************/
  656. static const uuid_tt uuid_g_nil_uuid = { 0, 0, 0, 0, 0, 0 };
  657. static const uuid_tt uuid_nil = { 0, 0, 0, 0, 0, 0 };
  658. /*
  659.  * Check the reserved bits to make sure the UUID is of the known structure.
  660.  */
  661. /*
  662.  * defines for time calculations
  663.  */
  664. #ifndef UUID_C_100NS_PER_SEC
  665. #define UUID_C_100NS_PER_SEC            10000000
  666. #endif
  667. #ifndef UUID_C_100NS_PER_MSEC
  668. #define UUID_C_100NS_PER_MSEC           10000
  669. #endif
  670. #define HX_GET_PID() 0xC0C0
  671.  /*
  672.  * UADD_UVLW_2_UVLW - macro to add two unsigned 64-bit long integers
  673.  *                      (ie. add two unsigned 'very' long words)
  674.  *
  675.  * Important note: It is important that this macro accommodate (and it does)
  676.  *                 invocations where one of the addends is also the sum.
  677.  *
  678.  * This macro was snarfed from the DTSS group and was originally:
  679.  *
  680.  * UTCadd - macro to add two UTC times
  681.  *
  682.  * add lo and high order longword separately, using sign bits of the low-order
  683.  * longwords to determine carry.  sign bits are tested before addition in two
  684.  * cases - where sign bits match. when the addend sign bits differ the sign of
  685.  * the result is also tested:
  686.  *
  687.  *        sign            sign
  688.  *      addend 1        addend 2        carry?
  689.  *
  690.  *          1               1            TRUE
  691.  *          1               0            TRUE if sign of sum clear
  692.  *          0               1            TRUE if sign of sum clear
  693.  *          0               0            FALSE
  694.  */
  695. #define UADD_UVLW_2_UVLW(add1, add2, sum)                               
  696.     if (!(((add1)->lo&0x80000000UL) ^ ((add2)->lo&0x80000000UL)))           
  697.     {                                                                   
  698.         if (((add1)->lo&0x80000000UL))                                    
  699.         {                                                               
  700.             (sum)->lo = (add1)->lo + (add2)->lo ;                       
  701.             (sum)->hi = (add1)->hi + (add2)->hi+1 ;                     
  702.         }                                                               
  703.         else                                                            
  704.         {                                                               
  705.             (sum)->lo  = (add1)->lo + (add2)->lo ;                      
  706.             (sum)->hi = (add1)->hi + (add2)->hi ;                       
  707.         }                                                               
  708.     }                                                                   
  709.     else                                                                
  710.     {                                                                   
  711.         (sum)->lo = (add1)->lo + (add2)->lo ;                           
  712.         (sum)->hi = (add1)->hi + (add2)->hi ;                           
  713.         if (!((sum)->lo&0x80000000UL))                                    
  714.             (sum)->hi++ ;                                               
  715.     }
  716. /*
  717.  * UADD_ULW_2_UVLW - macro to add a 32-bit unsigned integer to
  718.  *                   a 64-bit unsigned integer
  719.  *
  720.  * Note: see the UADD_UVLW_2_UVLW() macro
  721.  *
  722.  */
  723. #define UADD_ULW_2_UVLW(add1, add2, sum)                                
  724. {                                                                       
  725.     (sum)->hi = (add2)->hi;                                             
  726.     if ((*add1) & (add2)->lo & 0x80000000UL)                              
  727.     {                                                                   
  728.         (sum)->lo = (*add1) + (add2)->lo;                               
  729.         (sum)->hi++;                                                    
  730.     }                                                                   
  731.     else                                                                
  732.     {                                                                   
  733.         (sum)->lo = (*add1) + (add2)->lo;                               
  734.         if (!((sum)->lo & 0x80000000UL))                                  
  735.         {                                                               
  736.             (sum)->hi++;                                                
  737.         }                                                               
  738.     }                                                                   
  739. }
  740. /*
  741.  * UADD_UW_2_UVLW - macro to add a 16-bit unsigned integer to
  742.  *                   a 64-bit unsigned integer
  743.  *
  744.  * Note: see the UADD_UVLW_2_UVLW() macro
  745.  *
  746.  */
  747. #define UADD_UW_2_UVLW(add1, add2, sum)                                 
  748. {                                                                       
  749.     (sum)->hi = (add2)->hi;                                             
  750.     if ((add2)->lo & 0x80000000UL)                                        
  751.     {                                                                   
  752.         (sum)->lo = (*add1) + (add2)->lo;                               
  753.         if (!((sum)->lo & 0x80000000UL))                                  
  754.         {                                                               
  755.             (sum)->hi++;                                                
  756.         }                                                               
  757.     }                                                                   
  758.     else                                                                
  759.     {                                                                   
  760.         (sum)->lo = (*add1) + (add2)->lo;                               
  761.     }                                                                   
  762. }
  763. CHXuuid::CHXuuid()
  764. {
  765.     uuid_ttime_t         t;
  766.     UINT16          *seedp, seed=0;
  767.     /*
  768.      * Generating our 'seed' value
  769.      *
  770.      * We start with the current time, but, since the resolution of clocks is
  771.      * system hardware dependent (eg. Ultrix is 10 msec.) and most likely
  772.      * coarser than our resolution (10 usec) we 'mixup' the bits by xor'ing
  773.      * all the bits together.  This will have the effect of involving all of
  774.      * the bits in the determination of the seed value while remaining system
  775.      * independent.  Then for good measure to ensure a unique seed when there
  776.      * are multiple processes creating UUID's on a system, we add in the PID.
  777.      */
  778.     GetOSTime(&t);
  779.     seedp = (UINT16 *)(&t);
  780.     seed ^= *seedp++;
  781.     seed ^= *seedp++;
  782.     seed ^= *seedp++;
  783.     seed ^= *seedp++;
  784.     seed += HX_GET_PID();
  785.     /*
  786.      * init the random number generator
  787.      */
  788.     m_pRand = new CMultiplePrimeRandom(seed);
  789.     GetOSTime (&m_time_last);
  790.     m_time_adjust = 0;
  791.     m_clock_seq = TrueRandom();
  792.     GenerateMachineID();
  793. }
  794. CHXuuid::CHXuuid(UCHAR machineID[MACHINEID_SIZE])
  795. {
  796.     uuid_ttime_t         t;
  797.     UINT16          *seedp, seed=0;
  798.     /*
  799.      * Generating our 'seed' value
  800.      *
  801.      * We start with the current time, but, since the resolution of clocks is
  802.      * system hardware dependent (eg. Ultrix is 10 msec.) and most likely
  803.      * coarser than our resolution (10 usec) we 'mixup' the bits by xor'ing
  804.      * all the bits together.  This will have the effect of involving all of
  805.      * the bits in the determination of the seed value while remaining system
  806.      * independent.  Then for good measure to ensure a unique seed when there
  807.      * are multiple processes creating UUID's on a system, we add in the PID.
  808.      */
  809.     GetOSTime(&t);
  810.     seedp = (UINT16 *)(&t);
  811.     seed ^= *seedp++;
  812.     seed ^= *seedp++;
  813.     seed ^= *seedp++;
  814.     seed ^= *seedp++;
  815.     seed += HX_GET_PID();
  816.     /*
  817.      * init the random number generator
  818.      */
  819.     m_pRand = new CMultiplePrimeRandom(seed);
  820.     GetOSTime (&m_time_last);
  821.     m_time_adjust = 0;
  822.     m_clock_seq = TrueRandom();
  823.     memcpy(m_machineID, machineID, sizeof(machineID)); /* Flawfinder: ignore */
  824. }
  825. CHXuuid::~CHXuuid()
  826. {
  827.     if (m_pRand != NULL)
  828.     {
  829. delete m_pRand;
  830.     }
  831. }
  832. //
  833. // Changed this routine to avoid unaligned access errors on RISC
  834. // processors. -dbrumley 10-15-98 
  835. //
  836. void CHXuuid::GenerateMachineID()
  837. {
  838.     ULONG32 rand;
  839.     UINT16  tick;
  840.     rand = m_pRand->GetRandomNumber();
  841.     tick = (UINT16)HX_GET_TICKCOUNT();
  842.     memcpy(m_machineID, (UCHAR*)&rand, sizeof rand); /* Flawfinder: ignore */
  843.     memcpy(&m_machineID[4], (UCHAR*)&tick, sizeof tick); /* Flawfinder: ignore */
  844. }
  845. /////////////////////////////////////////////////////////////////////////
  846. // Method:
  847. // CHXuuid::GetUuid
  848. // Purpose:
  849. //      Loose implementation of version 3 UUID (creation of name-based UUID).  This
  850. //      algorithm outputs the result of an MD5 hash of an internally generated 
  851. //      namespace (GUID) and a name (input buffer).  Unlike the version 3 UUID algorithm, 
  852. //      the namespace is essentially generated at random, so UUIDs created from 
  853. //      the same name at any point of time have a very high probability of being different.
  854. HX_RESULT CHXuuid::GetUuid(uuid_tt* pUuid, const UCHAR* pBuffer, UINT32 ulBufferSize)
  855. {
  856.     // Validate params
  857.     HX_ASSERT(pUuid && pBuffer && ulBufferSize);
  858.     if (!pUuid || !pBuffer || !ulBufferSize)
  859.         return HXR_INVALID_PARAMETER;
  860.     
  861.     // Get a UUID to use as a namespace ID
  862.     HX_RESULT res = GetUuid(pUuid);
  863.     
  864.     if (SUCCEEDED(res))
  865.     {
  866.         md5_state_t ctx;
  867.         md5_init(&ctx);
  868.         UCHAR aHashBuffer[20];
  869.         memset(aHashBuffer, 0, 20);
  870.         // MD5-hash the namespace ID with the name buffer
  871.         md5_append(&ctx, (const UCHAR*)pUuid, sizeof(uuid_tt));
  872.         md5_append(&ctx, (const UCHAR*)pBuffer, ulBufferSize);                
  873.         md5_finish(aHashBuffer, &ctx);
  874.         // Copy the 128-bit hash result into the UUID.  Memcpy one var at a time
  875.         // in case the struct is padded.
  876.         memcpy(&pUuid->time_low, aHashBuffer, sizeof(pUuid->time_low)); /* Flawfinder: ignore */
  877.         memcpy(&pUuid->time_mid, aHashBuffer+4, sizeof(pUuid->time_mid)); /* Flawfinder: ignore */
  878.         memcpy(&pUuid->time_hi_and_version, aHashBuffer+6, sizeof(pUuid->time_hi_and_version)); /* Flawfinder: ignore */
  879.         memcpy(&pUuid->clock_seq_hi_and_reserved, aHashBuffer+8, sizeof(pUuid->clock_seq_hi_and_reserved)); /* Flawfinder: ignore */
  880.         memcpy(&pUuid->clock_seq_low, aHashBuffer+9, sizeof(pUuid->clock_seq_low)); /* Flawfinder: ignore */
  881.         memcpy(&pUuid->node, aHashBuffer+10, sizeof(pUuid->node)); /* Flawfinder: ignore */
  882.     }
  883.     return res;
  884. }
  885. HX_RESULT CHXuuid::GetUuid(uuid_tt* uuid)
  886. {
  887.     HX_RESULT theErr = HXR_OK;
  888. #if defined(_WIN32) && !defined(WIN32_PLATFORM_PSPC)
  889.     if(CoCreateGuid((GUID*)uuid) != S_OK)
  890. theErr = HXR_FAILED;
  891. #else
  892.     BOOL got_no_time = FALSE;
  893.     do
  894.     {
  895.         /*
  896.          * get the current time
  897.          */
  898.         GetOSTime (&m_time_now);
  899.         /*
  900.          * do stuff like:
  901.          *
  902.          *  o check that our clock hasn't gone backwards and handle it
  903.          *    accordingly with clock_seq
  904.          *  o check that we're not generating uuid's faster than we
  905.          *    can accommodate with our time_adjust fudge factor
  906.          */
  907.         switch (TimeCmp(&m_time_now, &m_time_last))
  908.         {
  909.             case uuid_e_less_than:
  910.                 NewClockSeq(m_clock_seq);
  911.                 m_time_adjust = 0;
  912. got_no_time = FALSE;
  913.                 break;
  914.             case uuid_e_greater_than:
  915.                 m_time_adjust = 0;
  916. got_no_time = FALSE;
  917.                 break;
  918.             case uuid_e_equal_to:
  919.                 if (m_time_adjust == MAX_TIME_ADJUST)
  920.                 {
  921.                     /*
  922.                      * spin your wheels while we wait for the clock to tick
  923.                      */
  924.                     got_no_time = TRUE;
  925.                 }
  926.                 else
  927.                 {
  928.                     m_time_adjust++;
  929.     got_no_time = FALSE;
  930.                 }
  931.                 break;
  932.             default:
  933.                 theErr = HXR_FAILED;
  934.                 return theErr;
  935.         }
  936.     } while (got_no_time);
  937.     m_time_last.lo = m_time_now.lo;
  938.     m_time_last.hi = m_time_now.hi;
  939.     if (m_time_adjust != 0)
  940.     {
  941.         UADD_UW_2_UVLW (&m_time_adjust, &m_time_now, &m_time_now);
  942.     }
  943.     /*
  944.      * now construct a uuid with the information we've gathered
  945.      * plus a few constants
  946.      */
  947.     uuid->time_low = m_time_now.lo;
  948.     uuid->time_mid = (UINT16)(m_time_now.hi & TIME_MID_MASK);
  949.     uuid->time_hi_and_version = (UINT16)
  950.         ((m_time_now.hi & TIME_HIGH_MASK) >> TIME_HIGH_SHIFT_COUNT);
  951.     uuid->time_hi_and_version |= UUID_VERSION_BITS;
  952.     uuid->clock_seq_low = HX_SAFEINT(m_clock_seq & CLOCK_SEQ_LOW_MASK);
  953.     uuid->clock_seq_hi_and_reserved =
  954.         HX_SAFEINT((m_clock_seq & CLOCK_SEQ_HIGH_MASK) >> CLOCK_SEQ_HIGH_SHIFT_COUNT);
  955.     uuid->clock_seq_hi_and_reserved |= UUID_RESERVED_BITS;
  956.     memcpy (uuid->node, m_machineID, sizeof (m_machineID)); /* Flawfinder: ignore */
  957. #endif // _WIN32
  958.     return theErr;
  959. }
  960. /*
  961. **++
  962. **
  963. **  ROUTINE NAME:       uuid_to_string
  964. **
  965. **--
  966. **/
  967. HX_RESULT CHXuuid::HXUuidToString(const uuid_tt* uuid, CHXString* uuid_string)
  968. {
  969.     HX_RESULT theErr = HXR_OK;
  970.     /*
  971.      * don't do anything if the output argument is NULL
  972.      */
  973.     if (uuid_string == NULL)
  974.     {
  975.         return theErr;
  976.     }
  977.     char *theBuff = uuid_string->GetBuffer(UUID_C_UUID_STRING_MAX);
  978.     SafeSprintf(theBuff, UUID_C_UUID_STRING_MAX,
  979.                 "%.4x%.4x-%.4x-%.4x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x",
  980. HIWORD(uuid->time_low), LOWORD(uuid->time_low), uuid->time_mid, 
  981. uuid->time_hi_and_version, uuid->clock_seq_hi_and_reserved, uuid->clock_seq_low,
  982. (UCHAR) uuid->node[0], (UCHAR) uuid->node[1],
  983. (UCHAR) uuid->node[2], (UCHAR) uuid->node[3],
  984. (UCHAR) uuid->node[4], (UCHAR) uuid->node[5]);
  985.     uuid_string->ReleaseBuffer();
  986.     return theErr;
  987. }
  988. /*
  989. **++
  990. **
  991. **  ROUTINE NAME:       uuid_from_string
  992. **
  993. **--
  994. **/
  995. static int ParseIIDString(
  996.     const char* uuid_string,
  997.     long&       time_low,
  998.     int&        time_mid,
  999.     int&        time_hi_and_version,
  1000.     int&        clock_seq_hi_and_reserved,
  1001.     int&        clock_seq_low,
  1002.     int*        node /*[6]*/)
  1003. {
  1004.     int count = 0;
  1005. #if defined(_OPENWAVE)
  1006. // XXXSAB Untested...
  1007.     // No sscanf()...
  1008.     const char* pCur = uuid_string;
  1009.     char* pEnd = NULL;
  1010.     unsigned long curVal;
  1011.     // Skip leading white space
  1012.     pCur += strspn(pCur, " t");
  1013.     curVal = strtoul(pCur, &pEnd, 16);
  1014.     if (pEnd == (pCur + 8) && *pEnd == '-') time_low = curVal;
  1015.     else return count;
  1016.     pCur += 8; ++count;
  1017.     curVal = strtoul(pCur, &pEnd, 16);
  1018.     if (pEnd == (pCur + 4) && *pEnd == '-') time_mid = curVal;
  1019.     else return count;
  1020.     pCur += 4; ++count;
  1021.     curVal = strtoul(pCur, &pEnd, 16);
  1022.     if (pEnd == (pCur + 4) && *pEnd == '-') time_hi_and_version = curVal;
  1023.     else return count;
  1024.     pCur += 4; ++count;
  1025.     curVal = strtoul(pCur, &pEnd, 16);
  1026.     if (pEnd == (pCur + 4) && *pEnd == '-')
  1027.     {
  1028.         clock_seq_hi_and_reserved = (curVal & 0xff00) >> 8;
  1029.         clock_seq_low = curVal & 0xff;
  1030.     }
  1031.     else return count;
  1032.     pCur += 4; count += 2;
  1033.     curVal = strtoul(pCur, &pEnd, 16);
  1034.     if (pEnd == (pCur + 6) && *(pEnd+strspn(pEnd, " t")) == 0)
  1035.     {
  1036.         for (int i = 5; i >= 0; ++i, curVal = curVal >> 8)
  1037.         {
  1038.             node[i] = curVal & 0xff;
  1039.         }
  1040.     }
  1041.     else return count;
  1042.     pCur += 4; count += 6;
  1043. #else
  1044.     count = sscanf(uuid_string, "%8lx-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
  1045.                    &time_low,
  1046.                    &time_mid,
  1047.                    &time_hi_and_version,
  1048.                    &clock_seq_hi_and_reserved,
  1049.                    &clock_seq_low,
  1050.                    &node[0], &node[1], &node[2], &node[3], &node[4], &node[5]);
  1051. #endif
  1052.     return count;
  1053. }
  1054. HX_RESULT CHXuuid::HXUuidFromString(const char* uuid_string, uuid_tt* uuid)
  1055. {
  1056.     HX_RESULT theErr = HXR_OK;
  1057.     uuid_tt             uuid_new;       /* used for sscanf for new uuid's */
  1058.     uuid_p_t            uuid_ptr=0;     /* pointer to correct uuid (old/new) */
  1059.     int                 i;
  1060.     /*
  1061.      * If a NULL pointer or empty string, give the nil UUID.
  1062.      */
  1063.     if (uuid_string == NULL || *uuid_string == '')
  1064.     {
  1065. memcpy (uuid, &uuid_g_nil_uuid, sizeof *uuid); /* Flawfinder: ignore */
  1066. return theErr;
  1067.     }
  1068.     /*
  1069.      * check to see that the string length is right at least
  1070.      */
  1071.     if (strlen ((char *) uuid_string) != UUID_C_UUID_STRING_MAX - 1)
  1072.     {
  1073.         theErr = HXR_FAILED;
  1074.         return theErr;
  1075.     }
  1076.     /*
  1077.      * check for a new uuid
  1078.      */
  1079.     if (uuid_string[8] == '-')
  1080.     {
  1081.         long    time_low;
  1082.         int     time_mid;
  1083.         int     time_hi_and_version;
  1084.         int     clock_seq_hi_and_reserved;
  1085.         int     clock_seq_low;
  1086.         int     node[6];
  1087. // VC1.5's runtime library(lddcew.lib) doesn't have sscanf()!!
  1088. #if defined(_WIN16)
  1089. i = wsscanf((char *) uuid_string, "%8lx-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
  1090.     (long FAR *)&time_low,
  1091.     (int FAR *)&time_mid,
  1092.     (int FAR *)&time_hi_and_version,
  1093.     (int FAR *)&clock_seq_hi_and_reserved,
  1094.     (int FAR *)&clock_seq_low,
  1095.     (int FAR *)&node[0], (int FAR *)&node[1], (int FAR *)&node[2], 
  1096.     (int FAR *)&node[3], (int FAR *)&node[4], (int FAR *)&node[5]);
  1097. #else
  1098.         i = ParseIIDString(
  1099.             uuid_string,
  1100.             time_low,
  1101.             time_mid,
  1102.             time_hi_and_version,
  1103.             clock_seq_hi_and_reserved,
  1104.             clock_seq_low,
  1105.             node);
  1106. #ifdef Commented_out_code_20030421_114057
  1107.         i = sscanf((char *) uuid_string, "%8lx-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
  1108.             &time_low,
  1109.             &time_mid,
  1110.             &time_hi_and_version,
  1111.             &clock_seq_hi_and_reserved,
  1112.             &clock_seq_low,
  1113.             &node[0], &node[1], &node[2], &node[3], &node[4], &node[5]);
  1114. #endif /* Commented_out_code_20030421_114057 */
  1115. #endif
  1116.         /*
  1117.          * check that sscanf worked
  1118.          */
  1119.         if (i != UUID_ELEMENTS_NUM)
  1120.         {
  1121.             theErr = HXR_FAILED;
  1122.             return theErr;
  1123.         }
  1124.         /*
  1125.          * note that we're going through this agony because scanf is defined to
  1126.          * know only to scan into "int"s or "long"s.
  1127.          */
  1128.         uuid_new.time_low                   = time_low;
  1129.         uuid_new.time_mid                   = time_mid;
  1130.         uuid_new.time_hi_and_version        = time_hi_and_version;
  1131.         uuid_new.clock_seq_hi_and_reserved  = clock_seq_hi_and_reserved;
  1132.         uuid_new.clock_seq_low              = clock_seq_low;
  1133.         uuid_new.node[0]                    = node[0];
  1134.         uuid_new.node[1]                    = node[1];
  1135.         uuid_new.node[2]                    = node[2];
  1136.         uuid_new.node[3]                    = node[3];
  1137.         uuid_new.node[4]                    = node[4];
  1138.         uuid_new.node[5]                    = node[5];
  1139.         /*
  1140.          * point to the correct uuid
  1141.          */
  1142.         uuid_ptr = &uuid_new;
  1143.     }
  1144.     /*
  1145.      * copy the uuid to user
  1146.      */
  1147.     memcpy(uuid, uuid_ptr, sizeof (uuid_tt)); /* Flawfinder: ignore */
  1148.     return theErr;
  1149. }
  1150. /*
  1151. **++
  1152. **
  1153. **  ROUTINE NAME:       uuid_from_string
  1154. **
  1155. **--
  1156. **/
  1157. HX_RESULT CHXuuid::HXPack(UINT8* pBuffer, uuid_p_t uuid)
  1158. {
  1159.     uuid_p_t uuidPacket = (uuid_p_t) pBuffer;
  1160.     *uuidPacket = *uuid;
  1161.     uuidPacket->time_low = DwToNet(uuid->time_low);
  1162.     uuidPacket->time_mid = WToNet(uuid->time_mid);
  1163.     uuidPacket->time_hi_and_version = WToNet(uuid->time_hi_and_version);
  1164.     return HXR_OK;
  1165. }
  1166. /*
  1167. **++
  1168. **
  1169. **  ROUTINE NAME:       uuid_from_string
  1170. **
  1171. **--
  1172. **/
  1173. HX_RESULT CHXuuid::HXUnpack(uuid_p_t uuid, UINT8* pBuffer)
  1174. {
  1175.     uuid_p_t uuidPacket = (uuid_p_t) pBuffer;
  1176.     *uuid = *uuidPacket;
  1177.     uuid->time_low = DwToHost(uuidPacket->time_low);
  1178.     uuid->time_mid = WToHost(uuidPacket->time_mid);
  1179.     uuid->time_hi_and_version = WToHost(uuidPacket->time_hi_and_version);
  1180.     return HXR_OK;
  1181. }
  1182. /*
  1183. **++
  1184. **
  1185. **  ROUTINE NAME:       uuid_equal
  1186. **
  1187. **--
  1188. **/
  1189. BOOL CHXuuid::HXIsEqual(uuid_p_t uuid1, uuid_p_t uuid2)
  1190. {
  1191.     /*
  1192.      * Note: This used to be a memcmp(), but changed to a field-by-field compare
  1193.      * because of portability problems with alignment and garbage in a UUID.
  1194.      */
  1195.     if ((uuid1->time_low == uuid2->time_low) && 
  1196. (uuid1->time_mid == uuid2->time_mid) &&
  1197. (uuid1->time_hi_and_version == uuid2->time_hi_and_version) && 
  1198. (uuid1->clock_seq_hi_and_reserved == uuid2->clock_seq_hi_and_reserved) &&
  1199. (uuid1->clock_seq_low == uuid2->clock_seq_low) &&
  1200. (memcmp(uuid1->node, uuid2->node, 6) == 0))
  1201.     {
  1202. return ( TRUE );
  1203.     }
  1204.     else
  1205.     {
  1206.         return (FALSE);
  1207.     }
  1208. }
  1209. /*****************************************************************************
  1210.  *
  1211.  *  LOCAL MATH PROCEDURES - math procedures used internally by the UUID module
  1212.  *
  1213.  ****************************************************************************/
  1214. /*
  1215. ** T I M E _ C M P
  1216. **
  1217. ** Compares two UUID times (64-bit UTC values)
  1218. **/
  1219. uuid_compval_t CHXuuid::TimeCmp(uuid_ttime_p_t time1, uuid_ttime_p_t time2)
  1220. {
  1221.     /*
  1222.      * first check the hi parts
  1223.      */
  1224.     if (time1->hi < time2->hi) return (uuid_e_less_than);
  1225.     if (time1->hi > time2->hi) return (uuid_e_greater_than);
  1226.     /*
  1227.      * hi parts are equal, check the lo parts
  1228.      */
  1229.     if (time1->lo < time2->lo) return (uuid_e_less_than);
  1230.     if (time1->lo > time2->lo) return (uuid_e_greater_than);
  1231.     return (uuid_e_equal_to);
  1232. }
  1233. /*
  1234. **  UnsignedExtendedMultiply
  1235. **
  1236. **  Functional Description:
  1237. **        32-bit unsigned quantity * 32-bit unsigned quantity
  1238. **        producing 64-bit unsigned result. This routine assumes
  1239. **        long's contain at least 32 bits. It makes no assumptions
  1240. **        about byte orderings.
  1241. **
  1242. **  Inputs:
  1243. **
  1244. **        u, v       Are the numbers to be multiplied passed by value
  1245. **
  1246. **  Outputs:
  1247. **
  1248. **        prodPtr    is a pointer to the 64-bit result
  1249. **
  1250. **  Note:
  1251. **        This algorithm is taken from: "The Art of Computer
  1252. **        Programming", by Donald E. Knuth. Vol 2. Section 4.3.1
  1253. **        Pages: 253-255.
  1254. **--
  1255. **/
  1256. void CHXuuid::UnsignedExtendedMultiply(ULONG32 u,ULONG32 v, unsigned64_t* prodPtr)
  1257. {
  1258.     /*
  1259.      * following the notation in Knuth, Vol. 2
  1260.      */
  1261.     ULONG32      uuid1, uuid2, v1, v2, temp;
  1262.     uuid1 = u >> 16;
  1263.     uuid2 = u & 0xffff;
  1264.     v1 = v >> 16;
  1265.     v2 = v & 0xffff;
  1266.     temp = uuid2 * v2;
  1267.     prodPtr->lo = temp & 0xffff;
  1268.     temp = uuid1 * v2 + (temp >> 16);
  1269.     prodPtr->hi = temp >> 16;
  1270.     temp = uuid2 * v1 + (temp & 0xffff);
  1271.     prodPtr->lo += (temp & 0xffff) << 16;
  1272.     prodPtr->hi += uuid1 * v1 + (temp >> 16);
  1273. }
  1274. UINT16 CHXuuid::TrueRandom()
  1275. {
  1276.     ULONG32 nRand = m_pRand->GetRandomNumber(); 
  1277.     return (UINT16)(HI_WORD(nRand) ^ (nRand & RAND_MASK));
  1278. }
  1279. /*****************************************************************************
  1280.  *
  1281.  *  LOCAL PROCEDURES - procedures used staticly by the UUID module
  1282.  *
  1283.  ****************************************************************************/
  1284. /*
  1285. ** N E W _ C L O C K _ S E Q
  1286. **
  1287. ** Ensure *clkseq is up-to-date
  1288. **
  1289. ** Note: clock_seq is architected to be 14-bits (unsigned) but
  1290. **       I've put it in here as 16-bits since there isn't a
  1291. **       14-bit unsigned integer type (yet)
  1292. **/
  1293. void CHXuuid::NewClockSeq(UINT16& clkseq)
  1294. {
  1295.     /*
  1296.      * A clkseq value of 0 indicates that it hasn't been initialized.
  1297.      */
  1298.     if (clkseq == 0)
  1299.     {
  1300.         /*
  1301.          * with a volatile clock, we always init to a random number
  1302.          */
  1303.         clkseq = (UINT16) m_pRand->GetRandomNumber();
  1304.     }
  1305.     CLOCK_SEQ_BUMP (&clkseq);
  1306.     if (clkseq == 0)
  1307.     {
  1308.         clkseq = clkseq + 1;
  1309.     }
  1310. }
  1311. /*
  1312.  *  Define constant designation difference in Unix and DTSS base times:
  1313.  *  DTSS UTC base time is October 15, 1582.
  1314.  *  Unix base time is January 1, 1970.
  1315.  */
  1316. #define uuid_c_os_base_time_diff_lo     0x13814000
  1317. #define uuid_c_os_base_time_diff_hi     0x01B21DD2
  1318. /*
  1319.  * U U I D _ _ G E T _ O S _ T I M E
  1320.  *
  1321.  * Get OS time - contains platform-specific code.
  1322.  */
  1323.  
  1324. void CHXuuid::GetOSTime(uuid_ttime_t * uuid_ttime)
  1325. {
  1326.     HXTime tv;
  1327.     unsigned64_t        utc,
  1328.                         usecs,
  1329.                         os_basetime_diff;
  1330.     /*
  1331.      * Fill out the HXTime struct with the current time
  1332.      */
  1333.     gettimeofday(&tv, NULL);
  1334.     /*
  1335.      * Multiply the number of seconds by the number clunks 
  1336.      */
  1337.     UnsignedExtendedMultiply ((long) tv.tv_sec, UUID_C_100NS_PER_SEC, &utc);
  1338.     /*
  1339.      * Multiply the number of milliseconds by the number clunks 
  1340.      * and add to the seconds
  1341.      */
  1342.     UnsignedExtendedMultiply ((long) tv.tv_usec / 1000, UUID_C_100NS_PER_MSEC, &usecs);
  1343.     UADD_UVLW_2_UVLW (&usecs, &utc, &utc);
  1344.     /*
  1345.      * Offset between DTSS formatted times and Unix formatted times.
  1346.      */
  1347.     os_basetime_diff.lo = uuid_c_os_base_time_diff_lo;
  1348.     os_basetime_diff.hi = uuid_c_os_base_time_diff_hi;
  1349.     UADD_UVLW_2_UVLW (&utc, &os_basetime_diff, uuid_ttime);
  1350. }