2025-11-28 00:35:46 +09:00

407 lines
14 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "stdafx.h"
#include "Adminwrap.h"
#include <comadmin.h>
#include <assert.h>
#define if_failed_exit(HR) do { if FAILED(HR) goto exit; } while (false)
#define exit_with_result(HR) do { hr = HR; goto exit; } while (false)
//*********************************************
// Globals
CComBSTR g_bstrPublisherID(L"PublisherID");
CComBSTR g_bstrName(L"Name");
CComBSTR g_bstrValue(L"Value");
CComBSTR g_bstrID(L"ID");
CComBSTR g_bstrEventCLSID(L"EventCLSID");
CComBSTR g_bstrInterfaceID(L"InterfaceID");
CComBSTR g_bstrMethodName(L"MethodName");
CComBSTR g_bstrFilterCriteria(L"FilterCriteria");
CComBSTR g_bstrTransientSubscriptions(L"TransientSubscriptions");
CComBSTR g_bstrSubscriberInterface(L"SubscriberInterface");
CComBSTR g_bstrTransientPublisherProperties(L"TransientPublisherProperties");
CComBSTR g_bstrTransientSubscriberProperties(L"TransientSubscriberProperties");
///////////////////////////////////////////////////////////////////////////////////////////////////
// Name : AddTransientSubscription
// Purpose : Adds a Transient Subscription
// Parameters :
// : ICOMAdminCatalog* pCatalog - COM+ admin catalog object
// : LPCWSTR pwszSubName - Name of the subscription
// : LPCWSTR pwszECID - EventCLSID to subscribe
// : LPCWSTR pwszPubID - Name of the Publisher
// : LPCWSTR pwszIID - IID to subscribe
// : IUnknown* punk - IUnknown* of the subscriber
// : LPCWSTR pwszMethod - Method name in the interface to subscribe
// : LPCWSTR pwszCriteria - Filter Criteria (used in parameterized filtering)
// : ULONG cPubProps - Count of publisher properties
// : SubscriptionProperty* pubProps - Array of publisher properties
// : ULONG cSubProps - Count of subscriber properties
// : SubscriptionProperty* subProps - Array of subscriber properties
// : BSTR* pbstrSubscriptionID - On return, the ID of the subscription created
// Return Value : HRESULT
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT AddTransientSubscription(
__in ICOMAdminCatalog* pCatalog,
__in LPCWSTR pwszSubName,
__in LPCWSTR pwszECID,
__in_opt LPCWSTR pwszPubID,
__in LPCWSTR pwszIID,
__in IUnknown *punk,
__in_opt LPCWSTR pwszMethod,
__in_opt LPCWSTR pwszCriteria,
__in ULONG cPubProps,
__in_ecount_opt(cPubProps) SubscriptionProperty* pubProps,
__in ULONG cSubProps,
__in_ecount_opt(cSubProps) SubscriptionProperty* subProps,
__deref_out BSTR* pbstrSubscriptionID)
{
HRESULT hr;
CComPtr<ICatalogObject> pCatObjSub;
CComPtr<ICatalogCollection> pCatCollSubs;
CComPtr<IDispatch> pDisp;
LONG lIgnored;
bool fCreate = false, fComplete = false;
if (!pCatalog || !pwszSubName || !punk || !pbstrSubscriptionID)
return E_INVALIDARG;
if ((cPubProps > 0) && (pubProps == NULL))
return E_INVALIDARG;
if ((cSubProps > 0) && (subProps == NULL))
return E_INVALIDARG;
hr = GetCollection(pCatalog, g_bstrTransientSubscriptions, &pCatCollSubs);
if_failed_exit(hr);
hr = pCatCollSubs->Add(&pDisp);
if_failed_exit(hr);
hr = pDisp->QueryInterface(IID_PPV_ARGS(&pCatObjSub));
if_failed_exit(hr);
pDisp.Release();
hr = SetStringProperty(pCatObjSub, g_bstrName, pwszSubName);
if_failed_exit(hr);
hr = SetStringProperty(pCatObjSub, g_bstrEventCLSID, pwszECID);
if_failed_exit(hr);
hr = SetStringProperty(pCatObjSub, g_bstrPublisherID, pwszPubID);
if_failed_exit(hr);
hr = SetStringProperty(pCatObjSub, g_bstrInterfaceID, pwszIID);
if_failed_exit(hr);
hr = SetIUnknownProperty(pCatObjSub, g_bstrSubscriberInterface, punk);
if_failed_exit(hr);
hr = SetStringProperty(pCatObjSub, g_bstrMethodName, pwszMethod);
if_failed_exit(hr);
hr = SetStringProperty(pCatObjSub, g_bstrFilterCriteria, pwszCriteria);
if_failed_exit(hr);
// The catalog automatically sets this to a new GUID value (in string form)
hr = GetStringProperty(pCatObjSub, g_bstrID, pbstrSubscriptionID);
if_failed_exit(hr);
hr = pCatCollSubs->SaveChanges(&lIgnored);
if_failed_exit(hr);
fCreate = true;
if (cPubProps > 0)
{
CComPtr<ICatalogCollection> pCatCollPubProps;
hr = GetCollection(pCatCollSubs, pCatObjSub, g_bstrTransientPublisherProperties, &pCatCollPubProps);
if_failed_exit(hr);
for (ULONG i = 0; i < cPubProps; i++)
{
hr = pCatCollPubProps->Add(&pDisp);
if_failed_exit(hr);
CComPtr<ICatalogObject> pCatObjProp;
hr = pDisp->QueryInterface(IID_PPV_ARGS(&pCatObjProp));
if_failed_exit(hr);
pDisp.Release();
hr = SetStringProperty(pCatObjProp, g_bstrName, pubProps[i].pwszPropName);
if_failed_exit(hr);
hr = pCatObjProp->put_Value(g_bstrValue, pubProps[i].varPropVal);
if_failed_exit(hr);
}
hr = pCatCollPubProps->SaveChanges(&lIgnored);
if_failed_exit(hr);
}
if (cSubProps > 0)
{
CComPtr<ICatalogCollection> pCatCollSubProps;
hr = GetCollection(pCatCollSubs, pCatObjSub, g_bstrTransientSubscriberProperties, &pCatCollSubProps);
if_failed_exit(hr);
for (ULONG i = 0; i < cSubProps; i++)
{
hr = pCatCollSubProps->Add(&pDisp);
if_failed_exit(hr);
CComPtr<ICatalogObject> pCatObjProp;
hr = pDisp->QueryInterface(IID_PPV_ARGS(&pCatObjProp));
if_failed_exit(hr);
pDisp.Release();
hr = SetStringProperty(pCatObjProp, g_bstrName, subProps[i].pwszPropName);
if_failed_exit(hr);
hr = pCatObjProp->put_Value(g_bstrValue, subProps[i].varPropVal);
if_failed_exit(hr);
}
hr = pCatCollSubProps->SaveChanges(&lIgnored);
if_failed_exit(hr);
}
fComplete = true;
exit:
if (fCreate && !fComplete)
RemoveTransientSubscription(pCatalog, *pbstrSubscriptionID);
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Name : RemoveTransientSubscription
// Purpose : Removes a Transient Subscription
// Parameters :
// : ICOMAdminCatalog* pCatalog - COM+ admin catalog object
// : BSTR bstrSubscriptionID - ID of the subscription to remove
// Return Value : HRESULT
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT RemoveTransientSubscription(
__in ICOMAdminCatalog* pCatalog,
__in BSTR bstrSubscriptionID)
{
HRESULT hr;
CComPtr<ICatalogCollection> pCatCollSubs;
LONG lCount, lIndex, lIgnored;
if (!pCatalog || !bstrSubscriptionID)
return E_INVALIDARG;
hr = GetCollection(pCatalog, g_bstrTransientSubscriptions, &pCatCollSubs);
if_failed_exit(hr);
hr = pCatCollSubs->Populate();
if_failed_exit(hr);
hr = pCatCollSubs->get_Count(&lCount);
if_failed_exit(hr);
if (lCount == 0)
exit_with_result(E_UNEXPECTED);
// Loop through
for (lIndex = 0; lIndex < lCount; lIndex++)
{
// Get the next item
CComPtr<IDispatch> pDisp;
hr = pCatCollSubs->get_Item(lIndex, &pDisp);
if_failed_exit(hr);
CComPtr<ICatalogObject> pCatObjSub;
hr = pDisp->QueryInterface(IID_PPV_ARGS(&pCatObjSub));
if_failed_exit(hr);
// Retrieve its key
CComVariant var;
hr = pCatObjSub->get_Key(&var);
if (var.vt != VT_BSTR)
exit_with_result(E_UNEXPECTED);
// Check for a match
if (wcscmp(bstrSubscriptionID, var.bstrVal) == 0)
{
// Found it!
hr = pCatCollSubs->Remove(lIndex);
if_failed_exit(hr);
hr = pCatCollSubs->SaveChanges(&lIgnored);
if_failed_exit(hr);
exit_with_result(S_OK);
}
}
// If we get here, the object didn't exist
exit_with_result(E_UNEXPECTED);
exit:
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Name : GetCollection
// Purpose : Gets a collection from the Catalogue
// Parameters :
// : ICOMAdminCatalog* pCatalog - Admin Catalog object
// : BSTR bstrCollName - Collection Name
// : ICatalogCollection** ppCatColl - Collection returned
// Return Value : HRESULT
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT GetCollection(
__in ICOMAdminCatalog* pCatalog,
__in BSTR bstrCollName,
__deref_out ICatalogCollection** ppCatColl)
{
HRESULT hr;
CComPtr<IDispatch> pDisp;
if (!pCatalog || !bstrCollName || !ppCatColl)
return E_INVALIDARG;
hr = pCatalog->GetCollection(bstrCollName, &pDisp);
if_failed_exit(hr);
hr = pDisp->QueryInterface(IID_PPV_ARGS(ppCatColl));
if_failed_exit(hr);
hr = (*ppCatColl)->Populate();
if_failed_exit(hr);
exit:
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Name : GetCollection
// Purpose : Gets a collection from the Catalogue
// Parameters :
// : ICatalogCollection* pCatCollParent- Parent Collection
// : ICatalogObject* pCatObjParent - Parent Object
// : BSTR bstrCollName - Collection Name
// : ICatalogCollection** ppCatColl - Collection returned
// Return Value : HRESULT
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT GetCollection(
__in ICatalogCollection* pCatCollParent,
__in ICatalogObject* pCatObjParent,
__in BSTR bstrCollName,
__deref_out ICatalogCollection** ppCatColl)
{
HRESULT hr;
CComVariant var;
CComPtr<IDispatch> pDisp;
if (!pCatCollParent || !pCatObjParent || !bstrCollName || !ppCatColl)
return E_INVALIDARG;
hr = pCatObjParent->get_Key(&var);
if_failed_exit(hr);
hr = pCatCollParent->GetCollection(bstrCollName, var, &pDisp);
if_failed_exit(hr);
hr = pDisp->QueryInterface(IID_PPV_ARGS(ppCatColl));
if_failed_exit(hr);
hr = (*ppCatColl)->Populate();
if_failed_exit(hr);
exit:
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Name : SetStringProperty
// Purpose : Sets a string property of an object
// Parameters :
// : ICatalogObject* pCatObj - Pointer to the object
// : BSTR bstrPropName - Name of the property
// : LPCWSTR pwszVal - Value of the property
// Return Value : HRESULT
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT SetStringProperty(
__in ICatalogObject* pCatObj,
__in BSTR bstrPropName,
__in_opt LPCWSTR pwszVal)
{
if (!pCatObj || !bstrPropName)
return E_INVALIDARG;
CComVariant var(pwszVal);
if ((pwszVal != NULL) && (var.bstrVal == NULL))
return E_OUTOFMEMORY;
return pCatObj->put_Value(bstrPropName, var);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Name : SetIUnknownProperty
// Purpose : Sets an IUnknown property of an object
// Parameters :
// : ICatalogObject* pCatObj - Pointer to the object
// : BSTR bstrPropName - Name of the property
// : IUnknown* punk - Value of the property
// Return Value : HRESULT
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT SetIUnknownProperty(
__in ICatalogObject* pCatObj,
__in BSTR bstrPropName,
__in IUnknown* punk)
{
if (!pCatObj || !bstrPropName || !punk)
return E_INVALIDARG;
CComVariant var(punk);
return pCatObj->put_Value(bstrPropName, var);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Name : GetStringProperty
// Purpose : Gets a string property of the object
// Parameters :
// : ICatalogObject* pCatObj - Pointer to the object
// : BSTR bstrPropName - Name of the property
// : BSTR* pbstrVal - Value of the property
// Return Value : HRESULT
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT GetStringProperty(
__in ICatalogObject* pCatObj,
__in BSTR bstrPropName,
__deref_out BSTR* pbstrVal)
{
HRESULT hr;
if (!pCatObj || !bstrPropName || !pbstrVal)
return E_INVALIDARG;
CComVariant var;
hr = pCatObj->get_Value(bstrPropName, &var);
if_failed_exit(hr);
if (var.vt != VT_BSTR)
return E_UNEXPECTED;
*pbstrVal = var.bstrVal;
var.bstrVal = NULL; // Caller now owns the BSTR
exit:
return hr;
}