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.

591 lines
20 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 <vs_sec.hxx>
  34. #include "vssmsg.h"
  35. #include "vs_inc.hxx"
  36. #include "vs_idl.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.hr = m_pICatalog.CoCreateInstance(__uuidof(COMAdminCatalog));
  98. if (ft.HrFailed()) {
  99. ft.LogError( VSS_ERROR_CREATING_COMPLUS_ADMIN_CATALOG, VSSDBG_GEN << ft.hr );
  100. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Error creating the COMAdminCatalog instance hr = 0x%08lx", ft.hr);
  101. }
  102. // Getting the application name
  103. m_bstrAppName = pwszAppName;
  104. if (!m_bstrAppName)
  105. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  106. // End initializing
  107. m_bInitialized = true;
  108. }
  109. VSS_STANDARD_CATCH(ft)
  110. return ft.hr;
  111. }
  112. HRESULT CVssCOMAdminCatalog::InstallComponent(
  113. IN const WCHAR* pwszDllName,
  114. IN const WCHAR* pwszTlbName,
  115. IN const WCHAR* pwszProxyStubName
  116. )
  117. {
  118. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMAdminCatalog::InstallComponent" );
  119. try
  120. {
  121. // Test if initialized
  122. if (!m_bInitialized)
  123. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized");
  124. // Testing arguments
  125. if (pwszDllName == NULL || pwszDllName[0] == L'\0')
  126. ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"NULL or empty paths");
  127. CComBSTR bstrAppName = (LPWSTR)m_bstrAppName;
  128. if ((LPWSTR)bstrAppName == NULL)
  129. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  130. CComBSTR bstrDllName = pwszDllName;
  131. if ((LPWSTR)bstrDllName == NULL)
  132. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  133. CComBSTR bstrTlbName = pwszTlbName? pwszTlbName: L"";
  134. if ((LPWSTR)bstrTlbName == NULL)
  135. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  136. CComBSTR bstrProxyStubName = pwszProxyStubName? pwszProxyStubName: L"";
  137. if ((LPWSTR)bstrProxyStubName == NULL)
  138. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  139. // Install event class for this application
  140. ft.hr = m_pICatalog->InstallComponent(
  141. bstrAppName,
  142. bstrDllName,
  143. bstrTlbName,
  144. bstrProxyStubName
  145. );
  146. if (ft.HrFailed()) {
  147. ft.TraceComError();
  148. ft.LogError( VSS_ERROR_INSTALL_COMPONENT, VSSDBG_GEN << bstrDllName << bstrAppName << ft.hr );
  149. ft.Throw(VSSDBG_GEN, ft.hr, L"Installing the component failed");
  150. }
  151. }
  152. VSS_STANDARD_CATCH(ft)
  153. return ft.hr;
  154. }
  155. HRESULT CVssCOMAdminCatalog::CreateServiceForApplication(
  156. IN const WCHAR* pwszServiceName
  157. )
  158. {
  159. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMAdminCatalog::CreateServiceForApplication" );
  160. try
  161. {
  162. // Test if initialized
  163. if (!m_bInitialized)
  164. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized");
  165. CComBSTR bstrAppName = (LPWSTR)m_bstrAppName;
  166. if ((LPWSTR)bstrAppName == NULL)
  167. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  168. CComBSTR bstrSvcName = pwszServiceName;
  169. if ((LPWSTR)bstrSvcName == NULL)
  170. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  171. CComBSTR bstrStartType = L"SERVICE_DEMAND_START";
  172. if ((LPWSTR)bstrStartType == NULL)
  173. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  174. CComBSTR bstrErrorControl = L"SERVICE_ERROR_IGNORE";
  175. if ((LPWSTR)bstrErrorControl == NULL)
  176. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  177. CComBSTR bstrRunAs = L"LocalSystem";
  178. if ((LPWSTR)bstrRunAs == NULL)
  179. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  180. CComBSTR bstrPassword = L"";
  181. if ((LPWSTR)bstrRunAs == NULL)
  182. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  183. #ifdef _DEBUG
  184. VARIANT_BOOL vboolDesktopOK = VARIANT_TRUE;
  185. #else
  186. VARIANT_BOOL vboolDesktopOK = VARIANT_FALSE;
  187. #endif
  188. ft.Trace(VSSDBG_GEN,
  189. L"Calling CreateServiceForApplicationStrings(%s, %s, %s, %s, %s, %s, %s, %s)",
  190. bstrAppName,
  191. bstrSvcName,
  192. bstrStartType,
  193. bstrErrorControl,
  194. NULL,
  195. bstrRunAs,
  196. bstrPassword,
  197. vboolDesktopOK == VARIANT_TRUE? L"TRUE": L"FALSE"
  198. );
  199. // Install event class for this application
  200. ft.hr = m_pICatalog->CreateServiceForApplication(
  201. m_bstrAppName,
  202. bstrSvcName,
  203. bstrStartType,
  204. bstrErrorControl,
  205. NULL,
  206. bstrRunAs,
  207. bstrPassword,
  208. vboolDesktopOK
  209. );
  210. if (ft.HrFailed()) {
  211. ft.TraceComError();
  212. ft.LogError( VSS_ERROR_CREATE_SERVICE_FOR_APPLICATION, VSSDBG_GEN << bstrSvcName << m_bstrAppName << ft.hr );
  213. ft.Throw(VSSDBG_GEN, ft.hr, L"Installing the component failed");
  214. }
  215. }
  216. VSS_STANDARD_CATCH(ft)
  217. return ft.hr;
  218. }
  219. /////////////////////////////////////////////////////////////////////////////
  220. // Implementation of CVssCOMCatalogCollection
  221. HRESULT CVssCOMCatalogCollection::Attach(
  222. IN CVssCOMAdminCatalog& catalog
  223. )
  224. {
  225. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::Attach_ToCatalog" );
  226. try
  227. {
  228. // Begin intializing
  229. m_bInitialized = false;
  230. m_pICollection = NULL;
  231. // Check if Collection type is valid
  232. if ((m_eType <= 0) || (m_eType >= VSS_COM_COLLECTIONS_COUNT))
  233. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Invalid collection type");
  234. // Converting collection name into BSTR
  235. CComBSTR bstrCollectionName = g_VsCOMCollectionsArray[m_eType].wszName;
  236. if (!bstrCollectionName)
  237. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  238. // Get the catalog interface
  239. CComPtr<ICOMAdminCatalog2> pICatalog = catalog.GetInterface();
  240. if (pICatalog == NULL) {
  241. BS_ASSERT(false);
  242. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog object not initialized.");
  243. }
  244. // Get the collection object
  245. CComPtr<IDispatch> pIDisp;
  246. ft.hr = pICatalog->GetCollection(bstrCollectionName, &pIDisp);
  247. if (ft.HrFailed()) {
  248. ft.LogError( VSS_ERROR_GETTING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr );
  249. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting the collection. hr = 0x%08lx", ft.hr);
  250. }
  251. BS_ASSERT(pIDisp);
  252. // Convert to ICatalogCollection
  253. CComPtr<ICatalogCollection> pICollection;
  254. ft.hr = pIDisp->SafeQI(ICatalogCollection, &pICollection);
  255. if (ft.HrFailed())
  256. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogCollection. hr = 0x%08lx", ft.hr);
  257. // Populate the collection
  258. ft.hr = pICollection->Populate();
  259. if (ft.HrFailed()) {
  260. ft.LogError( VSS_ERROR_POPULATING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr );
  261. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in populating the collection object. hr = 0x%08lx", ft.hr);
  262. }
  263. // End intializing
  264. m_pICollection = pICollection;
  265. m_bInitialized = true;
  266. }
  267. VSS_STANDARD_CATCH(ft)
  268. return ft.hr;
  269. }
  270. HRESULT CVssCOMCatalogCollection::Attach(
  271. IN CVssCOMCatalogObject& parentObject
  272. )
  273. {
  274. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::Attach_ToParentCollection" );
  275. try
  276. {
  277. // Begin intializing
  278. m_bInitialized = false;
  279. m_pICollection = NULL;
  280. // Check if Collection type is valid
  281. if ((m_eType <= 0) || (m_eType >= VSS_COM_COLLECTIONS_COUNT))
  282. ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"Invalid collection type");
  283. // Converting collection name into BSTR
  284. CComBSTR bstrCollectionName = g_VsCOMCollectionsArray[m_eType].wszName;
  285. if (!bstrCollectionName)
  286. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Memory allocation error");
  287. // Get the parent object interface
  288. CComPtr<ICatalogObject> pIParentObject = parentObject.GetInterface();
  289. if (pIParentObject == NULL) {
  290. BS_ASSERT(false);
  291. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Parent object not initialized yet.");
  292. }
  293. // Get the Key that uniquely identifies the parent object in the grand parent collection
  294. CComVariant variant;
  295. // Beware to not leave variant resources before get_Key call!
  296. ft.hr = pIParentObject->get_Key(&variant);
  297. if (ft.HrFailed()) {
  298. ft.LogError( VSS_ERROR_GET_COLLECTION_KEY, VSSDBG_GEN << ft.hr );
  299. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting object key. hr = 0x%08lx", ft.hr);
  300. }
  301. // Get the grand parent collection interface
  302. CComPtr<ICatalogCollection> pIGrandParentCollection = parentObject.GetParentInterface();
  303. if (pIGrandParentCollection == NULL) {
  304. BS_ASSERT(false);
  305. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Parent object not initialized.");
  306. }
  307. // Get the collection object
  308. CComPtr<IDispatch> pIDisp;
  309. ft.hr = pIGrandParentCollection->GetCollection(bstrCollectionName, variant, &pIDisp);
  310. if (ft.HrFailed()) {
  311. ft.LogError( VSS_ERROR_GET_COLLECTION_FROM_PARENT, VSSDBG_GEN << bstrCollectionName << ft.hr );
  312. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in getting collection. hr = 0x%08lx", ft.hr);
  313. }
  314. BS_ASSERT(pIDisp);
  315. // Convert to ICatalogCollection
  316. ICatalogCollection* pICollection;
  317. ft.hr = pIDisp->SafeQI(ICatalogCollection, &pICollection);
  318. if (ft.HrFailed())
  319. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogCollection. hr = 0x%08lx", ft.hr);
  320. BS_ASSERT(pICollection);
  321. m_pICollection.Attach(pICollection);
  322. // Populate the collection
  323. ft.hr = m_pICollection->Populate();
  324. if (ft.HrFailed()) {
  325. ft.LogError( VSS_ERROR_POPULATING_COLLECTION, VSSDBG_GEN << bstrCollectionName << ft.hr );
  326. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in populating the collection object. hr = 0x%08lx", ft.hr);
  327. }
  328. // End intializing
  329. m_bInitialized = true;
  330. }
  331. VSS_STANDARD_CATCH(ft)
  332. return ft.hr;
  333. }
  334. HRESULT CVssCOMCatalogCollection::SaveChanges()
  335. {
  336. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogCollection::SaveChanges" );
  337. try
  338. {
  339. // Test if initialized
  340. if (!m_bInitialized)
  341. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Catalog not initialized");
  342. // Save changes
  343. LONG lRet = 0;
  344. ft.hr = m_pICollection->SaveChanges(&lRet);
  345. if (ft.HrFailed()) {
  346. ft.LogError( VSS_ERROR_SAVING_CHANGES, VSSDBG_GEN << ft.hr );
  347. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in saving the changes. hr = 0x%08lx", ft.hr);
  348. }
  349. }
  350. VSS_STANDARD_CATCH(ft)
  351. return ft.hr;
  352. }
  353. /////////////////////////////////////////////////////////////////////////////
  354. // Implementation of CVssCOMCatalogCollection
  355. HRESULT CVssCOMCatalogObject::InsertInto(
  356. IN CVssCOMCatalogCollection& collection
  357. )
  358. {
  359. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogObject::InsertInto" );
  360. try
  361. {
  362. // Begin initialization
  363. m_bInitialized = false;
  364. m_pIObject = NULL;
  365. m_pIParentCollection = NULL;
  366. m_lIndex = -1;
  367. // Get the collection object
  368. CComPtr<ICatalogCollection> pIParentCollection = collection.GetInterface();
  369. if (pIParentCollection == NULL)
  370. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Collection object not initialized");
  371. // Get the instance of the new object
  372. CComPtr<IDispatch> pIDisp;
  373. ft.hr = pIParentCollection->Add(&pIDisp);
  374. if (ft.HrFailed()) {
  375. ft.LogError( VSS_ERROR_INSERT_INTO, VSSDBG_GEN << ft.hr );
  376. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in adding the catalog object. hr = 0x%08lx", ft.hr);
  377. }
  378. BS_ASSERT(pIDisp);
  379. // Convert to ICatalogObject
  380. BS_ASSERT(m_pIObject == NULL);
  381. ft.hr = pIDisp->SafeQI(ICatalogObject, &m_pIObject);
  382. if (ft.HrFailed())
  383. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogObject. hr = 0x%08lx", ft.hr);
  384. // End initialization
  385. m_pIParentCollection = pIParentCollection;
  386. m_bInitialized = true;
  387. }
  388. VSS_STANDARD_CATCH(ft)
  389. return ft.hr;
  390. }
  391. //
  392. // Disclaimer: this method assumes that the collection is already populated
  393. //
  394. // S_FALSE means object not found
  395. //
  396. HRESULT CVssCOMCatalogObject::AttachByName(
  397. IN CVssCOMCatalogCollection& collection,
  398. IN const WCHAR wszName[],
  399. IN const WCHAR wszPropertyName[] /* = NULL */
  400. )
  401. {
  402. CVssFunctionTracer ft( VSSDBG_GEN, L"CVssCOMCatalogObject::AttachByName" );
  403. try
  404. {
  405. // Begin initialization
  406. m_bInitialized = false;
  407. m_pIObject = NULL;
  408. m_pIParentCollection = NULL;
  409. m_lIndex = -1;
  410. // Check if Object type is valid
  411. if ((m_eType <= 0) && (m_eType >= VSS_COM_COLLECTIONS_COUNT))
  412. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Invalid object type");
  413. if (m_eType != collection.GetType())
  414. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Object type doesn't match with collection type");
  415. // Get the collection object
  416. CComPtr<ICatalogCollection> pIParentCollection = collection.GetInterface();
  417. if (pIParentCollection == NULL)
  418. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Collection object not initialized.");
  419. // Get the name of the property used as a key
  420. CComBSTR bstrPropertyName;
  421. if (wszPropertyName == NULL)
  422. bstrPropertyName = g_VsCOMCollectionsArray[m_eType].wszDefaultKey;
  423. else
  424. bstrPropertyName = wszPropertyName;
  425. // Get the number of objects in the collection
  426. LONG lCount = -1;
  427. ft.hr = pIParentCollection->get_Count(&lCount);
  428. if (ft.HrFailed())
  429. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying the number of elements. hr = 0x%08lx", ft.hr);
  430. if (lCount == 0)
  431. ft.Trace(VSSDBG_GEN, L"Empty collection");
  432. CComVariant varObjectName = wszName;
  433. CComVariant variant;
  434. CComPtr<IDispatch> pIDisp;
  435. CComPtr<ICatalogObject> pIObject;
  436. for(LONG lIndex = 0; lIndex < lCount; lIndex++)
  437. {
  438. // Release previous references
  439. pIDisp = pIObject = NULL;
  440. // Get next item
  441. ft.hr = pIParentCollection->get_Item(lIndex, &pIDisp);
  442. if (ft.HrFailed())
  443. ft.Throw(VSSDBG_GEN, E_UNEXPECTED,
  444. L"Failure in getting object with index %ld. hr = 0x%08lx", lIndex, ft.hr);
  445. // Convert it to ICatalogObject
  446. ft.hr = pIDisp->SafeQI(ICatalogObject, &pIObject);
  447. if (ft.HrFailed())
  448. ft.Throw(VSSDBG_GEN, E_UNEXPECTED, L"Failure in querying ICatalogObject. hr = 0x%08lx", ft.hr);
  449. variant.Clear(); // do not forget to release resources before get_XXX !
  450. ft.hr = pIObject->get_Value(bstrPropertyName, &variant);
  451. if (ft.HrFailed())
  452. ft.Throw(VSSDBG_GEN, E_UNEXPECTED,
  453. L"Failure in getting value for the object key with index %ld. hr = 0x%08lx", lIndex, ft.hr);
  454. if (varObjectName == variant)
  455. {
  456. m_bInitialized = TRUE;
  457. m_lIndex = lIndex;
  458. m_pIParentCollection = pIParentCollection;
  459. m_pIObject = pIObject;
  460. break;
  461. }
  462. }
  463. if (!m_bInitialized)
  464. ft.hr = S_FALSE; // Object not found!
  465. }
  466. VSS_STANDARD_CATCH(ft)
  467. return ft.hr;
  468. }