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.

1871 lines
52 KiB

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