windows-nt/Source/XPSP1/NT/net/ias/mmc/proxy/sdowrap.cpp

1177 lines
25 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, Microsoft Corp. All rights reserved.
//
// FILE
//
// sdowrap.cpp
//
// SYNOPSIS
//
// Defines various wrapper classes for manipulating SDOs.
//
// MODIFICATION HISTORY
//
// 02/10/2000 Original version.
// 04/19/2000 Support for using wrappers across apartment boundaries.
//
///////////////////////////////////////////////////////////////////////////////
#include <proxypch.h>
#include <sdowrap.h>
#include <condlist.h>
VOID
WINAPI
SdoTrimBSTR(
CComBSTR& bstr
)
{
// Characters to be trimmed.
static const WCHAR delim[] = L" \t\n";
if (bstr.m_str)
{
PCWSTR begin, end, first, last;
// Find the beginning and end of the whole string.
begin = bstr;
end = begin + wcslen(begin);
// Find the first and last character of the trimmed string.
first = begin + wcsspn(begin, delim);
for (last = end; last > first && wcschr(delim, *(last - 1)); --last) { }
// If they're not the same ...
if (first != begin || last != end)
{
// ... then we have to allocate a new string ...
BSTR newBstr = SysAllocStringLen(first, last - first);
if (!newBstr) { AfxThrowOleException(E_OUTOFMEMORY); }
// ... and replace the original.
SysFreeString(bstr.m_str);
bstr.m_str = newBstr;
}
}
}
BOOL SdoException::GetErrorMessage(
LPWSTR lpszError,
UINT nMaxError,
PUINT pnHelpContext
)
{
UINT id;
switch (type)
{
case CONNECT_ERROR:
id = IDS_PROXY_E_SDO_CONNECT;
break;
case READ_ERROR:
id = IDS_PROXY_E_SDO_READ;
break;
default:
id = IDS_PROXY_E_SDO_WRITE;
}
return LoadStringW(
AfxGetResourceHandle(),
id,
lpszError,
nMaxError
);
}
inline SdoException::SdoException(HRESULT hr, Type errorType) throw ()
: type(errorType)
{
m_sc = hr;
}
VOID
WINAPI
SdoThrowException(
HRESULT hr,
SdoException::Type errorType
)
{
throw new SdoException(hr, errorType);
}
// Extract an interface pointer from a VARIANT.
void ExtractInterface(const VARIANT& v, REFIID iid, PVOID* intfc)
{
if (V_VT(&v) != VT_UNKNOWN && V_VT(&v) != VT_DISPATCH)
{
AfxThrowOleException(DISP_E_TYPEMISMATCH);
}
if (!V_UNKNOWN(&v))
{
AfxThrowOleException(E_POINTER);
}
CheckError(V_UNKNOWN(&v)->QueryInterface(iid, intfc));
}
Sdo::Sdo(IUnknown* unk)
{
if (unk)
{
CheckError(unk->QueryInterface(__uuidof(ISdo), (PVOID*)&self));
}
}
bool Sdo::setName(BSTR value)
{
if (!self) { AfxThrowOleException(E_POINTER); }
bool retval;
VARIANT v;
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = value;
HRESULT hr = self->PutProperty(PROPERTY_SDO_NAME, &v);
if (SUCCEEDED(hr))
{
retval = true;
}
else if (hr == E_INVALIDARG && value && value[0])
{
retval = false;
}
else
{
AfxThrowOleException(hr);
}
return retval;
}
void Sdo::clearValue(LONG id)
{
if (!self) { AfxThrowOleException(E_POINTER); }
VARIANT v;
V_VT(&v) = VT_EMPTY;
HRESULT hr = self->PutProperty(id, &v);
if (FAILED(hr) && hr != DISP_E_MEMBERNOTFOUND)
{
AfxThrowOleException(hr);
}
}
void Sdo::getValue(LONG id, bool& value) const
{
VARIANT v;
getValue(id, VT_BOOL, &v, true);
value = (V_BOOL(&v) != 0);
}
void Sdo::getValue(LONG id, bool& value, bool defVal) const
{
VARIANT v;
if (getValue(id, VT_BOOL, &v, false))
{
value = (V_BOOL(&v) != 0);
}
else
{
value = defVal;
}
}
void Sdo::getValue(LONG id, LONG& value) const
{
VARIANT v;
getValue(id, VT_I4, &v, true);
value = V_UI4(&v);
}
void Sdo::getValue(LONG id, LONG& value, LONG defVal) const
{
VARIANT v;
if (getValue(id, VT_I4, &v, false))
{
value = V_UI4(&v);
}
else
{
value = defVal;
}
}
void Sdo::getValue(LONG id, CComBSTR& value) const
{
VARIANT v;
getValue(id, VT_BSTR, &v, true);
SysFreeString(value.m_str);
value.m_str = V_BSTR(&v);
}
void Sdo::getValue(LONG id, CComBSTR& value, PCWSTR defVal) const
{
VARIANT v;
if (getValue(id, VT_BSTR, &v, false))
{
SysFreeString(value.m_str);
value.m_str = V_BSTR(&v);
}
else
{
value = defVal;
if (defVal && !value) { AfxThrowOleException(E_OUTOFMEMORY); }
}
}
void Sdo::getValue(LONG id, VARIANT& value) const
{
if (!self) { AfxThrowOleException(E_POINTER); }
VariantClear(&value);
CheckError(self->GetProperty(id, &value));
}
void Sdo::getValue(LONG id, SdoCollection& value) const
{
if (!self) { AfxThrowOleException(E_POINTER); }
CComVariant v;
HRESULT hr = self->GetProperty(id, &v);
if (FAILED(hr))
{
switch (hr)
{
case DISP_E_MEMBERNOTFOUND:
case E_OUTOFMEMORY:
AfxThrowOleException(hr);
default:
SdoThrowException(hr, SdoException::READ_ERROR);
}
}
CComPtr<ISdoCollection> obj;
ExtractInterface(v, __uuidof(ISdoCollection), (PVOID*)&obj);
value = obj;
}
void Sdo::setValue(LONG id, bool value)
{
VARIANT v;
V_VT(&v) = VT_BOOL;
V_BOOL(&v) = value ? VARIANT_TRUE : VARIANT_FALSE;
setValue(id, v);
}
void Sdo::setValue(LONG id, LONG value)
{
VARIANT v;
V_VT(&v) = VT_I4;
V_I4(&v) = value;
setValue(id, v);
}
void Sdo::setValue(LONG id, BSTR value)
{
VARIANT v;
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = value;
setValue(id, v);
}
void Sdo::setValue(LONG id, const VARIANT& val)
{
if (!self) { AfxThrowOleException(E_POINTER); }
CheckError(self->PutProperty(id, const_cast<VARIANT*>(&val)));
}
void Sdo::apply()
{
if (!self) { AfxThrowOleException(E_POINTER); }
HRESULT hr = self->Apply();
if (FAILED(hr))
{
switch (hr)
{
case E_OUTOFMEMORY:
AfxThrowOleException(hr);
default:
SdoThrowException(hr, SdoException::WRITE_ERROR);
}
}
}
void Sdo::restore()
{
if (!self) { AfxThrowOleException(E_POINTER); }
CheckError(self->Restore());
}
bool Sdo::getValue(LONG id, VARTYPE vt, VARIANT* val, bool mandatory) const
{
if (!self) { AfxThrowOleException(E_POINTER); }
V_VT(val) = VT_EMPTY;
HRESULT hr = self->GetProperty(id, val);
if (SUCCEEDED(hr))
{
if (V_VT(val) == VT_EMPTY)
{
if (mandatory)
{
AfxThrowOleException(DISP_E_MEMBERNOTFOUND);
}
}
else if (V_VT(val) != vt)
{
VariantClear(val);
AfxThrowOleException(DISP_E_TYPEMISMATCH);
}
else
{
return true;
}
}
else if (hr == DISP_E_MEMBERNOTFOUND)
{
if (mandatory)
{
AfxThrowOleException(DISP_E_MEMBERNOTFOUND);
}
}
else
{
AfxThrowOleException(hr);
}
return false;
}
SdoEnum::SdoEnum(IUnknown* unk)
{
if (unk)
{
CheckError(unk->QueryInterface(__uuidof(IEnumVARIANT), (PVOID*)&self));
}
}
bool SdoEnum::next(Sdo& s)
{
if (!self) { AfxThrowOleException(E_POINTER); }
CComVariant element;
ULONG fetched;
HRESULT hr = self->Next(1, &element, &fetched);
if (hr == S_OK && fetched)
{
CComPtr<ISdo> obj;
ExtractInterface(element, __uuidof(ISdo), (PVOID*)&obj);
s = obj;
return true;
}
CheckError(hr);
return false;
}
void SdoEnum::reset()
{
if (!self) { AfxThrowOleException(E_POINTER); }
CheckError(self->Reset());
}
SdoCollection::SdoCollection(IUnknown* unk)
{
if (unk)
{
CheckError(unk->QueryInterface(__uuidof(ISdoCollection), (PVOID*)&self));
}
}
void SdoCollection::add(ISdo* sdo)
{
if (!self) { AfxThrowOleException(E_POINTER); }
// We must hold a reference across the call to Add since the interface
// pointer passed to Add is an [in, out] parameter.
CComPtr<IDispatch> disp(sdo);
CheckError(self->Add(NULL, &disp));
}
LONG SdoCollection::count() throw ()
{
if (!self) { AfxThrowOleException(E_POINTER); }
LONG retval;
CheckError(self->get_Count(&retval));
return retval;
}
Sdo SdoCollection::create(BSTR name)
{
if (!self) { AfxThrowOleException(E_POINTER); }
CComBSTR tmp;
// If no name is specified, we'll make use a GUID.
if (!name)
{
// Create the GUID.
UUID uuid;
UuidCreate(&uuid);
// Convert to a string.
WCHAR buffer[40];
StringFromGUID2(uuid, buffer, sizeof(buffer)/sizeof(buffer[0]));
// Convert the string to a BSTR.
name = tmp = buffer;
if (!name) { AfxThrowOleException(E_OUTOFMEMORY); }
}
CComPtr<IDispatch> disp;
CheckError(self->Add(name, &disp));
return Sdo(disp);
}
Sdo SdoCollection::find(BSTR name)
{
if (!self) { AfxThrowOleException(E_POINTER); }
VARIANT v;
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = name;
CComPtr<IDispatch> disp;
HRESULT hr = self->Item(&v, &disp);
if (FAILED(hr) && hr != DISP_E_MEMBERNOTFOUND)
{
AfxThrowOleException(hr);
}
return Sdo(disp);
}
SdoEnum SdoCollection::getNewEnum()
{
if (!self) { AfxThrowOleException(E_POINTER); }
CComPtr<IUnknown> unk;
CheckError(self->get__NewEnum(&unk));
return SdoEnum(unk);
}
bool SdoCollection::isNameUnique(BSTR name)
{
if (!self) { AfxThrowOleException(E_POINTER); }
VARIANT_BOOL retval;
CheckError(self->IsNameUnique(name, &retval));
return retval != 0;
}
void SdoCollection::reload()
{
if (self)
{
HRESULT hr = self->Reload();
if (FAILED(hr))
{
switch (hr)
{
case DISP_E_MEMBERNOTFOUND:
case E_OUTOFMEMORY:
AfxThrowOleException(hr);
default:
SdoThrowException(hr, SdoException::READ_ERROR);
}
}
}
}
void SdoCollection::remove(ISdo* sdo)
{
if (!self) { AfxThrowOleException(E_POINTER); }
HRESULT hr = self->Remove(sdo);
if (FAILED(hr))
{
switch (hr)
{
case DISP_E_MEMBERNOTFOUND:
case E_OUTOFMEMORY:
AfxThrowOleException(hr);
default:
SdoThrowException(hr, SdoException::WRITE_ERROR);
}
}
}
void SdoCollection::removeAll()
{
if (!self) { AfxThrowOleException(E_POINTER); }
HRESULT hr = self->RemoveAll();
if (FAILED(hr))
{
switch (hr)
{
case E_OUTOFMEMORY:
AfxThrowOleException(hr);
default:
SdoThrowException(hr, SdoException::WRITE_ERROR);
}
}
}
SdoDictionary::SdoDictionary(IUnknown* unk)
{
if (unk)
{
CheckError(unk->QueryInterface(
__uuidof(ISdoDictionaryOld),
(PVOID*)&self
));
}
}
Sdo SdoDictionary::createAttribute(ATTRIBUTEID id) const
{
if (!self) { AfxThrowOleException(E_POINTER); }
CComPtr<IDispatch> disp;
CheckError(self->CreateAttribute(id, &disp));
return Sdo(disp);
}
ULONG SdoDictionary::enumAttributeValues(ATTRIBUTEID attrId, IdName*& values)
{
if (!self) { AfxThrowOleException(E_POINTER); }
// Get the variant arrays.
CComVariant v1, v2;
CheckError(self->EnumAttributeValues(attrId, &v1, &v2));
// Allocate memory for the 'friendly' array.
ULONG nelem = V_ARRAY(&v1)->rgsabound[0].cElements;
IdName* vals = new (AfxThrow) IdName[nelem];
// Get the raw data.
VARIANT* id = (VARIANT*)V_ARRAY(&v1)->pvData;
VARIANT* name = (VARIANT*)V_ARRAY(&v2)->pvData;
// Copy the variant data into the friendly array.
for (ULONG i = 0; i < nelem; ++i, ++id, ++name)
{
vals[i].id = V_I4(id);
vals[i].name = V_BSTR(name);
if (!vals[i].name)
{
delete[] vals;
AfxThrowOleException(E_OUTOFMEMORY);
}
}
values = vals;
return nelem;
}
SdoMachine::SdoMachine(IUnknown* unk)
{
if (unk)
{
CheckError(unk->QueryInterface(__uuidof(ISdoMachine), (PVOID*)&self));
}
}
void SdoMachine::attach(BSTR machineName)
{
if (!self) { create(); }
if (machineName && !machineName[0]) { machineName = NULL; }
HRESULT hr = self->Attach(machineName);
if (FAILED(hr))
{
switch (hr)
{
case E_OUTOFMEMORY:
AfxThrowOleException(hr);
default:
SdoThrowException(hr, SdoException::CONNECT_ERROR);
}
}
}
void SdoMachine::create()
{
self.Release();
CheckError(CoCreateInstance(
__uuidof(SdoMachine),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ISdoMachine),
(PVOID*)&self
));
}
Sdo SdoMachine::getIAS()
{
if (!self) { AfxThrowOleException(E_POINTER); }
// Get the service SDO.
CComPtr<IUnknown> unk;
CComBSTR serviceName(L"IAS");
if (!serviceName) { AfxThrowOleException(E_OUTOFMEMORY); }
HRESULT hr = self->GetServiceSDO(
DATA_STORE_LOCAL,
serviceName,
&unk
);
if (FAILED(hr))
{
switch (hr)
{
case E_OUTOFMEMORY:
AfxThrowOleException(hr);
default:
SdoThrowException(hr, SdoException::CONNECT_ERROR);
}
}
return Sdo(unk);
}
SdoDictionary SdoMachine::getDictionary()
{
if (!self) { AfxThrowOleException(E_POINTER); }
// Get the dictionary SDO.
CComPtr<IUnknown> unk;
HRESULT hr = self->GetDictionarySDO(&unk);
if (FAILED(hr))
{
switch (hr)
{
case E_OUTOFMEMORY:
AfxThrowOleException(hr);
default:
SdoThrowException(hr, SdoException::CONNECT_ERROR);
}
}
return SdoDictionary(unk);
}
void SdoConsumer::propertyChanged(SnapInView& view, IASPROPERTIES id)
{ }
bool SdoConsumer::queryRefresh(SnapInView& view)
{ return true; }
void SdoConsumer::refreshComplete(SnapInView& view)
{ }
SdoConnection::SdoConnection() throw ()
: dictionary(0),
service(0),
control(0),
attrList(NULL)
{ }
SdoConnection::~SdoConnection() throw ()
{
executeInMTA(mtaDisconnect);
}
void SdoConnection::advise(SdoConsumer& obj)
{
consumers.Add(&obj);
}
void SdoConnection::unadvise(SdoConsumer& obj)
{
for (int i = 0; i < consumers.GetSize(); ++i)
{
if (consumers[i] == &obj)
{
consumers.RemoveAt(i);
break;
}
}
}
SdoDictionary SdoConnection::getDictionary()
{
if (!dictionary) { AfxThrowOleException(E_POINTER); }
CComPtr<ISdoDictionaryOld> obj;
CheckError(git->GetInterfaceFromGlobal(
dictionary,
__uuidof(ISdoDictionaryOld),
(PVOID*)&obj
));
return SdoDictionary(obj);
}
SdoCollection SdoConnection::getProxyPolicies()
{
SdoCollection retval;
getService().getValue(
PROPERTY_IAS_PROXYPOLICIES_COLLECTION,
retval
);
return retval;
}
SdoCollection SdoConnection::getProxyProfiles()
{
SdoCollection retval;
getService().getValue(
PROPERTY_IAS_PROXYPROFILES_COLLECTION,
retval
);
return retval;
}
SdoCollection SdoConnection::getServerGroups()
{
SdoCollection retval;
getService().getValue(
PROPERTY_IAS_RADIUSSERVERGROUPS_COLLECTION,
retval
);
return retval;
}
void SdoConnection::connect(PCWSTR computerName)
{
if (machine) { AfxThrowOleException(E_UNEXPECTED); }
machineName = computerName;
if (computerName && !machineName)
{
AfxThrowOleException(E_OUTOFMEMORY);
}
executeInMTA(mtaConnect);
}
void SdoConnection::propertyChanged(SnapInView& view, IASPROPERTIES id)
{
for (int i = 0; i < consumers.GetSize(); ++i)
{
((SdoConsumer*)consumers[i])->propertyChanged(view, id);
}
}
bool SdoConnection::refresh(SnapInView& view)
{
int i;
// Make sure the refresh is okay.
for (i = 0; i < consumers.GetSize(); ++i)
{
if (!((SdoConsumer*)consumers[i])->queryRefresh(view))
{
return false;
}
}
// Get a new connection.
executeInMTA(mtaRefresh);
// Let the consumers know we've refreshed.
for (i = 0; i < consumers.GetSize(); ++i)
{
((SdoConsumer*)consumers[i])->refreshComplete(view);
}
return true;
}
void SdoConnection::resetService()
{
if (!control) { AfxThrowOleException(E_POINTER); }
CComPtr<ISdoServiceControl> obj;
CheckError(git->GetInterfaceFromGlobal(
control,
__uuidof(ISdoServiceControl),
(PVOID*)&obj
));
// We ignore the error code since the SDOs return an error when the service
// isn't running.
obj->ResetService();
}
CIASAttrList* SdoConnection::getCIASAttrList()
{
if (!attrList)
{
attrList = CreateCIASAttrList();
if (!attrList) { AfxThrowOleException(E_OUTOFMEMORY); }
}
return attrList;
}
Sdo SdoConnection::getService()
{
if (!service) { AfxThrowOleException(E_POINTER); }
CComPtr<ISdo> obj;
CheckError(git->GetInterfaceFromGlobal(
service,
__uuidof(ISdo),
(PVOID*)&obj
));
return Sdo(obj);
}
void SdoConnection::mtaConnect()
{
// Get the GIT.
CheckError(CoCreateInstance(
CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IGlobalInterfaceTable),
(PVOID*)&git
));
// Attach to the machine.
machine.attach(machineName);
// Get the dictionary SDO.
CheckError(git->RegisterInterfaceInGlobal(
machine.getDictionary(),
__uuidof(ISdoDictionaryOld),
&dictionary
));
// Get the service SDO.
Sdo serviceSdo = machine.getIAS();
CheckError(git->RegisterInterfaceInGlobal(
serviceSdo,
__uuidof(ISdo),
&service
));
// Get the control SDO.
CComPtr<ISdoServiceControl> controlSdo;
CheckError(serviceSdo.self->QueryInterface(
__uuidof(ISdoServiceControl),
(PVOID*)&controlSdo
));
CheckError(git->RegisterInterfaceInGlobal(
controlSdo,
__uuidof(ISdoServiceControl),
&control
));
}
void SdoConnection::mtaDisconnect()
{
// Revoke all the GIT cookies.
if (git)
{
if (dictionary) { git->RevokeInterfaceFromGlobal(dictionary); }
if (service) { git->RevokeInterfaceFromGlobal(service); }
if (control) { git->RevokeInterfaceFromGlobal(control); }
git.Release();
}
DestroyCIASAttrList(attrList);
// Drop the connection.
machine.release();
}
void SdoConnection::mtaRefresh()
{
// Revoke the old connection.
if (service)
{
git->RevokeInterfaceFromGlobal(service);
service = 0;
}
// Get a new connection.
CheckError(git->RegisterInterfaceInGlobal(
machine.getIAS(),
__uuidof(ISdo),
&service
));
}
namespace
{
// Struct to store the data for an MTA action.
struct ActionData
{
SdoConnection* cxn;
SdoConnection::Action action;
};
};
void SdoConnection::executeInMTA(Action action)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
// We're already in the MTA, so execute in place.
(this->*action)();
CoUninitialize();
}
else
{
// Save the action data.
ActionData data = { this, action };
// Create a thread to perform the action.
HANDLE thread = CreateThread(
NULL,
0,
actionRoutine,
&data,
0,
NULL
);
// Wait for the thread to exit and retrieve the exit code.
DWORD exitCode;
if (!thread ||
WaitForSingleObject(thread, INFINITE) == WAIT_FAILED ||
!GetExitCodeThread(thread, &exitCode))
{
exitCode = GetLastError();
hr = HRESULT_FROM_WIN32(exitCode);
}
else
{
hr = (HRESULT)exitCode;
}
CloseHandle(thread);
CheckError(hr);
}
}
DWORD WINAPI SdoConnection::actionRoutine(PVOID parameter) throw ()
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
ActionData* data = (ActionData*)parameter;
try
{
((data->cxn)->*(data->action))();
hr = S_OK;
}
catch (CException* e)
{
hr = COleException::Process(e);
e->Delete();
}
CoUninitialize();
}
return (DWORD)hr;
}
SdoProfile::SdoProfile(SdoConnection& connection)
: cxn(connection)
{
}
SdoProfile::SdoProfile(SdoConnection& connection, Sdo& profile)
: cxn(connection)
{
operator=(profile);
}
SdoProfile& SdoProfile::operator=(Sdo& profile)
{
if (!profile) { AfxThrowOleException(E_POINTER); }
// Get the new attributes collection.
SdoCollection newSelf;
profile.getValue(PROPERTY_PROFILE_ATTRIBUTES_COLLECTION, newSelf);
return operator=(newSelf);
}
SdoProfile& SdoProfile::operator=(ISdoCollection* p)
{
if (!p) { AfxThrowOleException(E_POINTER); }
SdoCollection newSelf(p);
// Create a temporary vector to hold the attributes.
SdoVector newAttrs;
newAttrs.reserve(newSelf.count());
// Get the attributes.
Sdo attr;
SdoEnum sdoEnum(newSelf.getNewEnum());
while (sdoEnum.next(attr))
{
newAttrs.push_back(attr);
}
// Store the results.
attrs.swap(newAttrs);
self = newSelf;
return *this;
}
void SdoProfile::clear()
{
self.removeAll();
attrs.clear();
}
Sdo SdoProfile::find(ATTRIBUTEID id) const
{
return getExisting(id);
}
void SdoProfile::clearValue(ATTRIBUTEID id)
{
ISdo* sdo = getExisting(id);
if (sdo)
{
self.remove(sdo);
attrs.erase(sdo);
}
}
bool SdoProfile::getValue(ATTRIBUTEID id, bool& value) const
{
Sdo sdo(getExisting(id));
return sdo ? sdo.getValue(PROPERTY_ATTRIBUTE_VALUE, value), true : false;
}
bool SdoProfile::getValue(ATTRIBUTEID id, LONG& value) const
{
Sdo sdo(getExisting(id));
return sdo ? sdo.getValue(PROPERTY_ATTRIBUTE_VALUE, value), true : false;
}
bool SdoProfile::getValue(ATTRIBUTEID id, CComBSTR& value) const
{
Sdo sdo(getExisting(id));
return sdo ? sdo.getValue(PROPERTY_ATTRIBUTE_VALUE, value), true : false;
}
bool SdoProfile::getValue(ATTRIBUTEID id, VARIANT& value) const
{
Sdo sdo(getExisting(id));
return sdo ? sdo.getValue(PROPERTY_ATTRIBUTE_VALUE, value), true : false;
}
void SdoProfile::setValue(ATTRIBUTEID id, bool value)
{
Sdo(getAlways(id)).setValue(PROPERTY_ATTRIBUTE_VALUE, value);
}
void SdoProfile::setValue(ATTRIBUTEID id, LONG value)
{
Sdo(getAlways(id)).setValue(PROPERTY_ATTRIBUTE_VALUE, value);
}
void SdoProfile::setValue(ATTRIBUTEID id, BSTR value)
{
Sdo(getAlways(id)).setValue(PROPERTY_ATTRIBUTE_VALUE, value);
}
void SdoProfile::setValue(ATTRIBUTEID id, const VARIANT& val)
{
Sdo(getAlways(id)).setValue(PROPERTY_ATTRIBUTE_VALUE, val);
}
ISdo* SdoProfile::getAlways(ATTRIBUTEID id)
{
// Does it already exist ?
ISdo* sdo = getExisting(id);
if (sdo) { return sdo; }
// No, so create a new one
Sdo attr = cxn.getDictionary().createAttribute(id);
self.add(attr);
attrs.push_back(attr);
return attr;
}
ISdo* SdoProfile::getExisting(ATTRIBUTEID key) const
{
// Iterate through the attributes.
for (SdoVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
{
// Get the attribute ID.
LONG id;
Sdo(*i).getValue(PROPERTY_ATTRIBUTE_ID, id);
// Does it match the key ?
if (id == key) { return *i; }
}
return NULL;
}
void InterfaceStream::marshal(REFIID riid, LPUNKNOWN pUnk)
{
// Create the new stream.
CComPtr<IStream> newStream;
CheckError(CoMarshalInterThreadInterfaceInStream(
riid,
pUnk,
&newStream
));
// Release the old one if any.
if (stream) { stream->Release(); }
// Save the new one.
stream = newStream.p;
newStream.p = NULL;
}
void InterfaceStream::get(REFIID riid, LPVOID* ppv)
{
// Unmarshall the interface.
HRESULT hr = CoGetInterfaceAndReleaseStream(
stream,
riid,
ppv
);
// The stream can only be used once even if the above fails.
stream = NULL;
// Check the result of CoGetInterfaceAndReleaseStream.
CheckError(hr);
}