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.

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