UTIL.C
/*========================================================================== 
 * 
 *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved. 
 * 
 *  File:       util.c 
 *  Content:    miscellaneous functions 
 * 
 * 
 ***************************************************************************/ 
#include "util.h" 
 
/* 
 * Globals 
 */ 
static const BYTE GuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-', 
                                8, 9, '-', 10, 11, 12, 13, 14, 15 }; 
static const WCHAR wszDigits[] = L"0123456789ABCDEF"; 
 
 
/* 
 * StringFromGUID 
 *  
 * Converts a GUID into a wide string 
 */ 
int StringFromGUID(LPGUID lpguid, LPWSTR lpwsz) 
{ 
    int i; 
 
    const BYTE * pBytes = (const BYTE *) lpguid; 
 
    *lpwsz++ = L'{'; 
 
    for (i = 0; i < sizeof(GuidMap); i++) 
    { 
        if (GuidMap[i] == '-') 
        { 
            *lpwsz++ = L'-'; 
        } 
        else 
        { 
            *lpwsz++ = wszDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ]; 
            *lpwsz++ = wszDigits[ (pBytes[GuidMap[i]] & 0x0F) ]; 
        } 
    } 
    *lpwsz++ = L'}'; 
    *lpwsz   = L'\0'; 
 
    return GUIDSTR_MAX; 
} 
 
/* 
 * IsEqualGuid 
 * 
 * Determines if two guids are equal 
 */ 
BOOL  IsEqualGuid(GUID *lpguid1, GUID *lpguid2) 
{ 
   return ( 
      ((PLONG) lpguid1)[0] == ((PLONG) lpguid2)[0] && 
      ((PLONG) lpguid1)[1] == ((PLONG) lpguid2)[1] && 
      ((PLONG) lpguid1)[2] == ((PLONG) lpguid2)[2] && 
      ((PLONG) lpguid1)[3] == ((PLONG) lpguid2)[3]); 
} 
 
 
// convert a hex char to an int - used by str to guid conversion 
// we wrote our own, since the ole one is slow, and requires ole32.dll 
// we use ansi strings here, since guids won't get internationalized 
int GetDigit(LPSTR lpstr) 
{ 
char ch = *lpstr; 
     
    if (ch >= '0' && ch <= '9') 
        return(ch - '0'); 
    if (ch >= 'a' && ch <= 'f') 
        return(ch - 'a' + 10); 
    if (ch >= 'A' && ch <= 'F') 
        return(ch - 'A' + 10); 
    return(0); 
} 
// walk the string, writing pairs of bytes into the byte stream (guid) 
// we need to write the bytes into the byte stream from right to left 
// or left to right as indicated by fRightToLeft 
void ConvertField(LPBYTE lpByte,LPSTR * ppStr,int iFieldSize,BOOL fRightToLeft) 
{ 
int i; 
 
for (i=0;i<iFieldSize ;i++ ) 
{ 
// don't barf on the field separators 
if ('-' == **ppStr) (*ppStr)++;  
if (fRightToLeft == TRUE) 
{ 
// work from right to left within the byte stream 
*(lpByte + iFieldSize - (i+1)) = 16*GetDigit(*ppStr) + GetDigit((*ppStr)+1); 
}  
else  
{ 
// work from  left to right within the byte stream 
*(lpByte + i) = 16*GetDigit(*ppStr) + GetDigit((*ppStr)+1); 
} 
*ppStr+=2; // get next two digit pair 
} 
} // ConvertField 
 
 
// convert the passed in string to a real GUID 
// walk the guid, setting each byte in the guid to the two digit hex pair in the 
// passed string 
HRESULT GUIDFromString(LPWSTR lpWStr, GUID * pGuid) 
{ 
BYTE * lpByte; // byte index into guid 
int iFieldSize; // size of current field we're converting 
// since its a guid, we can do a "brute force" conversion 
char lpTemp[GUID_STRING_SIZE]; 
char *lpStr = lpTemp; 
 
WideToAnsi(lpStr,lpWStr,GUID_STRING_SIZE); 
 
// make sure we have a {xxxx-...} type guid 
if ('{' !=  *lpStr) return E_FAIL; 
lpStr++; 
 
lpByte = (BYTE *)pGuid; 
// data 1 
iFieldSize = sizeof(unsigned long); 
ConvertField(lpByte,&lpStr,iFieldSize,TRUE); 
lpByte += iFieldSize; 
 
// data 2 
iFieldSize = sizeof(unsigned short); 
ConvertField(lpByte,&lpStr,iFieldSize,TRUE); 
lpByte += iFieldSize; 
 
// data 3 
iFieldSize = sizeof(unsigned short); 
ConvertField(lpByte,&lpStr,iFieldSize,TRUE); 
lpByte += iFieldSize; 
 
// data 4 
iFieldSize = 8*sizeof(unsigned char); 
ConvertField(lpByte,&lpStr,iFieldSize,FALSE); 
lpByte += iFieldSize; 
 
// make sure we ended in the right place 
if ('}' != *lpStr)  
{ 
memset(pGuid,0,sizeof(GUID)); 
return E_FAIL; 
} 
 
return S_OK; 
}// GUIDFromString 
 
/* 
 ** WideToAnsi 
 * 
 *  CALLED BY:everywhere 
 * 
 *  PARAMETERS: lpStr - destination string 
 *lpWStr - string to convert 
 *cchStr - size of dest buffer 
 * 
 *  DESCRIPTION: 
 *converts unicode lpWStr to ansi lpStr. 
 *fills in unconvertable chars w/ DPLAY_DEFAULT_CHAR "-" 
 * 
 * 
 *  RETURNS:  if cchStr is 0, returns the size required to hold the string 
 *otherwise, returns the number of chars converted 
 * 
 */ 
int WideToAnsi(LPSTR lpStr,LPWSTR lpWStr,int cchStr) 
{ 
 
int rval; 
BOOL bDefault; 
 
// use the default code page (CP_ACP) 
// -1 indicates WStr must be null terminated 
rval = WideCharToMultiByte(CP_ACP,0,lpWStr,-1,lpStr,cchStr,"-",&bDefault); 
 
return rval; 
 
} // WideToAnsi 
 
/* 
 ** AnsiToWide 
 * 
 *  CALLED BY: everywhere 
 * 
 *  PARAMETERS: lpWStr - dest string 
 *lpStr  - string to convert 
 *cchWstr - size of dest buffer 
 * 
 *  DESCRIPTION: converts Ansi lpStr to Unicode lpWstr 
 * 
 * 
 *  RETURNS:  if cchStr is 0, returns the size required to hold the string 
 *otherwise, returns the number of chars converted 
 * 
 */ 
int AnsiToWide(LPWSTR lpWStr,LPSTR lpStr,int cchWStr) 
{ 
int rval; 
 
rval =  MultiByteToWideChar(CP_ACP,0,lpStr,-1,lpWStr,cchWStr); 
 
return rval; 
}  // AnsiToWide 
 
 
/*  
 * randInt 
 * 
 * returns a random integer in the specified range 
 */ 
int randInt( int low, int high ) 
{ 
    int range = high - low; 
    int num = rand() % range; 
    return( num + low ); 
} 
 
/* 
 * randDouble 
 * 
 * returns a random double in the specified range 
 */ 
double randDouble( double low, double high ) 
{ 
    double range = high - low; 
    double num = range * (double)rand()/(double)RAND_MAX; 
    return( num + low ); 
}