1586 lines
44 KiB
C++
1586 lines
44 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1998.
|
|
//
|
|
// File: StgVarA.cxx
|
|
//
|
|
// Contents: C++ wrapper for PROPVARIANT.
|
|
//
|
|
// History: 01-Aug-94 KyleP Created
|
|
// 14-May-97 mohamedn allocate/deallocate SafeArrays (VT_ARRAY)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#ifndef _NTDLLBUILD_
|
|
|
|
#include <propset.h>
|
|
#include <propvar.h>
|
|
#include <pmalloc.hxx>
|
|
|
|
CAllocStorageVariant::CAllocStorageVariant(
|
|
BYTE *pb,
|
|
ULONG cb,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
vt = VT_BLOB;
|
|
|
|
if ( 0 == pb )
|
|
{
|
|
blob.cbSize = 0;
|
|
blob.pBlobData = 0;
|
|
}
|
|
else
|
|
{
|
|
blob.cbSize = cb;
|
|
blob.pBlobData = (BYTE *) ma.Allocate(cb);
|
|
|
|
if (blob.pBlobData != NULL)
|
|
{
|
|
memcpy(blob.pBlobData, pb, cb);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CAllocStorageVariant::CAllocStorageVariant(
|
|
char const *psz,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
vt = VT_LPSTR;
|
|
|
|
if ( 0 == psz )
|
|
{
|
|
pszVal = 0;
|
|
}
|
|
else
|
|
{
|
|
int cb = strlen(psz) + 1;
|
|
|
|
pszVal = (char *) ma.Allocate(cb);
|
|
|
|
if (pszVal != NULL)
|
|
{
|
|
memcpy(pszVal, psz, cb);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CAllocStorageVariant::CAllocStorageVariant(
|
|
WCHAR const *pwsz,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
vt = VT_LPWSTR;
|
|
|
|
if ( 0 == pwsz )
|
|
{
|
|
pwszVal = 0;
|
|
}
|
|
else
|
|
{
|
|
int cb = (wcslen(pwsz) + 1) * sizeof(WCHAR);
|
|
|
|
pwszVal = (WCHAR *) ma.Allocate(cb);
|
|
|
|
if (pszVal != NULL)
|
|
{
|
|
memcpy(pwszVal, pwsz, cb);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CAllocStorageVariant::CAllocStorageVariant(
|
|
CLSID const *pcid,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
vt = VT_CLSID;
|
|
puuid = (CLSID *) ma.Allocate(sizeof(CLSID));
|
|
|
|
if (puuid != NULL)
|
|
{
|
|
memcpy(puuid, pcid, sizeof(CLSID));
|
|
}
|
|
}
|
|
|
|
|
|
CAllocStorageVariant::CAllocStorageVariant(
|
|
VARENUM v,
|
|
ULONG cElements,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
ULONG cbElement;
|
|
BOOLEAN fZero = FALSE;
|
|
|
|
// Ignore vector flag. This constructor is always for vectors only.
|
|
|
|
vt = v | VT_VECTOR;
|
|
|
|
switch (vt)
|
|
{
|
|
case VT_VECTOR | VT_I1:
|
|
case VT_VECTOR | VT_UI1:
|
|
AssertByteVector(cac); // VT_I1
|
|
AssertByteVector(caub); // VT_UI1
|
|
cbElement = sizeof(caub.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I2:
|
|
case VT_VECTOR | VT_UI2:
|
|
case VT_VECTOR | VT_BOOL:
|
|
AssertShortVector(cai); // VT_I2
|
|
AssertShortVector(caui); // VT_UI2
|
|
AssertShortVector(cabool); // VT_BOOL
|
|
cbElement = sizeof(cai.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I4:
|
|
case VT_VECTOR | VT_UI4:
|
|
case VT_VECTOR | VT_R4:
|
|
case VT_VECTOR | VT_ERROR:
|
|
AssertLongVector(cal); // VT_I4
|
|
AssertLongVector(caul); // VT_UI4
|
|
AssertLongVector(caflt); // VT_R4
|
|
AssertLongVector(cascode); // VT_ERROR
|
|
cbElement = sizeof(cal.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I8:
|
|
case VT_VECTOR | VT_UI8:
|
|
case VT_VECTOR | VT_R8:
|
|
case VT_VECTOR | VT_CY:
|
|
case VT_VECTOR | VT_DATE:
|
|
case VT_VECTOR | VT_FILETIME:
|
|
AssertLongLongVector(cah); // VT_I8
|
|
AssertLongLongVector(cauh); // VT_UI8
|
|
AssertLongLongVector(cadbl); // VT_R8
|
|
AssertLongLongVector(cacy); // VT_CY
|
|
AssertLongLongVector(cadate); // VT_DATE
|
|
AssertLongLongVector(cafiletime); // VT_FILETIME
|
|
cbElement = sizeof(cah.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CLSID:
|
|
AssertVarVector(cauuid, sizeof(GUID));
|
|
cbElement = sizeof(GUID);
|
|
fZero = TRUE;
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CF:
|
|
AssertVarVector(caclipdata, sizeof(CLIPDATA)); // VT_CF
|
|
cbElement = sizeof(CLIPDATA);
|
|
fZero = TRUE;
|
|
break;
|
|
|
|
case VT_VECTOR | VT_BSTR:
|
|
case VT_VECTOR | VT_LPSTR:
|
|
case VT_VECTOR | VT_LPWSTR:
|
|
AssertStringVector(calpwstr); // VT_LPWSTR
|
|
AssertStringVector(cabstr); // VT_BSTR
|
|
AssertStringVector(calpstr); // VT_LPSTR
|
|
cbElement = sizeof(VOID *);
|
|
fZero = TRUE;
|
|
break;
|
|
|
|
case VT_VECTOR | VT_VARIANT:
|
|
AssertVarVector(capropvar, sizeof(PROPVARIANT)); // VT_VARIANT
|
|
cbElement = sizeof(PROPVARIANT);
|
|
ASSERT(VT_EMPTY == 0);
|
|
fZero = TRUE;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(!"CAllocStorageVariant -- Invalid vector type");
|
|
vt = VT_EMPTY;
|
|
break;
|
|
}
|
|
if (vt != VT_EMPTY)
|
|
{
|
|
caub.cElems = 0;
|
|
caub.pElems = (BYTE *) ma.Allocate(cElements * cbElement);
|
|
if (caub.pElems != NULL)
|
|
{
|
|
if (fZero)
|
|
{
|
|
memset(caub.pElems, 0, cElements * cbElement);
|
|
}
|
|
caub.cElems = cElements;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#define POINTER_FIXUP(type, field) \
|
|
field.pElems = (type *) ma.Allocate(field.cElems * sizeof(field.pElems[0]));\
|
|
if (field.pElems != NULL) \
|
|
{ \
|
|
memcpy( \
|
|
field.pElems, \
|
|
var.field.pElems, \
|
|
field.cElems * sizeof(field.pElems[0])); \
|
|
}
|
|
|
|
|
|
CAllocStorageVariant::CAllocStorageVariant(
|
|
PROPVARIANT& var,
|
|
PMemoryAllocator &ma): CBaseStorageVariant(var)
|
|
{
|
|
BOOLEAN fNoMemory = FALSE;
|
|
ULONG i;
|
|
|
|
//
|
|
// Fixup any pointers
|
|
//
|
|
|
|
switch (vt)
|
|
{
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_I1:
|
|
case VT_UI1:
|
|
case VT_I2:
|
|
case VT_UI2:
|
|
case VT_BOOL:
|
|
case VT_I4:
|
|
case VT_UI4:
|
|
case VT_R4:
|
|
case VT_ERROR:
|
|
case VT_I8:
|
|
case VT_UI8:
|
|
case VT_R8:
|
|
case VT_INT:
|
|
case VT_UINT:
|
|
case VT_DECIMAL:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_FILETIME:
|
|
break;
|
|
|
|
case VT_CLSID:
|
|
vt = VT_EMPTY;
|
|
SetCLSID(var.puuid, ma);
|
|
break;
|
|
|
|
case VT_BLOB:
|
|
case VT_BLOB_OBJECT:
|
|
blob.pBlobData = (BYTE *) ma.Allocate(blob.cbSize);
|
|
if (blob.pBlobData == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memcpy(blob.pBlobData, var.blob.pBlobData, blob.cbSize);
|
|
break;
|
|
|
|
case VT_CF:
|
|
pclipdata = (CLIPDATA *) ma.Allocate(sizeof(*pclipdata));
|
|
if (pclipdata == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
*pclipdata = *var.pclipdata;
|
|
pclipdata->pClipData = (BYTE *) ma.Allocate(CBPCLIPDATA(*pclipdata));
|
|
if (pclipdata->pClipData == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memcpy(pclipdata->pClipData, var.pclipdata->pClipData, CBPCLIPDATA(*pclipdata));
|
|
break;
|
|
|
|
case VT_STREAM:
|
|
case VT_VERSIONED_STREAM:
|
|
case VT_STREAMED_OBJECT:
|
|
pStream->AddRef();
|
|
break;
|
|
|
|
case VT_STORAGE:
|
|
case VT_STORED_OBJECT:
|
|
pStorage->AddRef();
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
vt = VT_EMPTY;
|
|
SetBSTR(var.bstrVal, ma);
|
|
break;
|
|
|
|
case VT_LPSTR:
|
|
vt = VT_EMPTY;
|
|
SetLPSTR(var.pszVal, ma);
|
|
break;
|
|
|
|
case VT_LPWSTR:
|
|
vt = VT_EMPTY;
|
|
SetLPWSTR(var.pwszVal, ma);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I1:
|
|
case VT_VECTOR | VT_UI1:
|
|
POINTER_FIXUP(BYTE, caub);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I2:
|
|
case VT_VECTOR | VT_UI2:
|
|
case VT_VECTOR | VT_BOOL:
|
|
AssertShortVector(cai); // VT_I2
|
|
AssertShortVector(caui); // VT_UI2
|
|
AssertShortVector(cabool); // VT_BOOL
|
|
POINTER_FIXUP(short, cai);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I4:
|
|
case VT_VECTOR | VT_UI4:
|
|
case VT_VECTOR | VT_R4:
|
|
case VT_VECTOR | VT_ERROR:
|
|
AssertLongVector(cal); // VT_I4
|
|
AssertLongVector(caul); // VT_UI4
|
|
AssertLongVector(caflt); // VT_R4
|
|
AssertLongVector(cascode); // VT_ERROR
|
|
POINTER_FIXUP(long, cal);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I8:
|
|
case VT_VECTOR | VT_UI8:
|
|
case VT_VECTOR | VT_R8:
|
|
case VT_VECTOR | VT_CY:
|
|
case VT_VECTOR | VT_DATE:
|
|
case VT_VECTOR | VT_FILETIME:
|
|
AssertLongLongVector(cah); // VT_I8
|
|
AssertLongLongVector(cauh); // VT_UI8
|
|
AssertLongLongVector(cadbl); // VT_R8
|
|
AssertLongLongVector(cacy); // VT_CY
|
|
AssertLongLongVector(cadate); // VT_DATE
|
|
AssertLongLongVector(cafiletime); // VT_FILETIME
|
|
POINTER_FIXUP(LARGE_INTEGER, cah);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CLSID:
|
|
POINTER_FIXUP(CLSID, cauuid);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CF:
|
|
{
|
|
caclipdata.pElems = (CLIPDATA *)
|
|
ma.Allocate(caclipdata.cElems * sizeof(caclipdata.pElems[0]));
|
|
if (caclipdata.pElems == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memset(
|
|
caclipdata.pElems,
|
|
0,
|
|
caclipdata.cElems * sizeof(caclipdata.pElems[0]));
|
|
for (i = 0; i < caclipdata.cElems; i++)
|
|
{
|
|
caclipdata.pElems[i] = var.caclipdata.pElems[i];
|
|
caclipdata.pElems[i].pClipData = (BYTE *)
|
|
ma.Allocate(CBPCLIPDATA(caclipdata.pElems[i]));
|
|
|
|
if (caclipdata.pElems[i].pClipData == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memcpy(
|
|
caclipdata.pElems[i].pClipData,
|
|
var.caclipdata.pElems[i].pClipData,
|
|
CBPCLIPDATA(caclipdata.pElems[i]));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_VECTOR | VT_BSTR:
|
|
{
|
|
cabstr.pElems = (BSTR *)
|
|
ma.Allocate(cabstr.cElems * sizeof(cabstr.pElems[0]));
|
|
if (cabstr.pElems == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memset(cabstr.pElems, 0, cabstr.cElems * sizeof(cabstr.pElems[0]));
|
|
for (i = 0; i < cabstr.cElems; i++)
|
|
{
|
|
cabstr.pElems[i] = SysAllocString(var.cabstr.pElems[i]);
|
|
if (cabstr.pElems[i] == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_VECTOR | VT_LPSTR:
|
|
{
|
|
calpstr.pElems = (LPSTR *)
|
|
ma.Allocate(calpstr.cElems * sizeof(calpstr.pElems[0]));
|
|
if (calpstr.pElems == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memset(calpstr.pElems, 0, calpstr.cElems * sizeof(calpstr.pElems[0]));
|
|
for (i = 0; i < calpstr.cElems; i++)
|
|
{
|
|
unsigned cb = strlen(var.calpstr.pElems[i]) + 1;
|
|
calpstr.pElems[i] = (char *) ma.Allocate(cb);
|
|
if (calpstr.pElems[i] == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memcpy(calpstr.pElems[i], var.calpstr.pElems[i], cb);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_VECTOR | VT_LPWSTR:
|
|
{
|
|
calpwstr.pElems = (LPWSTR *)
|
|
ma.Allocate(calpwstr.cElems * sizeof(calpwstr.pElems[0]));
|
|
if (calpwstr.pElems == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memset(calpwstr.pElems, 0, calpwstr.cElems * sizeof(calpwstr.pElems[0]));
|
|
for (i = 0; i < calpwstr.cElems; i++)
|
|
{
|
|
unsigned cb = (wcslen(var.calpwstr.pElems[i]) + 1) * sizeof(WCHAR);
|
|
calpwstr.pElems[i] = (WCHAR *) ma.Allocate(cb);
|
|
if (calpwstr.pElems[i] == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
memcpy(calpwstr.pElems[i], var.calpwstr.pElems[i], cb);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_VECTOR | VT_VARIANT:
|
|
capropvar.pElems = (PROPVARIANT *)
|
|
ma.Allocate(capropvar.cElems * sizeof(capropvar.pElems[0]));
|
|
if (capropvar.pElems == NULL)
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
ASSERT(VT_EMPTY == 0);
|
|
memset(
|
|
capropvar.pElems,
|
|
0,
|
|
capropvar.cElems * sizeof(capropvar.pElems[0]));
|
|
|
|
for (i = 0; i < capropvar.cElems; i++)
|
|
{
|
|
new (&capropvar.pElems[i]) CAllocStorageVariant(
|
|
var.capropvar.pElems[i],
|
|
ma);
|
|
|
|
if (!((CAllocStorageVariant *) &capropvar.pElems[i])->IsValid())
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_ARRAY | VT_I4:
|
|
case VT_ARRAY | VT_UI1:
|
|
case VT_ARRAY | VT_I2:
|
|
case VT_ARRAY | VT_R4:
|
|
case VT_ARRAY | VT_R8:
|
|
case VT_ARRAY | VT_BOOL:
|
|
case VT_ARRAY | VT_ERROR:
|
|
case VT_ARRAY | VT_CY:
|
|
case VT_ARRAY | VT_DATE:
|
|
case VT_ARRAY | VT_I1:
|
|
case VT_ARRAY | VT_UI2:
|
|
case VT_ARRAY | VT_UI4:
|
|
case VT_ARRAY | VT_INT:
|
|
case VT_ARRAY | VT_UINT:
|
|
case VT_ARRAY | VT_DECIMAL:
|
|
case VT_ARRAY | VT_BSTR:
|
|
case VT_ARRAY | VT_VARIANT:
|
|
{
|
|
//
|
|
// avoid double delete of the source variant
|
|
//
|
|
|
|
parray = 0;
|
|
|
|
SAFEARRAY * pSaDst = 0;
|
|
|
|
if ( FAILED( SafeArrayCopy( var.parray, &pSaDst ) ) )
|
|
{
|
|
fNoMemory = TRUE;
|
|
break;
|
|
}
|
|
|
|
parray = pSaDst;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
Win4Assert( !"Unexpected vt type" );
|
|
return;
|
|
}
|
|
}
|
|
if (fNoMemory || !IsValid())
|
|
{
|
|
ResetType(ma);
|
|
|
|
// We cannot raise in a non-unwindable constructor.
|
|
// Just return a PROPVARIANT guaranteed to look invalid.
|
|
|
|
vt = VT_LPSTR;
|
|
pszVal = NULL;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SaCreateAndCopy
|
|
//
|
|
// Synopsis: Creates a safearray & initializes it with source safearray.
|
|
//
|
|
// Arguments: [ma] - memory allocator to use
|
|
// [psaSrc] - source safearry
|
|
// [ppsaDst] - safearray to be created.
|
|
//
|
|
// Returns: TRUE - upon success
|
|
// FALSE - upon failure
|
|
//
|
|
// History: 5-10-97 mohamedn created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL SaCreateAndCopy( PMemoryAllocator &ma,
|
|
SAFEARRAY * psaSrc,
|
|
SAFEARRAY **ppsaDst )
|
|
{
|
|
ULONG cb = sizeof SAFEARRAY + ( ( 0 != psaSrc->cDims ?
|
|
(psaSrc->cDims-1) : 0) * sizeof SAFEARRAYBOUND );
|
|
|
|
Win4Assert( psaSrc->cDims > 0);
|
|
|
|
SAFEARRAY * psaDst = (SAFEARRAY *) ma.Allocate( cb );
|
|
if ( 0 == psaDst )
|
|
{
|
|
*ppsaDst = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
RtlCopyMemory(psaDst, psaSrc, cb);
|
|
|
|
// reset fields and values
|
|
psaDst->fFeatures &= ~( FADF_AUTO | FADF_STATIC );
|
|
psaDst->cLocks = 1; // new safearray has lockcount of 1
|
|
psaDst->pvData = 0;
|
|
|
|
*ppsaDst = psaDst;
|
|
|
|
return TRUE;
|
|
} //SaCreateAndCopy
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SaCreateData
|
|
//
|
|
// Synopsis: Creates/initializes SafeArray's data area
|
|
//
|
|
// Arguments: [ma] - memory allocator to use
|
|
// [vt] - variant type (VT_ARRAY assumed)
|
|
// [saSrc] - source safearry
|
|
// [saDst] - destination safearray.
|
|
// [fUseAllocatorOnly] - if TRUE, BSTRs are allocated using [ma]
|
|
//
|
|
// Returns: TRUE - upon success
|
|
// FALSE - upon failure
|
|
//
|
|
// History: 5-10-97 mohamedn created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL SaCreateData(
|
|
PVarAllocator & ma,
|
|
VARTYPE vt,
|
|
SAFEARRAY & saSrc,
|
|
SAFEARRAY & saDst,
|
|
BOOL fUseAllocatorOnly )
|
|
{
|
|
//
|
|
// Find out how much memory is needed for the array and allocate it.
|
|
//
|
|
unsigned cDataElements = SaCountElements(saSrc);
|
|
ULONG cb = cDataElements * saSrc.cbElements;
|
|
void * pv = ma.Allocate( cb );
|
|
|
|
if ( !pv )
|
|
return FALSE;
|
|
|
|
RtlZeroMemory( pv, cb );
|
|
|
|
switch (vt)
|
|
{
|
|
case VT_I4:
|
|
case VT_UI1:
|
|
case VT_I2:
|
|
case VT_R4:
|
|
case VT_R8:
|
|
case VT_BOOL:
|
|
case VT_ERROR:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_I1:
|
|
case VT_UI2:
|
|
case VT_UI4:
|
|
case VT_INT:
|
|
case VT_UINT:
|
|
case VT_DECIMAL:
|
|
{
|
|
RtlCopyMemory( pv, saSrc.pvData, cb);
|
|
saDst.pvData = pv;
|
|
}
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
{
|
|
BSTR *pBstrSrc = (BSTR *) saSrc.pvData;
|
|
BSTR *pBstrDst = (BSTR *) pv;
|
|
|
|
for ( unsigned i = 0; i < cDataElements; i++ )
|
|
{
|
|
Win4Assert( pBstrSrc[i] != 0 );
|
|
Win4Assert( pBstrDst[i] == 0 );
|
|
|
|
if ( fUseAllocatorOnly )
|
|
{
|
|
ULONG cbBstr = SysStringByteLen(pBstrSrc[i]) +
|
|
sizeof (ULONG) +
|
|
sizeof (WCHAR);
|
|
void * pv = ma.Allocate( cbBstr );
|
|
if ( 0 != pv )
|
|
{
|
|
BYTE * pbSrc = (BYTE *) pBstrSrc[i];
|
|
pbSrc -= sizeof ULONG;
|
|
RtlCopyMemory( pv, pbSrc, cbBstr);
|
|
pBstrDst[i] = (BSTR) ( (BYTE *) pv + sizeof ULONG );
|
|
pBstrDst[i] = (BSTR) ma.PointerToOffset( pBstrDst[i] );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pBstrDst[i] = SysAllocString(pBstrSrc[i]);
|
|
}
|
|
|
|
if ( 0 == pBstrDst[i] )
|
|
return FALSE;
|
|
}
|
|
|
|
saDst.pvData = pv;
|
|
}
|
|
break;
|
|
|
|
case VT_VARIANT:
|
|
{
|
|
CAllocStorageVariant *pVarntSrc = (CAllocStorageVariant *)saSrc.pvData;
|
|
CAllocStorageVariant *pVarntDst = (CAllocStorageVariant *)pv;
|
|
|
|
for ( unsigned i = 0; i < cDataElements; i++ )
|
|
{
|
|
Win4Assert( pVarntDst[i].vt == 0 );
|
|
|
|
if ( VT_BSTR == pVarntSrc[i].vt )
|
|
{
|
|
if ( fUseAllocatorOnly )
|
|
{
|
|
ULONG cbBstr = SysStringByteLen(pVarntSrc[i].bstrVal) +
|
|
sizeof (ULONG) +
|
|
sizeof (WCHAR);
|
|
void * pv = ma.Allocate( cbBstr );
|
|
if ( 0 != pv )
|
|
{
|
|
BYTE * pbSrc = (BYTE *) pVarntSrc[i].bstrVal;
|
|
pbSrc -= sizeof ULONG;
|
|
RtlCopyMemory( pv, pbSrc, cbBstr);
|
|
pVarntDst[i].bstrVal = (BSTR) ((BYTE *) pv + sizeof ULONG);
|
|
pVarntDst[i].bstrVal = (BSTR) ma.PointerToOffset( pVarntDst[i].bstrVal );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pVarntDst[i].bstrVal = SysAllocString(pVarntSrc[i].bstrVal);
|
|
}
|
|
|
|
if ( 0 == pVarntDst[i].bstrVal )
|
|
return FALSE;
|
|
|
|
pVarntDst[i].vt = VT_BSTR;
|
|
}
|
|
else if ( 0 != (pVarntSrc[i].vt & VT_ARRAY) )
|
|
{
|
|
SAFEARRAY * pSaSrc = pVarntSrc[i].parray;
|
|
SAFEARRAY * pSaDst = 0;
|
|
|
|
if ( !SaCreateAndCopy( ma, pSaSrc, &pSaDst ) )
|
|
return FALSE;
|
|
|
|
if ( !SaCreateData( ma,
|
|
pVarntSrc[i].vt & ~VT_ARRAY,
|
|
*pSaSrc,
|
|
*pSaDst,
|
|
fUseAllocatorOnly ) )
|
|
return FALSE;
|
|
|
|
pVarntDst[i].parray = (SAFEARRAY *) ma.PointerToOffset( pSaDst );
|
|
pVarntDst[i].vt = pVarntSrc[i].vt;
|
|
}
|
|
else
|
|
{
|
|
Win4Assert( pVarntSrc[i].vt != VT_VARIANT );
|
|
Win4Assert( pVarntSrc[i].vt != VT_LPWSTR );
|
|
Win4Assert( pVarntSrc[i].vt != VT_LPSTR );
|
|
Win4Assert( pVarntSrc[i].vt != VT_CLSID );
|
|
|
|
pVarntDst[i] = pVarntSrc[i];
|
|
}
|
|
}
|
|
|
|
saDst.pvData = pv;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ciDebugOut(( DEB_ERROR, "Unexpected SafeArray type: vt=%x\n", vt ) );
|
|
Win4Assert( !"Unexpected SafeArray Type" );
|
|
return FALSE;
|
|
}
|
|
|
|
saDst.pvData = (void *) ma.PointerToOffset( saDst.pvData );
|
|
|
|
return TRUE;
|
|
} //SaCreateData
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SaComputeSize
|
|
//
|
|
// Synopsis: Computes the size of a safearray.
|
|
//
|
|
// Arguments: [vt] - variant type (VT_ARRAY assumed)
|
|
// [saSrc] - source safearry
|
|
//
|
|
// Returns: ULONG - number of bytes of memory needed to store safearray
|
|
//
|
|
// History: 5-01-98 AlanW Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG SaComputeSize( VARTYPE vt,
|
|
SAFEARRAY & saSrc )
|
|
{
|
|
//
|
|
// get number of data elements in array and size of the header.
|
|
//
|
|
unsigned cDataElements = SaCountElements(saSrc);
|
|
|
|
Win4Assert( 0 != saSrc.cDims );
|
|
|
|
ULONG cb = sizeof (SAFEARRAY) +
|
|
(saSrc.cDims-1) * sizeof (SAFEARRAYBOUND) +
|
|
cDataElements * saSrc.cbElements;
|
|
|
|
cb = AlignBlock( cb, sizeof LONGLONG );
|
|
|
|
switch (vt)
|
|
{
|
|
case VT_I4:
|
|
case VT_UI1:
|
|
case VT_I2:
|
|
case VT_R4:
|
|
case VT_R8:
|
|
case VT_BOOL:
|
|
case VT_ERROR:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_I1:
|
|
case VT_UI2:
|
|
case VT_UI4:
|
|
case VT_INT:
|
|
case VT_UINT:
|
|
case VT_DECIMAL:
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
{
|
|
BSTR *pBstrSrc = (BSTR *) saSrc.pvData;
|
|
|
|
for ( unsigned i = 0; i < cDataElements; i++ )
|
|
{
|
|
Win4Assert( pBstrSrc[i] != 0 );
|
|
|
|
cb += AlignBlock( SysStringByteLen(pBstrSrc[i]) +
|
|
sizeof ULONG + sizeof WCHAR,
|
|
sizeof LONGLONG );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VARIANT:
|
|
{
|
|
CAllocStorageVariant *pVarnt = (CAllocStorageVariant *)saSrc.pvData;
|
|
|
|
for ( unsigned i = 0; i < cDataElements; i++ )
|
|
{
|
|
if ( VT_BSTR == pVarnt[i].vt )
|
|
{
|
|
cb += AlignBlock( SysStringByteLen(pVarnt[i].bstrVal) +
|
|
sizeof ULONG + sizeof WCHAR,
|
|
sizeof LONGLONG );
|
|
}
|
|
else if ( 0 != (pVarnt[i].vt & VT_ARRAY) )
|
|
{
|
|
cb += AlignBlock( SaComputeSize( (pVarnt[i].vt & ~VT_ARRAY),
|
|
*pVarnt[i].parray),
|
|
sizeof LONGLONG );
|
|
}
|
|
else
|
|
{
|
|
Win4Assert( pVarnt[i].vt != VT_VARIANT );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ciDebugOut(( DEB_ERROR, "Unexpected SafeArray type: vt=%x\n", vt ) );
|
|
Win4Assert( !"Unexpected SafeArray Type" );
|
|
return 1;
|
|
}
|
|
|
|
return cb;
|
|
}
|
|
|
|
|
|
|
|
CAllocStorageVariant::~CAllocStorageVariant()
|
|
{
|
|
switch (vt)
|
|
{
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_I1:
|
|
case VT_UI1:
|
|
case VT_I2:
|
|
case VT_UI2:
|
|
case VT_BOOL:
|
|
case VT_I4:
|
|
case VT_UI4:
|
|
case VT_R4:
|
|
case VT_ERROR:
|
|
case VT_I8:
|
|
case VT_UI8:
|
|
case VT_R8:
|
|
case VT_INT:
|
|
case VT_UINT:
|
|
case VT_DECIMAL:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_FILETIME:
|
|
break;
|
|
|
|
default:
|
|
ciDebugOut(( DEB_ERROR, "~CAllocStorageVariant -- Memory Leak: vt=%x\n", vt ) );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
CAllocStorageVariant::ResetType(PMemoryAllocator &ma)
|
|
{
|
|
// The most typical case
|
|
|
|
if ( VT_EMPTY == vt )
|
|
return;
|
|
|
|
ULONG i;
|
|
|
|
if ((vt & VT_BYREF) == 0)
|
|
{
|
|
switch (vt)
|
|
{
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_I1:
|
|
case VT_UI1:
|
|
case VT_I2:
|
|
case VT_UI2:
|
|
case VT_BOOL:
|
|
case VT_I4:
|
|
case VT_UI4:
|
|
case VT_R4:
|
|
case VT_ERROR:
|
|
case VT_I8:
|
|
case VT_UI8:
|
|
case VT_R8:
|
|
case VT_INT:
|
|
case VT_UINT:
|
|
case VT_DECIMAL:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_FILETIME:
|
|
break;
|
|
|
|
case VT_CLSID:
|
|
ma.Free(puuid);
|
|
break;
|
|
|
|
case VT_BLOB:
|
|
case VT_BLOB_OBJECT:
|
|
ma.Free(blob.pBlobData);
|
|
break;
|
|
|
|
case VT_CF:
|
|
if (pclipdata != NULL)
|
|
{
|
|
ma.Free(pclipdata->pClipData);
|
|
ma.Free(pclipdata);
|
|
}
|
|
break;
|
|
|
|
case VT_STREAM:
|
|
case VT_VERSIONED_STREAM:
|
|
case VT_STREAMED_OBJECT:
|
|
pStream->Release();
|
|
break;
|
|
|
|
case VT_STORAGE:
|
|
case VT_STORED_OBJECT:
|
|
pStorage->Release();
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
SysFreeString(bstrVal);
|
|
break;
|
|
|
|
case VT_LPSTR:
|
|
case VT_LPWSTR:
|
|
AssertStringField(pszVal); // VT_LPSTR
|
|
AssertStringField(pwszVal); // VT_LPWSTR
|
|
ma.Free(pwszVal);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I1:
|
|
case VT_VECTOR | VT_UI1:
|
|
case VT_VECTOR | VT_I2:
|
|
case VT_VECTOR | VT_UI2:
|
|
case VT_VECTOR | VT_BOOL:
|
|
case VT_VECTOR | VT_I4:
|
|
case VT_VECTOR | VT_UI4:
|
|
case VT_VECTOR | VT_R4:
|
|
case VT_VECTOR | VT_ERROR:
|
|
case VT_VECTOR | VT_I8:
|
|
case VT_VECTOR | VT_UI8:
|
|
case VT_VECTOR | VT_R8:
|
|
case VT_VECTOR | VT_CY:
|
|
case VT_VECTOR | VT_DATE:
|
|
case VT_VECTOR | VT_FILETIME:
|
|
case VT_VECTOR | VT_CLSID:
|
|
AssertByteVector(cac); // VT_I1
|
|
AssertByteVector(caub); // VT_UI1
|
|
AssertShortVector(cai); // VT_I2
|
|
AssertShortVector(caui); // VT_UI2
|
|
AssertShortVector(cabool); // VT_BOOL
|
|
AssertLongVector(cal); // VT_I4
|
|
AssertLongVector(caul); // VT_UI4
|
|
AssertLongVector(caflt); // VT_R4
|
|
AssertLongVector(cascode); // VT_ERROR
|
|
AssertLongLongVector(cah); // VT_I8
|
|
AssertLongLongVector(cauh); // VT_UI8
|
|
AssertLongLongVector(cadbl); // VT_R8
|
|
AssertLongLongVector(cacy); // VT_CY
|
|
AssertLongLongVector(cadate); // VT_DATE
|
|
AssertLongLongVector(cafiletime); // VT_FILETIME
|
|
AssertVarVector(cauuid, sizeof(GUID)); // VT_CLSID
|
|
ma.Free(cal.pElems);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CF:
|
|
if (caclipdata.pElems != NULL)
|
|
{
|
|
for (i = 0; i < caclipdata.cElems; i++)
|
|
{
|
|
ma.Free(caclipdata.pElems[i].pClipData);
|
|
}
|
|
ma.Free(caclipdata.pElems);
|
|
}
|
|
break;
|
|
|
|
|
|
case VT_VECTOR | VT_LPSTR:
|
|
case VT_VECTOR | VT_LPWSTR:
|
|
AssertStringVector(calpwstr); // VT_LPWSTR
|
|
AssertStringVector(calpstr); // VT_LPSTR
|
|
if (calpwstr.pElems != NULL)
|
|
{
|
|
for (i = 0; i < calpwstr.cElems; i++)
|
|
{
|
|
if (calpstr.pElems[i] != NULL) // don't free (NULL - cbbstr)
|
|
{
|
|
ma.Free((BYTE *) calpstr.pElems[i] );
|
|
}
|
|
}
|
|
ma.Free(calpwstr.pElems);
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_BSTR:
|
|
|
|
AssertStringVector(cabstr); // VT_BSTR
|
|
|
|
if (cabstr.pElems != NULL )
|
|
{
|
|
for (i = 0; i < cabstr.cElems; i++)
|
|
{
|
|
SysFreeString(cabstr.pElems[i]);
|
|
}
|
|
ma.Free(cabstr.pElems);
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_VARIANT:
|
|
if (capropvar.pElems != NULL)
|
|
{
|
|
for (i = 0; i < calpstr.cElems; i++)
|
|
{
|
|
((CAllocStorageVariant *) &capropvar.pElems[i])->ResetType(ma);
|
|
}
|
|
ma.Free(capropvar.pElems);
|
|
}
|
|
break;
|
|
|
|
case VT_ARRAY | VT_I4:
|
|
case VT_ARRAY | VT_UI1:
|
|
case VT_ARRAY | VT_I2:
|
|
case VT_ARRAY | VT_R4:
|
|
case VT_ARRAY | VT_R8:
|
|
case VT_ARRAY | VT_BOOL:
|
|
case VT_ARRAY | VT_ERROR:
|
|
case VT_ARRAY | VT_CY:
|
|
case VT_ARRAY | VT_DATE:
|
|
case VT_ARRAY | VT_I1:
|
|
case VT_ARRAY | VT_UI2:
|
|
case VT_ARRAY | VT_UI4:
|
|
case VT_ARRAY | VT_INT:
|
|
case VT_ARRAY | VT_UINT:
|
|
case VT_ARRAY | VT_DECIMAL:
|
|
case VT_ARRAY | VT_BSTR:
|
|
case VT_ARRAY | VT_VARIANT:
|
|
{
|
|
//
|
|
// What should we do if the array is locked?
|
|
// Perhaps just set cLocks to 0 so it can be freed.
|
|
// Note that we never hit the assert below because
|
|
// we deal with SafeArrays under our control so we
|
|
// know they won't be locked.
|
|
//
|
|
|
|
if ( 0 != parray )
|
|
{
|
|
Win4Assert( 0 == parray->cLocks );
|
|
HRESULT hr = SafeArrayDestroy( parray );
|
|
Win4Assert( S_OK == hr );
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
Win4Assert( !" Unexpected VT type" );
|
|
}
|
|
}
|
|
|
|
vt = VT_EMPTY;
|
|
}
|
|
|
|
|
|
// Invalid variants have a pointer type but a NULL pointer.
|
|
// Some are valid in this form in general, but not for many uses.
|
|
|
|
BOOL
|
|
CAllocStorageVariant::IsValid() const
|
|
{
|
|
ULONG i;
|
|
|
|
if ((VT_VECTOR & vt) && cal.cElems != 0 && cal.pElems == NULL)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
switch (vt)
|
|
{
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_I1:
|
|
case VT_UI1:
|
|
case VT_I2:
|
|
case VT_UI2:
|
|
case VT_BOOL:
|
|
case VT_I4:
|
|
case VT_UI4:
|
|
case VT_R4:
|
|
case VT_ERROR:
|
|
case VT_I8:
|
|
case VT_UI8:
|
|
case VT_INT:
|
|
case VT_UINT:
|
|
case VT_R8:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_FILETIME:
|
|
break;
|
|
|
|
case VT_DECIMAL:
|
|
return ( 0 == decVal.sign || DECIMAL_NEG == decVal.sign );
|
|
|
|
case VT_CLSID:
|
|
return(puuid != NULL);
|
|
|
|
case VT_BLOB:
|
|
case VT_BLOB_OBJECT:
|
|
return(blob.cbSize == 0 || blob.pBlobData != NULL);
|
|
|
|
case VT_CF:
|
|
return(pclipdata != NULL && pclipdata->pClipData != NULL);
|
|
|
|
case VT_STREAM:
|
|
case VT_VERSIONED_STREAM:
|
|
case VT_STREAMED_OBJECT:
|
|
return(pStream != NULL);
|
|
|
|
case VT_STORAGE:
|
|
case VT_STORED_OBJECT:
|
|
return(pStorage != NULL);
|
|
|
|
case VT_BSTR:
|
|
case VT_LPSTR:
|
|
case VT_LPWSTR:
|
|
AssertStringField(bstrVal); // VT_BSTR
|
|
AssertStringField(pszVal); // VT_LPSTR
|
|
AssertStringField(pwszVal); // VT_LPWSTR
|
|
return(pszVal != NULL);
|
|
|
|
case VT_VECTOR | VT_I1:
|
|
case VT_VECTOR | VT_UI1:
|
|
case VT_VECTOR | VT_I2:
|
|
case VT_VECTOR | VT_UI2:
|
|
case VT_VECTOR | VT_BOOL:
|
|
case VT_VECTOR | VT_I4:
|
|
case VT_VECTOR | VT_UI4:
|
|
case VT_VECTOR | VT_R4:
|
|
case VT_VECTOR | VT_ERROR:
|
|
case VT_VECTOR | VT_I8:
|
|
case VT_VECTOR | VT_UI8:
|
|
case VT_VECTOR | VT_R8:
|
|
case VT_VECTOR | VT_CY:
|
|
case VT_VECTOR | VT_DATE:
|
|
case VT_VECTOR | VT_FILETIME:
|
|
case VT_VECTOR | VT_CLSID:
|
|
AssertByteVector(cac); // VT_I1
|
|
AssertByteVector(caub); // VT_UI1
|
|
AssertShortVector(cai); // VT_I2
|
|
AssertShortVector(caui); // VT_UI2
|
|
AssertShortVector(cabool); // VT_BOOL
|
|
AssertLongVector(cal); // VT_I4
|
|
AssertLongVector(caul); // VT_UI4
|
|
AssertLongVector(caflt); // VT_R4
|
|
AssertLongVector(cascode); // VT_ERROR
|
|
AssertLongLongVector(cah); // VT_I8
|
|
AssertLongLongVector(cauh); // VT_UI8
|
|
AssertLongLongVector(cadbl); // VT_R8
|
|
AssertLongLongVector(cacy); // VT_CY
|
|
AssertLongLongVector(cadate); // VT_DATE
|
|
AssertLongLongVector(cafiletime); // VT_FILETIME
|
|
AssertVarVector(cauuid, sizeof(GUID)); // VT_CLSID
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CF:
|
|
for (i = 0; i < caclipdata.cElems; i++)
|
|
{
|
|
if (caclipdata.pElems[i].pClipData == NULL)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
case VT_VECTOR | VT_BSTR:
|
|
case VT_VECTOR | VT_LPSTR:
|
|
case VT_VECTOR | VT_LPWSTR:
|
|
AssertStringVector(calpwstr); // VT_LPWSTR
|
|
AssertStringVector(cabstr); // VT_BSTR
|
|
AssertStringVector(calpstr); // VT_LPSTR
|
|
for (i = 0; i < calpstr.cElems; i++)
|
|
{
|
|
if (calpstr.pElems[i] == NULL)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_VARIANT:
|
|
for (i = 0; i < capropvar.cElems; i++)
|
|
{
|
|
if (!((CAllocStorageVariant *) &capropvar.pElems[i])->IsValid())
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_ARRAY | VT_I4:
|
|
case VT_ARRAY | VT_UI1:
|
|
case VT_ARRAY | VT_I2:
|
|
case VT_ARRAY | VT_R4:
|
|
case VT_ARRAY | VT_R8:
|
|
case VT_ARRAY | VT_BOOL:
|
|
case VT_ARRAY | VT_ERROR:
|
|
case VT_ARRAY | VT_CY:
|
|
case VT_ARRAY | VT_DATE:
|
|
case VT_ARRAY | VT_I1:
|
|
case VT_ARRAY | VT_UI2:
|
|
case VT_ARRAY | VT_UI4:
|
|
case VT_ARRAY | VT_INT:
|
|
case VT_ARRAY | VT_UINT:
|
|
case VT_ARRAY | VT_BSTR:
|
|
case VT_ARRAY | VT_DECIMAL:
|
|
case VT_ARRAY | VT_VARIANT:
|
|
{
|
|
SAFEARRAY *pSa = parray;
|
|
|
|
if ( 0 == pSa )
|
|
return FALSE;
|
|
|
|
if ( !(pSa->cDims && pSa->pvData) )
|
|
return FALSE;
|
|
|
|
// validate all the bstrs are allocated
|
|
|
|
if ( ( VT_BSTR | VT_ARRAY ) == vt )
|
|
{
|
|
unsigned cDataElements = SaCountElements(*pSa);
|
|
BSTR *pBstr = (BSTR *)pSa->pvData;
|
|
|
|
for ( i = 0; i < cDataElements; i++ )
|
|
if ( 0 == pBstr[i] )
|
|
return FALSE;
|
|
}
|
|
if ( ( VT_VARIANT | VT_ARRAY ) == vt )
|
|
{
|
|
unsigned cDataElements = SaCountElements(*pSa);
|
|
CAllocStorageVariant *pVarnt = (CAllocStorageVariant *)pSa->pvData;
|
|
|
|
for ( i = 0; i < cDataElements; i++ )
|
|
if ( ! pVarnt[i].IsValid() )
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_BYREF | VT_I2:
|
|
case VT_BYREF | VT_I4:
|
|
case VT_BYREF | VT_R4:
|
|
case VT_BYREF | VT_R8:
|
|
case VT_BYREF | VT_CY:
|
|
case VT_BYREF | VT_DATE:
|
|
case VT_BYREF | VT_ERROR:
|
|
case VT_BYREF | VT_BOOL:
|
|
case VT_BYREF | VT_I1:
|
|
case VT_BYREF | VT_UI1:
|
|
case VT_BYREF | VT_UI2:
|
|
case VT_BYREF | VT_UI4:
|
|
case VT_BYREF | VT_INT:
|
|
case VT_BYREF | VT_UINT:
|
|
return (piVal != 0);
|
|
|
|
case VT_BYREF | VT_BSTR:
|
|
return ( pbstrVal != 0 && *pbstrVal != 0 );
|
|
|
|
case VT_BYREF | VT_DECIMAL:
|
|
return ( pdecVal != 0 &&
|
|
( 0 == pdecVal->sign || DECIMAL_NEG == pdecVal->sign ) );
|
|
|
|
case VT_BYREF | VT_VARIANT:
|
|
return ( pvarVal != 0 && pvarVal->vt != (VT_BYREF|VT_VARIANT) &&
|
|
((CAllocStorageVariant*)pvarVal)->IsValid() );
|
|
|
|
default:
|
|
ASSERT(!"CAllocStorageVariant::IsValid -- Invalid variant type");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
CAllocStorageVariant::CAllocStorageVariant(
|
|
PDeSerStream& stm,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
Unmarshall(stm, *((PROPVARIANT *)this), ma);
|
|
}
|
|
|
|
|
|
#define VECTOR_SET_BODY(type, vtype, val, aval) \
|
|
\
|
|
void CAllocStorageVariant::Set##vtype( \
|
|
type val, \
|
|
unsigned pos, \
|
|
PMemoryAllocator &ma) \
|
|
{ \
|
|
if (vt != ( VT_##vtype | VT_VECTOR ) ) \
|
|
{ \
|
|
ResetType(ma); \
|
|
new (this) CAllocStorageVariant(VT_##vtype, pos, ma); \
|
|
} \
|
|
\
|
|
if (pos >= cai.cElems) \
|
|
{ \
|
|
type *pTemp = aval.pElems; \
|
|
aval.pElems = (type *) ma.Allocate( (pos+1) * sizeof(aval.pElems[0]));\
|
|
if (aval.pElems != NULL) \
|
|
{ \
|
|
memcpy(aval.pElems, pTemp, aval.cElems * sizeof(aval.pElems[0])); \
|
|
memset( \
|
|
&aval.pElems[aval.cElems], \
|
|
0, \
|
|
(( pos+1 ) - aval.cElems) * sizeof(aval.pElems[0])); \
|
|
aval.pElems[pos] = val; \
|
|
aval.cElems = pos+1; \
|
|
ma.Free(pTemp); \
|
|
} \
|
|
} \
|
|
else \
|
|
{ \
|
|
aval.pElems[pos] = val; \
|
|
} \
|
|
}
|
|
|
|
|
|
#define VECTOR_GET_BODY(type, vtype, aval, nullval) \
|
|
\
|
|
type CAllocStorageVariant::Get##vtype(unsigned pos) const \
|
|
{ \
|
|
if (vt == (VT_##vtype | VT_VECTOR) && pos < aval.cElems) \
|
|
{ \
|
|
return(aval.pElems[pos]); \
|
|
} \
|
|
return(nullval); \
|
|
}
|
|
|
|
|
|
VECTOR_SET_BODY(CHAR, I1, i, cac)
|
|
VECTOR_GET_BODY(CHAR, I1, cac, 0)
|
|
|
|
VECTOR_SET_BODY(BYTE, UI1, ui, caub)
|
|
VECTOR_GET_BODY(BYTE, UI1, caub, 0)
|
|
|
|
VECTOR_SET_BODY(short, I2, i, cai)
|
|
VECTOR_GET_BODY(short, I2, cai, 0)
|
|
|
|
VECTOR_SET_BODY(USHORT, UI2, ui, caui)
|
|
VECTOR_GET_BODY(USHORT, UI2, caui, 0)
|
|
|
|
VECTOR_SET_BODY(long, I4, l, cal)
|
|
VECTOR_GET_BODY(long, I4, cal, 0)
|
|
|
|
VECTOR_SET_BODY(ULONG, UI4, ul, caul)
|
|
VECTOR_GET_BODY(ULONG, UI4, caul, 0)
|
|
|
|
VECTOR_SET_BODY(SCODE, ERROR, scode, cascode)
|
|
VECTOR_GET_BODY(SCODE, ERROR, cascode, 0)
|
|
|
|
static LARGE_INTEGER const liZero = { 0, 0 };
|
|
VECTOR_SET_BODY(LARGE_INTEGER, I8, li, cah)
|
|
VECTOR_GET_BODY(LARGE_INTEGER, I8, cah, liZero)
|
|
|
|
static ULARGE_INTEGER const uliZero = { 0, 0 };
|
|
VECTOR_SET_BODY(ULARGE_INTEGER, UI8, uli, cauh)
|
|
VECTOR_GET_BODY(ULARGE_INTEGER, UI8, cauh, uliZero)
|
|
|
|
VECTOR_SET_BODY(float, R4, f, caflt)
|
|
VECTOR_GET_BODY(float, R4, caflt, (float)0.0)
|
|
|
|
VECTOR_SET_BODY(double, R8, d, cadbl)
|
|
VECTOR_GET_BODY(double, R8, cadbl, 0.0)
|
|
|
|
VECTOR_SET_BODY(VARIANT_BOOL, BOOL, b, cabool)
|
|
VECTOR_GET_BODY(VARIANT_BOOL, BOOL, cabool, FALSE)
|
|
|
|
static CY const cyZero = { 0, 0 };
|
|
VECTOR_SET_BODY(CY, CY, cy, cacy)
|
|
VECTOR_GET_BODY(CY, CY, cacy, cyZero)
|
|
|
|
VECTOR_SET_BODY(DATE, DATE, d, cadate)
|
|
VECTOR_GET_BODY(DATE, DATE, cadate, 0.0)
|
|
|
|
|
|
BOOLEAN
|
|
CAllocStorageVariant::_AddStringToVector(
|
|
unsigned pos,
|
|
VOID *pv,
|
|
ULONG cb,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
ASSERT(vt == (VT_VECTOR | VT_BSTR) ||
|
|
vt == (VT_VECTOR | VT_LPSTR) ||
|
|
vt == (VT_VECTOR | VT_LPWSTR));
|
|
ASSERT(calpstr.pElems != NULL);
|
|
|
|
if (pos >= calpstr.cElems)
|
|
{
|
|
char **ppsz = calpstr.pElems;
|
|
|
|
calpstr.pElems =
|
|
(char **) ma.Allocate((pos + 1) * sizeof(calpstr.pElems[0]));
|
|
if (calpstr.pElems == NULL)
|
|
{
|
|
calpstr.pElems = ppsz;
|
|
return(FALSE);
|
|
}
|
|
memcpy(calpstr.pElems, ppsz, calpstr.cElems * sizeof(calpstr.pElems[0]));
|
|
memset(
|
|
&calpstr.pElems[calpstr.cElems],
|
|
0,
|
|
((pos + 1) - calpstr.cElems) * sizeof(calpstr.pElems[0]));
|
|
calpstr.cElems = pos + 1;
|
|
ma.Free(ppsz);
|
|
}
|
|
|
|
if ( vt == (VT_VECTOR|VT_BSTR) )
|
|
{
|
|
BSTR bstrVal = SysAllocString( (OLECHAR *)pv );
|
|
|
|
if (bstrVal == NULL)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
if ( cabstr.pElems[pos] != NULL )
|
|
{
|
|
SysFreeString(cabstr.pElems[pos]);
|
|
}
|
|
|
|
cabstr.pElems[pos] = bstrVal;
|
|
}
|
|
else
|
|
{
|
|
char *psz = (char *) ma.Allocate(cb);
|
|
|
|
if (psz == NULL)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
memcpy(psz, pv, cb);
|
|
|
|
if (calpstr.pElems[pos] != NULL)
|
|
{
|
|
ma.Free(calpstr.pElems[pos]);
|
|
}
|
|
calpstr.pElems[pos] = psz;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
void
|
|
CAllocStorageVariant::SetBSTR(BSTR b, PMemoryAllocator &ma)
|
|
{
|
|
ResetType(ma);
|
|
vt = VT_BSTR;
|
|
|
|
bstrVal = SysAllocString(b);
|
|
}
|
|
|
|
|
|
void
|
|
CAllocStorageVariant::SetBSTR(
|
|
BSTR b,
|
|
unsigned pos,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
if (vt != (VT_VECTOR | VT_BSTR))
|
|
{
|
|
ResetType(ma);
|
|
new (this) CAllocStorageVariant(VT_BSTR, pos, ma);
|
|
}
|
|
|
|
_AddStringToVector(
|
|
pos,
|
|
b,
|
|
-1, // not used, pass an invalid value to detect failure.
|
|
ma);
|
|
}
|
|
|
|
|
|
void
|
|
CAllocStorageVariant::SetLPSTR(
|
|
char const *psz,
|
|
unsigned pos,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
if (vt != (VT_VECTOR | VT_LPSTR))
|
|
{
|
|
ResetType(ma);
|
|
new (this) CAllocStorageVariant(VT_LPSTR, pos, ma);
|
|
}
|
|
_AddStringToVector(pos, (VOID *) psz, strlen(psz) + 1, ma);
|
|
}
|
|
|
|
|
|
void
|
|
CAllocStorageVariant::SetLPWSTR(
|
|
WCHAR const *pwsz,
|
|
unsigned pos,
|
|
PMemoryAllocator &ma)
|
|
{
|
|
if (vt != (VT_VECTOR | VT_LPWSTR))
|
|
{
|
|
ResetType(ma);
|
|
new (this) CAllocStorageVariant(VT_LPWSTR, pos, ma);
|
|
}
|
|
_AddStringToVector(
|
|
pos,
|
|
(VOID *) pwsz,
|
|
(wcslen(pwsz) + 1) * sizeof(WCHAR),
|
|
ma);
|
|
}
|
|
|
|
|
|
VECTOR_GET_BODY(char *, LPSTR, calpstr, 0);
|
|
VECTOR_GET_BODY(WCHAR *, LPWSTR, calpwstr, 0);
|
|
|
|
static FILETIME const fiZero = { 0, 0 };
|
|
VECTOR_SET_BODY(FILETIME, FILETIME, ft, cafiletime)
|
|
VECTOR_GET_BODY(FILETIME, FILETIME, cafiletime, fiZero)
|
|
|
|
static CLSID const guidZero =
|
|
{
|
|
0x00000000,
|
|
0x0000,
|
|
0x0000,
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
|
};
|
|
|
|
VECTOR_SET_BODY(CLSID, CLSID, c, cauuid)
|
|
VECTOR_GET_BODY(CLSID, CLSID, cauuid, guidZero)
|
|
#endif //ifndef _NTDLLBUILD_
|