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 );
}