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.

635 lines
18 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ExtObj.cpp
  7. //
  8. // Description:
  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. // Maintained By:
  14. // David Potter (DavidP) Mmmm DD, 1997
  15. //
  16. // Revision History:
  17. //
  18. // Notes:
  19. //
  20. /////////////////////////////////////////////////////////////////////////////
  21. #include "stdafx.h"
  22. #include "DebugEx.h"
  23. #include "ExtObj.h"
  24. #include "ResProp.h"
  25. /////////////////////////////////////////////////////////////////////////////
  26. // Global Variables
  27. /////////////////////////////////////////////////////////////////////////////
  28. static CRuntimeClass * g_rgprtcResPSPages[] = {
  29. RUNTIME_CLASS(CDebugParamsPage),
  30. NULL
  31. };
  32. static CRuntimeClass ** g_rgpprtcResPSPages[] = {
  33. g_rgprtcResPSPages,
  34. };
  35. static CRuntimeClass * g_rgprtcResTypePSPages[] = {
  36. RUNTIME_CLASS(CDebugParamsPage),
  37. NULL
  38. };
  39. static CRuntimeClass ** g_rgpprtcResTypePSPages[] = {
  40. g_rgprtcResTypePSPages,
  41. };
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CExtObject
  44. /////////////////////////////////////////////////////////////////////////////
  45. /////////////////////////////////////////////////////////////////////////////
  46. //++
  47. //
  48. // CExtObject::CExtObject
  49. //
  50. // Routine Description:
  51. // Default constructor.
  52. //
  53. // Arguments:
  54. // None.
  55. //
  56. // Return Value:
  57. // None.
  58. //
  59. //--
  60. /////////////////////////////////////////////////////////////////////////////
  61. CExtObject::CExtObject(void)
  62. {
  63. m_piData = NULL;
  64. m_bWizard = FALSE;
  65. m_istrResTypeName = 0;
  66. m_lcid = NULL;
  67. m_hfont = NULL;
  68. m_hicon = NULL;
  69. m_hcluster = NULL;
  70. m_cobj = 0;
  71. m_podObjData = NULL;
  72. } //*** CExtObject::CExtObject()
  73. /////////////////////////////////////////////////////////////////////////////
  74. //++
  75. //
  76. // CExtObject::~CExtObject
  77. //
  78. // Routine Description:
  79. // Destructor.
  80. //
  81. // Arguments:
  82. // None.
  83. //
  84. // Return Value:
  85. // None.
  86. //
  87. //--
  88. /////////////////////////////////////////////////////////////////////////////
  89. CExtObject::~CExtObject(void)
  90. {
  91. // Release the data interface.
  92. if (PiData() != NULL)
  93. {
  94. PiData()->Release();
  95. m_piData = NULL;
  96. } // if: we have a data interface pointer
  97. // Delete the pages.
  98. {
  99. POSITION pos;
  100. pos = Lpg().GetHeadPosition();
  101. while (pos != NULL)
  102. delete Lpg().GetNext(pos);
  103. } // Delete the pages
  104. delete m_podObjData;
  105. } //*** CExtObject::~CExtObject()
  106. /////////////////////////////////////////////////////////////////////////////
  107. // ISupportErrorInfo Implementation
  108. /////////////////////////////////////////////////////////////////////////////
  109. //++
  110. //
  111. // CExtObject::InterfaceSupportsErrorInfo (ISupportErrorInfo)
  112. //
  113. // Routine Description:
  114. // Indicates whether an interface suportes the IErrorInfo interface.
  115. // This interface is provided by ATL.
  116. //
  117. // Arguments:
  118. // riid Interface ID.
  119. //
  120. // Return Value:
  121. // S_OK Interface supports IErrorInfo.
  122. // S_FALSE Interface does not support IErrorInfo.
  123. //
  124. //--
  125. /////////////////////////////////////////////////////////////////////////////
  126. STDMETHODIMP CExtObject::InterfaceSupportsErrorInfo(REFIID riid)
  127. {
  128. static const IID * rgiid[] =
  129. {
  130. &IID_IWEExtendPropertySheet,
  131. };
  132. int iiid;
  133. for (iiid = 0 ; iiid < sizeof(rgiid) / sizeof(rgiid[0]) ; iiid++)
  134. {
  135. if (InlineIsEqualGUID(*rgiid[iiid], riid))
  136. return S_OK;
  137. }
  138. return S_FALSE;
  139. } //*** CExtObject::InterfaceSupportsErrorInfo()
  140. /////////////////////////////////////////////////////////////////////////////
  141. // IWEExtendPropertySheet Implementation
  142. /////////////////////////////////////////////////////////////////////////////
  143. //++
  144. //
  145. // CExtObject::CreatePropertySheetPages (IWEExtendPropertySheet)
  146. //
  147. // Routine Description:
  148. // Create property sheet pages and add them to the sheet.
  149. //
  150. // Arguments:
  151. // piData IUnkown pointer from which to obtain interfaces
  152. // for obtaining data describing the object for
  153. // which the sheet is being displayed.
  154. // piCallback Pointer to an IWCPropertySheetCallback interface
  155. // for adding pages to the sheet.
  156. //
  157. // Return Value:
  158. // NOERROR Pages added successfully.
  159. // E_INVALIDARG Invalid arguments to the function.
  160. // E_OUTOFMEMORY Error allocating memory.
  161. // E_FAIL Error creating a page.
  162. // E_NOTIMPL Not implemented for this type of data.
  163. // Any error codes from IDataObject::GetData() (through HrSaveData()).
  164. //
  165. //--
  166. /////////////////////////////////////////////////////////////////////////////
  167. STDMETHODIMP CExtObject::CreatePropertySheetPages(
  168. IN IUnknown * piData,
  169. IN IWCPropertySheetCallback * piCallback
  170. )
  171. {
  172. HRESULT hr = NOERROR;
  173. HPROPSHEETPAGE hpage = NULL;
  174. CException exc(FALSE /*bAutoDelete*/);
  175. CRuntimeClass ** pprtc = NULL;
  176. int irtc;
  177. CBasePropertyPage * ppage;
  178. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  179. // Validate the parameters.
  180. if ((piData == NULL) || (piCallback == NULL))
  181. return E_INVALIDARG;
  182. try
  183. {
  184. // Get info about displaying UI.
  185. hr = HrGetUIInfo(piData);
  186. if (hr != NOERROR)
  187. throw &exc;
  188. // Save the data.
  189. hr = HrSaveData(piData);
  190. if (hr != NOERROR)
  191. throw &exc;
  192. // Delete any previous pages.
  193. {
  194. POSITION pos;
  195. pos = Lpg().GetHeadPosition();
  196. while (pos != NULL)
  197. delete Lpg().GetNext(pos);
  198. Lpg().RemoveAll();
  199. } // Delete any previous pages
  200. // Create property pages.
  201. ASSERT(PodObjData() != NULL);
  202. switch (PodObjData()->m_cot)
  203. {
  204. case CLUADMEX_OT_RESOURCE:
  205. pprtc = g_rgpprtcResPSPages[0];
  206. break;
  207. case CLUADMEX_OT_RESOURCETYPE:
  208. pprtc = g_rgpprtcResTypePSPages[0];
  209. break;
  210. default:
  211. hr = E_NOTIMPL;
  212. throw &exc;
  213. break;
  214. } // switch: object type
  215. // Create each page.
  216. for (irtc = 0 ; pprtc[irtc] != NULL ; irtc++)
  217. {
  218. // Create the page.
  219. ppage = (CBasePropertyPage *) pprtc[irtc]->CreateObject();
  220. ASSERT(ppage->IsKindOf(pprtc[irtc]));
  221. // Add it to the list.
  222. Lpg().AddTail(ppage);
  223. // Initialize the property page.
  224. if (!ppage->BInit(this))
  225. throw &exc;
  226. // Create the page.
  227. hpage = ::CreatePropertySheetPage(&ppage->m_psp);
  228. if (hpage == NULL)
  229. throw &exc;
  230. // Save the hpage in the page itself.
  231. ppage->SetHpage(hpage);
  232. // Add it to the property sheet.
  233. hr = piCallback->AddPropertySheetPage((LONG *) hpage);
  234. if (hr != NOERROR)
  235. throw &exc;
  236. } // for: each page in the list
  237. } // try
  238. catch (CMemoryException * pme)
  239. {
  240. TRACE(_T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n"));
  241. pme->Delete();
  242. hr = E_OUTOFMEMORY;
  243. } // catch: anything
  244. catch (CException * pe)
  245. {
  246. TRACE(_T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n"));
  247. pe->Delete();
  248. if (hr == NOERROR)
  249. hr = E_FAIL;
  250. } // catch: anything
  251. if (hr != NOERROR)
  252. {
  253. if (hpage != NULL)
  254. ::DestroyPropertySheetPage(hpage);
  255. piData->Release();
  256. m_piData = NULL;
  257. } // if: error occurred
  258. piCallback->Release();
  259. return hr;
  260. } //*** CExtObject::CreatePropertySheetPages()
  261. /////////////////////////////////////////////////////////////////////////////
  262. //++
  263. //
  264. // CExtObject::HrGetUIInfo
  265. //
  266. // Routine Description:
  267. // Get info about displaying UI.
  268. //
  269. // Arguments:
  270. // piData IUnkown pointer from which to obtain interfaces
  271. // for obtaining data describing the object.
  272. //
  273. // Return Value:
  274. // NOERROR Data saved successfully.
  275. // E_NOTIMPL Not implemented for this type of data.
  276. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  277. // or HrGetResourceName().
  278. //
  279. //--
  280. /////////////////////////////////////////////////////////////////////////////
  281. HRESULT CExtObject::HrGetUIInfo(IUnknown * piData)
  282. {
  283. HRESULT hr = NOERROR;
  284. ASSERT(piData != NULL);
  285. // Save info about all types of objects.
  286. {
  287. IGetClusterUIInfo * pi;
  288. hr = piData->QueryInterface(IID_IGetClusterUIInfo, (LPVOID *) &pi);
  289. if (hr != NOERROR)
  290. return hr;
  291. m_lcid = pi->GetLocale();
  292. m_hfont = pi->GetFont();
  293. m_hicon = pi->GetIcon();
  294. pi->Release();
  295. } // Save info about all types of objects
  296. return hr;
  297. } //*** CExtObject::HrGetUIInfo()
  298. /////////////////////////////////////////////////////////////////////////////
  299. //++
  300. //
  301. // CExtObject::HrSaveData
  302. //
  303. // Routine Description:
  304. // Save data from the object so that it can be used for the life
  305. // of the object.
  306. //
  307. // Arguments:
  308. // piData IUnkown pointer from which to obtain interfaces
  309. // for obtaining data describing the object.
  310. //
  311. // Return Value:
  312. // NOERROR Data saved successfully.
  313. // E_NOTIMPL Not implemented for this type of data.
  314. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  315. // or HrGetResourceName().
  316. //
  317. //--
  318. /////////////////////////////////////////////////////////////////////////////
  319. HRESULT CExtObject::HrSaveData(IUnknown * piData)
  320. {
  321. HRESULT hr = NOERROR;
  322. ASSERT(piData != NULL);
  323. if (piData != m_piData)
  324. {
  325. if (m_piData != NULL)
  326. m_piData->Release();
  327. m_piData = piData;
  328. } // if: different data interface pointer
  329. // Save info about all types of objects.
  330. {
  331. IGetClusterDataInfo * pi;
  332. hr = piData->QueryInterface(IID_IGetClusterDataInfo, (LPVOID *) &pi);
  333. if (hr != NOERROR)
  334. return hr;
  335. m_hcluster = pi->GetClusterHandle();
  336. m_cobj = pi->GetObjectCount();
  337. if (Cobj() != 1) // Only have support for one selected object.
  338. hr = E_NOTIMPL;
  339. pi->Release();
  340. if (hr != NOERROR)
  341. return hr;
  342. } // Save info about all types of objects
  343. // Save info about this object.
  344. hr = HrGetObjectInfo();
  345. if (hr != NOERROR)
  346. return hr;
  347. return hr;
  348. } //*** CExtObject::HrSaveData()
  349. /////////////////////////////////////////////////////////////////////////////
  350. //++
  351. //
  352. // CExtObject::HrGetObjectInfo
  353. //
  354. // Routine Description:
  355. // Get information about the object.
  356. //
  357. // Arguments:
  358. // None.
  359. //
  360. // Return Value:
  361. // NOERROR Data saved successfully.
  362. // E_OUTOFMEMORY Error allocating memory.
  363. // E_NOTIMPL Not implemented for this type of data.
  364. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
  365. // or HrGetResourceTypeName().
  366. //
  367. //--
  368. /////////////////////////////////////////////////////////////////////////////
  369. HRESULT CExtObject::HrGetObjectInfo(void)
  370. {
  371. HRESULT hr = NOERROR;
  372. IGetClusterObjectInfo * piGcoi;
  373. CLUADMEX_OBJECT_TYPE cot;
  374. CException exc(FALSE /*bAutoDelete*/);
  375. ASSERT(PiData() != NULL);
  376. // Get object info.
  377. {
  378. // Get an IGetClusterObjectInfo interface pointer.
  379. hr = PiData()->QueryInterface(IID_IGetClusterObjectInfo, (LPVOID *) &piGcoi);
  380. if (hr != NOERROR)
  381. return hr;
  382. // Read the object data.
  383. try
  384. {
  385. // Delete the previous object data.
  386. delete m_podObjData;
  387. m_podObjData = NULL;
  388. // Get the type of the object.
  389. cot = piGcoi->GetObjectType(0);
  390. switch (cot)
  391. {
  392. case CLUADMEX_OT_RESOURCE:
  393. {
  394. IGetClusterResourceInfo * pi;
  395. m_podObjData = new CResData;
  396. // Get an IGetClusterResourceInfo interface pointer.
  397. hr = PiData()->QueryInterface(IID_IGetClusterResourceInfo, (LPVOID *) &pi);
  398. if (hr != NOERROR)
  399. throw &exc;
  400. PrdResDataRW()->m_hresource = pi->GetResourceHandle(0);
  401. hr = HrGetResourceTypeName(pi);
  402. pi->Release();
  403. if (hr != NOERROR)
  404. throw &exc;
  405. } // if: object is a node
  406. break;
  407. case CLUADMEX_OT_RESOURCETYPE:
  408. m_podObjData = new CObjData;
  409. break;
  410. default:
  411. hr = E_NOTIMPL;
  412. throw &exc;
  413. } // switch: object type
  414. PodObjDataRW()->m_cot = cot;
  415. hr = HrGetObjectName(piGcoi);
  416. } // try
  417. catch (CException * pe)
  418. {
  419. pe->Delete();
  420. } // catch: CException
  421. piGcoi->Release();
  422. if (hr != NOERROR)
  423. return hr;
  424. } // Get object info
  425. return hr;
  426. } //*** CExtObject::HrGetObjectInfo()
  427. /////////////////////////////////////////////////////////////////////////////
  428. //++
  429. //
  430. // CExtObject::HrGetObjectName
  431. //
  432. // Routine Description:
  433. // Get the name of the object.
  434. //
  435. // Arguments:
  436. // piData IGetClusterObjectInfo interface pointer for getting
  437. // the object name.
  438. //
  439. // Return Value:
  440. // NOERROR Data saved successfully.
  441. // E_OUTOFMEMORY Error allocating memory.
  442. // E_NOTIMPL Not implemented for this type of data.
  443. // Any error codes from IGetClusterObjectInfo::GetObjectInfo().
  444. //
  445. //--
  446. /////////////////////////////////////////////////////////////////////////////
  447. HRESULT CExtObject::HrGetObjectName(
  448. IN OUT IGetClusterObjectInfo * pi
  449. )
  450. {
  451. HRESULT hr = NOERROR;
  452. WCHAR * pwszName = NULL;
  453. LONG cchName;
  454. BSTR bstr = NULL;
  455. ASSERT(pi != NULL);
  456. hr = pi->GetObjectName(0, NULL, &cchName);
  457. if (hr != NOERROR)
  458. return hr;
  459. bstr = SysAllocStringLen( NULL, cchName );
  460. if ( bstr != NULL )
  461. {
  462. try
  463. {
  464. hr = pi->GetObjectName(0, bstr, &cchName);
  465. if (hr == NOERROR)
  466. {
  467. pwszName = new WCHAR[cchName];
  468. hr = StringCchCopyNW( pwszName, cchName, bstr, SysStringLen( bstr ) );
  469. if ( FAILED( hr ) )
  470. {
  471. goto Cleanup;
  472. }
  473. }
  474. PodObjDataRW()->m_strName = pwszName;
  475. } // try
  476. catch (CMemoryException * pme)
  477. {
  478. pme->Delete();
  479. hr = E_OUTOFMEMORY;
  480. } // catch: CMemoryException
  481. } // if: ( bstr != NULL )
  482. else
  483. {
  484. hr = E_OUTOFMEMORY;
  485. }
  486. Cleanup:
  487. delete [] pwszName;
  488. SysFreeString( bstr );
  489. return hr;
  490. } //*** CExtObject::HrGetObjectName()
  491. /////////////////////////////////////////////////////////////////////////////
  492. //++
  493. //
  494. // CExtObject::HrGetResourceTypeName
  495. //
  496. // Routine Description:
  497. // Get the name of the resource's type.
  498. //
  499. // Arguments:
  500. // piData IGetClusterResourceInfo interface pointer for getting
  501. // the resource type name.
  502. //
  503. // Return Value:
  504. // NOERROR Data saved successfully.
  505. // E_OUTOFMEMORY Error allocating memory.
  506. // E_NOTIMPL Not implemented for this type of data.
  507. // Any error codes from IGetClusterResourceInfo::GetResourceTypeName().
  508. //
  509. //--
  510. /////////////////////////////////////////////////////////////////////////////
  511. HRESULT CExtObject::HrGetResourceTypeName(
  512. IN OUT IGetClusterResourceInfo * pi
  513. )
  514. {
  515. HRESULT hr = NOERROR;
  516. WCHAR * pwszName = NULL;
  517. LONG cchName;
  518. BSTR bstr = NULL;
  519. ASSERT(pi != NULL);
  520. hr = pi->GetResourceTypeName(0, NULL, &cchName);
  521. if (hr != NOERROR)
  522. return hr;
  523. bstr = SysAllocStringLen( NULL, cchName );
  524. if ( bstr != NULL )
  525. {
  526. try
  527. {
  528. hr = pi->GetResourceTypeName(0, bstr, &cchName);
  529. if (hr == NOERROR)
  530. {
  531. pwszName = new WCHAR[cchName];
  532. hr = StringCchCopyNW( pwszName, cchName, bstr, SysStringLen( bstr ) );
  533. if ( FAILED( hr ) );
  534. {
  535. goto Cleanup;
  536. }
  537. }
  538. PrdResDataRW()->m_strResTypeName = pwszName;
  539. } // try
  540. catch (CMemoryException * pme)
  541. {
  542. pme->Delete();
  543. hr = E_OUTOFMEMORY;
  544. } // catch: CMemoryException
  545. } // if: ( bstr != NULL )
  546. else
  547. {
  548. hr = E_OUTOFMEMORY;
  549. }
  550. Cleanup:
  551. delete [] pwszName;
  552. SysFreeString( bstr );
  553. return hr;
  554. } //*** CExtObject::HrGetResourceTypeName()