|
|
//
// util.cpp, implementation for various utility classes
//
#include "global.h"
#include "util.h"
extern LPCWSTR g_pwszSsrRootPath; extern const DWORD g_dwSsrRootPathLen;
/*
Routine Description:
Name:
CSafeArray::CSafeArray
Functionality: Constructor. Will prepare our private data for a safearray variant. In case the in parameter is not a safearray, then we will behave as it is a one element array.
Virtual: no. Arguments:
none.
Return Value:
none.
Notes:
*/
CSafeArray::CSafeArray ( IN VARIANT * pVal ) : m_pSA(NULL), m_pVal(NULL), m_ulSize(0), m_bValidArray(true) { if (pVal->vt & VT_ARRAY) { m_pSA = pVal->parray;
if ( pVal->vt & VT_BYREF ) { m_pSA = *(pVal->pparray); }
LONG lb = 0; LONG ub = 0; ::SafeArrayGetLBound(m_pSA, 1, &lb); ::SafeArrayGetUBound(m_pSA, 1, &ub);
m_ulSize = ub - lb + 1;
//
// we won't support it as an array, instead, we treat it as
// a normal VARIANT
//
if (m_pSA->cDims > 2) { m_ulSize = 1; m_pVal = pVal; m_bValidArray = false; m_pSA = NULL; } } else { m_ulSize = 1; m_pVal = pVal; m_bValidArray = false; } }
/*
Routine Description:
Name:
CSafeArray::GetElement
Functionality: Get the ulIndex-th element as the given (guid) interface object.
Virtual: no. Arguments:
none.
Return Value:
Success: S_OK Failure: various error codes.
Notes:
*/
HRESULT CSafeArray::GetElement ( IN REFIID guid, IN ULONG ulIndex, OUT IUnknown ** ppUnk ) { //
// The following default return value is not really good for invalid
// array var given to this object.
//
if (ppUnk == NULL || ulIndex >= m_ulSize) { return E_INVALIDARG; } else if (!m_bValidArray) { //
// if the given variant is not an array, then
// we will use the value to handle the request
//
if (ulIndex == 0 && m_pVal != NULL) { if (m_pVal->vt == VT_UNKNOWN) { return m_pVal->punkVal->QueryInterface(guid, (LPVOID*)ppUnk); } else if (m_pVal->vt == VT_DISPATCH) { return m_pVal->pdispVal->QueryInterface(guid, (LPVOID*)ppUnk); } else { return E_SSR_VARIANT_NOT_CONTAIN_OBJECT; } } else if (ulIndex >= 1) { return E_SSR_ARRAY_INDEX_OUT_OF_RANGE; } else { return E_SSR_NO_VALID_ELEMENT; } }
HRESULT hr = E_INVALIDARG; *ppUnk = NULL;
VARIANT v; ::VariantInit(&v);
long index[1] = {ulIndex};
hr = ::SafeArrayGetElement(m_pSA, index, &v);
if (SUCCEEDED(hr) && v.vt == VT_UNKNOWN) { hr = v.punkVal->QueryInterface(guid, (LPVOID*)ppUnk); if (S_OK != hr) { hr = E_NOINTERFACE; } } else if (SUCCEEDED(hr) && v.vt == VT_DISPATCH) { hr = v.pdispVal->QueryInterface(guid, (LPVOID*)ppUnk); if (S_OK != hr) { hr = E_NOINTERFACE; } } else { hr = E_NOINTERFACE; }
::VariantClear(&v);
return hr; }
/*
Routine Description:
Name:
CSafeArray::GetElement
Functionality: Get the ulIndex-th element as the given type (non-interface).
Virtual: no. Arguments:
none.
Return Value:
Success: S_OK Failure: various error codes.
Notes:
*/
HRESULT CSafeArray::GetElement ( IN ULONG ulIndex, IN VARTYPE vt, OUT VARIANT * pVal ) { HRESULT hr = GetElement(ulIndex, pVal);
//
// if the types do not match, then we need to coerce it
//
if (SUCCEEDED(hr) && pVal->vt != vt) { VARIANT v; hr = ::VariantCopy(&v, pVal);
::VariantClear(pVal);
if (SUCCEEDED(hr)) { hr = ::VariantChangeType(pVal, &v, VARIANT_NOVALUEPROP, vt); }
::VariantClear(&v); }
return hr; }
/*
Routine Description:
Name:
CSafeArray::GetElement
Functionality: Get the ulIndex-th element as a variant.
Virtual: no. Arguments:
none.
Return Value:
Success: S_OK Failure: various error codes.
Notes:
*/
HRESULT CSafeArray::GetElement ( IN ULONG ulIndex, OUT VARIANT * pVal ) { if (pVal == NULL || ulIndex >= m_ulSize) { return E_INVALIDARG; }
::VariantInit(pVal);
if (!m_bValidArray) { if (ulIndex == 0 && m_pVal != NULL) { return ::VariantCopy(pVal, m_pVal); } else if (ulIndex >= 1) { return E_SSR_ARRAY_INDEX_OUT_OF_RANGE; } else { return E_SSR_NO_VALID_ELEMENT; }
}
HRESULT hr = E_INVALIDARG;
LONG index[2] = {ulIndex, 0};
if (m_pSA->cDims > 1) { //
// we must be dealing with 2-dimensional arrays because we don't
// support more than that
//
LONG ilb = m_pSA->rgsabound[1].lLbound; LONG iSize = m_pSA->rgsabound[1].cElements;
VARIANT * pvarValues = new VARIANT[iSize];
if (pvarValues != NULL) { //
// null all the contents
//
::memset(pvarValues, 0, sizeof(VARIANT) * iSize);
for (LONG i = ilb; i < ilb + iSize; i++) { //
// Gett every element in the second dimension, so the index[1]
//
index[1] = i; hr = ::SafeArrayGetElement(m_pSA, index, &(pvarValues[i - ilb])); if (FAILED(hr)) { break; } }
if (SUCCEEDED(hr)) { SAFEARRAYBOUND rgsabound[1]; rgsabound[0].lLbound = 0; rgsabound[0].cElements = iSize;
SAFEARRAY * psa = ::SafeArrayCreate(VT_VARIANT , 1, rgsabound); if (psa == NULL) { hr = E_OUTOFMEMORY; } else { //
// put every element in the second dimension into the new safearray
// BTW, this is a single dimension new safearray, so the index[0]
//
for (i = 0; i < iSize; i++) { index[0] = i; hr = ::SafeArrayPutElement(psa, index, &(pvarValues[i]));
if (FAILED(hr)) { break; } }
if (SUCCEEDED(hr)) { pVal->vt = VT_ARRAY | VT_VARIANT; pVal->parray = psa; } else { ::SafeArrayDestroy(psa); } } }
//
// now clean it up
//
for (i = 0; i < iSize; i++) { ::VariantClear(&(pvarValues[i])); }
delete [] pvarValues; } } else { hr = ::SafeArrayGetElement(m_pSA, index, pVal); }
return hr; }
|