/*++ Copyright (C) Microsoft Corporation, 1997 - 1999 Module Name: csubchng.cxx Abstract: This file contains the implementation of the IEventObjectChange interface. We need to subscribe to this interface for publishing the DestinationReachable events of SENS's ISensNetwork interface. Author: Gopal Parupudi [Notes:] optional-notes Revision History: GopalP 1/26/1998 Start. --*/ #include // // Globals // LONG g_cSubChangeObj; // Count of active components LONG g_cSubChangeLock; // Count of Server locks extern LIST *gpReachList; // // Constructors and Destructors // CImpIEventObjectChange::CImpIEventObjectChange( void ) : m_cRef(1L) // Add a reference. { InterlockedIncrement(&g_cSubChangeObj); } CImpIEventObjectChange::~CImpIEventObjectChange( void ) { InterlockedDecrement(&g_cSubChangeObj); } // // Standard QueryInterface // STDMETHODIMP CImpIEventObjectChange::QueryInterface( REFIID riid, LPVOID *ppv ) { HRESULT hr; DebugTraceGuid("CImpIEventObjectChange:QueryInterface()", riid); hr = S_OK; *ppv = NULL; // IUnknown if (IsEqualIID(riid, IID_IUnknown)) { *ppv = (ISensNetwork *) this; } else // IEventObjectChange if (IsEqualIID(riid, IID_IEventObjectChange)) { *ppv = (ISensNetwork *) this; } else { hr = E_NOINTERFACE; } if (NULL != *ppv) { ((LPUNKNOWN)*ppv)->AddRef(); } return hr; } // // Standard AddRef and Release // STDMETHODIMP_(ULONG) CImpIEventObjectChange::AddRef( void ) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CImpIEventObjectChange::Release( void ) { LONG cRefT; SensPrint(SENS_INFO, (SENS_STRING("\t| CImpIEventObjectChange::Release(m_cRef = %d) called.\n"), m_cRef)); cRefT = InterlockedDecrement((PLONG) &m_cRef); if (0 == m_cRef) { delete this; } return cRefT; } // // IEventObjectChange Implementation. // STDMETHODIMP CImpIEventObjectChange::ChangedSubscription( EOC_ChangeType changeType, BSTR bstrSubscriptionID ) { HRESULT hr; NODE *pNode; DWORD dwStatus; BOOL bSuccess; BSTR bstrDestinationName; hr = S_OK; pNode = NULL; dwStatus = ERROR_SUCCESS; bSuccess = FALSE; bstrDestinationName = NULL; SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n"))); SensPrint(SENS_INFO, (SENS_STRING("CImpIEventObjectChange::ChangedSubscription() called\n\n"))); SensPrint(SENS_INFO, (SENS_STRING(" ChangeType - %d\n"), changeType)); SensPrintW(SENS_INFO, (SENS_BSTR(" bstrSubscriptionID - %s\n"), bstrSubscriptionID)); SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n"))); hr = GetDestinationNameFromSubscription( bstrSubscriptionID, &bstrDestinationName ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SENS_STRING("GetDestinationNameFromSubscription() returned 0x%x\n"), hr)); if (HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION) == hr) { hr = S_OK; // Implies we got a non-DestinationReachability subscription. } goto Cleanup; } else if (bstrDestinationName == NULL) { SensPrintW(SENS_WARN, (SENS_BSTR("Destination is !\n"))); goto Cleanup; } else { SensPrintW(SENS_INFO, (SENS_BSTR("Destination is %s\n"), bstrDestinationName)); } // // Deal with the changed subscription appropriately. // switch (changeType) { case EOC_NewObject: { if (wcslen(bstrDestinationName) > MAX_DESTINATION_LENGTH) { SensPrintW(SENS_ERR, (SENS_BSTR("Destination %s is too long.\n"), bstrDestinationName)); break; } gpReachList->InsertByDest(bstrDestinationName); StartReachabilityEngine(); break; } case EOC_DeletedObject: // Delete the node from the reachability list. bSuccess = gpReachList->DeleteByDest(bstrDestinationName); break; case EOC_ModifiedObject: default: // Nothing to do. break;; } Cleanup: // // Cleanup // if (bstrDestinationName) { ::SysFreeString(bstrDestinationName); } return hr; } STDMETHODIMP CImpIEventObjectChange::ChangedEventClass( EOC_ChangeType changeType, BSTR bstrSubscriptionID ) { SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n"))); SensPrint(SENS_INFO, (SENS_STRING("CImpIEventObjectChange::ChangedEventClass() called\n\n"))); SensPrint(SENS_INFO, (SENS_STRING(" ChangeType - %d\n"), changeType)); SensPrintW(SENS_INFO, (SENS_BSTR(" bstrSubscriptionID - %s\n"), bstrSubscriptionID)); SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n"))); return S_OK; } STDMETHODIMP CImpIEventObjectChange::ChangedPublisher( EOC_ChangeType changeType, BSTR bstrSubscriptionID ) { SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n"))); SensPrint(SENS_INFO, (SENS_STRING("CImpIEventObjectChange::ChangedPublisher() called\n\n"))); SensPrint(SENS_INFO, (SENS_STRING(" ChangeType - %d\n"), changeType)); SensPrintW(SENS_INFO, (SENS_BSTR(" bstrSubscriptionID - %s\n"), bstrSubscriptionID)); SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n"))); return S_OK; } HRESULT GetDestinationNameFromSubscription( BSTR bstrSubscriptionID, BSTR *pbstrDestinationName ) { HRESULT hr; int errorIndex; BSTR bstrPropertyName; BSTR bstrMethodName; VARIANT variantPropertyValue; WCHAR wszQuery[MAX_QUERY_SIZE]; LPOLESTR strDestinationName; IEventSystem *pIEventSystem; IEventSubscription *pIEventSubscription; IUnknown *pIUnkQueryResult; hr = S_OK; errorIndex = 0; strDestinationName = NULL; bstrPropertyName = NULL; bstrMethodName = NULL; *pbstrDestinationName = NULL; pIEventSystem = NULL; pIEventSubscription = NULL; pIUnkQueryResult = NULL; // Get a new IEventSystem object to play with. hr = CoCreateInstance( CLSID_CEventSystem, NULL, CLSCTX_SERVER, IID_IEventSystem, (LPVOID *) &pIEventSystem ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SENS_STRING("GetDestinationNameFromSubscription(): failed to create ") SENS_STRING("IEventSystem - hr = <%x>\n"), hr)); goto Cleanup; } // Form the query wcscpy(wszQuery, SENS_BSTR("SubscriptionID")); wcscat(wszQuery, SENS_BSTR("=")); wcscat(wszQuery, bstrSubscriptionID); wcscat(wszQuery, SENS_BSTR("")); hr = pIEventSystem->Query( PROGID_EventSubscription, wszQuery, &errorIndex, &pIUnkQueryResult ); if (hr != S_OK) { SensPrint(SENS_ERR, (SENS_STRING("GetDestinationNameFromSubscription(): failed to Query() ") SENS_STRING("- hr = <%x>\n"), hr)); goto Cleanup; } hr = pIUnkQueryResult->QueryInterface( IID_IEventSubscription, (LPVOID *) &pIEventSubscription ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SENS_STRING("GetDestinationNameFromSubscription(): QI for IEventSubscription") SENS_STRING(" failed - hr = <%x>\n"), hr)); goto Cleanup; } // // See if it is a subscription for Destination Reachability event. If not, // return success. If yes, try to get the value for Publisher property - // bstrDestination. // hr = pIEventSubscription->get_MethodName( &bstrMethodName ); if (hr != S_OK) { SensPrint(SENS_ERR, (SENS_STRING("GetDestinationNameFromSubscription(): get_MethodName()") SENS_STRING(" failed - hr = <%x>\n"), hr)); goto Cleanup; } if ( (wcscmp(bstrMethodName, DESTINATION_REACHABLE_METHOD) != 0) && (wcscmp(bstrMethodName, DESTINATION_REACHABLE_NOQOC_METHOD) != 0)) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); SensPrint(SENS_ERR, (SENS_STRING("GetDestinationNameFromSubscription(): Non-Reachability event") SENS_STRING(" subscription (%s). Returning - hr = <%x>\n"), bstrMethodName, hr)); goto Cleanup; } // // Try to get the value for Publisher property - bstrDestination // VariantInit(&variantPropertyValue); AllocateBstrFromString(bstrPropertyName, PROPERTY_DESTINATION); hr = pIEventSubscription->GetPublisherProperty( bstrPropertyName, &variantPropertyValue ); if (hr == S_OK) { *pbstrDestinationName = variantPropertyValue.bstrVal; // Found the property! goto Cleanup; } // // Now, try to get the value for Publisher property - bstrDestinationNoQOC // FreeBstr(bstrPropertyName); VariantInit(&variantPropertyValue); AllocateBstrFromString(bstrPropertyName, PROPERTY_DESTINATION_NOQOC); hr = pIEventSubscription->GetPublisherProperty( bstrPropertyName, &variantPropertyValue ); if (hr == S_OK) { // Found the property! *pbstrDestinationName = variantPropertyValue.bstrVal; goto Cleanup; } SensPrint(SENS_ERR, (SENS_STRING("GetDestinationNameFromSubscription(): failed to get ") SENS_STRING("PublisherProperty - hr = <%x>\n"), hr)); Cleanup: // // Cleanup // if (pIEventSystem) { pIEventSystem->Release(); } if (pIEventSubscription) { pIEventSubscription->Release(); } if (pIUnkQueryResult) { pIUnkQueryResult->Release(); } FreeBstr(bstrPropertyName); FreeBstr(bstrMethodName); return (hr); }