402 lines
10 KiB
C++
402 lines
10 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1993 - 1993.
|
|
//
|
|
// File: ccompapi.cxx
|
|
//
|
|
// Contents: common compobj API Worker routines used by com, stg, scm etc
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 31-Dec-93 ErikGav Chicago port
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <ole2sp.h>
|
|
#include <ole2com.h>
|
|
#include <olesem.hxx>
|
|
|
|
NAME_SEG(CompApi)
|
|
ASSERTDATA
|
|
|
|
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";
|
|
|
|
LPVOID WINAPI PrivHeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
|
|
BOOL WINAPI PrivHeapFree (HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
|
|
|
|
HANDLE g_hHeap = 0;
|
|
HEAP_ALLOC_ROUTINE *pfnHeapAlloc = PrivHeapAlloc;
|
|
HEAP_FREE_ROUTINE *pfnHeapFree = PrivHeapFree;
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: PrivHeapAlloc (internal)
|
|
//
|
|
// Synopsis: Allocate memory from the heap.
|
|
//
|
|
// Notes: This function handles the first call to PrivMemAlloc.
|
|
// This function changes pfnHeapAlloc so that subsequent calls
|
|
// to PrivMemAlloc will go directly to HeapAlloc.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
LPVOID WINAPI PrivHeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes)
|
|
{
|
|
// Fault in g_hHeap if it's not initialized already via MallocInitialize
|
|
if (g_hHeap == NULL)
|
|
{
|
|
g_hHeap = GetProcessHeap();
|
|
if (g_hHeap == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
pfnHeapFree = HeapFree;
|
|
pfnHeapAlloc = HeapAlloc;
|
|
return HeapAlloc(g_hHeap, dwFlags, dwBytes);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: PrivHeapFree (internal)
|
|
//
|
|
// Synopsis: Free memory from the heap.
|
|
//
|
|
// Notes: lpMem should always be zero. We assume that memory
|
|
// freed via PrivMemFree has been allocated via PrivMemAlloc.
|
|
// The first call to PrivMemAlloc changes pfnHeapFree.
|
|
// Subsequent calls to PrivMemFree go directly to HeapFree.
|
|
// Therefore PrivHeapFree should never be called with a
|
|
// non-zero lpMem.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
BOOL WINAPI PrivHeapFree (HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
|
|
{
|
|
Win4Assert(lpMem == 0 && "PrivMemFree requires PrivMemAlloc.");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: wStringFromUUID (internal)
|
|
//
|
|
// Synopsis: converts UUID into xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
//
|
|
// Arguments: [rguid] - the guid to convert
|
|
// [lpszy] - buffer to hold the results
|
|
//
|
|
// Returns: Number of characters copied to the buffer.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
INTERNAL wStringFromUUID(REFGUID rguid, LPWSTR lpsz)
|
|
{
|
|
int i;
|
|
LPWSTR p = lpsz;
|
|
|
|
const BYTE * pBytes = (const BYTE *) &rguid;
|
|
|
|
for (i = 0; i < sizeof(GuidMap); i++)
|
|
{
|
|
if (GuidMap[i] == '-')
|
|
{
|
|
*p++ = L'-';
|
|
}
|
|
else
|
|
{
|
|
*p++ = wszDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
|
|
*p++ = wszDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
|
|
}
|
|
}
|
|
|
|
*p = L'\0';
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: HexStringToDword (private)
|
|
//
|
|
// Synopsis: scan lpsz for a number of hex digits (at most 8); update lpsz
|
|
// return value in Value; check for chDelim;
|
|
//
|
|
// Arguments: [lpsz] - the hex string to convert
|
|
// [Value] - the returned value
|
|
// [cDigits] - count of digits
|
|
//
|
|
// Returns: TRUE for success
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
static BOOL HexStringToDword(LPCWSTR FAR& lpsz, DWORD FAR& Value,
|
|
int cDigits, WCHAR chDelim)
|
|
{
|
|
int Count;
|
|
|
|
Value = 0;
|
|
for (Count = 0; Count < cDigits; Count++, lpsz++)
|
|
{
|
|
if (*lpsz >= '0' && *lpsz <= '9')
|
|
Value = (Value << 4) + *lpsz - '0';
|
|
else if (*lpsz >= 'A' && *lpsz <= 'F')
|
|
Value = (Value << 4) + *lpsz - 'A' + 10;
|
|
else if (*lpsz >= 'a' && *lpsz <= 'f')
|
|
Value = (Value << 4) + *lpsz - 'a' + 10;
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
if (chDelim != 0)
|
|
return *lpsz++ == chDelim;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: wUUIDFromString (internal)
|
|
//
|
|
// Synopsis: Parse UUID such as 00000000-0000-0000-0000-000000000000
|
|
//
|
|
// Arguments: [lpsz] - Supplies the UUID string to convert
|
|
// [pguid] - Returns the GUID.
|
|
//
|
|
// Returns: TRUE if successful
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
INTERNAL_(BOOL) wUUIDFromString(LPCWSTR lpsz, LPGUID pguid)
|
|
{
|
|
DWORD dw;
|
|
|
|
if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
|
|
return FALSE;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
|
|
return FALSE;
|
|
|
|
pguid->Data2 = (WORD)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
|
|
return FALSE;
|
|
|
|
pguid->Data3 = (WORD)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pguid->Data4[0] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
|
|
return FALSE;
|
|
|
|
pguid->Data4[1] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pguid->Data4[2] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pguid->Data4[3] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pguid->Data4[4] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pguid->Data4[5] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pguid->Data4[6] = (BYTE)dw;
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pguid->Data4[7] = (BYTE)dw;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: wGUIDFromString (internal)
|
|
//
|
|
// Synopsis: Parse GUID such as {00000000-0000-0000-0000-000000000000}
|
|
//
|
|
// Arguments: [lpsz] - the guid string to convert
|
|
// [pguid] - guid to return
|
|
//
|
|
// Returns: TRUE if successful
|
|
//
|
|
// CODEWORK: these are common with com\class\compapi.cxx ..
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
INTERNAL_(BOOL) wGUIDFromString(LPCWSTR lpsz, LPGUID pguid)
|
|
{
|
|
DWORD dw;
|
|
|
|
if (*lpsz++ != '{' )
|
|
return FALSE;
|
|
|
|
if (wUUIDFromString(lpsz, pguid) != TRUE)
|
|
return FALSE;
|
|
|
|
lpsz +=36;
|
|
|
|
if (*lpsz++ != '}' )
|
|
return FALSE;
|
|
|
|
if (*lpsz != '\0') // check for zero terminated string - test bug #18307
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: wStringFromGUID2 (internal)
|
|
//
|
|
// Synopsis: converts GUID into {...} form without leading identifier;
|
|
//
|
|
// Arguments: [rguid] - the guid to convert
|
|
// [lpszy] - buffer to hold the results
|
|
// [cbMax] - sizeof the buffer
|
|
//
|
|
// Returns: amount of data copied to lpsz if successful
|
|
// 0 if buffer too small.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
INTERNAL_(int) wStringFromGUID2(REFGUID rguid, LPWSTR lpsz, int cbMax)
|
|
{
|
|
int i;
|
|
LPWSTR p = lpsz;
|
|
|
|
if (cbMax < GUIDSTR_MAX)
|
|
return 0;
|
|
|
|
*p++ = L'{';
|
|
|
|
wStringFromUUID(rguid, p);
|
|
|
|
p += 36;
|
|
|
|
*p++ = L'}';
|
|
*p = L'\0';
|
|
|
|
return GUIDSTR_MAX;
|
|
}
|
|
|
|
static const CHAR szDigits[] = "0123456789ABCDEF";
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: wStringFromGUID2A (internal)
|
|
//
|
|
// Synopsis: Ansi version of wStringFromGUID2 (for Win95 Optimizations)
|
|
//
|
|
// Arguments: [rguid] - the guid to convert
|
|
// [lpszy] - buffer to hold the results
|
|
// [cbMax] - sizeof the buffer
|
|
//
|
|
// Returns: amount of data copied to lpsz if successful
|
|
// 0 if buffer too small.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
INTERNAL_(int) wStringFromGUID2A(REFGUID rguid, LPSTR lpsz, int cbMax) // internal
|
|
{
|
|
int i;
|
|
LPSTR p = lpsz;
|
|
|
|
const BYTE * pBytes = (const BYTE *) &rguid;
|
|
|
|
*p++ = '{';
|
|
|
|
for (i = 0; i < sizeof(GuidMap); i++)
|
|
{
|
|
if (GuidMap[i] == '-')
|
|
{
|
|
*p++ = '-';
|
|
}
|
|
else
|
|
{
|
|
*p++ = szDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
|
|
*p++ = szDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
|
|
}
|
|
}
|
|
*p++ = '}';
|
|
*p = '\0';
|
|
|
|
return GUIDSTR_MAX;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FormatHexNumA
|
|
//
|
|
// Synopsis: Given a value, and a count of characters, translate
|
|
// the value into a hex string. This is the ANSI version
|
|
//
|
|
// Arguments: [ulValue] -- Value to convert
|
|
// [chChars] -- Number of characters to format
|
|
// [pchStr] -- Pointer to output buffer
|
|
//
|
|
// Requires: pwcStr must be valid for chChars
|
|
//
|
|
// History: 12-Dec-95 KevinRo Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void FormatHexNumA( unsigned long ulValue, unsigned long chChars, char *pchStr)
|
|
{
|
|
while (chChars--)
|
|
{
|
|
pchStr[chChars] = (char) szDigits[ulValue & 0xF];
|
|
ulValue = ulValue >> 4;
|
|
}
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FormatHexNumW
|
|
//
|
|
// Synopsis: Given a value, and a count of characters, translate
|
|
// the value into a hex string. This is the WCHAR version
|
|
//
|
|
// Arguments: [ulValue] -- Value to convert
|
|
// [chChars] -- Number of characters to format
|
|
// [pwcStr] -- Pointer to output buffer
|
|
//
|
|
// Requires: pwcStr must be valid for chChars
|
|
//
|
|
// History: 12-Dec-95 KevinRo Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void FormatHexNumW( unsigned long ulValue, unsigned long chChars, WCHAR *pwcStr)
|
|
{
|
|
while (chChars--)
|
|
{
|
|
pwcStr[chChars] = (char) wszDigits[ulValue & 0xF];
|
|
ulValue = ulValue >> 4;
|
|
}
|
|
}
|