|
|
/*
Copyright (c) 1997-1999 Microsoft Corporation
*/
#include "sdppch.h"
#include "sdpsarr.h"
inline void IncrementIndices( IN ULONG NumSafeArrays, IN OUT LONG *Index ) { for (ULONG i=0; i < NumSafeArrays; i++) { Index[i]++; } }
inline ULONG MinSize( IN const ULONG NumSafeArrays, IN VARIANT *Variant[] ) { ULONG ReturnValue = 0; for (UINT i=0; i < NumSafeArrays; i++) { if ( ReturnValue < V_ARRAY(Variant[i])->rgsabound[0].cElements ) { ReturnValue = V_ARRAY(Variant[i])->rgsabound[0].cElements; } }
return ReturnValue; }
BOOL SDP_SAFEARRAY::CreateAndAttach( IN ULONG MinSize, IN VARTYPE VarType, IN OUT VARIANT &Variant, OUT HRESULT &HResult ) { // create a 1 based 1 dimensional safearray
SAFEARRAYBOUND rgsabound[1]; rgsabound[0].lLbound = 1; rgsabound[0].cElements = MinSize; SAFEARRAY *SafeArray = SafeArrayCreate(VarType, 1, rgsabound); if ( NULL == SafeArray ) { HResult = E_OUTOFMEMORY; return FALSE; }
// set the variant type
V_VT(&Variant) = VT_ARRAY | VarType; V_ARRAY(&Variant) = SafeArray;
// attach the variant to the instance
Attach(Variant);
HResult = S_OK; return TRUE; }
HRESULT SDP_SAFEARRAY_WRAP::GetSafeArrays( IN const ULONG NumElements, IN const ULONG NumSafeArrays, IN VARTYPE VarType[], OUT VARIANT *Variant[] ) { if ( 0 == NumElements ) { return HRESULT_FROM_ERROR_CODE(ERROR_INVALID_DATA); }
// clear each of the variants (it may not be a safearray)
for(ULONG Index=0; Index < NumSafeArrays; Index++) { BAIL_IF_NULL(Variant[Index], E_INVALIDARG); BAIL_ON_FAILURE(VariantClear(Variant[Index])); }
try { DYNAMIC_POINTER_ARRAY<SDP_SAFEARRAY> SdpSafeArray(NumSafeArrays); for (ULONG j=0; j < NumSafeArrays; j++) { HRESULT HResult;
// create 1 based one-dimensional safearrays
if ( !SdpSafeArray[j].CreateAndAttach(NumElements, VarType[j], *(Variant[j]), HResult) ) { for (ULONG k=0; k < j; k++) { HRESULT FreeResult; if ( !SdpSafeArray[k].Free(FreeResult) ) { return FreeResult; } }
return HResult; } }
// for each element in the attribute list, add the bstr
// to the safe array
// the indexing begins at 1 (1 based one-dimensional array)
LONG Index = 1; DYNAMIC_ARRAY<void *> Element(NumSafeArrays); for( ULONG i= 0; i < NumElements; i++, Index++ ) { HRESULT HResult;
if ( !GetElement(i, NumSafeArrays, Element(), HResult) ) { return HResult; } // assign the list element to the ith safe array element
for (j=0; j < NumSafeArrays; j++) { SdpSafeArray[j].PutElement(&Index, Element[j]); } } } catch(COleException &OleException) { // *** convert the SCODE to HRESULT
return ResultFromScode(OleException.Process(&OleException)); }
return S_OK; }
HRESULT SDP_SAFEARRAY_WRAP::SetSafeArrays( IN const ULONG NumSafeArrays, IN VARTYPE VarType[], IN VARIANT *Variant[] ) { // validate parameter
for ( ULONG j=0; j < NumSafeArrays; j++ ) { if ( !ValidateSafeArray(VarType[j], Variant[j]) ) { return E_INVALIDARG; } }
try { DYNAMIC_POINTER_ARRAY<SDP_SAFEARRAY> SdpSafeArray(NumSafeArrays); for (j=0; j < NumSafeArrays; j++) { SdpSafeArray[j].Attach(*(Variant[j])); }
// while there are elements in the list, set bstrs
// if no corresponding element in the list, create and add a new one
DYNAMIC_ARRAY<LONG> Index(NumSafeArrays); for (j=0; j < NumSafeArrays; j++) { Index[j] = V_ARRAY(Variant[j])->rgsabound[0].lLbound; }
DYNAMIC_ARRAY<void **> Element(NumSafeArrays);
// need only consider the number of items in the smallest sized safearray
ULONG MinSafeArraySize = MinSize(NumSafeArrays, Variant);
// *** currently not checking that all safe arrays have the same number of non-null
// elements
for ( ULONG i = 0; i < MinSafeArraySize; i++, IncrementIndices(NumSafeArrays, Index()) ) { for (j=0; j < NumSafeArrays; j++) { SdpSafeArray[j].PtrOfIndex(&Index[j], (void **)&Element[j]); }
HRESULT HResult;
// grow the list if required
if ( !SetElement(i, NumSafeArrays, Element(), HResult) ) { // success means that there are no more elements in the safe array
if ( SUCCEEDED(HResult) ) { break; } else { return HResult; } } }
// get rid of each list element that is in excess of the safearray members
RemoveExcessElements(i); } catch(COleException &OleException) { // *** convert the SCODE to HRESULT
return ResultFromScode(OleException.Process(&OleException)); }
return S_OK; }
|