Source code of Windows XP (NT5)
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.

1006 lines
25 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1997 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ExtObj.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CExtObject class, which implements the
  10. // extension interfaces required by a Microsoft Windows NT Cluster
  11. // Administrator Extension DLL.
  12. //
  13. // Author:
  14. // David Potter (davidp) August 29, 1996
  15. //
  16. // Revision History:
  17. //
  18. // Notes:
  19. //
  20. /////////////////////////////////////////////////////////////////////////////
  21. #include "stdafx.h"
  22. #include "IISClEx3.h"
  23. #include "ExtObj.h"
  24. #include "Iis.h"
  25. /////////////////////////////////////////////////////////////////////////////
  26. // Global Variables
  27. /////////////////////////////////////////////////////////////////////////////
  28. const WCHAR g_wszResourceTypeNames[] =
  29. RESTYPE_NAME_IIS_VIRTUAL_ROOT L"\0"
  30. ;
  31. const DWORD g_cchResourceTypeNames = sizeof(g_wszResourceTypeNames) / sizeof(WCHAR);
  32. static CRuntimeClass * g_rgprtcPSIISPages[] = {
  33. RUNTIME_CLASS(CIISVirtualRootParamsPage),
  34. NULL
  35. };
  36. static CRuntimeClass ** g_rgpprtcPSPages[] = {
  37. g_rgprtcPSIISPages
  38. };
  39. // Wizard pages and property sheet pages are the same.
  40. static CRuntimeClass ** g_rgpprtcWizPages[] = {
  41. g_rgprtcPSIISPages
  42. };
  43. /////////////////////////////////////////////////////////////////////////////
  44. // CExtObject
  45. /////////////////////////////////////////////////////////////////////////////
  46. /////////////////////////////////////////////////////////////////////////////
  47. //++
  48. //
  49. // CExtObject::CExtObject
  50. //
  51. // Routine Description:
  52. // Default constructor.
  53. //
  54. // Arguments:
  55. // None.
  56. //
  57. // Return Value:
  58. // None.
  59. //
  60. //--
  61. /////////////////////////////////////////////////////////////////////////////
  62. CExtObject::CExtObject(void)
  63. {
  64. m_piData = NULL;
  65. m_piWizardCallback = NULL;
  66. m_bWizard = FALSE;
  67. m_istrResTypeName = 0;
  68. m_hcluster = NULL;
  69. m_lcid = NULL;
  70. m_hfont = NULL;
  71. m_hicon = NULL;
  72. } //*** CExtObject::CExtObject()
  73. /////////////////////////////////////////////////////////////////////////////
  74. //++
  75. //
  76. // CExtObject::~CExtObject
  77. //
  78. // Routine Description:
  79. // Destructor.
  80. //
  81. // Arguments:
  82. // None.
  83. //
  84. // Return Value:
  85. // None.
  86. //
  87. //--
  88. /////////////////////////////////////////////////////////////////////////////
  89. CExtObject::~CExtObject(void)
  90. {
  91. // Release the data interface.
  92. if (PiData() != NULL)
  93. {
  94. PiData()->Release();
  95. m_piData = NULL;
  96. } // if: we have a data interface pointer
  97. // Release the wizard callback interface.
  98. if (PiWizardCallback() != NULL)
  99. {
  100. PiWizardCallback()->Release();
  101. m_piWizardCallback = NULL;
  102. } // if: we have a wizard callback interface pointer
  103. // Delete the pages.
  104. {
  105. POSITION pos;
  106. pos = Lpg().GetHeadPosition();
  107. while (pos != NULL)
  108. delete Lpg().GetNext(pos);
  109. } // Delete the pages
  110. } //*** CExtObject::~CExtObject()
  111. /////////////////////////////////////////////////////////////////////////////
  112. // ISupportErrorInfo Implementation
  113. /////////////////////////////////////////////////////////////////////////////
  114. //++
  115. //
  116. // CExtObject::InterfaceSupportsErrorInfo (ISupportErrorInfo)
  117. //
  118. // Routine Description:
  119. // Indicates whether an interface suportes the IErrorInfo interface.
  120. // This interface is provided by ATL.
  121. //
  122. // Arguments:
  123. // riid Interface ID.
  124. //
  125. // Return Value:
  126. // S_OK Interface supports IErrorInfo.
  127. // S_FALSE Interface does not support IErrorInfo.
  128. //
  129. //--
  130. /////////////////////////////////////////////////////////////////////////////
  131. STDMETHODIMP CExtObject::InterfaceSupportsErrorInfo(REFIID riid)
  132. {
  133. static const IID * rgiid[] =
  134. {
  135. &IID_IWEExtendPropertySheet,
  136. &IID_IWEExtendWizard,
  137. #ifdef _DEMO_CTX_MENUS
  138. &IID_IWEExtendContextMenu,
  139. #endif
  140. };
  141. int iiid;
  142. for (iiid = 0 ; iiid < sizeof(rgiid) / sizeof(rgiid[0]) ; iiid++)
  143. {
  144. if (InlineIsEqualGUID(*rgiid[iiid], riid))
  145. return S_OK;
  146. }
  147. return S_FALSE;
  148. } //*** CExtObject::InterfaceSupportsErrorInfo()
  149. /////////////////////////////////////////////////////////////////////////////
  150. // IWEExtendPropertySheet Implementation
  151. /////////////////////////////////////////////////////////////////////////////
  152. //++
  153. //
  154. // CExtObject::CreatePropertySheetPages (IWEExtendPropertySheet)
  155. //
  156. // Routine Description:
  157. // Create property sheet pages and add them to the sheet.
  158. //
  159. // Arguments:
  160. // piData IUnkown pointer from which to obtain interfaces
  161. // for obtaining data describing the object for
  162. // which the sheet is being displayed.
  163. // piCallback Pointer to an IWCPropertySheetCallback interface
  164. // for adding pages to the sheet.
  165. //
  166. // Return Value:
  167. // NOERROR Pages added successfully.
  168. // E_INVALIDARG Invalid arguments to the function.
  169. // E_OUTOFMEMORY Error allocating memory.
  170. // E_FAIL Error creating a page.
  171. // E_NOTIMPL Not implemented for this type of data.
  172. // Any error codes from IDataObject::GetData() (through HrSaveData()).
  173. //
  174. //--
  175. /////////////////////////////////////////////////////////////////////////////
  176. STDMETHODIMP CExtObject::CreatePropertySheetPages(
  177. IN IUnknown * piData,
  178. IN IWCPropertySheetCallback * piCallback
  179. )
  180. {
  181. HRESULT hr = NOERROR;
  182. HPROPSHEETPAGE hpage = NULL;
  183. CException exc(FALSE /*bAutoDelete*/);
  184. int irtc;
  185. CBasePropertyPage * ppage;
  186. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  187. // Validate the parameters.
  188. if ((piData == NULL) || (piCallback == NULL))
  189. return E_INVALIDARG;
  190. try
  191. {
  192. // Get info about displaying UI.
  193. hr = HrGetUIInfo(piData);
  194. if (hr != NOERROR)
  195. throw &exc;
  196. // Save the data.
  197. hr = HrSaveData(piData);
  198. if (hr != NOERROR)
  199. throw &exc;
  200. // Delete any previous pages.
  201. {
  202. POSITION pos;
  203. pos = Lpg().GetHeadPosition();
  204. while (pos != NULL)
  205. delete Lpg().GetNext(pos);
  206. Lpg().RemoveAll();
  207. } // Delete any previous pages
  208. // Add each page for this type of resource.
  209. for (irtc = 0 ; g_rgpprtcPSPages[IstrResTypeName()][irtc] != NULL ; irtc++)
  210. {
  211. // Create the property pages.
  212. ppage = (CBasePropertyPage *) g_rgpprtcPSPages[IstrResTypeName()][irtc]->CreateObject();
  213. ASSERT(ppage->IsKindOf(g_rgpprtcPSPages[IstrResTypeName()][irtc]));
  214. // Add it to the list.
  215. Lpg().AddTail(ppage);
  216. // Initialize the property page.
  217. if (!ppage->BInit(this))
  218. throw &exc;
  219. // Create the page.
  220. hpage = ::CreatePropertySheetPage(&ppage->m_psp);
  221. if (hpage == NULL)
  222. throw &exc;
  223. // Save the hpage in the page itself.
  224. ppage->SetHpage(hpage);
  225. // Add it to the property sheet.
  226. hr = piCallback->AddPropertySheetPage((LONG *) hpage);
  227. if (hr != NOERROR)
  228. throw &exc;
  229. } // for: each page for the type of resource
  230. } // try
  231. catch (CMemoryException * pme)
  232. {
  233. TRACE(_T("CExtObject::CreatePropetySheetPages: Failed to add property page\n"));
  234. pme->Delete();
  235. hr = E_OUTOFMEMORY;
  236. } // catch: anything
  237. catch (CException * pe)
  238. {
  239. TRACE(_T("CExtObject::CreatePropetySheetPages: Failed to add property page\n"));
  240. pe->Delete();
  241. if (hr == NOERROR)
  242. hr = E_FAIL;
  243. } // catch: anything
  244. if (hr != NOERROR)
  245. {
  246. if (hpage != NULL)
  247. ::DestroyPropertySheetPage(hpage);
  248. piData->Release();
  249. m_piData = NULL;
  250. } // if: error occurred
  251. piCallback->Release();
  252. return hr;
  253. } //*** CExtObject::CreatePropertySheetPages()
  254. /////////////////////////////////////////////////////////////////////////////
  255. // IWEExtendWizard Implementation
  256. /////////////////////////////////////////////////////////////////////////////
  257. //++
  258. //
  259. // CExtObject::CreateWizardPages (IWEExtendWizard)
  260. //
  261. // Routine Description:
  262. // Create property sheet pages and add them to the wizard.
  263. //
  264. // Arguments:
  265. // piData IUnkown pointer from which to obtain interfaces
  266. // for obtaining data describing the object for
  267. // which the wizard is being displayed.
  268. // piCallback Pointer to an IWCPropertySheetCallback interface
  269. // for adding pages to the sheet.
  270. //
  271. // Return Value:
  272. // NOERROR Pages added successfully.
  273. // E_INVALIDARG Invalid arguments to the function.
  274. // E_OUTOFMEMORY Error allocating memory.
  275. // E_FAIL Error creating a page.
  276. // E_NOTIMPL Not implemented for this type of data.
  277. // Any error codes from IDataObject::GetData() (through HrSaveData()).
  278. //
  279. //--
  280. /////////////////////////////////////////////////////////////////////////////
  281. STDMETHODIMP CExtObject::CreateWizardPages(
  282. IN IUnknown * piData,
  283. IN IWCWizardCallback * piCallback
  284. )
  285. {
  286. HRESULT hr = NOERROR;
  287. HPROPSHEETPAGE hpage = NULL;
  288. CException exc(FALSE /*bAutoDelete*/);
  289. int irtc;
  290. CBasePropertyPage * ppage;
  291. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  292. // Validate the parameters.
  293. if ((piData == NULL) || (piCallback == NULL))
  294. return E_INVALIDARG;
  295. try
  296. {
  297. // Get info about displaying UI.
  298. hr = HrGetUIInfo(piData);
  299. if (hr != NOERROR)
  300. throw &exc;
  301. // Save the data.
  302. hr = HrSaveData(piData);
  303. if (hr != NOERROR)
  304. throw &exc;
  305. // Delete any previous pages.
  306. {
  307. POSITION pos;
  308. pos = Lpg().GetHeadPosition();
  309. while (pos != NULL)
  310. delete Lpg().GetNext(pos);
  311. Lpg().RemoveAll();
  312. } // Delete any previous pages
  313. m_piWizardCallback = piCallback;
  314. m_bWizard = TRUE;
  315. // Add each page for this type of resource.
  316. for (irtc = 0 ; g_rgpprtcWizPages[IstrResTypeName()][irtc] != NULL ; irtc++)
  317. {
  318. // Create the property pages.
  319. ppage = (CBasePropertyPage *) g_rgpprtcWizPages[IstrResTypeName()][irtc]->CreateObject();
  320. ASSERT(ppage->IsKindOf(g_rgpprtcWizPages[IstrResTypeName()][irtc]));
  321. // Add it to the list.
  322. Lpg().AddTail(ppage);
  323. // Initialize the property page.
  324. if (!ppage->BInit(this))
  325. throw &exc;
  326. // Create the page.
  327. hpage = ::CreatePropertySheetPage(&ppage->m_psp);
  328. if (hpage == NULL)
  329. throw &exc;
  330. // Save the hpage in the page itself.
  331. ppage->SetHpage(hpage);
  332. // Add it to the property sheet.
  333. hr = piCallback->AddWizardPage((LONG *) hpage);
  334. if (hr != NOERROR)
  335. throw &exc;
  336. } // for: each page for the type of resource
  337. } // try
  338. catch (CMemoryException * pme)
  339. {
  340. TRACE(_T("CExtObject::CreatePropetySheetPages: Failed to add wizard page\n"));
  341. pme->Delete();
  342. hr = E_OUTOFMEMORY;
  343. } // catch: anything
  344. catch (CException * pe)
  345. {
  346. TRACE(_T("CExtObject::CreatePropetySheetPages: Failed to add wizard page\n"));
  347. pe->Delete();
  348. if (hr == NOERROR)
  349. hr = E_FAIL;
  350. } // catch: anything
  351. if (hr != NOERROR)
  352. {
  353. if (hpage != NULL)
  354. ::DestroyPropertySheetPage(hpage);
  355. piCallback->Release();
  356. piData->Release();
  357. m_piData = NULL;
  358. } // if: error occurred
  359. return hr;
  360. } //*** CExtObject::CreateWizardPages()
  361. #ifdef _DEMO_CTX_MENUS
  362. /////////////////////////////////////////////////////////////////////////////
  363. // IWEExtendContextMenu Implementation
  364. /////////////////////////////////////////////////////////////////////////////
  365. //++
  366. //
  367. // CExtObject::AddContextMenuItems (IWEExtendContextMenu)
  368. //
  369. // Routine Description:
  370. // Add items to a context menu.
  371. //
  372. // Arguments:
  373. // piData IUnkown pointer from which to obtain interfaces
  374. // for obtaining data describing the object for
  375. // which the context menu is being displayed.
  376. // piCallback Pointer to an IWCContextMenuCallback interface
  377. // for adding menu items to the context menu.
  378. //
  379. // Return Value:
  380. // NOERROR Pages added successfully.
  381. // E_INVALIDARG Invalid arguments to the function.
  382. // E_FAIL Error adding context menu item.
  383. // E_NOTIMPL Not implemented for this type of data.
  384. // Any error codes returned by HrSaveData() or IWCContextMenuCallback::
  385. // AddExtensionMenuItem().
  386. //
  387. //--
  388. /////////////////////////////////////////////////////////////////////////////
  389. STDMETHODIMP CExtObject::AddContextMenuItems(
  390. IN IUnknown * piData,
  391. IN IWCContextMenuCallback * piCallback
  392. )
  393. {
  394. HRESULT hr = NOERROR;
  395. CException exc(FALSE /*bAutoDelete*/);
  396. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  397. // Validate the parameters.
  398. if ((piData == NULL) || (piCallback == NULL))
  399. return E_INVALIDARG;
  400. try
  401. {
  402. // Save the data.
  403. hr = HrSaveData(piData);
  404. if (hr != NOERROR)
  405. throw &exc;
  406. // Add menu items specific to this resource type.
  407. {
  408. ULONG iCommandID;
  409. LPWSTR pwsz = g_rgpwszContextMenuItems[IstrResTypeName()];
  410. LPWSTR pwszName;
  411. LPWSTR pwszStatusBarText;
  412. for (iCommandID = 0 ; *pwsz != L'\0' ; iCommandID++)
  413. {
  414. pwszName = pwsz;
  415. pwszStatusBarText = pwszName + (::wcslen(pwszName) + 1);
  416. hr = piCallback->AddExtensionMenuItem(
  417. pwszName, // lpszName
  418. pwszStatusBarText, // lpszStatusBarText
  419. iCommandID, // lCommandID
  420. 0, // lSubCommandID
  421. 0 // uFlags
  422. );
  423. if (hr != NOERROR)
  424. throw &exc;
  425. pwsz = pwszStatusBarText + (::wcslen(pwszStatusBarText) + 1);
  426. } // while: more menu items to add
  427. } // Add menu items specific to this resource type
  428. } // try
  429. catch (CException * pe)
  430. {
  431. TRACE(_T("CExtObject::CreatePropetySheetPages: Failed to add context menu item\n"));
  432. pe->Delete();
  433. if (hr == NOERROR)
  434. hr = E_FAIL;
  435. } // catch: anything
  436. if (hr != NOERROR)
  437. {
  438. piData->Release();
  439. m_piData = NULL;
  440. } // if: error occurred
  441. piCallback->Release();
  442. return hr;
  443. } //*** CExtObject::AddContextMenuItems()
  444. /////////////////////////////////////////////////////////////////////////////
  445. // IWEInvokeCommand Implementation
  446. /////////////////////////////////////////////////////////////////////////////
  447. //++
  448. //
  449. // CExtObject::InvokeCommand (IWEInvokeCommand)
  450. //
  451. // Routine Description:
  452. // Invoke a command offered by a context menu.
  453. //
  454. // Arguments:
  455. // lCommandID ID of the menu item to execute. This is the same
  456. // ID passed to the IWCContextMenuCallback
  457. // ::AddExtensionMenuItem() method.
  458. // piData IUnkown pointer from which to obtain interfaces
  459. // for obtaining data describing the object for
  460. // which the command is to be invoked.
  461. //
  462. // Return Value:
  463. // NOERROR Command invoked successfully.
  464. // E_INVALIDARG Invalid arguments to the function.
  465. // E_OUTOFMEMORY Error allocating memory.
  466. // E_NOTIMPL Not implemented for this type of data.
  467. // Any error codes from IDataObject::GetData() (through HrSaveData()).
  468. //
  469. //--
  470. /////////////////////////////////////////////////////////////////////////////
  471. HRESULT CExtObject::InvokeCommand(
  472. IN ULONG nCommandID,
  473. IN IUnknown * piData
  474. )
  475. {
  476. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  477. // Find the item that was executed in our table.
  478. hr = HrSaveData(piData);
  479. if (hr == NOERROR)
  480. {
  481. ULONG iCommandID;
  482. LPWSTR pwsz = g_rgpwszContextMenuItems[IstrResTypeName()];
  483. LPWSTR pwszName;
  484. LPWSTR pwszStatusBarText;
  485. for (iCommandID = 0 ; *pwsz != L'\0' ; iCommandID++)
  486. {
  487. pwszName = pwsz;
  488. pwszStatusBarText = pwszName + (::wcslen(pwszName) + 1);
  489. if (iCommandID == nCommandID)
  490. break;
  491. pwsz = pwszStatusBarText + (::wcslen(pwszStatusBarText) + 1);
  492. } // while: more menu items to add
  493. if (iCommandID == nCommandID)
  494. {
  495. CString strMsg;
  496. CString strName;
  497. try
  498. {
  499. strName = pwszName;
  500. strMsg.Format(_T("Item %s was executed"), strName);
  501. AfxMessageBox(strMsg);
  502. } // try
  503. catch (CException * pe)
  504. {
  505. pe->Delete();
  506. } // catch: CException
  507. } // if: command ID found
  508. } // if: no errors saving the data
  509. piData->Release();
  510. m_piData = NULL;
  511. return NOERROR;
  512. } //*** CExtObject::InvokeCommand()
  513. #endif
  514. /////////////////////////////////////////////////////////////////////////////
  515. //++
  516. //
  517. // CExtObject::HrGetUIInfo
  518. //
  519. // Routine Description:
  520. // Get info about displaying UI.
  521. //
  522. // Arguments:
  523. // piData IUnkown pointer from which to obtain interfaces
  524. // for obtaining data describing the object.
  525. //
  526. // Return Value:
  527. // NOERROR Data saved successfully.
  528. // E_NOTIMPL Not implemented for this type of data.
  529. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  530. // or HrGetResourceName().
  531. //
  532. //--
  533. /////////////////////////////////////////////////////////////////////////////
  534. HRESULT CExtObject::HrGetUIInfo(IUnknown * piData)
  535. {
  536. HRESULT hr = NOERROR;
  537. ASSERT(piData != NULL);
  538. // Save info about all types of objects.
  539. {
  540. IGetClusterUIInfo * pi;
  541. hr = piData->QueryInterface(IID_IGetClusterUIInfo, (LPVOID *) &pi);
  542. if (hr != NOERROR)
  543. return hr;
  544. m_lcid = pi->GetLocale();
  545. m_hfont = pi->GetFont();
  546. m_hicon = pi->GetIcon();
  547. pi->Release();
  548. } // Save info about all types of objects
  549. return hr;
  550. } //*** CExtObject::HrGetUIInfo()
  551. /////////////////////////////////////////////////////////////////////////////
  552. //++
  553. //
  554. // CExtObject::HrSaveData
  555. //
  556. // Routine Description:
  557. // Save data from the object so that it can be used for the life
  558. // of the object.
  559. //
  560. // Arguments:
  561. // piData IUnkown pointer from which to obtain interfaces
  562. // for obtaining data describing the object.
  563. //
  564. // Return Value:
  565. // NOERROR Data saved successfully.
  566. // E_NOTIMPL Not implemented for this type of data.
  567. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  568. // or HrGetResourceName().
  569. //
  570. //--
  571. /////////////////////////////////////////////////////////////////////////////
  572. HRESULT CExtObject::HrSaveData(IUnknown * piData)
  573. {
  574. HRESULT hr = NOERROR;
  575. ASSERT(piData != NULL);
  576. if (piData != m_piData)
  577. {
  578. if (m_piData != NULL)
  579. m_piData->Release();
  580. m_piData = piData;
  581. } // if: different data interface pointer
  582. // Save info about all types of objects.
  583. {
  584. IGetClusterDataInfo * pi;
  585. hr = piData->QueryInterface(IID_IGetClusterDataInfo, (LPVOID *) &pi);
  586. if (hr != NOERROR)
  587. return hr;
  588. m_hcluster = pi->GetClusterHandle();
  589. m_cobj = pi->GetObjectCount();
  590. if (Cobj() != 1)
  591. hr = E_NOTIMPL;
  592. else
  593. hr = HrGetClusterName(pi);
  594. pi->Release();
  595. if (hr != NOERROR)
  596. return hr;
  597. } // Save info about all types of objects
  598. // Save info about this object.
  599. hr = HrGetObjectInfo();
  600. if (hr != NOERROR)
  601. return hr;
  602. return hr;
  603. } //*** CExtObject::HrSaveData()
  604. /////////////////////////////////////////////////////////////////////////////
  605. //++
  606. //
  607. // CExtObject::HrGetObjectInfo
  608. //
  609. // Routine Description:
  610. // Get information about the object.
  611. //
  612. // Arguments:
  613. // None.
  614. //
  615. // Return Value:
  616. // NOERROR Data saved successfully.
  617. // E_OUTOFMEMORY Error allocating memory.
  618. // E_NOTIMPL Not implemented for this type of data.
  619. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  620. // or HrGetResourceName().
  621. //
  622. //--
  623. /////////////////////////////////////////////////////////////////////////////
  624. HRESULT CExtObject::HrGetObjectInfo(void)
  625. {
  626. HRESULT hr = NOERROR;
  627. IGetClusterObjectInfo * piGcoi;
  628. IGetClusterResourceInfo * piGcri;
  629. CException exc(FALSE /*bAutoDelete*/);
  630. ASSERT(PiData() != NULL);
  631. // Get an IGetClusterObjectInfo interface pointer.
  632. hr = PiData()->QueryInterface(IID_IGetClusterObjectInfo, (LPVOID *) &piGcoi);
  633. if (hr != NOERROR)
  634. return hr;
  635. // Read the object data.
  636. try
  637. {
  638. // Get the type of the object.
  639. m_rdResData.m_cot = piGcoi->GetObjectType(0);
  640. if (m_rdResData.m_cot != CLUADMEX_OT_RESOURCE)
  641. {
  642. hr = E_NOTIMPL;
  643. throw &exc;
  644. } // if: not a resource
  645. hr = HrGetObjectName(piGcoi);
  646. } // try
  647. catch (CException * pe)
  648. {
  649. pe->Delete();
  650. } // catch: CException
  651. piGcoi->Release();
  652. if (hr != NOERROR)
  653. return hr;
  654. // Get an IGetClusterResourceInfo interface pointer.
  655. hr = PiData()->QueryInterface(IID_IGetClusterResourceInfo, (LPVOID *) &piGcri);
  656. if (hr != NOERROR)
  657. return hr;
  658. m_rdResData.m_hresource = piGcri->GetResourceHandle(0);
  659. hr = HrGetResourceTypeName(piGcri);
  660. // See if we know about this resource type.
  661. if (hr == NOERROR)
  662. {
  663. LPCWSTR pwszResTypeName;
  664. // Find the resource type name in our list.
  665. // Save the index for use in other arrays.
  666. for (m_istrResTypeName = 0, pwszResTypeName = g_wszResourceTypeNames
  667. ; *pwszResTypeName != L'\0'
  668. ; m_istrResTypeName++, pwszResTypeName += ::wcslen(pwszResTypeName) + 1
  669. )
  670. {
  671. if (RrdResData().m_strResTypeName.CompareNoCase(pwszResTypeName) == 0)
  672. break;
  673. } // for: each resource type in the list
  674. if (*pwszResTypeName == L'\0')
  675. hr = E_NOTIMPL;
  676. } // See if we know about this resource type
  677. piGcoi->Release();
  678. return hr;
  679. } //*** CExtObject::HrGetObjectInfo()
  680. /////////////////////////////////////////////////////////////////////////////
  681. //++
  682. //
  683. // CExtObject::HrGetClusterName
  684. //
  685. // Routine Description:
  686. // Get the name of the cluster.
  687. //
  688. // Arguments:
  689. // piData IGetClusterDataInfo interface pointer for getting
  690. // the object name.
  691. //
  692. // Return Value:
  693. // NOERROR Data saved successfully.
  694. // E_NOTIMPL Not implemented for this type of data.
  695. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  696. // or HrGetResourceName().
  697. //
  698. //--
  699. /////////////////////////////////////////////////////////////////////////////
  700. HRESULT CExtObject::HrGetClusterName(
  701. IN OUT IGetClusterDataInfo * pi
  702. )
  703. {
  704. HRESULT hr = NOERROR;
  705. WCHAR * pwszName = NULL;
  706. LONG cchName;
  707. ASSERT(pi != NULL);
  708. hr = pi->GetClusterName(NULL, &cchName);
  709. if (hr != NOERROR)
  710. return hr;
  711. try
  712. {
  713. pwszName = new WCHAR[cchName];
  714. hr = pi->GetClusterName(pwszName, &cchName);
  715. if (hr != NOERROR)
  716. {
  717. delete [] pwszName;
  718. pwszName = NULL;
  719. } // if: error getting cluster name
  720. m_strClusterName = pwszName;
  721. } // try
  722. catch (CMemoryException * pme)
  723. {
  724. pme->Delete();
  725. hr = E_OUTOFMEMORY;
  726. } // catch: CMemoryException
  727. delete [] pwszName;
  728. return hr;
  729. } //*** CExtObject::HrGetClusterName()
  730. /////////////////////////////////////////////////////////////////////////////
  731. //++
  732. //
  733. // CExtObject::HrGetObjectName
  734. //
  735. // Routine Description:
  736. // Get the name of the object.
  737. //
  738. // Arguments:
  739. // piData IGetClusterObjectInfo interface pointer for getting
  740. // the object name.
  741. //
  742. // Return Value:
  743. // NOERROR Data saved successfully.
  744. // E_NOTIMPL Not implemented for this type of data.
  745. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  746. // or HrGetResourceName().
  747. //
  748. //--
  749. /////////////////////////////////////////////////////////////////////////////
  750. HRESULT CExtObject::HrGetObjectName(
  751. IN OUT IGetClusterObjectInfo * pi
  752. )
  753. {
  754. HRESULT hr = NOERROR;
  755. WCHAR * pwszName = NULL;
  756. LONG cchName;
  757. ASSERT(pi != NULL);
  758. hr = pi->GetObjectName(0, NULL, &cchName);
  759. if (hr != NOERROR)
  760. return hr;
  761. try
  762. {
  763. pwszName = new WCHAR[cchName];
  764. hr = pi->GetObjectName(0, pwszName, &cchName);
  765. if (hr != NOERROR)
  766. {
  767. delete [] pwszName;
  768. pwszName = NULL;
  769. } // if: error getting object name
  770. m_rdResData.m_strName = pwszName;
  771. } // try
  772. catch (CMemoryException * pme)
  773. {
  774. pme->Delete();
  775. hr = E_OUTOFMEMORY;
  776. } // catch: CMemoryException
  777. delete [] pwszName;
  778. return hr;
  779. } //*** CExtObject::HrGetObjectName()
  780. /////////////////////////////////////////////////////////////////////////////
  781. //++
  782. //
  783. // CExtObject::HrGetResourceTypeName
  784. //
  785. // Routine Description:
  786. // Get the name of the resource's type.
  787. //
  788. // Arguments:
  789. // piData IGetClusterResourceInfo interface pointer for getting
  790. // the resource type name.
  791. //
  792. // Return Value:
  793. // NOERROR Data saved successfully.
  794. // E_NOTIMPL Not implemented for this type of data.
  795. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  796. // or HrGetResourceName().
  797. //
  798. //--
  799. /////////////////////////////////////////////////////////////////////////////
  800. HRESULT CExtObject::HrGetResourceTypeName(
  801. IN OUT IGetClusterResourceInfo * pi
  802. )
  803. {
  804. HRESULT hr = NOERROR;
  805. WCHAR * pwszName = NULL;
  806. LONG cchName;
  807. ASSERT(pi != NULL);
  808. hr = pi->GetResourceTypeName(0, NULL, &cchName);
  809. if (hr != NOERROR)
  810. return hr;
  811. try
  812. {
  813. pwszName = new WCHAR[cchName];
  814. hr = pi->GetResourceTypeName(0, pwszName, &cchName);
  815. if (hr != NOERROR)
  816. {
  817. delete [] pwszName;
  818. pwszName = NULL;
  819. } // if: error getting resource type name
  820. m_rdResData.m_strResTypeName = pwszName;
  821. } // try
  822. catch (CMemoryException * pme)
  823. {
  824. pme->Delete();
  825. hr = E_OUTOFMEMORY;
  826. } // catch: CMemoryException
  827. delete [] pwszName;
  828. return hr;
  829. } //*** CExtObject::HrGetResourceTypeName()
  830. /////////////////////////////////////////////////////////////////////////////
  831. //++
  832. //
  833. // CExtObject::BGetResourceNetworkName
  834. //
  835. // Routine Description:
  836. // Get the name of the resource's type.
  837. //
  838. // Arguments:
  839. // lpszNetName [OUT] String in which to return the network name resource name.
  840. // pcchNetName [IN OUT] Points to a variable that specifies the
  841. // maximum size, in characters, of the buffer. This
  842. // value shold be large enough to contain
  843. // MAX_COMPUTERNAME_LENGTH + 1 characters. Upon
  844. // return it contains the actual number of characters
  845. // copied.
  846. //
  847. // Return Value:
  848. // TRUE Resource is dependent on a network name resource.
  849. // FALSE Resource is NOT dependent on a network name resource.
  850. //
  851. //--
  852. /////////////////////////////////////////////////////////////////////////////
  853. BOOL CExtObject::BGetResourceNetworkName(
  854. OUT WCHAR * lpszNetName,
  855. IN OUT DWORD * pcchNetName
  856. )
  857. {
  858. BOOL bSuccess;
  859. IGetClusterResourceInfo * piGcri;
  860. ASSERT(PiData() != NULL);
  861. // Get an IGetClusterResourceInfo interface pointer.
  862. {
  863. HRESULT hr;
  864. hr = PiData()->QueryInterface(IID_IGetClusterResourceInfo, (LPVOID *) &piGcri);
  865. if (hr != NOERROR)
  866. {
  867. SetLastError(hr);
  868. return FALSE;
  869. } // if: error getting the interface
  870. } // Get an IGetClusterResourceInfo interface pointer
  871. // Get the resource network name.
  872. bSuccess = piGcri->GetResourceNetworkName(0, lpszNetName, pcchNetName);
  873. piGcri->Release();
  874. return bSuccess;
  875. } //*** CExtObject::BGetResourceNetworkName()