Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1746 lines
34 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. inetmgr.cpp
  5. Abstract:
  6. Main MMC snap-in code
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. #include "stdafx.h"
  14. #include "common.h"
  15. #include "InetMgrApp.h"
  16. #include "iisobj.h"
  17. #include "toolbar.h"
  18. #include "util.h"
  19. #include "tracker.h"
  20. #include "guids.h"
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char BASED_CODE THIS_FILE[] = __FILE__;
  24. #endif
  25. #define new DEBUG_NEW
  26. //const GUID * CCompMgrExtData::m_NODETYPE = &cCompMgmtService;
  27. //const OLECHAR * CCompMgrExtData::m_SZNODETYPE = OLESTR("476e6446-aaff-11d0-b944-00c04fd8d5b0");
  28. //const OLECHAR * CCompMgrExtData::m_SZDISPLAY_NAME = OLESTR("CMSnapin");
  29. //const CLSID * CCompMgrExtData::m_SNAPIN_CLASSID = &CLSID_InetMgr;
  30. extern CInetmgrApp theApp;
  31. extern CPropertySheetTracker g_OpenPropertySheetTracker;
  32. extern CWNetConnectionTrackerGlobal g_GlobalConnections;
  33. #if defined(_DEBUG) || DBG
  34. extern CDebug_IISObject g_Debug_IISObject;
  35. #endif
  36. int g_IISMMCComLoaded = 0;
  37. int g_IISMMCInstanceCount = 0;
  38. int g_IISMMCInstanceCountExtensionMode = 0;
  39. HRESULT
  40. GetHelpTopic(LPOLESTR *lpCompiledHelpFile)
  41. {
  42. if (lpCompiledHelpFile == NULL)
  43. return E_INVALIDARG;
  44. CString strFilePath, strWindowsPath, strBuffer;
  45. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  46. // Use system API to get windows directory.
  47. UINT uiResult = GetWindowsDirectory(strWindowsPath.GetBuffer(MAX_PATH), MAX_PATH);
  48. strWindowsPath.ReleaseBuffer();
  49. if (uiResult <= 0 || uiResult > MAX_PATH)
  50. {
  51. return E_FAIL;
  52. }
  53. if (!strFilePath.LoadString(IDS_HELPFILE))
  54. {
  55. return E_FAIL;
  56. }
  57. strBuffer = strWindowsPath;
  58. strBuffer += _T('\\');
  59. strBuffer += strFilePath;
  60. *lpCompiledHelpFile
  61. = reinterpret_cast<LPOLESTR>(CoTaskMemAlloc((strBuffer.GetLength() + 1)
  62. * sizeof(_TCHAR)));
  63. if (*lpCompiledHelpFile == NULL)
  64. return E_OUTOFMEMORY;
  65. USES_CONVERSION;
  66. _tcscpy(*lpCompiledHelpFile, T2OLE((LPTSTR)(LPCTSTR)strBuffer));
  67. return S_OK;
  68. }
  69. //
  70. // CInetMgrComponent Implementation
  71. //
  72. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  73. CInetMgrComponent::CInetMgrComponent()
  74. /*++
  75. Routine Description:
  76. Constructor
  77. Arguments:
  78. None
  79. Return Value:
  80. N/A
  81. --*/
  82. {
  83. _lpControlBar = NULL;
  84. _lpToolBar = NULL;
  85. g_IISMMCInstanceCount++;
  86. TRACEEOLID("CInetMgrComponent::CInetMgrComponent:g_IISMMCInstanceCount=" << g_IISMMCInstanceCount);
  87. }
  88. CInetMgrComponent::~CInetMgrComponent()
  89. {
  90. TRACEEOLID("CInetMgrComponent::~CInetMgrComponent:g_IISMMCInstanceCount=" << g_IISMMCInstanceCount);
  91. }
  92. HRESULT
  93. CInetMgrComponent::Destroy(LONG cookie)
  94. {
  95. g_IISMMCInstanceCount--;
  96. TRACEEOLID("CInetMgrComponent::Destroy:g_IISMMCInstanceCount=" << g_IISMMCInstanceCount);
  97. return S_OK;
  98. }
  99. HRESULT
  100. CInetMgrComponent::Notify(
  101. IN LPDATAOBJECT lpDataObject,
  102. IN MMC_NOTIFY_TYPE event,
  103. IN LPARAM arg,
  104. IN LPARAM param
  105. )
  106. /*++
  107. Routine Description:
  108. Notification handler.
  109. Arguments:
  110. LPDATAOBJECT lpDataObject : Data object
  111. MMC_NOTIFY_TYPE event : Notification event
  112. long arg : Event specific argument
  113. long param : Event specific parameter
  114. Return Value:
  115. HRESULT
  116. --*/
  117. {
  118. HRESULT hr = E_NOTIMPL;
  119. if (lpDataObject == NULL)
  120. {
  121. switch (event)
  122. {
  123. case MMCN_PROPERTY_CHANGE:
  124. {
  125. TRACEEOLID("CInetMgrComponent::Notify:MMCN_PROPERTY_CHANGE");
  126. hr = S_OK;
  127. if (m_spConsole != NULL)
  128. {
  129. CSnapInItem * pNode = (CSnapInItem *)param;
  130. LPDATAOBJECT pDataObject = NULL;
  131. if (pNode)
  132. {
  133. if (IsValidAddress( (const void*) pNode,sizeof(void*),FALSE))
  134. {
  135. pNode->GetDataObject(&pDataObject, CCT_SCOPE);
  136. }
  137. }
  138. hr = m_spConsole->UpdateAllViews(pDataObject, param, 0);
  139. }
  140. }
  141. break;
  142. case MMCN_SNAPINHELP:
  143. break;
  144. default:
  145. break;
  146. }
  147. }
  148. else if (lpDataObject != DOBJ_CUSTOMWEB && lpDataObject != DOBJ_CUSTOMOCX)
  149. {
  150. //
  151. // Pass it on to IComponentImpl
  152. //
  153. hr = IComponentImpl<CInetMgrComponent>::Notify(lpDataObject, event, arg, param);
  154. }
  155. else
  156. {
  157. hr = S_OK;
  158. }
  159. return hr;
  160. }
  161. HRESULT
  162. CInetMgrComponent::GetProperty(
  163. LPDATAOBJECT pDataObject,
  164. BSTR szPropertyName,
  165. BSTR* pbstrProperty)
  166. {
  167. HRESULT hr = S_OK;
  168. CSnapInItem * pItem = NULL;
  169. DATA_OBJECT_TYPES type;
  170. IDataObject * p = (IDataObject *)pDataObject;
  171. if (p == DOBJ_CUSTOMWEB || p == DOBJ_CUSTOMOCX)
  172. {
  173. return S_OK;
  174. }
  175. hr = m_pComponentData->GetDataClass((IDataObject *)pDataObject, &pItem, &type);
  176. // Find out CIISObject this belongs to and pass on the message
  177. CIISObject * pObject = (CIISObject *)pItem;
  178. if (SUCCEEDED(hr) && pObject != NULL)
  179. {
  180. hr = pObject->GetProperty(pDataObject,szPropertyName,pbstrProperty);
  181. }
  182. return hr;
  183. }
  184. HRESULT
  185. CInetMgrComponent::GetClassID(
  186. OUT CLSID * pClassID
  187. )
  188. /*++
  189. Routine Description:
  190. Get class ID for storage stream.
  191. Arguments:
  192. CLSID * pClassID : Returns class ID information
  193. Return Value:
  194. HRESULT
  195. --*/
  196. {
  197. *pClassID = CLSID_InetMgr;
  198. return S_OK;
  199. }
  200. STDMETHODIMP
  201. CInetMgrComponent::GetHelpTopic(LPOLESTR *lpCompiledHelpFile)
  202. {
  203. return ::GetHelpTopic(lpCompiledHelpFile);
  204. }
  205. STDMETHODIMP
  206. CInetMgrComponent::GetLinkedTopics(LPOLESTR *lpCompiledHelpFile)
  207. {
  208. return S_FALSE;
  209. }
  210. HRESULT
  211. CInetMgrComponent::IsDirty()
  212. /*++
  213. Routine Description:
  214. Check to see if we need to write to the cache.
  215. Arguments:
  216. None
  217. Return Value:
  218. S_OK if dirty, S_FALSE if not
  219. --*/
  220. {
  221. TRACEEOLID("CInetMgrComponent::IsDirty");
  222. return S_FALSE;
  223. }
  224. HRESULT
  225. CInetMgrComponent::InitNew(
  226. IN OUT IStorage * pStg
  227. )
  228. /*++
  229. Routine Description:
  230. Initialize storage stream.
  231. Arguments:
  232. IStorage * pStg : Storage stream
  233. Return Value:
  234. HRESULT
  235. --*/
  236. {
  237. TRACEEOLID("CInetMgrComponent::InitNew");
  238. return S_OK;
  239. }
  240. HRESULT
  241. CInetMgrComponent::Load(
  242. IN OUT IStorage * pStg
  243. )
  244. /*++
  245. Routine Description:
  246. Load from the storage stream
  247. Arguments:
  248. IStorage * pStg : Storage stream
  249. Return Value:
  250. HRESULT
  251. --*/
  252. {
  253. TRACEEOLID("CInetMgrComponent::Load");
  254. return S_OK;
  255. }
  256. /* virtual */
  257. HRESULT
  258. STDMETHODCALLTYPE
  259. CInetMgrComponent::Save(
  260. IN OUT IStorage * pStgSave,
  261. IN BOOL fSameAsLoad
  262. )
  263. /*++
  264. Routine Description:
  265. Save to to the storage stream.
  266. Arguments:
  267. IStorage * pStgSave : Storage stream
  268. BOOL fSameAsLoad : TRUE if same as load
  269. Return Value:
  270. HRESULT
  271. --*/
  272. {
  273. TRACEEOLID("CInetMgrComponent::Save");
  274. return S_OK;
  275. }
  276. /* virtual */
  277. HRESULT
  278. STDMETHODCALLTYPE
  279. CInetMgrComponent::SaveCompleted(IStorage * pStgNew)
  280. /*++
  281. Routine Description:
  282. Save completed.
  283. Arguments:
  284. IStorage * pStgNew : Storage stream
  285. Return Value:
  286. HRESULT
  287. --*/
  288. {
  289. TRACEEOLID("CInetMgrComponent::SaveCompleted");
  290. return S_OK;
  291. }
  292. /* virtual */
  293. HRESULT
  294. STDMETHODCALLTYPE
  295. CInetMgrComponent::HandsOffStorage()
  296. /*++
  297. Routine Description:
  298. Hands off storage.
  299. Arguments:
  300. None
  301. Return Value:
  302. HRESULT
  303. --*/
  304. {
  305. TRACEEOLID("CInetMgrComponent::HandsOffStorage");
  306. return S_OK;
  307. }
  308. /* virtual */
  309. HRESULT
  310. CInetMgrComponent::SetControlbar(
  311. IN LPCONTROLBAR lpControlBar
  312. )
  313. /*++
  314. Routine Description:
  315. Set/Reset the control bar
  316. Arguments:
  317. LPCONTROLBAR lpControlBar : Control bar pointer or NULL
  318. Return Value:
  319. HRESULT
  320. --*/
  321. {
  322. HRESULT hr = S_OK;
  323. if (lpControlBar)
  324. {
  325. if (_lpControlBar){_lpControlBar.Release();_lpControlBar=NULL;}
  326. _lpControlBar = lpControlBar;
  327. // BUG:680625
  328. if (_lpToolBar){_lpToolBar.Release();_lpToolBar=NULL;}
  329. if (_lpToolBar == NULL)
  330. {
  331. hr = ToolBar_Create(lpControlBar,this,(IToolbar **) &_lpToolBar);
  332. }
  333. }
  334. else
  335. {
  336. if (_lpControlBar != NULL && _lpToolBar != NULL)
  337. {
  338. _lpControlBar->Detach(_lpToolBar);
  339. }
  340. //
  341. // Release existing controlbar
  342. //
  343. if (_lpControlBar){_lpControlBar.Release();_lpControlBar=NULL;}
  344. }
  345. return hr;
  346. }
  347. /* virtual */
  348. HRESULT
  349. CInetMgrComponent::ControlbarNotify(
  350. IN MMC_NOTIFY_TYPE event,
  351. IN LPARAM arg,
  352. IN LPARAM param
  353. )
  354. /*++
  355. Routine Description:
  356. Handle control bar notification message. Figure out the CIISObject
  357. selected, and pass the notification message off to it.
  358. Arguments:
  359. MMC_NOTIFY_TYPE event : Notification message
  360. long arg : Message specific argument
  361. long param : Message specific parameter
  362. Return Value:
  363. HRESULT
  364. --*/
  365. {
  366. HRESULT hr = S_OK;
  367. CSnapInItem * pItem = NULL;
  368. DATA_OBJECT_TYPES type;
  369. BOOL fSelect = (BOOL)HIWORD(arg);
  370. BOOL fScope = (BOOL)LOWORD(arg);
  371. //
  372. // Special casing this is annoying...
  373. //
  374. // CODEWORK: Handle MMCN_HELP and others
  375. //
  376. if (event == MMCN_BTN_CLICK)
  377. {
  378. hr = m_pComponentData->GetDataClass((IDataObject *)arg, &pItem, &type);
  379. }
  380. else if (event == MMCN_SELECT)
  381. {
  382. IDataObject * p = (IDataObject *)param;
  383. if (p == DOBJ_CUSTOMWEB || p == DOBJ_CUSTOMOCX)
  384. {
  385. return S_OK;
  386. }
  387. hr = m_pComponentData->GetDataClass((IDataObject *)param, &pItem, &type);
  388. }
  389. //
  390. // Find out CIISObject this belongs to and pass on
  391. // the message
  392. //
  393. CIISObject * pObject = (CIISObject *)pItem;
  394. if (SUCCEEDED(hr) && pObject != NULL)
  395. {
  396. if (MMCN_SELECT == event)
  397. {
  398. arg = (LPARAM)(LPUNKNOWN *) &_lpControlBar;
  399. param = (LPARAM)(LPUNKNOWN *) &_lpToolBar;
  400. if (_lpControlBar)
  401. {
  402. if (_lpToolBar)
  403. {
  404. hr = _lpControlBar->Attach(TOOLBAR, _lpToolBar);
  405. }
  406. }
  407. }
  408. if (fSelect)
  409. {
  410. if (SUCCEEDED(hr))
  411. {
  412. hr = pObject->ControlbarNotify(event, arg, param);
  413. }
  414. }
  415. }
  416. return hr;
  417. }
  418. /* virtual */
  419. HRESULT
  420. CInetMgrComponent::Compare(
  421. IN RDCOMPARE * prdc,
  422. OUT int * pnResult
  423. )
  424. /*++
  425. Routine Description:
  426. Compare method used for sorting the result and scope panes.
  427. Arguments:
  428. RDCOMPARE * prdc : Compare structure
  429. int * pnResult : Returns result
  430. Return Value:
  431. HRESULT
  432. --*/
  433. {
  434. if (!pnResult || !prdc || !prdc->prdch1->cookie || !prdc->prdch2->cookie)
  435. {
  436. ASSERT_MSG("Invalid parameter(s)");
  437. return E_POINTER;
  438. }
  439. CIISObject * pObjectA = (CIISObject *)prdc->prdch1->cookie;
  440. CIISObject * pObjectB = (CIISObject *)prdc->prdch2->cookie;
  441. *pnResult = pObjectA->CompareResultPaneItem(pObjectB, prdc->nColumn);
  442. return S_OK;
  443. }
  444. /* virtual */
  445. HRESULT
  446. CInetMgrComponent::CompareObjects(
  447. IN LPDATAOBJECT lpDataObjectA,
  448. IN LPDATAOBJECT lpDataObjectB
  449. )
  450. /*++
  451. Routine Description:
  452. Compare two data objects. This method is used to see if a property
  453. sheet for the given data object is already open
  454. Arguments:
  455. LPDATAOBJECT lpDataObjectA : A data object
  456. LPDATAOBJECT lpDataObjectB : B data object
  457. Return Value:
  458. S_OK if they match, S_FALSE otherwise
  459. --*/
  460. {
  461. //
  462. // Pass it on to IComponentImpl
  463. //
  464. return IComponentImpl<CInetMgrComponent>::CompareObjects(lpDataObjectA, lpDataObjectB);
  465. }
  466. //
  467. // CInetMgr Implementation
  468. //
  469. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  470. /* static */ DWORD CInetMgr::_dwSignature = 0x3517;
  471. /* static */ LPCTSTR CInetMgr::_szStream = _T("CInetMgr");
  472. HRESULT
  473. CInetMgr::GetProperty(
  474. LPDATAOBJECT pDataObject,
  475. BSTR szPropertyName,
  476. BSTR* pbstrProperty)
  477. {
  478. HRESULT hr = S_OK;
  479. CSnapInItem * pItem = NULL;
  480. DATA_OBJECT_TYPES type;
  481. IDataObject * p = (IDataObject *)pDataObject;
  482. if (p == DOBJ_CUSTOMWEB || p == DOBJ_CUSTOMOCX)
  483. {
  484. return S_OK;
  485. }
  486. hr = m_pComponentData->GetDataClass((IDataObject *)pDataObject, &pItem, &type);
  487. // Find out CIISObject this belongs to and pass on the message
  488. CIISObject * pObject = (CIISObject *)pItem;
  489. if (SUCCEEDED(hr) && pObject != NULL)
  490. {
  491. hr = pObject->GetProperty(pDataObject,szPropertyName,pbstrProperty);
  492. }
  493. return hr;
  494. }
  495. /* static */
  496. void
  497. WINAPI
  498. CInetMgr::ObjectMain(
  499. IN bool bStarting
  500. )
  501. /*++
  502. Routine Description:
  503. CInetMgr main entry point
  504. Arguments:
  505. bool bStarting : TRUE if starting
  506. Return Value:
  507. None
  508. --*/
  509. {
  510. TRACEEOLID("CInetMgr::ObjectMain:g_IISMMCInstanceCount=" << g_IISMMCInstanceCount);
  511. if (bStarting)
  512. {
  513. g_IISMMCComLoaded++;
  514. // Check regkey if debugging is okay to be turned on..
  515. GetOutputDebugFlag();
  516. // Get Special parameters used by the snapin...
  517. GetInetmgrParamFlag();
  518. //
  519. // Register clipboard formats
  520. //
  521. CSnapInItem::Init();
  522. CIISObject::Init();
  523. ToolBar_Init();
  524. g_OpenPropertySheetTracker.Init();
  525. #if defined(_DEBUG) || DBG
  526. g_Debug_IISObject.Init();
  527. #endif
  528. }
  529. else
  530. {
  531. g_OpenPropertySheetTracker.Clear();
  532. #if defined(_DEBUG) || DBG
  533. g_GlobalConnections.Dump();
  534. #endif
  535. g_GlobalConnections.Clear();
  536. ToolBar_Destroy();
  537. g_IISMMCComLoaded--;
  538. }
  539. }
  540. CInetMgr::CInetMgr() : m_pConsoleNameSpace(NULL),m_pConsole(NULL)
  541. {
  542. TRACEEOLID("CInetMgr::CInetMgr");
  543. //
  544. // Initialize strings we will be using
  545. // for the lifetime of the snapin
  546. //
  547. m_pNode = new CIISRoot;
  548. ASSERT_PTR(m_pNode);
  549. m_pComponentData = this;
  550. CIISObject * pNode = dynamic_cast<CIISObject *>(m_pNode);
  551. if (pNode)
  552. {
  553. pNode->AddRef();
  554. }
  555. }
  556. CInetMgr::~CInetMgr()
  557. {
  558. TRACEEOLID("CInetMgr::~CInetMgr:g_IISMMCInstanceCount=" << g_IISMMCInstanceCount);
  559. //
  560. // Clean up the root node
  561. //
  562. CIISObject * pNode = dynamic_cast<CIISObject *>(m_pNode);
  563. if (pNode)
  564. {
  565. pNode->Release();
  566. }
  567. m_pNode = NULL;
  568. }
  569. HRESULT
  570. CInetMgr::Destroy()
  571. {
  572. TRACEEOLID("CInetMgr::Destroy:g_IISMMCInstanceCount=" << g_IISMMCInstanceCount);
  573. #if defined(_DEBUG) || DBG
  574. // check if we leaked anything.
  575. g_Debug_IISObject.Dump(1);
  576. #endif
  577. return S_OK;
  578. }
  579. HRESULT
  580. CInetMgr::Initialize(
  581. IN LPUNKNOWN lpUnknown
  582. )
  583. /*++
  584. Routine Description:
  585. Initialize the snap-in
  586. Arguments:
  587. LPUNKNOWN lpUnknown : IUnknown
  588. Return Value:
  589. HRESULT
  590. --*/
  591. {
  592. TRACEEOLID("CInetMgr::Initialize");
  593. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  594. HRESULT hr =
  595. IComponentDataImpl<CInetMgr, CInetMgrComponent>::Initialize(lpUnknown);
  596. if (FAILED(hr))
  597. {
  598. return hr;
  599. }
  600. //
  601. // Query the interfaces for console name space and console
  602. //
  603. CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> lpConsoleNameSpace(lpUnknown);
  604. if (!lpConsoleNameSpace)
  605. {
  606. TRACEEOLID("failed to query console name space interface");
  607. return hr;
  608. }
  609. m_pConsoleNameSpace = lpConsoleNameSpace;
  610. CComQIPtr<IConsole, &IID_IConsole> lpConsole(lpConsoleNameSpace);
  611. if (!lpConsole)
  612. {
  613. TRACEEOLID("failed to query console interface");
  614. return hr;
  615. }
  616. m_pConsole = lpConsole;
  617. CIISObject * pNode = dynamic_cast<CIISObject *>(m_pNode);
  618. if (pNode)
  619. {
  620. pNode->SetConsoleData(m_pConsoleNameSpace,m_pConsole);
  621. }
  622. CComPtr<IImageList> lpImageList;
  623. hr = m_spConsole->QueryScopeImageList(&lpImageList);
  624. if (FAILED(hr) || lpImageList == NULL)
  625. {
  626. TRACEEOLID("IConsole::QueryScopeImageList failed");
  627. return E_UNEXPECTED;
  628. }
  629. return CIISObject::SetImageList(lpImageList);
  630. }
  631. HRESULT
  632. CInetMgr::OnPropertyChange(LPARAM arg, LPARAM param)
  633. {
  634. HRESULT hr = S_OK;
  635. if (param != 0)
  636. {
  637. CSnapInItem * pNode = (CSnapInItem *)param;
  638. LPDATAOBJECT pDataObject = NULL;
  639. if (IsValidAddress( (const void*) pNode,sizeof(void*),FALSE))
  640. {
  641. pNode->GetDataObject(&pDataObject, CCT_SCOPE);
  642. CIISObject * pObj = dynamic_cast<CIISObject *>(pNode);
  643. ASSERT(pNode != NULL);
  644. hr = m_spConsole->UpdateAllViews(pDataObject, param, pObj->m_UpdateFlag);
  645. }
  646. }
  647. return hr;
  648. }
  649. HRESULT
  650. CInetMgr::Notify(
  651. LPDATAOBJECT lpDataObject,
  652. MMC_NOTIFY_TYPE event,
  653. LPARAM arg,
  654. LPARAM param
  655. )
  656. {
  657. HRESULT hr = S_OK;
  658. if (lpDataObject == NULL)
  659. {
  660. switch (event)
  661. {
  662. case MMCN_PROPERTY_CHANGE:
  663. TRACEEOLID("CInetMgr::Notify:MMCN_PROPERTY_CHANGE");
  664. hr = OnPropertyChange(arg, param);
  665. break;
  666. case MMCN_SNAPINHELP:
  667. break;
  668. default:
  669. break;
  670. }
  671. }
  672. else
  673. {
  674. hr = IComponentDataImpl<CInetMgr, CInetMgrComponent>::Notify(
  675. lpDataObject, event, arg, param);
  676. }
  677. return hr;
  678. }
  679. HRESULT
  680. CInetMgr::GetClassID(CLSID * pClassID)
  681. /*++
  682. Routine Description:
  683. Get class ID for storage stream
  684. Arguments:
  685. CLSID * pClassID : Returns class ID information
  686. Return Value:
  687. HRESULT
  688. --*/
  689. {
  690. *pClassID = CLSID_InetMgr;
  691. return S_OK;
  692. }
  693. STDMETHODIMP
  694. CInetMgr::GetHelpTopic(LPOLESTR *lpCompiledHelpFile)
  695. {
  696. return ::GetHelpTopic(lpCompiledHelpFile);
  697. }
  698. STDMETHODIMP
  699. CInetMgr::GetLinkedTopics(LPOLESTR *lpCompiledHelpFile)
  700. {
  701. return S_FALSE;
  702. }
  703. HRESULT
  704. CInetMgr::IsDirty()
  705. /*++
  706. Routine Description:
  707. Check to see if we need to write to the cache.
  708. Arguments:
  709. None
  710. Return Value:
  711. S_OK if dirty, S_FALSE if not
  712. --*/
  713. {
  714. TRACEEOLID("CInetMgr::IsDirty");
  715. ASSERT_PTR(m_pNode);
  716. if (IsExtension())
  717. {
  718. return FALSE;
  719. }
  720. else
  721. {
  722. return ((CIISRoot *)m_pNode)->m_scServers.IsDirty() ? S_OK : S_FALSE;
  723. }
  724. }
  725. HRESULT
  726. CInetMgr::InitNew(IStorage * pStg)
  727. /*++
  728. Routine Description:
  729. Initialize new storage stream (newly created console file)
  730. Arguments:
  731. IStorage * pStg : Storage stream
  732. Return Value:
  733. HRESULT
  734. --*/
  735. {
  736. TRACEEOLID("CInetMgr::InitNew");
  737. //
  738. // We could create the stream here, but it's just as easy to
  739. // create it inside Save().
  740. //
  741. return S_OK;
  742. }
  743. HRESULT
  744. CInetMgr::Load(IStorage * pStg)
  745. /*++
  746. Routine Description:
  747. Load machine cache from the storage stream.
  748. Arguments:
  749. IStorage * pStg : Storage stream
  750. Return Value:
  751. HRESULT
  752. --*/
  753. {
  754. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  755. TRACEEOLID("CInetMgr::Load");
  756. if (IsExtension())
  757. {
  758. return S_OK;
  759. }
  760. ASSERT_READ_WRITE_PTR(pStg);
  761. DWORD cBytesRead;
  762. DWORD dw;
  763. HRESULT hr = S_OK;
  764. CIISServerCache & cache = ((CIISRoot *)m_pNode)->m_scServers;
  765. IStream * pStream = NULL;
  766. ASSERT(cache.IsEmpty());
  767. do
  768. {
  769. hr = pStg->OpenStream(
  770. _szStream,
  771. NULL,
  772. STGM_READ | STGM_SHARE_EXCLUSIVE,
  773. 0L,
  774. &pStream
  775. );
  776. if (FAILED(hr))
  777. {
  778. break;
  779. }
  780. //
  781. // Read and verify the signature
  782. //
  783. hr = pStream->Read(&dw, sizeof(dw), &cBytesRead);
  784. ASSERT(SUCCEEDED(hr) && cBytesRead == sizeof(dw));
  785. if (FAILED(hr))
  786. {
  787. break;
  788. }
  789. if (dw != _dwSignature)
  790. {
  791. hr = HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT);
  792. break;
  793. }
  794. //
  795. // Read number of machines in the cache
  796. //
  797. DWORD cMachines;
  798. hr = pStream->Read(&cMachines, sizeof(cMachines), &cBytesRead);
  799. ASSERT(SUCCEEDED(hr) && cBytesRead == sizeof(cMachines));
  800. if (FAILED(hr))
  801. {
  802. break;
  803. }
  804. TRACEEOLID("Reading " << cMachines << " machines from cache");
  805. CIISMachine * pMachine;
  806. //
  807. // Read each machine from the cache
  808. //
  809. for (dw = 0; dw < cMachines; ++dw)
  810. {
  811. hr = CIISMachine::ReadFromStream(pStream, &pMachine,m_pConsoleNameSpace,m_pConsole);
  812. if (FAILED(hr))
  813. {
  814. break;
  815. }
  816. pMachine->AddRef();
  817. if (!cache.Add(pMachine))
  818. {
  819. pMachine->Release();
  820. }
  821. }
  822. }
  823. while(FALSE);
  824. if (pStream)
  825. {
  826. pStream->Release();
  827. }
  828. if (hr == STG_E_FILENOTFOUND)
  829. {
  830. //
  831. // Stream was not initialized. This is acceptable.
  832. //
  833. hr = S_OK;
  834. }
  835. //
  836. // Mark cache as clean
  837. //
  838. cache.SetDirty(FALSE);
  839. return hr;
  840. }
  841. /* virtual */
  842. HRESULT STDMETHODCALLTYPE
  843. CInetMgr::Save(IStorage * pStgSave, BOOL fSameAsLoad)
  844. /*++
  845. Routine Description:
  846. Save computer cache to to the storage stream.
  847. Arguments:
  848. IStorage * pStgSave : Storage stream
  849. BOOL fSameAsLoad : TRUE if same as load
  850. Return Value:
  851. HRESULT
  852. --*/
  853. {
  854. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  855. TRACEEOLID("CInetMgr::Save");
  856. if (IsExtension())
  857. {
  858. return S_OK;
  859. }
  860. //
  861. // Write the computer names to the cache
  862. //
  863. ASSERT_READ_WRITE_PTR(pStgSave);
  864. DWORD cBytesWritten;
  865. HRESULT hr = STG_E_CANTSAVE;
  866. IStream * pStream = NULL;
  867. CIISServerCache & cache = ((CIISRoot *)m_pNode)->m_scServers;
  868. do
  869. {
  870. hr = pStgSave->CreateStream(
  871. _szStream,
  872. STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
  873. 0L,
  874. 0L,
  875. &pStream
  876. );
  877. if (FAILED(hr))
  878. {
  879. break;
  880. }
  881. //
  882. // Write the signature
  883. //
  884. hr = pStream->Write(&_dwSignature, sizeof(_dwSignature), &cBytesWritten);
  885. ASSERT(SUCCEEDED(hr) && cBytesWritten == sizeof(_dwSignature));
  886. if (FAILED(hr))
  887. {
  888. break;
  889. }
  890. //
  891. // Write number of entries.
  892. //
  893. INT_PTR dw = cache.GetCount();
  894. hr = pStream->Write(&dw, sizeof(dw), &cBytesWritten);
  895. ASSERT(SUCCEEDED(hr) && cBytesWritten == sizeof(dw));
  896. if (FAILED(hr))
  897. {
  898. break;
  899. }
  900. //
  901. // Write each string -- but write them in reverse
  902. // order to improve our sort performance when we load
  903. // the cache.
  904. //
  905. CIISMachine * pMachine = cache.GetLast();
  906. while(pMachine)
  907. {
  908. hr = pMachine->WriteToStream(pStream);
  909. if (FAILED(hr))
  910. {
  911. break;
  912. }
  913. pMachine = cache.GetPrev();
  914. }
  915. }
  916. while(FALSE);
  917. if (pStream)
  918. {
  919. pStream->Release();
  920. }
  921. if (SUCCEEDED(hr))
  922. {
  923. //
  924. // Mark cache as clean
  925. //
  926. cache.SetDirty(FALSE);
  927. }
  928. return hr;
  929. }
  930. /* virtual */
  931. HRESULT
  932. STDMETHODCALLTYPE
  933. CInetMgr::SaveCompleted(IStorage * pStgNew)
  934. /*++
  935. Routine Description:
  936. Save completed notification.
  937. Arguments:
  938. IStorage * pStgNew : Storage stream
  939. Return Value:
  940. HRESULT
  941. --*/
  942. {
  943. TRACEEOLID("CInetMgr::SaveCompleted");
  944. //
  945. // Nothing to do
  946. //
  947. return S_OK;
  948. }
  949. /* virtual */
  950. HRESULT
  951. STDMETHODCALLTYPE
  952. CInetMgr::HandsOffStorage()
  953. /*++
  954. Routine Description:
  955. Hands off storage.
  956. Arguments:
  957. None
  958. Return Value:
  959. HRESULT
  960. --*/
  961. {
  962. TRACEEOLID("CInetMgr::HandsOffStorage");
  963. //
  964. // Nothing to do
  965. //
  966. return S_OK;
  967. }
  968. /* virtual */
  969. HRESULT
  970. CInetMgr::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  971. /*++
  972. Routine Description:
  973. Compare two data objects. This method is used by MMC to see if a property
  974. sheet for the given data object is already open.
  975. Arguments:
  976. LPDATAOBJECT lpDataObjectA : A data object
  977. LPDATAOBJECT lpDataObjectB : B data object
  978. Return Value:
  979. S_OK if they match, S_FALSE otherwise
  980. --*/
  981. {
  982. HRESULT hr = E_POINTER;
  983. do
  984. {
  985. if (!lpDataObjectA || !lpDataObjectB)
  986. {
  987. TRACEEOLID("CInetMgr:IComponentData::CompareObjects called with NULL ptr");
  988. break;
  989. }
  990. CSnapInItem * pItemA;
  991. CSnapInItem * pItemB;
  992. DATA_OBJECT_TYPES type;
  993. hr = m_pComponentData->GetDataClass(lpDataObjectA, &pItemA, &type);
  994. if (SUCCEEDED(hr))
  995. {
  996. hr = m_pComponentData->GetDataClass(lpDataObjectB, &pItemB, &type);
  997. }
  998. if (FAILED(hr))
  999. {
  1000. break;
  1001. }
  1002. if (!pItemA || !pItemB)
  1003. {
  1004. hr = E_POINTER;
  1005. break;
  1006. }
  1007. if (pItemA == pItemB)
  1008. {
  1009. //
  1010. // Literally the same object
  1011. //
  1012. hr = S_OK;
  1013. break;
  1014. }
  1015. CIISObject * pObjectA = (CIISObject *)pItemA;
  1016. CIISObject * pObjectB = (CIISObject *)pItemB;
  1017. hr = !pObjectA->CompareScopeItem(pObjectB) ? S_OK : S_FALSE;
  1018. }
  1019. while(FALSE);
  1020. return hr;
  1021. }
  1022. HRESULT
  1023. CInetMgr::GetDataClass(
  1024. IDataObject * pDataObject,
  1025. CSnapInItem ** ppItem,
  1026. DATA_OBJECT_TYPES * pType)
  1027. {
  1028. if (ppItem == NULL)
  1029. return E_POINTER;
  1030. if (pType == NULL)
  1031. return E_POINTER;
  1032. *ppItem = NULL;
  1033. *pType = CCT_UNINITIALIZED;
  1034. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  1035. FORMATETC formatetc = { CSnapInItem::m_CCF_NODETYPE,
  1036. NULL,
  1037. DVASPECT_CONTENT,
  1038. -1,
  1039. TYMED_HGLOBAL
  1040. };
  1041. stgmedium.hGlobal = GlobalAlloc(0, sizeof(GUID));
  1042. if (stgmedium.hGlobal == NULL)
  1043. return E_OUTOFMEMORY;
  1044. HRESULT hr = pDataObject->GetDataHere(&formatetc, &stgmedium);
  1045. if (FAILED(hr))
  1046. {
  1047. GlobalFree(stgmedium.hGlobal);
  1048. return hr;
  1049. }
  1050. GUID guid;
  1051. memcpy(&guid, stgmedium.hGlobal, sizeof(GUID));
  1052. GlobalFree(stgmedium.hGlobal);
  1053. hr = S_OK;
  1054. if (IsEqualGUID(guid, cCompMgmtService))
  1055. {
  1056. if (!IsExtension())
  1057. {
  1058. CIISRoot * pRootExt = new CIISRoot;
  1059. if (pRootExt == NULL)
  1060. {
  1061. return E_OUTOFMEMORY;
  1062. }
  1063. hr = pRootExt->InitAsExtension(pDataObject);
  1064. if (FAILED(hr))
  1065. {
  1066. return hr;
  1067. }
  1068. pRootExt->SetConsoleData(m_pConsoleNameSpace,m_pConsole);
  1069. if (m_pNode != NULL)
  1070. {
  1071. CIISObject * pNode = dynamic_cast<CIISObject *>(m_pNode);
  1072. if (pNode->GetConsoleNameSpace())
  1073. {
  1074. pRootExt->SetConsoleData(pNode->GetConsoleNameSpace(),pNode->GetConsole());
  1075. }
  1076. pNode->Release();
  1077. }
  1078. g_IISMMCInstanceCountExtensionMode++;
  1079. m_pNode = pRootExt;
  1080. }
  1081. *ppItem = m_pNode;
  1082. return hr;
  1083. }
  1084. return CSnapInItem::GetDataClass(pDataObject, ppItem, pType);
  1085. };
  1086. BOOL
  1087. CInetMgr::IsExtension()
  1088. {
  1089. ASSERT(m_pNode != NULL);
  1090. CIISRoot * pRoot = (CIISRoot *)m_pNode;
  1091. return pRoot->IsExtension();
  1092. }
  1093. //
  1094. // CInetMrgAbout Class
  1095. //
  1096. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1097. HRESULT
  1098. CInetMgrAbout::GetStringHelper(UINT nStringID, LPOLESTR * lpString)
  1099. /*++
  1100. Routine Description:
  1101. Get resource string helper function. Called from inline string fetcher
  1102. methods.
  1103. Arguments:
  1104. UINT nStringID : String ID from local resource segment
  1105. LPOLESTR * lpString : Returns the string
  1106. Return Value:
  1107. HRESULT
  1108. --*/
  1109. {
  1110. USES_CONVERSION;
  1111. TCHAR szBuf[256];
  1112. if (::LoadString(
  1113. _Module.GetResourceInstance(),
  1114. nStringID,
  1115. szBuf,
  1116. 256) == 0)
  1117. {
  1118. return E_FAIL;
  1119. }
  1120. *lpString = (LPOLESTR)::CoTaskMemAlloc(
  1121. (lstrlen(szBuf) + 1) * sizeof(OLECHAR)
  1122. );
  1123. if (*lpString == NULL)
  1124. {
  1125. return E_OUTOFMEMORY;
  1126. }
  1127. ::ocscpy(*lpString, T2OLE(szBuf));
  1128. return S_OK;
  1129. }
  1130. HRESULT
  1131. CInetMgrAbout::GetSnapinImage(HICON * hAppIcon)
  1132. /*++
  1133. Routine Description:
  1134. Get the icon for this snapin.
  1135. Arguments:
  1136. HICON * hAppIcon : Return handle to the icon
  1137. Return Value:
  1138. HRESULT
  1139. --*/
  1140. {
  1141. if (hAppIcon == NULL)
  1142. {
  1143. return E_POINTER;
  1144. }
  1145. m_hSnapinIcon = ::LoadIcon(
  1146. _Module.GetModuleInstance(),
  1147. MAKEINTRESOURCE(IDI_INETMGR)
  1148. );
  1149. *hAppIcon = m_hSnapinIcon;
  1150. ASSERT(*hAppIcon != NULL);
  1151. return (*hAppIcon != NULL) ? S_OK : E_FAIL;
  1152. }
  1153. HRESULT
  1154. CInetMgrAbout::GetStaticFolderImage(
  1155. HBITMAP * phSmallImage,
  1156. HBITMAP * phSmallImageOpen,
  1157. HBITMAP * phLargeImage,
  1158. COLORREF * prgbMask
  1159. )
  1160. /*++
  1161. Routine Description:
  1162. Get the static folder images.
  1163. Arguments:
  1164. HBITMAP * phSmallImage : Small folder
  1165. HBITMAP * phSmallImageOpen : Small open folder
  1166. HBITMAP * phLargeImage : Large image
  1167. COLORREF * prgbMask : Mask
  1168. Return Value:
  1169. HRESULT
  1170. --*/
  1171. {
  1172. if (!phSmallImage || !phSmallImageOpen || !phLargeImage || !prgbMask)
  1173. {
  1174. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1175. }
  1176. m_hSmallImage = (HBITMAP)::LoadImage(
  1177. _Module.GetModuleInstance(),
  1178. MAKEINTRESOURCE(IDB_SMALL_ROOT),
  1179. IMAGE_BITMAP,
  1180. 0,
  1181. 0,
  1182. LR_DEFAULTCOLOR
  1183. );
  1184. m_hLargeImage = (HBITMAP)::LoadImage(
  1185. _Module.GetModuleInstance(),
  1186. MAKEINTRESOURCE(IDB_LARGE_ROOT),
  1187. IMAGE_BITMAP,
  1188. 0,
  1189. 0,
  1190. LR_DEFAULTCOLOR
  1191. );
  1192. *phSmallImage = m_hSmallImage;
  1193. *phSmallImageOpen = m_hSmallImage;
  1194. *phLargeImage = m_hLargeImage;
  1195. *prgbMask = RGB_BK_IMAGES;
  1196. return *phSmallImage && *phLargeImage ? S_OK : E_FAIL;
  1197. }
  1198. CInetMgrAbout::~CInetMgrAbout()
  1199. {
  1200. if (m_hSmallImage != NULL)
  1201. {
  1202. ::DeleteObject(m_hSmallImage);
  1203. }
  1204. if (m_hLargeImage != NULL)
  1205. {
  1206. ::DeleteObject(m_hLargeImage);
  1207. }
  1208. if (m_hSnapinIcon != NULL)
  1209. {
  1210. ::DestroyIcon(m_hSnapinIcon);
  1211. }
  1212. }
  1213. #if 0
  1214. HRESULT
  1215. ExtractComputerNameExt(IDataObject * pDataObject, CString& strComputer)
  1216. {
  1217. //
  1218. // Find the computer name from the ComputerManagement snapin
  1219. //
  1220. CLIPFORMAT CCF_MyComputMachineName = (CLIPFORMAT)RegisterClipboardFormat(MYCOMPUT_MACHINE_NAME);
  1221. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  1222. FORMATETC formatetc = {
  1223. CCF_MyComputMachineName, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  1224. };
  1225. //
  1226. // Allocate memory for the stream
  1227. //
  1228. int len = MAX_PATH;
  1229. stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, len);
  1230. if(stgmedium.hGlobal == NULL)
  1231. return ERROR_NOT_ENOUGH_MEMORY;
  1232. HRESULT hr = pDataObject->GetDataHere(&formatetc, &stgmedium);
  1233. ASSERT(SUCCEEDED(hr));
  1234. //
  1235. // Get the computer name
  1236. //
  1237. strComputer = (LPTSTR)stgmedium.hGlobal;
  1238. GlobalFree(stgmedium.hGlobal);
  1239. return hr;
  1240. }
  1241. HRESULT
  1242. CCompMgrExtData::Init(IDataObject * pDataObject)
  1243. {
  1244. TRACEEOLID("CCompMgrExtData::Init:g_IISMMCInstanceCount=" << g_IISMMCInstanceCount);
  1245. return ExtractComputerNameExt(pDataObject, m_ExtMachineName);
  1246. }
  1247. HRESULT
  1248. STDMETHODCALLTYPE
  1249. CCompMgrExtData::Notify(
  1250. MMC_NOTIFY_TYPE event,
  1251. LPARAM arg,
  1252. LPARAM param,
  1253. IComponentData* pComponentData,
  1254. IComponent* pComponent,
  1255. DATA_OBJECT_TYPES type)
  1256. {
  1257. TRACEEOLID("CCompMgrExtData::Notify");
  1258. CError err;
  1259. CComPtr<IConsole> pConsole;
  1260. CComQIPtr<IHeaderCtrl, &IID_IHeaderCtrl> pHeader;
  1261. CComQIPtr<IResultData, &IID_IResultData> pResultData;
  1262. if (pComponentData != NULL)
  1263. {
  1264. pConsole = ((CInetMgr *)pComponentData)->m_spConsole;
  1265. }
  1266. else
  1267. {
  1268. pConsole = ((CInetMgrComponent *)pComponent)->m_spConsole;
  1269. }
  1270. CComQIPtr<IConsoleNameSpace2, &IID_IConsoleNameSpace2> pScope = pConsole;
  1271. switch (event)
  1272. {
  1273. case MMCN_EXPAND:
  1274. err = EnumerateScopePane((HSCOPEITEM)param, pScope);
  1275. break;
  1276. default:
  1277. err = CSnapInItemImpl<CCompMgrExtData, TRUE>::Notify(event, arg, param, pComponentData, pComponent, type);
  1278. break;
  1279. }
  1280. return err;
  1281. }
  1282. HRESULT
  1283. CCompMgrExtData::EnumerateScopePane(HSCOPEITEM hParent, IConsoleNameSpace2 * pScope)
  1284. {
  1285. TRACEEOLID("CCompMgrExtData::EnumerateScopePane");
  1286. CError err;
  1287. ASSERT_PTR(pScope);
  1288. DWORD dwMask = SDI_PARENT;
  1289. SCOPEDATAITEM scopeDataItem;
  1290. ::ZeroMemory(&scopeDataItem, sizeof(SCOPEDATAITEM));
  1291. scopeDataItem.mask =
  1292. SDI_STR | SDI_IMAGE | SDI_CHILDREN | SDI_OPENIMAGE | SDI_PARAM | dwMask;
  1293. scopeDataItem.displayname = MMC_CALLBACK;
  1294. scopeDataItem.nImage = scopeDataItem.nOpenImage = MMC_IMAGECALLBACK;//QueryImage();
  1295. scopeDataItem.lParam = (LPARAM)this;
  1296. scopeDataItem.relativeID = hParent;
  1297. scopeDataItem.cChildren = 1;
  1298. err = pScope->InsertItem(&scopeDataItem);
  1299. if (err.Succeeded())
  1300. {
  1301. //
  1302. // Cache the scope item handle
  1303. //
  1304. ASSERT(m_hScopeItem == NULL);
  1305. m_hScopeItem = scopeDataItem.ID;
  1306. // MMC_IMAGECALLBACK doesn't work in InsertItem. Update it here.
  1307. scopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  1308. err = pScope->SetItem(&scopeDataItem);
  1309. }
  1310. return err;
  1311. }
  1312. #endif