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.
602 lines
15 KiB
602 lines
15 KiB
/*++
|
|
|
|
Copyright (C) 1995-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
CVARIANT.CPP
|
|
|
|
Abstract:
|
|
|
|
Defines the CVarinat class which is a purpose object to
|
|
wrap VARIANT structures.
|
|
|
|
History:
|
|
|
|
a-davj 4-27-95 Created.
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#include "impdyn.h"
|
|
#include "cvariant.h"
|
|
//#include <afxpriv.h>
|
|
|
|
BSTR SysAllocBstrFromTCHAR(TCHAR * pFrom)
|
|
{
|
|
#ifdef UNICODE
|
|
return SysAllocString(pFrom);
|
|
#else
|
|
WCHAR * pTemp = new WCHAR[lstrlen(pFrom)+1];
|
|
if(pTemp == NULL)
|
|
return NULL;
|
|
mbstowcs(pTemp, pFrom, lstrlen(pFrom)+1);
|
|
BSTR bRet = SysAllocString(pTemp);
|
|
delete pTemp;
|
|
return bRet;
|
|
#endif
|
|
}
|
|
//***************************************************************************
|
|
//
|
|
// int CVariant::CalcNumStrings
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Calculates the number of strings
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pTest points to string to test
|
|
//
|
|
// RETURN VALUE:
|
|
// Return - the number of strings in a multistring block.
|
|
//
|
|
//***************************************************************************
|
|
|
|
int CVariant::CalcNumStrings(
|
|
IN TCHAR *pTest)
|
|
{
|
|
int iRet = 0;
|
|
if(pTest == NULL)
|
|
return 0;
|
|
while(*pTest)
|
|
{
|
|
iRet++;
|
|
pTest += lstrlen(pTest)+1;
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CVariant::ChangeType
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Changes the CVariant data into a new type.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// vtNew Type to convert to
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if alright, otherwise an error set by OMSVariantChangeType
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CVariant::ChangeType(
|
|
IN VARTYPE vtNew)
|
|
{
|
|
SCODE sc;
|
|
|
|
// if type doesnt need changing, then already done!
|
|
|
|
if(vtNew == var.vt)
|
|
return S_OK;
|
|
|
|
// Create and initialize a temp VARIANT
|
|
|
|
VARIANTARG vTemp;
|
|
VariantInit(&vTemp);
|
|
|
|
// Change to the desired type. Then delete the current value
|
|
// and copy the temp copy
|
|
|
|
sc = OMSVariantChangeType(&vTemp,&var,0,vtNew);
|
|
OMSVariantClear(&var);
|
|
|
|
var = vTemp; // structure copy
|
|
return sc;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CVariant::Clear
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Clears out the VARIANT.
|
|
//
|
|
//***************************************************************************
|
|
|
|
void CVariant::Clear(void)
|
|
{
|
|
OMSVariantClear(&var);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CVariant::
|
|
// CVariant::~CVariant
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor and destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CVariant::CVariant()
|
|
{
|
|
VariantInit(&var);
|
|
memset((void *)&var.lVal,0,8);
|
|
}
|
|
|
|
CVariant::CVariant(LPWSTR pwcStr)
|
|
{
|
|
VariantInit(&var);
|
|
if(pwcStr)
|
|
{
|
|
var.bstrVal = SysAllocString(pwcStr);
|
|
if(var.bstrVal)
|
|
var.vt = VT_BSTR;
|
|
}
|
|
}
|
|
|
|
CVariant::~CVariant()
|
|
{
|
|
OMSVariantClear(&var);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// SCODE CVariant::DoPut
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// "Puts" the data out to the WBEM server (if pClassInt isnt NULL), or just
|
|
// copies the data to the variant.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// lFlags flags to pass along to wbem server
|
|
// pClassInt pointer to class/instance object
|
|
// PropName property name
|
|
// pVar variant value
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if no error other wise see wbemsvc error codes when, pClass isnt
|
|
// null, or see the OMSVariantChangeType function.
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CVariant::DoPut(
|
|
IN long lFlags,
|
|
IN IWbemClassObject FAR * pClassInt,
|
|
IN BSTR PropName,
|
|
IN CVariant * pVar)
|
|
{
|
|
SCODE sc;
|
|
|
|
if(pClassInt)
|
|
{
|
|
|
|
sc = pClassInt->Put(PropName,lFlags,&var,0);
|
|
}
|
|
else if(pVar)
|
|
{
|
|
pVar->Clear();
|
|
sc = OMSVariantChangeType(&pVar->var,&var,0,var.vt);
|
|
}
|
|
else sc = WBEM_E_FAILED;
|
|
return sc;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// SCODE CVariant::GetArrayData
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Converts array data into a single data block. This is used by the
|
|
// registry provider when it writes out array data.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// ppData pointer to the return data. Note it is the job of the
|
|
// caller to free this when the return code is S_OK
|
|
// pdwSize Size of returned data
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well
|
|
// WBEM_E_OUT_OF_MEMORY when we memory allocation fails
|
|
// WBEM_E_FAILED when variant has bogus type.
|
|
// ??? when failure is in SafeArrayGetElement
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CVariant::GetArrayData(
|
|
OUT void ** ppData,
|
|
OUT DWORD * pdwSize)
|
|
{
|
|
SCODE sc;
|
|
DWORD dwSoFar = 0;
|
|
SAFEARRAY * psa;
|
|
long ix[2] = {0,0};
|
|
BYTE * pb;
|
|
TCHAR * ptc;
|
|
BOOL bString = ((var.vt & ~VT_ARRAY) == CHARTYPE ||(var.vt & ~VT_ARRAY) == VT_BSTR );
|
|
|
|
int iNumElements = GetNumElements();
|
|
|
|
int iSizeOfType = iTypeSize(var.vt);
|
|
if(iSizeOfType < 1)
|
|
return WBEM_E_FAILED;
|
|
|
|
// Calculate necessary size;
|
|
|
|
psa = var.parray;
|
|
if(bString) {
|
|
*pdwSize = CHARSIZE; // 1 for the final double null!
|
|
for(ix[0] = 0; ix[0] < iNumElements; ix[0]++) {
|
|
BSTR bstr;
|
|
sc = SafeArrayGetElement(psa,ix,&bstr);
|
|
if(FAILED(sc))
|
|
return sc;
|
|
#ifdef UNICODE
|
|
*pdwSize += 2 * (wcslen(bstr) +1);
|
|
#else
|
|
int iWCSLen = wcslen(bstr) + 1;
|
|
*pdwSize += wcstombs(NULL,bstr,iWCSLen) + 1;
|
|
#endif
|
|
SysFreeString(bstr);
|
|
}
|
|
}
|
|
else {
|
|
*pdwSize = iNumElements * iSizeOfType;
|
|
}
|
|
|
|
// Allocate the memory to be filled
|
|
|
|
*ppData = CoTaskMemAlloc(*pdwSize);
|
|
if(*ppData == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
pb = (BYTE *)*ppData;
|
|
ptc = (TCHAR *)*ppData;
|
|
|
|
// loop for each array element
|
|
|
|
sc = S_OK;
|
|
for(ix[0] = 0; ix[0] < iNumElements && sc == S_OK; ix[0]++) {
|
|
if (bString) {
|
|
BSTR bstr;
|
|
sc = SafeArrayGetElement(psa,ix,&bstr);
|
|
if(sc != S_OK)
|
|
break;
|
|
DWORD dwBytesLeft = *pdwSize-dwSoFar;
|
|
#ifdef UNICODE
|
|
lstrcpyn(ptc,bstr,dwBytesLeft/2);
|
|
#else
|
|
wcstombs(ptc,bstr,dwBytesLeft);
|
|
#endif
|
|
dwSoFar += CHARSIZE * (lstrlen(ptc) + 1);
|
|
ptc += lstrlen(ptc) + 1;
|
|
SysFreeString(bstr);
|
|
*ptc = 0; // double null
|
|
}
|
|
else {
|
|
sc = SafeArrayGetElement(psa,ix,pb);
|
|
pb += iSizeOfType;
|
|
}
|
|
}
|
|
if(sc != S_OK)
|
|
CoTaskMemFree(*ppData);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// SCODE CVariant::GetData
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Used by the registry provider to take the data from VARIANT arg format
|
|
// into a raw block for output. Note that the data allocated and stuck into
|
|
// *ppData should be freed using CoTaskMemFree!
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// ppData Pointer to output data.
|
|
// dwRegType Type to convert to
|
|
// pdwSize Pointer to size of returned data
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if all is well, otherwise a error code which is set by either
|
|
// OMSVariantChangeType, or GetArrayData.
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CVariant::GetData(
|
|
OUT void ** ppData,
|
|
IN DWORD dwRegType,
|
|
OUT DWORD * pdwSize)
|
|
{
|
|
|
|
SCODE sc = S_OK;
|
|
|
|
// Determine the type it may need to be converted to. Note that binary
|
|
// data is not converted intentionally.
|
|
|
|
switch(dwRegType) {
|
|
case REG_DWORD:
|
|
sc = ChangeType(VT_I4);
|
|
break;
|
|
case REG_SZ:
|
|
sc = ChangeType(VT_BSTR);
|
|
break;
|
|
|
|
case REG_MULTI_SZ:
|
|
sc = ChangeType(VT_BSTR | VT_ARRAY);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if(sc != S_OK)
|
|
return sc;
|
|
|
|
// Special case for arrays
|
|
|
|
if(dwRegType == REG_BINARY || dwRegType == REG_MULTI_SZ)
|
|
return GetArrayData(ppData, pdwSize);
|
|
|
|
// Allocate some memory and move the data into it.
|
|
|
|
if(dwRegType == REG_SZ) {
|
|
#ifdef UNICODE
|
|
*pdwSize = 2 * (wcslen(var.bstrVal)+1);
|
|
*ppData = CoTaskMemAlloc(*pdwSize);
|
|
if(*ppData == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
StringCchCopyW((WCHAR *)*ppData, *pdwSize/sizeof(WCHAR),var.bstrVal);
|
|
#else
|
|
*ppData = WideToNarrow(var.bstrVal);
|
|
if(*ppData == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
*pdwSize = lstrlenA((char *)*ppData)+1;
|
|
#endif
|
|
}
|
|
else {
|
|
*pdwSize = iTypeSize(var.vt);
|
|
*ppData = CoTaskMemAlloc(*pdwSize);
|
|
if(*ppData == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
memcpy(*ppData,(void *)&var.lVal,*pdwSize);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CVariant::GetNumElements
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Gets the number of elements in an array.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// number of elements. Scalers return a 1.
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD CVariant::GetNumElements(void)
|
|
{
|
|
SCODE sc;
|
|
if(!IsArray())
|
|
return 1;
|
|
SAFEARRAY * psa = var.parray;
|
|
long uLower, uUpper;
|
|
sc = SafeArrayGetLBound(psa,1,&uLower);
|
|
sc |= SafeArrayGetUBound(psa,1,&uUpper);
|
|
if(sc != S_OK)
|
|
return 0;
|
|
else
|
|
return uUpper - uLower +1;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// SCODE CVariant::SetArrayData
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Sets the CVariant value using raw data. Used by the reg provider.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pData pointer to data to set
|
|
// vtSimple Type to set the data to
|
|
// iSize size of data pointed to by pData
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if OK.
|
|
// WBEM_E_INVALID_PARAMETER if the arguments are bad
|
|
// WBEM_E_OUT_OF_MEMORY if out of memory
|
|
// other wise error from SafeArrayPutElement
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CVariant::SetArrayData(
|
|
IN void * pData,
|
|
IN VARTYPE vtSimple,
|
|
IN int iSize)
|
|
{
|
|
SCODE sc;
|
|
int iNumElements;
|
|
BYTE * pNext;
|
|
long ix[2] = {0,0};
|
|
DWORD dwLeftOver = 0;
|
|
int iSizeOfType = iTypeSize(vtSimple);
|
|
|
|
if(pData == NULL || iSizeOfType < 1 || iSize < 1)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Calculate the number of elements and make sure it is a type that
|
|
// is supported
|
|
|
|
if(vtSimple == VT_BSTR) {
|
|
iNumElements = CalcNumStrings((TCHAR *)pData);
|
|
}
|
|
else {
|
|
iNumElements = iSize / iSizeOfType;
|
|
dwLeftOver = iSize % iSizeOfType;
|
|
}
|
|
|
|
// Allocate array
|
|
|
|
int iNumCreate = (dwLeftOver) ? iNumElements + 1 : iNumElements;
|
|
SAFEARRAY * psa = OMSSafeArrayCreate(vtSimple,iNumCreate);
|
|
if(psa == NULL)
|
|
return WBEM_E_FAILED;
|
|
|
|
// Set each element of the array
|
|
|
|
for(ix[0] = 0, pNext = (BYTE *)pData; ix[0] < iNumElements; ix[0]++) {
|
|
if(vtSimple == VT_BSTR) {
|
|
BSTR bstr;
|
|
bstr = SysAllocBstrFromTCHAR((LPTSTR)pNext);
|
|
if(bstr == NULL) { // todo, free previously allocated strings!
|
|
SafeArrayDestroy(psa);
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
sc = SafeArrayPutElement(psa,ix,(void*)bstr);
|
|
pNext += sizeof(TCHAR)*(lstrlen((TCHAR *)pNext) + 1);
|
|
SysFreeString(bstr);
|
|
}
|
|
else {
|
|
sc = SafeArrayPutElement(psa,ix,pNext);
|
|
pNext += iSizeOfType;
|
|
}
|
|
if(sc) { // todo, cleanup???
|
|
SafeArrayDestroy(psa);
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
// it is possible that the number of bytes being set doesnt evenly factor
|
|
// into the type size. For instance, there may be 10 bytes of registry
|
|
// data being put into a DWORD array. In this case, the last two bytes
|
|
// are left overs
|
|
|
|
if(dwLeftOver) {
|
|
__int64 iTemp = 0;
|
|
memcpy((void *)&iTemp,(void *)pNext,dwLeftOver);
|
|
sc = SafeArrayPutElement(psa,ix,&iTemp);
|
|
}
|
|
|
|
var.vt = vtSimple | VT_ARRAY;
|
|
var.parray = psa;
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CVariant::SetData
|
|
//
|
|
// Sets the CVariant value using raw data. Used by the reg provider.
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pData Data to be set
|
|
// vtChangeTo Type to change the data to
|
|
// iSize size of data pointed to by pData
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK if OK.
|
|
// WBEM_E_INVALID_PARAMETER if the arguments are bad
|
|
// WBEM_E_OUT_OF_MEMORY if out of memory
|
|
// other wise error from SafeArrayPutElement
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CVariant::SetData(
|
|
IN void * pData,
|
|
IN VARTYPE vtChangeTo,
|
|
IN int iSize)
|
|
{
|
|
int iToSize = iTypeSize(vtChangeTo);
|
|
|
|
// check arguments and clear the variant
|
|
|
|
if(pData == NULL || iToSize < 1)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
OMSVariantClear(&var);
|
|
if(iSize < 1)
|
|
iSize = iToSize;
|
|
|
|
// Special case for arrays!
|
|
|
|
if(vtChangeTo & VT_ARRAY)
|
|
return SetArrayData(pData,vtChangeTo & ~VT_ARRAY,iSize);
|
|
|
|
if(vtChangeTo == CIM_SINT64 || vtChangeTo == CIM_UINT64)
|
|
{
|
|
|
|
// int64 and uint64 need to be converted to strings
|
|
|
|
WCHAR wcTemp[50];
|
|
__int64 iLong;
|
|
memcpy((void *)&iLong, pData, 8);
|
|
if(vtChangeTo == CIM_SINT64)
|
|
StringCchPrintfW(wcTemp, 50, L"%I64d", iLong);
|
|
else
|
|
StringCchPrintfW(wcTemp, 50, L"%I64u", iLong);
|
|
|
|
var.bstrVal = SysAllocString(wcTemp);
|
|
if(var.bstrVal == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
var.vt = VT_BSTR;
|
|
}
|
|
else if(vtChangeTo == VT_BSTR)
|
|
{
|
|
|
|
// All strings are stored as BSTRS
|
|
|
|
var.bstrVal = SysAllocBstrFromTCHAR((LPTSTR)pData);
|
|
if(var.bstrVal == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
var.vt = VT_BSTR;
|
|
}
|
|
else
|
|
{
|
|
memcpy((void *)&var.lVal,pData,iToSize);
|
|
var.vt = vtChangeTo;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|