/*++ Copyright (c) 1999 Microsoft Corporation Abstract: @doc @module COMAdmin.cxx | Simple wrapper around COM Admin classes @end Author: Adi Oltean [aoltean] 08/15/1999 TBD: Add comments. Revision History: Name Date Comments aoltean 08/15/1999 Created. aoltean 09/09/1999 dss -> vss aoltean 09/21/1999 Fixing VSSDBG_GEN. --*/ ///////////////////////////////////////////////////////////////////////////// // Defines // C4290: C++ Exception Specification ignored #pragma warning(disable:4290) // C4127: conditional expression is constant #pragma warning( disable: 4127 ) #define STRICT ///////////////////////////////////////////////////////////////////////////// // Includes #include #include #include #include "vs_assert.hxx" #include #include #include #include "vssmsg.h" #include "vs_inc.hxx" #include "vs_idl.hxx" #include #include "comadmin.hxx" //////////////////////////////////////////////////////////////////////// // Standard foo for file name aliasing. This code block must be after // all includes of VSS header files. // #ifdef VSS_FILE_ALIAS #undef VSS_FILE_ALIAS #endif #define VSS_FILE_ALIAS "CADCADMC" // //////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Globals // Collection attributes - TBD: Verify if Keys are OK!! struct _VsCOMCollectionAttr g_VsCOMCollectionsArray[] = { { L"", L"", L"", }, // VSS_COM_UNKNOWN = 0, { L"ApplicationCluster", L"Name", L"Name", }, // VSS_COM_APPLICATION_CLUSTER, { L"Applications", L"ID", L"Name", }, // VSS_COM_APPLICATIONS, { L"Components", L"CLSID", L"ProgID", }, // VSS_COM_COMPONENTS, { L"ComputerList", L"Name", L"Name", }, // VSS_COM_COMPUTERLIST, { L"DCOMProtocols", L"Name", L"Name", }, // VSS_COM_DCOM_PROTOCOLS, { L"ErrorInfo", L"MajorRef", L"MajorRef", }, // VSS_COM_ERRORINFO, { L"IMDBDataSources", L"DataSource", L"DataSource",}, // VSS_COM_IMDB_DATA_SOURCES, { L"IMDBDataSourceTables", L"TableName", L"TableName", }, // VSS_COM_IMDB_DATA_SOURCE_TABLES, { L"InprocServers", L"CLSID", L"ProgID", }, // VSS_COM_INPROC_SERVERS, { L"InterfacesForComponent", L"IID" L"Name" }, // VSS_COM_INTERFACES_FOR_COMPONENT, { L"LocalComputer", L"Name", L"Name", }, // VSS_COM_LOCAL_COMPUTER, { L"MethodsForInterface", L"Index", L"Name", }, // VSS_COM_METHODS_FOR_INTERFACE, { L"PropertyInfo", L"Name", L"Name", }, // VSS_COM_PROPERTY_INFO, { L"PublisherProperties", L"Name", L"Name", }, // VSS_COM_PUBLISHER_PROPERTIES, { L"RelatedCollectionInfo", L"Name", L"Name", }, // VSS_COM_RELATED_COLLECTION_INFO, { L"Roles", L"Name", L"Name", }, // VSS_COM_ROLES, { L"RolesForComponent", L"Name", L"Name", }, // VSS_COM_ROLES_FOR_COMPONENT, { L"RolesForInterface", L"Name", L"Name", }, // VSS_COM_ROLES_FOR_INTERFACE, { L"RolesForMethod", L"Name", L"Name", }, // VSS_COM_ROLES_FOR_METHOD, { L"Root", L"", L"", }, // VSS_COM_ROOT, { L"SubscriberProperties", L"Name", L"Name", }, // VSS_COM_SUBSCRIBER_PROPERTIES, { L"Subscriptions", L"ID", L"Name", }, // VSS_COM_SUBSCRIPTIONS, { L"TransientSubscriptions", L"ID", L"Name", }, // VSS_COM_TRANSIENT_SUBSCRIPTIONS, { L"UsersInRole", L"User", L"User", } // VSS_COM_USERS_IN_ROLE, }; ///////////////////////////////////////////////////////////////////////////// // Implementation of CVssCOMAdminCatalog HRESULT CVssCOMAdminCatalog::Attach( IN const WCHAR* pwszAppName ) { CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMAdminCatalog::Attach" ); try { // Testing argument if (pwszAppName == NULL || pwszAppName[0] == L'\0') { BS_ASSERT(false); ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"NULL or empty application name"); } // Begin initializing m_bInitialized = false; m_pICatalog = NULL; // Creating the COMAdminCatalog instance ft.CoCreateInstanceWithLog( VSSDBG_GEN, __uuidof(COMAdminCatalog), L"COMAdminCatalog", CLSCTX_ALL, IID_ICOMAdminCatalog2, (IUnknown**)&m_pICatalog); if (ft.HrFailed()) { ft.LogError( VSS_ERROR_CREATING_COMPLUS_ADMIN_CATALOG, VSSDBG_GEN << ft.hr ); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Error creating the COMAdminCatalog instance hr = 0x%08lx", ft.hr); } // Getting the application name m_bstrAppName = pwszAppName; if (!m_bstrAppName) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); // End initializing m_bInitialized = true; } VSS_STANDARD_CATCH(ft) return ft.hr; } HRESULT CVssCOMAdminCatalog::InstallComponent( IN const WCHAR* pwszDllName, IN const WCHAR* pwszTlbName, IN const WCHAR* pwszProxyStubName ) { CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMAdminCatalog::InstallComponent" ); try { // Test if initialized if (!m_bInitialized) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized"); // Testing arguments if (pwszDllName == NULL || pwszDllName[0] == L'\0') ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"NULL or empty paths"); CComBSTR bstrAppName = (LPWSTR)m_bstrAppName; if ((LPWSTR)bstrAppName == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); CComBSTR bstrDllName = pwszDllName; if ((LPWSTR)bstrDllName == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); CComBSTR bstrTlbName = pwszTlbName? pwszTlbName: L""; if ((LPWSTR)bstrTlbName == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); CComBSTR bstrProxyStubName = pwszProxyStubName? pwszProxyStubName: L""; if ((LPWSTR)bstrProxyStubName == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); // Install event class for this application ft.hr = m_pICatalog->InstallComponent( bstrAppName, bstrDllName, bstrTlbName, bstrProxyStubName ); if (ft.HrFailed()) { ft.TraceComError(); ft.LogError( VSS_ERROR_INSTALL_COMPONENT, VSSDBG_GEN << bstrDllName << bstrAppName << ft.hr ); ft.Throw(VSSDBG_GEN, ft.hr, L"Installing the component failed"); } } VSS_STANDARD_CATCH(ft) return ft.hr; } HRESULT CVssCOMAdminCatalog::CreateServiceForApplication( IN const WCHAR* pwszServiceName ) { CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMAdminCatalog::CreateServiceForApplication" ); try { // Test if initialized if (!m_bInitialized) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized"); CComBSTR bstrAppName = (LPWSTR)m_bstrAppName; if ((LPWSTR)bstrAppName == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); CComBSTR bstrSvcName = pwszServiceName; if ((LPWSTR)bstrSvcName == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); CComBSTR bstrStartType = L"SERVICE_DEMAND_START"; if ((LPWSTR)bstrStartType == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); CComBSTR bstrErrorControl = L"SERVICE_ERROR_IGNORE"; if ((LPWSTR)bstrErrorControl == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); CComBSTR bstrRunAs = L"LocalSystem"; if ((LPWSTR)bstrRunAs == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); CComBSTR bstrPassword = L""; if ((LPWSTR)bstrRunAs == NULL) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); #ifdef _DEBUG VARIANT_BOOL vboolDesktopOK = VARIANT_TRUE; #else VARIANT_BOOL vboolDesktopOK = VARIANT_FALSE; #endif ft.Trace(VSSDBG_GEN, L"Calling CreateServiceForApplicationStrings(%s, %s, %s, %s, %s, %s, %s, %s)", bstrAppName, bstrSvcName, bstrStartType, bstrErrorControl, NULL, bstrRunAs, bstrPassword, vboolDesktopOK == VARIANT_TRUE? L"TRUE": L"FALSE" ); // Install event class for this application ft.hr = m_pICatalog->CreateServiceForApplication( m_bstrAppName, bstrSvcName, bstrStartType, bstrErrorControl, NULL, bstrRunAs, bstrPassword, vboolDesktopOK ); if (ft.HrFailed()) { ft.TraceComError(); ft.LogError( VSS_ERROR_CREATE_SERVICE_FOR_APPLICATION, VSSDBG_GEN << bstrSvcName << m_bstrAppName << ft.hr ); ft.Throw(VSSDBG_GEN, ft.hr, L"Installing the component failed"); } } VSS_STANDARD_CATCH(ft) return ft.hr; } ///////////////////////////////////////////////////////////////////////////// // Implementation of CVssCOMCatalogCollection HRESULT CVssCOMCatalogCollection::Attach( IN CVssCOMAdminCatalog& catalog ) { CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::Attach_ToCatalog" ); try { // Begin intializing m_bInitialized = false; m_pICollection = NULL; // Check if Collection type is valid if ((m_eType <= 0) || (m_eType >= VSS_COM_COLLECTIONS_COUNT)) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Invalid collection type"); // Converting collection name into BSTR CComBSTR bstrCollectionName = g_VsCOMCollectionsArray[m_eType].wszName; if (!bstrCollectionName) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); // Get the catalog interface CComPtr pICatalog = catalog.GetInterface(); if (pICatalog == NULL) { BS_ASSERT(false); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog object not initialized."); } // Get the collection object CComPtr pIDisp; ft.hr = pICatalog->GetCollection(bstrCollectionName, &pIDisp); if (ft.HrFailed()) { ft.LogError( VSS_ERROR_GETTING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr ); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting the collection. hr = 0x%08lx", ft.hr); } BS_ASSERT(pIDisp); // Convert to ICatalogCollection CComPtr pICollection; ft.hr = pIDisp->SafeQI(ICatalogCollection, &pICollection); if (ft.HrFailed()) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogCollection. hr = 0x%08lx", ft.hr); // Populate the collection ft.hr = pICollection->Populate(); if (ft.HrFailed()) { ft.LogError( VSS_ERROR_POPULATING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr ); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in populating the collection object. hr = 0x%08lx", ft.hr); } // End intializing m_pICollection = pICollection; m_bInitialized = true; } VSS_STANDARD_CATCH(ft) return ft.hr; } HRESULT CVssCOMCatalogCollection::Attach( IN CVssCOMCatalogObject& parentObject ) { CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::Attach_ToParentCollection" ); try { // Begin intializing m_bInitialized = false; m_pICollection = NULL; // Check if Collection type is valid if ((m_eType <= 0) || (m_eType >= VSS_COM_COLLECTIONS_COUNT)) ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"Invalid collection type"); // Converting collection name into BSTR CComBSTR bstrCollectionName = g_VsCOMCollectionsArray[m_eType].wszName; if (!bstrCollectionName) ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error"); // Get the parent object interface CComPtr pIParentObject = parentObject.GetInterface(); if (pIParentObject == NULL) { BS_ASSERT(false); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Parent object not initialized yet."); } // Get the Key that uniquely identifies the parent object in the grand parent collection CComVariant variant; // Beware to not leave variant resources before get_Key call! ft.hr = pIParentObject->get_Key(&variant); if (ft.HrFailed()) { ft.LogError( VSS_ERROR_GET_COLLECTION_KEY, VSSDBG_GEN << ft.hr ); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting object key. hr = 0x%08lx", ft.hr); } // Get the grand parent collection interface CComPtr pIGrandParentCollection = parentObject.GetParentInterface(); if (pIGrandParentCollection == NULL) { BS_ASSERT(false); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Parent object not initialized."); } // Get the collection object CComPtr pIDisp; ft.hr = pIGrandParentCollection->GetCollection(bstrCollectionName, variant, &pIDisp); if (ft.HrFailed()) { ft.LogError( VSS_ERROR_GET_COLLECTION_FROM_PARENT, VSSDBG_GEN << bstrCollectionName << ft.hr ); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting collection. hr = 0x%08lx", ft.hr); } BS_ASSERT(pIDisp); // Convert to ICatalogCollection ICatalogCollection* pICollection; ft.hr = pIDisp->SafeQI(ICatalogCollection, &pICollection); if (ft.HrFailed()) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogCollection. hr = 0x%08lx", ft.hr); BS_ASSERT(pICollection); m_pICollection.Attach(pICollection); // Populate the collection ft.hr = m_pICollection->Populate(); if (ft.HrFailed()) { ft.LogError( VSS_ERROR_POPULATING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr ); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in populating the collection object. hr = 0x%08lx", ft.hr); } // End intializing m_bInitialized = true; } VSS_STANDARD_CATCH(ft) return ft.hr; } HRESULT CVssCOMCatalogCollection::SaveChanges() { CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::SaveChanges" ); try { // Test if initialized if (!m_bInitialized) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized"); // Save changes LONG lRet = 0; ft.hr = m_pICollection->SaveChanges(&lRet); if (ft.HrFailed()) { ft.LogError( VSS_ERROR_SAVING_CHANGES, VSSDBG_GEN << ft.hr ); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in saving the changes. hr = 0x%08lx", ft.hr); } } VSS_STANDARD_CATCH(ft) return ft.hr; } ///////////////////////////////////////////////////////////////////////////// // Implementation of CVssCOMCatalogCollection HRESULT CVssCOMCatalogObject::InsertInto( IN CVssCOMCatalogCollection& collection ) { CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogObject::InsertInto" ); try { // Begin initialization m_bInitialized = false; m_pIObject = NULL; m_pIParentCollection = NULL; m_lIndex = -1; // Get the collection object CComPtr pIParentCollection = collection.GetInterface(); if (pIParentCollection == NULL) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Collection object not initialized"); // Get the instance of the new object CComPtr pIDisp; ft.hr = pIParentCollection->Add(&pIDisp); if (ft.HrFailed()) { ft.LogError( VSS_ERROR_INSERT_INTO, VSSDBG_GEN << ft.hr ); ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in adding the catalog object. hr = 0x%08lx", ft.hr); } BS_ASSERT(pIDisp); // Convert to ICatalogObject BS_ASSERT(m_pIObject == NULL); ft.hr = pIDisp->SafeQI(ICatalogObject, &m_pIObject); if (ft.HrFailed()) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogObject. hr = 0x%08lx", ft.hr); // End initialization m_pIParentCollection = pIParentCollection; m_bInitialized = true; } VSS_STANDARD_CATCH(ft) return ft.hr; } // // Disclaimer: this method assumes that the collection is already populated // // S_FALSE means object not found // HRESULT CVssCOMCatalogObject::AttachByName( IN CVssCOMCatalogCollection& collection, IN const WCHAR wszName[], IN const WCHAR wszPropertyName[] /* = NULL */ ) { CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogObject::AttachByName" ); try { // Begin initialization m_bInitialized = false; m_pIObject = NULL; m_pIParentCollection = NULL; m_lIndex = -1; // Check if Object type is valid if ((m_eType <= 0) && (m_eType >= VSS_COM_COLLECTIONS_COUNT)) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Invalid object type"); if (m_eType != collection.GetType()) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Object type doesn't match with collection type"); // Get the collection object CComPtr pIParentCollection = collection.GetInterface(); if (pIParentCollection == NULL) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Collection object not initialized."); // Get the name of the property used as a key CComBSTR bstrPropertyName; if (wszPropertyName == NULL) bstrPropertyName = g_VsCOMCollectionsArray[m_eType].wszDefaultKey; else bstrPropertyName = wszPropertyName; // Get the number of objects in the collection LONG lCount = -1; ft.hr = pIParentCollection->get_Count(&lCount); if (ft.HrFailed()) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying the number of elements. hr = 0x%08lx", ft.hr); if (lCount == 0) ft.Trace(VSSDBG_GEN, L"Empty collection"); CComVariant varObjectName = wszName; CComVariant variant; CComPtr pIDisp; CComPtr pIObject; for(LONG lIndex = 0; lIndex < lCount; lIndex++) { // Release previous references pIDisp = pIObject = NULL; // Get next item ft.hr = pIParentCollection->get_Item(lIndex, &pIDisp); if (ft.HrFailed()) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting object with index %ld. hr = 0x%08lx", lIndex, ft.hr); // Convert it to ICatalogObject ft.hr = pIDisp->SafeQI(ICatalogObject, &pIObject); if (ft.HrFailed()) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogObject. hr = 0x%08lx", ft.hr); variant.Clear(); // do not forget to release resources before get_XXX ! ft.hr = pIObject->get_Value(bstrPropertyName, &variant); if (ft.HrFailed()) ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting value for the object key with index %ld. hr = 0x%08lx", lIndex, ft.hr); if (varObjectName == variant) { m_bInitialized = TRUE; m_lIndex = lIndex; m_pIParentCollection = pIParentCollection; m_pIObject = pIObject; break; } } if (!m_bInitialized) ft.hr = S_FALSE; // Object not found! } VSS_STANDARD_CATCH(ft) return ft.hr; }