Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

513 lines
11 KiB

//+--------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: cpropvar.cxx
//
//---------------------------------------------------------------
#include "cpropvar.hxx"
#include "chresult.hxx"
#include <stdio.h>
#include "../../h/tchar.h"
// this function is from refstg
BOOLEAN STDCALL
RtlCompareVariants(
USHORT CodePage,
PROPVARIANT const *pvar1,
PROPVARIANT const *pvar2);
DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPSTR, LPSTR);
DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(LPSTR, calpstr, pszVal );
DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPWSTR, LPWSTR);
DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(LPWSTR, calpwstr, pwszVal );
DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CF, CLIPDATA&);
DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CF, CClipData&);
DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CLSID, CLSID);
CPropVariant::CPropVariant( VARENUM v, ULONG cElements)
{
Init(v, cElements);
}
void CPropVariant::Init(
VARENUM v,
ULONG cElements)
{
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_UI1:
cbElement = sizeof(caub.pElems[0]);
break;
case VT_VECTOR | VT_I2:
case VT_VECTOR | VT_UI2:
case VT_VECTOR | 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:
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:
cbElement = sizeof(cah.pElems[0]);
break;
case VT_VECTOR | VT_CLSID:
cbElement = sizeof(GUID);
fZero = TRUE;
break;
case VT_VECTOR | VT_CF:
cbElement = sizeof(CLIPDATA);
fZero = TRUE;
break;
case VT_VECTOR | VT_BSTR:
case VT_VECTOR | VT_LPSTR:
case VT_VECTOR | VT_LPWSTR:
cbElement = sizeof(VOID *);
fZero = TRUE;
break;
case VT_VECTOR | 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 *) CoTaskMemAlloc(cElements * cbElement);
if (caub.pElems != NULL)
{
if (fZero)
{
memset(caub.pElems, 0, cElements * cbElement);
}
caub.cElems = cElements;
}
}
}
VOID *
CPropVariant::_AddStringToVector(
unsigned pos,
VOID *pv,
ULONG cb)
{
ASSERT(vt == (VT_VECTOR | VT_BSTR) ||
vt == (VT_VECTOR | VT_LPSTR) ||
vt == (VT_VECTOR | VT_LPWSTR) ||
vt == (VT_VECTOR | VT_CF) );
ASSERT(calpstr.pElems != NULL);
if (pos >= calpstr.cElems)
{
char **ppsz = calpstr.pElems;
calpstr.pElems =
(char **) CoTaskMemAlloc((pos + 1) * sizeof(calpstr.pElems[0]));
if (calpstr.pElems == NULL)
{
calpstr.pElems = ppsz;
return(NULL);
}
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;
CoTaskMemFree(ppsz);
}
LPSTR psz;
if( (VT_VECTOR | VT_BSTR) == vt )
{
psz = (LPSTR) SysAllocString( (BSTR) pv );
if (psz == NULL)
{
return(NULL);
}
if (calpstr.pElems[pos] != NULL)
{
SysFreeString((BSTR) calpstr.pElems[pos]);
}
calpstr.pElems[pos] = psz;
}
else
{
psz = (LPSTR) CoTaskMemAlloc((VT_BSTR == (vt & ~VT_VECTOR) )
? cb + sizeof(ULONG)
: cb );
if (psz == NULL)
{
return(NULL);
}
memcpy(psz, pv, cb);
if (calpstr.pElems[pos] != NULL)
{
CoTaskMemFree(calpstr.pElems[pos]);
}
calpstr.pElems[pos] = psz;
}
return(calpstr.pElems[pos]);
}
VOID *
CPropVariant::_AddScalerToVector(
unsigned pos,
VOID *pv,
ULONG cb)
{
ASSERT(calpstr.pElems != NULL);
if (pos >= calpstr.cElems)
{
char **ppsz = calpstr.pElems;
calpstr.pElems =
(char **) CoTaskMemAlloc((pos + 1) * cb);
if (calpstr.pElems == NULL)
{
calpstr.pElems = ppsz;
return(NULL);
}
memset(
calpstr.pElems,
0,
((pos + 1) - calpstr.cElems) * cb);
memcpy(calpstr.pElems, ppsz, calpstr.cElems * cb);
calpstr.cElems = pos + 1;
CoTaskMemFree(ppsz);
}
memcpy( (BYTE*)calpstr.pElems + pos*cb, pv, cb );
return( (BYTE*)calpstr.pElems + pos*cb );
}
void
CPropVariant::SetLPSTR(
char const *psz,
unsigned pos)
{
if (vt != (VT_VECTOR | VT_LPSTR))
{
PropVariantClear( this );
new (this) CPropVariant(VT_LPSTR, pos);
}
_AddStringToVector(pos, (VOID *) psz, strlen(psz) + 1);
}
void
CPropVariant::SetLPWSTR(
WCHAR const *pwsz,
unsigned pos)
{
if (vt != (VT_VECTOR | VT_LPWSTR))
{
PropVariantClear( this );
new (this) CPropVariant(VT_LPWSTR, pos);
}
_AddStringToVector(pos, (VOID *) pwsz,
sizeof(WCHAR) * (wcslen(pwsz) + 1) );
}
void
CPropVariant::SetCF(
const CLIPDATA *pclipdata,
unsigned pos)
{
CLIPDATA *pclipdataNew;
if (vt != (VT_VECTOR | VT_CF))
{
PropVariantClear( this );
new (this) CPropVariant(VT_CF, pos);
}
pclipdataNew = (CLIPDATA*) _AddScalerToVector(pos, (VOID *) pclipdata, sizeof(CLIPDATA) );
if( NULL != pclipdataNew
&&
NULL != pclipdata )
{
pclipdataNew->pClipData = (BYTE*) CoTaskMemAlloc( CBPCLIPDATA(*pclipdata) );
if( NULL == pclipdataNew->pClipData )
{
ASSERT( !"Couldn't allocate pclipdataNew" );
return;
}
else
{
pclipdataNew->cbSize = pclipdata->cbSize;
pclipdataNew->ulClipFmt = pclipdata->ulClipFmt;
memcpy( pclipdataNew->pClipData,
pclipdata->pClipData,
CBPCLIPDATA(*pclipdata) );
return;
}
}
}
void
CPropVariant::SetBSTR(
const BSTR pbstr,
unsigned int pos)
{
if (vt != (VT_VECTOR | VT_BSTR))
{
PropVariantClear( this );
new (this) CPropVariant(VT_BSTR, pos+1);
}
_AddStringToVector(pos, (VOID *) pbstr,
sizeof(OLECHAR) * (ocslen(pbstr) + 1) );
}
BSTR
CPropVariant::GetBSTR( int nSubscript )
{
ASSERT( vt & VT_VECTOR );
ASSERT( vt == (VT_BSTR | VT_VECTOR) );
ASSERT( wReserved1 > 0 );
if( wReserved1 > 0
&&
cabstr.cElems > 0
&&
wReserved1 <= cabstr.cElems )
{
int nSubscript = wReserved1 - 1;
wReserved1 = INVALID_SUBSCRIPT;
return( cabstr.pElems[ nSubscript ] );
}
else
return( NULL );
}
CPropVariant & CPropVariant::operator=(LPPROPVARIANT lppropvar)
{
if( INVALID_SUBSCRIPT == wReserved1 )
{
ASSERT( INVALID_SUBSCRIPT != wReserved1 );
PropVariantClear(this);
Init();
return (*this);
}
else
{
if( !(vt & VT_VECTOR)
||
(vt & ~VT_VECTOR) != VT_VARIANT )
{
USHORT wReserved1Save = wReserved1;
PropVariantClear(this);
Init(VT_VARIANT, wReserved1Save );
wReserved1 = wReserved1Save;
}
SetLPPROPVARIANT( lppropvar, wReserved1 - 1 );
wReserved1 = INVALID_SUBSCRIPT;
return (*this);
}
}
CPropVariant::operator LPPROPVARIANT()
{
if( vt & VT_VECTOR )
{
if( wReserved1 > 0
&&
capropvar.cElems > 0
&&
wReserved1 <= capropvar.cElems )
{
int nSubscript = wReserved1 - 1;
wReserved1 = INVALID_SUBSCRIPT;
return( &capropvar.pElems[ nSubscript ] );
}
else
{
ASSERT( INVALID_SUBSCRIPT == wReserved1 );
return( (LPPROPVARIANT) this );
}
}
else
return( (LPPROPVARIANT) this );
}
void
CPropVariant::SetLPPROPVARIANT( LPPROPVARIANT lppropvar, unsigned pos )
{
if (vt != (VT_VECTOR | VT_VARIANT))
{
PropVariantClear( this );
new (this) CPropVariant(VT_VARIANT, pos + 1);
}
if (pos >= capropvar.cElems)
{
LPPROPVARIANT rgpropvar = capropvar.pElems;
capropvar.pElems =
(PROPVARIANT *) CoTaskMemAlloc((pos + 1) * sizeof(capropvar.pElems[0]));
if (capropvar.pElems == NULL)
{
capropvar.pElems = rgpropvar;
return;
}
memcpy(capropvar.pElems, rgpropvar, capropvar.cElems * sizeof(capropvar.pElems[0]));
memset(
&capropvar.pElems[capropvar.cElems],
0,
((pos + 1) - capropvar.cElems) * sizeof(capropvar.pElems[0]));
capropvar.cElems = pos + 1;
CoTaskMemFree(rgpropvar);
}
PropVariantClear( &capropvar.pElems[pos] );
PropVariantCopy( &capropvar.pElems[pos], lppropvar );
return;
}
void CPropVariant::Init(const CLIPDATA *p)
{
Init();
if( NULL == p )
return;
pclipdata = (CLIPDATA*) CoTaskMemAlloc( sizeof(CLIPDATA) );
if( NULL == pclipdata )
{
return;
}
pclipdata->cbSize = p->cbSize;
pclipdata->ulClipFmt = p->ulClipFmt;
pclipdata->pClipData = NULL;
if( sizeof(pclipdata->ulClipFmt) > p->cbSize )
{
Init();
return;
}
if( NULL != p->pClipData )
{
pclipdata->pClipData = (BYTE*) CoTaskMemAlloc( pclipdata->cbSize
- sizeof(pclipdata->ulClipFmt) );
if( NULL == pclipdata->pClipData )
return;
memcpy( pclipdata->pClipData, p->pClipData, pclipdata->cbSize - sizeof(pclipdata->ulClipFmt) );
}
vt = VT_CF;
}
void
CPropVariant::SetCLSID( const CLSID &clsid )
{
PropVariantClear( this );
puuid = (CLSID*) CoTaskMemAlloc( sizeof(CLSID) );
if( NULL == puuid )
{
assert(FALSE && "out of memory!");
exit(-1);
}
*puuid = clsid;
vt = VT_CLSID;
}
void
CPropVariant::SetCLSID(
const CLSID &clsid,
unsigned pos)
{
CLSID *pclsidNew;
if (vt != (VT_VECTOR | VT_CLSID))
{
PropVariantClear( this );
new (this) CPropVariant(VT_CLSID, pos);
}
pclsidNew = (CLSID*) _AddScalerToVector(pos, (VOID *) &clsid, sizeof(CLSID) );
if( NULL != pclsidNew )
{
*pclsidNew = clsid;
}
}
HRESULT
CPropVariant::Compare( PROPVARIANT *ppropvar1, PROPVARIANT *ppropvar2 )
{
if( RtlCompareVariants( CP_ACP, // Ignored,
ppropvar1,
ppropvar2 ))
{
return( S_OK );
}
else
{
return( S_FALSE );
}
}