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