Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

228 lines
5.7 KiB

/*
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;
}