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.

2112 lines
61 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2002 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 "CluAdmX.h"
  23. #include "ExtObj.h"
  24. #include "GenApp.h"
  25. #include "GenScript.h"
  26. #include "GenSvc.h"
  27. #include "NetName.h"
  28. #include "Disks.h"
  29. #include "PrtSpool.h"
  30. #include "SmbShare.h"
  31. #include "IpAddr.h"
  32. #include "RegRepl.h"
  33. #include "AclUtils.h"
  34. #include "ClusPage.h"
  35. /////////////////////////////////////////////////////////////////////////////
  36. // Global Variables
  37. /////////////////////////////////////////////////////////////////////////////
  38. const WCHAR g_wszResourceTypeNames[] =
  39. RESTYPE_NAME_GENERIC_APP L"\0"
  40. RESTYPE_NAME_GENERIC_SCRIPT L"\0"
  41. RESTYPE_NAME_GENERIC_SERVICE L"\0"
  42. RESTYPE_NAME_NETWORK_NAME L"\0"
  43. RESTYPE_NAME_PHYS_DISK L"\0"
  44. #ifdef SUPPORT_FT_SET
  45. RESTYPE_NAME_FT_SET L"\0"
  46. #endif // SUPPORT_FT_SET
  47. RESTYPE_NAME_PRINT_SPOOLER L"\0"
  48. RESTYPE_NAME_FILE_SHARE L"\0"
  49. RESTYPE_NAME_IP_ADDRESS L"\0"
  50. ;
  51. const DWORD g_cchResourceTypeNames = sizeof(g_wszResourceTypeNames) / sizeof(WCHAR);
  52. static CRuntimeClass * g_rgprtcPSGenAppPages[] = {
  53. RUNTIME_CLASS(CGenericAppParamsPage),
  54. RUNTIME_CLASS(CRegReplParamsPage),
  55. NULL
  56. };
  57. static CRuntimeClass * g_rgprtcPSGenScriptPages[] = {
  58. RUNTIME_CLASS(CGenericScriptParamsPage),
  59. NULL
  60. };
  61. static CRuntimeClass * g_rgprtcPSGenSvcPages[] = {
  62. RUNTIME_CLASS(CGenericSvcParamsPage),
  63. RUNTIME_CLASS(CRegReplParamsPage),
  64. NULL
  65. };
  66. static CRuntimeClass * g_rgprtcPSNetNamePages[] = {
  67. RUNTIME_CLASS(CNetworkNameParamsPage),
  68. NULL
  69. };
  70. static CRuntimeClass * g_rgprtcPSPhysDiskPages[] = {
  71. RUNTIME_CLASS(CPhysDiskParamsPage),
  72. NULL
  73. };
  74. #ifdef SUPPORT_FT_SET
  75. static CRuntimeClass * g_rgprtcPSFTSetPages[] = {
  76. RUNTIME_CLASS(CPhysDiskParamsPage),
  77. NULL
  78. };
  79. #endif // SUPPORT_FT_SET
  80. static CRuntimeClass * g_rgprtcPSPrintSpoolerPages[] = {
  81. RUNTIME_CLASS(CPrintSpoolerParamsPage),
  82. NULL
  83. };
  84. static CRuntimeClass * g_rgprtcPSFileSharePages[] = {
  85. RUNTIME_CLASS(CFileShareParamsPage),
  86. NULL
  87. };
  88. static CRuntimeClass * g_rgprtcPSIpAddrPages[] = {
  89. RUNTIME_CLASS(CIpAddrParamsPage),
  90. NULL
  91. };
  92. static CRuntimeClass ** g_rgpprtcPSPages[] = {
  93. g_rgprtcPSGenAppPages,
  94. g_rgprtcPSGenScriptPages,
  95. g_rgprtcPSGenSvcPages,
  96. g_rgprtcPSNetNamePages,
  97. g_rgprtcPSPhysDiskPages,
  98. #ifdef SUPPORT_FT_SET
  99. g_rgprtcPSFTSetPages,
  100. #endif // SUPPORT_FT_SET
  101. g_rgprtcPSPrintSpoolerPages,
  102. g_rgprtcPSFileSharePages,
  103. g_rgprtcPSIpAddrPages,
  104. };
  105. // Wizard pages and property sheet pages are the same.
  106. static CRuntimeClass ** g_rgpprtcWizPages[] = {
  107. g_rgprtcPSGenAppPages,
  108. g_rgprtcPSGenScriptPages,
  109. g_rgprtcPSGenSvcPages,
  110. g_rgprtcPSNetNamePages,
  111. g_rgprtcPSPhysDiskPages,
  112. #ifdef SUPPORT_FT_SET
  113. g_rgprtcPSFTSetPages,
  114. #endif // SUPPORT_FT_SET
  115. g_rgprtcPSPrintSpoolerPages,
  116. g_rgprtcPSFileSharePages,
  117. g_rgprtcPSIpAddrPages,
  118. };
  119. #ifdef _DEMO_CTX_MENUS
  120. static WCHAR g_wszGenAppMenuItems[] = {
  121. L"GenApp Item 1\0First Generic Application menu item\0"
  122. L"GenApp Item 2\0Second Generic Application menu item\0"
  123. L"GenApp Item 3\0Third Generic Application menu item\0"
  124. L"\0"
  125. };
  126. static WCHAR g_wszGenScriptMenuItems[] = {
  127. L"GenApp Item 1\0First Generic Script menu item\0"
  128. L"GenApp Item 2\0Second Generic Script menu item\0"
  129. L"GenApp Item 3\0Third Generic Script menu item\0"
  130. L"\0"
  131. };
  132. static WCHAR g_wszGenSvcMenuItems[] = {
  133. L"GenSvc Item 1\0First Generic Service menu item\0"
  134. L"GenSvc Item 2\0Second Generic Service menu item\0"
  135. L"GenSvc Item 3\0Third Generic Service menu item\0"
  136. L"\0"
  137. };
  138. static WCHAR g_wszNetNameMenuItems[] = {
  139. L"NetName Item 1\0First Network Name menu item\0"
  140. L"NetName Item 2\0Second Network Name menu item\0"
  141. L"NetName Item 3\0Third Network Name menu item\0"
  142. L"\0"
  143. };
  144. static WCHAR g_wszPhysDiskMenuItems[] = {
  145. L"PhysDisk Item 1\0First Physical Disk menu item\0"
  146. L"PhysDisk Item 2\0Second Physical Disk menu item\0"
  147. L"PhysDisk Item 3\0Third Physical Disk menu item\0"
  148. L"\0"
  149. };
  150. static WCHAR g_wszPrintSpoolerMenuItems[] = {
  151. L"FileShare Item 1\0First Print Spooler menu item\0"
  152. L"FileShare Item 2\0Second Print Spooler menu item\0"
  153. L"FileShare Item 3\0Third Print Spooler menu item\0"
  154. L"\0"
  155. };
  156. static WCHAR g_wszFileShareMenuItems[] = {
  157. L"FileShare Item 1\0First File Share menu item\0"
  158. L"FileShare Item 2\0Second File Share menu item\0"
  159. L"FileShare Item 3\0Third File Share menu item\0"
  160. L"\0"
  161. };
  162. static WCHAR g_wszIpAddrMenuItems[] = {
  163. L"IpAddr Item 1\0First IP Address menu item\0"
  164. L"IpAddr Item 2\0Second IP Address menu item\0"
  165. L"IpAddr Item 3\0Third IP Address menu item\0"
  166. L"\0"
  167. };
  168. static LPWSTR g_rgpwszContextMenuItems[] = {
  169. g_wszGenAppMenuItems,
  170. g_wszGenScriptMenuItems,
  171. g_wszGenSvcMenuItems,
  172. g_wszNetNameMenuItems,
  173. g_wszPhysDiskMenuItems,
  174. g_wszPrintSpoolerMenuItems,
  175. g_wszFileShareMenuItems,
  176. g_wszIpAddrMenuItems,
  177. };
  178. static WCHAR g_wszClusterMenuItems[] = {
  179. L"Cluster Item 1\0First Cluster menu item\0"
  180. L"Cluster Item 2\0Second Cluster menu item\0"
  181. L"Cluster Item 3\0Third Cluster menu item\0"
  182. L"\0"
  183. };
  184. static LPWSTR g_rgpwszClusterContextMenuItems[] = {
  185. g_wszClusterMenuItems,
  186. };
  187. #endif
  188. /////////////////////////////////////////////////////////////////////////////
  189. // CExtObject
  190. /////////////////////////////////////////////////////////////////////////////
  191. /////////////////////////////////////////////////////////////////////////////
  192. //++
  193. //
  194. // CExtObject::CExtObject
  195. //
  196. // Routine Description:
  197. // Default constructor.
  198. //
  199. // Arguments:
  200. // None.
  201. //
  202. // Return Value:
  203. // None.
  204. //
  205. //--
  206. /////////////////////////////////////////////////////////////////////////////
  207. CExtObject::CExtObject(void)
  208. {
  209. m_piData = NULL;
  210. m_piWizardCallback = NULL;
  211. m_bWizard = FALSE;
  212. m_istrResTypeName = 0;
  213. m_hcluster = NULL;
  214. m_lcid = NULL;
  215. m_hfont = NULL;
  216. m_hicon = NULL;
  217. m_podObjData = NULL;
  218. m_pCvi = NULL;
  219. } //*** CExtObject::CExtObject()
  220. /////////////////////////////////////////////////////////////////////////////
  221. //++
  222. //
  223. // CExtObject::~CExtObject
  224. //
  225. // Routine Description:
  226. // Destructor.
  227. //
  228. // Arguments:
  229. // None.
  230. //
  231. // Return Value:
  232. // None.
  233. //
  234. //--
  235. /////////////////////////////////////////////////////////////////////////////
  236. CExtObject::~CExtObject(void)
  237. {
  238. // Release the data interface.
  239. if (PiData() != NULL)
  240. {
  241. PiData()->Release();
  242. m_piData = NULL;
  243. } // if: we have a data interface pointer
  244. // Release the wizard callback interface.
  245. if (PiWizardCallback() != NULL)
  246. {
  247. PiWizardCallback()->Release();
  248. m_piWizardCallback = NULL;
  249. } // if: we have a wizard callback interface pointer
  250. // Delete the pages.
  251. {
  252. POSITION pos;
  253. pos = Lpg().GetHeadPosition();
  254. while (pos != NULL)
  255. delete Lpg().GetNext(pos);
  256. } // Delete the pages
  257. delete m_podObjData;
  258. delete m_pCvi;
  259. } //*** CExtObject::~CExtObject()
  260. /////////////////////////////////////////////////////////////////////////////
  261. // ISupportErrorInfo Implementation
  262. /////////////////////////////////////////////////////////////////////////////
  263. //++
  264. //
  265. // CExtObject::InterfaceSupportsErrorInfo (ISupportErrorInfo)
  266. //
  267. // Routine Description:
  268. // Indicates whether an interface suportes the IErrorInfo interface.
  269. // This interface is provided by ATL.
  270. //
  271. // Arguments:
  272. // riid Interface ID.
  273. //
  274. // Return Value:
  275. // S_OK Interface supports IErrorInfo.
  276. // S_FALSE Interface does not support IErrorInfo.
  277. //
  278. //--
  279. /////////////////////////////////////////////////////////////////////////////
  280. STDMETHODIMP CExtObject::InterfaceSupportsErrorInfo(REFIID riid)
  281. {
  282. static const IID * rgiid[] =
  283. {
  284. &IID_IWEExtendPropertySheet,
  285. &IID_IWEExtendWizard,
  286. #ifdef _DEMO_CTX_MENUS
  287. &IID_IWEExtendContextMenu,
  288. #endif
  289. };
  290. int iiid;
  291. for (iiid = 0 ; iiid < sizeof(rgiid) / sizeof(rgiid[0]) ; iiid++)
  292. {
  293. if (InlineIsEqualGUID(*rgiid[iiid], riid))
  294. return S_OK;
  295. }
  296. return S_FALSE;
  297. } //*** CExtObject::InterfaceSupportsErrorInfo()
  298. /////////////////////////////////////////////////////////////////////////////
  299. // IWEExtendPropertySheet Implementation
  300. /////////////////////////////////////////////////////////////////////////////
  301. //++
  302. //
  303. // CExtObject::CreatePropertySheetPages (IWEExtendPropertySheet)
  304. //
  305. // Routine Description:
  306. // Create property sheet pages and add them to the sheet.
  307. //
  308. // Arguments:
  309. // piData IUnkown pointer from which to obtain interfaces
  310. // for obtaining data describing the object for
  311. // which the sheet is being displayed.
  312. // piCallback Pointer to an IWCPropertySheetCallback interface
  313. // for adding pages to the sheet.
  314. //
  315. // Return Value:
  316. // NOERROR Pages added successfully.
  317. // E_INVALIDARG Invalid arguments to the function.
  318. // E_OUTOFMEMORY Error allocating memory.
  319. // E_FAIL Error creating a page.
  320. // E_NOTIMPL Not implemented for this type of data.
  321. // Any error codes from IDataObject::GetData() (through HrSaveData()).
  322. //
  323. //--
  324. /////////////////////////////////////////////////////////////////////////////
  325. STDMETHODIMP CExtObject::CreatePropertySheetPages(
  326. IN IUnknown * piData,
  327. IN IWCPropertySheetCallback * piCallback
  328. )
  329. {
  330. HRESULT hr = E_FAIL;
  331. HPROPSHEETPAGE hpage = NULL;
  332. CException exc(FALSE /*bAutoDelete*/);
  333. CRuntimeClass ** pprtc = NULL;
  334. int irtc;
  335. CBasePropertyPage * ppage;
  336. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  337. // Validate the parameters.
  338. if ((piData == NULL) || (piCallback == NULL))
  339. return E_INVALIDARG;
  340. try
  341. {
  342. // Get info about displaying UI.
  343. hr = HrGetUIInfo(piData);
  344. if (hr != NOERROR)
  345. throw &exc;
  346. // Save the data.
  347. hr = HrSaveData(piData);
  348. if (hr != NOERROR)
  349. throw &exc;
  350. // Delete any previous pages.
  351. {
  352. POSITION pos;
  353. pos = Lpg().GetHeadPosition();
  354. while (pos != NULL)
  355. delete Lpg().GetNext(pos);
  356. Lpg().RemoveAll();
  357. } // Delete any previous pages
  358. // Create property pages.
  359. ASSERT(PodObjData() != NULL);
  360. switch (PodObjData()->m_cot)
  361. {
  362. case CLUADMEX_OT_CLUSTER:
  363. {
  364. CClusterSecurityPage *pClusterSecurityPage = new CClusterSecurityPage;
  365. if ( pClusterSecurityPage != NULL )
  366. {
  367. // Add it to the list.
  368. Lpg().AddTail( pClusterSecurityPage );
  369. hr = pClusterSecurityPage->HrInit( this );
  370. if ( SUCCEEDED( hr ) )
  371. {
  372. hr = piCallback->AddPropertySheetPage(
  373. (LONG *) pClusterSecurityPage->GetHPage() );
  374. }
  375. }
  376. else
  377. {
  378. hr = E_OUTOFMEMORY;
  379. }
  380. if ( FAILED( hr ) )
  381. {
  382. throw &exc;
  383. }
  384. }
  385. break;
  386. case CLUADMEX_OT_RESOURCE:
  387. pprtc = g_rgpprtcPSPages[IstrResTypeName()];
  388. break;
  389. default:
  390. hr = E_NOTIMPL;
  391. throw &exc;
  392. break;
  393. } // switch: object type
  394. if (pprtc)
  395. {
  396. // Create each page.
  397. for (irtc = 0 ; pprtc[irtc] != NULL ; irtc++)
  398. {
  399. // Create the page.
  400. ppage = (CBasePropertyPage *) pprtc[irtc]->CreateObject();
  401. ASSERT(ppage->IsKindOf(pprtc[irtc]));
  402. // Add it to the list.
  403. Lpg().AddTail(ppage);
  404. // Initialize the property page.
  405. hr = ppage->HrInit(this);
  406. if (FAILED(hr))
  407. throw &exc;
  408. // Create the page.
  409. hpage = ::CreatePropertySheetPage(&ppage->m_psp);
  410. if (hpage == NULL)
  411. {
  412. DWORD sc = GetLastError();
  413. hr = HRESULT_FROM_WIN32(sc);
  414. throw &exc;
  415. } // if: error creating the page
  416. // Save the hpage in the page itself.
  417. ppage->SetHpage(hpage);
  418. // Add it to the property sheet.
  419. hr = piCallback->AddPropertySheetPage((LONG *) hpage);
  420. if (hr != NOERROR)
  421. throw &exc;
  422. } // for: each page in the list
  423. } // if: pprtc is null
  424. } // try
  425. catch (CMemoryException * pme)
  426. {
  427. TRACE(_T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n"));
  428. pme->Delete();
  429. hr = E_OUTOFMEMORY;
  430. } // catch: anything
  431. catch (CException * pe)
  432. {
  433. TRACE(_T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n"));
  434. pe->Delete();
  435. if (hr == NOERROR)
  436. hr = E_FAIL;
  437. } // catch: anything
  438. if (hr != NOERROR)
  439. {
  440. if (hpage != NULL)
  441. ::DestroyPropertySheetPage(hpage);
  442. piData->Release();
  443. m_piData = NULL;
  444. } // if: error occurred
  445. piCallback->Release();
  446. return hr;
  447. } //*** CExtObject::CreatePropertySheetPages()
  448. /////////////////////////////////////////////////////////////////////////////
  449. // IWEExtendWizard Implementation
  450. /////////////////////////////////////////////////////////////////////////////
  451. //++
  452. //
  453. // CExtObject::CreateWizardPages (IWEExtendWizard)
  454. //
  455. // Routine Description:
  456. // Create property sheet pages and add them to the wizard.
  457. //
  458. // Arguments:
  459. // piData IUnkown pointer from which to obtain interfaces
  460. // for obtaining data describing the object for
  461. // which the wizard is being displayed.
  462. // piCallback Pointer to an IWCPropertySheetCallback interface
  463. // for adding pages to the sheet.
  464. //
  465. // Return Value:
  466. // NOERROR Pages added successfully.
  467. // E_INVALIDARG Invalid arguments to the function.
  468. // E_OUTOFMEMORY Error allocating memory.
  469. // E_FAIL Error creating a page.
  470. // E_NOTIMPL Not implemented for this type of data.
  471. // Any error codes from IDataObject::GetData() (through HrSaveData()).
  472. //
  473. //--
  474. /////////////////////////////////////////////////////////////////////////////
  475. STDMETHODIMP CExtObject::CreateWizardPages(
  476. IN IUnknown * piData,
  477. IN IWCWizardCallback * piCallback
  478. )
  479. {
  480. HRESULT hr = NOERROR;
  481. HPROPSHEETPAGE hpage = NULL;
  482. CException exc(FALSE /*bAutoDelete*/);
  483. int irtc;
  484. CBasePropertyPage * ppage;
  485. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  486. // Validate the parameters.
  487. if ((piData == NULL) || (piCallback == NULL))
  488. return E_INVALIDARG;
  489. try
  490. {
  491. // Get info about displaying UI.
  492. hr = HrGetUIInfo(piData);
  493. if (hr != NOERROR)
  494. throw &exc;
  495. // Save the data.
  496. hr = HrSaveData(piData);
  497. if (hr != NOERROR)
  498. throw &exc;
  499. // Delete any previous pages.
  500. {
  501. POSITION pos;
  502. pos = Lpg().GetHeadPosition();
  503. while (pos != NULL)
  504. delete Lpg().GetNext(pos);
  505. Lpg().RemoveAll();
  506. } // Delete any previous pages
  507. m_piWizardCallback = piCallback;
  508. m_bWizard = TRUE;
  509. // Add each page for this type of resource.
  510. for (irtc = 0 ; g_rgpprtcWizPages[IstrResTypeName()][irtc] != NULL ; irtc++)
  511. {
  512. // Create the property pages.
  513. ppage = (CBasePropertyPage *) g_rgpprtcWizPages[IstrResTypeName()][irtc]->CreateObject();
  514. ASSERT(ppage->IsKindOf(g_rgpprtcWizPages[IstrResTypeName()][irtc]));
  515. // Add it to the list.
  516. Lpg().AddTail(ppage);
  517. // Initialize the property page.
  518. hr = ppage->HrInit(this);
  519. if (FAILED(hr))
  520. throw &exc;
  521. // Create the page.
  522. hpage = ::CreatePropertySheetPage(&ppage->m_psp);
  523. if (hpage == NULL)
  524. {
  525. DWORD sc = GetLastError();
  526. hr = HRESULT_FROM_WIN32(sc);
  527. throw &exc;
  528. } // if: error creating the page
  529. // Save the hpage in the page itself.
  530. ppage->SetHpage(hpage);
  531. // Add it to the property sheet.
  532. hr = piCallback->AddWizardPage((LONG *) hpage);
  533. if (hr != NOERROR)
  534. throw &exc;
  535. } // for: each page for the type of resource
  536. } // try
  537. catch (CMemoryException * pme)
  538. {
  539. TRACE(_T("CExtObject::CreateWizardPages: Failed to add wizard page (CMemoryException)\n"));
  540. pme->Delete();
  541. hr = E_OUTOFMEMORY;
  542. } // catch: CMemoryException
  543. catch (CException * pe)
  544. {
  545. TRACE(_T("CExtObject::CreateWizardPages: Failed to add wizard page (CException)\n"));
  546. pe->Delete();
  547. if (hr == NOERROR)
  548. hr = E_FAIL;
  549. } // catch: CException
  550. // catch (...)
  551. // {
  552. // TRACE(_T("CExtObject::CreateWizardPages: Failed to add wizard page (...)\n"));
  553. // } // catch: anything
  554. if (hr != NOERROR)
  555. {
  556. if (hpage != NULL)
  557. ::DestroyPropertySheetPage(hpage);
  558. piCallback->Release();
  559. if ( m_piWizardCallback == piCallback )
  560. {
  561. m_piWizardCallback = NULL;
  562. } // if: already saved interface pointer
  563. piData->Release();
  564. m_piData = NULL;
  565. } // if: error occurred
  566. return hr;
  567. } //*** CExtObject::CreateWizardPages()
  568. #ifdef _DEMO_CTX_MENUS
  569. /////////////////////////////////////////////////////////////////////////////
  570. // IWEExtendContextMenu Implementation
  571. /////////////////////////////////////////////////////////////////////////////
  572. //++
  573. //
  574. // CExtObject::AddContextMenuItems (IWEExtendContextMenu)
  575. //
  576. // Routine Description:
  577. // Add items to a context menu. This is called each time the context
  578. // menu is invoked.
  579. //
  580. // Arguments:
  581. // piData IUnkown pointer from which to obtain interfaces
  582. // for obtaining data describing the object for
  583. // which the context menu is being displayed.
  584. // piCallback Pointer to an IWCContextMenuCallback interface
  585. // for adding menu items to the context menu.
  586. //
  587. // Return Value:
  588. // NOERROR Pages added successfully.
  589. // E_INVALIDARG Invalid arguments to the function.
  590. // E_FAIL Error adding context menu item.
  591. // E_NOTIMPL Not implemented for this type of data.
  592. // Any error codes returned by HrSaveData() or IWCContextMenuCallback::
  593. // AddExtensionMenuItem().
  594. //
  595. //--
  596. /////////////////////////////////////////////////////////////////////////////
  597. STDMETHODIMP CExtObject::AddContextMenuItems(
  598. IN IUnknown * piData,
  599. IN IWCContextMenuCallback * piCallback
  600. )
  601. {
  602. HRESULT hr = NOERROR;
  603. ULONG iCommandID;
  604. UINT uFlags;
  605. LPWSTR pwsz = NULL;
  606. LPWSTR pwszName = NULL;
  607. LPWSTR pwszStatusBarText = NULL;
  608. CString strName;
  609. CException exc(FALSE /*bAutoDelete*/);
  610. BSTR bstrName = NULL;
  611. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  612. // Validate the parameters.
  613. if ((piData == NULL) || (piCallback == NULL))
  614. return E_INVALIDARG;
  615. try
  616. {
  617. // Save the data.
  618. hr = HrSaveData(piData);
  619. if (hr != NOERROR)
  620. throw &exc;
  621. switch ( PodObjData()->m_cot )
  622. {
  623. case CLUADMEX_OT_CLUSTER:
  624. // Add menu items to the cluster object.
  625. pwsz = g_rgpwszClusterContextMenuItems[ 0 ];
  626. for (iCommandID = 0 ; *pwsz != L'\0' ; iCommandID++)
  627. {
  628. pwszName = pwsz;
  629. pwszStatusBarText = pwszName + (wcslen(pwszName) + 1);
  630. // Gray the first item, disable the second and enable
  631. // the rest to show that it's working.
  632. strName = "";
  633. uFlags = 0;
  634. if ( iCommandID == 0 )
  635. {
  636. uFlags = MF_GRAYED;
  637. strName += L"(Grayed) ";
  638. }
  639. else if ( iCommandID == 1 )
  640. {
  641. uFlags = MF_DISABLED;
  642. strName += L"(Disabled) ";
  643. }
  644. strName += pwszName;
  645. bstrName = strName.AllocSysString();
  646. hr = piCallback->AddExtensionMenuItem(
  647. bstrName, // lpszName
  648. pwszStatusBarText, // lpszStatusBarText
  649. iCommandID, // lCommandID
  650. 0, // lSubCommandID
  651. uFlags // uFlags
  652. );
  653. if (hr != NOERROR)
  654. {
  655. throw &exc;
  656. }
  657. SysFreeString( bstrName );
  658. bstrName = NULL;
  659. pwsz = pwszStatusBarText + (wcslen(pwszStatusBarText) + 1);
  660. } // while: more menu items to add
  661. break;
  662. case CLUADMEX_OT_RESOURCE:
  663. case CLUADMEX_OT_RESOURCETYPE:
  664. // Add menu items specific to this resource type.
  665. pwsz = g_rgpwszContextMenuItems[IstrResTypeName()];
  666. for (iCommandID = 0 ; *pwsz != L'\0' ; iCommandID++)
  667. {
  668. pwszName = pwsz;
  669. pwszStatusBarText = pwszName + (wcslen(pwszName) + 1);
  670. // Gray the first item, disable the second and enable
  671. // the rest to show that it's working.
  672. strName = "";
  673. uFlags = 0;
  674. if ( iCommandID == 0 )
  675. {
  676. uFlags = MF_GRAYED;
  677. strName += L"(Grayed) ";
  678. }
  679. else if ( iCommandID == 1 )
  680. {
  681. uFlags = MF_DISABLED;
  682. strName += L"(Disabled) ";
  683. }
  684. strName += pwszName;
  685. bstrName = strName.AllocSysString();
  686. hr = piCallback->AddExtensionMenuItem(
  687. bstrName, // lpszName
  688. pwszStatusBarText, // lpszStatusBarText
  689. iCommandID, // lCommandID
  690. 0, // lSubCommandID
  691. uFlags // uFlags
  692. );
  693. if (hr != NOERROR)
  694. {
  695. throw &exc;
  696. }
  697. SysFreeString( bstrName );
  698. bstrName = NULL;
  699. pwsz = pwszStatusBarText + (wcslen(pwszStatusBarText) + 1);
  700. } // while: more menu items to add
  701. break;
  702. default:
  703. hr = E_NOTIMPL;
  704. break;
  705. } // switch:
  706. } // try
  707. catch (CException * pe)
  708. {
  709. TRACE(_T("CExtObject::AddContextMenuItems: Failed to add context menu item\n"));
  710. pe->Delete();
  711. if (hr == NOERROR)
  712. hr = E_FAIL;
  713. } // catch: anything
  714. if (hr != NOERROR)
  715. {
  716. piData->Release();
  717. m_piData = NULL;
  718. } // if: error occurred
  719. piCallback->Release();
  720. return hr;
  721. } //*** CExtObject::AddContextMenuItems()
  722. /////////////////////////////////////////////////////////////////////////////
  723. // IWEInvokeCommand Implementation
  724. /////////////////////////////////////////////////////////////////////////////
  725. //++
  726. //
  727. // CExtObject::InvokeCommand (IWEInvokeCommand)
  728. //
  729. // Routine Description:
  730. // Invoke a command offered by a context menu.
  731. //
  732. // Arguments:
  733. // lCommandID ID of the menu item to execute. This is the same
  734. // ID passed to the IWCContextMenuCallback
  735. // ::AddExtensionMenuItem() method.
  736. // piData IUnkown pointer from which to obtain interfaces
  737. // for obtaining data describing the object for
  738. // which the command is to be invoked.
  739. //
  740. // Return Value:
  741. // NOERROR Command invoked successfully.
  742. // E_INVALIDARG Invalid arguments to the function.
  743. // E_OUTOFMEMORY Error allocating memory.
  744. // E_NOTIMPL Not implemented for this type of data.
  745. // Any error codes from IDataObject::GetData() (through HrSaveData()).
  746. //
  747. //--
  748. /////////////////////////////////////////////////////////////////////////////
  749. HRESULT CExtObject::InvokeCommand(
  750. IN ULONG nCommandID,
  751. IN IUnknown * piData
  752. )
  753. {
  754. HRESULT hr = NOERROR;
  755. ULONG iCommandID;
  756. LPWSTR pwsz = NULL;
  757. LPWSTR pwszName = NULL;
  758. LPWSTR pwszStatusBarText = NULL;
  759. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  760. // Find the item that was executed in our table.
  761. hr = HrSaveData(piData);
  762. if (hr != NOERROR)
  763. {
  764. goto Cleanup;
  765. } // if:
  766. switch ( PodObjData()->m_cot )
  767. {
  768. case CLUADMEX_OT_CLUSTER:
  769. pwsz = g_rgpwszClusterContextMenuItems[ 0 ];
  770. for (iCommandID = 0 ; *pwsz != L'\0' ; iCommandID++)
  771. {
  772. pwszName = pwsz;
  773. pwszStatusBarText = pwszName + (wcslen(pwszName) + 1);
  774. if (iCommandID == nCommandID)
  775. break;
  776. pwsz = pwszStatusBarText + (wcslen(pwszStatusBarText) + 1);
  777. } // while: more menu items to add
  778. if (iCommandID == nCommandID)
  779. {
  780. CString strMsg;
  781. CString strName;
  782. try
  783. {
  784. strName = pwszName;
  785. strMsg.Format(_T("Item %s was executed"), strName);
  786. AfxMessageBox(strMsg);
  787. } // try
  788. catch (CException * pe)
  789. {
  790. pe->Delete();
  791. } // catch: CException
  792. } // if: command ID found
  793. break;
  794. case CLUADMEX_OT_RESOURCE:
  795. case CLUADMEX_OT_RESOURCETYPE:
  796. pwsz = g_rgpwszContextMenuItems[IstrResTypeName()];
  797. for (iCommandID = 0 ; *pwsz != L'\0' ; iCommandID++)
  798. {
  799. pwszName = pwsz;
  800. pwszStatusBarText = pwszName + (wcslen(pwszName) + 1);
  801. if (iCommandID == nCommandID)
  802. break;
  803. pwsz = pwszStatusBarText + (wcslen(pwszStatusBarText) + 1);
  804. } // while: more menu items to add
  805. if (iCommandID == nCommandID)
  806. {
  807. CString strMsg;
  808. CString strName;
  809. try
  810. {
  811. strName = pwszName;
  812. strMsg.Format(_T("Item %s was executed"), strName);
  813. AfxMessageBox(strMsg);
  814. } // try
  815. catch (CException * pe)
  816. {
  817. pe->Delete();
  818. } // catch: CException
  819. } // if: command ID found
  820. break;
  821. default:
  822. hr = E_NOTIMPL;
  823. break;
  824. } // switch:
  825. Cleanup:
  826. piData->Release();
  827. m_piData = NULL;
  828. return hr;
  829. } //*** CExtObject::InvokeCommand()
  830. #endif
  831. /////////////////////////////////////////////////////////////////////////////
  832. //++
  833. //
  834. // CExtObject::HrGetUIInfo
  835. //
  836. // Routine Description:
  837. // Get info about displaying UI.
  838. //
  839. // Arguments:
  840. // piData IUnkown pointer from which to obtain interfaces
  841. // for obtaining data describing the object.
  842. //
  843. // Return Value:
  844. // NOERROR Data saved successfully.
  845. // E_NOTIMPL Not implemented for this type of data.
  846. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  847. // or HrGetResourceName().
  848. //
  849. //--
  850. /////////////////////////////////////////////////////////////////////////////
  851. HRESULT CExtObject::HrGetUIInfo(IUnknown * piData)
  852. {
  853. HRESULT hr = NOERROR;
  854. ASSERT(piData != NULL);
  855. // Save info about all types of objects.
  856. {
  857. IGetClusterUIInfo * pi;
  858. hr = piData->QueryInterface(IID_IGetClusterUIInfo, (LPVOID *) &pi);
  859. if (hr != NOERROR)
  860. return hr;
  861. m_lcid = pi->GetLocale();
  862. m_hfont = pi->GetFont();
  863. m_hicon = pi->GetIcon();
  864. pi->Release();
  865. } // Save info about all types of objects
  866. return hr;
  867. } //*** CExtObject::HrGetUIInfo()
  868. /////////////////////////////////////////////////////////////////////////////
  869. //++
  870. //
  871. // CExtObject::HrSaveData
  872. //
  873. // Routine Description:
  874. // Save data from the object so that it can be used for the life
  875. // of the object.
  876. //
  877. // Arguments:
  878. // piData IUnkown pointer from which to obtain interfaces
  879. // for obtaining data describing the object.
  880. //
  881. // Return Value:
  882. // NOERROR Data saved successfully.
  883. // E_NOTIMPL Not implemented for this type of data.
  884. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  885. // or HrGetResourceName().
  886. //
  887. //--
  888. /////////////////////////////////////////////////////////////////////////////
  889. HRESULT CExtObject::HrSaveData(IUnknown * piData)
  890. {
  891. HRESULT hr = NOERROR;
  892. ASSERT(piData != NULL);
  893. if (piData != m_piData)
  894. {
  895. if (m_piData != NULL)
  896. m_piData->Release();
  897. m_piData = piData;
  898. } // if: different data interface pointer
  899. // Save info about all types of objects.
  900. {
  901. IGetClusterDataInfo * pi;
  902. hr = piData->QueryInterface(IID_IGetClusterDataInfo, (LPVOID *) &pi);
  903. if (hr != NOERROR)
  904. return hr;
  905. m_hcluster = pi->GetClusterHandle();
  906. m_cobj = pi->GetObjectCount();
  907. if (Cobj() != 1)
  908. hr = E_NOTIMPL;
  909. else
  910. hr = HrGetClusterName(pi);
  911. pi->Release();
  912. if (hr != NOERROR)
  913. return hr;
  914. } // Save info about all types of objects
  915. // Save info about this object.
  916. hr = HrGetObjectInfo();
  917. if (hr != NOERROR)
  918. return hr;
  919. return hr;
  920. } //*** CExtObject::HrSaveData()
  921. /////////////////////////////////////////////////////////////////////////////
  922. //++
  923. //
  924. // CExtObject::HrGetObjectInfo
  925. //
  926. // Routine Description:
  927. // Get information about the object.
  928. //
  929. // Arguments:
  930. // None.
  931. //
  932. // Return Value:
  933. // NOERROR Data saved successfully.
  934. // E_OUTOFMEMORY Error allocating memory.
  935. // E_NOTIMPL Not implemented for this type of data.
  936. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  937. // or HrGetResourceName().
  938. //
  939. //--
  940. /////////////////////////////////////////////////////////////////////////////
  941. HRESULT CExtObject::HrGetObjectInfo(void)
  942. {
  943. HRESULT hr = NOERROR;
  944. IGetClusterObjectInfo * piGcoi;
  945. CLUADMEX_OBJECT_TYPE cot = CLUADMEX_OT_NONE;
  946. CException exc(FALSE /*bAutoDelete*/);
  947. const CString * pstrResTypeName = NULL;
  948. ASSERT(PiData() != NULL);
  949. // Get object info.
  950. {
  951. // Get an IGetClusterObjectInfo interface pointer.
  952. hr = PiData()->QueryInterface(IID_IGetClusterObjectInfo, (LPVOID *) &piGcoi);
  953. if (hr != NOERROR)
  954. return hr;
  955. // Read the object data.
  956. try
  957. {
  958. // Delete the previous object data.
  959. delete m_podObjData;
  960. m_podObjData = NULL;
  961. // Get the type of the object.
  962. cot = piGcoi->GetObjectType(0);
  963. switch (cot)
  964. {
  965. case CLUADMEX_OT_CLUSTER:
  966. m_podObjData = new CObjData;
  967. if ( m_podObjData == NULL )
  968. {
  969. AfxThrowMemoryException();
  970. }
  971. break;
  972. case CLUADMEX_OT_RESOURCE:
  973. {
  974. IGetClusterResourceInfo * pi;
  975. m_podObjData = new CResData;
  976. if ( m_podObjData == NULL )
  977. {
  978. AfxThrowMemoryException();
  979. }
  980. // Get an IGetClusterResourceInfo interface pointer.
  981. hr = PiData()->QueryInterface(IID_IGetClusterResourceInfo, (LPVOID *) &pi);
  982. if (hr != NOERROR)
  983. {
  984. throw &exc;
  985. }
  986. PrdResDataRW()->m_hresource = pi->GetResourceHandle(0);
  987. ASSERT(PrdResDataRW()->m_hresource != NULL);
  988. if (PrdResDataRW()->m_hresource == NULL)
  989. {
  990. hr = E_INVALIDARG;
  991. }
  992. else
  993. {
  994. hr = HrGetResourceTypeName(pi);
  995. }
  996. pi->Release();
  997. if (hr != NOERROR)
  998. {
  999. throw &exc;
  1000. }
  1001. pstrResTypeName = &PrdResDataRW()->m_strResTypeName;
  1002. } // if: object is a resource
  1003. break;
  1004. case CLUADMEX_OT_RESOURCETYPE:
  1005. m_podObjData = new CObjData;
  1006. if ( m_podObjData == NULL )
  1007. {
  1008. AfxThrowMemoryException();
  1009. }
  1010. pstrResTypeName = &PodObjDataRW()->m_strName;
  1011. break;
  1012. default:
  1013. hr = E_NOTIMPL;
  1014. throw &exc;
  1015. } // switch: object type
  1016. PodObjDataRW()->m_cot = cot;
  1017. hr = HrGetObjectName(piGcoi);
  1018. } // try
  1019. catch (CMemoryException * pme)
  1020. {
  1021. pme->Delete();
  1022. hr = E_OUTOFMEMORY;
  1023. } // catch: CMemoryException
  1024. catch (CException * pe)
  1025. {
  1026. pe->Delete();
  1027. } // catch: CException
  1028. piGcoi->Release();
  1029. if (hr != NOERROR)
  1030. {
  1031. return hr;
  1032. }
  1033. } // Get object info
  1034. // If this is a resource or resource type, see if we know about this type.
  1035. if (((cot == CLUADMEX_OT_RESOURCE)
  1036. || (cot == CLUADMEX_OT_RESOURCETYPE))
  1037. && (hr == NOERROR))
  1038. {
  1039. LPCWSTR pwszResTypeName = NULL;
  1040. // Find the resource type name in our list.
  1041. // Save the index for use in other arrays.
  1042. for (m_istrResTypeName = 0, pwszResTypeName = g_wszResourceTypeNames
  1043. ; *pwszResTypeName != L'\0'
  1044. ; m_istrResTypeName++, pwszResTypeName += wcslen(pwszResTypeName) + 1
  1045. )
  1046. {
  1047. if (pstrResTypeName->CompareNoCase(pwszResTypeName) == 0)
  1048. {
  1049. break;
  1050. }
  1051. } // for: each resource type in the list
  1052. if (*pwszResTypeName == L'\0')
  1053. {
  1054. hr = E_NOTIMPL;
  1055. }
  1056. } // See if we know about this resource type
  1057. return hr;
  1058. } //*** CExtObject::HrGetObjectInfo()
  1059. /////////////////////////////////////////////////////////////////////////////
  1060. //++
  1061. //
  1062. // CExtObject::HrGetClusterName
  1063. //
  1064. // Routine Description:
  1065. // Get the name of the cluster.
  1066. //
  1067. // Arguments:
  1068. // piData IGetClusterDataInfo interface pointer for getting
  1069. // the object name.
  1070. //
  1071. // Return Value:
  1072. // NOERROR Data saved successfully.
  1073. // E_NOTIMPL Not implemented for this type of data.
  1074. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  1075. // or HrGetResourceName().
  1076. //
  1077. //--
  1078. /////////////////////////////////////////////////////////////////////////////
  1079. HRESULT CExtObject::HrGetClusterName(
  1080. IN OUT IGetClusterDataInfo * pi
  1081. )
  1082. {
  1083. HRESULT hr = NOERROR;
  1084. WCHAR * pwszName = NULL;
  1085. LONG cchName;
  1086. BSTR bstr = NULL;
  1087. ASSERT(pi != NULL);
  1088. hr = pi->GetClusterName(NULL, &cchName);
  1089. if (hr != NOERROR)
  1090. return hr;
  1091. bstr = SysAllocStringLen( NULL, cchName );
  1092. if ( bstr != NULL )
  1093. {
  1094. try
  1095. {
  1096. hr = pi->GetClusterName(bstr, &cchName);
  1097. if (hr == NOERROR)
  1098. {
  1099. pwszName = new WCHAR[cchName];
  1100. hr = StringCchCopyNW( pwszName, cchName, bstr, SysStringLen( bstr ) );
  1101. if ( FAILED( hr ) )
  1102. {
  1103. goto Cleanup;
  1104. }
  1105. }
  1106. m_strClusterName = pwszName;
  1107. } // try
  1108. catch (CMemoryException * pme)
  1109. {
  1110. pme->Delete();
  1111. hr = E_OUTOFMEMORY;
  1112. } // catch: CMemoryException
  1113. } // if: ( bstr != NULL )
  1114. else
  1115. {
  1116. hr = E_OUTOFMEMORY;
  1117. }
  1118. Cleanup:
  1119. SysFreeString( bstr );
  1120. delete [] pwszName;
  1121. return hr;
  1122. } //*** CExtObject::HrGetClusterName()
  1123. /////////////////////////////////////////////////////////////////////////////
  1124. //++
  1125. //
  1126. // CExtObject::HrGetObjectName
  1127. //
  1128. // Routine Description:
  1129. // Get the name of the object.
  1130. //
  1131. // Arguments:
  1132. // piData IGetClusterObjectInfo interface pointer for getting
  1133. // the object name.
  1134. //
  1135. // Return Value:
  1136. // NOERROR Data saved successfully.
  1137. // E_NOTIMPL Not implemented for this type of data.
  1138. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  1139. // or HrGetResourceName().
  1140. //
  1141. //--
  1142. /////////////////////////////////////////////////////////////////////////////
  1143. HRESULT CExtObject::HrGetObjectName(
  1144. IN OUT IGetClusterObjectInfo * pi
  1145. )
  1146. {
  1147. HRESULT hr = NOERROR;
  1148. WCHAR * pwszName = NULL;
  1149. LONG cchName;
  1150. BSTR bstr = NULL;
  1151. ASSERT(pi != NULL);
  1152. hr = pi->GetObjectName(0, NULL, &cchName);
  1153. if (hr != NOERROR)
  1154. return hr;
  1155. bstr = SysAllocStringLen( NULL, cchName );
  1156. if ( bstr != NULL )
  1157. {
  1158. try
  1159. {
  1160. hr = pi->GetObjectName(0, bstr, &cchName);
  1161. if (hr == NOERROR)
  1162. {
  1163. pwszName = new WCHAR[cchName];
  1164. hr = StringCchCopyNW( pwszName, cchName, bstr, SysStringLen( bstr ) );
  1165. if ( FAILED( hr ) )
  1166. {
  1167. goto Cleanup;
  1168. }
  1169. }
  1170. PodObjDataRW()->m_strName = pwszName;
  1171. } // try
  1172. catch (CMemoryException * pme)
  1173. {
  1174. pme->Delete();
  1175. hr = E_OUTOFMEMORY;
  1176. } // catch: CMemoryException
  1177. } // if: ( bstr != NULL )
  1178. else
  1179. {
  1180. hr = E_OUTOFMEMORY;
  1181. }
  1182. Cleanup:
  1183. SysFreeString( bstr );
  1184. delete [] pwszName;
  1185. return hr;
  1186. } //*** CExtObject::HrGetObjectName()
  1187. /////////////////////////////////////////////////////////////////////////////
  1188. //++
  1189. //
  1190. // CExtObject::HrGetClusterVersion
  1191. //
  1192. // Routine Description:
  1193. // Get the version of the cluster.
  1194. //
  1195. // Arguments:
  1196. // ppCvi [OUT] holds the Cluster version info.
  1197. //
  1198. // Return Value:
  1199. // NOERROR Data retrieved successfully.
  1200. // E_NOTIMPL Not implemented for this type of data.
  1201. // Any error codes from GetClusterInformation()
  1202. //
  1203. //--
  1204. /////////////////////////////////////////////////////////////////////////////
  1205. HRESULT CExtObject::HrGetClusterVersion(
  1206. OUT LPCLUSTERVERSIONINFO *ppCvi
  1207. )
  1208. {
  1209. ASSERT(ppCvi != NULL);
  1210. HRESULT hr = E_FAIL;
  1211. if (ppCvi != NULL)
  1212. {
  1213. if (m_pCvi == NULL)
  1214. {
  1215. LPWSTR pwszName = NULL;
  1216. DWORD cchName = 128;
  1217. CWaitCursor wc;
  1218. try
  1219. {
  1220. pwszName = new WCHAR[cchName];
  1221. m_pCvi = new CLUSTERVERSIONINFO;
  1222. m_pCvi->dwVersionInfoSize = sizeof( CLUSTERVERSIONINFO );
  1223. hr = GetClusterInformation(Hcluster(), pwszName, &cchName, m_pCvi);
  1224. if (hr == ERROR_MORE_DATA)
  1225. {
  1226. delete [] pwszName;
  1227. cchName++;
  1228. pwszName = new WCHAR[cchName];
  1229. hr = GetClusterInformation(Hcluster(), pwszName, &cchName, m_pCvi);
  1230. } // if: buffer is too small
  1231. delete [] pwszName;
  1232. *ppCvi = m_pCvi;
  1233. } // try
  1234. catch (CException *)
  1235. {
  1236. delete [] pwszName;
  1237. delete m_pCvi;
  1238. m_pCvi = NULL;
  1239. throw;
  1240. } // catch: CException
  1241. }
  1242. else
  1243. {
  1244. *ppCvi = m_pCvi;
  1245. hr = S_OK;
  1246. }
  1247. }
  1248. return hr;
  1249. } //*** CExtObject::HrGetClusterVersion()
  1250. /////////////////////////////////////////////////////////////////////////////
  1251. //++
  1252. //
  1253. // CExtObject::HrGetResourceTypeName
  1254. //
  1255. // Routine Description:
  1256. // Get the name of the resource's type.
  1257. //
  1258. // Arguments:
  1259. // piData IGetClusterResourceInfo interface pointer for getting
  1260. // the resource type name.
  1261. //
  1262. // Return Value:
  1263. // NOERROR Data saved successfully.
  1264. // E_NOTIMPL Not implemented for this type of data.
  1265. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  1266. // or HrGetResourceName().
  1267. //
  1268. //--
  1269. /////////////////////////////////////////////////////////////////////////////
  1270. HRESULT CExtObject::HrGetResourceTypeName(
  1271. IN OUT IGetClusterResourceInfo * pi
  1272. )
  1273. {
  1274. HRESULT hr = NOERROR;
  1275. WCHAR * pwszName = NULL;
  1276. LONG cchName;
  1277. BSTR bstr = NULL;
  1278. ASSERT(pi != NULL);
  1279. hr = pi->GetResourceTypeName(0, NULL, &cchName);
  1280. if (hr != NOERROR)
  1281. return hr;
  1282. bstr = SysAllocStringLen( NULL, cchName );
  1283. if ( bstr != NULL )
  1284. {
  1285. try
  1286. {
  1287. hr = pi->GetResourceTypeName(0, bstr, &cchName);
  1288. if (hr == NOERROR)
  1289. {
  1290. pwszName = new WCHAR[cchName];
  1291. hr = StringCchCopyNW( pwszName, cchName, bstr, SysStringLen( bstr ) );
  1292. if ( FAILED( hr ) )
  1293. {
  1294. goto Cleanup;
  1295. }
  1296. }
  1297. PrdResDataRW()->m_strResTypeName = pwszName;
  1298. } // try
  1299. catch (CMemoryException * pme)
  1300. {
  1301. pme->Delete();
  1302. hr = E_OUTOFMEMORY;
  1303. } // catch: CMemoryException
  1304. } // if: ( bstr != NULL )
  1305. else
  1306. {
  1307. hr = E_OUTOFMEMORY;
  1308. }
  1309. Cleanup:
  1310. SysFreeString( bstr );
  1311. delete [] pwszName;
  1312. return hr;
  1313. } //*** CExtObject::HrGetResourceTypeName()
  1314. /////////////////////////////////////////////////////////////////////////////
  1315. //++
  1316. //
  1317. // CExtObject::BGetResourceNetworkName
  1318. //
  1319. // Routine Description:
  1320. // Get the name of the resource's type.
  1321. //
  1322. // Arguments:
  1323. // lpszNetName [OUT] String in which to return the network name resource name.
  1324. // pcchNetName [IN OUT] Points to a variable that specifies the
  1325. // maximum size, in characters, of the buffer. This
  1326. // value shold be large enough to contain
  1327. // MAX_COMPUTERNAME_LENGTH + 1 characters. Upon
  1328. // return it contains the actual number of characters
  1329. // copied.
  1330. //
  1331. // Return Value:
  1332. // TRUE Resource is dependent on a network name resource.
  1333. // FALSE Resource is NOT dependent on a network name resource.
  1334. //
  1335. //--
  1336. /////////////////////////////////////////////////////////////////////////////
  1337. BOOL CExtObject::BGetResourceNetworkName(
  1338. OUT WCHAR * lpszNetName,
  1339. IN OUT DWORD * pcchNetName
  1340. )
  1341. {
  1342. BOOL bSuccess = TRUE;
  1343. HRESULT hr = S_OK;
  1344. IGetClusterResourceInfo * piGcri = NULL;
  1345. BSTR bstr = NULL;
  1346. DWORD cchNetName;
  1347. ASSERT(PiData() != NULL);
  1348. if ( ( lpszNetName == NULL )
  1349. || ( pcchNetName == NULL ) )
  1350. {
  1351. hr = E_INVALIDARG;
  1352. goto Cleanup;
  1353. }
  1354. // Get an IGetClusterResourceInfo interface pointer.
  1355. {
  1356. hr = PiData()->QueryInterface(IID_IGetClusterResourceInfo, (LPVOID *) &piGcri);
  1357. if (hr != NOERROR)
  1358. {
  1359. goto Cleanup;
  1360. } // if: error getting the interface
  1361. } // Get an IGetClusterResourceInfo interface pointer
  1362. bstr = SysAllocStringLen( NULL, *pcchNetName );
  1363. if ( bstr == NULL )
  1364. {
  1365. hr = E_OUTOFMEMORY;
  1366. goto Cleanup;
  1367. }
  1368. // Get the resource network name.
  1369. cchNetName = *pcchNetName;
  1370. bSuccess = piGcri->GetResourceNetworkName(0, bstr, &cchNetName);
  1371. if ( bSuccess == TRUE )
  1372. {
  1373. hr = StringCchCopyNW( lpszNetName, *pcchNetName, bstr, SysStringLen( bstr ) );
  1374. if ( FAILED( hr ) )
  1375. {
  1376. goto Cleanup;
  1377. }
  1378. }
  1379. Cleanup:
  1380. SysFreeString( bstr );
  1381. if ( piGcri != NULL )
  1382. {
  1383. piGcri->Release();
  1384. }
  1385. if ( hr != S_OK )
  1386. {
  1387. SetLastError( hr );
  1388. if ( FAILED( hr ) )
  1389. {
  1390. bSuccess = FALSE;
  1391. }
  1392. }
  1393. return bSuccess;
  1394. } //*** CExtObject::BGetResourceNetworkName()
  1395. /////////////////////////////////////////////////////////////////////////////
  1396. //++
  1397. //
  1398. // CExtObject::BIsClusterVersionMixed
  1399. //
  1400. // Routine Description:
  1401. // Is the cluster of mixed version? Meaning that a rolling upgrade is
  1402. // is in progress and not all nodes are up to the current version.
  1403. //
  1404. // Arguments:
  1405. // none.
  1406. //
  1407. // Return Value:
  1408. // TRUE Cluster is mixed version
  1409. // FALSE Cluster is homogonous
  1410. //
  1411. //--
  1412. /////////////////////////////////////////////////////////////////////////////
  1413. BOOL CExtObject::BIsClusterVersionMixed(
  1414. void
  1415. )
  1416. {
  1417. BOOL bRet = FALSE;
  1418. LPCLUSTERVERSIONINFO pCvi;
  1419. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1420. {
  1421. bRet = pCvi->dwFlags & CLUSTER_VERSION_FLAG_MIXED_MODE;
  1422. }
  1423. return bRet;
  1424. } //*** CExtObject::BIsClusterVersionMixed()
  1425. #if 0
  1426. //SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster or a pure sp3 cluster
  1427. /////////////////////////////////////////////////////////////////////////////
  1428. //++
  1429. //
  1430. // CExtObject::BIsClusterVersionNT4Sp3
  1431. //
  1432. // Routine Description:
  1433. // Is the cluster version NT4Sp3?
  1434. //
  1435. // Arguments:
  1436. // none.
  1437. //
  1438. // Return Value:
  1439. // TRUE Cluster is version NT4Sp3
  1440. // FALSE Cluster is not version NT4Sp3
  1441. //
  1442. //--
  1443. /////////////////////////////////////////////////////////////////////////////
  1444. BOOL CExtObject::BIsClusterVersionNT4Sp3(
  1445. void
  1446. )
  1447. {
  1448. LPCLUSTERVERSIONINFO pCvi;
  1449. BOOL bRet = FALSE;
  1450. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1451. {
  1452. if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4_MAJOR_VERSION) &&
  1453. !(BIsClusterVersionMixed()))
  1454. {
  1455. bRet = TRUE;
  1456. }
  1457. }
  1458. return bRet;
  1459. } //*** CExtObject::BIsClusterVersionNT4Sp3()
  1460. #endif//SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster or a pure sp3 cluster
  1461. /////////////////////////////////////////////////////////////////////////////
  1462. //++
  1463. //
  1464. // CExtObject::BIsClusterVersionNT4Sp4
  1465. //
  1466. // Routine Description:
  1467. // Is the cluster version a pure NT4Sp4 cluster
  1468. //
  1469. // Arguments:
  1470. // none.
  1471. //
  1472. // Return Value:
  1473. // TRUE Cluster is version NT4Sp4
  1474. // FALSE Cluster is not version NT4Sp4
  1475. //
  1476. //--
  1477. /////////////////////////////////////////////////////////////////////////////
  1478. BOOL CExtObject::BIsClusterVersionNT4Sp4(
  1479. void
  1480. )
  1481. {
  1482. LPCLUSTERVERSIONINFO pCvi;
  1483. BOOL bRet = FALSE;
  1484. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1485. {
  1486. if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4SP4_MAJOR_VERSION) &&
  1487. !(BIsClusterVersionMixed()))
  1488. {
  1489. bRet = TRUE;
  1490. }
  1491. }
  1492. return bRet;
  1493. } //*** CExtObject::BIsClusterVersionNT4Sp4()
  1494. /////////////////////////////////////////////////////////////////////////////
  1495. //++
  1496. //
  1497. // CExtObject::BIsClusterVersionNT5
  1498. //
  1499. // Routine Description:
  1500. // Is the cluster version a pure NT5 version?
  1501. //
  1502. // Arguments:
  1503. // none.
  1504. //
  1505. // Return Value:
  1506. // TRUE Cluster is version NT5
  1507. // FALSE Cluster is not version NT5
  1508. //
  1509. //--
  1510. /////////////////////////////////////////////////////////////////////////////
  1511. BOOL CExtObject::BIsClusterVersionNT5(
  1512. void
  1513. )
  1514. {
  1515. LPCLUSTERVERSIONINFO pCvi;
  1516. BOOL bRet = FALSE;
  1517. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1518. {
  1519. if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT5_MAJOR_VERSION) &&
  1520. !(BIsClusterVersionMixed()))
  1521. {
  1522. bRet = TRUE;
  1523. }
  1524. }
  1525. return bRet;
  1526. } //*** CExtObject::BIsClusterVersionNT5()
  1527. #if 0
  1528. //SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster
  1529. //or a pure sp3 cluster
  1530. /////////////////////////////////////////////////////////////////////////////
  1531. //++
  1532. //
  1533. // CExtObject::BIsClusterHighestVersionNT4Sp3
  1534. //
  1535. // Routine Description:
  1536. // Is the highest cluster version NT4Sp3?
  1537. //
  1538. // Arguments:
  1539. // none.
  1540. //
  1541. // Return Value:
  1542. // TRUE highest cluster is version NT4Sp3
  1543. // FALSE highest cluster is not version NT4Sp3
  1544. //
  1545. //--
  1546. /////////////////////////////////////////////////////////////////////////////
  1547. BOOL CExtObject::BIsClusterHighestVersionNT4Sp3(
  1548. void
  1549. )
  1550. {
  1551. LPCLUSTERVERSIONINFO pCvi;
  1552. BOOL bRet = FALSE;
  1553. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1554. {
  1555. if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterLowestVersion) == NT4_MAJOR_VERSION)
  1556. {
  1557. bRet = TRUE;
  1558. }
  1559. }
  1560. return bRet;
  1561. } //*** CExtObject::BIsClusterHighestVersionNT4Sp3()
  1562. /////////////////////////////////////////////////////////////////////////////
  1563. //++
  1564. //
  1565. // CExtObject::BIsClusterHighestVersionNT4Sp4
  1566. //
  1567. // Routine Description:
  1568. // Is the highest cluster version NT4Sp4?
  1569. //
  1570. // Arguments:
  1571. // none.
  1572. //
  1573. // Return Value:
  1574. // TRUE highest cluster is version NT4Sp4
  1575. // FALSE highest cluster is not version NT4Sp4
  1576. //
  1577. //--
  1578. /////////////////////////////////////////////////////////////////////////////
  1579. BOOL CExtObject::BIsClusterHighestVersionNT4Sp4(
  1580. void
  1581. )
  1582. {
  1583. LPCLUSTERVERSIONINFO pCvi;
  1584. BOOL bRet = FALSE;
  1585. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1586. {
  1587. if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterLowestVersion) == NT4_MAJOR_VERSION)
  1588. {
  1589. bRet = TRUE;
  1590. }
  1591. }
  1592. return bRet;
  1593. } //*** CExtObject::BIsClusterHighestVersionNT4Sp4()
  1594. #endif //SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster or a pure sp3 cluster
  1595. /////////////////////////////////////////////////////////////////////////////
  1596. //++
  1597. //
  1598. // CExtObject::BIsClusterHighestVersionNT5
  1599. //
  1600. // Routine Description:
  1601. // Is the highest cluster version NT5? Is the node with the
  1602. // highest version in the cluster an nt 5 node.
  1603. //
  1604. // Arguments:
  1605. // none.
  1606. //
  1607. // Return Value:
  1608. // TRUE highest cluster is version NT5
  1609. // FALSE highest cluster is not version NT5
  1610. //
  1611. //--
  1612. /////////////////////////////////////////////////////////////////////////////
  1613. BOOL CExtObject::BIsClusterHighestVersionNT5(
  1614. void
  1615. )
  1616. {
  1617. LPCLUSTERVERSIONINFO pCvi;
  1618. BOOL bRet = FALSE;
  1619. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1620. {
  1621. if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterLowestVersion) == NT4SP4_MAJOR_VERSION)
  1622. {
  1623. bRet = TRUE;
  1624. }
  1625. }
  1626. return bRet;
  1627. } //*** CExtObject::BIsClusterHighestVersionNT5()
  1628. /////////////////////////////////////////////////////////////////////////////
  1629. //++
  1630. //
  1631. // CExtObject::BIsClusterLowestVersionNT4Sp3
  1632. //
  1633. // Routine Description:
  1634. // Is the Lowest cluster version NT4Sp3? Is the node with the lowest
  1635. // version an nt4 sp3 node
  1636. //
  1637. // Arguments:
  1638. // none.
  1639. //
  1640. // Return Value:
  1641. // TRUE Lowest cluster is version NT4Sp3
  1642. // FALSE Lowest cluster is not version NT4Sp3
  1643. //
  1644. //--
  1645. /////////////////////////////////////////////////////////////////////////////
  1646. BOOL CExtObject::BIsClusterLowestVersionNT4Sp3(
  1647. void
  1648. )
  1649. {
  1650. LPCLUSTERVERSIONINFO pCvi;
  1651. BOOL bRet = FALSE;
  1652. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1653. {
  1654. if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4_MAJOR_VERSION)
  1655. {
  1656. bRet = TRUE;
  1657. }
  1658. }
  1659. return bRet;
  1660. } //*** CExtObject::BIsClusterLowestVersionNT4Sp3()
  1661. /////////////////////////////////////////////////////////////////////////////
  1662. //++
  1663. //
  1664. // CExtObject::BIsClusterLowestVersionNT4Sp4
  1665. //
  1666. // Routine Description:
  1667. // Is the Lowest cluster version NT4Sp4?Is the node with the lowest
  1668. // version an nt4 sp4 node.
  1669. //
  1670. // Arguments:
  1671. // none.
  1672. //
  1673. // Return Value:
  1674. // TRUE Lowest cluster is version NT4Sp4
  1675. // FALSE Lowest cluster is not version NT4Sp4
  1676. //
  1677. //--
  1678. /////////////////////////////////////////////////////////////////////////////
  1679. BOOL CExtObject::BIsClusterLowestVersionNT4Sp4(
  1680. void
  1681. )
  1682. {
  1683. LPCLUSTERVERSIONINFO pCvi;
  1684. BOOL bRet = FALSE;
  1685. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1686. {
  1687. if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4SP4_MAJOR_VERSION)
  1688. {
  1689. bRet = TRUE;
  1690. }
  1691. }
  1692. return bRet;
  1693. } //*** CExtObject::BIsClusterLowestVersionNT4Sp4()
  1694. /////////////////////////////////////////////////////////////////////////////
  1695. //++
  1696. //
  1697. // CExtObject::BIsClusterLowestVersionNT5
  1698. //
  1699. // Routine Description:
  1700. // Is the Lowest cluster version NT5?Is the node with the lowest
  1701. // version an nt5 node
  1702. //
  1703. // Arguments:
  1704. // none.
  1705. //
  1706. // Return Value:
  1707. // TRUE Lowest cluster is version NT5
  1708. // FALSE Lowest cluster is not version NT5
  1709. //
  1710. //--
  1711. /////////////////////////////////////////////////////////////////////////////
  1712. BOOL CExtObject::BIsClusterLowestVersionNT5(
  1713. void
  1714. )
  1715. {
  1716. LPCLUSTERVERSIONINFO pCvi;
  1717. BOOL bRet = FALSE;
  1718. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1719. {
  1720. if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT5_MAJOR_VERSION)
  1721. {
  1722. bRet = TRUE;
  1723. }
  1724. }
  1725. return bRet;
  1726. } //*** CExtObject::BIsClusterLowestVersionNT5()
  1727. /////////////////////////////////////////////////////////////////////////////
  1728. //++
  1729. //
  1730. // CExtObject::BIsAnyNodeVersionLowerThanNT5
  1731. //
  1732. // Routine Description:
  1733. // Is the Lowest cluster version NT5?Is the node with the lowest
  1734. // version an nt5 node
  1735. //
  1736. // Arguments:
  1737. // none.
  1738. //
  1739. // Return Value:
  1740. // TRUE Lowest cluster is version NT5
  1741. // FALSE Lowest cluster is not version NT5
  1742. //
  1743. //--
  1744. /////////////////////////////////////////////////////////////////////////////
  1745. BOOL CExtObject::BIsAnyNodeVersionLowerThanNT5(
  1746. void
  1747. )
  1748. {
  1749. LPCLUSTERVERSIONINFO pCvi;
  1750. BOOL bRet = FALSE;
  1751. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1752. {
  1753. if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) < NT5_MAJOR_VERSION)
  1754. {
  1755. bRet = TRUE;
  1756. }
  1757. }
  1758. return bRet;
  1759. } //*** CExtObject::BIsClusterLowestVersionNT5()
  1760. /////////////////////////////////////////////////////////////////////////////
  1761. //++
  1762. //
  1763. // CExtObject::BIsNT5ClusterMember
  1764. //
  1765. // Routine Description:
  1766. // Is NT5 a cluster member?
  1767. //
  1768. // Arguments:
  1769. // none.
  1770. //
  1771. // Return Value:
  1772. // TRUE NT5 is a cluster member
  1773. // FALSE NT5 is not a cluster member
  1774. //
  1775. //--
  1776. /////////////////////////////////////////////////////////////////////////////
  1777. BOOL CExtObject::BIsNT5ClusterMember(
  1778. void
  1779. )
  1780. {
  1781. LPCLUSTERVERSIONINFO pCvi;
  1782. BOOL bRet = FALSE;
  1783. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1784. {
  1785. if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT5_MAJOR_VERSION)
  1786. || (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterLowestVersion) == NT4SP4_MAJOR_VERSION))
  1787. {
  1788. bRet = TRUE;
  1789. }
  1790. }
  1791. return bRet;
  1792. } //*** CExtObject::BIsNT5ClusterMember()
  1793. #if 0
  1794. //SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster
  1795. //or a pure sp3 cluster
  1796. /////////////////////////////////////////////////////////////////////////////
  1797. //++
  1798. //
  1799. // CExtObject::BIsNT4Sp3ClusterMember
  1800. //
  1801. // Routine Description:
  1802. // Is NT4Sp3 a cluster member?
  1803. //
  1804. // Arguments:
  1805. // none.
  1806. //
  1807. // Return Value:
  1808. // TRUE NT4Sp3 is a cluster member
  1809. // FALSE NT4Sp3 is not a cluster member
  1810. //
  1811. //--
  1812. /////////////////////////////////////////////////////////////////////////////
  1813. BOOL CExtObject::BIsNT4Sp3ClusterMember(
  1814. void
  1815. )
  1816. {
  1817. LPCLUSTERVERSIONINFO pCvi;
  1818. BOOL bRet = FALSE;
  1819. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1820. {
  1821. if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4_MAJOR_VERSION))
  1822. {
  1823. bRet = TRUE;
  1824. }
  1825. }
  1826. return bRet;
  1827. } //*** CExtObject::BIsNT4Sp3ClusterMember()
  1828. /////////////////////////////////////////////////////////////////////////////
  1829. //++
  1830. //
  1831. // CExtObject::BIsNT4Sp4ClusterMember
  1832. //
  1833. // Routine Description:
  1834. // Is NT4Sp4 a cluster member?
  1835. //
  1836. // Arguments:
  1837. // none.
  1838. //
  1839. // Return Value:
  1840. // TRUE NT4Sp4 is a cluster member
  1841. // FALSE NT4Sp4 is not a cluster member
  1842. //
  1843. //--
  1844. /////////////////////////////////////////////////////////////////////////////
  1845. BOOL CExtObject::BIsNT4Sp4ClusterMember(
  1846. void
  1847. )
  1848. {
  1849. LPCLUSTERVERSIONINFO pCvi;
  1850. BOOL bRet = FALSE;
  1851. if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
  1852. {
  1853. if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4SP4_MAJOR_VERSION))
  1854. {
  1855. bRet = TRUE;
  1856. }
  1857. }
  1858. return bRet;
  1859. } //*** CExtObject::BIsNT4Sp4ClusterMember()
  1860. #endif