chxuuid.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:49k
源码类别:

Symbian

开发平台:

Visual C++

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