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.
441 lines
8.1 KiB
441 lines
8.1 KiB
//
|
|
// 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;
|
|
}
|