windows-nt/Source/XPSP1/NT/inetsrv/iis/admin/wmiprov_dynamic/multiszhelper.cpp
2020-09-26 16:20:57 +08:00

564 lines
11 KiB
C++

/*++
Copyright (c) 1998-2001 Microsoft Corporation
Module Name:
MultiSzHelper.cpp
Abstract:
Implements the CMultiSzHelper class
Author:
Mohit Srivastava 22-March-01
Revision History:
--*/
#include "MultiSzHelper.h"
#include <iiscnfg.h>
#include <dbgutil.h>
#include <atlbase.h>
#include "utils.h"
//
// CMultiSz
//
CMultiSz::CMultiSz()
{
m_pMbp = NULL;
m_pNamespace = NULL;
m_pFormattedMultiSz = NULL;
}
CMultiSz::CMultiSz(
METABASE_PROPERTY* i_pMbp,
CWbemServices* i_pNamespace)
{
DBG_ASSERT(i_pMbp != NULL);
DBG_ASSERT(i_pNamespace != NULL);
m_pMbp = i_pMbp;
m_pNamespace = i_pNamespace;
m_pFormattedMultiSz = NULL;
if(m_pMbp != NULL)
{
TFormattedMultiSz* pFormattedMultiSz = NULL;
for(ULONG i = 0; ; i++)
{
pFormattedMultiSz = TFormattedMultiSzData::apFormattedMultiSz[i];
if(pFormattedMultiSz == NULL)
{
break;
}
else if(pFormattedMultiSz->dwPropId == m_pMbp->dwMDIdentifier)
{
m_pFormattedMultiSz = pFormattedMultiSz;
break;
}
}
}
}
CMultiSz::~CMultiSz()
{
}
HRESULT CMultiSz::ToMetabaseForm(
const VARIANT* i_pvt,
LPWSTR* o_pmsz,
PDWORD io_pdw)
{
DBG_ASSERT(i_pvt != NULL);
DBG_ASSERT(o_pmsz != NULL);
DBG_ASSERT(io_pdw != NULL);
*o_pmsz = NULL;
*io_pdw = NULL;
return CreateMultiSzFromSafeArray(
*i_pvt,
o_pmsz,
io_pdw);
}
HRESULT CMultiSz::ToWmiForm(
LPCWSTR i_msz,
VARIANT* io_pvt)
{
DBG_ASSERT(i_msz != NULL);
DBG_ASSERT(io_pvt != NULL);
return LoadSafeArrayFromMultiSz(
i_msz,
*io_pvt);
}
//
// private
//
HRESULT CMultiSz::CreateMultiSzFromSafeArray(
const VARIANT& i_vt,
WCHAR** o_pmsz,
DWORD* io_pdw
)
/*++
Synopsis:
Arguments: [i_vt] -
[o_pmsz] -
[io_pdw] -
--*/
{
DBG_ASSERT(i_vt.vt == (VT_ARRAY | VT_BSTR) || i_vt.vt == (VT_ARRAY | VT_UNKNOWN));
DBG_ASSERT(o_pmsz != NULL);
DBG_ASSERT(io_pdw != NULL);
HRESULT hr = S_OK;
if(i_vt.parray == NULL)
{
*o_pmsz = NULL;
*io_pdw = 0;
}
WCHAR* msz = NULL;
long iLo,iUp,c;
SAFEARRAY* psa = i_vt.parray;
long i = 0;
BSTR bstr = NULL;
hr = SafeArrayGetLBound(psa,1,&iLo);
if(FAILED(hr))
{
goto exit;
}
hr = SafeArrayGetUBound(psa,1,&iUp);
if(FAILED(hr))
{
goto exit;
}
for (*io_pdw=0, c = iLo; c <= iUp; c++)
{
if(m_pFormattedMultiSz)
{
DBG_ASSERT(m_pMbp != NULL);
DBG_ASSERT(m_pNamespace != NULL);
CComPtr<IWbemClassObject> spObj;
hr = SafeArrayGetElement(psa, &c, &spObj);
if(FAILED(hr))
{
goto exit;
}
hr = UnparseEntry(spObj, &bstr);
if(FAILED(hr))
{
goto exit;
}
}
else
{
hr = SafeArrayGetElement(psa,&c,&bstr);
if(FAILED(hr))
{
goto exit;
}
}
*io_pdw = *io_pdw + wcslen(bstr) + 1;
hr = MzCat(&msz,bstr);
if(FAILED(hr))
{
goto exit;
}
SysFreeString(bstr);
bstr = NULL;
}
*io_pdw +=1;
*o_pmsz = msz;
exit:
if(FAILED(hr))
{
delete [] msz;
msz = NULL;
}
SysFreeString(bstr);
bstr = NULL;
return hr;
}
HRESULT CMultiSz::MzCat(
WCHAR** io_ppdst,
const WCHAR* i_psz
)
/*++
Synopsis:
The metabase has this animal called METADATA_STRINGSZ which has the
following form: <string><null><string><null><null>. MzCat concatenates
strings in the defined way. *io_ppdst has the new pointer upon exit. The
previous value of *io_ppdst is delelted. *io_ppdst == NULL is handled.
Arguments: [io_ppdst] -
[i_psz] -
--*/
{
DBG_ASSERT(io_ppdst != NULL);
WCHAR *psrc;
WCHAR *pdst;
WCHAR *pnew;
int ilen;
if (i_psz == NULL)
return WBEM_E_FAILED;
if (*io_ppdst)
{
for ( ilen=0, psrc = *io_ppdst
; *psrc || *(psrc+1)
; psrc++, ilen++
)
{
;
}
ilen = ilen + wcslen(i_psz)+3;
}
else ilen = wcslen(i_psz)+2;
pnew = pdst = new WCHAR[ilen];
if (!pdst)
return WBEM_E_OUT_OF_MEMORY;
if (*io_ppdst)
{
for ( psrc = *io_ppdst
; *psrc || *(psrc+1)
; pdst++, psrc++
)
{
*pdst = *psrc;
}
*pdst = L'\0';
pdst++;
}
wcscpy(pdst,i_psz);
*(pnew+ilen-1)=L'\0';
delete *io_ppdst;
*io_ppdst=pnew;
return WBEM_S_NO_ERROR;
}
HRESULT CMultiSz::LoadSafeArrayFromMultiSz(
LPCWSTR i_msz,
VARIANT& io_vt)
/*++
Synopsis:
Arguments: [i_msz] -
[io_vt] -
Return Value:
--*/
{
DBG_ASSERT(i_msz != NULL);
LPCWSTR msz;
HRESULT hr = WBEM_S_NO_ERROR;
DWORD c;
SAFEARRAYBOUND aDim;
SAFEARRAY* psa = NULL;
long i = 0;
VARTYPE vtypeData = (m_pFormattedMultiSz) ? VT_UNKNOWN : VT_BSTR;
CComPtr<IWbemClassObject> spClass;
//
// figure the dimensions of the multisz
//
for (c=1,msz=i_msz; *msz||*(msz+1); msz++)
{
if(!*msz)
{
c++;
}
}
aDim.lLbound = 0;
aDim.cElements= c;
psa = SafeArrayCreate(vtypeData, 1, &aDim);
if (!psa)
{
hr = WBEM_E_OUT_OF_MEMORY;
goto exit;
}
if( m_pFormattedMultiSz )
{
HRESULT hr = S_OK;
hr = m_pNamespace->GetObject(
m_pFormattedMultiSz->wszWmiClassName,
0,
NULL,
&spClass,
NULL);
if(FAILED(hr))
{
goto exit;
}
}
for (msz=i_msz; ; i++)
{
if(m_pFormattedMultiSz)
{
DBG_ASSERT(m_pMbp != NULL);
DBG_ASSERT(m_pNamespace != NULL);
CComPtr<IWbemClassObject> spObj;
hr = spClass->SpawnInstance(0, &spObj);
if(FAILED(hr))
{
goto exit;
}
hr = ParseEntry(msz, spObj);
if(FAILED(hr))
{
goto exit;
}
hr = SafeArrayPutElement(psa, &i, spObj);
if(FAILED(hr))
{
goto exit;
}
}
else
{
CComBSTR sbstr = msz;
if(sbstr.m_str == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
goto exit;
}
hr = SafeArrayPutElement(psa, &i, (BSTR)sbstr);
if(FAILED(hr))
{
goto exit;
}
}
msz += wcslen(msz) + 1;
if (!*msz)
{
break;
}
}
io_vt.vt = VT_ARRAY | vtypeData;
io_vt.parray = psa;
exit:
if (psa && FAILED(hr))
{
SafeArrayDestroy(psa);
}
return hr;
}
HRESULT CMultiSz::ParseEntry(
LPCWSTR i_wszEntry,
IWbemClassObject* io_pObj)
/*++
Synopsis:
Arguments: [i_wszEntry] -
[io_pObj] - WMI object corresponding to the particular entry.
SpawnInstance should have been called by caller.
Return Value:
--*/
{
DBG_ASSERT(i_wszEntry != NULL);
DBG_ASSERT(io_pObj != NULL);
DBG_ASSERT(m_pFormattedMultiSz != NULL);
HRESULT hr = WBEM_S_NO_ERROR;
ULONG idx = 0;
LPCWSTR wszValue = NULL;
ULONG NrFields = 0;
CComPtr<IWbemClassObject> spObj = io_pObj; // dest object
//
// Make a copy of the entry. Put on stack or heap depending on size.
//
WCHAR wszBufStack[64];
LPWSTR wszBufDyn = NULL;
LPWSTR wszEntry = NULL;
ULONG cchEntry = wcslen(i_wszEntry);
if((cchEntry+1) < 64)
{
wszEntry = wszBufStack;
}
else
{
wszBufDyn = new WCHAR[cchEntry+1];
if(wszBufDyn == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
goto exit;
}
wszEntry = wszBufDyn;
}
memcpy(wszEntry, i_wszEntry, sizeof(WCHAR) * (cchEntry + 1));
//
// get the number of fields
//
if(m_pFormattedMultiSz->awszFields != NULL)
{
for(idx = 0; m_pFormattedMultiSz->awszFields[idx] != NULL; idx++)
{
}
NrFields = idx;
DBG_ASSERT(NrFields <= MAX_FIELDS);
}
//
// Parse
//
ULONG jdx = 0;
LONG idxEndOfLastString = -1;
for(idx = 0; idx < (cchEntry+1) && jdx < NrFields; idx++)
{
if( wszEntry[idx] == m_pFormattedMultiSz->wcDelim ||
wszEntry[idx] == L'\0' )
{
//
// If there's only one spot left in our array, we take the remaining
// string -- including delimeters -- and put it as the last element
//
if(jdx != NrFields-1)
{
wszEntry[idx] = L'\0';
}
CComVariant vtEntry;
vtEntry = wszEntry + idxEndOfLastString + 1;
if(vtEntry.vt == VT_ERROR)
{
hr = vtEntry.scode;
goto exit;
}
hr = spObj->Put(
m_pFormattedMultiSz->awszFields[jdx],
0,
&vtEntry,
0);
if(FAILED(hr))
{
goto exit;
}
jdx++;
idxEndOfLastString = idx;
}
}
exit:
delete [] wszBufDyn;
wszBufDyn = NULL;
return hr;
}
HRESULT CMultiSz::UnparseEntry(
IWbemClassObject* i_pObj,
BSTR* o_pbstrEntry)
{
DBG_ASSERT(i_pObj != NULL);
DBG_ASSERT(o_pbstrEntry != NULL);
DBG_ASSERT(m_pFormattedMultiSz != NULL);
*o_pbstrEntry = NULL;
HRESULT hr = S_OK;
LPCWSTR* awszFields = m_pFormattedMultiSz->awszFields;
CComBSTR sbstrUnparsed;
if(awszFields == NULL)
{
goto exit;
}
WCHAR wszDelim[2];
wszDelim[0] = m_pFormattedMultiSz->wcDelim;
wszDelim[1] = L'\0';
for(ULONG i = 0; awszFields[i] != NULL; i++)
{
CComVariant vtValue;
hr = i_pObj->Get(
awszFields[i],
0,
&vtValue,
NULL,
NULL);
if(FAILED(hr))
{
goto exit;
}
if(vtValue.vt == VT_BSTR && vtValue.bstrVal != NULL)
{
sbstrUnparsed += vtValue.bstrVal;
if(sbstrUnparsed.m_str == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
goto exit;
}
}
if(awszFields[i+1] != NULL)
{
sbstrUnparsed += wszDelim;
if(sbstrUnparsed.m_str == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
goto exit;
}
}
}
//
// Set out parameters if everything succeeded
//
*o_pbstrEntry = sbstrUnparsed.Detach();
exit:
return hr;
}