686 lines
17 KiB
C
686 lines
17 KiB
C
|
|
|
|
//====================================================================
|
|
//
|
|
// File:
|
|
// pstg_ca.c
|
|
//
|
|
// Purpose:
|
|
// This file provides helper functions for the
|
|
// IPropertyStorage call_as routines. Those call_as
|
|
// routines are necessary to convert BSTR properties
|
|
// into a remotable form (BSTR_BLOBs).
|
|
//
|
|
// BSTRs are always allocated from the OleAutomation
|
|
// heap. BSTR_BLOBs are always allocated from the
|
|
// IMalloc heap.
|
|
//
|
|
//====================================================================
|
|
|
|
#include <rpcproxy.h>
|
|
#include <privoa.h> // Private OleAutomation wrappers
|
|
#include "prstg_ca.h"
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: ContainsSpecialProperty
|
|
//
|
|
// Synopsis: This routine scans an array of PropVariants
|
|
// and checks for existance of a BSTR property
|
|
// or non-simple property. These types require
|
|
// special handling.
|
|
// This routine recurses on Variant Vectors.
|
|
//
|
|
// Pre-Conditions:
|
|
// None.
|
|
//
|
|
// Inputs: [ULONG] cElems
|
|
// Count of elements in the array.
|
|
// [LPPROPVARIANT] lppropvar
|
|
// The PropVariant[] to check.
|
|
//
|
|
// Outputs: An OR of the bits BSTR_EXISTS and
|
|
// NONSIMPLE_EXISTS, or 0 if neither exists.
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
|
|
ULONG
|
|
ContainsSpecialProperty( ULONG cElems, const PROPVARIANT rgpropvar[] )
|
|
{
|
|
ULONG ulVTExists = 0;
|
|
|
|
// Walk the array and search for BSTR and non-simple properties.
|
|
// Note that we will needlessly continue to search here even after
|
|
// we've found both a BSTR and a non-simple property. But to check
|
|
// for this condition would hurt normal-case performance, in order
|
|
// to make a savings in the error-case (since existance of a non-
|
|
// simple is an error).
|
|
|
|
ULONG ulIndex;
|
|
for( ulIndex = 0; ulIndex < cElems; ulIndex++ )
|
|
{
|
|
switch( rgpropvar[ ulIndex ].vt )
|
|
{
|
|
// Is this a BSTR?
|
|
|
|
case VT_BSTR:
|
|
case (VT_BSTR | VT_VECTOR):
|
|
|
|
ulVTExists |= BSTR_EXISTS;
|
|
break;
|
|
|
|
// Or is it a non-simple?
|
|
|
|
case VT_STORAGE:
|
|
case VT_STREAM:
|
|
case VT_STORED_OBJECT:
|
|
case VT_STREAMED_OBJECT:
|
|
|
|
ulVTExists |= NONSIMPLE_EXISTS;
|
|
break;
|
|
|
|
// Or is it a vector of variants which we need
|
|
// to search recursively?
|
|
|
|
case (VT_VECTOR | VT_VARIANT):
|
|
|
|
ulVTExists |= ContainsSpecialProperty(
|
|
rgpropvar[ ulIndex ].capropvar.cElems,
|
|
rgpropvar[ ulIndex ].capropvar.pElems );
|
|
break;
|
|
|
|
} // switch( rgpropvar[ ulIndex ].vt )
|
|
} // for( ulIndex = 0; ulIndex < cElems; ulIndex++ )
|
|
|
|
|
|
return( ulVTExists );
|
|
|
|
} // ContainsSpecialProperty()
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: PropVarMarshalBstr
|
|
//
|
|
// Synopsis: This routine converts a PropVariant from a BSTR to a
|
|
// BSTR_BLOB. The old buffer is freed (from the OleAut
|
|
// heap) and the new buffer is allocated from the
|
|
// IMalloc heap.
|
|
//
|
|
// Pre-Conditions:
|
|
// The input is a VT_BSTR.
|
|
//
|
|
// Inputs: [LPPROPVARIANT] lppropvar
|
|
// The PropVariant to convert.
|
|
//
|
|
// Outputs: HRESULT.
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
PropVarMarshalBstr( LPPROPVARIANT lppropvar )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Save a pointer to the characters.
|
|
BSTR bstrVal = lppropvar->bstrVal;
|
|
|
|
// Is this a NULL BSTR value?
|
|
|
|
if( NULL == bstrVal )
|
|
{
|
|
lppropvar->bstrblobVal.cbSize = 0;
|
|
lppropvar->bstrblobVal.pData = NULL;
|
|
}
|
|
else
|
|
{
|
|
// Set the size to be the *byte* count of the string, plus
|
|
// the bytes for the length DWORD, plus the bytes for the NULL
|
|
// terminator.
|
|
|
|
lppropvar->bstrblobVal.cbSize = *SYSSTRINGBUF( bstrVal )
|
|
+ sizeof(ULONG)
|
|
+ sizeof(OLECHAR);
|
|
|
|
|
|
// Reallocate with IMalloc (as opposed to SysAllocString).
|
|
lppropvar->bstrblobVal.pData
|
|
= (BYTE*) CoTaskMemAlloc( lppropvar->bstrblobVal.cbSize );
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
// Copy the BSTR, including the length field and the NULL.
|
|
memcpy( lppropvar->bstrblobVal.pData,
|
|
(BYTE*) SYSSTRINGBUF( bstrVal ),
|
|
lppropvar->bstrblobVal.cbSize);
|
|
|
|
// Free the old value.
|
|
PrivSysFreeString( bstrVal );
|
|
bstrVal = NULL;
|
|
|
|
} // if( NULL == bstrVal ) ... else
|
|
|
|
|
|
// Convert the VT
|
|
lppropvar->vt = VT_BSTR_BLOB;
|
|
|
|
// ----
|
|
// Exit
|
|
// ----
|
|
|
|
Exit:
|
|
|
|
// Restore the input on failures.
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
// We don't need to free anything, because the
|
|
// only possible failure is from the one and only
|
|
// memory allocation.
|
|
|
|
lppropvar->bstrVal = bstrVal;
|
|
}
|
|
|
|
return( hr );
|
|
|
|
} // PropVarMarshalBstr
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: PropVarUnmarshalBstr
|
|
//
|
|
// Synopsis: We convert a PropVariant from a BSTR_BLOB to a
|
|
// BSTR. The new BSTR is allocated from the
|
|
// OleAutomation heap, and the old buffer is freed
|
|
// from the IMalloc heap.
|
|
//
|
|
// Pre-Conditions:
|
|
// The input is a VT_BSTR_BLOB.
|
|
//
|
|
// Inputs: [LPPROPVARIANT] lppropvar
|
|
// The PropVariant to convert.
|
|
//
|
|
// Outputs: HRESULT
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
PropVarUnmarshalBstr( LPPROPVARIANT lppropvar )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Save the original value.
|
|
BSTRBLOB bstrblob = lppropvar->bstrblobVal;
|
|
|
|
// Convert the Bstr property
|
|
|
|
if( NULL == bstrblob.pData )
|
|
{
|
|
// There is no BSTR buffer
|
|
lppropvar->bstrVal = NULL;
|
|
}
|
|
else
|
|
{
|
|
// Alloc a BSTR from OleAut32 heap, and copy to it the string data.
|
|
|
|
lppropvar->bstrVal = PrivSysAllocString( SYSSTRINGOFBUF( bstrblob.pData ));
|
|
if( NULL == lppropvar->bstrVal )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
// Free the old buffer
|
|
CoTaskMemFree( bstrblob.pData );
|
|
|
|
} // if( NULL == lppropvar->bstrblobVal.pData )
|
|
|
|
|
|
// Update the VT
|
|
lppropvar->vt = VT_BSTR;
|
|
|
|
// ----
|
|
// Exit
|
|
// ----
|
|
|
|
Exit:
|
|
|
|
// Restore the input on failure.
|
|
|
|
if( FAILED(hr) )
|
|
lppropvar->bstrblobVal = bstrblob;
|
|
|
|
return( hr );
|
|
|
|
} // PropVarUnmarshalBstr
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: PropVarMarshalBstrVector
|
|
//
|
|
// Synopsis: This routine converts a Propvariant from
|
|
// a VT_BSTR|VT_VECTOR to a VT_BSTR_BLOB|VT_VECTOR.
|
|
//
|
|
// Pre-Conditions:
|
|
// The input is a VT_BSTR | VT_VECTOR.
|
|
//
|
|
// Inputs: [LPPROPVARIANT] lppropvar
|
|
// The PropVariant to convert.
|
|
//
|
|
// Outputs: HRESULT
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
PropVarMarshalBstrVector( LPPROPVARIANT lppropvar )
|
|
{
|
|
// ------
|
|
// Locals
|
|
// ------
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG cElems;
|
|
ULONG nIndex;
|
|
|
|
LPBSTRBLOB rgbstrblob = NULL;
|
|
|
|
// -----
|
|
// Begin
|
|
// -----
|
|
|
|
cElems = lppropvar->cabstr.cElems;
|
|
|
|
// Allocate a BSTRBLOB array.
|
|
|
|
rgbstrblob = CoTaskMemAlloc( cElems * sizeof(*rgbstrblob) );
|
|
if( NULL == rgbstrblob )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
memset( rgbstrblob, 0, cElems * sizeof(*rgbstrblob) );
|
|
|
|
// Fill in the BSTRBLOB array.
|
|
|
|
for( nIndex = 0; nIndex < cElems; nIndex++ )
|
|
{
|
|
// Is this a NULL BSTR?
|
|
if( NULL == lppropvar->cabstr.pElems[nIndex] )
|
|
{
|
|
rgbstrblob[nIndex].cbSize = 0;
|
|
rgbstrblob[nIndex].pData = NULL;
|
|
}
|
|
|
|
// Otherwise, alloc a new BSTRBLOB buffer fill it from the BSTR.
|
|
else
|
|
{
|
|
// Set the size to the byte-count for the characters, plus the size
|
|
// of the length DWORD and the NULL terminator.
|
|
|
|
rgbstrblob[nIndex].cbSize = *SYSSTRINGBUF( lppropvar->cabstr.pElems[nIndex] )
|
|
+ sizeof(ULONG)
|
|
+ sizeof(OLECHAR);
|
|
|
|
// Allocate from IMalloc
|
|
|
|
rgbstrblob[nIndex].pData
|
|
= (BYTE*) CoTaskMemAlloc( rgbstrblob[nIndex].cbSize );
|
|
|
|
if( NULL == rgbstrblob[nIndex].pData )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
// Copy the string, plus the length field & NULL terminator.
|
|
// We'll free the old buffer after this for loop.
|
|
|
|
memcpy( rgbstrblob[nIndex].pData,
|
|
(BYTE*) SYSSTRINGBUF( lppropvar->cabstr.pElems[nIndex] ),
|
|
rgbstrblob[nIndex].cbSize );
|
|
|
|
} // if( NULL == lppropvar->cabstr.pElems[nIndex] ) ... else
|
|
} // for( nIndex = 0; nIndex < cElems; nIndex++ )
|
|
|
|
// Free the original BSTRs.
|
|
|
|
for( nIndex = 0; nIndex < cElems; nIndex++ )
|
|
{
|
|
PrivSysFreeString( lppropvar->cabstr.pElems[nIndex] );
|
|
}
|
|
|
|
// Update the PropVariant to use the new buffer. We don't
|
|
// need to set the cElems, because it hasn't changed.
|
|
|
|
lppropvar->vt = VT_BSTR_BLOB | VT_VECTOR;
|
|
CoTaskMemFree( lppropvar->cabstr.pElems );
|
|
lppropvar->cabstrblob.pElems = rgbstrblob;
|
|
rgbstrblob = NULL;
|
|
|
|
// ----
|
|
// Exit
|
|
// ----
|
|
|
|
Exit:
|
|
|
|
// Free the new array (if there was an error).
|
|
|
|
if( NULL != rgbstrblob )
|
|
{
|
|
for( nIndex = 0; nIndex < cElems; nIndex++ )
|
|
CoTaskMemFree( rgbstrblob[ nIndex ].pData );
|
|
|
|
CoTaskMemFree( rgbstrblob );
|
|
}
|
|
|
|
return( hr );
|
|
|
|
} // PropVarMarshalBstrVector
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: PropVarUnmarshalBstrVector
|
|
//
|
|
// Synopsis: This routine converts a Propvariant from a
|
|
// VT_BSTR_BLOB|VT_VECTOR to a VT_BSTR|VT_VECTOR.
|
|
//
|
|
// Pre-Conditions:
|
|
// The input is a VT_BSTR_BLOB | VT_VECTOR.
|
|
// The old memory may be freed.
|
|
//
|
|
// Inputs: [LPPROPVARIANT] lppropvar
|
|
// The PropVariant to convert.
|
|
//
|
|
// Outputs: HRESULT
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
PropVarUnmarshalBstrVector( LPPROPVARIANT lppropvar )
|
|
{
|
|
// ------
|
|
// Locals
|
|
// ------
|
|
|
|
ULONG nIndex;
|
|
ULONG cElems;
|
|
LPBSTR rgbstr = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
// -----
|
|
// Begin
|
|
// -----
|
|
|
|
cElems = lppropvar->cabstrblob.cElems;
|
|
|
|
// Allocate a new array of BSTRs.
|
|
|
|
rgbstr = CoTaskMemAlloc( cElems * sizeof(*rgbstr) );
|
|
if( NULL == rgbstr )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
memset( rgbstr, 0, cElems * sizeof(*rgbstr) );
|
|
|
|
|
|
// Convert each of the buffers to BSTRs
|
|
|
|
for( nIndex = 0; nIndex < cElems; nIndex++ )
|
|
{
|
|
// Is this a NULL BSTR?
|
|
|
|
if( NULL == lppropvar->cabstrblob.pElems[nIndex].pData )
|
|
{
|
|
rgbstr[nIndex] = NULL;
|
|
}
|
|
|
|
// Otherwise, allocate a buffer for the BSTR fill it
|
|
// from the BSTRBLOB.
|
|
|
|
else
|
|
{
|
|
|
|
// We'll free the old buffer after we get out of this for loop.
|
|
|
|
rgbstr[nIndex]
|
|
= PrivSysAllocString(
|
|
SYSSTRINGOFBUF( lppropvar->cabstrblob.pElems[nIndex].pData )
|
|
);
|
|
if( NULL == rgbstr[nIndex] )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
} // if( NULL == lppropvar->cabstrblob.pElems[nIndex].pData ) ... else
|
|
} // for( nIndex = 0; nIndex < cElems; nIndex++ )
|
|
|
|
// Free the BSTRBLOBs
|
|
|
|
for( nIndex = 0; nIndex < cElems; nIndex++ )
|
|
{
|
|
CoTaskMemFree( lppropvar->cabstrblob.pElems[nIndex].pData );
|
|
}
|
|
|
|
// Update the PropVariant with the new data.
|
|
|
|
lppropvar->vt = VT_BSTR | VT_VECTOR;
|
|
CoTaskMemFree( lppropvar->cabstrblob.pElems );
|
|
lppropvar->cabstr.pElems = rgbstr;
|
|
rgbstr = NULL;
|
|
|
|
// ----
|
|
// Exit
|
|
// ----
|
|
|
|
Exit:
|
|
|
|
// If there was an error, free what memory was
|
|
// allocated.
|
|
|
|
if( NULL != rgbstr )
|
|
{
|
|
for( nIndex = 0; nIndex < cElems; nIndex++ )
|
|
{
|
|
PrivSysFreeString( rgbstr[nIndex] );
|
|
}
|
|
|
|
CoTaskMemFree( rgbstr );
|
|
}
|
|
|
|
return( hr );
|
|
|
|
} // PropVariantUnmarshalBstrVector
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: PropVarMarshal
|
|
//
|
|
// Synopsis: This routine is used by the IPropertyStorage wrappers.
|
|
// We convert an array of PropVariants so that they are
|
|
// remotable. This involves the conversion of BSTR
|
|
// properties to a remotable type (BSTRBLOBs).
|
|
//
|
|
// Pre-Conditions:
|
|
// The inputs must not be NULL.
|
|
//
|
|
// Inputs: [ULONG] cVariants
|
|
// The size of the PropVariant array.
|
|
// [LPPROPVARIANT] rgpropvar
|
|
// The PropVariant to convert.
|
|
//
|
|
// Outputs: [HRESULT]
|
|
// Whether or not there is an error, the
|
|
// caller is responsible for freeing the
|
|
// PropVariant[]
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
PropVarMarshal( ULONG cVariants,
|
|
PROPVARIANT rgpropvar[] )
|
|
{
|
|
// ------
|
|
// Locals
|
|
// ------
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex;
|
|
|
|
// --------------------------------------------------------
|
|
// Walk through the PropVariant array, converting all BSTRs
|
|
// to BSTRBLOBs.
|
|
// --------------------------------------------------------
|
|
|
|
for( ulIndex = 0; ulIndex < cVariants; ulIndex++ )
|
|
{
|
|
switch( rgpropvar[ulIndex].vt )
|
|
{
|
|
// -------
|
|
// VT_BSTR
|
|
// -------
|
|
|
|
case VT_BSTR:
|
|
|
|
hr = PropVarMarshalBstr( &rgpropvar[ulIndex] );
|
|
if( FAILED(hr) ) goto Exit;
|
|
break;
|
|
|
|
// -------------------
|
|
// VT_BSTR | VT_VECTOR
|
|
// -------------------
|
|
|
|
case VT_BSTR | VT_VECTOR:
|
|
|
|
hr = PropVarMarshalBstrVector( &rgpropvar[ulIndex] );
|
|
if( FAILED(hr) ) goto Exit;
|
|
break;
|
|
|
|
// ----------------------
|
|
// VT_VARIANT | VT_VECTOR
|
|
// ----------------------
|
|
|
|
case VT_VARIANT | VT_VECTOR:
|
|
|
|
hr = PropVarMarshal( rgpropvar[ulIndex].capropvar.cElems,
|
|
rgpropvar[ulIndex].capropvar.pElems );
|
|
if( FAILED(hr) ) goto Exit;
|
|
break;
|
|
|
|
} // switch( rgpropvar[ulIndex].vt )
|
|
} // for( ulIndex = 0; ulIndex < cVariants; ulIndex++ )
|
|
|
|
|
|
// ----
|
|
// Exit
|
|
// ----
|
|
|
|
Exit:
|
|
|
|
return( hr );
|
|
|
|
} // PropVarMarshal()
|
|
|
|
|
|
//+-----------------------------------------------------------------------
|
|
//
|
|
// Function: PropVarUnmarshal
|
|
//
|
|
// Synopsis: Unmarshal an array of PropVariants.
|
|
// The BSTRs in the original PropVariant[]
|
|
// were converted to BSTRBLOBs for the remoting
|
|
// process.
|
|
//
|
|
// Inputs: [ULONG] cVariants
|
|
// The number of elements in the PropVariant[]
|
|
// [PROPVARIANT*] rgpropvar
|
|
// The PropVariant[] to be unmarshaled
|
|
//
|
|
// Output: HRESULT
|
|
// Whether or not there is an error, the
|
|
// caller is responsible for freeing the
|
|
// PropVariant[]
|
|
//
|
|
//+-----------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
PropVarUnmarshal( ULONG cVariants,
|
|
PROPVARIANT rgpropvar[])
|
|
{
|
|
// ------
|
|
// Locals
|
|
// ------
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex;
|
|
|
|
|
|
// -------------------
|
|
// Unmarshal the array
|
|
// -------------------
|
|
|
|
for( ulIndex = 0; ulIndex < cVariants; ulIndex++ )
|
|
{
|
|
|
|
switch( rgpropvar[ ulIndex ].vt )
|
|
{
|
|
// ------------
|
|
// VT_BSTR_BLOB
|
|
// ------------
|
|
|
|
case VT_BSTR_BLOB:
|
|
|
|
hr = PropVarUnmarshalBstr( &rgpropvar[ ulIndex ] );
|
|
if( FAILED(hr) ) goto Exit;
|
|
break;
|
|
|
|
// ------------------------
|
|
// VT_BSTR_BLOB | VT_VECTOR
|
|
// ------------------------
|
|
|
|
case VT_BSTR_BLOB | VT_VECTOR:
|
|
|
|
hr = PropVarUnmarshalBstrVector( &rgpropvar[ ulIndex ] );
|
|
if( FAILED(hr) ) goto Exit;
|
|
break;
|
|
|
|
// ----------------------
|
|
// VT_VARIANT | VT_VECTOR
|
|
// ----------------------
|
|
|
|
case VT_VARIANT | VT_VECTOR:
|
|
|
|
hr = PropVarUnmarshal( rgpropvar[ ulIndex ].capropvar.cElems,
|
|
rgpropvar[ ulIndex ].capropvar.pElems );
|
|
if( FAILED(hr) ) goto Exit;
|
|
break;
|
|
|
|
} // switch( rgpropvar[ ulIndex ].vt )
|
|
} // for( ulIndex = 0; ulIndex < cVariants; ulIndex++ )
|
|
|
|
|
|
// ----
|
|
// Exit
|
|
// ----
|
|
|
|
Exit:
|
|
|
|
return( hr );
|
|
|
|
} // PropVarUnmarshal
|
|
|
|
|
|
|