2025-04-27 07:49:33 -04:00

2454 lines
73 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name :
autobj.cxx
Abstract:
This module defines Automation Admin APIs.
Author:
Michael Thomas (michth) 17-Dec-1996
--*/
extern "C" {
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
}
#include <dbgutil.h>
#include <ole2.h>
#include <windows.h>
#include <defaults.hxx>
#include <coiadm.hxx>
#include <coiaut.hxx>
#include <admacl.hxx>
#include <cguid.h>
#include <oleauto.h>
#define RELEASE_INTERFACE(p)\
{\
IUnknown* pTmp = (IUnknown*)p;\
p = NULL;\
if (NULL != pTmp)\
pTmp->Release();\
}
//HRESULT RaiseException(int nID, REFGUID rguid);
CMSMetaBase::CMSMetaBase()
{
HRESULT hresInit;
IMSAdminBase *padmcDcomInterface;
ITypeLib *pITypeLib;
m_pITINeutral=NULL;
m_pITIDataNeutral=NULL;
m_pITIKeyNeutral=NULL;
m_bComInitialized = FALSE;
m_padmcDcomInterface = NULL;
hresInit = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hresInit)) {
m_bComInitialized = TRUE;
hresInit = CoCreateInstance(GETAdminBaseCLSID(TRUE), NULL, CLSCTX_SERVER, IID_IMSAdminBase, (void**) &padmcDcomInterface);
if (FAILED(hresInit)) {
hresInit = CoCreateInstance(GETAdminBaseCLSID(FALSE), NULL, CLSCTX_SERVER, IID_IMSAdminBase, (void**) &padmcDcomInterface);
}
}
if (SUCCEEDED(hresInit)) {
m_padmcDcomInterface = padmcDcomInterface;
hresInit = LoadRegTypeLib(LIBID_MSAdmin,
1,
0,
LANG_NEUTRAL,
&pITypeLib);
if (FAILED(hresInit)) {
hresInit=LoadTypeLib(OLESTR("iadm.tlb"), &pITypeLib);
}
if (SUCCEEDED(hresInit)) {
//Got the type lib, get type info for the interface we want
hresInit=pITypeLib->GetTypeInfoOfGuid(IID_IMSMetaBase, &m_pITINeutral);
if (SUCCEEDED(hresInit)) {
m_pITINeutral->AddRef();
hresInit=pITypeLib->GetTypeInfoOfGuid(IID_IMSMetaDataItem, &m_pITIDataNeutral);
if (SUCCEEDED(hresInit)) {
m_pITIDataNeutral->AddRef();
hresInit=pITypeLib->GetTypeInfoOfGuid(IID_IMSMetaKey, &m_pITIKeyNeutral);
if (SUCCEEDED(hresInit)) {
m_pITIKeyNeutral->AddRef();
}
}
}
pITypeLib->Release();
}
}
m_hresInit = hresInit;
}
CMSMetaBase::~CMSMetaBase()
{
if (m_bComInitialized) {
RELEASE_INTERFACE(m_pITINeutral);
RELEASE_INTERFACE(m_pITIDataNeutral);
RELEASE_INTERFACE(m_pITIKeyNeutral);
RELEASE_INTERFACE(m_padmcDcomInterface);
CoUninitialize();
}
}
HRESULT STDMETHODCALLTYPE
CMSMetaBase::CopyKey(
/* [in] */ IMSMetaKey __RPC_FAR *pmkSourceKey,
/* [in] */ IMSMetaKey __RPC_FAR *pmkDestKey,
/* [in] */ BOOL bOverwriteFlag,
/* [in] */ BOOL bCopyFlag,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaSourcePath,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaDestPath)
{
HRESULT hresReturn;
BYTE *pszSourcePath;
BYTE *pszDestPath;
//DebugBreak();
if ((pmkSourceKey == NULL) ||
(!(((CMSMetaKey *)pmkSourceKey)->IsOpen())) ||
(pmkDestKey == NULL) ||
(!(((CMSMetaKey *)pmkDestKey)->IsOpen()))) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantString(pvaSourcePath, pszSourcePath);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantString(pvaDestPath, pszDestPath);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->CopyKey(((CMSMetaKey *)pmkSourceKey)->GetHandle(),
pszSourcePath,
((CMSMetaKey *)pmkDestKey)->GetHandle(),
pszDestPath,
bOverwriteFlag,
bCopyFlag);
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaBase::CopyData(
/* [in] */ IMSMetaKey __RPC_FAR *pmkSourceKey,
/* [in] */ IMSMetaKey __RPC_FAR *pmkDestKey,
/* [in] */ long dwAttributes,
/* [in] */ long dwUserType,
/* [in] */ long dwDataType,
/* [in] */ BOOL bCopyFlag,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaSourcePath,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaDestPath)
{
HRESULT hresReturn;
BYTE *pszSourcePath;
BYTE *pszDestPath;
//DebugBreak();
if ((pmkSourceKey == NULL) ||
(!(((CMSMetaKey *)pmkSourceKey)->IsOpen())) ||
(pmkDestKey == NULL) ||
(!(((CMSMetaKey *)pmkDestKey)->IsOpen()))) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantString(pvaSourcePath, pszSourcePath);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantString(pvaDestPath, pszDestPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->CopyData(((CMSMetaKey *)pmkSourceKey)->GetHandle(),
pszSourcePath,
((CMSMetaKey *)pmkDestKey)->GetHandle(),
pszDestPath,
dwAttributes,
dwUserType,
dwDataType,
bCopyFlag);
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaBase::OpenKey(
/* [in] */ long dwAccessRequested,
/* [optional][in] */ VARIANTARG vaTimeOut,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath,
/* [retval][out] */ IMSMetaKey __RPC_FAR *__RPC_FAR *ppmkKey)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
METADATA_HANDLE hNew;
DWORD dwTimeOut;
//DebugBreak();
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantDword(&vaTimeOut, dwTimeOut, ADM_DEFAULT_TIMEOUT);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->OpenKey(METADATA_MASTER_ROOT_HANDLE,
pszPath,
dwAccessRequested,
dwTimeOut,
&hNew);
if (SUCCEEDED(hresReturn)) {
IMSMetaKey *pmkKey = new CMSMetaKey(m_pITIKeyNeutral,
m_pITIDataNeutral,
hNew,
m_padmcDcomInterface,
(IMSMetaBase *)this);
if (pmkKey == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
hresReturn = pmkKey->QueryInterface(IID_IMSMetaKey, (void **)ppmkKey);
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaBase::FlushData( void)
{
HRESULT hresReturn = ERROR_SUCCESS;
//DebugBreak();
hresReturn = m_padmcDcomInterface->SaveData();
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaBase::GetSystemChangeNumber(
/* [out] */ VARIANTARG __RPC_FAR *pdwSystemChangeNumber)
{
HRESULT hresReturn = ERROR_SUCCESS;
DWORD *pdwSCN;
//DebugBreak();
if ((pdwSystemChangeNumber == NULL) || ((pdwSystemChangeNumber->vt & VT_BYREF) == 0)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
switch ((pdwSystemChangeNumber->vt & 0xFF)) {
case VT_I4:
pdwSCN = (DWORD *)pdwSystemChangeNumber->plVal;
break;
case VT_UI1:
pdwSCN = pdwSystemChangeNumber->pulVal;
break;
default:
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
}
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->GetSystemChangeNumber(pdwSCN);
}
return hresReturn;
}
HRESULT _stdcall
CMSMetaBase::QueryInterface(REFIID riid, void **ppObject)
{
if (riid==IID_IUnknown || riid==IID_IMSMetaBase || riid==IID_IDispatch) {
*ppObject = (IMSMetaBase *) this;
AddRef();
}
else {
return E_NOINTERFACE;
}
return NO_ERROR;
}
ULONG _stdcall
CMSMetaBase::AddRef()
{
DWORD dwRefCount;
dwRefCount = InterlockedIncrement((long *)&m_dwRefCount);
return dwRefCount;
}
ULONG _stdcall
CMSMetaBase::Release()
{
DWORD dwRefCount;
dwRefCount = InterlockedDecrement((long *)&m_dwRefCount);
if (dwRefCount == 0) {
delete this;
}
return dwRefCount;
}
//IDispatch members
//IDispatch functions, now part of CMDCOM
/*
* CMDCOM::GetTypeInfoCount
*
* Purpose:
* Returns the number of type information (ITypeInfo) interfaces
* that the object provides (0 or 1).
*
* Parameters:
* pctInfo UINT * to the location to receive
* the count of interfaces.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaBase::GetTypeInfoCount(UINT *pctInfo)
{
//We implement GetTypeInfo so return 1
*pctInfo=1;
return NOERROR;
}
/*
* CMDCOM::GetTypeInfo
*
* Purpose:
* Retrieves type information for the automation interface. This
* is used anywhere that the right ITypeInfo interface is needed
* for whatever LCID is applicable. Specifically, this is used
* from within GetIDsOfNames and Invoke.
*
* Parameters:
* itInfo UINT reserved. Must be zero.
* lcid LCID providing the locale for the type
* information. If the object does not support
* localization, this is ignored.
* ppITypeInfo ITypeInfo ** in which to store the ITypeInfo
* interface for the object.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaBase::GetTypeInfo(UINT itInfo, LCID lcid
, ITypeInfo **ppITypeInfo)
{
HRESULT hr;
ITypeLib *pITypeLib;
ITypeInfo **ppITI=NULL;
if (0!=itInfo)
return ResultFromScode(TYPE_E_ELEMENTNOTFOUND);
if (NULL==ppITypeInfo)
return ResultFromScode(E_POINTER);
/*
* Note: the type library is still loaded since we have
* an ITypeInfo from it.
*/
m_pITINeutral->AddRef();
*ppITypeInfo=m_pITINeutral;
return NOERROR;
}
/*
* CMDCOM::GetIDsOfNames
*
* Purpose:
* Converts text names into DISPIDs to pass to Invoke
*
* Parameters:
* riid REFIID reserved. Must be IID_NULL.
* rgszNames OLECHAR ** pointing to the array of names to be
* mapped.
* cNames UINT number of names to be mapped.
* lcid LCID of the locale.
* rgDispID DISPID * caller allocated array containing IDs
* corresponging to those names in rgszNames.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaBase::GetIDsOfNames(REFIID riid
, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
{
HRESULT hr;
ITypeInfo *pTI;
if (IID_NULL!=riid)
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
//Get the right ITypeInfo for lcid.
hr=GetTypeInfo(0, lcid, &pTI);
if (SUCCEEDED(hr))
{
hr=DispGetIDsOfNames(pTI, rgszNames, cNames, rgDispID);
pTI->Release();
}
return hr;
}
/*
* CMDCOM::Invoke
*
* Purpose:
* Calls a method in the dispatch interface or manipulates a
* property.
*
* Parameters:
* dispID DISPID of the method or property of interest.
* riid REFIID reserved, must be IID_NULL.
* lcid LCID of the locale.
* wFlags USHORT describing the context of the invocation.
* pDispParams DISPPARAMS * to the array of arguments.
* pVarResult VARIANT * in which to store the result. Is
* NULL if the caller is not interested.
* pExcepInfo EXCEPINFO * to exception information.
* puArgErr UINT * in which to store the index of an
* invalid parameter if DISP_E_TYPEMISMATCH
* is returned.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaBase::Invoke(DISPID dispID, REFIID riid
, LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams
, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
HRESULT hr;
//riid is supposed to be IID_NULL always
if (IID_NULL!=riid)
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
//Clear exceptions
SetErrorInfo(0L, NULL);
//This is exactly what DispInvoke does--so skip the overhead.
// hr=pTI->Invoke((IADMCOM *)this, dispID, wFlags
// , pDispParams, pVarResult, pExcepInfo, puArgErr);
hr=DispInvoke((IMSMetaBase *)this, m_pITINeutral, dispID, wFlags
, pDispParams, pVarResult, pExcepInfo, puArgErr);
//Exception handling is done within ITypeInfo::Invoke
return hr;
}
CMSMetaKey::CMSMetaKey(ITypeInfo *pITIKey,
ITypeInfo *pITIData,
METADATA_HANDLE hHandle,
IMSAdminBase *padmcDcomInterface,
IMSMetaBase *pmbMetaBase)
{
m_pITIKey = pITIKey;
m_pITIKey->AddRef();
m_pITIData = pITIData;
m_pITIData->AddRef();
m_hHandle = hHandle;
m_bOpen = TRUE;
DBG_REQUIRE(SUCCEEDED(pmbMetaBase->QueryInterface(IID_IMSMetaBase, (void **)&m_pmbMetaBase)));
DBG_REQUIRE(SUCCEEDED(padmcDcomInterface->QueryInterface(IID_IMSAdminBase, (void **)&m_padmcDcomInterface)));
// m_psaData = NULL;
// m_dwData = 0;
}
CMSMetaKey::~CMSMetaKey()
{
m_pITIKey->Release();
m_pITIData->Release();
if (m_bOpen) {
Close();
}
m_padmcDcomInterface->Release();
m_pmbMetaBase->Release();
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::AddKey(
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->AddKey(m_hHandle, pszPath);
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::DeleteKey(
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
//DebugBreak();
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->DeleteKey(m_hHandle, pszPath);
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::DeleteChildKeys(
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->DeleteChildKeys(m_hHandle, pszPath);
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::EnumKeys(
/* [out] */ VARIANTARG __RPC_FAR *pvaName,
/* [in] */ long dwEnumObjectIndex,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
BYTE pszName[METADATA_MAX_NAME_LEN];
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
if (pvaName == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
}
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->EnumKeys(m_hHandle, pszPath, pszName, dwEnumObjectIndex);
if (SUCCEEDED(hresReturn)) {
hresReturn = SetVariantString(pvaName, pszName);
}
}
}
return hresReturn;
}
//HRESULT STDMETHODCALLTYPE
//CMSMetaBase::GetDataObject(
// /* [out] */ IMSMetaDataItem __RPC_FAR *__RPC_FAR *ppmdiData)
///* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
//CMSMetaBase::get_GetDataObject(
// /* [retval][out] */ IMSMetaDataItem __RPC_FAR *__RPC_FAR *ppmdiData)
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaKey::get_DataItem(
/* [retval][out] */ IMSMetaDataItem __RPC_FAR *__RPC_FAR *ppmdiData)
{
HRESULT hresReturn;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
CMSMetaDataItem *padmadData = new CMSMetaDataItem(m_pITIData);
if (padmadData == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
hresReturn = padmadData->QueryInterface(IID_IMSMetaDataItem, (void **)ppmdiData);
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::SetData(
/* [in] */ IMSMetaDataItem __RPC_FAR *pmdiData,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
if (pmdiData == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantString(pvaPath, pszPath);
}
if (SUCCEEDED(hresReturn)) {
METADATA_RECORD *pmdrData = ((CMSMetaDataItem *)pmdiData)->GetMDRecord();
hresReturn = m_padmcDcomInterface->SetData(m_hHandle,
pszPath,
pmdrData);
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::GetData(
/* [in][out] */ IMSMetaDataItem __RPC_FAR *__RPC_FAR *ppmdiData,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
if (*ppmdiData == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantString(pvaPath, pszPath);
}
if (SUCCEEDED(hresReturn)) {
METADATA_RECORD *pmdrInput = ((CMSMetaDataItem *)(*ppmdiData))->GetMDRecord();
METADATA_RECORD mdrData = *pmdrInput;
BUFFER bufData;
DWORD dwDataLen;
mdrData.dwMDDataLen = bufData.QuerySize();
mdrData.pbMDData = (BYTE *) (bufData.QueryPtr());
hresReturn = m_padmcDcomInterface->GetData(m_hHandle,
pszPath,
&mdrData,
&dwDataLen);
if (hresReturn == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
if (!(bufData.Resize(dwDataLen))) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
mdrData.dwMDDataLen = bufData.QuerySize();
mdrData.pbMDData = (BYTE *) (bufData.QueryPtr());
hresReturn = m_padmcDcomInterface->GetData(m_hHandle,
pszPath,
&mdrData,
&dwDataLen);
}
}
if (SUCCEEDED(hresReturn)) {
hresReturn = ((CMSMetaDataItem *)(*ppmdiData))->SetMDRecord(&mdrData);
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::DeleteData(
/* [in] */ long dwIdentifier,
/* [in] */ long dwDataType,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->DeleteData(m_hHandle,
pszPath,
dwIdentifier,
dwDataType);
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::EnumData(
/* [out][in] */ IMSMetaDataItem __RPC_FAR *__RPC_FAR *ppmdiData,
/* [in] */ long dwEnumDataIndex,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
if (*ppmdiData == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantString(pvaPath, pszPath);
}
if (SUCCEEDED(hresReturn)) {
METADATA_RECORD *pmdrInput = ((CMSMetaDataItem *)(*ppmdiData))->GetMDRecord();
METADATA_RECORD mdrData = *pmdrInput;
BUFFER bufData;
DWORD dwDataLen;
mdrData.dwMDDataLen = bufData.QuerySize();
mdrData.pbMDData = (BYTE *) (bufData.QueryPtr());
hresReturn = m_padmcDcomInterface->EnumData(m_hHandle,
pszPath,
&mdrData,
dwEnumDataIndex,
&dwDataLen);
if (hresReturn == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
if (!(bufData.Resize(dwDataLen))) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
mdrData.dwMDDataLen = bufData.QuerySize();
mdrData.pbMDData = (BYTE *) (bufData.QueryPtr());
hresReturn = m_padmcDcomInterface->EnumData(m_hHandle,
pszPath,
&mdrData,
dwEnumDataIndex,
&dwDataLen);
}
}
if (SUCCEEDED(hresReturn)) {
hresReturn = ((CMSMetaDataItem *)(*ppmdiData))->SetMDRecord(&mdrData);
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::GetAllData(
/* [in] */ long dwAttributes,
/* [in] */ long dwUserType,
/* [in] */ long dwDataType,
/* [out] */ long __RPC_FAR *pdwDataSetNumber,
/* [out] */ VARIANTARG __RPC_FAR *pvaDataObjectsArray,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
if (pvaDataObjectsArray == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantString(pvaPath, pszPath);
}
if (SUCCEEDED(hresReturn)) {
BUFFER bufData;
DWORD dwNumDataEntries;
DWORD dwRequiredBufferLen;
hresReturn = m_padmcDcomInterface->GetAllData(m_hHandle,
pszPath,
(DWORD) dwAttributes,
(DWORD) dwUserType,
(DWORD) dwDataType,
&dwNumDataEntries,
(DWORD *)pdwDataSetNumber,
bufData.QuerySize(),
(BYTE *)bufData.QueryPtr(),
&dwRequiredBufferLen);
if (hresReturn == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
if (!(bufData.Resize(dwRequiredBufferLen))) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
hresReturn = m_padmcDcomInterface->GetAllData(m_hHandle,
pszPath,
(DWORD) dwAttributes,
(DWORD) dwUserType,
(DWORD) dwDataType,
&dwNumDataEntries,
(DWORD *)pdwDataSetNumber,
bufData.QuerySize(),
(BYTE *)bufData.QueryPtr(),
&dwRequiredBufferLen);
}
}
if (SUCCEEDED(hresReturn)) {
SAFEARRAYBOUND sabBounds;
SAFEARRAY *psaDataObjects;
CMSMetaDataItem **ppadmadDataObjects;
METADATA_GETALL_RECORD *pmdgarDataEntries = (METADATA_GETALL_RECORD *)bufData.QueryPtr();
sabBounds.cElements = dwNumDataEntries;
sabBounds.lLbound = 0;
psaDataObjects = SafeArrayCreate(VT_DISPATCH, 1, &sabBounds);
if (psaDataObjects == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
hresReturn = SafeArrayAccessData(psaDataObjects, (void **)&ppadmadDataObjects);
if (SUCCEEDED(hresReturn)) {
DWORD i;
CMSMetaDataItem *padmadNew;
for (i = 0; i < dwNumDataEntries; i++ ) {
padmadNew = new CMSMetaDataItem(m_pITIData);
if (padmadNew == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
break;
}
hresReturn = padmadNew->SetMDGetAllRecord((BYTE *)bufData.QueryPtr(), (&pmdgarDataEntries[i]));
if (FAILED(hresReturn)) {
break;
}
hresReturn = padmadNew->QueryInterface(IID_IMSMetaDataItem, (void **)&(ppadmadDataObjects[i]));
if (FAILED(hresReturn)) {
delete padmadNew;
break;
}
}
if (FAILED(hresReturn)) {
for (DWORD j = 0; j < i; j++) {
ppadmadDataObjects[j]->Release();
}
}
SafeArrayUnaccessData(psaDataObjects);
if (FAILED(hresReturn)) {
SafeArrayDestroy(psaDataObjects);
}
else {
pvaDataObjectsArray->vt = VT_ARRAY | VT_DISPATCH;
pvaDataObjectsArray->parray = psaDataObjects;
}
}
}
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::DeleteAllData(
/* [in] */ long dwUserType,
/* [in] */ long dwDataType,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
//DebugBreak();
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->DeleteAllData(m_hHandle,
pszPath,
dwUserType,
dwDataType);
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::OpenKey(
/* [in] */ long dwAccessRequested,
/* [optional][in] */ VARIANTARG vaTimeOut,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath,
/* [retval][out] */ IMSMetaKey __RPC_FAR *__RPC_FAR *ppmkKey)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
METADATA_HANDLE hNew;
DWORD dwTimeOut;
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
//DebugBreak();
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = GetVariantDword(&vaTimeOut, dwTimeOut, ADM_DEFAULT_TIMEOUT);
}
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->OpenKey(m_hHandle,
pszPath,
dwAccessRequested,
dwTimeOut,
&hNew);
if (SUCCEEDED(hresReturn)) {
IMSMetaKey *pmkKey = new CMSMetaKey(m_pITIKey,
m_pITIData,
hNew,
m_padmcDcomInterface,
m_pmbMetaBase);
if (pmkKey == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
hresReturn = pmkKey->QueryInterface(IID_IMSMetaKey, (void **)ppmkKey);
}
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::Close(void)
{
HRESULT hresReturn = ERROR_SUCCESS;
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
hresReturn = m_padmcDcomInterface->CloseKey(m_hHandle);
if (SUCCEEDED(hresReturn)) {
m_bOpen = FALSE;
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::ChangePermissions(
/* [in] */ long dwAccessRequested,
/* [optional][in] */ VARIANTARG vaTimeOut)
{
HRESULT hresReturn = ERROR_SUCCESS;
DWORD dwTimeOut;
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
//DebugBreak();
hresReturn = GetVariantDword(&vaTimeOut, dwTimeOut, ADM_DEFAULT_TIMEOUT);
hresReturn = m_padmcDcomInterface->ChangePermissions(m_hHandle,
dwTimeOut,
dwAccessRequested);
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::GetKeyInfo(
/* [out] */ long __RPC_FAR *dwPermissions,
/* [out] */ long __RPC_FAR *dwSystemChangeNumber)
{
HRESULT hresReturn = ERROR_SUCCESS;
METADATA_HANDLE_INFO mhiInfo;
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
//DebugBreak();
hresReturn = m_padmcDcomInterface->GetHandleInfo(m_hHandle,
&mhiInfo);
if (SUCCEEDED(hresReturn)) {
*(DWORD *)dwPermissions = mhiInfo.dwMDPermissions;
*(DWORD *)dwSystemChangeNumber = mhiInfo.dwMDSystemChangeNumber;
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::GetDataSetNumber(
/* [out] */ long __RPC_FAR *pdwDataSetNumber,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
//DebugBreak();
if (pdwDataSetNumber == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
hresReturn = m_padmcDcomInterface->GetDataSetNumber(m_hHandle,
pszPath,
(DWORD *)pdwDataSetNumber);
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::SetLastChangeTime(
/* [in] */ DATE dLastChangeTime,
/* [optional][in] */ VARIANTARG vaLocalTime,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
BOOL bLocalTime = TRUE;
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
if (SUCCEEDED(VariantChangeType(&vaLocalTime,
&vaLocalTime,
0,
VT_BOOL))) {
bLocalTime = vaLocalTime.boolVal;
}
//DebugBreak();
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
FILETIME ftTime;
SYSTEMTIME stTime;
if (!VariantTimeToSystemTime(dLastChangeTime,&stTime)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else if (!SystemTimeToFileTime(&stTime, &ftTime)) {
hresReturn = E_UNEXPECTED;
}
else {
hresReturn = m_padmcDcomInterface->SetLastChangeTime(m_hHandle,
pszPath,
&ftTime,
bLocalTime);
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CMSMetaKey::GetLastChangeTime(
/* [out] */ DATE __RPC_FAR *pdLastChangeTime,
/* [optional][in] */ VARIANTARG vaLocalTime,
/* [optional][in] */ VARIANTARG __RPC_FAR *pvaPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
BYTE *pszPath;
BOOL bLocalTime = TRUE;
if (!m_bOpen) {
hresReturn = E_HANDLE;
}
else {
if (SUCCEEDED(VariantChangeType(&vaLocalTime,
&vaLocalTime,
0,
VT_BOOL))) {
bLocalTime = vaLocalTime.boolVal;
}
hresReturn = GetVariantString(pvaPath, pszPath);
if (SUCCEEDED(hresReturn)) {
FILETIME ftTime;
SYSTEMTIME stTime;
hresReturn = m_padmcDcomInterface->GetLastChangeTime(m_hHandle,
pszPath,
&ftTime,
bLocalTime);
if (SUCCEEDED(hresReturn)) {
if (!FileTimeToSystemTime(&ftTime, &stTime)) {
hresReturn = E_UNEXPECTED;
}
else if (!SystemTimeToVariantTime(&stTime, pdLastChangeTime)) {
hresReturn = E_UNEXPECTED;
}
}
}
}
return hresReturn;
}
HRESULT _stdcall
CMSMetaKey::QueryInterface(REFIID riid, void **ppObject)
{
if (riid==IID_IUnknown || riid==IID_IMSMetaKey || riid==IID_IDispatch) {
*ppObject = (IMSMetaKey *) this;
AddRef();
}
else {
return E_NOINTERFACE;
}
return NO_ERROR;
}
ULONG _stdcall
CMSMetaKey::AddRef()
{
DWORD dwRefCount;
dwRefCount = InterlockedIncrement((long *)&m_dwRefCount);
return dwRefCount;
}
ULONG _stdcall
CMSMetaKey::Release()
{
DWORD dwRefCount;
dwRefCount = InterlockedDecrement((long *)&m_dwRefCount);
if (dwRefCount == 0) {
delete (this);
}
return dwRefCount;
}
//IDispatch members
//IDispatch functions, now part of CMDCOM
/*
* CMDCOM::GetTypeInfoCount
*
* Purpose:
* Returns the number of type information (ITypeInfo) interfaces
* that the object provides (0 or 1).
*
* Parameters:
* pctInfo UINT * to the location to receive
* the count of interfaces.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaKey::GetTypeInfoCount(UINT *pctInfo)
{
//We implement GetTypeInfo so return 1
*pctInfo=1;
return NOERROR;
}
/*
* CMDCOM::GetTypeInfo
*
* Purpose:
* Retrieves type information for the automation interface. This
* is used anywhere that the right ITypeInfo interface is needed
* for whatever LCID is applicable. Specifically, this is used
* from within GetIDsOfNames and Invoke.
*
* Parameters:
* itInfo UINT reserved. Must be zero.
* lcid LCID providing the locale for the type
* information. If the object does not support
* localization, this is ignored.
* ppITypeInfo ITypeInfo ** in which to store the ITypeInfo
* interface for the object.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaKey::GetTypeInfo(UINT itInfo, LCID lcid
, ITypeInfo **ppITypeInfo)
{
HRESULT hr;
ITypeLib *pITypeLib;
ITypeInfo **ppITI=NULL;
if (0!=itInfo)
return ResultFromScode(TYPE_E_ELEMENTNOTFOUND);
if (NULL==ppITypeInfo)
return ResultFromScode(E_POINTER);
m_pITIKey->AddRef();
*ppITypeInfo = m_pITIKey;
return NOERROR;
}
/*
* CMDCOM::GetIDsOfNames
*
* Purpose:
* Converts text names into DISPIDs to pass to Invoke
*
* Parameters:
* riid REFIID reserved. Must be IID_NULL.
* rgszNames OLECHAR ** pointing to the array of names to be
* mapped.
* cNames UINT number of names to be mapped.
* lcid LCID of the locale.
* rgDispID DISPID * caller allocated array containing IDs
* corresponging to those names in rgszNames.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaKey::GetIDsOfNames(REFIID riid
, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
{
HRESULT hr;
ITypeInfo *pTI;
if (IID_NULL!=riid)
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
//Get the right ITypeInfo for lcid.
hr=GetTypeInfo(0, lcid, &pTI);
if (SUCCEEDED(hr))
{
hr=DispGetIDsOfNames(pTI, rgszNames, cNames, rgDispID);
pTI->Release();
}
return hr;
}
/*
* CMDCOM::Invoke
*
* Purpose:
* Calls a method in the dispatch interface or manipulates a
* property.
*
* Parameters:
* dispID DISPID of the method or property of interest.
* riid REFIID reserved, must be IID_NULL.
* lcid LCID of the locale.
* wFlags USHORT describing the context of the invocation.
* pDispParams DISPPARAMS * to the array of arguments.
* pVarResult VARIANT * in which to store the result. Is
* NULL if the caller is not interested.
* pExcepInfo EXCEPINFO * to exception information.
* puArgErr UINT * in which to store the index of an
* invalid parameter if DISP_E_TYPEMISMATCH
* is returned.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaKey::Invoke(DISPID dispID, REFIID riid
, LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams
, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
HRESULT hr;
//riid is supposed to be IID_NULL always
if (IID_NULL!=riid)
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
//Clear exceptions
SetErrorInfo(0L, NULL);
//This is exactly what DispInvoke does--so skip the overhead.
// hr=pTI->Invoke((IADMCOM *)this, dispID, wFlags
// , pDispParams, pVarResult, pExcepInfo, puArgErr);
hr=DispInvoke((IMSMetaKey *)this, m_pITIKey, dispID, wFlags
, pDispParams, pVarResult, pExcepInfo, puArgErr);
//Exception handling is done within ITypeInfo::Invoke
return hr;
}
CMSMetaDataItem::CMSMetaDataItem(ITypeInfo *pITIData)
{
m_mdrData.dwMDIdentifier = 0;
m_mdrData.dwMDAttributes = 0;
m_mdrData.dwMDDataType = ALL_METADATA;
m_mdrData.dwMDUserType = ALL_METADATA;
m_mdrData.pbMDData = NULL;
m_pITIData = pITIData;
m_pITIData->AddRef();
// m_psaData = NULL;
// m_dwData = 0;
}
CMSMetaDataItem::~CMSMetaDataItem()
{
m_pITIData->Release();
}
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_Identifier(
/* [out] */ long __RPC_FAR *pdwIdentifier)
{
HRESULT hresReturn = ERROR_SUCCESS;
//DebugBreak();
if (pdwIdentifier == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
*pdwIdentifier = m_mdrData.dwMDIdentifier;
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_Identifier(
/* [in] */ long dwIdentifier)
{
//DebugBreak();
m_mdrData.dwMDIdentifier = dwIdentifier;
return ERROR_SUCCESS;
}
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_Attributes(
/* [out] */ long __RPC_FAR *pdwAttributes)
{
HRESULT hresReturn = ERROR_SUCCESS;
//DebugBreak();
if (pdwAttributes == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
*pdwAttributes = m_mdrData.dwMDAttributes;
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_Attributes(
/* [in] */ long dwAttributes)
{
//DebugBreak();
m_mdrData.dwMDAttributes = dwAttributes;
return ERROR_SUCCESS;
}
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_InheritAttribute(
/* [retval][out] */ BOOL __RPC_FAR *pbInherit)
{
HRESULT hresReturn = ERROR_SUCCESS;
if (pbInherit == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
if ((m_mdrData.dwMDAttributes & METADATA_INHERIT) == 0) {
*pbInherit = FALSE;
}
else {
*pbInherit = TRUE;
}
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_InheritAttribute(
/* [in] */ BOOL bInherit)
{
if (bInherit) {
m_mdrData.dwMDAttributes |= METADATA_INHERIT;
}
else {
m_mdrData.dwMDAttributes &= !METADATA_INHERIT;
}
return ERROR_SUCCESS;
}
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_ParialPathAttribute(
/* [retval][out] */ BOOL __RPC_FAR *pbParialPath)
{
HRESULT hresReturn = ERROR_SUCCESS;
if (pbParialPath == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
if ((m_mdrData.dwMDAttributes & METADATA_PARTIAL_PATH) == 0) {
*pbParialPath = FALSE;
}
else {
*pbParialPath = TRUE;
}
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_PartialPathAttribute(
/* [in] */ BOOL bPartialPath)
{
if (bPartialPath) {
m_mdrData.dwMDAttributes |= METADATA_PARTIAL_PATH;
}
else {
m_mdrData.dwMDAttributes &= !METADATA_PARTIAL_PATH;
}
return ERROR_SUCCESS;
}
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_SecureAttribute(
/* [retval][out] */ BOOL __RPC_FAR *pbSecure)
{
HRESULT hresReturn = ERROR_SUCCESS;
if (pbSecure == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
if ((m_mdrData.dwMDAttributes & METADATA_SECURE) == 0) {
*pbSecure = FALSE;
}
else {
*pbSecure = TRUE;
}
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_SecureAttribute(
/* [in] */ BOOL bSecure)
{
if (bSecure) {
m_mdrData.dwMDAttributes |= METADATA_SECURE;
}
else {
m_mdrData.dwMDAttributes &= !METADATA_SECURE;
}
return ERROR_SUCCESS;
}
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_ReferenceAttribute(
/* [retval][out] */ BOOL __RPC_FAR *pbReference)
{
HRESULT hresReturn = ERROR_SUCCESS;
if (pbReference == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
if ((m_mdrData.dwMDAttributes & METADATA_REFERENCE) == 0) {
*pbReference = FALSE;
}
else {
*pbReference = TRUE;
}
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_ReferenceAttribute(
/* [in] */ BOOL bReference)
{
if (bReference) {
m_mdrData.dwMDAttributes |= METADATA_REFERENCE;
}
else {
m_mdrData.dwMDAttributes &= !METADATA_REFERENCE;
}
return ERROR_SUCCESS;
}
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_UserType(
/* [out] */ long __RPC_FAR *pdwUserType)
{
HRESULT hresReturn = ERROR_SUCCESS;
//DebugBreak();
if (pdwUserType == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
*pdwUserType = m_mdrData.dwMDUserType;
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_UserType(
/* [in] */ long dwUserType)
{
//DebugBreak();
m_mdrData.dwMDUserType = dwUserType;
return ERROR_SUCCESS;
}
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_DataType(
/* [out] */ long __RPC_FAR *pdwDataType)
{
HRESULT hresReturn = ERROR_SUCCESS;
//DebugBreak();
if (pdwDataType == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
*pdwDataType = m_mdrData.dwMDDataType;
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_DataType(
/* [in] */ LONG dwDataType)
{
//DebugBreak();
m_mdrData.dwMDDataType = (DWORD)dwDataType;
return ERROR_SUCCESS;
}
///* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
//CMSMetaDataItem::get_GetDataLen(
// /* [retval][out] */ long __RPC_FAR *pdwMDDataLen)
/*
{
HRESULT hresReturn = ERROR_SUCCESS;
//DebugBreak();
if (pdwMDDataLen == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
*pdwMDDataLen = m_mdrData.dwMDDataLen;
}
return hresReturn;
}
*/
///* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
//CMSMetaDataItem::put_SetDataLen(
// /* [in] */ long dwMDDataLen)
/*
{
//DebugBreak();
m_mdrData.dwMDDataLen = dwMDDataLen;
return ERROR_SUCCESS;
}
*/
/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::get_Value(
/* [retval][out] */ VARIANTARG __RPC_FAR *pvaData)
{
HRESULT hresReturn = ERROR_SUCCESS;
//DebugBreak();
if (pvaData == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else if (m_mdrData.pbMDData == NULL) {
//
// Data not set
//
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_DATA);
}
else {
switch (m_mdrData.dwMDDataType) {
case DWORD_METADATA:
{
if (m_mdrData.dwMDDataLen != sizeof(DWORD)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_DATA);
}
else {
pvaData->vt = VT_I4;
pvaData->lVal = *(long *) m_mdrData.pbMDData;
}
/*
m_vaData.vt = VT_I4;
m_vaData.lVal = m_dwData;
*/
}
break;
case STRING_METADATA:
case BINARY_METADATA:
case MULTISZ_METADATA:
case EXPANDSZ_METADATA:
{
SAFEARRAYBOUND sabBounds;
SAFEARRAY *psaData;
BYTE *pbData;
sabBounds.cElements = m_mdrData.dwMDDataLen;
sabBounds.lLbound = 0;
psaData = SafeArrayCreate(VT_I1, 1, &sabBounds);
if (psaData == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
hresReturn = SafeArrayAccessData(psaData, (void **)&pbData);
}
if (SUCCEEDED(hresReturn)) {
memcpy(pbData, m_mdrData.pbMDData, m_mdrData.dwMDDataLen);
pvaData->vt = VT_ARRAY | VT_UI1;
pvaData->parray = psaData;
SafeArrayUnaccessData(psaData);
}
/*
m_vaData.vt = VT_ARRAY | VT_UI1;
m_vaData.parray = m_psaData;
*/
}
break;
default:
{
hresReturn = RETURNCODETOHRESULT(MD_ERROR_NOT_INITIALIZED);
}
break;
}
/*
if (SUCCEEDED(hresReturn)) {
pvaMDData = &m_vaData;
}
*/
}
return hresReturn;
}
/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE
CMSMetaDataItem::put_Value(
/* [in] */ VARIANTARG __RPC_FAR *pvaData)
{
HRESULT hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_DATATYPE);
//DebugBreak();
/*
if ((m_mdrData.dwMDDataType <= ALL_METADATA) ||
(m_mdrData.dwMDDataType >= INVALID_END_METADATA)) {
hresReturn = RETURNCODETOHRESULT(MD_ERROR_NOT_INITIALIZED);
}
else {
if ((pvaMDData->vt & VT_ARRAY) != 0) {
SAFEARRAY *psaInput;
SAFEARRAY *psaOutput;
if ((pvaMDData->vt & VT_BYREF) != 0) {
psaInput = *(pvaMDData->pparray);
}
else {
psaInput = (pvaMDData->parray);
}
if ((SafeArrayGetDim(psaInput) == 1) &&
(SafeArrayGetElemsize(psaInput) == 1)) {
//
// byte array, good for all types except DWORD.
//
if ((m_mdrData.dwMDDataType == STRING_METADATA) ||
(m_mdrData.dwMDDataType == BINARY_METADATA) ||
(m_mdrData.dwMDDataType == MULTISZ_METADATA) ||
(m_mdrData.dwMDDataType == EXPANDSZ_METADATA)) {
hresReturn = SafeArrayCopy(psaInput, &psaOutput);
if (SUCCEEDED(hresReturn)) {
hresReturn = SafeArrayAccessData(psaOutput, (void **)&(m_mdrData.pbMDData));
if (SUCCEEDED(hresReturn)) {
SafeArrayUnaccessData(psaOutput);
if (m_psaData != NULL) {
SafeArrayDestroy(m_psaData);
}
long lLBound = 0;
long lUBound = 0;
hresReturn = SafeArrayGetLBound(psaOutput, 1, &lLBound);
hresReturn = SafeArrayGetUBound(psaOutput, 1, &lUBound);
m_mdrData.dwMDDataLen = (lUBound - lLBound) + 1;
m_psaData = psaOutput;
}
else {
SafeArrayDestroy(psaOutput);
}
}
*/
/*
SAFEARRAYBOUND sabBounds;
long lLBound = 0;
long lUBound = 0;
hresReturn = SafeArrayGetLBound(psaInput, 1, &lLBound);
hresReturn = SafeArrayGetUBound(psaInput, 1, &lUBound);
sabBounds.cElements = (lUBound - lLBound) + 1;
sabBounds.lLbound = 0;
if (m_psaData == NULL) {
m_psaData = SafeArrayCreate(VT_I1, 1, &sabBounds);
if (m_psaData == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
}
else {
hresReturn = SafeArrayRedim(m_psaData, &sabBounds);
}
void *pvInput;
void *pvOutput;
hresReturn = SafeArrayAccessData(m_psaData, &pvOutput);
hresReturn = SafeArrayAccessData(psaInput, &pvInput);
memcpy(pvOutput, pvInput, (lUBound - lLBound) + 1);
SafeArrayUnaccessData(m_psaData);
SafeArrayUnaccessData(psaInput);
*/
/*
}
}
}
else if (((pvaMDData->vt & 0xff) == VT_I4) || ((pvaMDData->vt & 0xff) == VT_UI4)) {
if (m_mdrData.dwMDDataType == DWORD_METADATA) {
if ((pvaMDData->vt & VT_BYREF) == 0) {
m_dwData = pvaMDData->ulVal;
}
else {
m_dwData = *(pvaMDData->pulVal);
}
m_mdrData.pbMDData = (BYTE *) &m_dwData;
m_mdrData.dwMDDataLen = sizeof(DWORD);
hresReturn = ERROR_SUCCESS;
}
}
else if (((pvaMDData->vt & 0xff) == VT_I2) || ((pvaMDData->vt & 0xff) == VT_UI2)) {
if (m_mdrData.dwMDDataType == DWORD_METADATA) {
if ((pvaMDData->vt & VT_BYREF) == 0) {
m_dwData = pvaMDData->uiVal;
}
else {
m_dwData = *(pvaMDData->puiVal);
}
m_mdrData.pbMDData = (BYTE *) &m_dwData;
m_mdrData.dwMDDataLen = sizeof(DWORD);
hresReturn = ERROR_SUCCESS;
}
}
}
*/
if ((m_mdrData.dwMDDataType > ALL_METADATA) &&
(m_mdrData.dwMDDataType < INVALID_END_METADATA)) {
BYTE *pbData;
DWORD dwDataLen;
if ((pvaData->vt & VT_ARRAY) != 0) {
SAFEARRAY *psaInput;
if ((pvaData->vt & VT_BYREF) != 0) {
psaInput = *(pvaData->pparray);
}
else {
psaInput = (pvaData->parray);
}
if ((SafeArrayGetDim(psaInput) == 1) &&
(SafeArrayGetElemsize(psaInput) == 1)) {
//
// byte array, good for all types except DWORD.
//
if ((m_mdrData.dwMDDataType == STRING_METADATA) ||
(m_mdrData.dwMDDataType == BINARY_METADATA) ||
(m_mdrData.dwMDDataType == MULTISZ_METADATA) ||
(m_mdrData.dwMDDataType == EXPANDSZ_METADATA)) {
hresReturn = SafeArrayAccessData(psaInput, (void **)&pbData);
if (SUCCEEDED(hresReturn)) {
long lLBound = 0;
long lUBound = 0;
hresReturn = SafeArrayGetLBound(psaInput, 1, &lLBound);
if (SUCCEEDED(hresReturn)) {
hresReturn = SafeArrayGetUBound(psaInput, 1, &lUBound);
}
if (SUCCEEDED(hresReturn)) {
DWORD i;
dwDataLen = (lUBound - lLBound) + 1;
//
// Make sure a string has a '\0'
//
if ((m_mdrData.dwMDDataType == STRING_METADATA) ||
(m_mdrData.dwMDDataType == EXPANDSZ_METADATA)) {
for (i = 0; (i < dwDataLen) && (pbData[i] != (BYTE)'\0'); i++) {
}
if (i == dwDataLen) {
HRESULT hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_DATA);
}
}
else if (m_mdrData.dwMDDataType == MULTISZ_METADATA) {
for (i = 0; (i < dwDataLen - 1); i++) {
if ((pbData[i] == '\0') && (pbData[i+1]== (BYTE)'\0')) {
break;
}
}
if (i == dwDataLen - 1) {
HRESULT hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_DATA);
}
}
if (SUCCEEDED(hresReturn)) {
if (!m_bufData.Resize(dwDataLen)) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
memcpy(m_bufData.QueryPtr(), pbData, dwDataLen);
}
}
}
SafeArrayUnaccessData(psaInput);
}
}
}
}
else if (((pvaData->vt & 0xff) == VT_I4) || ((pvaData->vt & 0xff) == VT_UI4)) {
if (m_mdrData.dwMDDataType == DWORD_METADATA) {
if ((pvaData->vt & VT_BYREF) == 0) {
*(DWORD *)(m_bufData.QueryPtr()) = pvaData->ulVal;
}
else {
*(DWORD *)(m_bufData.QueryPtr()) = *(pvaData->pulVal);
}
dwDataLen = sizeof(DWORD);
hresReturn = ERROR_SUCCESS;
}
}
else if (((pvaData->vt & 0xff) == VT_I2) || ((pvaData->vt & 0xff) == VT_UI2)) {
if (m_mdrData.dwMDDataType == DWORD_METADATA) {
if ((pvaData->vt & VT_BYREF) == 0) {
*(DWORD *)(m_bufData.QueryPtr()) = pvaData->uiVal;
}
else {
*(DWORD *)(m_bufData.QueryPtr()) = *(pvaData->puiVal);
}
dwDataLen = sizeof(DWORD);
hresReturn = ERROR_SUCCESS;
}
}
if (SUCCEEDED(hresReturn)) {
m_mdrData.pbMDData = (BYTE *)m_bufData.QueryPtr();
m_mdrData.dwMDDataLen = dwDataLen;
}
}
return hresReturn;
}
METADATA_RECORD *
CMSMetaDataItem::GetMDRecord()
{
return &m_mdrData;
}
HRESULT
CMSMetaDataItem::SetMDGetAllRecord(BYTE *pbBase, METADATA_GETALL_RECORD *pmdgarData)
{
METADATA_RECORD mdrData;
mdrData.dwMDIdentifier = pmdgarData->dwMDIdentifier;
mdrData.dwMDAttributes = pmdgarData->dwMDAttributes;
mdrData.dwMDUserType = pmdgarData->dwMDUserType;
mdrData.dwMDDataType = pmdgarData->dwMDDataType;
mdrData.dwMDDataLen = pmdgarData->dwMDDataLen;
mdrData.pbMDData = pbBase + pmdgarData->dwMDDataOffset;
return SetMDRecord(&mdrData);
}
HRESULT
CMSMetaDataItem::SetMDRecord(METADATA_RECORD *pmdrData)
{
HRESULT hresReturn = ERROR_SUCCESS;
if (!m_bufData.Resize(pmdrData->dwMDDataLen)) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
m_mdrData = *pmdrData;
memcpy(m_bufData.QueryPtr(), m_mdrData.pbMDData, m_mdrData.dwMDDataLen);
m_mdrData.pbMDData = (BYTE *)m_bufData.QueryPtr();
}
/*
if (m_mdrData.dwMDDataType == DWORD_METADATA) {
m_dwData = *(DWORD *)m_mdrData.pbMDData;
m_mdrData.pbMDData = (BYTE *)&m_dwData;
}
else {
SAFEARRAY *psaNew;
SAFEARRAYBOUND sabBounds;
sabBounds.cElements = m_mdrData.dwMDDataLen;
sabBounds.lLbound = 0;
psaNew = SafeArrayCreate(VT_I1, 1, &sabBounds);
if (psaNew == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
hresReturn = SafeArrayAccessData(psaNew, (void **)&(m_mdrData.pbMDData));
if (SUCCEEDED(hresReturn)) {
if (m_psaData != NULL) {
SafeArrayUnaccessData(m_psaData);
SafeArrayDestroy(m_psaData);
}
memcpy(m_mdrData.pbMDData, pmdrData->pbMDData, m_mdrData.dwMDDataLen);
m_psaData = psaNew;
}
else {
SafeArrayDestroy(psaNew);
}
}
}
*/
return hresReturn;
}
HRESULT _stdcall
CMSMetaDataItem::QueryInterface(REFIID riid, void **ppObject)
{
if (riid==IID_IUnknown || riid==IID_IMSMetaDataItem || riid==IID_IDispatch) {
*ppObject = (IMSMetaDataItem *) this;
AddRef();
}
else {
return E_NOINTERFACE;
}
return NO_ERROR;
}
ULONG _stdcall
CMSMetaDataItem::AddRef()
{
DWORD dwRefCount;
dwRefCount = InterlockedIncrement((long *)&m_dwRefCount);
return dwRefCount;
}
ULONG _stdcall
CMSMetaDataItem::Release()
{
DWORD dwRefCount;
dwRefCount = InterlockedDecrement((long *)&m_dwRefCount);
if (dwRefCount == 0) {
delete (this);
}
return dwRefCount;
}
//IDispatch members
//IDispatch functions, now part of CMDCOM
/*
* CMDCOM::GetTypeInfoCount
*
* Purpose:
* Returns the number of type information (ITypeInfo) interfaces
* that the object provides (0 or 1).
*
* Parameters:
* pctInfo UINT * to the location to receive
* the count of interfaces.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaDataItem::GetTypeInfoCount(UINT *pctInfo)
{
//We implement GetTypeInfo so return 1
*pctInfo=1;
return NOERROR;
}
/*
* CMDCOM::GetTypeInfo
*
* Purpose:
* Retrieves type information for the automation interface. This
* is used anywhere that the right ITypeInfo interface is needed
* for whatever LCID is applicable. Specifically, this is used
* from within GetIDsOfNames and Invoke.
*
* Parameters:
* itInfo UINT reserved. Must be zero.
* lcid LCID providing the locale for the type
* information. If the object does not support
* localization, this is ignored.
* ppITypeInfo ITypeInfo ** in which to store the ITypeInfo
* interface for the object.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaDataItem::GetTypeInfo(UINT itInfo, LCID lcid
, ITypeInfo **ppITypeInfo)
{
HRESULT hr;
ITypeLib *pITypeLib;
ITypeInfo **ppITI=NULL;
if (0!=itInfo)
return ResultFromScode(TYPE_E_ELEMENTNOTFOUND);
if (NULL==ppITypeInfo)
return ResultFromScode(E_POINTER);
m_pITIData->AddRef();
*ppITypeInfo = m_pITIData;
return NOERROR;
}
/*
* CMDCOM::GetIDsOfNames
*
* Purpose:
* Converts text names into DISPIDs to pass to Invoke
*
* Parameters:
* riid REFIID reserved. Must be IID_NULL.
* rgszNames OLECHAR ** pointing to the array of names to be
* mapped.
* cNames UINT number of names to be mapped.
* lcid LCID of the locale.
* rgDispID DISPID * caller allocated array containing IDs
* corresponging to those names in rgszNames.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaDataItem::GetIDsOfNames(REFIID riid
, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
{
HRESULT hr;
ITypeInfo *pTI;
if (IID_NULL!=riid)
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
//Get the right ITypeInfo for lcid.
hr=GetTypeInfo(0, lcid, &pTI);
if (SUCCEEDED(hr))
{
hr=DispGetIDsOfNames(pTI, rgszNames, cNames, rgDispID);
pTI->Release();
}
return hr;
}
/*
* CMDCOM::Invoke
*
* Purpose:
* Calls a method in the dispatch interface or manipulates a
* property.
*
* Parameters:
* dispID DISPID of the method or property of interest.
* riid REFIID reserved, must be IID_NULL.
* lcid LCID of the locale.
* wFlags USHORT describing the context of the invocation.
* pDispParams DISPPARAMS * to the array of arguments.
* pVarResult VARIANT * in which to store the result. Is
* NULL if the caller is not interested.
* pExcepInfo EXCEPINFO * to exception information.
* puArgErr UINT * in which to store the index of an
* invalid parameter if DISP_E_TYPEMISMATCH
* is returned.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP
CMSMetaDataItem::Invoke(DISPID dispID, REFIID riid
, LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams
, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
HRESULT hr;
//riid is supposed to be IID_NULL always
if (IID_NULL!=riid)
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
//Clear exceptions
SetErrorInfo(0L, NULL);
//This is exactly what DispInvoke does--so skip the overhead.
// hr=pTI->Invoke((IADMCOM *)this, dispID, wFlags
// , pDispParams, pVarResult, pExcepInfo, puArgErr);
hr=DispInvoke((IMSMetaDataItem *)this, m_pITIData, dispID, wFlags
, pDispParams, pVarResult, pExcepInfo, puArgErr);
//Exception handling is done within ITypeInfo::Invoke
return hr;
}
/*
* RaiseException
*
* Parameters:
* nID Error number
* rguid GUID of interface that is raising the exception.
*
* Return Value:
* HRESULT correspnding to the nID error number.
*
* Purpose:
* Fills the EXCEPINFO structure.
* Sets ErrorInfo object for vtable-binding controllers.
* For id-binding and late binding controllers DispInvoke
* will return DISP_E_EXCEPTION and fill the EXCEPINFO parameter
* with the error information set by SetErrorInfo.
*
*/
/*
HRESULT RaiseException(int nID, REFGUID rguid)
{
extern SCODE g_scodes[];
// TCHAR szError[STR_LEN];
ICreateErrorInfo *pcerrinfo;
IErrorInfo *perrinfo;
HRESULT hr;
BSTR bstrDescription = NULL;
// if (LoadString(g_pApplication->m_hinst, nID, szError, sizeof(szError)))
// bstrDescription = SysAllocString(TO_OLE_STRING(szError));
// Set ErrorInfo object so that vtable binding controller can get
// rich error information. If the controller is using IDispatch
// to access properties or methods, DispInvoke will fill the
// EXCEPINFO structure using the values specified in the ErrorInfo
// object and DispInvoke will return DISP_E_EXCEPTION. The property
// or method must return a failure SCODE for DispInvoke to do this.
hr = CreateErrorInfo(&pcerrinfo);
if (SUCCEEDED(hr))
{
pcerrinfo->SetGUID(rguid);
// pcerrinfo->SetSource(g_pApplication->m_bstrProgID);
pcerrinfo->SetSource(NULL);
if (bstrDescription)
pcerrinfo->SetDescription(bstrDescription);
hr = pcerrinfo->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &perrinfo);
if (SUCCEEDED(hr))
{
SetErrorInfo(0, perrinfo);
perrinfo->Release();
}
pcerrinfo->Release();
}
if (bstrDescription)
SysFreeString(bstrDescription);
return ResultFromScode(nID);
}
*/
HRESULT
GetVariantDword(VARIANTARG *pvaData, DWORD &rdwData, DWORD dwDefault)
{
HRESULT hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
rdwData = dwDefault;
if ((pvaData == NULL) || (pvaData->vt == VT_ERROR)) {
//
// if optional path is not specified
// type comes in as VT_ERROR
//
hresReturn = ERROR_SUCCESS;
}
else {
hresReturn = VariantChangeType(pvaData,
pvaData,
0,
VT_UI4);
if (SUCCEEDED(hresReturn)) {
rdwData = pvaData->ulVal;
}
}
return hresReturn;
}
HRESULT
GetVariantString(VARIANTARG *pvaPath, BYTE *&rpszPath)
{
HRESULT hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
rpszPath = NULL;
if ((pvaPath == NULL) || (pvaPath->vt == VT_ERROR)) {
//
// if optional path is not specified
// type comes in as VT_ERROR
//
hresReturn = ERROR_SUCCESS;
}
else if ((pvaPath->vt & VT_ARRAY) != 0) {
SAFEARRAY *psaPath;
if ((pvaPath->vt & VT_BYREF) != 0) {
psaPath = *(pvaPath->pparray);
}
else {
psaPath = (pvaPath->parray);
}
if ((SafeArrayGetDim(psaPath) == 1) &&
(SafeArrayGetElemsize(psaPath) == 1)) {
hresReturn = SafeArrayAccessData(psaPath, (void **) &rpszPath);
if (SUCCEEDED(hresReturn)) {
SafeArrayUnaccessData(psaPath);
}
}
}
return hresReturn;
}
HRESULT
SetVariantString(VARIANTARG *pvaString, BYTE *pszString)
{
HRESULT hresReturn = ERROR_SUCCESS;
SAFEARRAYBOUND sabBounds;
SAFEARRAY *psaString;
BYTE *pbString;
DWORD dwStringLen = strlen((LPSTR)pszString) + 1;
sabBounds.cElements = dwStringLen;
sabBounds.lLbound = 0;
psaString = SafeArrayCreate(VT_I1, 1, &sabBounds);
if (psaString == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
hresReturn = SafeArrayAccessData(psaString, (void **)&pbString);
}
if (SUCCEEDED(hresReturn)) {
memcpy(pbString, pszString, dwStringLen);
pvaString->vt = VT_ARRAY | VT_UI1;
pvaString->parray = psaString;
SafeArrayUnaccessData(psaString);
}
return hresReturn;
}