Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

597 lines
21 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Abstract:
  4. @doc
  5. @module COMAdmin.cxx | Simple wrapper around COM Admin classes
  6. @end
  7. Author:
  8. Adi Oltean [aoltean] 08/15/1999
  9. TBD:
  10. Add comments.
  11. Revision History:
  12. Name Date Comments
  13. aoltean 08/15/1999 Created.
  14. aoltean 09/09/1999 dss -> vss
  15. aoltean 09/21/1999 Fixing VSSDBG_GEN.
  16. --*/
  17. /////////////////////////////////////////////////////////////////////////////
  18. // Defines
  19. // C4290: C++ Exception Specification ignored
  20. #pragma warning(disable:4290)
  21. // C4127: conditional expression is constant
  22. #pragma warning( disable: 4127 )
  23. #define STRICT
  24. /////////////////////////////////////////////////////////////////////////////
  25. // Includes
  26. #include <wtypes.h>
  27. #include <stddef.h>
  28. #include <oleauto.h>
  29. #include "vs_assert.hxx"
  30. #include <atlconv.h>
  31. #include <atlbase.h>
  32. #include <comadmin.h>
  33. #include "vssmsg.h"
  34. #include "vs_inc.hxx"
  35. #include "vs_idl.hxx"
  36. #include <vs_sec.hxx>
  37. #include "comadmin.hxx"
  38. ////////////////////////////////////////////////////////////////////////
  39. // Standard foo for file name aliasing. This code block must be after
  40. // all includes of VSS header files.
  41. //
  42. #ifdef VSS_FILE_ALIAS
  43. #undef VSS_FILE_ALIAS
  44. #endif
  45. #define VSS_FILE_ALIAS "CADCADMC"
  46. //
  47. ////////////////////////////////////////////////////////////////////////
  48. /////////////////////////////////////////////////////////////////////////////
  49. // Globals
  50. // Collection attributes - TBD: Verify if Keys are OK!!
  51. struct _VsCOMCollectionAttr g_VsCOMCollectionsArray[] =
  52. {
  53. { L"", L"", L"", }, // VSS_COM_UNKNOWN = 0,
  54. { L"ApplicationCluster", L"Name", L"Name", }, // VSS_COM_APPLICATION_CLUSTER,
  55. { L"Applications", L"ID", L"Name", }, // VSS_COM_APPLICATIONS,
  56. { L"Components", L"CLSID", L"ProgID", }, // VSS_COM_COMPONENTS,
  57. { L"ComputerList", L"Name", L"Name", }, // VSS_COM_COMPUTERLIST,
  58. { L"DCOMProtocols", L"Name", L"Name", }, // VSS_COM_DCOM_PROTOCOLS,
  59. { L"ErrorInfo", L"MajorRef", L"MajorRef", }, // VSS_COM_ERRORINFO,
  60. { L"IMDBDataSources", L"DataSource", L"DataSource",}, // VSS_COM_IMDB_DATA_SOURCES,
  61. { L"IMDBDataSourceTables", L"TableName", L"TableName", }, // VSS_COM_IMDB_DATA_SOURCE_TABLES,
  62. { L"InprocServers", L"CLSID", L"ProgID", }, // VSS_COM_INPROC_SERVERS,
  63. { L"InterfacesForComponent", L"IID" L"Name" }, // VSS_COM_INTERFACES_FOR_COMPONENT,
  64. { L"LocalComputer", L"Name", L"Name", }, // VSS_COM_LOCAL_COMPUTER,
  65. { L"MethodsForInterface", L"Index", L"Name", }, // VSS_COM_METHODS_FOR_INTERFACE,
  66. { L"PropertyInfo", L"Name", L"Name", }, // VSS_COM_PROPERTY_INFO,
  67. { L"PublisherProperties", L"Name", L"Name", }, // VSS_COM_PUBLISHER_PROPERTIES,
  68. { L"RelatedCollectionInfo", L"Name", L"Name", }, // VSS_COM_RELATED_COLLECTION_INFO,
  69. { L"Roles", L"Name", L"Name", }, // VSS_COM_ROLES,
  70. { L"RolesForComponent", L"Name", L"Name", }, // VSS_COM_ROLES_FOR_COMPONENT,
  71. { L"RolesForInterface", L"Name", L"Name", }, // VSS_COM_ROLES_FOR_INTERFACE,
  72. { L"RolesForMethod", L"Name", L"Name", }, // VSS_COM_ROLES_FOR_METHOD,
  73. { L"Root", L"", L"", }, // VSS_COM_ROOT,
  74. { L"SubscriberProperties", L"Name", L"Name", }, // VSS_COM_SUBSCRIBER_PROPERTIES,
  75. { L"Subscriptions", L"ID", L"Name", }, // VSS_COM_SUBSCRIPTIONS,
  76. { L"TransientSubscriptions", L"ID", L"Name", }, // VSS_COM_TRANSIENT_SUBSCRIPTIONS,
  77. { L"UsersInRole", L"User", L"User", } // VSS_COM_USERS_IN_ROLE,
  78. };
  79. /////////////////////////////////////////////////////////////////////////////
  80. // Implementation of CVssCOMAdminCatalog
  81. HRESULT CVssCOMAdminCatalog::Attach(
  82. IN const WCHAR* pwszAppName
  83. )
  84. {
  85. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMAdminCatalog::Attach" );
  86. try
  87. {
  88. // Testing argument
  89. if (pwszAppName == NULL || pwszAppName[0] == L'\0') {
  90. BS_ASSERT(false);
  91. ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"NULL or empty application name");
  92. }
  93. // Begin initializing
  94. m_bInitialized = false;
  95. m_pICatalog = NULL;
  96. // Creating the COMAdminCatalog instance
  97. ft.CoCreateInstanceWithLog(
  98. VSSDBG_GEN,
  99. __uuidof(COMAdminCatalog),
  100. L"COMAdminCatalog",
  101. CLSCTX_ALL,
  102. IID_ICOMAdminCatalog2,
  103. (IUnknown**)&m_pICatalog);
  104. if (ft.HrFailed()) {
  105. ft.LogError( VSS_ERROR_CREATING_COMPLUS_ADMIN_CATALOG, VSSDBG_GEN << ft.hr );
  106. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Error creating the COMAdminCatalog instance hr = 0x%08lx", ft.hr);
  107. }
  108. // Getting the application name
  109. m_bstrAppName = pwszAppName;
  110. if (!m_bstrAppName)
  111. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  112. // End initializing
  113. m_bInitialized = true;
  114. }
  115. VSS_STANDARD_CATCH(ft)
  116. return ft.hr;
  117. }
  118. HRESULT CVssCOMAdminCatalog::InstallComponent(
  119. IN const WCHAR* pwszDllName,
  120. IN const WCHAR* pwszTlbName,
  121. IN const WCHAR* pwszProxyStubName
  122. )
  123. {
  124. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMAdminCatalog::InstallComponent" );
  125. try
  126. {
  127. // Test if initialized
  128. if (!m_bInitialized)
  129. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized");
  130. // Testing arguments
  131. if (pwszDllName == NULL || pwszDllName[0] == L'\0')
  132. ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"NULL or empty paths");
  133. CComBSTR bstrAppName = (LPWSTR)m_bstrAppName;
  134. if ((LPWSTR)bstrAppName == NULL)
  135. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  136. CComBSTR bstrDllName = pwszDllName;
  137. if ((LPWSTR)bstrDllName == NULL)
  138. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  139. CComBSTR bstrTlbName = pwszTlbName? pwszTlbName: L"";
  140. if ((LPWSTR)bstrTlbName == NULL)
  141. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  142. CComBSTR bstrProxyStubName = pwszProxyStubName? pwszProxyStubName: L"";
  143. if ((LPWSTR)bstrProxyStubName == NULL)
  144. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  145. // Install event class for this application
  146. ft.hr = m_pICatalog->InstallComponent(
  147. bstrAppName,
  148. bstrDllName,
  149. bstrTlbName,
  150. bstrProxyStubName
  151. );
  152. if (ft.HrFailed()) {
  153. ft.TraceComError();
  154. ft.LogError( VSS_ERROR_INSTALL_COMPONENT, VSSDBG_GEN << bstrDllName << bstrAppName << ft.hr );
  155. ft.Throw(VSSDBG_GEN, ft.hr, L"Installing the component failed");
  156. }
  157. }
  158. VSS_STANDARD_CATCH(ft)
  159. return ft.hr;
  160. }
  161. HRESULT CVssCOMAdminCatalog::CreateServiceForApplication(
  162. IN const WCHAR* pwszServiceName
  163. )
  164. {
  165. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMAdminCatalog::CreateServiceForApplication" );
  166. try
  167. {
  168. // Test if initialized
  169. if (!m_bInitialized)
  170. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized");
  171. CComBSTR bstrAppName = (LPWSTR)m_bstrAppName;
  172. if ((LPWSTR)bstrAppName == NULL)
  173. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  174. CComBSTR bstrSvcName = pwszServiceName;
  175. if ((LPWSTR)bstrSvcName == NULL)
  176. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  177. CComBSTR bstrStartType = L"SERVICE_DEMAND_START";
  178. if ((LPWSTR)bstrStartType == NULL)
  179. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  180. CComBSTR bstrErrorControl = L"SERVICE_ERROR_IGNORE";
  181. if ((LPWSTR)bstrErrorControl == NULL)
  182. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  183. CComBSTR bstrRunAs = L"LocalSystem";
  184. if ((LPWSTR)bstrRunAs == NULL)
  185. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  186. CComBSTR bstrPassword = L"";
  187. if ((LPWSTR)bstrRunAs == NULL)
  188. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  189. #ifdef _DEBUG
  190. VARIANT_BOOL vboolDesktopOK = VARIANT_TRUE;
  191. #else
  192. VARIANT_BOOL vboolDesktopOK = VARIANT_FALSE;
  193. #endif
  194. ft.Trace(VSSDBG_GEN,
  195. L"Calling CreateServiceForApplicationStrings(%s, %s, %s, %s, %s, %s, %s, %s)",
  196. bstrAppName,
  197. bstrSvcName,
  198. bstrStartType,
  199. bstrErrorControl,
  200. NULL,
  201. bstrRunAs,
  202. bstrPassword,
  203. vboolDesktopOK == VARIANT_TRUE? L"TRUE": L"FALSE"
  204. );
  205. // Install event class for this application
  206. ft.hr = m_pICatalog->CreateServiceForApplication(
  207. m_bstrAppName,
  208. bstrSvcName,
  209. bstrStartType,
  210. bstrErrorControl,
  211. NULL,
  212. bstrRunAs,
  213. bstrPassword,
  214. vboolDesktopOK
  215. );
  216. if (ft.HrFailed()) {
  217. ft.TraceComError();
  218. ft.LogError( VSS_ERROR_CREATE_SERVICE_FOR_APPLICATION, VSSDBG_GEN << bstrSvcName << m_bstrAppName << ft.hr );
  219. ft.Throw(VSSDBG_GEN, ft.hr, L"Installing the component failed");
  220. }
  221. }
  222. VSS_STANDARD_CATCH(ft)
  223. return ft.hr;
  224. }
  225. /////////////////////////////////////////////////////////////////////////////
  226. // Implementation of CVssCOMCatalogCollection
  227. HRESULT CVssCOMCatalogCollection::Attach(
  228. IN CVssCOMAdminCatalog& catalog
  229. )
  230. {
  231. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::Attach_ToCatalog" );
  232. try
  233. {
  234. // Begin intializing
  235. m_bInitialized = false;
  236. m_pICollection = NULL;
  237. // Check if Collection type is valid
  238. if ((m_eType <= 0) || (m_eType >= VSS_COM_COLLECTIONS_COUNT))
  239. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Invalid collection type");
  240. // Converting collection name into BSTR
  241. CComBSTR bstrCollectionName = g_VsCOMCollectionsArray[m_eType].wszName;
  242. if (!bstrCollectionName)
  243. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  244. // Get the catalog interface
  245. CComPtr<ICOMAdminCatalog2> pICatalog = catalog.GetInterface();
  246. if (pICatalog == NULL) {
  247. BS_ASSERT(false);
  248. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog object not initialized.");
  249. }
  250. // Get the collection object
  251. CComPtr<IDispatch> pIDisp;
  252. ft.hr = pICatalog->GetCollection(bstrCollectionName, &pIDisp);
  253. if (ft.HrFailed()) {
  254. ft.LogError( VSS_ERROR_GETTING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr );
  255. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting the collection. hr = 0x%08lx", ft.hr);
  256. }
  257. BS_ASSERT(pIDisp);
  258. // Convert to ICatalogCollection
  259. CComPtr<ICatalogCollection> pICollection;
  260. ft.hr = pIDisp->SafeQI(ICatalogCollection, &pICollection);
  261. if (ft.HrFailed())
  262. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogCollection. hr = 0x%08lx", ft.hr);
  263. // Populate the collection
  264. ft.hr = pICollection->Populate();
  265. if (ft.HrFailed()) {
  266. ft.LogError( VSS_ERROR_POPULATING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr );
  267. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in populating the collection object. hr = 0x%08lx", ft.hr);
  268. }
  269. // End intializing
  270. m_pICollection = pICollection;
  271. m_bInitialized = true;
  272. }
  273. VSS_STANDARD_CATCH(ft)
  274. return ft.hr;
  275. }
  276. HRESULT CVssCOMCatalogCollection::Attach(
  277. IN CVssCOMCatalogObject& parentObject
  278. )
  279. {
  280. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::Attach_ToParentCollection" );
  281. try
  282. {
  283. // Begin intializing
  284. m_bInitialized = false;
  285. m_pICollection = NULL;
  286. // Check if Collection type is valid
  287. if ((m_eType <= 0) || (m_eType >= VSS_COM_COLLECTIONS_COUNT))
  288. ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"Invalid collection type");
  289. // Converting collection name into BSTR
  290. CComBSTR bstrCollectionName = g_VsCOMCollectionsArray[m_eType].wszName;
  291. if (!bstrCollectionName)
  292. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  293. // Get the parent object interface
  294. CComPtr<ICatalogObject> pIParentObject = parentObject.GetInterface();
  295. if (pIParentObject == NULL) {
  296. BS_ASSERT(false);
  297. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Parent object not initialized yet.");
  298. }
  299. // Get the Key that uniquely identifies the parent object in the grand parent collection
  300. CComVariant variant;
  301. // Beware to not leave variant resources before get_Key call!
  302. ft.hr = pIParentObject->get_Key(&variant);
  303. if (ft.HrFailed()) {
  304. ft.LogError( VSS_ERROR_GET_COLLECTION_KEY, VSSDBG_GEN << ft.hr );
  305. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting object key. hr = 0x%08lx", ft.hr);
  306. }
  307. // Get the grand parent collection interface
  308. CComPtr<ICatalogCollection> pIGrandParentCollection = parentObject.GetParentInterface();
  309. if (pIGrandParentCollection == NULL) {
  310. BS_ASSERT(false);
  311. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Parent object not initialized.");
  312. }
  313. // Get the collection object
  314. CComPtr<IDispatch> pIDisp;
  315. ft.hr = pIGrandParentCollection->GetCollection(bstrCollectionName, variant, &pIDisp);
  316. if (ft.HrFailed()) {
  317. ft.LogError( VSS_ERROR_GET_COLLECTION_FROM_PARENT, VSSDBG_GEN << bstrCollectionName << ft.hr );
  318. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting collection. hr = 0x%08lx", ft.hr);
  319. }
  320. BS_ASSERT(pIDisp);
  321. // Convert to ICatalogCollection
  322. ICatalogCollection* pICollection;
  323. ft.hr = pIDisp->SafeQI(ICatalogCollection, &pICollection);
  324. if (ft.HrFailed())
  325. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogCollection. hr = 0x%08lx", ft.hr);
  326. BS_ASSERT(pICollection);
  327. m_pICollection.Attach(pICollection);
  328. // Populate the collection
  329. ft.hr = m_pICollection->Populate();
  330. if (ft.HrFailed()) {
  331. ft.LogError( VSS_ERROR_POPULATING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr );
  332. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in populating the collection object. hr = 0x%08lx", ft.hr);
  333. }
  334. // End intializing
  335. m_bInitialized = true;
  336. }
  337. VSS_STANDARD_CATCH(ft)
  338. return ft.hr;
  339. }
  340. HRESULT CVssCOMCatalogCollection::SaveChanges()
  341. {
  342. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::SaveChanges" );
  343. try
  344. {
  345. // Test if initialized
  346. if (!m_bInitialized)
  347. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized");
  348. // Save changes
  349. LONG lRet = 0;
  350. ft.hr = m_pICollection->SaveChanges(&lRet);
  351. if (ft.HrFailed()) {
  352. ft.LogError( VSS_ERROR_SAVING_CHANGES, VSSDBG_GEN << ft.hr );
  353. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in saving the changes. hr = 0x%08lx", ft.hr);
  354. }
  355. }
  356. VSS_STANDARD_CATCH(ft)
  357. return ft.hr;
  358. }
  359. /////////////////////////////////////////////////////////////////////////////
  360. // Implementation of CVssCOMCatalogCollection
  361. HRESULT CVssCOMCatalogObject::InsertInto(
  362. IN CVssCOMCatalogCollection& collection
  363. )
  364. {
  365. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogObject::InsertInto" );
  366. try
  367. {
  368. // Begin initialization
  369. m_bInitialized = false;
  370. m_pIObject = NULL;
  371. m_pIParentCollection = NULL;
  372. m_lIndex = -1;
  373. // Get the collection object
  374. CComPtr<ICatalogCollection> pIParentCollection = collection.GetInterface();
  375. if (pIParentCollection == NULL)
  376. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Collection object not initialized");
  377. // Get the instance of the new object
  378. CComPtr<IDispatch> pIDisp;
  379. ft.hr = pIParentCollection->Add(&pIDisp);
  380. if (ft.HrFailed()) {
  381. ft.LogError( VSS_ERROR_INSERT_INTO, VSSDBG_GEN << ft.hr );
  382. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in adding the catalog object. hr = 0x%08lx", ft.hr);
  383. }
  384. BS_ASSERT(pIDisp);
  385. // Convert to ICatalogObject
  386. BS_ASSERT(m_pIObject == NULL);
  387. ft.hr = pIDisp->SafeQI(ICatalogObject, &m_pIObject);
  388. if (ft.HrFailed())
  389. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogObject. hr = 0x%08lx", ft.hr);
  390. // End initialization
  391. m_pIParentCollection = pIParentCollection;
  392. m_bInitialized = true;
  393. }
  394. VSS_STANDARD_CATCH(ft)
  395. return ft.hr;
  396. }
  397. //
  398. // Disclaimer: this method assumes that the collection is already populated
  399. //
  400. // S_FALSE means object not found
  401. //
  402. HRESULT CVssCOMCatalogObject::AttachByName(
  403. IN CVssCOMCatalogCollection& collection,
  404. IN const WCHAR wszName[],
  405. IN const WCHAR wszPropertyName[] /* = NULL */
  406. )
  407. {
  408. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogObject::AttachByName" );
  409. try
  410. {
  411. // Begin initialization
  412. m_bInitialized = false;
  413. m_pIObject = NULL;
  414. m_pIParentCollection = NULL;
  415. m_lIndex = -1;
  416. // Check if Object type is valid
  417. if ((m_eType <= 0) && (m_eType >= VSS_COM_COLLECTIONS_COUNT))
  418. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Invalid object type");
  419. if (m_eType != collection.GetType())
  420. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Object type doesn't match with collection type");
  421. // Get the collection object
  422. CComPtr<ICatalogCollection> pIParentCollection = collection.GetInterface();
  423. if (pIParentCollection == NULL)
  424. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Collection object not initialized.");
  425. // Get the name of the property used as a key
  426. CComBSTR bstrPropertyName;
  427. if (wszPropertyName == NULL)
  428. bstrPropertyName = g_VsCOMCollectionsArray[m_eType].wszDefaultKey;
  429. else
  430. bstrPropertyName = wszPropertyName;
  431. // Get the number of objects in the collection
  432. LONG lCount = -1;
  433. ft.hr = pIParentCollection->get_Count(&lCount);
  434. if (ft.HrFailed())
  435. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying the number of elements. hr = 0x%08lx", ft.hr);
  436. if (lCount == 0)
  437. ft.Trace(VSSDBG_GEN, L"Empty collection");
  438. CComVariant varObjectName = wszName;
  439. CComVariant variant;
  440. CComPtr<IDispatch> pIDisp;
  441. CComPtr<ICatalogObject> pIObject;
  442. for(LONG lIndex = 0; lIndex < lCount; lIndex++)
  443. {
  444. // Release previous references
  445. pIDisp = pIObject = NULL;
  446. // Get next item
  447. ft.hr = pIParentCollection->get_Item(lIndex, &pIDisp);
  448. if (ft.HrFailed())
  449. ft.Throw(VSSDBG_GEN, E_UNEXPECTED,
  450. L"Failure in getting object with index %ld. hr = 0x%08lx", lIndex, ft.hr);
  451. // Convert it to ICatalogObject
  452. ft.hr = pIDisp->SafeQI(ICatalogObject, &pIObject);
  453. if (ft.HrFailed())
  454. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogObject. hr = 0x%08lx", ft.hr);
  455. variant.Clear(); // do not forget to release resources before get_XXX !
  456. ft.hr = pIObject->get_Value(bstrPropertyName, &variant);
  457. if (ft.HrFailed())
  458. ft.Throw(VSSDBG_GEN, E_UNEXPECTED,
  459. L"Failure in getting value for the object key with index %ld. hr = 0x%08lx", lIndex, ft.hr);
  460. if (varObjectName == variant)
  461. {
  462. m_bInitialized = TRUE;
  463. m_lIndex = lIndex;
  464. m_pIParentCollection = pIParentCollection;
  465. m_pIObject = pIObject;
  466. break;
  467. }
  468. }
  469. if (!m_bInitialized)
  470. ft.hr = S_FALSE; // Object not found!
  471. }
  472. VSS_STANDARD_CATCH(ft)
  473. return ft.hr;
  474. }