windows-nt/Source/XPSP1/NT/net/tapi/skywalker/inc/sdpsarr.h
2020-09-26 16:20:57 +08:00

534 lines
9.3 KiB
C++

/*
Copyright (c) 1997-1999 Microsoft Corporation
*/
#ifndef __SDP_SAFEARRAY__
#define __SDP_SAFEARRAY__
#include <afxdisp.h>
#include "sdpcommo.h"
#include "sdpdef.h"
inline BOOL
ValidateSafeArray(
IN VARTYPE VarType,
IN VARIANT *Variant
)
{
ASSERT(NULL != Variant);
// check if its a safearray and the type of elements in the safe array is whats expected
if ( !(V_VT(Variant) & (VT_ARRAY | VarType)) )
{
return FALSE;
}
// check number of dimensions, cannot handle more than one dimension
if ( V_ARRAY(Variant)->cDims != 1 )
{
return FALSE;
}
return TRUE;
}
class _DllDecl SDP_SAFEARRAY : public COleSafeArray
{
public:
inline SDP_SAFEARRAY();
BOOL CreateAndAttach(
IN ULONG MinSize,
IN VARTYPE VarType,
IN OUT VARIANT &Variant,
OUT HRESULT &HResult
);
inline void Attach(
IN VARIANT &Variant
);
inline void Detach();
inline BOOL Free(
OUT HRESULT &HResult
);
inline BOOL IsAllocated() const;
inline ~SDP_SAFEARRAY();
protected:
VARIANT *m_Variant;
};
inline
SDP_SAFEARRAY::SDP_SAFEARRAY(
)
: m_Variant(NULL)
{
}
inline void
SDP_SAFEARRAY::Attach(
IN VARIANT &Variant
)
{
m_Variant = &Variant;
// because of the way attach is implemented, the variant vt type field is set to VT_EMPTY
// and the ptr is set to null
// if the instance is destroyed without calling free, the vt type and the safe array are assigned
// back to the member variant
COleSafeArray::Attach(Variant);
}
inline void
SDP_SAFEARRAY::Detach(
)
{
ASSERT(NULL != m_Variant);
if ( NULL != m_Variant )
{
*m_Variant = COleSafeArray::Detach();
m_Variant = NULL;
}
}
inline BOOL
SDP_SAFEARRAY::Free(
OUT HRESULT &HResult
)
{
if (NULL == m_Variant)
{
HResult = S_OK;
return TRUE;
}
// destroy the underlying safearray
Clear();
// set the member variant ptr to null so that we are no longer attached to it
m_Variant = NULL;
return TRUE;
}
inline BOOL
SDP_SAFEARRAY::IsAllocated(
) const
{
return (NULL != m_Variant) ? TRUE : FALSE;
}
inline
SDP_SAFEARRAY::~SDP_SAFEARRAY(
)
{
if ( NULL != m_Variant )
{
*m_Variant = COleSafeArray::Detach();
}
}
template <class T>
class DYNAMIC_ARRAY
{
public:
inline DYNAMIC_ARRAY(
IN ULONG NumElements
);
inline T &operator[](
IN ULONG Index
);
inline T *operator()();
virtual ~DYNAMIC_ARRAY();
protected:
T *m_Array;
};
template <class T>
inline
DYNAMIC_ARRAY<T>::DYNAMIC_ARRAY(
IN ULONG NumElements
)
{
ASSERT(0 != NumElements);
m_Array = new T[NumElements];
}
template <class T>
inline T &
DYNAMIC_ARRAY<T>::operator[](
IN ULONG Index
)
{
return m_Array[Index];
}
template <class T>
inline T *
DYNAMIC_ARRAY<T>::operator ()(
)
{
return m_Array;
}
template <class T>
DYNAMIC_ARRAY<T>::~DYNAMIC_ARRAY(
)
{
ASSERT( NULL != m_Array );
delete[] m_Array;
}
template <class T>
class DYNAMIC_POINTER_ARRAY : public DYNAMIC_ARRAY<T *>
{
public:
inline DYNAMIC_POINTER_ARRAY(
IN ULONG NumElements
);
inline T &operator[](
IN ULONG Index
);
virtual ~DYNAMIC_POINTER_ARRAY();
protected:
ULONG m_NumElements;
// should not be called
inline T *operator()()
{
ASSERT(FALSE);
return NULL;
}
};
template <class T>
inline
DYNAMIC_POINTER_ARRAY<T>::DYNAMIC_POINTER_ARRAY(
IN ULONG NumElements
)
: DYNAMIC_ARRAY<T *>(NumElements),
m_NumElements(NumElements)
{
for (UINT i=0; i < NumElements; i++)
{
m_Array[i] = new T();
}
}
template <class T>
inline T &
DYNAMIC_POINTER_ARRAY<T>::operator[](
IN ULONG Index
)
{
return *m_Array[Index];
}
template <class T>
DYNAMIC_POINTER_ARRAY<T>::~DYNAMIC_POINTER_ARRAY(
)
{
ASSERT( NULL != m_Array );
for (UINT i=0; i < m_NumElements; i++)
{
delete m_Array[i];
}
}
class _DllDecl SDP_SAFEARRAY_WRAP
{
public:
HRESULT GetSafeArrays(
IN const ULONG NumElements,
IN const ULONG NumSafeArrays,
IN VARTYPE VarType[],
OUT VARIANT *Variant[]
);
HRESULT SetSafeArrays(
IN const ULONG NumSafeArrays,
IN VARTYPE VarType[],
IN VARIANT *Variant[]
);
protected:
virtual BOOL GetElement(
IN ULONG Index,
IN ULONG NumEntries,
IN void **Element,
OUT HRESULT &HResult
) = 0;
virtual BOOL SetElement(
IN ULONG Index,
IN ULONG NumEntries,
IN void ***Element,
OUT HRESULT &HResult
) = 0;
virtual void RemoveExcessElements(
IN ULONG StartIndex
) = 0;
};
template <class T, class TLIST>
class _DllDecl SDP_SAFEARRAY_WRAP_EX : public SDP_SAFEARRAY_WRAP
{
public:
inline SDP_SAFEARRAY_WRAP_EX(
IN TLIST &TList
);
protected:
TLIST &m_TList;
T *GetListMember(
IN ULONG Index,
OUT HRESULT &HResult
);
virtual BOOL Get(
IN T &ListMember,
IN ULONG NumEntries,
IN void **Element,
OUT HRESULT &HResult
) = 0;
virtual BOOL GetElement(
IN ULONG Index,
IN ULONG NumEntries,
IN void **Element,
OUT HRESULT &HResult
);
T *CreateListMemberIfRequired(
IN ULONG Index,
OUT HRESULT &HResult
);
virtual BOOL Set(
IN T &ListMember,
IN ULONG NumEntries,
IN void ***Element,
OUT HRESULT &HResult
) = 0;
virtual BOOL SetElement(
IN ULONG Index,
IN ULONG NumEntries,
IN void ***Element,
OUT HRESULT &HResult
);
virtual void RemoveExcessElements(
IN ULONG StartIndex
);
};
template <class T, class TLIST>
inline
SDP_SAFEARRAY_WRAP_EX<T, TLIST>::SDP_SAFEARRAY_WRAP_EX(
IN TLIST &TList
)
: m_TList(TList)
{}
template <class T, class TLIST>
T *
SDP_SAFEARRAY_WRAP_EX<T, TLIST>::GetListMember(
IN ULONG Index,
OUT HRESULT &HResult
)
{
T *ToReturn = dynamic_cast<T *>(m_TList[Index]);
if ( NULL == ToReturn )
{
HResult = HRESULT_FROM_ERROR_CODE(SDP_INTERNAL_ERROR);
}
return ToReturn;
}
template <class T, class TLIST>
BOOL
SDP_SAFEARRAY_WRAP_EX<T, TLIST>::GetElement(
IN ULONG Index,
IN ULONG NumEntries,
IN void **Element,
OUT HRESULT &HResult
)
{
T *ListMember = GetListMember(Index, HResult);
if ( NULL == ListMember )
{
return FALSE;
}
ASSERT(ListMember->IsValid());
if ( !Get(*ListMember, NumEntries, Element, HResult) )
{
return FALSE;
}
return TRUE;
}
template <class T, class TLIST>
T *
SDP_SAFEARRAY_WRAP_EX<T, TLIST>::CreateListMemberIfRequired(
IN ULONG Index,
OUT HRESULT &HResult
)
{
// assert that the index is atmost 1 more than the size of the list
ASSERT(0 <= m_TList.GetSize());
ASSERT(Index <= (ULONG)(m_TList.GetSize() + 1));
if ( Index >= (ULONG)m_TList.GetSize() )
{
T *NewElement = dynamic_cast<T *>(m_TList.CreateElement());
if ( NULL == NewElement )
{
HResult = HRESULT_FROM_ERROR_CODE(SDP_INTERNAL_ERROR);
}
return NewElement;
}
else
{
return GetListMember(Index, HResult);
}
// should never reach here
ASSERT(FALSE);
}
template <class T, class TLIST>
BOOL
SDP_SAFEARRAY_WRAP_EX<T, TLIST>::SetElement(
IN ULONG Index,
IN ULONG NumEntries,
IN void ***Element,
OUT HRESULT &HResult
)
{
T *ListMember = CreateListMemberIfRequired(Index, HResult);
if ( NULL == ListMember )
{
return FALSE;
}
if ( !Set(*ListMember, NumEntries, Element, HResult) )
{
return FALSE;
}
ASSERT(ListMember->IsValid());
// if its a newly created instance, make it valid and add it to the list at the appropriate
// index
if ( Index >= (ULONG)m_TList.GetSize() )
{
try
{
m_TList.SetAtGrow(Index, ListMember);
}
catch(...)
{
delete ListMember;
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
}
return TRUE;
}
template <class T, class TLIST>
void
SDP_SAFEARRAY_WRAP_EX<T, TLIST>::RemoveExcessElements(
IN ULONG StartIndex
)
{
ASSERT(0 <= m_TList.GetSize());
// for each list element that is in excess of the safearray members,
// delete and remove them
for ( ULONG i = StartIndex; i < (ULONG)m_TList.GetSize(); i++ )
{
delete m_TList[i];
m_TList.RemoveAt(i);
i++;
}
}
#endif // __SDP_SAFEARRAY__