229 lines
5.7 KiB
C++
229 lines
5.7 KiB
C++
|
/*
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|