/* 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 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 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 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 Index(NumSafeArrays); for (j=0; j < NumSafeArrays; j++) { Index[j] = V_ARRAY(Variant[j])->rgsabound[0].lLbound; } DYNAMIC_ARRAY 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; }