743 lines
18 KiB
C++
743 lines
18 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: variant.cxx
|
|
//
|
|
// Contents: Variant helper API stubs
|
|
//
|
|
// Functions: StgVariantClear
|
|
// StgVariantCopy
|
|
//
|
|
// History: 30-Jun-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
#include "headers.cxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
void CopyString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
|
|
void FreeString(PROPVARIANT *pvar);
|
|
|
|
void CopyWString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
|
|
void FreeWString(PROPVARIANT *pvar);
|
|
|
|
void CopyBString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
|
|
void FreeBString(PROPVARIANT *pvar);
|
|
|
|
void CopyUUID(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
|
|
void FreeUUID(PROPVARIANT *pvar);
|
|
|
|
void CopyArray(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest, ULONG cbElem);
|
|
void FreeArray(PROPVARIANT *pvar);
|
|
|
|
void CopyStrings(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
|
|
void FreeStrings(PROPVARIANT *pvar);
|
|
|
|
void CopyWStrings(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
|
|
void FreeWStrings(PROPVARIANT *pvar);
|
|
|
|
void CopyVariants(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
|
|
void FreeVariants(PROPVARIANT *pvar);
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: StgVariantCopy (stub)
|
|
//
|
|
// Synopsis: Copies a variant structure
|
|
//
|
|
// Arguments: [pvargDest] - destination variant
|
|
// [pvargSrc] - source variant
|
|
//
|
|
// Modifies: [pvargDest]
|
|
//
|
|
// History: 30-Jun-93 CarlH Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
HRESULT StgVariantCopy(PROPVARIANTARG *pvargDest, PROPVARIANTARG *pvargSrc)
|
|
{
|
|
Win4Assert(!(pvargSrc->vt & VT_BYREF) && "VariantCopy() does not support VT_BYREF yet!");
|
|
|
|
// Copy the fields of the variant first. If the source contains
|
|
// a value that needs special treatment, we'll take care of it
|
|
// after this.
|
|
//
|
|
*pvargDest = *pvargSrc;
|
|
|
|
// We need to figure out if this variant contains a value that requires
|
|
// any special treatment (e.g. an interface or data pointer).
|
|
//
|
|
switch (pvargSrc->vt)
|
|
{
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_I2:
|
|
case VT_I4:
|
|
case VT_I8:
|
|
case VT_R4:
|
|
case VT_R8:
|
|
case VT_BOOL:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_FILETIME:
|
|
case VT_ERROR:
|
|
break;
|
|
case VT_BSTR:
|
|
Win4Assert(!"StgVariantCopy() does not support VT_BSTR yet!");
|
|
break;
|
|
|
|
case VT_LPSTR:
|
|
CopyString(pvargSrc, pvargDest);
|
|
break;
|
|
|
|
case VT_LPWSTR:
|
|
CopyWString(pvargSrc, pvargDest);
|
|
break;
|
|
|
|
case VT_CLSID:
|
|
CopyUUID(pvargSrc, pvargDest);
|
|
break;
|
|
|
|
case VT_BLOB:
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->blob.pBlobData));
|
|
break;
|
|
|
|
case (VT_VECTOR | VT_I2):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cai.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_I4):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cal.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_I8):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cali.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_R4):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->caflt.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_R8):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cadbl.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_BOOL):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cabool.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_CY):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cacy.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_DATE):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cadate.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_FILETIME):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cafiletime.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_CLSID):
|
|
CopyArray(
|
|
pvargSrc,
|
|
pvargDest,
|
|
sizeof(*pvargSrc->cauuid.pElems));
|
|
break;
|
|
case (VT_VECTOR | VT_LPSTR):
|
|
CopyStrings(pvargSrc, pvargDest);
|
|
break;
|
|
case (VT_VECTOR | VT_LPWSTR):
|
|
CopyWStrings(pvargSrc, pvargDest);
|
|
break;
|
|
case (VT_VECTOR | VT_BSTR):
|
|
Win4Assert(!"VariantCopy() does not support VT_VECTOR | VT_BSTR yet!");
|
|
break;
|
|
case (VT_VECTOR | VT_VARIANT):
|
|
CopyVariants(pvargSrc, pvargDest);
|
|
break;
|
|
case VT_CF:
|
|
Win4Assert(!"VariantCopy() does not support VT_CF yet!");
|
|
break;
|
|
case VT_SAFEARRAY:
|
|
Win4Assert(!"VariantCopy() does not support VT_SAFEARRAY yet!");
|
|
break;
|
|
#ifdef FULL_VARIANT
|
|
// BUGBUG: [mikese] I'm pretty sure this is wrong for PROPVARIANT
|
|
|
|
case VT_STREAM:
|
|
pvargSrc->pStream->AddRef();
|
|
pvargDest->pStream = pvargSrc->pStream;
|
|
break;
|
|
|
|
case VT_STORAGE:
|
|
pvargSrc->pStorage->AddRef();
|
|
pvargDest->pStorage = pvargSrc->pStorage;
|
|
break;
|
|
#endif // FULL_VARIANT
|
|
default:
|
|
Win4Assert(!"VariantCopy() unknown type!");
|
|
break;
|
|
}
|
|
|
|
return (NO_ERROR);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: StgVariantClear
|
|
//
|
|
// Synopsis: Clears a variant structure
|
|
//
|
|
// Arguments: [pvarg] - variant to clear
|
|
//
|
|
// Modifies: [pvarg]
|
|
//
|
|
// History: 30-Jun-93 CarlH Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
HRESULT StgVariantClear(PROPVARIANTARG *pvarg)
|
|
{
|
|
Win4Assert(!(pvarg->vt & VT_BYREF) && "VariantClear() does not support VT_BYREF yet!");
|
|
|
|
// We need to figure out if this variant contains a value that requires
|
|
// any special treatment (e.g. an interface or data pointer).
|
|
//
|
|
switch (pvarg->vt)
|
|
{
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_I2:
|
|
case VT_I4:
|
|
case VT_I8:
|
|
case VT_R4:
|
|
case VT_R8:
|
|
case VT_BOOL:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_FILETIME:
|
|
case VT_ERROR:
|
|
break;
|
|
case VT_BSTR:
|
|
Win4Assert(!"VariantClear() does not support VT_BSTR yet!");
|
|
break;
|
|
case VT_LPSTR:
|
|
FreeString(pvarg);
|
|
break;
|
|
case VT_LPWSTR:
|
|
FreeWString(pvarg);
|
|
break;
|
|
case VT_CLSID:
|
|
FreeUUID(pvarg);
|
|
break;
|
|
case VT_BLOB:
|
|
case (VT_VECTOR | VT_I2):
|
|
case (VT_VECTOR | VT_I4):
|
|
case (VT_VECTOR | VT_I8):
|
|
case (VT_VECTOR | VT_R4):
|
|
case (VT_VECTOR | VT_R8):
|
|
case (VT_VECTOR | VT_BOOL):
|
|
case (VT_VECTOR | VT_CY):
|
|
case (VT_VECTOR | VT_DATE):
|
|
case (VT_VECTOR | VT_FILETIME):
|
|
case (VT_VECTOR | VT_CLSID):
|
|
FreeArray(pvarg);
|
|
break;
|
|
case (VT_VECTOR | VT_LPSTR):
|
|
FreeStrings(pvarg);
|
|
break;
|
|
case (VT_VECTOR | VT_LPWSTR):
|
|
FreeWStrings(pvarg);
|
|
break;
|
|
case (VT_VECTOR | VT_BSTR):
|
|
Win4Assert(!"VariantClear() does not support VT_VECTOR | VT_BSTR yet!");
|
|
break;
|
|
case (VT_VECTOR | VT_VARIANT):
|
|
FreeVariants(pvarg);
|
|
break;
|
|
case VT_SAFEARRAY:
|
|
Win4Assert(!"VariantClear() does not support VT_SAFEARRAY yet!");
|
|
break;
|
|
#ifdef FULL_VARIANT
|
|
case VT_STREAM:
|
|
pvarg->pStream->Release();
|
|
break;
|
|
|
|
case VT_STORAGE:
|
|
pvarg->pStorage->Release();
|
|
break;
|
|
|
|
#endif // FULL_VARIANT
|
|
default:
|
|
Win4Assert(!"VariantClear() unknown type!");
|
|
break;
|
|
}
|
|
|
|
// We have all of the important information about the variant, so
|
|
// let's clear it out.
|
|
//
|
|
StgVariantInit(pvarg);
|
|
|
|
return (NO_ERROR);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeStgVariantArray, public
|
|
//
|
|
// Synopsis: Frees a value array returned from ReadMultiple
|
|
//
|
|
// Arguments: [cval] - Number of elements
|
|
// [rgvar] - Array
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 18-Dec-92 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI FreeStgVariantArray (
|
|
ULONG cVariants,
|
|
PROPVARIANT *rgvars)
|
|
{
|
|
for ( ULONG I=0; I < cVariants; I++ )
|
|
StgVariantClear ( rgvars + I );
|
|
return S_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyString, private
|
|
//
|
|
// Synopsis: Copies a VARIANT thin string
|
|
//
|
|
// Arguments: [pvarSrc] - source VARIANT
|
|
// [pvarDest] - destination VARIANT
|
|
//
|
|
// Modifies: [pvarDest]
|
|
//
|
|
// History: 02-Jul-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void CopyString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
|
|
{
|
|
ULONG cb = (strlen(pvarSrc->pszVal) + 1) * sizeof(*pvarSrc->pszVal);
|
|
|
|
if ((pvarDest->pszVal = (char *)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
strcpy(pvarDest->pszVal, pvarSrc->pszVal);
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeString, private
|
|
//
|
|
// Synopsis: Frees a VARIANT thin string
|
|
//
|
|
// Arguments: [pvar] - variant of which to free string
|
|
//
|
|
// History: 07-12-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void FreeString(PROPVARIANT *pvar)
|
|
{
|
|
CoTaskMemFree(pvar->pszVal);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyWString, private
|
|
//
|
|
// Synopsis: Copies a PROPVARIANT wide string
|
|
//
|
|
// Arguments: [pvarSrc] - source PROPVARIANT
|
|
// [pvarDest] - destination PROPVARIANT
|
|
//
|
|
// Modifies: [pvarDest]
|
|
//
|
|
// History: 02-Jul-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void CopyWString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
|
|
{
|
|
ULONG cb = (wcslen(pvarSrc->pwszVal) + 1) * sizeof(*pvarSrc->pwszVal);
|
|
|
|
if ((pvarDest->pwszVal = (WCHAR *)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
wcscpy(pvarDest->pwszVal, pvarSrc->pwszVal);
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeWString, private
|
|
//
|
|
// Synopsis: Frees a PROPVARIANT wide string
|
|
//
|
|
// Arguments: [pvar] - PROPVARIANT of which to free string
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// History: 07-12-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void FreeWString(PROPVARIANT *pvar)
|
|
{
|
|
CoTaskMemFree(pvar->pwszVal);
|
|
}
|
|
|
|
#ifdef BSTR_SUPPORT
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyBString, private
|
|
//
|
|
// Synopsis: Copies a PROPVARIANT wide basic string
|
|
//
|
|
// Arguments: [pvarSrc] - source PROPVARIANT
|
|
// [pvarDest] - destination PROPVARIANT
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// Modifies: [pvarDest]
|
|
//
|
|
// History: 02-Jul-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void CopyBString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
|
|
{
|
|
pvarDest->bstrVal = SysAllocString(pvarSrc->bstrVal);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeBString, private
|
|
//
|
|
// Synopsis: Frees a PROPVARIANT wide basic string
|
|
//
|
|
// Arguments: [pvar] - variant of which to free string
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// History: 07-12-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void FreeBString(PROPVARIANT *pvar)
|
|
{
|
|
SysFreeString(pvar->bstrVal);
|
|
}
|
|
|
|
#endif
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyUUID, private
|
|
//
|
|
// Synopsis: Copies a PROPVARIANT unique identifier
|
|
//
|
|
// Arguments: [pvarSrc] - source PROPVARIANT
|
|
// [pvarDest] - destination PROPVARIANT
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// Modifies: [pvarDest]
|
|
//
|
|
// History: 02-Jul-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void CopyUUID(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
|
|
{
|
|
ULONG cb = sizeof(*pvarSrc->puuid);
|
|
|
|
if ((pvarDest->puuid = (GUID *)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
*pvarDest->puuid = *pvarSrc->puuid;
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeUUID, private
|
|
//
|
|
// Synopsis: Frees a PROPVARIANT unique identifier
|
|
//
|
|
// Arguments: [pvar] - variant of which to identifier
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// History: 07-12-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void FreeUUID(PROPVARIANT *pvar)
|
|
{
|
|
CoTaskMemFree(pvar->puuid);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyArray, private
|
|
//
|
|
// Synopsis: Copies a PROPVARIANT counted array
|
|
//
|
|
// Arguments: [pvarSrc] - source PROPVARIANT
|
|
// [pvarDest] - destination PROPVARIANT
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// Modifies: [pvarDest]
|
|
//
|
|
// History: 02-Jul-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void CopyArray(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest, ULONG cbElem)
|
|
{
|
|
ULONG cb = pvarSrc->cai.cElems * cbElem;
|
|
|
|
// BUGBUG: What the hell should I cast this allocation to?
|
|
// I'm going to throw in (short *) for right now,
|
|
// but there must be something better.
|
|
//
|
|
if ((pvarDest->cai.pElems = (short *)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
pvarDest->cai.cElems = pvarSrc->cai.cElems;
|
|
|
|
memcpy(
|
|
pvarDest->cai.pElems,
|
|
pvarSrc->cai.pElems,
|
|
pvarSrc->cai.cElems * cbElem);
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeArray, private
|
|
//
|
|
// Synopsis: Frees a PROPVARIANT counted array
|
|
//
|
|
// Arguments: [pvar] - variant of which to counted array
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// History: 07-12-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void FreeArray(PROPVARIANT *pvar)
|
|
{
|
|
CoTaskMemFree(pvar->cai.pElems);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyStrings, private
|
|
//
|
|
// Synopsis: Copies a PROPVARIANT array of thin strings
|
|
//
|
|
// Arguments: [pvarSrc] - source PROPVARIANT
|
|
// [pvarDest] - destination PROPVARIANT
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// Modifies: [pvarDest]
|
|
//
|
|
// Notes: BUGBUG: If any of the allocations after the first
|
|
// one below fails, we are in big trouble because
|
|
// we are going to leak memory.
|
|
//
|
|
// History: 02-Jul-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void CopyStrings(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
|
|
{
|
|
ULONG cb;
|
|
|
|
// First, we need to allocate an array of string pointers
|
|
// to hold all of the strings we are copying.
|
|
//
|
|
pvarDest->calpstr.cElems = pvarSrc->calpstr.cElems;
|
|
|
|
cb = pvarSrc->calpstr.cElems * sizeof(*pvarSrc->calpstr.pElems);
|
|
if ((pvarDest->calpstr.pElems = (char **)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
// And now we need to allocate memory for each string
|
|
// and copy the source string to the destination.
|
|
//
|
|
for (ULONG ipsz = 0; ipsz < pvarSrc->calpstr.cElems; ipsz++)
|
|
{
|
|
cb = (strlen(pvarSrc->calpstr.pElems[ipsz]) + 1) *
|
|
sizeof(**pvarSrc->calpstr.pElems);
|
|
|
|
if ((pvarDest->calpstr.pElems[ipsz] = (char *)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
strcpy(
|
|
pvarDest->calpstr.pElems[ipsz],
|
|
pvarSrc->calpstr.pElems[ipsz]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeStrings, private
|
|
//
|
|
// Synopsis: Frees a PROPVARIANT array of thin strings
|
|
//
|
|
// Arguments: [pvar] - variant of which to free strings
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// History: 07-12-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void FreeStrings(PROPVARIANT *pvar)
|
|
{
|
|
for (ULONG ipsz = 0; ipsz < pvar->calpstr.cElems; ipsz++)
|
|
{
|
|
CoTaskMemFree(pvar->calpstr.pElems[ipsz]);
|
|
}
|
|
|
|
CoTaskMemFree(pvar->calpstr.pElems);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyWStrings, private
|
|
//
|
|
// Synopsis: Copies a PROPVARIANT array of wide strings
|
|
//
|
|
// Arguments: [pvarSrc] - source PROPVARIANT
|
|
// [pvarDest] - destination PROPVARIANT
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// Modifies: [pvarDest]
|
|
//
|
|
// History: 02-Jul-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void CopyWStrings(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
|
|
{
|
|
ULONG cb;
|
|
|
|
// First, we need to allocate an array of string pointers
|
|
// to hold all of the strings we are copying.
|
|
//
|
|
pvarDest->calpwstr.cElems = pvarSrc->calpwstr.cElems;
|
|
|
|
cb = pvarSrc->calpwstr.cElems * sizeof(*pvarSrc->calpwstr.pElems);
|
|
if ((pvarDest->calpwstr.pElems = (WCHAR **)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
// And now we need to allocate memory for each string
|
|
// and copy the source string to the destination.
|
|
//
|
|
for (ULONG ipsz = 0; ipsz < pvarSrc->calpwstr.cElems; ipsz++)
|
|
{
|
|
cb = (wcslen(pvarSrc->calpwstr.pElems[ipsz]) + 1) *
|
|
sizeof(**pvarSrc->calpwstr.pElems);
|
|
|
|
if ((pvarDest->calpwstr.pElems[ipsz] = (WCHAR *)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
wcscpy(
|
|
pvarDest->calpwstr.pElems[ipsz],
|
|
pvarSrc->calpwstr.pElems[ipsz]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeWStrings, private
|
|
//
|
|
// Synopsis: Frees a PROPVARIANT array of wide strings
|
|
//
|
|
// Arguments: [pvar] - variant of which to free strings
|
|
//
|
|
// Returns: NO_ERROR is successful, error value otherwise
|
|
//
|
|
// History: 07-12-93 CarlH Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void FreeWStrings(PROPVARIANT *pvar)
|
|
{
|
|
for (ULONG ipsz = 0; ipsz < pvar->calpwstr.cElems; ipsz++)
|
|
{
|
|
CoTaskMemFree(pvar->calpwstr.pElems[ipsz]);
|
|
}
|
|
|
|
CoTaskMemFree(pvar->calpwstr.pElems);
|
|
}
|
|
|
|
|
|
void CopyVariants(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
|
|
{
|
|
ULONG cb = sizeof(*pvarDest->castgvar.pElems) * pvarDest->castgvar.cElems;
|
|
|
|
if ((pvarDest->castgvar.pElems = (PROPVARIANT *)CoTaskMemAlloc(cb)) != NULL)
|
|
{
|
|
pvarDest->castgvar.cElems = pvarSrc->castgvar.cElems;
|
|
|
|
for (ULONG ivar = 0; ivar < pvarDest->castgvar.cElems; ivar++)
|
|
{
|
|
// BUGBUG: what do we do if one of these copies fails?
|
|
//
|
|
StgVariantCopy(
|
|
pvarDest->castgvar.pElems + ivar,
|
|
pvarSrc->castgvar.pElems + ivar);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FreeVariants(PROPVARIANT *pvar)
|
|
{
|
|
for (ULONG ivar = 0; ivar < pvar->castgvar.cElems; ivar++)
|
|
{
|
|
StgVariantClear(pvar->castgvar.pElems + ivar);
|
|
}
|
|
|
|
CoTaskMemFree(pvar->castgvar.pElems);
|
|
}
|
|
|
|
|