Leaked source code of windows server 2003
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

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