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.

7192 lines
138 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. cinetmgr.cpp
  5. Abstract:
  6. Snapin object
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "inetmgr.h"
  18. #include "cinetmgr.h"
  19. #include "connects.h"
  20. #include "dataobj.h"
  21. #include "afxdlgs.h"
  22. #include "constr.h"
  23. #include "metaback.h"
  24. #include "shutdown.h"
  25. #include <shlwapi.h>
  26. #if !MSDEV_BUILD
  27. //
  28. // An odd difference between vc++ and sdk environments.
  29. //
  30. #include <atlimpl.cpp>
  31. #endif !MSDEV_BUILD
  32. #ifdef _DEBUG
  33. #define new DEBUG_NEW
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37. //
  38. // Image background colour for the toolbar buttons
  39. //
  40. #define RGB_BK_IMAGES (RGB(255,0,255)) // purple
  41. #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
  42. static HRESULT
  43. GetSnapinHelpFile(LPOLESTR * lpCompiledHelpFile);
  44. //
  45. // Toolbar Definition. String IDs for menu and tooltip text will be resolved at initialization
  46. //
  47. static MMCBUTTON SnapinButtons[] =
  48. {
  49. { IDM_CONNECT - 1, IDM_CONNECT, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_MENU_CONNECT, (BSTR)IDS_MENU_TT_CONNECT },
  50. // { IDM_DISCOVER - 1, IDM_DISCOVER, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_MENU_DISCOVER, (BSTR)IDS_MENU_TT_CONNECT },
  51. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, _T(" "), _T("") },
  52. { IDM_START - 1, IDM_START, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_MENU_START, (BSTR)IDS_MENU_TT_START },
  53. { IDM_STOP - 1, IDM_STOP, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_MENU_STOP, (BSTR)IDS_MENU_TT_STOP },
  54. { IDM_PAUSE - 1, IDM_PAUSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_MENU_PAUSE, (BSTR)IDS_MENU_TT_PAUSE },
  55. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, _T(" "), _T("") },
  56. //
  57. // Add-on tools come here
  58. //
  59. };
  60. #define NUM_BUTTONS (ARRAYLEN(SnapinButtons))
  61. #define NUM_BITMAPS (5)
  62. //
  63. // Name of our taskpad group
  64. //
  65. const LPCTSTR g_cszTaskGroup = _T("CMTP1");
  66. template <class TYPE>
  67. TYPE * Extract(
  68. IN LPDATAOBJECT lpDataObject,
  69. IN unsigned int cf,
  70. IN int len = -1
  71. )
  72. /*++
  73. Routine Description:
  74. Template function to extract information of type TYPE from the data object
  75. Arguments:
  76. LPDATAOBJECT lpDataObject : Data object to extract data from
  77. unsigned int cf : Clipboard format describing the info type
  78. Return Value:
  79. Pointer to type TYPE
  80. --*/
  81. {
  82. ASSERT(lpDataObject != NULL);
  83. TYPE * p = NULL;
  84. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  85. FORMATETC formatetc =
  86. {
  87. (CLIPFORMAT)cf,
  88. NULL,
  89. DVASPECT_CONTENT,
  90. -1,
  91. TYMED_HGLOBAL
  92. };
  93. //
  94. // Allocate memory for the stream
  95. //
  96. if (len < 0)
  97. {
  98. len = sizeof(TYPE);
  99. }
  100. stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, len);
  101. do
  102. {
  103. if (stgmedium.hGlobal == NULL)
  104. {
  105. break;
  106. }
  107. HRESULT hr = lpDataObject->GetDataHere(&formatetc, &stgmedium);
  108. if (FAILED(hr))
  109. {
  110. break;
  111. }
  112. p = (TYPE *)stgmedium.hGlobal;
  113. if (p == NULL)
  114. {
  115. break;
  116. }
  117. }
  118. while (FALSE);
  119. return p;
  120. }
  121. //
  122. // Data object extraction helpers
  123. //
  124. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  125. /*
  126. BOOL
  127. IsMMCMultiSelectDataObject(
  128. IN LPDATAOBJECT lpDataObject
  129. )
  130. {
  131. if (lpDataObject == NULL)
  132. {
  133. return FALSE;
  134. }
  135. static UINT s_cf = 0;
  136. if (s_cf == 0)
  137. {
  138. //
  139. // Multi-select clipboard format not registered -- do it now
  140. //
  141. s_cf = RegisterClipboardFormat(CCF_MMC_MULTISELECT_DATAOBJECT);
  142. }
  143. FORMATETC fmt = {s_cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  144. return (lpDataObject->QueryGetData(&fmt) == S_OK);
  145. }
  146. */
  147. CLSID *
  148. ExtractClassID(
  149. IN LPDATAOBJECT lpDataObject
  150. )
  151. {
  152. return Extract<CLSID>(lpDataObject, CDataObject::m_cfCoClass);
  153. }
  154. GUID *
  155. ExtractNodeType(
  156. IN LPDATAOBJECT lpDataObject
  157. )
  158. {
  159. return Extract<GUID>(lpDataObject, CDataObject::m_cfNodeType);
  160. }
  161. wchar_t *
  162. ExtractMachineName(
  163. IN LPDATAOBJECT lpDataObject
  164. )
  165. {
  166. wchar_t * lpszMachineName = Extract<wchar_t>(
  167. lpDataObject,
  168. CDataObject::m_cfISMMachineName,
  169. (MAX_PATH + 1) * sizeof(wchar_t)
  170. );
  171. if (lpszMachineName == NULL)
  172. {
  173. //
  174. // This is an extension -- grab the computer management
  175. // name instead.
  176. //
  177. lpszMachineName = Extract<wchar_t>(
  178. lpDataObject,
  179. CDataObject::m_cfMyComputMachineName,
  180. (MAX_PATH + 1) * sizeof(wchar_t)
  181. );
  182. }
  183. return lpszMachineName;
  184. }
  185. INTERNAL *
  186. ExtractInternalFormat(
  187. IN LPDATAOBJECT lpDataObject
  188. )
  189. {
  190. ASSERT(lpDataObject != NULL);
  191. return Extract<INTERNAL>(lpDataObject, CDataObject::m_cfInternal);
  192. }
  193. //
  194. // IEnumTask Implementation
  195. //
  196. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  197. CEnumTasks::CEnumTasks()
  198. /*++
  199. Routine Description:
  200. Constructor
  201. Arguments:
  202. None
  203. Return Value:
  204. N/A
  205. --*/
  206. : m_pObject(NULL)
  207. {
  208. }
  209. CEnumTasks::~CEnumTasks()
  210. /*++
  211. Routine Description:
  212. Destructor
  213. Arguments:
  214. None
  215. Return Value:
  216. None
  217. --*/
  218. {
  219. }
  220. HRESULT
  221. CEnumTasks::Next(
  222. IN ULONG celt,
  223. IN MMC_TASK * rgelt,
  224. IN ULONG * pceltFetched
  225. )
  226. /*++
  227. Routine Description:
  228. Add next task to taskpad
  229. Arguments:
  230. ULONG celt,
  231. MMC_TASK * rgelt,
  232. ULONG * pceltFetched
  233. Return Value:
  234. HRESULT
  235. --*/
  236. {
  237. //
  238. // Callee fills MMC_TASK elements (via CoTaskMemAlloc)
  239. //
  240. ASSERT(!IsBadWritePtr(rgelt, celt * sizeof(MMC_TASK)));
  241. if (m_pObject == NULL)
  242. {
  243. //
  244. // Must be at the snap-in's root handle
  245. //
  246. return S_FALSE;
  247. }
  248. //
  249. // celt will actually always only be 1
  250. //
  251. ASSERT(celt == 1);
  252. HRESULT hr = S_FALSE;
  253. for (ULONG i = 0; i < celt; ++i)
  254. {
  255. MMC_TASK * task = &rgelt[i];
  256. hr = m_pObject->AddNextTaskpadItem(task);
  257. if (FAILED(hr))
  258. {
  259. if (pceltFetched)
  260. {
  261. *pceltFetched = i;
  262. }
  263. break;
  264. }
  265. }
  266. //
  267. // If we get here all is well
  268. //
  269. if(pceltFetched)
  270. {
  271. *pceltFetched = celt;
  272. }
  273. return hr;
  274. }
  275. HRESULT
  276. CEnumTasks::Skip(
  277. IN ULONG celt
  278. )
  279. /*++
  280. Routine Description:
  281. Skip the task index
  282. Arguments:
  283. ULONG celt : Number of tasks to skip
  284. Return Value:
  285. HRESULT
  286. --*/
  287. {
  288. return E_NOTIMPL;
  289. }
  290. HRESULT
  291. CEnumTasks::Reset()
  292. /*++
  293. Routine Description:
  294. Result the taskpad enumeration index
  295. Arguments:
  296. None
  297. Return Value:
  298. HRESULT
  299. --*/
  300. {
  301. return E_NOTIMPL;
  302. }
  303. HRESULT
  304. CEnumTasks::Clone(
  305. IN IEnumTASK ** ppenum
  306. )
  307. /*++
  308. Routine Description:
  309. Close a task -- obsolete, no longer supported by mmc
  310. Arguments:
  311. IEnumTASK ** ppenum : Source task to clone
  312. Return Value:
  313. HRESULT
  314. --*/
  315. {
  316. return E_NOTIMPL;
  317. }
  318. HRESULT
  319. CEnumTasks::Init(
  320. IN IDataObject * pdo,
  321. IN LPOLESTR szTaskGroup
  322. )
  323. /*++
  324. Routine Description:
  325. Here is where we see what taskpad we are providing tasks for.
  326. In our case we know that we only have one taskpad.
  327. The string we test for is "CMTP1". This was the string following
  328. the '#' that we passed in GetResultViewType.
  329. Arguments:
  330. IDataObject * pdo : Data object
  331. LPOLESTR szTaskGroup : Taskpad group name
  332. Return Value:
  333. HRESULT
  334. --*/
  335. {
  336. //
  337. // Return ok if we can handle data object and group.
  338. //
  339. if (!lstrcmp(szTaskGroup, g_cszTaskGroup))
  340. {
  341. //
  342. // CODEWORK: How about a helper for this!
  343. //
  344. INTERNAL * pInternal = ExtractInternalFormat(pdo);
  345. if (pInternal == NULL)
  346. {
  347. //
  348. // Extension
  349. //
  350. return S_OK;
  351. }
  352. m_pObject = (CIISObject *)pInternal->m_cookie;
  353. return S_OK;
  354. }
  355. //
  356. // Should never happen
  357. //
  358. ASSERT(FALSE);
  359. return S_FALSE;
  360. }
  361. //
  362. // CSnapin class
  363. //
  364. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  365. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapin);
  366. long CSnapin::lDataObjectRefCount = 0;
  367. CSnapin::CSnapin()
  368. /*++
  369. Routine Description:
  370. Constructor
  371. Arguments:
  372. None
  373. Return Value:
  374. N/A
  375. --*/
  376. : m_pConsole(NULL),
  377. m_pHeader(NULL),
  378. m_pResult(NULL),
  379. m_pImageResult(NULL),
  380. m_pComponentData(NULL),
  381. m_pToolbar(NULL),
  382. m_pControlbar(NULL),
  383. m_pbmpToolbar(NULL),
  384. m_pConsoleVerb(NULL),
  385. m_oblResultItems(),
  386. m_strlRef(),
  387. m_fTaskView(FALSE),
  388. m_fSettingsChanged(FALSE),
  389. m_fIsExtension(FALSE),
  390. m_fWinSockInit(FALSE)
  391. {
  392. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  393. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapin);
  394. #ifdef _DEBUG
  395. dbg_cRef = 0;
  396. #endif // _DEBUG
  397. }
  398. CSnapin::~CSnapin()
  399. /*++
  400. Routine Description:
  401. Destructor
  402. Arguments:
  403. N/A
  404. Return Value:
  405. N/A
  406. --*/
  407. {
  408. #ifdef _DEBUG
  409. ASSERT(dbg_cRef == 0);
  410. #endif // _DEBUG
  411. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapin);
  412. SAFE_RELEASE(m_pToolbar);
  413. SAFE_RELEASE(m_pControlbar);
  414. //
  415. // Make sure the interfaces have been released
  416. //
  417. ASSERT(m_pConsole == NULL);
  418. ASSERT(m_pHeader == NULL);
  419. ASSERT(m_pToolbar == NULL);
  420. if (m_pbmpToolbar)
  421. {
  422. m_pbmpToolbar->DeleteObject();
  423. delete m_pbmpToolbar;
  424. }
  425. //
  426. // Should have been removed via notification, but just in case:
  427. //
  428. ASSERT(m_oblResultItems.GetCount() == 0);
  429. m_oblResultItems.RemoveAll();
  430. }
  431. LPTSTR
  432. CSnapin::StringReferenceFromResourceID(
  433. IN UINT nID
  434. )
  435. /*++
  436. Routine Description:
  437. Load a string from the resource segment, add it to the internal
  438. string table, and return a pointer to it. The pointer will be
  439. valid for the entire scope of the CSnapin object
  440. Arguments
  441. UINT nID : Resource ID
  442. Return Value:
  443. A pointer to the string.
  444. --*/
  445. {
  446. CString str;
  447. VERIFY(str.LoadString(nID));
  448. m_strlRef.AddTail(str);
  449. CString & strRef = m_strlRef.GetAt(m_strlRef.GetTailPosition());
  450. return (LPTSTR)(LPCTSTR)strRef;
  451. }
  452. BOOL
  453. CSnapin::IsEnumerating(
  454. IN LPDATAOBJECT lpDataObject
  455. )
  456. /*++
  457. Routine Description:
  458. Return TRUE if we are enumerating our main folder
  459. Arguments:
  460. LPDATAOBJECT lpDataObject : Data object
  461. Return Value:
  462. TRUE if we are enumerating our main folder, FALSE if not
  463. --*/
  464. {
  465. BOOL bResult = FALSE;
  466. ASSERT(lpDataObject);
  467. GUID * nodeType = ExtractNodeType(lpDataObject);
  468. //
  469. // Is this my main node (static folder node type)
  470. //
  471. bResult = ::IsEqualGUID(*nodeType, cInternetRootNode);
  472. //
  473. // Free resources
  474. //
  475. FREE_DATA(nodeType);
  476. return bResult;
  477. }
  478. //
  479. // CSnapin's IComponent implementation
  480. //
  481. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  482. STDMETHODIMP
  483. CSnapin::GetResultViewType(
  484. IN MMC_COOKIE cookie,
  485. OUT BSTR * ppViewType,
  486. OUT long * pViewOptions
  487. )
  488. /*++
  489. Routine Description:
  490. Tell MMC what our result view looks like
  491. Arguments:
  492. MMC_COOKIE cookie : Currently selected cookie
  493. BSTR * ppViewType : Return view type here
  494. long * pViewOptions : View options
  495. Return Value:
  496. S_FALSE to use default view type, S_OK indicates the
  497. view type is returned in *ppViewType
  498. --*/
  499. {
  500. //
  501. // Taskpads not supported for beta2
  502. //
  503. #if TASKPADS_SUPPORTED
  504. if (m_fTaskView)
  505. {
  506. //
  507. // We will use the default DHTML provided by MMC. It actually
  508. // resides as a resource inside MMC.EXE. We just get the path
  509. // to it and use that.
  510. //
  511. // The one piece of magic here is the text following the '#'. That
  512. // is the special way we have of identifying they taskpad we are
  513. // talking about. Here we say we are wanting to show a taskpad
  514. // that we refer to as "CMTP1". We will actually see this string
  515. // pass back to us later. If someone is extending our taskpad,
  516. // they also need to know what this secret string is.
  517. //
  518. *pViewOptions = MMC_VIEW_OPTIONS_NONE;
  519. CString strResURL;
  520. HRESULT hr = BuildResURL(strResURL, NULL);
  521. if (FAILED(hr))
  522. {
  523. return hr;
  524. }
  525. strResURL += _T("/default.htm#");
  526. strResURL += g_cszTaskGroup;
  527. TRACEEOLID("Taskpad URL is " << strResURL);
  528. *ppViewType = CoTaskDupString((LPCOLESTR)strResURL);
  529. return S_OK;
  530. }
  531. #endif // TASKPADS_SUPPORTED
  532. //
  533. // Use default view
  534. //
  535. *pViewOptions = MMC_VIEW_OPTIONS_USEFONTLINKING;
  536. //*pViewOptions = MMC_VIEW_OPTIONS_USEFONTLINKING
  537. // | MMC_VIEW_OPTIONS_LEXICAL_SORT;
  538. return S_FALSE;
  539. }
  540. STDMETHODIMP
  541. CSnapin::Initialize(
  542. IN LPCONSOLE lpConsole
  543. )
  544. /*++
  545. Routine Description:
  546. Initialize the console
  547. Arguments"
  548. LPCONSOLE lpConsole : Pointer to console
  549. Return Value:
  550. HRESULT
  551. --*/
  552. {
  553. ASSERT(lpConsole != NULL);
  554. ::AfxEnableControlContainer();
  555. //
  556. // Initialize IISUI extension DLL
  557. //
  558. #ifndef _COMSTATIC
  559. //
  560. // Initialize IISUI extension DLL
  561. //
  562. InitIISUIDll();
  563. #endif // _COMSTATIC
  564. //
  565. // Initialise winsock
  566. //
  567. // ISSUE: If proxy is installed, this might take a long time
  568. // if the proxy server is in a hung state.
  569. //
  570. WSADATA wsaData;
  571. m_fWinSockInit = (::WSAStartup(MAKEWORD(1, 1), &wsaData) == 0);
  572. //
  573. // Save the IConsole pointer
  574. //
  575. m_pConsole = lpConsole;
  576. m_pConsole->AddRef();
  577. //
  578. // Load resource strings
  579. //
  580. LoadResources();
  581. //
  582. // QI for a IHeaderCtrl
  583. //
  584. HRESULT hr = m_pConsole->QueryInterface(
  585. IID_IHeaderCtrl,
  586. (void **)&m_pHeader
  587. );
  588. //
  589. // Give the console the header control interface pointer
  590. //
  591. if (SUCCEEDED(hr))
  592. {
  593. m_pConsole->SetHeader(m_pHeader);
  594. }
  595. m_pConsole->QueryInterface(
  596. IID_IResultData,
  597. (void **)&m_pResult
  598. );
  599. m_pConsole->QueryResultImageList(&m_pImageResult);
  600. m_pConsole->QueryConsoleVerb(&m_pConsoleVerb);
  601. //
  602. // Resolve tool tips texts
  603. //
  604. CString str;
  605. static BOOL fInitialised = FALSE;
  606. if (!fInitialised)
  607. {
  608. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  609. for (int i = 0; i < NUM_BUTTONS; ++i)
  610. {
  611. if (SnapinButtons[i].idCommand != 0)
  612. {
  613. SnapinButtons[i].lpButtonText = StringReferenceFromResourceID(
  614. (UINT)PtrToUlong(SnapinButtons[i].lpButtonText));
  615. SnapinButtons[i].lpTooltipText = StringReferenceFromResourceID(
  616. (UINT)PtrToUlong(SnapinButtons[i].lpTooltipText));
  617. }
  618. }
  619. fInitialised = TRUE;
  620. }
  621. return S_OK;
  622. }
  623. STDMETHODIMP
  624. CSnapin::Notify(
  625. IN LPDATAOBJECT lpDataObject,
  626. IN MMC_NOTIFY_TYPE event,
  627. IN LPARAM arg,
  628. IN LPARAM param
  629. )
  630. /*++
  631. Routine Description:
  632. Notification handler
  633. Arguments:
  634. LPDATAOBJECT lpDataObject : Data object
  635. MMC_NOTIFY_TYPE event : Event
  636. LPARAM arg : Argument
  637. LPARAM param : Parameter
  638. Return Value:
  639. HRESULT
  640. --*/
  641. {
  642. HRESULT hr = S_OK;
  643. INTERNAL * pInternal = NULL;
  644. MMC_COOKIE cookie;
  645. switch(event)
  646. {
  647. case MMCN_REFRESH:
  648. case MMCN_RENAME:
  649. //
  650. // Delegate it to the IComponentData
  651. //
  652. ASSERT(m_pComponentData != NULL);
  653. hr = m_pComponentData->Notify(lpDataObject, event, arg, param);
  654. case MMCN_PROPERTY_CHANGE:
  655. hr = OnPropertyChange(lpDataObject);
  656. break;
  657. case MMCN_DELETE:
  658. //
  659. // Let IComponentData do the deletion, then refresh the parent object
  660. //
  661. ASSERT(m_pComponentData != NULL);
  662. hr = m_pComponentData->Notify(lpDataObject, event, arg, param);
  663. m_pComponentData->Notify(lpDataObject, MMCN_REFRESH, arg, param);
  664. case MMCN_VIEW_CHANGE:
  665. hr = OnUpdateView(lpDataObject);
  666. break;
  667. case MMCN_SNAPINHELP:
  668. case MMCN_CONTEXTHELP:
  669. {
  670. LPOLESTR pCompiledHelpFile = NULL;
  671. if (SUCCEEDED(hr = GetSnapinHelpFile(&pCompiledHelpFile)))
  672. {
  673. IDisplayHelp * pdh;
  674. if (SUCCEEDED(hr = m_pConsole->QueryInterface(
  675. IID_IDisplayHelp, (void **)&pdh)))
  676. {
  677. CString topic = PathFindFileName(pCompiledHelpFile);
  678. topic += _T("::/iint1.htm");
  679. LPTSTR p = topic.GetBuffer(topic.GetLength());
  680. hr = pdh->ShowTopic(p);
  681. topic.ReleaseBuffer();
  682. pdh->Release();
  683. }
  684. }
  685. if (FAILED(hr))
  686. {
  687. CError err(hr);
  688. err.MessageBoxOnFailure();
  689. }
  690. CoTaskMemFree(pCompiledHelpFile);
  691. }
  692. break;
  693. default:
  694. //
  695. // don't process the internal format if the dataobject is null.
  696. //
  697. if (lpDataObject == NULL)
  698. {
  699. return S_OK;
  700. }
  701. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  702. if (pInternal == NULL)
  703. {
  704. //
  705. // Extension
  706. //
  707. TRACEEOLID("This is an (CSnapin) EXTENSION");
  708. cookie = NULL;
  709. CIISObject::m_fIsExtension = m_fIsExtension = TRUE;
  710. }
  711. else
  712. {
  713. cookie = pInternal->m_cookie;
  714. FREE_DATA(pInternal);
  715. }
  716. switch(event)
  717. {
  718. case MMCN_CLICK:
  719. case MMCN_DBLCLICK:
  720. hr = OnResultItemClkOrDblClk(cookie, (event == MMCN_DBLCLICK));
  721. break;
  722. case MMCN_ADD_IMAGES:
  723. OnAddImages(cookie, arg, param);
  724. break;
  725. case MMCN_SHOW:
  726. hr = OnShow(cookie, arg, param);
  727. break;
  728. case MMCN_ACTIVATE:
  729. hr = OnActivate(cookie, arg, param);
  730. break;
  731. case MMCN_MINIMIZED:
  732. hr = OnMinimize(cookie, arg, param);
  733. break;
  734. case MMCN_BTN_CLICK:
  735. break;
  736. case MMCN_SELECT:
  737. HandleStandardVerbs(arg, lpDataObject);
  738. break;
  739. case MMCN_COLUMN_CLICK:
  740. break;
  741. case MMCN_MENU_BTNCLICK:
  742. break;
  743. default:
  744. ASSERT(FALSE); // Handle new messages
  745. hr = E_UNEXPECTED;
  746. break;
  747. }
  748. }
  749. return hr;
  750. }
  751. STDMETHODIMP
  752. CSnapin::Destroy(
  753. IN MMC_COOKIE cookie
  754. )
  755. /*++
  756. Routine Description:
  757. Destruction handler
  758. Arguments:
  759. MMC_COOKIE cookie : Currently selected cookie
  760. Return Value:
  761. HRESULT
  762. --*/
  763. {
  764. //
  765. // Release the interfaces that we QI'ed
  766. //
  767. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  768. if (m_pConsole != NULL)
  769. {
  770. //
  771. // Tell the console to release the header control interface
  772. //
  773. m_pConsole->SetHeader(NULL);
  774. SAFE_RELEASE_SETTONULL(m_pHeader);
  775. SAFE_RELEASE_SETTONULL(m_pResult);
  776. SAFE_RELEASE_SETTONULL(m_pImageResult);
  777. SAFE_RELEASE_SETTONULL(m_pConsole);
  778. SAFE_RELEASE_SETTONULL(m_pComponentData);
  779. SAFE_RELEASE_SETTONULL(m_pConsoleVerb);
  780. SAFE_RELEASE_SETTONULL(m_pToolbar);
  781. SAFE_RELEASE_SETTONULL(m_pControlbar);
  782. }
  783. //
  784. // Terminate use of the WinSock routines.
  785. //
  786. if (m_fWinSockInit)
  787. {
  788. ::WSACleanup();
  789. m_fWinSockInit = FALSE;
  790. }
  791. //
  792. // Everything OK
  793. //
  794. return S_OK;
  795. }
  796. STDMETHODIMP
  797. CSnapin::QueryDataObject(
  798. IN MMC_COOKIE cookie,
  799. IN DATA_OBJECT_TYPES type,
  800. OUT LPDATAOBJECT * ppDataObject
  801. )
  802. /*++
  803. Routine Description:
  804. Get dataobject info
  805. Arguments:
  806. MMC_COOKIE cookie : cookie
  807. DATA_OBJECT_TYPES : Data object type
  808. LPDATAOBJECT * : Returns the data object
  809. Return Value:
  810. HRESULT
  811. --*/
  812. {
  813. //
  814. // Delegate it to the IComponentData
  815. //
  816. ASSERT(m_pComponentData != NULL);
  817. return m_pComponentData->QueryDataObject(cookie, type, ppDataObject);
  818. }
  819. void
  820. CSnapin::LoadResources()
  821. /*++
  822. Routine Description:
  823. Load resource belong to the main snapin
  824. Arguments:
  825. None
  826. Return Value:
  827. None
  828. --*/
  829. {
  830. //
  831. // Load strings from resources
  832. //
  833. }
  834. //
  835. // IExtendPropertySheet Implementation
  836. //
  837. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  838. STDMETHODIMP
  839. CSnapin::CreatePropertyPages(
  840. IN LPPROPERTYSHEETCALLBACK lpProvider,
  841. IN LONG_PTR handle,
  842. IN LPDATAOBJECT lpDataObject
  843. )
  844. /*++
  845. Routine Description:
  846. Create the property pages for the given object
  847. Arguments:
  848. LPPROPERTYSHEETCALLBACK lpProvider : Provider
  849. LONG_PTR handle : Handle
  850. LPDATAOBJECT lpDataObject : Data object
  851. Return Value:
  852. HRESULT
  853. --*/
  854. {
  855. return static_cast<CComponentDataImpl *>(m_pComponentData)->CreatePropertyPages(
  856. lpProvider,
  857. handle,
  858. lpDataObject
  859. );
  860. }
  861. STDMETHODIMP
  862. CSnapin::QueryPagesFor(
  863. IN LPDATAOBJECT lpDataObject
  864. )
  865. /*++
  866. Routine Description:
  867. Check to see if a property sheet should be brought up for this data
  868. object
  869. Arguments:
  870. LPDATAOBJECT lpDataObject : Data object
  871. Return Value:
  872. S_OK, if properties may be brought up for this item, S_FALSE otherwise
  873. --*/
  874. {
  875. return static_cast<CComponentDataImpl *>(m_pComponentData)->QueryPagesFor(
  876. lpDataObject
  877. );
  878. }
  879. HRESULT
  880. CSnapin::InitializeHeaders(
  881. IN MMC_COOKIE cookie
  882. )
  883. /*++
  884. Routine Description:
  885. Initialize the result view headers for this cookie
  886. Arguments:
  887. MMC_COOKIE cookie : Current cookie
  888. Return Value:
  889. HRESULT
  890. --*/
  891. {
  892. CIISObject * pObject = (CIISObject *)cookie;
  893. //
  894. // The result pane is always one level behind the scope pane
  895. // for a folder object
  896. //
  897. if (pObject == NULL)
  898. {
  899. CIISMachine::InitializeHeaders(m_pHeader);
  900. }
  901. else
  902. {
  903. pObject->InitializeChildHeaders(m_pHeader);
  904. }
  905. return S_OK;
  906. }
  907. class CImage : public CObjectPlus
  908. /*++
  909. Class Description:
  910. A structure to tie a bitmap together with a background
  911. colour mask
  912. Public Interface:
  913. CImage : Constructor
  914. ~CImage : Destructor
  915. Notes: This image owns the bitmap and will delete it upon
  916. destruction.
  917. --*/
  918. {
  919. //
  920. // Constructor/Destructor
  921. //
  922. public:
  923. CImage(
  924. IN CBitmap * pbmp,
  925. IN COLORREF rgb
  926. )
  927. : m_pbmp(pbmp),
  928. m_rgb(rgb)
  929. {
  930. }
  931. ~CImage()
  932. {
  933. ASSERT(m_pbmp != NULL);
  934. m_pbmp->DeleteObject();
  935. delete m_pbmp;
  936. }
  937. //
  938. // Access
  939. //
  940. public:
  941. //
  942. // Get the bitmap object
  943. //
  944. CBitmap & GetBitmap() { return *m_pbmp; }
  945. //
  946. // Get the background colour definition
  947. //
  948. COLORREF & GetBkColor() { return m_rgb; }
  949. private:
  950. CBitmap * m_pbmp;
  951. COLORREF m_rgb;
  952. };
  953. //
  954. // Global oblists of service bitmaps -- used by scope and result side
  955. //
  956. CObListPlus g_obl16x16;
  957. CObListPlus g_obl32x32;
  958. //
  959. // Add-on-tools definitions
  960. //
  961. CObListPlus g_oblAddOnTools;
  962. HRESULT
  963. CSnapin::InitializeBitmaps(
  964. IN MMC_COOKIE cookie
  965. )
  966. /*++
  967. Routine Description:
  968. Initialize the service bitmaps
  969. Arguments:
  970. MMC_COOKIE cookie : Currently selected cookie (CIISObject *)
  971. Return Value:
  972. HRESULT
  973. --*/
  974. {
  975. ASSERT(m_pImageResult != NULL);
  976. CBitmap bmp16x16,
  977. bmp32x32,
  978. bmpMgr16x16,
  979. bmpMgr32x32;
  980. {
  981. //
  982. // Load the bitmaps from the dll
  983. //
  984. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  985. VERIFY(bmp16x16.LoadBitmap(IDB_VIEWS16));
  986. VERIFY(bmp32x32.LoadBitmap(IDB_VIEWS32));
  987. VERIFY(bmpMgr16x16.LoadBitmap(IDB_INETMGR16));
  988. VERIFY(bmpMgr32x32.LoadBitmap(IDB_INETMGR16));
  989. }
  990. //
  991. // Set the images
  992. //
  993. HRESULT hr = m_pImageResult->ImageListSetStrip(
  994. (LONG_PTR *)(HBITMAP)bmp16x16,
  995. (LONG_PTR *)(HBITMAP)bmp32x32,
  996. 0,
  997. RGB_BK_IMAGES
  998. );
  999. ASSERT(hr == S_OK);
  1000. //
  1001. // Add on inetmgr bitmap
  1002. //
  1003. hr = m_pImageResult->ImageListSetStrip(
  1004. (LONG_PTR *)(HBITMAP)bmpMgr16x16,
  1005. (LONG_PTR *)(HBITMAP)bmpMgr32x32,
  1006. BMP_INETMGR,
  1007. RGB_BK_IMAGES
  1008. );
  1009. //
  1010. // Add the ones from the service config DLLs
  1011. //
  1012. POSITION pos16x16 = g_obl16x16.GetHeadPosition();
  1013. POSITION pos32x32 = g_obl32x32.GetHeadPosition();
  1014. int i = BMP_SERVICE;
  1015. while (pos16x16 && pos32x32)
  1016. {
  1017. CImage * pimg16x16 = (CImage *)g_obl16x16.GetNext(pos16x16);
  1018. CImage * pimg32x32 = (CImage *)g_obl32x32.GetNext(pos32x32);
  1019. ASSERT(pimg16x16 && pimg32x32);
  1020. hr = m_pImageResult->ImageListSetStrip(
  1021. (LONG_PTR *)(HBITMAP)pimg16x16->GetBitmap(),
  1022. (LONG_PTR *)(HBITMAP)pimg32x32->GetBitmap(),
  1023. i++,
  1024. pimg16x16->GetBkColor()
  1025. );
  1026. ASSERT(hr == S_OK);
  1027. }
  1028. return hr;
  1029. }
  1030. STDMETHODIMP
  1031. CSnapin::GetDisplayInfo(
  1032. IN LPRESULTDATAITEM lpResultDataItem
  1033. )
  1034. /*++
  1035. Routine Description:
  1036. Get display info for result item
  1037. Arguments:
  1038. LPRESULTDATAITEM lpResultDataItem : Address of result data tiem
  1039. Return Value:
  1040. HRESULT
  1041. --*/
  1042. {
  1043. wchar_t * szString = _T("");
  1044. ASSERT(lpResultDataItem != NULL);
  1045. static int nImage = -1;
  1046. static CString str;
  1047. if (lpResultDataItem)
  1048. {
  1049. CIISObject * pObject = (CIISObject *)lpResultDataItem->lParam;
  1050. ASSERT(pObject != NULL);
  1051. if (pObject != NULL && pObject->IsValidObject())
  1052. {
  1053. pObject->GetResultDisplayInfo(lpResultDataItem->nCol, str, nImage);
  1054. lpResultDataItem->str = (LPTSTR)(LPCTSTR)str;
  1055. lpResultDataItem->nImage = nImage;
  1056. return S_OK;
  1057. }
  1058. }
  1059. return S_FALSE;
  1060. }
  1061. //
  1062. // IExtendContextMenu Implementation
  1063. //
  1064. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<</
  1065. STDMETHODIMP
  1066. CSnapin::AddMenuItems(
  1067. IN LPDATAOBJECT lpDataObject,
  1068. IN LPCONTEXTMENUCALLBACK lpContextMenuCallback,
  1069. IN long * pInsertionAllowed
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. Add menu items -- pass it on the the component date
  1074. Arguments:
  1075. LPDATAOBJECT lpDataObject : Data object
  1076. LPCONTEXTMENUCALLBACK lpContextMenuCallback : Context menu
  1077. long * pInsertionAllowed : TRUE if insertion is allowed
  1078. Return Value:
  1079. HRESULT
  1080. --*/
  1081. {
  1082. //
  1083. // Cut support for taskpads in beta2
  1084. //
  1085. #if TASKPADS_SUPPORTED
  1086. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW)
  1087. {
  1088. //
  1089. // Add View Menu Items
  1090. //
  1091. CIISObject::AddMenuItemByCommand(
  1092. lpContextMenuCallback,
  1093. IDM_VIEW_TASKPAD,
  1094. m_fTaskView ? MF_CHECKED : 0
  1095. );
  1096. }
  1097. #endif // TASKPADS_SUPPORTED
  1098. //
  1099. // Pass it on to CComponentDataImpl
  1100. //
  1101. return static_cast<CComponentDataImpl *>(m_pComponentData)->AddMenuItems(
  1102. lpDataObject,
  1103. lpContextMenuCallback,
  1104. pInsertionAllowed
  1105. );
  1106. }
  1107. STDMETHODIMP
  1108. CSnapin::Command(
  1109. IN long nCommandID,
  1110. IN LPDATAOBJECT lpDataObject
  1111. )
  1112. /*++
  1113. Routine Description:
  1114. Command handler -- pass it on the component data
  1115. Arguments:
  1116. long nCommandID : Command ID
  1117. LPDTATAOBJECT lpDataObject : Data object
  1118. Return Value:
  1119. HRESULT
  1120. --*/
  1121. {
  1122. HRESULT hr = S_OK;
  1123. INTERNAL * pInternal = NULL;
  1124. switch(nCommandID)
  1125. {
  1126. case -1:
  1127. //
  1128. // Built-in views -- everything handled.
  1129. //
  1130. m_fTaskView = FALSE;
  1131. m_fSettingsChanged = TRUE;
  1132. break;
  1133. #if TASKPADS_SUPPORTED
  1134. //
  1135. // No taskpad support in beta2
  1136. //
  1137. case IDM_VIEW_TASKPAD:
  1138. //
  1139. // Handle view change
  1140. //
  1141. m_fTaskView = !m_fTaskView;
  1142. m_fSettingsChanged = TRUE;
  1143. //
  1144. // Reselect current scope item to force view change
  1145. //
  1146. pInternal = ExtractInternalFormat(lpDataObject);
  1147. if (pInternal != NULL)
  1148. {
  1149. CIISObject * pObject = (CIISObject *)pInternal->m_cookie;
  1150. FREE_DATA(pInternal);
  1151. if (pObject)
  1152. {
  1153. m_pConsole->SelectScopeItem(pObject->GetScopeHandle());
  1154. }
  1155. else
  1156. {
  1157. //
  1158. // Must be the root item
  1159. //
  1160. m_pConsole->SelectScopeItem(
  1161. static_cast<CComponentDataImpl *>(m_pComponentData)->GetRootHandle()
  1162. );
  1163. }
  1164. }
  1165. break;
  1166. #endif // TASKPADS_SUPPORTED
  1167. default:
  1168. //
  1169. // Pass it on to CComponentDataImpl
  1170. //
  1171. hr = static_cast<CComponentDataImpl *>(m_pComponentData)->Command(
  1172. nCommandID,
  1173. lpDataObject
  1174. );
  1175. }
  1176. return hr;
  1177. }
  1178. //
  1179. // ITaskPad implementation
  1180. //
  1181. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1182. HRESULT
  1183. CSnapin::TaskNotify(
  1184. IN IDataObject * pdo,
  1185. IN VARIANT * pvarg,
  1186. IN VARIANT * pvparam
  1187. )
  1188. /*++
  1189. Routine Description:
  1190. Handle notification from taskpad
  1191. Arguments:
  1192. IDataObject * pdo,
  1193. VARIANT * pvarg,
  1194. VARIANT * pvparam
  1195. Return Value:
  1196. HRESULT
  1197. --*/
  1198. {
  1199. if (pvarg->vt == VT_I4)
  1200. {
  1201. //
  1202. // Pass it on to CComponentDataImpl
  1203. //
  1204. return static_cast<CComponentDataImpl *>(m_pComponentData)->Command(
  1205. pvarg->lVal,
  1206. pdo
  1207. );
  1208. }
  1209. return S_OK;
  1210. }
  1211. HRESULT
  1212. CSnapin::GetTitle(
  1213. IN LPOLESTR szGroup,
  1214. OUT LPOLESTR * lpszTitle
  1215. )
  1216. /*++
  1217. Routine Description:
  1218. Get the title of the taskpad
  1219. Arguments:
  1220. LPOLESTR szGroup : Group name
  1221. LPOLESTR * szTitle : Returns title
  1222. Return Value:
  1223. HRESULT
  1224. --*/
  1225. {
  1226. OLECHAR sztitle[] = L"IIS TaskPad";
  1227. *lpszTitle = CoTaskDupString(sztitle);
  1228. return *lpszTitle != NULL ? S_OK : E_OUTOFMEMORY;
  1229. }
  1230. HRESULT
  1231. CSnapin::GetDescriptiveText(
  1232. IN LPOLESTR szGroup,
  1233. OUT LPOLESTR * lpszDescriptiveText
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. Get the descriptive text
  1238. Arguments:
  1239. LPOLESTR szGroup : Group name
  1240. LPOLESTR * szTitle : Returns title
  1241. Return Value:
  1242. HRESULT
  1243. --*/
  1244. {
  1245. return E_NOTIMPL;
  1246. }
  1247. HRESULT
  1248. CSnapin::GetBanner(
  1249. IN LPOLESTR szGroup,
  1250. OUT LPOLESTR * pszBitmapResource
  1251. )
  1252. /*++
  1253. Routine Description:
  1254. Get the banner resource
  1255. Arguments:
  1256. LPOLESTR szGroup : Group name
  1257. LPOLESTR * pszBitmapResource : Returns bitmap resource
  1258. Return Value:
  1259. HRESULT
  1260. --*/
  1261. {
  1262. CString strResURL;
  1263. HRESULT hr = BuildResURL(strResURL);
  1264. if (FAILED(hr))
  1265. {
  1266. return hr;
  1267. }
  1268. strResURL += _T("/img\\ntbanner.gif");
  1269. TRACEEOLID(strResURL);
  1270. *pszBitmapResource = CoTaskDupString((LPCOLESTR)strResURL);
  1271. return *pszBitmapResource != NULL ? S_OK : E_OUTOFMEMORY;
  1272. }
  1273. HRESULT
  1274. CSnapin::GetBackground(
  1275. IN LPOLESTR szGroup,
  1276. OUT MMC_TASK_DISPLAY_OBJECT * pTDO
  1277. )
  1278. /*++
  1279. Routine Description:
  1280. Get the background resource
  1281. Arguments:
  1282. LPOLESTR szGroup : Group name
  1283. LPOLESTR * pszBitmapResource : Returns bitmap resource
  1284. Return Value:
  1285. HRESULT
  1286. --*/
  1287. {
  1288. return E_NOTIMPL;
  1289. }
  1290. HRESULT
  1291. CSnapin::EnumTasks(
  1292. IN IDataObject * pdo,
  1293. IN LPOLESTR szTaskGroup,
  1294. OUT IEnumTASK ** ppEnumTASK
  1295. )
  1296. /*++
  1297. Routine Description:
  1298. Enumerate the tasks on the taskpad
  1299. Arguments:
  1300. IDataObject * pdo : Data object selected;
  1301. LPOLESTR szTaskGroup, : Taskgroup name
  1302. IEnumTASK ** ppEnumTASK : Returns enumtask interface
  1303. Return Value:
  1304. HRESULT
  1305. --*/
  1306. {
  1307. HRESULT hr = S_OK;
  1308. try
  1309. {
  1310. ASSERT(ppEnumTASK != NULL);
  1311. CComObject<CEnumTasks>* pObject;
  1312. CComObject<CEnumTasks>::CreateInstance(&pObject);
  1313. ASSERT(pObject != NULL);
  1314. VERIFY(SUCCEEDED(pObject->Init(pdo, szTaskGroup)));
  1315. hr = pObject->QueryInterface(
  1316. IID_IEnumTASK,
  1317. reinterpret_cast<void **>(ppEnumTASK)
  1318. );
  1319. }
  1320. catch(CMemoryException * e)
  1321. {
  1322. e->Delete();
  1323. hr = E_OUTOFMEMORY;
  1324. }
  1325. return hr;
  1326. }
  1327. //
  1328. // IExtendControlbar implementation
  1329. //
  1330. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1331. STDMETHODIMP
  1332. CSnapin::SetControlbar(
  1333. IN LPCONTROLBAR lpControlbar
  1334. )
  1335. /*++
  1336. Routine Description:
  1337. Set the control bar
  1338. Arguments:
  1339. LPCONTROLBAR lpControlbar : Pointer to control bar
  1340. Return Value:
  1341. HRESULT
  1342. --*/
  1343. {
  1344. if (lpControlbar != NULL)
  1345. {
  1346. //
  1347. // Hold on to the controlbar interface.
  1348. //
  1349. if (m_pControlbar != NULL)
  1350. {
  1351. m_pControlbar->Release();
  1352. }
  1353. m_pControlbar = lpControlbar;
  1354. m_pControlbar->AddRef();
  1355. HRESULT hr = S_FALSE;
  1356. //
  1357. // Create the Toolbar
  1358. //
  1359. if (!m_pToolbar)
  1360. {
  1361. hr = m_pControlbar->Create(TOOLBAR, this, (LPUNKNOWN *)&m_pToolbar);
  1362. ASSERT(SUCCEEDED(hr));
  1363. m_pbmpToolbar = new CBitmap;
  1364. {
  1365. //
  1366. // Add the bitmap
  1367. //
  1368. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1369. m_pbmpToolbar->LoadBitmap(IDB_TOOLBAR);
  1370. }
  1371. //
  1372. // Add 16x16 bitmaps
  1373. //
  1374. hr = m_pToolbar->AddBitmap(
  1375. NUM_BITMAPS,
  1376. (HBITMAP)*m_pbmpToolbar,
  1377. 16,
  1378. 16,
  1379. TB_COLORMASK
  1380. );
  1381. ASSERT(SUCCEEDED(hr));
  1382. //
  1383. // Add the buttons to the toolbar
  1384. //
  1385. hr = m_pToolbar->AddButtons(NUM_BUTTONS, SnapinButtons);
  1386. ASSERT(SUCCEEDED(hr));
  1387. //
  1388. // Now add the add-on tools
  1389. //
  1390. POSITION pos = g_oblAddOnTools.GetHeadPosition();
  1391. //
  1392. // Toolbar buttons were created using buttonface
  1393. // background colour
  1394. //
  1395. COLORREF rgbMask = ::GetSysColor(COLOR_BTNFACE);
  1396. while (pos != NULL)
  1397. {
  1398. CISMShellExecutable * pTool =
  1399. (CISMShellExecutable *)g_oblAddOnTools.GetNext(pos);
  1400. ASSERT(pTool != NULL);
  1401. if (pTool->ShowInToolBar())
  1402. {
  1403. if (pTool->InitializedOK())
  1404. {
  1405. //
  1406. // Add 16x16 image
  1407. //
  1408. hr = m_pToolbar->AddBitmap(
  1409. 1,
  1410. pTool->GetBitmap(),
  1411. 16,
  1412. 16,
  1413. rgbMask
  1414. );
  1415. ASSERT(SUCCEEDED(hr));
  1416. hr = m_pToolbar->AddButtons(1, pTool->GetButton());
  1417. ASSERT(SUCCEEDED(hr));
  1418. }
  1419. }
  1420. }
  1421. }
  1422. }
  1423. else
  1424. {
  1425. SAFE_RELEASE_SETTONULL(m_pControlbar);
  1426. }
  1427. return S_OK;
  1428. }
  1429. CISMShellExecutable *
  1430. CSnapin::GetCommandAt(
  1431. IN CObListPlus & obl,
  1432. IN int nIndex
  1433. )
  1434. /*++
  1435. Routine Description:
  1436. Get the add-on tool at the given index.
  1437. Arguments:
  1438. int nIndex : Index where to look for the add-on tool
  1439. Return Value:
  1440. Shell Executable object pointer, or NULL if the index was not valid
  1441. --*/
  1442. {
  1443. if (nIndex < 0 || nIndex >= obl.GetCount())
  1444. {
  1445. TRACEEOLID("Invalid tool index requested");
  1446. return NULL;
  1447. }
  1448. return (CISMShellExecutable *)obl.GetAt(obl.FindIndex(nIndex));
  1449. }
  1450. HRESULT
  1451. CSnapin::SetToolbarStates(
  1452. IN MMC_COOKIE cookie
  1453. )
  1454. /*++
  1455. Routine Description:
  1456. Set toolbar states based on current selection
  1457. Arguments:
  1458. MMC_COOKIE cookie : Currently selected scope item cookie (CIISObject *)
  1459. Return Value:
  1460. HRESULT
  1461. --*/
  1462. {
  1463. CIISObject * pObject = (CIISObject *)cookie;
  1464. if (m_pToolbar)
  1465. {
  1466. m_pToolbar->SetButtonState(
  1467. IDM_CONNECT,
  1468. ENABLED,
  1469. !CIISObject::m_fIsExtension
  1470. );
  1471. m_pToolbar->SetButtonState(
  1472. IDM_PAUSE,
  1473. ENABLED,
  1474. pObject && pObject->IsPausable()
  1475. );
  1476. m_pToolbar->SetButtonState(
  1477. IDM_START,
  1478. ENABLED,
  1479. pObject && pObject->IsStartable()
  1480. );
  1481. m_pToolbar->SetButtonState(
  1482. IDM_STOP,
  1483. ENABLED,
  1484. pObject && pObject->IsStoppable()
  1485. );
  1486. m_pToolbar->SetButtonState(
  1487. IDM_PAUSE,
  1488. BUTTONPRESSED,
  1489. pObject && pObject->IsPaused()
  1490. );
  1491. }
  1492. return S_OK;
  1493. }
  1494. HRESULT
  1495. CSnapin::OnButtonClick(
  1496. IN LPDATAOBJECT lpDataObject,
  1497. IN long lID
  1498. )
  1499. /*++
  1500. Routine Description:
  1501. Handle toolbar button click
  1502. Arguments:
  1503. LPDATAOBJECT lpDataObject : Current data object
  1504. LONG lID : Button ID pressed
  1505. Return Value:
  1506. HRESULT
  1507. --*/
  1508. {
  1509. //
  1510. // Check to see if the button ID is in the add-on tools
  1511. // range
  1512. //
  1513. if (lID >= IDM_TOOLBAR)
  1514. {
  1515. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  1516. CIISObject * pObject = pInternal
  1517. ? (CIISObject *)pInternal->m_cookie
  1518. : NULL;
  1519. //
  1520. // Button ID was in the add-on tools range. Match
  1521. // up the ID with the add-on tool, and execute same.
  1522. //
  1523. CISMShellExecutable * pTool = GetCommandAt(
  1524. g_oblAddOnTools,
  1525. lID - IDM_TOOLBAR
  1526. );
  1527. ASSERT(pTool != NULL);
  1528. if (pTool != NULL)
  1529. {
  1530. CError err;
  1531. if (pObject == NULL)
  1532. {
  1533. //
  1534. // Nothing selected, execute with no parameters
  1535. //
  1536. err = pTool->Execute();
  1537. }
  1538. else
  1539. {
  1540. //
  1541. // Pass server/service to the add-on tool
  1542. //
  1543. LPCTSTR lpstrServer = pObject->GetMachineName();
  1544. LPCTSTR lpstrService = pObject->GetServiceName();
  1545. err = pTool->Execute(lpstrServer, lpstrService);
  1546. }
  1547. if (err.Failed())
  1548. {
  1549. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1550. err.MessageBox();
  1551. }
  1552. }
  1553. FREE_DATA(pInternal);
  1554. }
  1555. else
  1556. {
  1557. //
  1558. // Otherwise, it maps to a menu command, pass it on to the
  1559. // component data
  1560. //
  1561. ASSERT(m_pComponentData != NULL);
  1562. ((CComponentDataImpl *)m_pComponentData)->Command(lID, lpDataObject);
  1563. }
  1564. return S_OK;
  1565. }
  1566. void
  1567. CSnapin::HandleStandardVerbs(
  1568. IN LPARAM arg,
  1569. IN LPDATAOBJECT lpDataObject
  1570. )
  1571. /*++
  1572. Routine Description:
  1573. Set the standard verb states based on current selection
  1574. Arguments:
  1575. LPARAM arg : Argument
  1576. LPDATAOBJECT lpDataObject : Selected data object
  1577. Return Value:
  1578. None
  1579. --*/
  1580. {
  1581. if (lpDataObject == NULL || m_pConsoleVerb == NULL)
  1582. {
  1583. return;
  1584. }
  1585. CIISObject * pObject = NULL;
  1586. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  1587. if (pInternal != NULL)
  1588. {
  1589. pObject = (CIISObject *)pInternal->m_cookie;
  1590. }
  1591. m_pConsoleVerb->SetVerbState(
  1592. MMC_VERB_RENAME,
  1593. ENABLED,
  1594. pObject && pObject->IsRenamable()
  1595. );
  1596. m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE);
  1597. m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE);
  1598. m_pConsoleVerb->SetVerbState(
  1599. MMC_VERB_DELETE,
  1600. ENABLED,
  1601. pObject && pObject->IsDeletable()
  1602. );
  1603. m_pConsoleVerb->SetVerbState(
  1604. MMC_VERB_REFRESH,
  1605. ENABLED,
  1606. pObject && pObject->IsRefreshable()
  1607. );
  1608. #ifdef MMC_PAGES
  1609. BOOL fConfig = pObject && pObject->IsMMCConfigurable();
  1610. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED,fConfig);
  1611. if (pObject && pObject->IsLeafNode())
  1612. {
  1613. m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
  1614. }
  1615. else
  1616. {
  1617. m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN);
  1618. }
  1619. #else
  1620. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, TRUE);
  1621. #endif
  1622. }
  1623. void
  1624. CSnapin::HandleToolbar(
  1625. IN LPARAM arg,
  1626. IN LPARAM param
  1627. )
  1628. /*++
  1629. Routine Description:
  1630. Handle toolbar states
  1631. Arguments:
  1632. LPARAM arg : Selection change notification argument
  1633. LPARAM param : Selection change notification parameter
  1634. Return Value:
  1635. None.
  1636. --*/
  1637. {
  1638. INTERNAL * pInternal = NULL;
  1639. CIISObject * pObject = NULL;
  1640. HRESULT hr;
  1641. LPDATAOBJECT lpDataObject = NULL;
  1642. BOOL bScope = (BOOL)LOWORD(arg);
  1643. BOOL bSelect = (BOOL)HIWORD(arg);
  1644. if (bScope)
  1645. {
  1646. lpDataObject = (LPDATAOBJECT)param;
  1647. if (lpDataObject != NULL)
  1648. {
  1649. pInternal = ExtractInternalFormat(lpDataObject);
  1650. }
  1651. if (pInternal == NULL)
  1652. {
  1653. return;
  1654. }
  1655. pObject = (CIISObject *)pInternal->m_cookie;
  1656. //
  1657. // Attach the toolbars to the window
  1658. //
  1659. if (m_pControlbar != NULL)
  1660. {
  1661. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN)m_pToolbar);
  1662. ASSERT(SUCCEEDED(hr));
  1663. }
  1664. }
  1665. else
  1666. {
  1667. //
  1668. // Result Pane -- disable all if nothing selected.
  1669. //
  1670. if (bSelect)
  1671. {
  1672. lpDataObject = (LPDATAOBJECT)param;
  1673. if (lpDataObject != NULL)
  1674. {
  1675. pInternal = ExtractInternalFormat(lpDataObject);
  1676. }
  1677. if (pInternal == NULL)
  1678. {
  1679. return;
  1680. }
  1681. pObject = (CIISObject *)pInternal->m_cookie;
  1682. //
  1683. // Attach the toolbars to the window
  1684. //
  1685. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN)m_pToolbar);
  1686. ASSERT(SUCCEEDED(hr));
  1687. }
  1688. }
  1689. if (pInternal)
  1690. {
  1691. FREE_DATA(pInternal);
  1692. }
  1693. SetToolbarStates((MMC_COOKIE)pObject);
  1694. }
  1695. STDMETHODIMP
  1696. CSnapin::ControlbarNotify(
  1697. IN MMC_NOTIFY_TYPE event,
  1698. IN LPARAM arg,
  1699. IN LPARAM param
  1700. )
  1701. /*++
  1702. Routine Description:
  1703. Handle control bar notification
  1704. Arguments:
  1705. MMC_NOTIFY_TYPE event : Notification event
  1706. LPARAM arg : argument as needed
  1707. LPARAM param : Parameter ad needed
  1708. Return Value:
  1709. HRESULT
  1710. --*/
  1711. {
  1712. HRESULT hr = S_OK;
  1713. switch (event)
  1714. {
  1715. case MMCN_BTN_CLICK:
  1716. //
  1717. // Note for MMC: it seems to be that arg and param
  1718. // should be reversed here. The MMCN_SELECT
  1719. // casts the dataobject to the param (which makes
  1720. // more sense anyway).
  1721. //
  1722. TRACEEOLID("CSnapin::ControlbarNotify - MMCN_BTN_CLICK");
  1723. OnButtonClick((LPDATAOBJECT)arg, (long)PtrToUlong((PVOID)param));
  1724. break;
  1725. case MMCN_SELECT:
  1726. TRACEEOLID("CSnapin::ControlbarNotify - MMCN_SEL_CHANGE");
  1727. HandleToolbar(arg, param);
  1728. break;
  1729. case MMCN_HELP:
  1730. break; // New
  1731. default:
  1732. //
  1733. // Unhandled event
  1734. //
  1735. ASSERT(FALSE);
  1736. }
  1737. return hr;
  1738. }
  1739. STDMETHODIMP
  1740. CSnapin::CompareObjects(
  1741. IN LPDATAOBJECT lpDataObjectA,
  1742. IN LPDATAOBJECT lpDataObjectB
  1743. )
  1744. /*++
  1745. Routine Description:
  1746. Compare two data objects. This method is used to see if a property
  1747. sheet for the given data object is already open
  1748. Arguments:
  1749. LPDATAOBJECT lpDataObjectA : A data object
  1750. LPDATAOBJECT lpDataObjectB : B data object
  1751. Return Value:
  1752. S_OK if they match, S_FALSE otherwise
  1753. --*/
  1754. {
  1755. //
  1756. // Delegate it to the IComponentData
  1757. //
  1758. ASSERT(m_pComponentData != NULL);
  1759. return m_pComponentData->CompareObjects(lpDataObjectA, lpDataObjectB);
  1760. }
  1761. /* virtual */
  1762. HRESULT
  1763. CSnapin::Compare(
  1764. IN RDCOMPARE * prdc,
  1765. OUT int * pnResult
  1766. )
  1767. /*++
  1768. Routine Description:
  1769. Compare method
  1770. Arguments:
  1771. RDCOMPARE * prdc : Compare structure
  1772. int * pnResult : Returns result
  1773. Return Value:
  1774. HRESULT
  1775. --*/
  1776. {
  1777. if (!pnResult || !prdc || !prdc->prdch1->cookie || !prdc->prdch2->cookie)
  1778. {
  1779. ASSERT(FALSE);
  1780. return E_POINTER;
  1781. }
  1782. CIISObject * pObjectA = (CIISObject *)prdc->prdch1->cookie;
  1783. CIISObject * pObjectB = (CIISObject *)prdc->prdch2->cookie;
  1784. *pnResult = pObjectA->Compare(prdc->nColumn, pObjectB);
  1785. return S_OK;
  1786. }
  1787. //
  1788. // IPersistStream interface members
  1789. //
  1790. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1791. STDMETHODIMP
  1792. CSnapin::GetClassID(
  1793. OUT CLSID * pClassID
  1794. )
  1795. /*++
  1796. Routine Description:
  1797. Get class ID
  1798. Arguments:
  1799. CLSID * pClassID : Returns class ID
  1800. Return Value:
  1801. HRESULT
  1802. --*/
  1803. {
  1804. ASSERT(pClassID != NULL);
  1805. //
  1806. // Copy the CLSID for this snapin
  1807. //
  1808. *pClassID = CLSID_Snapin;
  1809. return E_NOTIMPL;
  1810. }
  1811. STDMETHODIMP
  1812. CSnapin::IsDirty()
  1813. /*++
  1814. Routine Description:
  1815. Checks to see if the snapin's persistence stream is dirty
  1816. Arguments:
  1817. None
  1818. Return Value:
  1819. S_OK if the stream needs to be updated, S_FALSE otherwise
  1820. --*/
  1821. {
  1822. return m_fSettingsChanged ? S_OK : S_FALSE;
  1823. }
  1824. STDMETHODIMP
  1825. CSnapin::Load(
  1826. IN IStream * pStm
  1827. )
  1828. /*++
  1829. Routine Description:
  1830. Load the persisted information
  1831. Arguments:
  1832. IStream * pStm : Persistence stream
  1833. Return Value:
  1834. HRESULT
  1835. --*/
  1836. {
  1837. ASSERT(pStm != NULL);
  1838. //
  1839. // Verify a simple signature
  1840. //
  1841. DWORD dw = 0x1234;
  1842. DWORD dw2;
  1843. DWORD cBytesRead;
  1844. HRESULT hr = S_OK;
  1845. do
  1846. {
  1847. hr = pStm->Read(&dw2, sizeof(dw2), &cBytesRead);
  1848. if (FAILED(hr))
  1849. {
  1850. break;
  1851. }
  1852. ASSERT(cBytesRead == sizeof(dw2) && dw2 == dw);
  1853. //
  1854. // Read settings
  1855. //
  1856. hr = pStm->Read(
  1857. &m_fTaskView,
  1858. sizeof(m_fTaskView),
  1859. &cBytesRead
  1860. );
  1861. if (cBytesRead == 0)
  1862. {
  1863. //
  1864. // Old style console file
  1865. //
  1866. TRACEEOLID("Warning: old-style console file encountered");
  1867. m_fTaskView = FALSE;
  1868. }
  1869. else
  1870. {
  1871. ASSERT(cBytesRead == sizeof(m_fTaskView));
  1872. }
  1873. }
  1874. while(FALSE);
  1875. #if !TASKPADS_SUPPORTED
  1876. m_fTaskView = FALSE;
  1877. #endif // TASKPADS_SUPPORTED
  1878. return hr;
  1879. }
  1880. STDMETHODIMP
  1881. CSnapin::Save(
  1882. IN IStream * pStm,
  1883. IN BOOL fClearDirty
  1884. )
  1885. /*++
  1886. Routine Description:
  1887. Save persistence information
  1888. Arguments:
  1889. IStream * pStm : Persistence stream
  1890. BOOL fClearDirty : TRUE to clear the dirty flag
  1891. Return Value:
  1892. HRESULT
  1893. --*/
  1894. {
  1895. ASSERT(pStm != NULL);
  1896. //
  1897. // Write a simple signature
  1898. //
  1899. DWORD dw = 0x1234;
  1900. DWORD cBytesWritten;
  1901. HRESULT hr = STG_E_CANTSAVE;
  1902. do
  1903. {
  1904. hr = pStm->Write(&dw, sizeof(dw), &cBytesWritten);
  1905. if (FAILED(hr))
  1906. {
  1907. break;
  1908. }
  1909. ASSERT(cBytesWritten == sizeof(dw));
  1910. hr = pStm->Write(&m_fTaskView, sizeof(m_fTaskView), &cBytesWritten);
  1911. ASSERT(cBytesWritten == sizeof(m_fTaskView));
  1912. }
  1913. while(FALSE);
  1914. return hr;
  1915. }
  1916. STDMETHODIMP
  1917. CSnapin::GetSizeMax(
  1918. ULARGE_INTEGER * pcbSize
  1919. )
  1920. /*++
  1921. Routine Description:
  1922. Get max size of persistence information
  1923. Arguments:
  1924. ULARGE_INTEGER * pcbSize : Returns the size
  1925. Return Value:
  1926. HRESULT
  1927. --*/
  1928. {
  1929. ASSERT(pcbSize != NULL);
  1930. //
  1931. // Set the size of the string to be saved
  1932. //
  1933. pcbSize->QuadPart = (ULONGLONG)sizeof(DWORD) + sizeof(m_fTaskView);
  1934. return S_OK;
  1935. }
  1936. STDMETHODIMP
  1937. CSnapin::GetHelpTopic(LPOLESTR *lpCompiledHelpFile)
  1938. {
  1939. return GetSnapinHelpFile(lpCompiledHelpFile);
  1940. }
  1941. //
  1942. // IComponentData implementation
  1943. //
  1944. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1945. DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
  1946. CComponentDataImpl::CComponentDataImpl()
  1947. /*++
  1948. Routine Description:
  1949. Contructor
  1950. Arguments:
  1951. None
  1952. Return Value:
  1953. N/A
  1954. --*/
  1955. : m_pScope(NULL),
  1956. m_pConsole(NULL),
  1957. m_hIISRoot(NULL),
  1958. m_fIsCacheDirty(FALSE),
  1959. m_fIsExtension(FALSE),
  1960. m_strlCachedServers(),
  1961. m_ullDiscoveryMask((ULONGLONG)0L)
  1962. {
  1963. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1964. DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  1965. EmptyServerList();
  1966. #ifdef _DEBUG
  1967. m_cDataObjects = 0;
  1968. #endif
  1969. }
  1970. CComponentDataImpl::~CComponentDataImpl()
  1971. /*++
  1972. Routine Description:
  1973. Destructor
  1974. Arguments:
  1975. N/A
  1976. Return Value:
  1977. N/A
  1978. --*/
  1979. {
  1980. SAFE_RELEASE(m_pScope);
  1981. SAFE_RELEASE(m_pConsole);
  1982. DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  1983. //
  1984. // Some snap-in is hanging on to data objects.
  1985. // If they access, it will crash!!!
  1986. //
  1987. ASSERT(m_cDataObjects == 0);
  1988. }
  1989. STDMETHODIMP
  1990. CComponentDataImpl::Initialize(
  1991. IN LPUNKNOWN pUnknown
  1992. )
  1993. /*++
  1994. Routine Description:
  1995. Initalize the component data
  1996. Arguments:
  1997. LPUNKNOWN pUnknown : Pointer to IUnknown implementation
  1998. Return Value:
  1999. HRESULT
  2000. --*/
  2001. {
  2002. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  2003. ASSERT(pUnknown != NULL);
  2004. HRESULT hr;
  2005. //
  2006. // MMC should only call ::Initialize once!
  2007. //
  2008. ASSERT(m_pScope == NULL);
  2009. pUnknown->QueryInterface(IID_IConsoleNameSpace, (void **)&m_pScope);
  2010. CIISObject::AttachScopeView(m_pScope);
  2011. //
  2012. // add the images for the scope tree
  2013. //
  2014. LPIMAGELIST lpScopeImage;
  2015. hr = pUnknown->QueryInterface(IID_IConsole2, (void **)&m_pConsole);
  2016. ASSERT(hr == S_OK);
  2017. hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
  2018. ASSERT(hr == S_OK);
  2019. //
  2020. // Load the config services DLLs
  2021. //
  2022. GetServicesDLL();
  2023. //
  2024. // Get the add-on tools
  2025. //
  2026. GetToolMenu();
  2027. //
  2028. // Get the DLLs which contain computer property pages
  2029. //
  2030. GetISMMachinePages();
  2031. CBitmap bmp16x16,
  2032. bmp32x32,
  2033. bmpMgr16x16,
  2034. bmpMgr32x32;
  2035. //
  2036. // Load the bitmaps from the dll
  2037. //
  2038. // Must AFX_MANAGE_STATE here
  2039. //
  2040. {
  2041. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  2042. VERIFY(bmp16x16.LoadBitmap(IDB_VIEWS16));
  2043. VERIFY(bmp32x32.LoadBitmap(IDB_VIEWS32));
  2044. VERIFY(bmpMgr16x16.LoadBitmap(IDB_INETMGR16));
  2045. VERIFY(bmpMgr32x32.LoadBitmap(IDB_INETMGR16));
  2046. }
  2047. //
  2048. // Set the images
  2049. //
  2050. hr = lpScopeImage->ImageListSetStrip(
  2051. (LONG_PTR *)(HBITMAP)bmp16x16,
  2052. (LONG_PTR *)(HBITMAP)bmp32x32,
  2053. 0,
  2054. RGB_BK_IMAGES
  2055. );
  2056. ASSERT(hr == S_OK);
  2057. //
  2058. // Add on inetmgr bitmap
  2059. //
  2060. hr = lpScopeImage->ImageListSetStrip(
  2061. (LONG_PTR *)(HBITMAP)bmpMgr16x16,
  2062. (LONG_PTR *)(HBITMAP)bmpMgr32x32,
  2063. BMP_INETMGR,
  2064. RGB_BK_IMAGES
  2065. );
  2066. ASSERT(hr == S_OK);
  2067. //
  2068. // Add the ones from the service config DLL's
  2069. //
  2070. POSITION pos16x16 = g_obl16x16.GetHeadPosition();
  2071. POSITION pos32x32 = g_obl32x32.GetHeadPosition();
  2072. int i = BMP_SERVICE;
  2073. while (pos16x16 && pos32x32)
  2074. {
  2075. CImage * pimg16x16 = (CImage *)g_obl16x16.GetNext(pos16x16);
  2076. CImage * pimg32x32 = (CImage *)g_obl32x32.GetNext(pos32x32);
  2077. ASSERT(pimg16x16 && pimg32x32);
  2078. hr = lpScopeImage->ImageListSetStrip(
  2079. (LONG_PTR *)(HBITMAP)pimg16x16->GetBitmap(),
  2080. (LONG_PTR *)(HBITMAP)pimg32x32->GetBitmap(),
  2081. i++,
  2082. pimg16x16->GetBkColor()
  2083. );
  2084. ASSERT(hr == S_OK);
  2085. }
  2086. lpScopeImage->Release();
  2087. return hr;
  2088. }
  2089. STDMETHODIMP
  2090. CComponentDataImpl::CreateComponent(
  2091. IN LPCOMPONENT * ppComponent
  2092. )
  2093. /*++
  2094. Routine Description:
  2095. Create component
  2096. Arguments:
  2097. LPCOMPONENT * ppComponent : Address if COMPONENT
  2098. Return Value:
  2099. HRESULT
  2100. --*/
  2101. {
  2102. ASSERT(ppComponent != NULL);
  2103. CComObject<CSnapin>* pObject;
  2104. CComObject<CSnapin>::CreateInstance(&pObject);
  2105. ASSERT(pObject != NULL);
  2106. //
  2107. // Store IComponentData
  2108. //
  2109. pObject->SetIComponentData(this);
  2110. return pObject->QueryInterface(IID_IComponent, (void **)ppComponent);
  2111. }
  2112. BOOL
  2113. CComponentDataImpl::FindOpenPropSheetOnNodeAndDescendants(
  2114. IN LPPROPERTYSHEETPROVIDER piPropertySheetProvider,
  2115. IN MMC_COOKIE cookie
  2116. )
  2117. /*++
  2118. Routine Description:
  2119. Starting with the current node, check to see if an open
  2120. property sheet exists. Keep looking through descendants also.
  2121. As soon as an open property sheet is found, return TRUE.
  2122. Arguments:
  2123. MMC_COOKIE cookie : Cookie for currently selected item
  2124. Return Value:
  2125. TRUE if an open property sheet is found, FALSE if not.
  2126. Notes:
  2127. Function is called recursively
  2128. --*/
  2129. {
  2130. HSCOPEITEM hScopeItem = NULL;
  2131. CIISObject * pObject = (CIISObject *)cookie;
  2132. if (pObject != NULL)
  2133. {
  2134. hScopeItem = pObject->GetScopeHandle();
  2135. }
  2136. //
  2137. // Check the current node
  2138. //
  2139. HRESULT hr = piPropertySheetProvider->FindPropertySheet(
  2140. (MMC_COOKIE)hScopeItem,
  2141. NULL,
  2142. NULL
  2143. );
  2144. if (hr == S_OK)
  2145. {
  2146. //
  2147. // Found a sheet
  2148. //
  2149. return TRUE;
  2150. }
  2151. //
  2152. // Now check the descendants for open sheets
  2153. //
  2154. ASSERT(m_pScope != NULL);
  2155. //
  2156. // Look for machine object off the root
  2157. //
  2158. HSCOPEITEM hChildItem;
  2159. hr = m_pScope->GetChildItem(hScopeItem, &hChildItem, &cookie);
  2160. while (hr == S_OK && hChildItem != NULL)
  2161. {
  2162. CIISObject * pObject = (CIISObject *)cookie;
  2163. if (FindOpenPropSheetOnNodeAndDescendants(
  2164. piPropertySheetProvider,
  2165. cookie
  2166. ))
  2167. {
  2168. //
  2169. // Found a sheet
  2170. //
  2171. return TRUE;
  2172. }
  2173. //
  2174. // Advance to next child of the same parent.
  2175. //
  2176. hr = m_pScope->GetNextItem(hChildItem, &hChildItem, &cookie);
  2177. }
  2178. //
  2179. // Not found
  2180. //
  2181. return FALSE;
  2182. }
  2183. /* INTRINSA suppress=null_pointers, uninitialized */
  2184. STDMETHODIMP
  2185. CComponentDataImpl::Notify(
  2186. IN LPDATAOBJECT lpDataObject,
  2187. IN MMC_NOTIFY_TYPE event,
  2188. IN LPARAM arg,
  2189. IN LPARAM param
  2190. )
  2191. /*++
  2192. Routine Description:
  2193. Notification message handler
  2194. Arguments:
  2195. LPDATAOBJECT lpDataObject : Selected item
  2196. MMC_NOTIFY_TYPE event : Notification message
  2197. LPARAM arg : Notification Argument
  2198. LPARAM param : Notification Parameter
  2199. Return Value:
  2200. HRESULT
  2201. --*/
  2202. {
  2203. if (event == MMCN_PROPERTY_CHANGE)
  2204. {
  2205. return OnProperties(param);
  2206. }
  2207. ASSERT(m_pScope != NULL);
  2208. HRESULT hr = S_OK;
  2209. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  2210. MMC_COOKIE cookie;
  2211. if (pInternal == NULL)
  2212. {
  2213. TRACEEOLID("Extension (CComponentDataImpl) Snapin");
  2214. CIISObject::m_fIsExtension = m_fIsExtension = TRUE;
  2215. cookie = NULL;
  2216. }
  2217. else
  2218. {
  2219. cookie = pInternal->m_cookie;
  2220. FREE_DATA(pInternal);
  2221. }
  2222. switch(event)
  2223. {
  2224. case MMCN_REFRESH:
  2225. RefreshIISObject((CIISObject *)cookie, TRUE, arg);
  2226. break;
  2227. case MMCN_DELETE:
  2228. DeleteObject((CIISObject *)cookie);
  2229. break;
  2230. case MMCN_RENAME:
  2231. hr = OnRename(cookie, arg, param);
  2232. break;
  2233. case MMCN_REMOVE_CHILDREN:
  2234. hr = OnRemoveChildren(arg);
  2235. break;
  2236. case MMCN_EXPAND:
  2237. hr = OnExpand(lpDataObject, arg, param);
  2238. break;
  2239. case MMCN_SELECT:
  2240. hr = OnSelect(cookie, arg, param);
  2241. break;
  2242. case MMCN_CONTEXTMENU:
  2243. hr = OnContextMenu(cookie, arg, param);
  2244. break;
  2245. default:
  2246. break;
  2247. }
  2248. return hr;
  2249. }
  2250. STDMETHODIMP
  2251. CComponentDataImpl::Destroy()
  2252. /*++
  2253. Routine Description:
  2254. Destroy component data
  2255. Arguments:
  2256. None
  2257. Return Value:
  2258. HRESULT
  2259. --*/
  2260. {
  2261. SAFE_RELEASE_SETTONULL(m_pScope);
  2262. SAFE_RELEASE_SETTONULL(m_pConsole);
  2263. m_hIISRoot = NULL;
  2264. //
  2265. // Scope items will clean themselves up
  2266. //
  2267. return S_OK;
  2268. }
  2269. STDMETHODIMP
  2270. CComponentDataImpl::QueryDataObject(
  2271. IN MMC_COOKIE cookie,
  2272. IN DATA_OBJECT_TYPES type,
  2273. OUT LPDATAOBJECT * ppDataObject
  2274. )
  2275. /*++
  2276. Routine Description:
  2277. Query data object
  2278. Arguments:
  2279. MMC_COOKIE cookie : Private data (i.e. a CIISObject *)
  2280. DATA_OBJECT_TYPES type : Data object type
  2281. LPDATAOBJECT * ppDataObject : Returns LPDATAOBJECT
  2282. Return Value:
  2283. HRESULT
  2284. --*/
  2285. {
  2286. ASSERT(ppDataObject != NULL);
  2287. CComObject<CDataObject>* pObject;
  2288. CComObject<CDataObject>::CreateInstance(&pObject);
  2289. ASSERT(pObject != NULL);
  2290. if (pObject == NULL)
  2291. return E_UNEXPECTED;
  2292. //
  2293. // Save cookie and type for delayed rendering
  2294. //
  2295. pObject->SetType(type);
  2296. pObject->SetCookie(cookie);
  2297. #ifdef _DEBUG
  2298. pObject->SetComponentData(this);
  2299. #endif
  2300. //
  2301. // Store the coclass with the data object
  2302. //
  2303. pObject->SetClsid(GetCoClassID());
  2304. return pObject->QueryInterface(IID_IDataObject, (void **)ppDataObject);
  2305. }
  2306. //
  2307. // IExtendPropertySheet Implementation
  2308. //
  2309. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2310. STDMETHODIMP
  2311. CComponentDataImpl::CreatePropertyPages(
  2312. IN LPPROPERTYSHEETCALLBACK lpProvider,
  2313. IN LONG_PTR handle,
  2314. IN LPDATAOBJECT lpDataObject
  2315. )
  2316. /*++
  2317. Routine Description:
  2318. Create the property pages for the given object
  2319. Arguments:
  2320. LPPROPERTYSHEETCALLBACK lpProvider : Provider
  2321. LONG_PTR handle : Handle.
  2322. LPDATAOBJECT lpDataObject : Data object
  2323. Return Value:
  2324. HRESULT
  2325. --*/
  2326. {
  2327. #ifdef MMC_PAGES
  2328. CIISObject * pObject = NULL;
  2329. if (lpDataObject != NULL)
  2330. {
  2331. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  2332. if (pInternal)
  2333. {
  2334. pObject = (CIISObject *)pInternal->m_cookie;
  2335. FREE_DATA(pInternal);
  2336. }
  2337. }
  2338. ASSERT(pObject && pObject->IsMMCConfigurable());
  2339. CError err(pObject->ConfigureMMC(lpProvider, (LPARAM)pObject, handle));
  2340. //
  2341. // ISSUE: MMC silently fails on this error. Perhaps it should
  2342. // write the error message?
  2343. //
  2344. if (err.Failed())
  2345. {
  2346. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2347. err.MessageBox();
  2348. }
  2349. return err;
  2350. #else
  2351. return E_NOTIMPL;
  2352. #endif // MMC_PAGES
  2353. }
  2354. STDMETHODIMP
  2355. CComponentDataImpl::QueryPagesFor(
  2356. IN LPDATAOBJECT lpDataObject
  2357. )
  2358. /*++
  2359. Routine Description:
  2360. Check to see if a property sheet should be brought up for this data
  2361. object
  2362. Arguments:
  2363. LPDATAOBJECT lpDataObject : Data object
  2364. Return Value:
  2365. S_OK, if properties may be brought up for this item, S_FALSE otherwise
  2366. --*/
  2367. {
  2368. #ifdef MMC_PAGES
  2369. CIISObject * pObject = NULL;
  2370. if (lpDataObject != NULL)
  2371. {
  2372. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  2373. if (pInternal)
  2374. {
  2375. pObject = (CIISObject *)pInternal->m_cookie;
  2376. FREE_DATA(pInternal);
  2377. }
  2378. }
  2379. return pObject && pObject->IsMMCConfigurable() ? S_OK : S_FALSE;
  2380. #else
  2381. return S_FALSE;
  2382. #endif // MMC_PAGES
  2383. }
  2384. //
  2385. // IPersistStream interface members
  2386. //
  2387. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2388. STDMETHODIMP
  2389. CComponentDataImpl::GetClassID(
  2390. OUT CLSID * pClassID
  2391. )
  2392. /*++
  2393. Routine Description:
  2394. Return the objects class ID
  2395. Arguments:
  2396. CLSID pClassID : Returns the class ID
  2397. Return Value:
  2398. HRESULT
  2399. --*/
  2400. {
  2401. ASSERT(pClassID != NULL);
  2402. //
  2403. // Copy the CLSID for this snapin
  2404. //
  2405. *pClassID = CLSID_Snapin;
  2406. return S_OK;
  2407. }
  2408. STDMETHODIMP
  2409. CComponentDataImpl::IsDirty()
  2410. /*++
  2411. Routine Description:
  2412. Determine if we need to save the cache
  2413. Arguments:
  2414. None
  2415. Return Value:
  2416. S_OK if the stream needs to be updated, S_FALSE otherwise
  2417. --*/
  2418. {
  2419. if (m_fIsExtension)
  2420. {
  2421. //
  2422. // Extension to computer management -- no private cache
  2423. //
  2424. return S_FALSE;
  2425. }
  2426. //
  2427. // Primary snapin
  2428. //
  2429. return IsCacheDirty() ? S_OK : S_FALSE;
  2430. }
  2431. STDMETHODIMP
  2432. CComponentDataImpl::Load(
  2433. IN IStream * pStm
  2434. )
  2435. /*++
  2436. Routine Description:
  2437. Load the persisted information
  2438. Arguments:
  2439. IStream * pStm : Persistence stream
  2440. Return Value:
  2441. HRESULT
  2442. --*/
  2443. {
  2444. ASSERT(pStm);
  2445. DWORD cch;
  2446. DWORD cBytesRead;
  2447. LPTSTR lpstr;
  2448. if (m_fIsExtension)
  2449. {
  2450. //
  2451. // Extension to computer management -- no private cache
  2452. //
  2453. return S_OK;
  2454. }
  2455. //
  2456. // First read the size of the string array
  2457. //
  2458. HRESULT hr = pStm->Read(&cch, sizeof(cch), &cBytesRead);
  2459. if (FAILED(hr))
  2460. {
  2461. return E_FAIL;
  2462. }
  2463. //
  2464. // Virgin cache
  2465. //
  2466. if (cBytesRead != sizeof(cch) || cch == 0)
  2467. {
  2468. return S_OK;
  2469. }
  2470. lpstr = AllocTString(cch);
  2471. if (lpstr == NULL)
  2472. {
  2473. return E_FAIL;
  2474. }
  2475. hr = pStm->Read(lpstr, cch * sizeof(TCHAR), &cBytesRead);
  2476. ASSERT(SUCCEEDED(hr) && cBytesRead == cch * sizeof(TCHAR));
  2477. if (FAILED(hr))
  2478. {
  2479. return E_FAIL;
  2480. }
  2481. CStringList strl;
  2482. ConvertDoubleNullListToStringList(lpstr, strl);
  2483. for (POSITION pos = strl.GetHeadPosition(); pos!= NULL; )
  2484. {
  2485. CString & str = strl.GetNext(pos);
  2486. AddServerToCache(str, FALSE);
  2487. }
  2488. FreeMem(lpstr);
  2489. return hr;
  2490. }
  2491. STDMETHODIMP
  2492. CComponentDataImpl::Save(
  2493. IN IStream * pStm,
  2494. IN BOOL fClearDirty
  2495. )
  2496. /*++
  2497. Routine Description:
  2498. Save persistence information
  2499. Arguments:
  2500. IStream * pStm : Persistence stream
  2501. BOOL fClearDirty : TRUE to clear the dirty flag
  2502. Return Value:
  2503. HRESULT
  2504. --*/
  2505. {
  2506. ASSERT(pStm);
  2507. if (m_fIsExtension)
  2508. {
  2509. //
  2510. // Extension to computer management -- no private cache
  2511. //
  2512. return S_OK;
  2513. }
  2514. //
  2515. // Flatten the cache
  2516. //
  2517. DWORD cch;
  2518. LPTSTR lpstr;
  2519. DWORD cBytesWritten;
  2520. HRESULT hr = S_OK;
  2521. DWORD err = ConvertStringListToDoubleNullList(
  2522. GetCachedServers(),
  2523. cch,
  2524. lpstr
  2525. );
  2526. if (err == ERROR_SUCCESS)
  2527. {
  2528. //
  2529. // First write the total size
  2530. //
  2531. hr = pStm->Write(&cch, sizeof(cch), &cBytesWritten);
  2532. ASSERT(SUCCEEDED(hr) && cBytesWritten == sizeof(cch));
  2533. if (FAILED(hr))
  2534. {
  2535. return STG_E_CANTSAVE;
  2536. }
  2537. //
  2538. // Now write the body.
  2539. //
  2540. hr = pStm->Write(lpstr, cch * sizeof(TCHAR), &cBytesWritten);
  2541. ASSERT(SUCCEEDED(hr) && cBytesWritten == cch * sizeof(TCHAR));
  2542. if (FAILED(hr))
  2543. {
  2544. return STG_E_CANTSAVE;
  2545. }
  2546. if (fClearDirty)
  2547. {
  2548. ClearCacheDirty();
  2549. }
  2550. FreeMem(lpstr);
  2551. }
  2552. return S_OK;
  2553. }
  2554. STDMETHODIMP
  2555. CComponentDataImpl::GetSizeMax(
  2556. OUT ULARGE_INTEGER * pcbSize
  2557. )
  2558. /*++
  2559. Routine Description:
  2560. Get max size of persistence information
  2561. Arguments:
  2562. ULARGE_INTEGER * pcbSize : Returns the size
  2563. Return Value:
  2564. HRESULT
  2565. --*/
  2566. {
  2567. ASSERT(pcbSize);
  2568. //
  2569. // Set the size of the string to be saved
  2570. //
  2571. pcbSize->QuadPart = (ULONGLONG)0;
  2572. return S_OK;
  2573. }
  2574. //
  2575. // IExtendContextMenu implementation
  2576. //
  2577. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2578. STDMETHODIMP
  2579. CComponentDataImpl::AddMenuItems(
  2580. IN LPDATAOBJECT lpDataObject,
  2581. IN LPCONTEXTMENUCALLBACK lpContextMenuCallback,
  2582. IN long * pInsertionAllowed
  2583. )
  2584. /*++
  2585. Routine Description:
  2586. Add menu items to the right-click context menu
  2587. Arguments:
  2588. LPDATAOBJECT pDataObject : Select
  2589. LPCONTEXTMENUCALLBACK pContextMenuCallback : Context menu callback function
  2590. long * pInsertionAllowed : ???
  2591. Return Value:
  2592. HRESULT
  2593. --*/
  2594. {
  2595. if (!(*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP))
  2596. {
  2597. //
  2598. // Nothing to add to the action menu.
  2599. //
  2600. return S_OK;
  2601. }
  2602. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  2603. if (pInternal == NULL)
  2604. {
  2605. //
  2606. // Extensions not supported yet.
  2607. //
  2608. ASSERT(FALSE);
  2609. return S_OK;
  2610. }
  2611. CIISObject * pObject = (CIISObject *)pInternal->m_cookie;
  2612. FREE_DATA(pInternal);
  2613. if (pObject == NULL)
  2614. {
  2615. //
  2616. // Must be the static root, add connect menu item only.
  2617. //
  2618. CIISObject::AddMenuItemByCommand(lpContextMenuCallback, IDM_CONNECT);
  2619. return S_OK;
  2620. }
  2621. return pObject->AddMenuItems(lpContextMenuCallback);
  2622. }
  2623. BOOL
  2624. CComponentDataImpl::DoChangeState(
  2625. IN CIISObject * pObject,
  2626. IN int nNewState
  2627. )
  2628. /*++
  2629. Routine Description:
  2630. Change the state of the selected object
  2631. Arguments:
  2632. CIISObject * pObject : Selected object
  2633. int nNewState : Desired new state
  2634. Return Value:
  2635. TRUE for success, FALSE for failure.
  2636. Notes:
  2637. In case of failure, this method will already have displayed
  2638. an error message with the cause
  2639. --*/
  2640. {
  2641. ASSERT(pObject != NULL);
  2642. ASSERT(pObject->IsControllable());
  2643. int nNumRunningChange = pObject->IsRunning()
  2644. ? -1
  2645. : 0;
  2646. CError err;
  2647. //
  2648. // Temporarily override some messages
  2649. //
  2650. TEMP_ERROR_OVERRIDE(ERROR_BAD_DEV_TYPE, IDS_CLUSTER_ENABLED);
  2651. TEMP_ERROR_OVERRIDE(ERROR_INVALID_PARAMETER, IDS_CANT_START_SERVICE);
  2652. {
  2653. //
  2654. // Needed for CWaitCursor
  2655. //
  2656. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  2657. CWaitCursor wait;
  2658. err = pObject->ChangeState(nNewState);
  2659. }
  2660. if (err.Failed())
  2661. {
  2662. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2663. err.MessageBox();
  2664. }
  2665. //
  2666. // Refresh regardless
  2667. //
  2668. pObject->RefreshDisplayInfo();
  2669. nNumRunningChange += pObject->IsRunning()
  2670. ? +1
  2671. : 0;
  2672. AddToNumRunning(nNumRunningChange);
  2673. //UpdateStatusBarNumbers();
  2674. return err.Succeeded();
  2675. }
  2676. void
  2677. CComponentDataImpl::OnMetaBackRest(
  2678. IN CIISObject * pObject
  2679. )
  2680. /*++
  2681. Routine Description:
  2682. Perform metabase backup/restore
  2683. Arguments:
  2684. CIISObject * pObject : Selected object (should be machine node)
  2685. Return Value:
  2686. None
  2687. --*/
  2688. {
  2689. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2690. ASSERT(pObject->QueryGUID() == cMachineNode);
  2691. CBackupDlg dlg(pObject->GetMachineName());
  2692. dlg.DoModal();
  2693. if (dlg.HasChangedMetabase())
  2694. {
  2695. RefreshIISObject(pObject, TRUE);
  2696. }
  2697. }
  2698. void
  2699. CComponentDataImpl::OnIISShutDown(
  2700. IN CIISObject * pObject
  2701. )
  2702. /*++
  2703. Routine Description:
  2704. Bring up IIS shutdown/restart dialogs
  2705. Arguments:
  2706. CIISObject * pObject : Selected object (should be machine node)
  2707. Return Value:
  2708. None
  2709. --*/
  2710. {
  2711. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2712. ASSERT(pObject->QueryGUID() == cMachineNode);
  2713. LPCTSTR lpszMachineName = pObject->GetMachineName();
  2714. //
  2715. // If a property sheet is open for this item, don't
  2716. // allow deletion.
  2717. //
  2718. LPPROPERTYSHEETPROVIDER piPropertySheetProvider = NULL;
  2719. HRESULT hr = m_pConsole->QueryInterface(
  2720. IID_IPropertySheetProvider,
  2721. (void **)&piPropertySheetProvider
  2722. );
  2723. if (FindOpenPropSheetOnNodeAndDescendants(
  2724. piPropertySheetProvider,
  2725. (ULONG_PTR)pObject
  2726. ))
  2727. {
  2728. //
  2729. // Already had properties open
  2730. //
  2731. ::AfxMessageBox(IDS_PROP_OPEN_SHUTDOWN);
  2732. return;
  2733. }
  2734. CIISShutdownDlg dlg(lpszMachineName);
  2735. dlg.DoModal();
  2736. if (dlg.ServicesWereRestarted())
  2737. {
  2738. //
  2739. // Rebind all metabase handles on this server
  2740. //
  2741. CServerInfo * pServerInfo;
  2742. CObListIter obli(m_oblServers);
  2743. while (pServerInfo = (CServerInfo *)obli.Next())
  2744. {
  2745. if (!::lstrcmpi(pServerInfo->QueryServerName(), lpszMachineName))
  2746. {
  2747. TRACEEOLID(
  2748. "Rebinding against "
  2749. << pServerInfo->GetShortName()
  2750. << " on "
  2751. << lpszMachineName
  2752. );
  2753. pServerInfo->ISMRebind();
  2754. }
  2755. }
  2756. //
  2757. // Now do a refresh on the computer node. Since we've forced
  2758. // the rebinding here, we should not get the disconnect warning.
  2759. //
  2760. RefreshIISObject(pObject, TRUE);
  2761. }
  2762. }
  2763. void
  2764. CComponentDataImpl::OnConnectOne()
  2765. /*++
  2766. Routine Description:
  2767. Connect to a single server
  2768. Arguments:
  2769. None
  2770. Return Value:
  2771. None
  2772. --*/
  2773. {
  2774. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2775. TEMP_ERROR_OVERRIDE(EPT_S_NOT_REGISTERED, IDS_ERR_RPC_NA);
  2776. TEMP_ERROR_OVERRIDE(RPC_S_SERVER_UNAVAILABLE, IDS_ERR_RPC_NA);
  2777. TEMP_ERROR_OVERRIDE(RPC_S_UNKNOWN_IF, IDS_ERR_INTERFACE);
  2778. TEMP_ERROR_OVERRIDE(RPC_S_PROCNUM_OUT_OF_RANGE, IDS_ERR_INTERFACE);
  2779. ConnectServerDlg dlg;
  2780. if (dlg.DoModal() == IDOK)
  2781. {
  2782. //
  2783. // Clean up name.
  2784. //
  2785. CString strServerName(dlg.QueryServerName());
  2786. int cServices = 0;
  2787. //
  2788. // The function will report the errors
  2789. //
  2790. CError err;
  2791. {
  2792. CWaitCursor wait;
  2793. err = AddServerToList(
  2794. TRUE, // Cache
  2795. FALSE, // Handle errors
  2796. strServerName,
  2797. cServices
  2798. );
  2799. }
  2800. if (err.Failed())
  2801. {
  2802. err.MessageBoxFormat(
  2803. IDS_ERROR_CONNECTING,
  2804. MB_OK,
  2805. NO_HELP_CONTEXT,
  2806. (LPCTSTR)strServerName
  2807. );
  2808. }
  2809. else if (cServices == 0)
  2810. {
  2811. //
  2812. // No errors, but no services found
  2813. //
  2814. ::AfxMessageBox(IDS_NO_SERVICE);
  2815. }
  2816. }
  2817. }
  2818. void
  2819. CComponentDataImpl::DoConfigure(
  2820. IN CIISObject * pObject
  2821. )
  2822. /*++
  2823. Routine Description:
  2824. Configure the given iis object
  2825. Arguments:
  2826. CIISObject * pObject : Object to be configured
  2827. Return Value:
  2828. None
  2829. --*/
  2830. {
  2831. CError err;
  2832. //
  2833. // We need a window handle for this, but MMC won't
  2834. // give us one. Fortunately, we know MMC to be
  2835. // an MFC app, so we can sleazily grab it anyway.
  2836. //
  2837. CWnd * pMainWnd = NULL;
  2838. {
  2839. HWND hwnd;
  2840. err = m_pConsole->GetMainWindow(&hwnd);
  2841. if (err.Succeeded())
  2842. {
  2843. pMainWnd = CWnd::FromHandle(hwnd);
  2844. }
  2845. }
  2846. ASSERT(pMainWnd != NULL);
  2847. CWnd wnd;
  2848. if (pMainWnd == NULL)
  2849. {
  2850. //
  2851. // No main window in MMC? Use NULL handle
  2852. //
  2853. pMainWnd = &wnd;
  2854. }
  2855. ASSERT(m_pConsole);
  2856. ASSERT(pObject->IsConfigurable());
  2857. err = pObject->Configure(pMainWnd);
  2858. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  2859. if (!err.MessageBoxOnFailure())
  2860. {
  2861. //
  2862. // Refresh and display the entry
  2863. //
  2864. OnProperties((LPARAM)pObject);
  2865. }
  2866. }
  2867. BOOL
  2868. CComponentDataImpl::DeleteObject(
  2869. IN CIISObject * pObject
  2870. )
  2871. /*++
  2872. Routine Description:
  2873. Delete the given iisobject. Ask for confirmation first.
  2874. Arguments:
  2875. CIISObject * pObject : Object to be deleted
  2876. Return Value:
  2877. TRUE if the item was deleted successfully,
  2878. FALSE otherwise.
  2879. --*/
  2880. {
  2881. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  2882. BOOL fReturn = FALSE;
  2883. //
  2884. // If a property sheet is open for this item, don't
  2885. // allow deletion.
  2886. //
  2887. LPPROPERTYSHEETPROVIDER piPropertySheetProvider = NULL;
  2888. HRESULT hr = m_pConsole->QueryInterface(
  2889. IID_IPropertySheetProvider,
  2890. (void **)&piPropertySheetProvider
  2891. );
  2892. if (FindOpenPropSheetOnNodeAndDescendants(
  2893. piPropertySheetProvider,
  2894. (ULONG_PTR)pObject
  2895. ))
  2896. {
  2897. //
  2898. // Already had properties open
  2899. //
  2900. ::AfxMessageBox(IDS_PROP_OPEN);
  2901. }
  2902. else
  2903. {
  2904. CError err;
  2905. // Before we go and delete this baby,
  2906. // let's check if it's got a Cluster property set.
  2907. if (pObject->IsClusterEnabled())
  2908. {
  2909. ::AfxMessageBox(IDS_CLUSTER_ENABLED_2);
  2910. }
  2911. else
  2912. {
  2913. if (!pObject->HandleUI() || NoYesMessageBox(IDS_CONFIRM_DELETE))
  2914. {
  2915. CWaitCursor wait;
  2916. err = pObject->Delete();
  2917. if (pObject->HandleUI())
  2918. {
  2919. //
  2920. // Only complain if we're to handle the error messages.
  2921. // In e.g. the file system, explorer handles all error
  2922. // messages
  2923. //
  2924. err.MessageBoxOnFailure();
  2925. }
  2926. if (err.Succeeded())
  2927. {
  2928. ASSERT(m_pScope);
  2929. //
  2930. // Delete the item from the view, but be careful that
  2931. // result item nodes store a scope handle, but which
  2932. // actually refers to the _parent_'s scope handle.
  2933. //
  2934. if (!pObject->ScopeHandleIsParent())
  2935. {
  2936. m_pScope->DeleteItem(pObject->GetScopeHandle(), TRUE);
  2937. delete pObject;
  2938. }
  2939. fReturn = TRUE;
  2940. }
  2941. }
  2942. }
  2943. }
  2944. piPropertySheetProvider->Release();
  2945. return fReturn;
  2946. }
  2947. void
  2948. CComponentDataImpl::DisconnectItem(
  2949. IN CIISObject * pObject
  2950. )
  2951. /*++
  2952. Routine Description:
  2953. Delete the given iisobject. Ask for confirmation first.
  2954. Arguments:
  2955. CIISObject * pObject : Object to be deleted
  2956. Return Value:
  2957. None
  2958. --*/
  2959. {
  2960. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  2961. //
  2962. // If a property sheet is open for this item, don't
  2963. // allow deletion.
  2964. //
  2965. LPPROPERTYSHEETPROVIDER piPropertySheetProvider = NULL;
  2966. HRESULT hr = m_pConsole->QueryInterface(
  2967. IID_IPropertySheetProvider,
  2968. (void **)&piPropertySheetProvider
  2969. );
  2970. if (FindOpenPropSheetOnNodeAndDescendants(
  2971. piPropertySheetProvider,
  2972. (ULONG_PTR)pObject
  2973. ))
  2974. {
  2975. //
  2976. // Already had properties open
  2977. //
  2978. ::AfxMessageBox(IDS_PROP_OPEN);
  2979. }
  2980. else
  2981. {
  2982. CString strMachine(pObject->GetMachineName());
  2983. CString str, str2;
  2984. VERIFY(str.LoadString(IDS_CONFIRM_DISCONNECT));
  2985. str2.Format(str, strMachine);
  2986. if (NoYesMessageBox(str2))
  2987. {
  2988. //
  2989. // Remove from Cache and oblist
  2990. //
  2991. CError err(RemoveServerFromList(TRUE, strMachine));
  2992. if (!err.MessageBoxOnFailure())
  2993. {
  2994. ASSERT(m_pScope);
  2995. m_pScope->DeleteItem(pObject->GetScopeHandle(), TRUE);
  2996. delete pObject;
  2997. }
  2998. }
  2999. }
  3000. piPropertySheetProvider->Release();
  3001. }
  3002. STDMETHODIMP
  3003. CComponentDataImpl::Command(
  3004. IN long nCommandID,
  3005. IN LPDATAOBJECT lpDataObject
  3006. )
  3007. /*++
  3008. Routine Description:
  3009. Command handler
  3010. Arguments:
  3011. long nCommandID : Command ID
  3012. LPDATAOBJECT lpDataObject : Selected Data object
  3013. Return Value:
  3014. HRESULT
  3015. --*/
  3016. {
  3017. if (nCommandID == IDM_CONNECT)
  3018. {
  3019. //
  3020. // This is the only case that doesn't require a selected
  3021. // data object.
  3022. //
  3023. OnConnectOne();
  3024. return S_OK;
  3025. }
  3026. /*
  3027. if (IsMMCMultiSelectDataObject(lpDataObject))
  3028. {
  3029. //
  3030. // Do something for multi-select?
  3031. //
  3032. TRACEEOLID("Multiple selection");
  3033. }
  3034. */
  3035. INTERNAL * pInternal = lpDataObject
  3036. ? ExtractInternalFormat(lpDataObject)
  3037. : NULL;
  3038. if (pInternal == NULL)
  3039. {
  3040. return S_OK;
  3041. }
  3042. CIISObject * pObject = (CIISObject *)pInternal->m_cookie;
  3043. FREE_DATA(pInternal);
  3044. CError err;
  3045. switch (nCommandID)
  3046. {
  3047. case IDM_METABACKREST:
  3048. OnMetaBackRest(pObject);
  3049. break;
  3050. case IDM_SHUTDOWN:
  3051. OnIISShutDown(pObject);
  3052. break;
  3053. case IDM_DISCONNECT:
  3054. DisconnectItem(pObject);
  3055. break;
  3056. case IDM_CONFIGURE:
  3057. DoConfigure(pObject);
  3058. break;
  3059. case IDM_STOP:
  3060. DoChangeState(pObject, INetServiceStopped);
  3061. m_pConsole->UpdateAllViews(lpDataObject, 0L, (LONG_PTR)pObject);
  3062. break;
  3063. case IDM_START:
  3064. DoChangeState(pObject, INetServiceRunning);
  3065. m_pConsole->UpdateAllViews(lpDataObject, 0L, (LONG_PTR)pObject);
  3066. break;
  3067. case IDM_PAUSE:
  3068. DoChangeState(
  3069. pObject,
  3070. pObject->IsPaused() ? INetServiceRunning : INetServicePaused
  3071. );
  3072. m_pConsole->UpdateAllViews(lpDataObject, 0L, (LONG_PTR)pObject);
  3073. break;
  3074. case IDM_EXPLORE:
  3075. pObject->Explore();
  3076. break;
  3077. case IDM_OPEN:
  3078. pObject->Open();
  3079. break;
  3080. case IDM_BROWSE:
  3081. pObject->Browse();
  3082. break;
  3083. case IDM_TASK_SECURITY_WIZARD:
  3084. {
  3085. //
  3086. // Launch the security wizard
  3087. //
  3088. err = pObject->SecurityWizard();
  3089. err.MessageBoxOnFailure();
  3090. }
  3091. break;
  3092. case IDM_NEW_INSTANCE:
  3093. {
  3094. //
  3095. // Executed from another instance of the same type
  3096. //
  3097. ISMINSTANCEINFO ii;
  3098. CServerInfo * pServerInfo = pObject->GetServerInfo();
  3099. ASSERT(pServerInfo);
  3100. err = pServerInfo->AddInstance(&ii, sizeof(ii));
  3101. if (err.Succeeded())
  3102. {
  3103. CIISInstance * pInstance = new CIISInstance(&ii, pServerInfo);
  3104. //
  3105. // Add the new instance grouped with the service type,
  3106. // and select it
  3107. //
  3108. BOOL fNext;
  3109. HSCOPEITEM hParent = FindServerInfoParent(
  3110. GetRootHandle(),
  3111. pServerInfo
  3112. );
  3113. ASSERT(hParent != NULL);
  3114. HSCOPEITEM hSibling = FindNextInstanceSibling(
  3115. hParent,
  3116. pInstance,
  3117. &fNext
  3118. );
  3119. HSCOPEITEM hItem = AddIISObject(
  3120. hParent,
  3121. pInstance,
  3122. hSibling,
  3123. fNext
  3124. );
  3125. //
  3126. // hItem could return NULL if the hParent
  3127. // was not yet expanded.
  3128. //
  3129. if (hItem)
  3130. {
  3131. m_pConsole->SelectScopeItem(hItem);
  3132. }
  3133. }
  3134. }
  3135. break;
  3136. case IDM_NEW_VROOT:
  3137. CIISChildNode * pChild;
  3138. err = pObject->AddChildNode(pChild);
  3139. if (err.Succeeded())
  3140. {
  3141. //
  3142. // Insert prior to file/dir nodes, and select the item
  3143. //
  3144. HSCOPEITEM hItem = AddIISObject(
  3145. pObject->GetScopeHandle(),
  3146. pChild,
  3147. FindNextVDirSibling(pObject->GetScopeHandle(), pChild)
  3148. );
  3149. //
  3150. // hItem could return NULL if the parent object
  3151. // was not yet expanded.
  3152. //
  3153. if (hItem)
  3154. {
  3155. m_pConsole->SelectScopeItem(hItem);
  3156. }
  3157. }
  3158. break;
  3159. default:
  3160. //
  3161. // Now try to get to the service that we're
  3162. // supposed to create a new instance for.
  3163. //
  3164. if (nCommandID >= IDM_NEW_EX_INSTANCE)
  3165. {
  3166. int nID = nCommandID - IDM_NEW_EX_INSTANCE;
  3167. CNewInstanceCmd * pcmd =
  3168. (CNewInstanceCmd *)m_oblNewInstanceCmds.Index(nID);
  3169. ASSERT(pcmd != NULL);
  3170. if (pcmd)
  3171. {
  3172. ISMINSTANCEINFO ii;
  3173. CServerInfo * pServerInfo = FindServerInfo(
  3174. pObject->GetMachineName(),
  3175. pcmd->GetServiceInfo()
  3176. );
  3177. if (pServerInfo == NULL)
  3178. {
  3179. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  3180. ::AfxMessageBox(IDS_ERR_SERVICE_NOT_INSTALLED);
  3181. break;
  3182. }
  3183. ASSERT(pServerInfo);
  3184. err = pServerInfo->AddInstance(&ii, sizeof(ii));
  3185. if (err.Succeeded())
  3186. {
  3187. //
  3188. // Add and select the item
  3189. //
  3190. CIISInstance * pInstance = new CIISInstance(
  3191. &ii,
  3192. pServerInfo
  3193. );
  3194. BOOL fNext;
  3195. HSCOPEITEM hSibling = FindNextInstanceSibling(
  3196. pObject->GetScopeHandle(),
  3197. pInstance,
  3198. &fNext
  3199. );
  3200. HSCOPEITEM hItem = AddIISObject(
  3201. pObject->GetScopeHandle(),
  3202. pInstance,
  3203. hSibling,
  3204. fNext
  3205. );
  3206. m_pConsole->SelectScopeItem(hItem);
  3207. }
  3208. }
  3209. }
  3210. else
  3211. {
  3212. //
  3213. // Unknown command!
  3214. //
  3215. ASSERT(FALSE);
  3216. }
  3217. break;
  3218. }
  3219. return S_OK;
  3220. }
  3221. //
  3222. // Notification handlers for IComponentData
  3223. //
  3224. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3225. HRESULT
  3226. CComponentDataImpl::OnAdd(
  3227. IN MMC_COOKIE cookie,
  3228. IN LPARAM arg,
  3229. IN LPARAM param
  3230. )
  3231. /*++
  3232. Routine Description:
  3233. Add handler
  3234. Arguments:
  3235. MMC_COOKIE cookie : Scope item cookie (CIISObject *)
  3236. LPARAM arg : Argument
  3237. LPARAM param : Parameter
  3238. Return Value:
  3239. HRESULT
  3240. --*/
  3241. {
  3242. return E_UNEXPECTED;
  3243. }
  3244. HRESULT
  3245. CComponentDataImpl::OnDelete(
  3246. IN MMC_COOKIE cookie
  3247. )
  3248. /*++
  3249. Routine Description:
  3250. Handle deletion of the given scope item (CIISObject *)
  3251. Arguments:
  3252. MMC_COOKIE cookie : Casts to a CIISObject *
  3253. Return Value:
  3254. HRESULT
  3255. --*/
  3256. {
  3257. CIISObject * pObject = (CIISObject *)cookie;
  3258. if (pObject == NULL)
  3259. {
  3260. return S_FALSE;
  3261. }
  3262. delete pObject;
  3263. return S_OK;
  3264. }
  3265. HRESULT
  3266. CComponentDataImpl::OnRename(
  3267. IN MMC_COOKIE cookie,
  3268. IN LPARAM arg,
  3269. IN LPARAM param
  3270. )
  3271. /*++
  3272. Routine Description:
  3273. Rename notification handler
  3274. Arguments:
  3275. MMC_COOKIE cookie : Currently selected cookie (CIISObject *)
  3276. LPARAM arg : Notification argument
  3277. LPARAM param : Notification parameter
  3278. Return Value:
  3279. HRESULT
  3280. --*/
  3281. {
  3282. CIISObject * pObject = (CIISObject *)cookie;
  3283. if (pObject == NULL)
  3284. {
  3285. //
  3286. // Can't rename this one
  3287. //
  3288. return S_FALSE;
  3289. }
  3290. if (!arg)
  3291. {
  3292. //
  3293. // Check to see if we're renamable
  3294. //
  3295. return pObject->IsRenamable() ? S_OK : S_FALSE;
  3296. }
  3297. TEMP_ERROR_OVERRIDE(ERROR_ALREADY_EXISTS, IDS_ERR_DUP_VROOT);
  3298. CError err;
  3299. //
  3300. // Do an actual rename
  3301. //
  3302. LPCTSTR lpstrNewName = (LPCTSTR)param;
  3303. err = pObject->Rename(lpstrNewName);
  3304. if (err.Succeeded())
  3305. {
  3306. //
  3307. // Force a refresh on the children
  3308. //
  3309. pObject->DirtyChildren();
  3310. }
  3311. else
  3312. {
  3313. if (pObject->HandleUI())
  3314. {
  3315. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  3316. err.MessageBox();
  3317. }
  3318. }
  3319. return err.Succeeded() ? S_OK : S_FALSE;
  3320. }
  3321. HRESULT
  3322. CComponentDataImpl::OnRemoveChildren(
  3323. IN LPARAM arg
  3324. )
  3325. /*++
  3326. Routine Description:
  3327. 'Remove Children' notification handler
  3328. Arguments:
  3329. LPARAM arg : Notification argument
  3330. Return Value:
  3331. HRESULT
  3332. --*/
  3333. {
  3334. m_strlCachedServers.RemoveAll();
  3335. return S_OK;
  3336. }
  3337. HRESULT
  3338. CComponentDataImpl::OnExpand(
  3339. LPDATAOBJECT lpDataObject,
  3340. LPARAM arg,
  3341. LPARAM param
  3342. )
  3343. /*++
  3344. Routine Description:
  3345. Expand notification handler
  3346. Arguments:
  3347. LPDATAOBJECT lpDataObject : Currently selected cookie (CIISObject *)
  3348. LPARAM arg : Notification argument
  3349. LPARAM param : Notification parameter
  3350. Return Value:
  3351. HRESULT
  3352. --*/
  3353. {
  3354. if (arg)
  3355. {
  3356. //
  3357. // Did Initialize get called?
  3358. //
  3359. ASSERT(m_pScope != NULL);
  3360. EnumerateScopePane(lpDataObject, param);
  3361. }
  3362. return S_OK;
  3363. }
  3364. HRESULT
  3365. CComponentDataImpl::OnSelect(
  3366. IN MMC_COOKIE cookie,
  3367. IN LPARAM arg,
  3368. IN LPARAM param
  3369. )
  3370. /*++
  3371. Routine Description:
  3372. Selection notification handler
  3373. Arguments:
  3374. MMC_COOKIE cookie : Currently selected cookie (CIISObject *)
  3375. LPARAM arg : Notification argument
  3376. LPARAM param : Notification parameter
  3377. Return Value:
  3378. HRESULT
  3379. --*/
  3380. {
  3381. return E_UNEXPECTED;
  3382. }
  3383. HRESULT
  3384. CComponentDataImpl::OnContextMenu(
  3385. IN MMC_COOKIE cookie,
  3386. IN LPARAM arg,
  3387. IN LPARAM param
  3388. )
  3389. /*++
  3390. Routine Description:
  3391. Context Menu notification handler
  3392. Arguments:
  3393. MMC_COOKIE cookie : Currently selected cookie (CIISObject *)
  3394. LPARAM arg : Notification argument
  3395. LPARAM param : Notification parameter
  3396. Return Value:
  3397. HRESULT
  3398. --*/
  3399. {
  3400. return S_OK;
  3401. }
  3402. HRESULT
  3403. CComponentDataImpl::OnProperties(
  3404. IN LPARAM param
  3405. )
  3406. /*++
  3407. Routine Description:
  3408. Properties change notification handler
  3409. Arguments:
  3410. LPARAM arg : Notification argument (CIISObject *)
  3411. Return Value:
  3412. HRESULT
  3413. --*/
  3414. {
  3415. if (param == NULL)
  3416. {
  3417. return S_OK;
  3418. }
  3419. CIISObject * pObject = (CIISObject *)param;
  3420. ASSERT(pObject != NULL);
  3421. if (pObject != NULL)
  3422. {
  3423. CString strOldPath(pObject->QueryPhysicalPath());
  3424. CString strOldRedirect(pObject->QueryRedirPath());
  3425. BOOL fOldChildRedirOnly = pObject->IsChildOnlyRedir();
  3426. //
  3427. // Refresh the data to see if either the physical or redirection
  3428. // path has changed. If it has, refresh the child objects
  3429. //
  3430. CError err(pObject->RefreshData());
  3431. //
  3432. // Determine if the file system needs to be refreshed
  3433. //
  3434. BOOL fRefreshFileSystem = err.Succeeded()
  3435. && pObject->SupportsChildren()
  3436. && pObject->ChildrenExpanded()
  3437. && pObject->SupportsFileSystem()
  3438. && strOldPath.CompareNoCase(pObject->QueryPhysicalPath()) != 0;
  3439. //
  3440. // Determine if everything needs to be refreshed
  3441. //
  3442. BOOL fFullRefresh = err.Succeeded()
  3443. && pObject->SupportsChildren()
  3444. && pObject->ChildrenExpanded()
  3445. && (strOldRedirect.CompareNoCase(pObject->QueryRedirPath()) != 0
  3446. || fOldChildRedirOnly != pObject->IsChildOnlyRedir());
  3447. TRACEEOLID("Refresh files: "
  3448. << fRefreshFileSystem
  3449. << " Full Refresh: "
  3450. << fFullRefresh
  3451. );
  3452. RefreshIISObject(pObject, fFullRefresh);
  3453. if (!fFullRefresh && fRefreshFileSystem)
  3454. {
  3455. //
  3456. // Not a full refresh -- the file system only.
  3457. //
  3458. CString strPhysicalPath, strMetaRoot;
  3459. pObject->BuildPhysicalPath(strPhysicalPath);
  3460. pObject->BuildFullPath(strMetaRoot, FALSE);
  3461. //
  3462. // Note: we can't use ExpandIISObject, because we're only
  3463. // replacing specific nodes, not the entire subtree
  3464. //
  3465. AddFileSystem(
  3466. pObject->GetScopeHandle(),
  3467. strPhysicalPath,
  3468. strMetaRoot,
  3469. pObject->FindOwnerInstance(),
  3470. GET_DIRECTORIES,
  3471. DELETE_CURRENT_DIR_TREE
  3472. );
  3473. //
  3474. // Mark this node to indicate that the child nodes
  3475. // have been added.
  3476. //
  3477. pObject->CleanChildren();
  3478. }
  3479. //
  3480. // Re-enumerate the result side if the current item is
  3481. // selected.
  3482. //
  3483. if ((fRefreshFileSystem || fFullRefresh) && pObject->IsScopeSelected())
  3484. {
  3485. ASSERT(m_pConsole);
  3486. m_pConsole->SelectScopeItem(pObject->GetScopeHandle());
  3487. }
  3488. }
  3489. return S_OK;
  3490. }
  3491. CServerInfo *
  3492. CComponentDataImpl::FindServerInfo(
  3493. IN LPCTSTR lpstrMachine,
  3494. IN CServiceInfo * pServiceInfo
  3495. )
  3496. /*++
  3497. Routine Description:
  3498. Find specific server info (i.e. machine name / service info
  3499. combination type)
  3500. Arguments:
  3501. LPCTSTR lpstrMachine : Machine name
  3502. CServiceInfo * pServiceInfo : Service info
  3503. Return Value:
  3504. Server Info object pointer, or NULL
  3505. --*/
  3506. {
  3507. CServerInfo * pServerInfo;
  3508. CObListIter obli(m_oblServers);
  3509. //
  3510. // Search is sequential, because we don't foresee more then a few
  3511. // of these objects in the cache
  3512. //
  3513. while (pServerInfo = (CServerInfo *)obli.Next())
  3514. {
  3515. if (!::lstrcmpi(pServerInfo->QueryServerName(), lpstrMachine)
  3516. && pServerInfo->GetServiceInfo() == pServiceInfo)
  3517. {
  3518. //
  3519. // Found it
  3520. //
  3521. return pServerInfo;
  3522. }
  3523. }
  3524. return NULL;
  3525. }
  3526. void
  3527. CComponentDataImpl::RefreshIISObject(
  3528. IN CIISObject * pObject,
  3529. IN BOOL fExpandTree,
  3530. IN HSCOPEITEM pParent
  3531. )
  3532. /*++
  3533. Routine Description:
  3534. Refresh object, and optionally re-enumerate its display
  3535. Arguments:
  3536. CIISObject * pObject : Object to be refreshed
  3537. BOOL fExpandTree : TRUE to expand its tree
  3538. Return Value:
  3539. None
  3540. --*/
  3541. {
  3542. ASSERT(pObject != NULL);
  3543. CError err;
  3544. CServerInfo * pServer = pObject->GetServerInfo();
  3545. CMetaInterface * pInterface = NULL;
  3546. if (pServer)
  3547. {
  3548. pInterface = GetMetaKeyFromHandle(pServer->GetHandle());
  3549. }
  3550. if (pInterface)
  3551. {
  3552. BEGIN_ASSURE_BINDING_SECTION
  3553. err = pObject->RefreshData();
  3554. END_ASSURE_BINDING_SECTION(err, pInterface, RPC_S_SERVER_UNAVAILABLE);
  3555. }
  3556. else
  3557. {
  3558. err = pObject->RefreshData();
  3559. }
  3560. if (err.Failed())
  3561. {
  3562. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  3563. err.MessageBox();
  3564. return;
  3565. }
  3566. pObject->RefreshDisplayInfo();
  3567. //
  3568. // Reenumerate its children if requested to do so and its necessary
  3569. //
  3570. if (fExpandTree)
  3571. {
  3572. if (pObject->ChildrenExpanded())
  3573. {
  3574. HSCOPEITEM hNode = pObject->GetScopeHandle();
  3575. if (KillChildren(
  3576. hNode,
  3577. IDS_PROP_OPEN_REFRESH,
  3578. DELETE_EVERYTHING,
  3579. DONT_CONTINUE_ON_OPEN_SHEET
  3580. ))
  3581. {
  3582. pObject->DirtyChildren();
  3583. ExpandIISObject(hNode, pObject);
  3584. }
  3585. }
  3586. //
  3587. // Re-enumerate the result side, if the current item is
  3588. // selected.
  3589. //
  3590. if (pObject->IsScopeSelected())
  3591. {
  3592. ASSERT(m_pConsole);
  3593. m_pConsole->SelectScopeItem(pObject->GetScopeHandle());
  3594. }
  3595. }
  3596. }
  3597. void
  3598. CComponentDataImpl::LoadDynamicExtensions(
  3599. IN HSCOPEITEM hParent,
  3600. IN CIISObject * pObject
  3601. )
  3602. /*++
  3603. Routine Description:
  3604. Load dynamic snap-in extensions for the given node type.
  3605. Arguments:
  3606. None
  3607. Return Value:
  3608. None (if it fails, it always fails silently)
  3609. --*/
  3610. {
  3611. //
  3612. // We'll look here (on the server) to see if we need to load
  3613. // extension snap-ins.
  3614. //
  3615. const TCHAR SERVICES_KEY[] = SZ_REMOTEIISEXT;
  3616. if (pObject == NULL)
  3617. {
  3618. //
  3619. // This should never happen, right?
  3620. //
  3621. ASSERT(FALSE);
  3622. return;
  3623. }
  3624. CString str, strKey;
  3625. //
  3626. // Get base path for the given node type
  3627. //
  3628. strKey.Format(
  3629. _T("%s\\%s"),
  3630. SERVICES_KEY,
  3631. GUIDToCString(pObject->QueryGUID(), str)
  3632. );
  3633. TRACEEOLID(
  3634. pObject->GetMachineName() <<
  3635. " Attempting to dynamically load extensions for " <<
  3636. strKey);
  3637. CError err;
  3638. CRMCRegKey rkExtensions(REG_KEY, strKey, KEY_READ, pObject->GetMachineName());
  3639. CComQIPtr<IConsoleNameSpace2, &IID_IConsoleNameSpace2> pIConsoleNameSpace2
  3640. = m_pConsole;
  3641. if (pIConsoleNameSpace2 && rkExtensions.Ok())
  3642. {
  3643. DWORD dwType;
  3644. GUID guidExtension;
  3645. CRMCRegValueIter rkValues(rkExtensions);
  3646. //
  3647. // Loop through, and attempt to add each extension found in the
  3648. // registry
  3649. //
  3650. while (rkValues.Next(&str, &dwType) == ERROR_SUCCESS)
  3651. {
  3652. TRACEEOLID("Found dynamic extension: " << str);
  3653. err = ::CLSIDFromString((LPTSTR)(LPCTSTR)str, &guidExtension);
  3654. if (err.Succeeded())
  3655. {
  3656. err = pIConsoleNameSpace2->AddExtension(hParent, &guidExtension);
  3657. }
  3658. TRACEEOLID("DynaLoad returned " << err);
  3659. }
  3660. }
  3661. }
  3662. void
  3663. CComponentDataImpl::ExpandIISObject(
  3664. IN HSCOPEITEM hParent,
  3665. IN CIISObject * pObject,
  3666. IN LPTSTR lpszMachineName
  3667. )
  3668. /*++
  3669. Routine Description:
  3670. Expand the given IIS object tree
  3671. Arguments:
  3672. HSCOPEITEM hParent : Handle to parent item
  3673. CIISObject * pObject : IISObject to expand
  3674. Return Value:
  3675. None
  3676. --*/
  3677. {
  3678. CError err;
  3679. if (pObject != NULL)
  3680. {
  3681. ASSERT(hParent == pObject->GetScopeHandle());
  3682. }
  3683. //
  3684. // make sure we QI'ed for the interface
  3685. //
  3686. ASSERT(m_pScope != NULL);
  3687. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  3688. {
  3689. CWaitCursor wait;
  3690. if (m_hIISRoot == NULL)
  3691. {
  3692. //
  3693. // Store the IIS root node for future use
  3694. //
  3695. m_hIISRoot = hParent;
  3696. }
  3697. if (pObject == NULL)
  3698. {
  3699. //
  3700. // Static root node -- populate with computers.
  3701. //
  3702. // This is done only once per session
  3703. //
  3704. ASSERT(GetRootHandle() == hParent);
  3705. TRACEEOLID("Inserting static root node");
  3706. AddCachedServersToView();
  3707. CServerInfo * pServerInfo = NULL;
  3708. CObListIter obli(m_oblServers);
  3709. if (m_fIsExtension)
  3710. {
  3711. //
  3712. // Since we're extending the computer management
  3713. // snap-in, only add the one server info parent
  3714. // object (only one computer, after all).
  3715. // This is also necessary, because for some reason
  3716. // I can't get the child item nodes of my parent,
  3717. // even if I've added them myself, and so we'd get
  3718. // duplicates.
  3719. //
  3720. if (lpszMachineName != NULL && *lpszMachineName != 0)
  3721. {
  3722. CServerInfo * p;
  3723. while (p = (CServerInfo *)obli.Next())
  3724. {
  3725. if (!::lstrcmpi(p->QueryServerName(), lpszMachineName))
  3726. {
  3727. pServerInfo = p;
  3728. break;
  3729. }
  3730. }
  3731. }
  3732. else
  3733. pServerInfo = (CServerInfo *)obli.Next();
  3734. ASSERT(pServerInfo != NULL);
  3735. if (pServerInfo)
  3736. {
  3737. AddServerInfoParent(hParent, pServerInfo);
  3738. }
  3739. }
  3740. else
  3741. {
  3742. //
  3743. // We're the primary snap-in, add all the server info
  3744. // parent objects (computers) to the view
  3745. //
  3746. while (pServerInfo = (CServerInfo *)obli.Next())
  3747. {
  3748. if (pServerInfo->IsServiceSelected())
  3749. {
  3750. //
  3751. // Add each item in the tree
  3752. //
  3753. AddServerInfoParent(hParent, pServerInfo);
  3754. }
  3755. }
  3756. }
  3757. }
  3758. else
  3759. {
  3760. if (!pObject->ChildrenExpanded())
  3761. {
  3762. //
  3763. // Delete whatever children there may be
  3764. //
  3765. if (pObject->QueryGUID() == cMachineNode)
  3766. {
  3767. CIISMachine * pMachine = (CIISMachine *)pObject;
  3768. CServerInfo * pServerInfo;
  3769. CObListIter obli(m_oblServers);
  3770. while (pServerInfo = (CServerInfo *)obli.Next())
  3771. {
  3772. if (pServerInfo->MatchServerName(pMachine->GetMachineName())
  3773. && pServerInfo->IsServiceSelected())
  3774. {
  3775. //
  3776. // Add each item in the tree
  3777. //
  3778. AddServerInfo(hParent, pServerInfo, FALSE);
  3779. }
  3780. }
  3781. }
  3782. CString strMetaPath;
  3783. if (pObject->SupportsChildren())
  3784. {
  3785. pObject->BuildFullPath(strMetaPath, FALSE);
  3786. //
  3787. // Expand the children off the root
  3788. //
  3789. AddVirtualRoots(
  3790. hParent,
  3791. strMetaPath,
  3792. pObject->FindOwnerInstance()
  3793. );
  3794. }
  3795. if (pObject->SupportsFileSystem())
  3796. {
  3797. if (strMetaPath.IsEmpty())
  3798. {
  3799. pObject->BuildFullPath(strMetaPath, FALSE);
  3800. }
  3801. //
  3802. // Expand file system objects
  3803. //
  3804. CString strPhysicalPath;
  3805. pObject->BuildPhysicalPath(strPhysicalPath);
  3806. AddFileSystem(
  3807. hParent,
  3808. strPhysicalPath,
  3809. strMetaPath,
  3810. pObject->FindOwnerInstance(),
  3811. GET_DIRECTORIES,
  3812. DONT_DELETE_CURRENT_DIR_TREE
  3813. );
  3814. }
  3815. //
  3816. // Now load the dynamic extensions
  3817. //
  3818. LoadDynamicExtensions(hParent, pObject);
  3819. //
  3820. // Mark this node to indicate that the child nodes
  3821. // have been added.
  3822. //
  3823. pObject->CleanChildren();
  3824. }
  3825. }
  3826. }
  3827. err.MessageBoxOnFailure();
  3828. }
  3829. void
  3830. CComponentDataImpl::EnumerateScopePane(
  3831. IN LPDATAOBJECT lpDataObject,
  3832. IN HSCOPEITEM hParent
  3833. )
  3834. /*++
  3835. Routine Description:
  3836. Handle expansion of hParent scope item.
  3837. Arguments:
  3838. LPDATAOBJECT lpDataObject : Selected data object
  3839. HSCOPEITEM hParent : Scope handle of parent item or NULL
  3840. Return Value:
  3841. None
  3842. --*/
  3843. {
  3844. ASSERT(lpDataObject != NULL);
  3845. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  3846. MMC_COOKIE cookie = 0L;
  3847. LPTSTR lpszMachine = NULL;
  3848. if (pInternal == NULL)
  3849. {
  3850. //
  3851. // Not mine -- must be an extension; Get the machine name
  3852. //
  3853. ASSERT(m_fIsExtension);
  3854. lpszMachine = ExtractMachineName(lpDataObject);
  3855. TRACEEOLID(lpszMachine);
  3856. CString strServerName = PURE_COMPUTER_NAME(lpszMachine);
  3857. if (strServerName.IsEmpty())
  3858. {
  3859. //
  3860. // MyComputer reports "" for the computer name.
  3861. // This means the local machine is indicated
  3862. //
  3863. DWORD dwSize = MAX_SERVERNAME_LEN;
  3864. if (::GetComputerName(strServerName.GetBuffer(dwSize + 1), &dwSize))
  3865. {
  3866. strServerName.ReleaseBuffer();
  3867. }
  3868. }
  3869. //
  3870. // Since we're an extension, the cache will not be
  3871. // loaded from the persistence stream, and we can
  3872. // therefore guarantee that this will be the only
  3873. // item in the cache.
  3874. //
  3875. AddServerToCache(strServerName, FALSE);
  3876. }
  3877. else
  3878. {
  3879. cookie = pInternal->m_cookie;
  3880. FREE_DATA(pInternal);
  3881. }
  3882. #ifdef _DEBUG
  3883. CIISObject * pObject = (CIISObject *)cookie;
  3884. if (pObject)
  3885. {
  3886. ASSERT(hParent == pObject->GetScopeHandle());
  3887. }
  3888. #endif // _DEBUG
  3889. ExpandIISObject(hParent, (CIISObject *)cookie, lpszMachine);
  3890. }
  3891. STDMETHODIMP
  3892. CComponentDataImpl::GetDisplayInfo(
  3893. IN LPSCOPEDATAITEM lpScopeDataItem
  3894. )
  3895. /*++
  3896. Routine Description:
  3897. Get display info (text, bitmap) for the selected scope item
  3898. Arguments:
  3899. LPSCOPEDATAITEM lpScopeDataItem : Selected item
  3900. Return Value:
  3901. HRESULT
  3902. --*/
  3903. {
  3904. ASSERT(lpScopeDataItem != NULL);
  3905. if (lpScopeDataItem == NULL)
  3906. {
  3907. return E_POINTER;
  3908. }
  3909. static CString strText;
  3910. CIISObject * pObject = (CIISObject *)lpScopeDataItem->lParam;
  3911. ASSERT(lpScopeDataItem->mask & SDI_STR);
  3912. pObject->GetDisplayText(strText);
  3913. lpScopeDataItem->displayname = (LPTSTR)(LPCTSTR)strText;
  3914. ASSERT(lpScopeDataItem->displayname != NULL);
  3915. return S_OK;
  3916. }
  3917. STDMETHODIMP
  3918. CComponentDataImpl::CompareObjects(
  3919. IN LPDATAOBJECT lpDataObjectA,
  3920. IN LPDATAOBJECT lpDataObjectB
  3921. )
  3922. /*++
  3923. Routine Description:
  3924. Compare two data objects. This is used by MMC to determine whether a
  3925. given node has a property sheet already open for it.
  3926. Arguments:
  3927. LPDATAOBJECT lpDataObjectA : Data object 1
  3928. LPDATAOBJECT lpDataObjectB : Data object 2
  3929. Return Value:
  3930. S_OK if the objects are identical, S_FALSE otherwise
  3931. --*/
  3932. {
  3933. if (lpDataObjectA == NULL || lpDataObjectB == NULL)
  3934. {
  3935. return E_POINTER;
  3936. }
  3937. //
  3938. // Make sure both data object are mine
  3939. //
  3940. INTERNAL * pA;
  3941. INTERNAL * pB;
  3942. HRESULT hr = S_FALSE;
  3943. pA = ExtractInternalFormat(lpDataObjectA);
  3944. pB = ExtractInternalFormat(lpDataObjectA);
  3945. if (pA != NULL && pB != NULL)
  3946. {
  3947. //hr = (*pA == *pB) ? S_OK : S_FALSE;
  3948. return S_OK;
  3949. }
  3950. FREE_DATA(pA);
  3951. FREE_DATA(pB);
  3952. return hr;
  3953. }
  3954. void
  3955. CComponentDataImpl::GetISMMachinePages()
  3956. /*++
  3957. Routine Description:
  3958. Load the names of the DLL providing ISM machine property
  3959. page extentions
  3960. Arguments:
  3961. Return Value:
  3962. --*/
  3963. {
  3964. /* OBSOLETE
  3965. OBSOLETE
  3966. OBSOLETE
  3967. OBSOLETE
  3968. OBSOLETE
  3969. CString strValueName;
  3970. DWORD dwValueType;
  3971. CRMCRegKey rkMachine(REG_KEY, SZ_ADDONMACHINEPAGES, KEY_READ);
  3972. if (rkMachine.Ok())
  3973. {
  3974. return;
  3975. }
  3976. CRMCRegValueIter rvi(rkMachine);
  3977. CIISMachine::AttachPages(&m_oblISMMachinePages);
  3978. try
  3979. {
  3980. while (rvi.Next(&strValueName, &dwValueType) == ERROR_SUCCESS)
  3981. {
  3982. CString strValue;
  3983. rkMachine.QueryValue(strValueName, strValue);
  3984. TRACEEOLID("Registering machine pages in " << strValue);
  3985. m_oblISMMachinePages.AddTail(new CISMMachinePageExt(strValue));
  3986. }
  3987. }
  3988. catch(CException * e)
  3989. {
  3990. TRACEEOLID("!!!exception building ISM machine page list");
  3991. e->ReportError();
  3992. e->Delete();
  3993. }
  3994. */
  3995. }
  3996. void
  3997. CComponentDataImpl::ConvertBitmapFormats(
  3998. IN CBitmap & bmpSource,
  3999. OUT CBitmap & bmp16x16,
  4000. OUT CBitmap & bmp32x32
  4001. )
  4002. /*++
  4003. Routine Description:
  4004. Convert a ISM service config bitmap to 16x16 and 32x32 exactly.
  4005. Downlevel services only included a single sized bitmap (usually
  4006. 16x16) for use in ISM. We need a small one and a large one,
  4007. so we expand as needed.
  4008. Arguments:
  4009. IN CBitmap & bmpSource : Source bitmap
  4010. OUT CBitmap & bmp16x16 : 16x16 output bitmap
  4011. OUT CBitmap & bmp32x32 : 32x32 output bitmap
  4012. Return Value:
  4013. None
  4014. --*/
  4015. {
  4016. CDC dcImage;
  4017. CDC dc16x16;
  4018. CDC dc32x32;
  4019. VERIFY(dcImage.CreateCompatibleDC(NULL));
  4020. VERIFY(dc16x16.CreateCompatibleDC(NULL));
  4021. VERIFY(dc32x32.CreateCompatibleDC(NULL));
  4022. CBitmap * pOld = dcImage.SelectObject(&bmpSource);
  4023. BITMAP bm;
  4024. VERIFY(bmpSource.GetObject(sizeof(bm), &bm));
  4025. VERIFY(bmp16x16.CreateBitmap(16, 16, bm.bmPlanes, bm.bmBitsPixel, NULL));
  4026. VERIFY(bmp32x32.CreateBitmap(32, 32, bm.bmPlanes, bm.bmBitsPixel, NULL));
  4027. CBitmap * pOld16x16 = dc16x16.SelectObject(&bmp16x16);
  4028. CBitmap * pOld32x32 = dc32x32.SelectObject(&bmp32x32);
  4029. dc16x16.StretchBlt(0, 0, 16, 16, &dcImage, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  4030. dc32x32.StretchBlt(0, 0, 32, 32, &dcImage, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  4031. dc16x16.SelectObject(pOld16x16);
  4032. dc32x32.SelectObject(pOld32x32);
  4033. dcImage.SelectObject(pOld);
  4034. }
  4035. BOOL
  4036. CComponentDataImpl::VerifyBitmapSize(
  4037. IN HBITMAP hBitmap,
  4038. IN LONG nHeight,
  4039. IN LONG nWidth
  4040. )
  4041. /*++
  4042. Routine Description:
  4043. Verify the given bitmap is of the right size
  4044. Arguments:
  4045. HBITMAP hBitmap : Bitmap handle
  4046. LONG nHeight : Height the bitmap should be
  4047. LONG nWidth : Width the bitmap should be
  4048. Return Value:
  4049. TRUE if the bitmap is of the right size, FALSE otherwise
  4050. --*/
  4051. {
  4052. BITMAP bm;
  4053. int cb = GetObject(hBitmap, sizeof(BITMAP), &bm);
  4054. return (cb == sizeof(BITMAP)
  4055. && bm.bmWidth == nWidth
  4056. && bm.bmHeight == nHeight
  4057. );
  4058. }
  4059. BOOL
  4060. CComponentDataImpl::GetBitmapParms(
  4061. IN CServiceInfo * pServiceInfo,
  4062. IN BMP_TYPES bmpt,
  4063. OUT CBitmap *& pbmp16x16,
  4064. OUT CBitmap *& pbmp32x32,
  4065. OUT COLORREF & rgbMask
  4066. )
  4067. /*++
  4068. Routine Description:
  4069. Get bitmap information from service info object
  4070. Arguments:
  4071. CServiceInfo * pServiceInfo : Service info
  4072. BMP_TYPES bmpt : Type of info requested
  4073. COLORREF & rgbMask : Returns background mask
  4074. Return Value:
  4075. None.
  4076. --*/
  4077. {
  4078. ASSERT(pServiceInfo != NULL);
  4079. UINT nID16x16 = 0;
  4080. UINT nID32x32 = 0;
  4081. HINSTANCE hMod = NULL;
  4082. if (pServiceInfo->InitializedOK())
  4083. {
  4084. switch(bmpt)
  4085. {
  4086. case BMT_BUTTON:
  4087. nID16x16 = pServiceInfo->QueryButtonBitmapID();
  4088. nID32x32 = 0;
  4089. rgbMask = pServiceInfo->QueryButtonBkMask();
  4090. break;
  4091. case BMT_SERVICE:
  4092. nID16x16 = pServiceInfo->QueryServiceBitmapID();
  4093. nID32x32 = pServiceInfo->QueryLargeServiceBitmapID();
  4094. rgbMask = pServiceInfo->QueryServiceBkMask();
  4095. break;
  4096. case BMT_VROOT:
  4097. ASSERT(pServiceInfo->SupportsChildren());
  4098. nID16x16 = pServiceInfo->QueryChildBitmapID();
  4099. nID32x32 = pServiceInfo->QueryLargeChildBitmapID();
  4100. rgbMask = pServiceInfo->QueryChildBkMask();
  4101. break;
  4102. }
  4103. if (nID16x16 != 0)
  4104. {
  4105. hMod = pServiceInfo->QueryInstanceHandle();
  4106. }
  4107. else
  4108. {
  4109. //
  4110. // No bitmap provided by the service DLL, provide one from our
  4111. // own resource segment.
  4112. //
  4113. nID16x16 = IDB_UNKNOWN;
  4114. nID32x32 = 0;
  4115. hMod = ::AfxGetResourceHandle();
  4116. rgbMask = TB_COLORMASK;
  4117. }
  4118. }
  4119. else
  4120. {
  4121. //
  4122. // Add a disabled dummy button for a service
  4123. // that didn't load.
  4124. //
  4125. nID16x16 = IDB_NOTLOADED;
  4126. nID32x32 = 0;
  4127. hMod = ::AfxGetResourceHandle();
  4128. rgbMask = TB_COLORMASK;
  4129. }
  4130. if (nID16x16 == 0)
  4131. {
  4132. return FALSE;
  4133. }
  4134. pbmp16x16 = new CBitmap;
  4135. pbmp32x32 = new CBitmap;
  4136. if (pbmp16x16 == NULL || pbmp32x32 == NULL)
  4137. {
  4138. return FALSE;
  4139. }
  4140. HINSTANCE hOld = ::AfxGetResourceHandle();
  4141. ::AfxSetResourceHandle(hMod);
  4142. if (nID32x32 != 0)
  4143. {
  4144. //
  4145. // Have explicit large and small images
  4146. //
  4147. VERIFY(pbmp16x16->LoadBitmap(nID16x16));
  4148. VERIFY(pbmp32x32->LoadBitmap(nID32x32));
  4149. //
  4150. // Check to make sure they're the right size
  4151. //
  4152. if (!VerifyBitmapSize((HBITMAP)*pbmp16x16, 16, 16) ||
  4153. !VerifyBitmapSize((HBITMAP)*pbmp32x32, 32, 32))
  4154. {
  4155. ASSERT(FALSE);
  4156. TRACEEOLID("Bogus bitmap size provided by service bitmap");
  4157. //
  4158. // Synthesize based on small image.
  4159. //
  4160. delete pbmp32x32;
  4161. CBitmap * pTmp = pbmp16x16;
  4162. ConvertBitmapFormats(*pTmp, *pbmp16x16, *pbmp32x32);
  4163. delete pTmp;
  4164. }
  4165. }
  4166. else
  4167. {
  4168. //
  4169. // Only have one image. Synthesize small and large from this
  4170. // image.
  4171. //
  4172. CBitmap bmp;
  4173. VERIFY(bmp.LoadBitmap(nID16x16));
  4174. //
  4175. // Convert to 16x16 and 32x32 image
  4176. //
  4177. ConvertBitmapFormats(bmp, *pbmp16x16, *pbmp32x32);
  4178. }
  4179. ::AfxSetResourceHandle(hOld);
  4180. return TRUE;
  4181. }
  4182. void
  4183. CComponentDataImpl::GetToolMenu()
  4184. /*++
  4185. Routine Description:
  4186. Load the add-on tools
  4187. Arguments:
  4188. None.
  4189. Return Value:
  4190. None.
  4191. --*/
  4192. {
  4193. CString strValueName;
  4194. DWORD dwValueType;
  4195. int cTools = 0;
  4196. CRMCRegKey rkMachine(REG_KEY, SZ_ADDONTOOLS, KEY_READ);
  4197. if (!rkMachine.Ok())
  4198. {
  4199. //
  4200. // No registry entry
  4201. //
  4202. return;
  4203. }
  4204. CRMCRegValueIter rvi(rkMachine);
  4205. static BOOL fInitialised = FALSE;
  4206. if (fInitialised)
  4207. {
  4208. TRACEEOLID("Toolbar already initialised");
  4209. return;
  4210. }
  4211. try
  4212. {
  4213. int nButton = IDM_TOOLBAR;
  4214. while (rvi.Next(&strValueName, &dwValueType) == ERROR_SUCCESS)
  4215. {
  4216. CString strValue;
  4217. BOOL fExpanded;
  4218. rkMachine.QueryValue(
  4219. strValueName,
  4220. strValue,
  4221. EXPANSION_ON,
  4222. &fExpanded
  4223. );
  4224. TRACEEOLID("Adding tool: " << strValueName);
  4225. TRACEEOLID("From Path: " << strValue);
  4226. TRACEEOLID("Expansion: " << fExpanded);
  4227. CISMShellExecutable * pNewAddOnTool = new CISMShellExecutable(
  4228. strValue,
  4229. nButton - 1,
  4230. nButton
  4231. );
  4232. if (!pNewAddOnTool->HasBitmap())
  4233. {
  4234. TRACEEOLID("Tossing useless toolbar item");
  4235. delete pNewAddOnTool;
  4236. continue;
  4237. }
  4238. g_oblAddOnTools.AddTail(pNewAddOnTool);
  4239. ++nButton;
  4240. }
  4241. }
  4242. catch(CException * e)
  4243. {
  4244. TRACEEOLID("!!!exception building tool menu");
  4245. e->ReportError();
  4246. e->Delete();
  4247. }
  4248. fInitialised = TRUE;
  4249. }
  4250. void
  4251. CComponentDataImpl::MatchupSuperDLLs()
  4252. /*++
  4253. Routine Description:
  4254. Match up all dlls with superceed dlls
  4255. Arguments:
  4256. None
  4257. Return Value:
  4258. None
  4259. --*/
  4260. {
  4261. POSITION pos = m_oblServices.GetHeadPosition();
  4262. while(pos)
  4263. {
  4264. CServiceInfo * pService = (CServiceInfo *)m_oblServices.GetNext(pos);
  4265. ASSERT(pService != NULL);
  4266. if (pService->RequiresSuperDll())
  4267. {
  4268. //
  4269. // Match up the super DLL
  4270. //
  4271. POSITION pos2 = m_oblServices.GetHeadPosition();
  4272. while (pos2)
  4273. {
  4274. CServiceInfo * pService2 =
  4275. (CServiceInfo *)m_oblServices.GetNext(pos2);
  4276. if (pService2->IsSuperDllFor(pService))
  4277. {
  4278. pService->AssignSuperDll(pService2);
  4279. break;
  4280. }
  4281. }
  4282. ASSERT(pService->HasSuperDll());
  4283. }
  4284. }
  4285. }
  4286. void
  4287. CComponentDataImpl::GetServicesDLL()
  4288. /*++
  4289. Routine Description:
  4290. Load the add-on services.
  4291. Arguments:
  4292. None
  4293. Return Value:
  4294. None
  4295. --*/
  4296. {
  4297. int cServices = 0;
  4298. HRESULT hr = S_OK;
  4299. LPIMAGELIST lpScopeImage = NULL;
  4300. LPIMAGELIST lpResultImage = NULL;
  4301. ASSERT(m_pConsole);
  4302. hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
  4303. ASSERT(SUCCEEDED(hr));
  4304. hr = m_pConsole->QueryResultImageList(&lpResultImage);
  4305. ASSERT(SUCCEEDED(hr));
  4306. //
  4307. // Run through the list of installed services,
  4308. // load its associated cfg dll, and build up
  4309. // a discovery mask for each service.
  4310. //
  4311. CString strValueName;
  4312. DWORD dwValueType;
  4313. CRMCRegKey rkMachine(REG_KEY, SZ_ADDONSERVICES, KEY_READ);
  4314. if (rkMachine.Ok())
  4315. {
  4316. CRMCRegValueIter rvi(rkMachine);
  4317. CIISMachine::AttachNewInstanceCmds(&m_oblNewInstanceCmds);
  4318. try
  4319. {
  4320. //
  4321. // Now load the services
  4322. //
  4323. // AFX_MANAGE_STATE required to load service bitmaps
  4324. // from the dlls
  4325. //
  4326. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  4327. int nBmpIndex = BMP_SERVICE;
  4328. while (rvi.Next(&strValueName, &dwValueType) == ERROR_SUCCESS)
  4329. {
  4330. //
  4331. // Expand environment variables in path if present.
  4332. //
  4333. CString strValue;
  4334. BOOL fExpanded;
  4335. rkMachine.QueryValue(
  4336. strValueName,
  4337. strValue,
  4338. EXPANSION_ON,
  4339. &fExpanded
  4340. );
  4341. CServiceInfo * pServiceInfo = NULL;
  4342. {
  4343. CWaitCursor wait;
  4344. TRACEEOLID("Adding service DLL: " << strValue);
  4345. pServiceInfo = new CServiceInfo(cServices, strValue);
  4346. }
  4347. CError err(pServiceInfo->QueryReturnCode());
  4348. if (err.Failed())
  4349. {
  4350. if (err.Win32Error() == ERROR_INVALID_PARAMETER)
  4351. {
  4352. //
  4353. // The ERROR_INVALID_PARAMETER error return code
  4354. // gets sent when the info buffer provided is too
  4355. // small for the configuration DLL
  4356. //
  4357. ::AfxMessageBox(
  4358. IDS_VERSION_INCOMPATIBLE,
  4359. MB_OK | MB_ICONEXCLAMATION
  4360. );
  4361. }
  4362. else
  4363. {
  4364. err.MessageBoxFormat(
  4365. IDS_ERR_NO_LOAD,
  4366. MB_OK | MB_ICONEXCLAMATION,
  4367. NO_HELP_CONTEXT,
  4368. (LPCTSTR)pServiceInfo->QueryDllName()
  4369. );
  4370. }
  4371. //
  4372. // Don't add it to the list
  4373. //
  4374. delete pServiceInfo;
  4375. continue;
  4376. }
  4377. AddServiceToList(pServiceInfo);
  4378. //
  4379. // If this service use inetsloc discovery,
  4380. // add it to the mask.
  4381. //
  4382. if (pServiceInfo->UseInetSlocDiscover())
  4383. {
  4384. m_ullDiscoveryMask |= pServiceInfo->QueryDiscoveryMask();
  4385. }
  4386. //
  4387. // Add a bitmap representing the service
  4388. // to the image list
  4389. //
  4390. CBitmap * pbmp16x16 = NULL;
  4391. CBitmap * pbmp32x32 = NULL;
  4392. COLORREF rgbMask;
  4393. if (GetBitmapParms(
  4394. pServiceInfo,
  4395. BMT_SERVICE,
  4396. pbmp16x16,
  4397. pbmp32x32,
  4398. rgbMask
  4399. ))
  4400. {
  4401. g_obl16x16.AddTail(new CImage(pbmp16x16, rgbMask));
  4402. g_obl32x32.AddTail(new CImage(pbmp32x32, rgbMask));
  4403. pServiceInfo->SetBitmapIndex(nBmpIndex++);
  4404. }
  4405. //
  4406. // Add to the 'new instance' menu commands
  4407. //
  4408. if (pServiceInfo->SupportsInstances())
  4409. {
  4410. //
  4411. // Add to new instances menu object
  4412. //
  4413. m_oblNewInstanceCmds.AddTail(new CNewInstanceCmd(pServiceInfo));
  4414. }
  4415. if (pServiceInfo->SupportsChildren())
  4416. {
  4417. if (GetBitmapParms(
  4418. pServiceInfo,
  4419. BMT_VROOT,
  4420. pbmp16x16,
  4421. pbmp32x32,
  4422. rgbMask
  4423. ))
  4424. {
  4425. g_obl16x16.AddTail(new CImage(pbmp16x16, rgbMask));
  4426. g_obl32x32.AddTail(new CImage(pbmp32x32, rgbMask));
  4427. pServiceInfo->SetChildBitmapIndex(nBmpIndex++);
  4428. }
  4429. }
  4430. ++cServices;
  4431. }
  4432. MatchupSuperDLLs();
  4433. }
  4434. catch(CException * e)
  4435. {
  4436. TRACEEOLID("Exception loading library");
  4437. e->ReportError();
  4438. e->Delete();
  4439. }
  4440. }
  4441. if (cServices == 0)
  4442. {
  4443. //
  4444. // No services installed
  4445. //
  4446. CString str;
  4447. VERIFY(str.LoadString(IDS_NO_SERVICES_INSTALLED));
  4448. AfxMessageBox(str);
  4449. }
  4450. }
  4451. BOOL
  4452. CComponentDataImpl::RemoveServerFromCache(
  4453. IN LPCTSTR lpstrServer
  4454. )
  4455. /*++
  4456. Routine Description:
  4457. Remove machine from cache.
  4458. Arguments:
  4459. LPCTSTR lpstrServer : computer name to be removed from cache
  4460. Return Value:
  4461. None
  4462. --*/
  4463. {
  4464. CStringList & strList = GetCachedServers();
  4465. TRACEEOLID("Removing " << lpstrServer << " from cache");
  4466. POSITION posOld;
  4467. POSITION pos = strList.GetHeadPosition();
  4468. int nResult;
  4469. while(pos)
  4470. {
  4471. posOld = pos;
  4472. CString & str = strList.GetNext(pos);
  4473. nResult = str.CompareNoCase(lpstrServer);
  4474. if (nResult == 0)
  4475. {
  4476. strList.RemoveAt(posOld);
  4477. SetCacheDirty(TRUE);
  4478. return TRUE;
  4479. }
  4480. if (nResult > 0)
  4481. {
  4482. //
  4483. // We're not going to find it.
  4484. //
  4485. break;
  4486. }
  4487. }
  4488. //
  4489. // Didn't exist
  4490. //
  4491. ASSERT(FALSE && "Attempting to remove non-existent server from cache");
  4492. return FALSE;
  4493. }
  4494. void
  4495. CComponentDataImpl::AddServerToCache(
  4496. IN LPCTSTR lpstrServer,
  4497. IN BOOL fSetCacheDirty OPTIONAL
  4498. )
  4499. /*++
  4500. Routine Description:
  4501. Add machine name to the cache
  4502. Arguments:
  4503. LPCTSTR lpstrServer : computer name to be added to the cache.
  4504. BOOL fSetCacheDirty : TRUE to dirty the cache
  4505. Return Value:
  4506. None
  4507. --*/
  4508. {
  4509. CStringList & strList = GetCachedServers();
  4510. TRACEEOLID("Adding " << lpstrServer << " to cache");
  4511. CString strServer(lpstrServer);
  4512. POSITION posOld;
  4513. POSITION pos = strList.GetHeadPosition();
  4514. int nResult;
  4515. while(pos)
  4516. {
  4517. posOld = pos;
  4518. CString & str = strList.GetNext(pos);
  4519. nResult = str.CompareNoCase(strServer);
  4520. if (nResult == 0)
  4521. {
  4522. //
  4523. // Already existed in the case, ignore
  4524. //
  4525. return;
  4526. }
  4527. else if (nResult > 0)
  4528. {
  4529. //
  4530. // Found the proper place
  4531. //
  4532. strList.InsertBefore(posOld, strServer);
  4533. if (fSetCacheDirty)
  4534. {
  4535. SetCacheDirty();
  4536. }
  4537. return;
  4538. }
  4539. }
  4540. //
  4541. // Didn't exist yet, so add to list here
  4542. //
  4543. strList.AddTail(strServer);
  4544. if (fSetCacheDirty)
  4545. {
  4546. SetCacheDirty();
  4547. }
  4548. }
  4549. static BOOL
  4550. GetCommandLineServer(LPTSTR * pStr)
  4551. {
  4552. BOOL bRes = FALSE;
  4553. LPTSTR pCmdLine = GetCommandLine();
  4554. int n;
  4555. LPTSTR * pArgv = CommandLineToArgvW(pCmdLine, &n);
  4556. *pStr = NULL;
  4557. if (pArgv != NULL)
  4558. {
  4559. TCHAR szCmd[] = _T("/SERVER:");
  4560. int len = sizeof(szCmd) / sizeof(TCHAR) - 1;
  4561. for (int i = 0; i < n; i++)
  4562. {
  4563. if (CSTR_EQUAL == CompareString(LOCALE_SYSTEM_DEFAULT,
  4564. NORM_IGNORECASE, pArgv[i], len, szCmd, len))
  4565. {
  4566. LPTSTR p = pArgv[i] + len;
  4567. int count = 0;
  4568. while (*p != _T(' ') && *p != 0)
  4569. {
  4570. p++;
  4571. count++;
  4572. }
  4573. *pStr = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * (count + 1));
  4574. if (*pStr != NULL)
  4575. {
  4576. lstrcpyn(*pStr, pArgv[i] + len, count + 1);
  4577. bRes = TRUE;
  4578. }
  4579. break;
  4580. }
  4581. }
  4582. GlobalFree(pArgv);
  4583. }
  4584. return bRes;
  4585. }
  4586. void
  4587. CComponentDataImpl::AddCachedServersToView()
  4588. /*++
  4589. Routine Description:
  4590. Move the cached servers to the scope view.
  4591. Arguments:
  4592. None
  4593. Return Value:
  4594. None
  4595. --*/
  4596. {
  4597. CStringList & strlList = GetCachedServers();
  4598. BOOL bCmdLine = FALSE;
  4599. LPTSTR pCmdLine = NULL;
  4600. if (GetCommandLineServer(&pCmdLine))
  4601. {
  4602. bCmdLine = TRUE;
  4603. EmptyServerList();
  4604. AddServerToCache(pCmdLine, FALSE);
  4605. if (pCmdLine != NULL)
  4606. LocalFree(pCmdLine);
  4607. }
  4608. else if (strlList.IsEmpty())
  4609. {
  4610. //
  4611. // Nothing pre-selected or cached.
  4612. // Add the local machine.
  4613. //
  4614. CString str;
  4615. DWORD dwSize = MAX_SERVERNAME_LEN;
  4616. if (::GetComputerName(str.GetBuffer(dwSize + 1), &dwSize))
  4617. {
  4618. //
  4619. // Add local machine, though don't persist this later
  4620. //
  4621. str.ReleaseBuffer();
  4622. AddServerToCache(str, FALSE);
  4623. }
  4624. }
  4625. //
  4626. // Now add everything cached to the current
  4627. // view
  4628. //
  4629. CError err;
  4630. for(POSITION pos = strlList.GetHeadPosition(); pos != NULL; )
  4631. {
  4632. CString & strMachine = strlList.GetNext(pos);
  4633. int cServices;
  4634. err = AddServerToList(
  4635. FALSE,
  4636. bCmdLine ? TRUE : FALSE,
  4637. strMachine,
  4638. cServices,
  4639. m_oblServices
  4640. );
  4641. TRACEEOLID("adding " << strMachine << " to the view returned error code " << err);
  4642. if (err.Failed())
  4643. {
  4644. //
  4645. // Temporarily map RPC errors to friendlier error message
  4646. //
  4647. TEMP_ERROR_OVERRIDE(EPT_S_NOT_REGISTERED, IDS_ERR_RPC_NA);
  4648. TEMP_ERROR_OVERRIDE(RPC_S_SERVER_UNAVAILABLE, IDS_ERR_RPC_NA);
  4649. TEMP_ERROR_OVERRIDE(RPC_S_UNKNOWN_IF, IDS_ERR_INTERFACE);
  4650. TEMP_ERROR_OVERRIDE(RPC_S_PROCNUM_OUT_OF_RANGE, IDS_ERR_INTERFACE);
  4651. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  4652. //
  4653. // Give the option of removing from cache
  4654. //
  4655. if (err.MessageBoxFormat(
  4656. IDS_ERROR_CONNECTING_CACHE,
  4657. MB_YESNO | MB_DEFBUTTON1,
  4658. NO_HELP_CONTEXT,
  4659. (LPCTSTR)strMachine) != IDYES)
  4660. {
  4661. VERIFY(RemoveServerFromCache(strMachine));
  4662. }
  4663. }
  4664. else if (cServices == 0)
  4665. {
  4666. //
  4667. // No errors, but no services found
  4668. //
  4669. ::AfxMessageBox(IDS_NO_SERVICE);
  4670. }
  4671. }
  4672. }
  4673. CServiceInfo *
  4674. CComponentDataImpl::GetServiceAt(
  4675. IN int nIndex
  4676. )
  4677. /*++
  4678. Routine Description:
  4679. Get the service object at the given index.
  4680. Arguments:
  4681. int nIndex : Index where to look for the service info object
  4682. Return Value:
  4683. Service info pointer, or NULL if the index was not valid
  4684. --*/
  4685. {
  4686. if (nIndex < 0 || nIndex >= m_oblServices.GetCount())
  4687. {
  4688. TRACEEOLID("Invalid service index requested");
  4689. return NULL;
  4690. }
  4691. return (CServiceInfo *)m_oblServices.GetAt(m_oblServices.FindIndex(nIndex));
  4692. }
  4693. void
  4694. CComponentDataImpl::EmptyServerList()
  4695. /*++
  4696. Routine Description:
  4697. Empty server list
  4698. Arguments:
  4699. None
  4700. Return Value:
  4701. None
  4702. --*/
  4703. {
  4704. m_oblServers.RemoveAll();
  4705. m_cServers = m_cServicesRunning = 0;
  4706. }
  4707. DWORD
  4708. CComponentDataImpl::AddServerToList(
  4709. IN BOOL fCache,
  4710. IN LPINET_SERVER_INFO lpServerInfo,
  4711. IN OUT CObListPlus & oblServices
  4712. )
  4713. /*++
  4714. Routine Description:
  4715. Add a service object for each service discovered
  4716. to be belonging to this server.
  4717. Arguments:
  4718. BOOL fCache : TRUE to cache
  4719. LPINET_SERVER_INFO lpServerInfo : Discovery information (from inetsloc)
  4720. CObListPlus & oblServices : List of installed services
  4721. Return Value:
  4722. Error return code
  4723. --*/
  4724. {
  4725. TRACEEOLID("For Server " << lpServerInfo->ServerName);
  4726. CServerInfo * pServerInfo;
  4727. DWORD err = ERROR_SUCCESS;
  4728. for (DWORD j = 0; j < lpServerInfo->Services.NumServices; ++j)
  4729. {
  4730. LPINET_SERVICE_INFO lpServiceInfo = lpServerInfo->Services.Services[j];
  4731. try
  4732. {
  4733. //
  4734. // Attempt to create a server info block
  4735. //
  4736. pServerInfo = new CServerInfo(
  4737. lpServerInfo->ServerName,
  4738. lpServiceInfo,
  4739. oblServices
  4740. );
  4741. if (pServerInfo->IsConfigurable())
  4742. {
  4743. TRACEEOLID("Adding " << (DWORD)lpServiceInfo->ServiceMask);
  4744. if (!AddToList(fCache, pServerInfo))
  4745. {
  4746. TRACEEOLID("It already existed in the list");
  4747. delete pServerInfo;
  4748. }
  4749. }
  4750. else
  4751. {
  4752. //
  4753. // Toss it
  4754. //
  4755. TRACEEOLID("Tossing " << (DWORD)lpServiceInfo->ServiceMask);
  4756. delete pServerInfo;
  4757. }
  4758. }
  4759. catch(CMemoryException * e)
  4760. {
  4761. TRACEEOLID("AddServerList: memory exception");
  4762. err = ERROR_NOT_ENOUGH_MEMORY;
  4763. e->Delete();
  4764. }
  4765. }
  4766. return err;
  4767. }
  4768. DWORD
  4769. CComponentDataImpl::AddServerToList(
  4770. IN BOOL fCache,
  4771. IN BOOL fHandleErrors,
  4772. IN CString & strServerName,
  4773. OUT int & cServices,
  4774. IN OUT CObListPlus & oblServices
  4775. )
  4776. /*++
  4777. Routine Description:
  4778. Add a service object for each service running
  4779. on the machine listed above.
  4780. Arguments:
  4781. BOOL fCache : TRUE to cache the server
  4782. BOOL fHandleErrors : TRUE to display error messages, FALSE to abort
  4783. on error
  4784. CString & strServerName : Name of this server
  4785. int & cServices : # Services added
  4786. CObListPlus & oblServices : List of installed services
  4787. Return Value:
  4788. Error return code
  4789. --*/
  4790. {
  4791. TEMP_ERROR_OVERRIDE(EPT_S_NOT_REGISTERED, IDS_ERR_RPC_NA);
  4792. TEMP_ERROR_OVERRIDE(RPC_S_SERVER_UNAVAILABLE, IDS_ERR_RPC_NA);
  4793. TEMP_ERROR_OVERRIDE(RPC_S_UNKNOWN_IF, IDS_ERR_INTERFACE);
  4794. TEMP_ERROR_OVERRIDE(RPC_S_PROCNUM_OUT_OF_RANGE, IDS_ERR_INTERFACE);
  4795. //
  4796. // Loop through the services, and find out which ones
  4797. // are installed on the target machine, if any.
  4798. //
  4799. CObListIter obli(oblServices);
  4800. CServiceInfo * psi;
  4801. cServices = 0;
  4802. CError err;
  4803. ISMSERVERINFO ServerInfo;
  4804. CServerInfo::CleanServerName(strServerName);
  4805. //
  4806. // See if we can make contact with the machine
  4807. //
  4808. if (!DoesServerExist(strServerName))
  4809. {
  4810. //
  4811. // No, quit right here
  4812. //
  4813. err = RPC_S_SERVER_UNAVAILABLE;
  4814. if (fHandleErrors)
  4815. {
  4816. err.MessageBox();
  4817. }
  4818. return err.Win32Error();
  4819. }
  4820. while (psi = (CServiceInfo *)obli.Next())
  4821. {
  4822. int cErrors = 0;
  4823. if (psi->InitializedOK())
  4824. {
  4825. TRACEEOLID("Trying: " << psi->GetShortName());
  4826. ServerInfo.dwSize = sizeof(ServerInfo);
  4827. {
  4828. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  4829. CWaitCursor wait;
  4830. err = psi->ISMQueryServerInfo(
  4831. strServerName,
  4832. &ServerInfo
  4833. );
  4834. }
  4835. if (err.Win32Error() == ERROR_SERVICE_DOES_NOT_EXIST)
  4836. {
  4837. TRACEEOLID("Service not installed -- acceptable response");
  4838. err.Reset();
  4839. }
  4840. else if (err.Win32Error() == ERROR_SERVICE_START_HANG)
  4841. {
  4842. TRACEEOLID("Service is hanging -- ignore silently");
  4843. err.Reset();
  4844. }
  4845. else if (err.Succeeded())
  4846. {
  4847. //
  4848. // Yes, this service is running on this
  4849. // machine.
  4850. //
  4851. ++cServices;
  4852. //
  4853. // Add to list
  4854. //
  4855. try
  4856. {
  4857. CServerInfo * pNewServer = new CServerInfo(
  4858. strServerName,
  4859. &ServerInfo,
  4860. psi
  4861. );
  4862. if (!AddToList(fCache, pNewServer, TRUE))
  4863. {
  4864. TRACEEOLID("It already existed in the list");
  4865. delete pNewServer;
  4866. }
  4867. }
  4868. catch(CMemoryException * e)
  4869. {
  4870. TRACEEOLID("AddServerList: memory exception");
  4871. err = ERROR_NOT_ENOUGH_MEMORY;
  4872. e->Delete();
  4873. }
  4874. }
  4875. if (err.Failed())
  4876. {
  4877. if (!fHandleErrors)
  4878. {
  4879. //
  4880. // Let the calling process handle the errors,
  4881. // we're stopping.
  4882. //
  4883. break;
  4884. }
  4885. ++cErrors;
  4886. //
  4887. // Display error about the service
  4888. //
  4889. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  4890. err.MessageBoxFormat(
  4891. IDS_ERR_ENUMERATE_SVC,
  4892. MB_OK,
  4893. NO_HELP_CONTEXT,
  4894. (LPCTSTR)psi->GetShortName(),
  4895. (LPCTSTR)strServerName
  4896. );
  4897. //
  4898. // Optionally cancel here on no response.
  4899. //
  4900. //break;
  4901. }
  4902. }
  4903. }
  4904. return err.Win32Error();
  4905. }
  4906. DWORD
  4907. CComponentDataImpl::RemoveServerFromList(
  4908. IN BOOL fCache,
  4909. IN CString & strServerName
  4910. )
  4911. /*++
  4912. Routine Description:
  4913. Remove each service in the list belonging to the given computer name.
  4914. Arguments:
  4915. CString & strServerName : Name of this server
  4916. Return Value:
  4917. Error return code
  4918. --*/
  4919. {
  4920. CServerInfo::CleanServerName(strServerName);
  4921. CServerInfo * pEntry;
  4922. POSITION pos1, pos2;
  4923. pos1 = m_oblServers.GetHeadPosition();
  4924. while(pos1)
  4925. {
  4926. pos2 = pos1;
  4927. pEntry = (CServerInfo *)m_oblServers.GetNext(pos1);
  4928. if (pEntry->MatchServerName(strServerName))
  4929. {
  4930. m_oblServers.RemoveAt(pos2);
  4931. }
  4932. }
  4933. if (fCache)
  4934. {
  4935. RemoveServerFromCache(strServerName);
  4936. }
  4937. return ERROR_SUCCESS;
  4938. }
  4939. void
  4940. CComponentDataImpl::Refresh()
  4941. /*++
  4942. Routine Description:
  4943. Refresh the server list
  4944. Arguments:
  4945. None
  4946. Return Value:
  4947. None
  4948. --*/
  4949. {
  4950. //
  4951. // AFX_MANAGE_STATE required for wait cursor
  4952. //
  4953. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  4954. POSITION pos;
  4955. CWaitCursor wait;
  4956. CServerInfo * pEntry;
  4957. for(pos = m_oblServers.GetHeadPosition(); pos != NULL; /**/ )
  4958. {
  4959. pEntry = (CServerInfo *)m_oblServers.GetNext(pos);
  4960. int oldState = pEntry->QueryServiceState();
  4961. if (pEntry->Refresh() == ERROR_SUCCESS)
  4962. {
  4963. if (oldState != pEntry->QueryServiceState())
  4964. {
  4965. //
  4966. // Take away this service from the total
  4967. // running count if it was part of it
  4968. // before, and (re-) add it if it's currently
  4969. // running.
  4970. //
  4971. if (oldState == INetServiceRunning)
  4972. {
  4973. --m_cServicesRunning;
  4974. }
  4975. if (pEntry->IsServiceRunning())
  4976. {
  4977. ++m_cServicesRunning;
  4978. }
  4979. }
  4980. //UpdateAllViews(NULL, HINT_REFRESHITEM, pEntry);
  4981. }
  4982. }
  4983. }
  4984. BOOL
  4985. CComponentDataImpl::AddToList(
  4986. IN BOOL fCache,
  4987. IN CServerInfo * pServerInfo,
  4988. IN BOOL fSelect
  4989. )
  4990. /*++
  4991. Routine Description:
  4992. Add the service to the list if it didn't exist already,
  4993. otherwise refresh the info if it did exist. Return
  4994. TRUE if the service was added, FALSE, if already
  4995. existed and was refreshed.
  4996. Arguments:
  4997. CServerInfo * pServerInfo : Server to add
  4998. BOOL fSelect : If TRUE, select the newly added item
  4999. Return Value:
  5000. TRUE if added, FALSE otherwise
  5001. --*/
  5002. {
  5003. POSITION pos;
  5004. BOOL fFoundService = FALSE;
  5005. BOOL fFoundServer = FALSE;
  5006. BOOL fServiceAdded = FALSE;
  5007. //int nAddHint = fSelect ? HINT_ADDITEM_SELECT : HINT_ADDITEM;
  5008. CServerInfo * pEntry;
  5009. for( pos = m_oblServers.GetHeadPosition();
  5010. pos != NULL;
  5011. m_oblServers.GetNext(pos)
  5012. )
  5013. {
  5014. pEntry = (CServerInfo *)m_oblServers.GetAt(pos);
  5015. if (pEntry->CompareByServer(pServerInfo) == 0)
  5016. {
  5017. fFoundServer = TRUE;
  5018. //
  5019. // Found the server, also the service?
  5020. //
  5021. if (pEntry->CompareByService(pServerInfo) == 0)
  5022. {
  5023. //
  5024. // Yes, the service was found also -- update the information
  5025. // if the service state has changed.
  5026. //
  5027. TRACEEOLID("Entry Already Existed");
  5028. fFoundService = TRUE;
  5029. if (pEntry->QueryServiceState()
  5030. != pServerInfo->QueryServiceState())
  5031. {
  5032. TRACEEOLID("Service State has changed -- refreshing");
  5033. //
  5034. // Decrement the running counter if this service
  5035. // was part of that counter. The counter will be
  5036. // re-added if the service is still running
  5037. //
  5038. if (pEntry->IsServiceRunning())
  5039. {
  5040. --m_cServicesRunning;
  5041. }
  5042. *pEntry = *pServerInfo;
  5043. if (pEntry->IsServiceRunning())
  5044. {
  5045. ++m_cServicesRunning;
  5046. }
  5047. //UpdateAllViews(NULL, HINT_REFRESHITEM, pEntry);
  5048. }
  5049. break;
  5050. }
  5051. }
  5052. else
  5053. {
  5054. if (fFoundServer)
  5055. {
  5056. //
  5057. // Server name no longer matches, but did match
  5058. // the last time, so we didn't find the service.
  5059. // Insert it at the end of the services belonging
  5060. // to this guy.
  5061. //
  5062. TRACEEOLID("Found new service belonging to known server");
  5063. m_oblServers.InsertBefore(pos, pServerInfo);
  5064. fServiceAdded = TRUE; // Don't add again.
  5065. if (pServerInfo->IsServiceRunning())
  5066. {
  5067. ++m_cServicesRunning;
  5068. }
  5069. //UpdateAllViews(NULL, nAddHint, pServerInfo);
  5070. break;
  5071. }
  5072. }
  5073. }
  5074. if (!fFoundService && !fServiceAdded)
  5075. {
  5076. //
  5077. // Came to the end of the list without
  5078. // finding the service -- add a new one
  5079. // at the end.
  5080. //
  5081. TRACEEOLID("Adding new entry to tail");
  5082. m_oblServers.AddTail(pServerInfo);
  5083. if (pServerInfo->IsServiceRunning())
  5084. {
  5085. ++m_cServicesRunning;
  5086. }
  5087. if (!fFoundServer)
  5088. {
  5089. ++m_cServers;
  5090. if (fCache)
  5091. {
  5092. AddServerToCache(pServerInfo->QueryServerName(), TRUE);
  5093. }
  5094. }
  5095. if (fCache && GetRootHandle() != NULL)
  5096. {
  5097. //
  5098. // View has already been expanded -- add it here.
  5099. //
  5100. if (pServerInfo->IsServiceSelected())
  5101. {
  5102. AddServerInfoParent(GetRootHandle(), pServerInfo);
  5103. }
  5104. }
  5105. }
  5106. return !fFoundService;
  5107. }
  5108. static HRESULT
  5109. GetSnapinHelpFile(LPOLESTR * lpCompiledHelpFile)
  5110. {
  5111. if (lpCompiledHelpFile == NULL)
  5112. return E_INVALIDARG;
  5113. CString strFilePath, strWindowsPath, strBuffer;
  5114. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  5115. // Use system API to get windows directory.
  5116. UINT uiResult = GetWindowsDirectory(strWindowsPath.GetBuffer(MAX_PATH),
  5117. MAX_PATH);
  5118. strWindowsPath.ReleaseBuffer();
  5119. if (uiResult <= 0 || uiResult > MAX_PATH)
  5120. {
  5121. return E_FAIL;
  5122. }
  5123. if (!strFilePath.LoadString(IDS_HELPFILE))
  5124. {
  5125. return E_FAIL;
  5126. }
  5127. strBuffer = strWindowsPath;
  5128. strBuffer += _T('\\');
  5129. strBuffer += strFilePath;
  5130. *lpCompiledHelpFile
  5131. = reinterpret_cast<LPOLESTR>(CoTaskMemAlloc((strBuffer.GetLength() + 1)
  5132. * sizeof(_TCHAR)));
  5133. if (*lpCompiledHelpFile == NULL)
  5134. return E_OUTOFMEMORY;
  5135. USES_CONVERSION;
  5136. _tcscpy(*lpCompiledHelpFile, T2OLE((LPTSTR)(LPCTSTR)strBuffer));
  5137. return S_OK;
  5138. }
  5139. STDMETHODIMP
  5140. CComponentDataImpl::GetHelpTopic(LPOLESTR *lpCompiledHelpFile)
  5141. {
  5142. return GetSnapinHelpFile(lpCompiledHelpFile);
  5143. }
  5144. //
  5145. // About implementation
  5146. //
  5147. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  5148. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapinAboutImpl);
  5149. CSnapinAboutImpl::CSnapinAboutImpl()
  5150. /*++
  5151. Routine Description:
  5152. Constructor
  5153. Arguments:
  5154. None
  5155. Return Value:
  5156. N/A
  5157. --*/
  5158. {
  5159. }
  5160. CSnapinAboutImpl::~CSnapinAboutImpl()
  5161. /*++
  5162. Routine Description:
  5163. Destructor
  5164. Arguments:
  5165. N/A
  5166. Return Value:
  5167. N/A
  5168. --*/
  5169. {
  5170. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapinAboutImpl);
  5171. }
  5172. HRESULT
  5173. CSnapinAboutImpl::AboutHelper(
  5174. IN UINT nID,
  5175. OUT LPOLESTR * lpPtr
  5176. )
  5177. /*++
  5178. Routine Description:
  5179. "About" helper function
  5180. Arguments:
  5181. UINT nID : String resource ID
  5182. LPOLESTR * lpPtr : Return buffer for the string
  5183. Return Value:
  5184. HRESULT
  5185. --*/
  5186. {
  5187. if (lpPtr == NULL)
  5188. {
  5189. return E_POINTER;
  5190. }
  5191. CString s;
  5192. VERIFY(::LoadString(
  5193. _Module.GetModuleInstance(),
  5194. nID,
  5195. s.GetBuffer(255),
  5196. 255));
  5197. s.ReleaseBuffer();
  5198. *lpPtr = (LPOLESTR)CoTaskMemAlloc((s.GetLength() + 1) * sizeof(wchar_t));
  5199. if (*lpPtr == NULL)
  5200. {
  5201. return E_OUTOFMEMORY;
  5202. }
  5203. lstrcpy(*lpPtr, (LPCTSTR)s);
  5204. return S_OK;
  5205. }
  5206. STDMETHODIMP
  5207. CSnapinAboutImpl::GetSnapinDescription(
  5208. OUT LPOLESTR * lpDescription
  5209. )
  5210. /*++
  5211. Routine Description:
  5212. Get the snapin description
  5213. Arguments:
  5214. LPOLESTR * lpDescription : String return buffer
  5215. Return Value:
  5216. HRESULT
  5217. --*/
  5218. {
  5219. return AboutHelper(IDS_SNAPIN_DESC, lpDescription);
  5220. }
  5221. STDMETHODIMP
  5222. CSnapinAboutImpl::GetProvider(
  5223. OUT LPOLESTR * lpName
  5224. )
  5225. /*++
  5226. Routine Description:
  5227. Get the snapin provider string
  5228. Arguments:
  5229. LPOLESTR * lpName : String return buffer
  5230. Return Value:
  5231. HRESULT
  5232. --*/
  5233. {
  5234. return AboutHelper(IDS_COMPANY, lpName);
  5235. }
  5236. STDMETHODIMP
  5237. CSnapinAboutImpl::GetSnapinVersion(
  5238. IN LPOLESTR * lpVersion
  5239. )
  5240. /*++
  5241. Routine Description:
  5242. Get the snapin version string:
  5243. Arguments:
  5244. LPOLESTR * lpVersion : Version string
  5245. Return Value:
  5246. HRESULT
  5247. --*/
  5248. {
  5249. return AboutHelper(IDS_VERSION, lpVersion);
  5250. }
  5251. STDMETHODIMP
  5252. CSnapinAboutImpl::GetSnapinImage(
  5253. IN HICON * hAppIcon
  5254. )
  5255. /*++
  5256. Routine Description:
  5257. Get the icon for this snapin
  5258. Arguments:
  5259. HICON * hAppIcon : Return handle to the icon
  5260. Return Value:
  5261. HRESULT
  5262. --*/
  5263. {
  5264. if (hAppIcon == NULL)
  5265. {
  5266. return E_POINTER;
  5267. }
  5268. *hAppIcon = LoadIcon(
  5269. _Module.GetModuleInstance(),
  5270. MAKEINTRESOURCE(IDI_ICON));
  5271. ASSERT(*hAppIcon != NULL);
  5272. return (*hAppIcon != NULL) ? S_OK : E_FAIL;
  5273. }
  5274. STDMETHODIMP
  5275. CSnapinAboutImpl::GetStaticFolderImage(
  5276. OUT HBITMAP * phSmallImage,
  5277. OUT HBITMAP * phSmallImageOpen,
  5278. OUT HBITMAP * phLargeImage,
  5279. OUT COLORREF * prgbMask
  5280. )
  5281. /*++
  5282. Routine Description:
  5283. Get the static folder image
  5284. Arguments:
  5285. HBITMAP * phSmallImage : Small folder
  5286. HBITMAP * phSmallImageOpen : Small open folder
  5287. HBITMAP * phLargeImage : Large image
  5288. COLORREF * prgbMask : Mask
  5289. Return Value:
  5290. HRESULT
  5291. --*/
  5292. {
  5293. if (!phSmallImage || !phSmallImageOpen || !phLargeImage || !prgbMask)
  5294. {
  5295. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  5296. }
  5297. *phSmallImage = (HBITMAP)LoadImage(
  5298. _Module.GetModuleInstance(),
  5299. MAKEINTRESOURCE(IDB_INETMGR16),
  5300. IMAGE_BITMAP,
  5301. 0,
  5302. 0,
  5303. LR_DEFAULTCOLOR
  5304. );
  5305. *phSmallImageOpen = (HBITMAP)LoadImage(
  5306. _Module.GetModuleInstance(),
  5307. MAKEINTRESOURCE(IDB_INETMGR16),
  5308. IMAGE_BITMAP,
  5309. 0,
  5310. 0,
  5311. LR_DEFAULTCOLOR
  5312. );
  5313. *phLargeImage = (HBITMAP)LoadImage(
  5314. _Module.GetModuleInstance(),
  5315. MAKEINTRESOURCE(IDB_INETMGR32),
  5316. IMAGE_BITMAP,
  5317. 0,
  5318. 0,
  5319. LR_DEFAULTCOLOR
  5320. );
  5321. *prgbMask = RGB_BK_IMAGES;
  5322. return *phSmallImage && *phLargeImage ? S_OK : E_FAIL;
  5323. }