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.

1541 lines
34 KiB

  1. /*++
  2. Copyright (C) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. componet.cpp
  5. Abstract:
  6. This module implemets CComponent class
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "devmgr.h"
  12. #include "factory.h"
  13. #include <devguid.h>
  14. //
  15. // ctor and dtor
  16. //
  17. CComponent::CComponent(
  18. CComponentData* pComponentData
  19. )
  20. {
  21. m_pComponentData = pComponentData;
  22. m_pHeader = NULL;
  23. m_pConsole = NULL;
  24. m_pResult = NULL;
  25. m_pConsoleVerb = NULL;
  26. m_pCurFolder = NULL;
  27. m_pPropSheetProvider = NULL;
  28. m_pDisplayHelp = NULL;
  29. m_MachineAttached = FALSE;
  30. m_Dirty = FALSE;
  31. m_pControlbar = NULL;
  32. m_pToolbar = NULL;
  33. //
  34. // Increment object count(used by CanUnloadNow)
  35. //
  36. ::InterlockedIncrement(&CClassFactory::s_Objects);
  37. m_Ref = 1;
  38. }
  39. CComponent::~CComponent()
  40. {
  41. //
  42. // Decrement object count(used by CanUnloadNow)
  43. //
  44. ::InterlockedDecrement(&CClassFactory::s_Objects);
  45. }
  46. //
  47. // IUNKNOWN interface
  48. //
  49. ULONG
  50. CComponent::AddRef()
  51. {
  52. ::InterlockedIncrement((LONG*)&m_Ref);
  53. return m_Ref;
  54. }
  55. ULONG
  56. CComponent::Release()
  57. {
  58. ::InterlockedDecrement((LONG*)&m_Ref);
  59. if (!m_Ref)
  60. {
  61. delete this;
  62. return 0;
  63. }
  64. return m_Ref;
  65. }
  66. STDMETHODIMP
  67. CComponent::QueryInterface(
  68. REFIID riid,
  69. void** ppv
  70. )
  71. {
  72. if (!ppv)
  73. {
  74. return E_INVALIDARG;
  75. }
  76. HRESULT hr = S_OK;
  77. if (IsEqualIID(riid, IID_IUnknown))
  78. {
  79. *ppv = (IUnknown*)(IComponent*)this;
  80. }
  81. else if (IsEqualIID(riid, IID_IComponent))
  82. {
  83. *ppv = (IComponent*)this;
  84. }
  85. else if (IsEqualIID(riid, IID_IResultDataCompare))
  86. {
  87. *ppv = (IResultDataCompare*)this;
  88. }
  89. else if (IsEqualIID(riid, IID_IExtendContextMenu))
  90. {
  91. *ppv = (IExtendContextMenu*)this;
  92. }
  93. else if (IsEqualIID(riid, IID_IExtendControlbar))
  94. {
  95. *ppv = (IExtendControlbar*)this;
  96. }
  97. else if (IsEqualIID(riid, IID_IExtendPropertySheet))
  98. {
  99. *ppv = (IExtendPropertySheet*)this;
  100. }
  101. else if (IsEqualIID(riid, IID_IPersistStream))
  102. {
  103. *ppv = (IPersistStream*)this;
  104. }
  105. else if (IsEqualIID(riid, IID_ISnapinCallback))
  106. {
  107. *ppv = (ISnapinCallback*)this;
  108. }
  109. else
  110. {
  111. *ppv = NULL;
  112. hr = E_NOINTERFACE;
  113. }
  114. if (SUCCEEDED(hr))
  115. {
  116. AddRef();
  117. }
  118. return hr;
  119. }
  120. //
  121. // IComponent interface implementation
  122. //
  123. STDMETHODIMP
  124. CComponent::GetResultViewType(
  125. MMC_COOKIE cookie,
  126. LPOLESTR* ppViewType,
  127. long* pViewOptions
  128. )
  129. {
  130. if (!ppViewType || !pViewOptions)
  131. {
  132. return E_INVALIDARG;
  133. }
  134. HRESULT hr;
  135. try
  136. {
  137. CFolder* pFolder;
  138. pFolder = FindFolder(cookie);
  139. if (pFolder)
  140. {
  141. return pFolder->GetResultViewType(ppViewType, pViewOptions);
  142. }
  143. else
  144. {
  145. return S_OK;
  146. }
  147. }
  148. catch (CMemoryException* e)
  149. {
  150. e->Delete();
  151. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  152. return S_FALSE;
  153. }
  154. }
  155. STDMETHODIMP
  156. CComponent::Initialize(
  157. LPCONSOLE lpConsole
  158. )
  159. {
  160. HRESULT hr;
  161. if (!lpConsole)
  162. {
  163. return E_INVALIDARG;
  164. }
  165. m_pConsole = lpConsole;
  166. lpConsole->AddRef();
  167. hr = lpConsole->QueryInterface(IID_IHeaderCtrl, (void**)&m_pHeader);
  168. if (SUCCEEDED(hr))
  169. {
  170. lpConsole->SetHeader(m_pHeader);
  171. hr = lpConsole->QueryInterface(IID_IResultData, (void**)&m_pResult);
  172. }
  173. if (SUCCEEDED(hr))
  174. {
  175. hr = lpConsole->QueryConsoleVerb(&m_pConsoleVerb);
  176. }
  177. if (SUCCEEDED(hr))
  178. {
  179. hr = lpConsole->QueryInterface(IID_IPropertySheetProvider,
  180. (void**)&m_pPropSheetProvider);
  181. }
  182. if (SUCCEEDED(hr))
  183. {
  184. hr = lpConsole->QueryInterface(IID_IDisplayHelp, (void**)&m_pDisplayHelp);
  185. }
  186. if (FAILED(hr))
  187. {
  188. TRACE((TEXT("CComponent::Initialize failed\n")));
  189. }
  190. return hr;
  191. }
  192. #if DBG
  193. TCHAR *mmcNotifyStr[] = {
  194. TEXT("UNKNOWN"),
  195. TEXT("ACTIVATE"),
  196. TEXT("ADD_IMAGES"),
  197. TEXT("BTN_CLICK"),
  198. TEXT("CLICK"),
  199. TEXT("COLUMN_CLICK"),
  200. TEXT("CONTEXTMENU"),
  201. TEXT("CUTORMOVE"),
  202. TEXT("DBLCLICK"),
  203. TEXT("DELETE"),
  204. TEXT("DESELECT_ALL"),
  205. TEXT("EXPAND"),
  206. TEXT("HELP"),
  207. TEXT("MENU_BTNCLICK"),
  208. TEXT("MINIMIZED"),
  209. TEXT("PASTE"),
  210. TEXT("PROPERTY_CHANGE"),
  211. TEXT("QUERY_PASTE"),
  212. TEXT("REFRESH"),
  213. TEXT("REMOVE_CHILDREN"),
  214. TEXT("RENAME"),
  215. TEXT("SELECT"),
  216. TEXT("SHOW"),
  217. TEXT("VIEW_CHANGE"),
  218. TEXT("SNAPINHELP"),
  219. TEXT("CONTEXTHELP"),
  220. TEXT("INITOCX"),
  221. TEXT("FILTER_CHANGE"),
  222. TEXT("FILTERBTN_CLICK"),
  223. TEXT("RESTORE_VIEW"),
  224. TEXT("PRINT"),
  225. TEXT("PRELOAD"),
  226. TEXT("LISTPAD"),
  227. TEXT("EXPANDSYNC")
  228. };
  229. #endif
  230. STDMETHODIMP
  231. CComponent::Notify(
  232. LPDATAOBJECT lpDataObject,
  233. MMC_NOTIFY_TYPE event,
  234. LPARAM arg,
  235. LPARAM param
  236. )
  237. {
  238. HRESULT hr;
  239. INTERNAL_DATA tID;
  240. #if DBG
  241. UINT i = event - MMCN_ACTIVATE + 1;
  242. if (event > MMCN_EXPANDSYNC || event < MMCN_ACTIVATE)
  243. {
  244. i = 0;
  245. }
  246. //TRACE((TEXT("Componet:Notify, event = %lx %s\n"), event, mmcNotifyStr[i]));
  247. #endif
  248. try
  249. {
  250. if (DOBJ_CUSTOMOCX == lpDataObject)
  251. {
  252. return OnOcxNotify(event, arg, param);
  253. }
  254. hr = ExtractData(lpDataObject, CDataObject::m_cfSnapinInternal,
  255. (PBYTE)&tID, sizeof(tID));
  256. if (SUCCEEDED(hr))
  257. {
  258. switch(event)
  259. {
  260. case MMCN_ACTIVATE:
  261. hr = OnActivate(tID.cookie, arg, param);
  262. break;
  263. case MMCN_VIEW_CHANGE:
  264. hr = OnViewChange(tID.cookie, arg, param);
  265. break;
  266. case MMCN_SHOW:
  267. hr = OnShow(tID.cookie, arg, param);
  268. break;
  269. case MMCN_CLICK:
  270. hr = OnResultItemClick(tID.cookie, arg, param);
  271. break;
  272. case MMCN_DBLCLICK:
  273. hr = OnResultItemDblClick(tID.cookie, arg, param);
  274. break;
  275. case MMCN_MINIMIZED:
  276. hr = OnMinimize(tID.cookie, arg, param);
  277. break;
  278. case MMCN_BTN_CLICK:
  279. hr = OnBtnClick(tID.cookie, arg, param);
  280. break;
  281. case MMCN_SELECT:
  282. hr = OnSelect(tID.cookie, arg, param);
  283. break;
  284. case MMCN_ADD_IMAGES:
  285. hr = OnAddImages(tID.cookie, (IImageList*)arg, param);
  286. break;
  287. case MMCN_RESTORE_VIEW:
  288. hr = OnRestoreView(tID.cookie, arg, param);
  289. break;
  290. case MMCN_CONTEXTHELP:
  291. hr = OnContextHelp(tID.cookie, arg, param);
  292. break;
  293. default:
  294. hr = S_OK;
  295. break;
  296. }
  297. }
  298. else
  299. {
  300. if (MMCN_ADD_IMAGES == event)
  301. {
  302. OnAddImages(0, (IImageList*)arg, (HSCOPEITEM)param);
  303. }
  304. }
  305. }
  306. catch (CMemoryException* e)
  307. {
  308. e->Delete();
  309. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  310. hr = E_OUTOFMEMORY;
  311. }
  312. return hr;
  313. }
  314. STDMETHODIMP
  315. CComponent::Destroy(
  316. MMC_COOKIE cookie
  317. )
  318. {
  319. //
  320. // cookie must point to the static node
  321. //
  322. ASSERT(0 == cookie);
  323. try
  324. {
  325. DetachAllFoldersFromMachine();
  326. DestroyFolderList(cookie);
  327. if (m_pToolbar)
  328. {
  329. m_pToolbar->Release();
  330. }
  331. if (m_pControlbar)
  332. {
  333. m_pControlbar->Release();
  334. }
  335. //
  336. // Release the interfaces that we QI'ed
  337. //
  338. if (m_pConsole != NULL)
  339. {
  340. //
  341. // Tell the console to release the header control interface
  342. //
  343. m_pConsole->SetHeader(NULL);
  344. m_pHeader->Release();
  345. m_pResult->Release();
  346. m_pConsoleVerb->Release();
  347. m_pDisplayHelp->Release();
  348. //
  349. // Release the IFrame interface last
  350. //
  351. m_pConsole->Release();
  352. }
  353. if (m_pPropSheetProvider)
  354. {
  355. m_pPropSheetProvider->Release();
  356. }
  357. }
  358. catch (CMemoryException* e)
  359. {
  360. e->Delete();
  361. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  362. }
  363. return S_OK;
  364. }
  365. STDMETHODIMP
  366. CComponent::QueryDataObject(
  367. MMC_COOKIE cookie,
  368. DATA_OBJECT_TYPES type,
  369. LPDATAOBJECT* ppDataObject
  370. )
  371. {
  372. try
  373. {
  374. ASSERT(m_pComponentData);
  375. //
  376. // Delegate to IComponentData
  377. //
  378. return m_pComponentData->QueryDataObject(cookie, type, ppDataObject);
  379. }
  380. catch (CMemoryException* e)
  381. {
  382. e->Delete();
  383. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  384. return E_OUTOFMEMORY;
  385. }
  386. }
  387. STDMETHODIMP
  388. CComponent::GetDisplayInfo(
  389. LPRESULTDATAITEM pResultDataItem
  390. )
  391. {
  392. try
  393. {
  394. CFolder* pFolder = FindFolder(pResultDataItem->lParam);
  395. if (pFolder)
  396. {
  397. return pFolder->GetDisplayInfo(pResultDataItem);
  398. }
  399. else
  400. {
  401. return S_OK;
  402. }
  403. }
  404. catch (CMemoryException* e)
  405. {
  406. e->Delete();
  407. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  408. return E_OUTOFMEMORY;
  409. }
  410. }
  411. STDMETHODIMP
  412. CComponent::CompareObjects(
  413. LPDATAOBJECT lpDataObjectA,
  414. LPDATAOBJECT lpDataObjectB
  415. )
  416. {
  417. try
  418. {
  419. ASSERT(m_pComponentData);
  420. //
  421. // Delegate to ComponentData
  422. //
  423. return m_pComponentData->CompareObjects(lpDataObjectA, lpDataObjectB);
  424. }
  425. catch (CMemoryException* e)
  426. {
  427. e->Delete();
  428. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  429. return E_OUTOFMEMORY;
  430. }
  431. }
  432. ///////////////////////////////////////////////////////////////////////////
  433. /// IResultDataCompare implementation
  434. ///
  435. // This compare is used to sort the item's in the listview.
  436. // lUserParam - user param passed in when IResultData::Sort() was called.
  437. // cookieA -- first item
  438. // cookieB -- second item
  439. // pnResult contains the column on entry. This function has the compared
  440. // result in the location pointed by this parameter.
  441. // the valid compare results are:
  442. // -1 if cookieA "<" cookieB
  443. // 0 if cookieA "==" cookieB
  444. // 1 if cookieA ">" cookieB
  445. //
  446. //
  447. STDMETHODIMP
  448. CComponent::Compare(
  449. LPARAM lUserParam,
  450. MMC_COOKIE cookieA,
  451. MMC_COOKIE cookieB,
  452. int* pnResult
  453. )
  454. {
  455. if (!pnResult)
  456. {
  457. return E_INVALIDARG;
  458. }
  459. HRESULT hr;
  460. try
  461. {
  462. int nCol = *pnResult;
  463. CFolder* pFolder = (CFolder*)lUserParam;
  464. if (pFolder)
  465. {
  466. hr = pFolder->Compare(cookieA, cookieB, nCol, pnResult);
  467. }
  468. else
  469. {
  470. hr = m_pCurFolder->Compare(cookieA, cookieB, nCol, pnResult);
  471. }
  472. }
  473. catch (CMemoryException* e)
  474. {
  475. e->Delete();
  476. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  477. hr = E_OUTOFMEMORY;
  478. }
  479. return hr;
  480. }
  481. ////////////////////////////////////////////////////////////////////////////
  482. /// Snapin's IExtendContextMenu implementation -- delegate to IComponentData
  483. ////
  484. // Note that IComponentData also has its own IExtendContextMenu
  485. // interface implementation. The difference is that
  486. // IComponentData only deals with scope items while we only
  487. // deal with result item except for cutomer view menu.
  488. //
  489. //
  490. STDMETHODIMP
  491. CComponent::AddMenuItems(
  492. LPDATAOBJECT lpDataObject,
  493. LPCONTEXTMENUCALLBACK pCallback,
  494. long* pInsertionAllowed
  495. )
  496. {
  497. HRESULT hr;
  498. INTERNAL_DATA tID;
  499. try
  500. {
  501. //
  502. // If lpDataObject is DOBJ_CUSTOMOCX then the user is viewing
  503. // the Action menu.
  504. //
  505. if (DOBJ_CUSTOMOCX == lpDataObject)
  506. {
  507. ASSERT(m_pCurFolder);
  508. hr = m_pCurFolder->m_pScopeItem->AddMenuItems(pCallback, pInsertionAllowed);
  509. }
  510. //
  511. // If we have a valid cookie then the user is using the context menu
  512. // or the View menu
  513. //
  514. else
  515. {
  516. hr = ExtractData(lpDataObject, CDataObject::m_cfSnapinInternal,
  517. reinterpret_cast<BYTE*>(&tID), sizeof(tID)
  518. );
  519. if (SUCCEEDED(hr))
  520. {
  521. ASSERT(m_pCurFolder);
  522. hr = m_pCurFolder->AddMenuItems(GetActiveCookie(tID.cookie),
  523. pCallback, pInsertionAllowed
  524. );
  525. }
  526. }
  527. }
  528. catch (CMemoryException* e)
  529. {
  530. e->Delete();
  531. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  532. hr = E_OUTOFMEMORY;
  533. }
  534. return hr;
  535. }
  536. STDMETHODIMP
  537. CComponent::Command(
  538. long nCommandID,
  539. LPDATAOBJECT lpDataObject
  540. )
  541. {
  542. INTERNAL_DATA tID;
  543. HRESULT hr;
  544. try
  545. {
  546. //
  547. // Menu item from the Action menu
  548. //
  549. if (DOBJ_CUSTOMOCX == lpDataObject)
  550. {
  551. ASSERT(m_pCurFolder);
  552. hr = m_pCurFolder->m_pScopeItem->MenuCommand(nCommandID);
  553. }
  554. //
  555. // Context menu item or View menu item
  556. //
  557. else
  558. {
  559. hr = ExtractData(lpDataObject, CDataObject::m_cfSnapinInternal,
  560. (PBYTE)&tID, sizeof(tID));
  561. if (SUCCEEDED(hr))
  562. {
  563. ASSERT(m_pCurFolder);
  564. hr = m_pCurFolder->MenuCommand(GetActiveCookie(tID.cookie), nCommandID);
  565. }
  566. }
  567. }
  568. catch (CMemoryException* e)
  569. {
  570. e->Delete();
  571. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  572. hr = E_OUTOFMEMORY;
  573. }
  574. return hr;
  575. }
  576. ///////////////////////////////////////////////////////////////////////////////
  577. // IExtendControlbar implementation
  578. //
  579. MMCBUTTON g_SnapinButtons[] =
  580. {
  581. { 0, IDM_REFRESH, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_BUTTON_REFRESH, (BSTR)IDS_TOOLTIP_REFRESH },
  582. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, NULL, NULL },
  583. { 4, IDM_UPDATEDRIVER, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_BUTTON_UPDATEDRIVER, (BSTR)IDS_TOOLTIP_UPDATEDRIVER },
  584. { 2, IDM_REMOVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_BUTTON_REMOVE, (BSTR)IDS_TOOLTIP_REMOVE },
  585. { 1, IDM_ENABLE, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_BUTTON_ENABLE, (BSTR)IDS_TOOLTIP_ENABLE },
  586. { 3, IDM_DISABLE, TBSTATE_ENABLED, TBSTYLE_BUTTON, (BSTR)IDS_BUTTON_DISABLE, (BSTR)IDS_TOOLTIP_DISABLE },
  587. };
  588. #define CBUTTONS_ARRAY ARRAYLEN(g_SnapinButtons)
  589. String* g_astrButtonStrings = NULL; // dynamic array of Strings
  590. BOOL g_bLoadedStrings = FALSE;
  591. STDMETHODIMP
  592. CComponent::SetControlbar(
  593. LPCONTROLBAR pControlbar
  594. )
  595. {
  596. if (pControlbar != NULL)
  597. {
  598. //
  599. // Hold on to the controlbar interface.
  600. //
  601. if (m_pControlbar)
  602. {
  603. m_pControlbar->Release();
  604. }
  605. m_pControlbar = pControlbar;
  606. m_pControlbar->AddRef();
  607. HRESULT hr = S_FALSE;
  608. if (!m_pToolbar)
  609. {
  610. //
  611. // Create the Toolbar
  612. //
  613. hr = m_pControlbar->Create(TOOLBAR, this,
  614. reinterpret_cast<LPUNKNOWN*>(&m_pToolbar));
  615. ASSERT(SUCCEEDED(hr));
  616. //
  617. // Add the bitmap
  618. //
  619. HBITMAP hBitmap = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_TOOLBAR));
  620. hr = m_pToolbar->AddBitmap(4, hBitmap, 16, 16, RGB(255, 0, 255));
  621. ASSERT(SUCCEEDED(hr));
  622. if (!g_bLoadedStrings)
  623. {
  624. //
  625. // Load strings
  626. //
  627. g_astrButtonStrings = new String[2*CBUTTONS_ARRAY];
  628. for (UINT i = 0; i < CBUTTONS_ARRAY; i++)
  629. {
  630. if (NULL != g_SnapinButtons[i].lpButtonText &&
  631. g_astrButtonStrings[i*2].LoadString(g_hInstance,
  632. (UINT)((ULONG_PTR)g_SnapinButtons[i].lpButtonText)))
  633. {
  634. g_SnapinButtons[i].lpButtonText =
  635. const_cast<BSTR>((LPCTSTR)(g_astrButtonStrings[i*2]));
  636. }
  637. else
  638. {
  639. g_SnapinButtons[i].lpButtonText = NULL;
  640. }
  641. if (NULL != g_SnapinButtons[i].lpTooltipText &&
  642. g_astrButtonStrings[(i*2)+1].LoadString(g_hInstance,
  643. (UINT)((ULONG_PTR)g_SnapinButtons[i].lpTooltipText)))
  644. {
  645. g_SnapinButtons[i].lpTooltipText =
  646. const_cast<BSTR>((LPCTSTR)(g_astrButtonStrings[(i*2)+1]));
  647. }
  648. else
  649. {
  650. g_SnapinButtons[i].lpTooltipText = NULL;
  651. }
  652. }
  653. g_bLoadedStrings = TRUE;
  654. }
  655. //
  656. // Add the buttons to the toolbar
  657. //
  658. hr = m_pToolbar->AddButtons(CBUTTONS_ARRAY, g_SnapinButtons);
  659. ASSERT(SUCCEEDED(hr));
  660. }
  661. }
  662. return S_OK;
  663. }
  664. STDMETHODIMP
  665. CComponent::ControlbarNotify(
  666. MMC_NOTIFY_TYPE event,
  667. LPARAM arg,
  668. LPARAM param
  669. )
  670. {
  671. switch (event)
  672. {
  673. case MMCN_BTN_CLICK:
  674. //
  675. // arg - Data object of the currently selected scope or result pane item.
  676. // param - CmdID of the button.
  677. //
  678. switch (param)
  679. {
  680. case IDM_REFRESH:
  681. case IDM_ENABLE:
  682. case IDM_REMOVE:
  683. case IDM_DISABLE:
  684. case IDM_UPDATEDRIVER:
  685. //
  686. // The arg parameter is supposed to be the data object of the
  687. // currently selected scope or result pane item, but it seems
  688. // to always passes 0xFFFFFFFF. So the ScopeItem MenuCommand is
  689. // used because it uses the selected cookie instead.
  690. //
  691. // Handle toolbar button requests.
  692. //
  693. return m_pCurFolder->m_pScopeItem->MenuCommand((LONG)param);
  694. default:
  695. break;
  696. }
  697. break;
  698. case MMCN_SELECT:
  699. //
  700. // param - Data object of the item being selected.
  701. // For select, if the cookie has toolbar items attach the toolbar.
  702. // Otherwise detach the toolbar.
  703. //
  704. HRESULT hr;
  705. if (LOWORD(arg))
  706. {
  707. //
  708. // LOWORD(arg) being set indicated this is for the scope pane item.
  709. //
  710. if (HIWORD(arg))
  711. {
  712. //
  713. // Detach the Controlbar.
  714. //
  715. hr = m_pControlbar->Detach(reinterpret_cast<LPUNKNOWN>(m_pToolbar));
  716. ASSERT(SUCCEEDED(hr));
  717. }
  718. else
  719. {
  720. //
  721. // Attach the Controlbar.
  722. //
  723. hr = m_pControlbar->Attach(TOOLBAR,
  724. reinterpret_cast<LPUNKNOWN>(m_pToolbar));
  725. ASSERT(SUCCEEDED(hr));
  726. }
  727. }
  728. break;
  729. default:
  730. break;
  731. }
  732. return S_OK;
  733. }
  734. //
  735. // This function updates the toolbar buttons based on the selected cookie type.
  736. //
  737. HRESULT
  738. CComponent::UpdateToolbar(
  739. CCookie* pCookie
  740. )
  741. {
  742. if (!m_pToolbar)
  743. {
  744. return S_OK;
  745. }
  746. //
  747. // Everything is hidden by default
  748. //
  749. BOOL fRemoveHidden = TRUE;
  750. BOOL fRefreshHidden = TRUE;
  751. BOOL fUpdateHidden = TRUE;
  752. BOOL fDisableHidden = TRUE;
  753. BOOL fEnableHidden = TRUE;
  754. switch (pCookie->GetType())
  755. {
  756. case COOKIE_TYPE_RESULTITEM_DEVICE:
  757. case COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ:
  758. case COOKIE_TYPE_RESULTITEM_RESOURCE_DMA:
  759. case COOKIE_TYPE_RESULTITEM_RESOURCE_IO:
  760. case COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY:
  761. if(m_pComponentData->m_pMachine->IsLocal() && g_HasLoadDriverNamePrivilege)
  762. {
  763. CDevice* pDevice = NULL;
  764. CClass* pClass;
  765. UINT index;
  766. if (COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType()) {
  767. pDevice = (CDevice*)pCookie->GetResultItem();
  768. } else {
  769. //
  770. // This is a resource item, get the pointer for the device
  771. // object from the resource object.
  772. //
  773. CResource* pResource = (CResource*) pCookie->GetResultItem();
  774. if (pResource) {
  775. pDevice = pResource->GetDevice();
  776. }
  777. }
  778. if (pDevice)
  779. {
  780. pClass = pDevice->GetClass();
  781. //
  782. // Device can be disabled
  783. //
  784. if (pDevice->IsDisableable()) {
  785. if (pDevice->IsStateDisabled()) {
  786. fEnableHidden = FALSE;
  787. } else {
  788. fDisableHidden = FALSE;
  789. }
  790. }
  791. //
  792. // Device cannot be disabled
  793. //
  794. else
  795. {
  796. //
  797. // Hide both the enable and disable buttons in case the
  798. // previously selected node was a device.
  799. //
  800. m_pToolbar->SetButtonState(IDM_ENABLE, HIDDEN, TRUE);
  801. m_pToolbar->SetButtonState(IDM_DISABLE, HIDDEN, TRUE);
  802. }
  803. //
  804. // Only show the uninstall button if the device can be uninstalled.
  805. //
  806. if (pDevice->IsUninstallable()) {
  807. fRemoveHidden = FALSE;
  808. }
  809. //
  810. // Display Update Driver button for everything except legacy drivers.
  811. //
  812. fUpdateHidden = IsEqualGUID(*pClass, GUID_DEVCLASS_LEGACYDRIVER) ? TRUE : FALSE;
  813. //
  814. // Display refresh (Scan...) button.
  815. //
  816. fRefreshHidden = FALSE;
  817. }
  818. break;
  819. }
  820. else
  821. {
  822. //
  823. // Must be an admin and on the local machine to remove or
  824. // enable/disable a device.
  825. //
  826. //
  827. // Fall through to hide the remove and enable/disable buttons.
  828. //
  829. }
  830. case COOKIE_TYPE_RESULTITEM_COMPUTER:
  831. case COOKIE_TYPE_RESULTITEM_CLASS:
  832. case COOKIE_TYPE_RESULTITEM_RESTYPE:
  833. //
  834. // Display refresh (enumerate) button if the user has SE_LOAD_DRIVER_NAME privileges
  835. //
  836. if (g_HasLoadDriverNamePrivilege) {
  837. fRefreshHidden = FALSE;
  838. }
  839. break;
  840. default:
  841. break;
  842. }
  843. //
  844. // Hide or show the buttons
  845. //
  846. m_pToolbar->SetButtonState(IDM_REMOVE, HIDDEN, fRemoveHidden);
  847. m_pToolbar->SetButtonState(IDM_REFRESH, HIDDEN, fRefreshHidden);
  848. m_pToolbar->SetButtonState(IDM_UPDATEDRIVER, HIDDEN, fUpdateHidden);
  849. m_pToolbar->SetButtonState(IDM_DISABLE, HIDDEN, fDisableHidden);
  850. m_pToolbar->SetButtonState(IDM_ENABLE, HIDDEN, fEnableHidden);
  851. return S_OK;
  852. }
  853. ////////////////////////////////////////////////////////////////////////////
  854. //// Snapin's IExtendPropertySheet implementation
  855. ////
  856. STDMETHODIMP
  857. CComponent::QueryPagesFor(
  858. LPDATAOBJECT lpDataObject
  859. )
  860. {
  861. HRESULT hr;
  862. if (!lpDataObject)
  863. {
  864. return E_INVALIDARG;
  865. }
  866. INTERNAL_DATA tID;
  867. try
  868. {
  869. hr = ExtractData(lpDataObject, CDataObject::m_cfSnapinInternal,
  870. reinterpret_cast<BYTE*>(&tID), sizeof(tID)
  871. );
  872. if (SUCCEEDED(hr))
  873. {
  874. ASSERT(m_pCurFolder);
  875. hr = m_pCurFolder->QueryPagesFor(GetActiveCookie(tID.cookie));
  876. }
  877. }
  878. catch (CMemoryException* e)
  879. {
  880. e->Delete();
  881. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  882. hr = S_FALSE;
  883. }
  884. return hr;
  885. }
  886. STDMETHODIMP
  887. CComponent::CreatePropertyPages(
  888. LPPROPERTYSHEETCALLBACK lpProvider,
  889. LONG_PTR handle,
  890. LPDATAOBJECT lpDataObject
  891. )
  892. {
  893. HRESULT hr;
  894. if (!lpProvider || !lpDataObject)
  895. {
  896. return E_INVALIDARG;
  897. }
  898. INTERNAL_DATA tID;
  899. try
  900. {
  901. hr = ExtractData(lpDataObject, CDataObject::m_cfSnapinInternal,
  902. reinterpret_cast<BYTE*>(&tID), sizeof(tID)
  903. );
  904. if (SUCCEEDED(hr))
  905. {
  906. ASSERT(m_pCurFolder);
  907. hr = m_pCurFolder->CreatePropertyPages(GetActiveCookie(tID.cookie),
  908. lpProvider, handle
  909. );
  910. }
  911. }
  912. catch (CMemoryException* e)
  913. {
  914. e->Delete();
  915. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  916. hr = E_OUTOFMEMORY;
  917. }
  918. return hr;
  919. }
  920. /////////////////////////////////////////////////////////////////////////////
  921. // Snapin's IPersistStream implementation
  922. STDMETHODIMP
  923. CComponent::GetClassID(
  924. CLSID* pClassID
  925. )
  926. {
  927. if(!pClassID)
  928. {
  929. return E_POINTER;
  930. }
  931. *pClassID = m_pComponentData->GetCoClassID();
  932. return S_OK;
  933. }
  934. STDMETHODIMP
  935. CComponent::IsDirty()
  936. {
  937. return m_Dirty ? S_OK : S_FALSE;
  938. }
  939. STDMETHODIMP
  940. CComponent::GetSizeMax(
  941. ULARGE_INTEGER* pcbSize
  942. )
  943. {
  944. if (!pcbSize)
  945. {
  946. return E_INVALIDARG;
  947. }
  948. // total folders folder signature
  949. int Size = sizeof(int) + m_listFolder.GetCount() * sizeof(FOLDER_SIGNATURE)
  950. + sizeof(CLSID);
  951. CFolder* pFolder;
  952. POSITION pos = m_listFolder.GetHeadPosition();
  953. while (NULL != pos)
  954. {
  955. pFolder = m_listFolder.GetNext(pos);
  956. ASSERT(pFolder);
  957. Size += pFolder->GetPersistDataSize();
  958. }
  959. ULISet32(*pcbSize, Size);
  960. return S_OK;
  961. }
  962. // save data format
  963. STDMETHODIMP
  964. CComponent::Save(
  965. IStream* pStm,
  966. BOOL fClearDirty
  967. )
  968. {
  969. HRESULT hr = S_OK;
  970. SafeInterfacePtr<IStream> StmPtr(pStm);
  971. int Count, Index;
  972. POSITION pos;
  973. CLSID clsid;
  974. try
  975. {
  976. //
  977. // write out CLSID
  978. //
  979. hr = pStm->Write(&CLSID_DEVMGR, sizeof(CLSID), NULL);
  980. if (SUCCEEDED(hr))
  981. {
  982. Count = m_listFolder.GetCount();
  983. CFolder* pFolder;
  984. //
  985. // write out folder count
  986. //
  987. hr = pStm->Write(&Count, sizeof(Count), NULL);
  988. if (SUCCEEDED(hr) && Count)
  989. {
  990. pos = m_listFolder.GetHeadPosition();
  991. while (NULL != pos)
  992. {
  993. pFolder = m_listFolder.GetNext(pos);
  994. //
  995. // write folder signature
  996. //
  997. FOLDER_SIGNATURE Signature = pFolder->GetSignature();
  998. hr = pStm->Write(&Signature, sizeof(Signature), NULL);
  999. if (SUCCEEDED(hr))
  1000. {
  1001. hr = SaveFolderPersistData(pFolder, pStm, fClearDirty);
  1002. }
  1003. if (FAILED(hr))
  1004. {
  1005. break;
  1006. }
  1007. }
  1008. }
  1009. }
  1010. }
  1011. catch (CMemoryException* e)
  1012. {
  1013. e->Delete();
  1014. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  1015. hr = E_OUTOFMEMORY;
  1016. }
  1017. if (fClearDirty)
  1018. {
  1019. m_Dirty = FALSE;
  1020. }
  1021. return hr;
  1022. }
  1023. STDMETHODIMP
  1024. CComponent::Load(
  1025. IStream* pStm
  1026. )
  1027. {
  1028. HRESULT hr = S_OK;
  1029. CLSID clsid;
  1030. SafeInterfacePtr<IStream> StmPtr(pStm);
  1031. ASSERT(pStm);
  1032. //
  1033. // Read the clsid
  1034. //
  1035. try
  1036. {
  1037. hr = pStm->Read(&clsid, sizeof(clsid), NULL);
  1038. if (SUCCEEDED(hr) && clsid == CLSID_DEVMGR)
  1039. {
  1040. CFolder* pFolder;
  1041. int FolderCount;
  1042. //
  1043. // Folder list must be create before Load.
  1044. // DO NOT rely on that IComponent::Initialize comes before IStream::Load
  1045. //
  1046. ASSERT(m_listFolder.GetCount());
  1047. //
  1048. // Load folder count
  1049. //
  1050. hr = pStm->Read(&FolderCount, sizeof(FolderCount), NULL);
  1051. if (SUCCEEDED(hr))
  1052. {
  1053. ASSERT(m_listFolder.GetCount() == FolderCount);
  1054. //
  1055. // Get folder signature
  1056. // go through every folder
  1057. //
  1058. for (int i = 0; i < FolderCount; i++)
  1059. {
  1060. FOLDER_SIGNATURE Signature;
  1061. hr = pStm->Read(&Signature, sizeof(Signature), NULL);
  1062. if (SUCCEEDED(hr))
  1063. {
  1064. POSITION pos;
  1065. pos = m_listFolder.GetHeadPosition();
  1066. while (NULL != pos)
  1067. {
  1068. pFolder = m_listFolder.GetNext(pos);
  1069. if (pFolder->GetSignature() == Signature)
  1070. {
  1071. hr = LoadFolderPersistData(pFolder, pStm);
  1072. break;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. }
  1078. }
  1079. }
  1080. catch (CMemoryException* e)
  1081. {
  1082. e->Delete();
  1083. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  1084. hr = E_OUTOFMEMORY;
  1085. }
  1086. m_Dirty = FALSE;
  1087. return hr;
  1088. }
  1089. HRESULT
  1090. CComponent::SaveFolderPersistData(
  1091. CFolder* pFolder,
  1092. IStream* pStm,
  1093. BOOL fClearDirty
  1094. )
  1095. {
  1096. HRESULT hr = S_OK;
  1097. int Size;
  1098. SafeInterfacePtr<IStream> StmPtr(pStm);
  1099. try
  1100. {
  1101. Size = pFolder->GetPersistDataSize();
  1102. //
  1103. // Always write the length even though it can be 0.
  1104. //
  1105. hr = pStm->Write(&Size, sizeof(Size), NULL);
  1106. if (SUCCEEDED(hr) && Size)
  1107. {
  1108. BufferPtr<BYTE> Buffer(Size);
  1109. pFolder->GetPersistData(Buffer, Size);
  1110. hr = pStm->Write(Buffer, Size, NULL);
  1111. }
  1112. }
  1113. catch (CMemoryException* e)
  1114. {
  1115. e->Delete();
  1116. MsgBoxParam(m_pComponentData->m_hwndMain, 0, 0, 0);
  1117. hr = E_OUTOFMEMORY;
  1118. }
  1119. return hr;
  1120. }
  1121. HRESULT
  1122. CComponent::LoadFolderPersistData(
  1123. CFolder* pFolder,
  1124. IStream* pStm
  1125. )
  1126. {
  1127. HRESULT hr = S_OK;
  1128. SafeInterfacePtr<IStream> StmPtr(pStm);
  1129. int Size = 0;
  1130. hr = pStm->Read(&Size, sizeof(Size), NULL);
  1131. if (SUCCEEDED(hr) && Size)
  1132. {
  1133. BufferPtr<BYTE> Buffer(Size);
  1134. hr = pStm->Read(Buffer, Size, NULL);
  1135. if (SUCCEEDED(hr))
  1136. {
  1137. hr = pFolder->SetPersistData(Buffer, Size);
  1138. }
  1139. }
  1140. return hr;
  1141. }
  1142. //
  1143. // This function attaches the given folder the the machine created
  1144. // by the component data. The machine notifies every attached folder
  1145. // when there are state changes in the machine.
  1146. //
  1147. // INPUT:
  1148. // pFolder -- the folder to be attached
  1149. // ppMachind -- to receive a pointer to the machine
  1150. // OUTPUT:
  1151. // TRUE if the folder is attached successfully.
  1152. // FALSE if the attachment failed.
  1153. //
  1154. //
  1155. BOOL
  1156. CComponent::AttachFolderToMachine(
  1157. CFolder* pFolder,
  1158. CMachine** ppMachine
  1159. )
  1160. {
  1161. if (!pFolder)
  1162. {
  1163. SetLastError(ERROR_INVALID_PARAMETER);
  1164. return FALSE;
  1165. }
  1166. // Initialize the machine.
  1167. if (m_pComponentData->InitializeMachine())
  1168. {
  1169. *ppMachine = m_pComponentData->m_pMachine;
  1170. (*ppMachine)->AttachFolder(pFolder);
  1171. return TRUE;
  1172. }
  1173. return FALSE;
  1174. }
  1175. //
  1176. // This function detaches all the component's folders from the machine
  1177. //
  1178. void
  1179. CComponent::DetachAllFoldersFromMachine()
  1180. {
  1181. if (m_pComponentData->m_pMachine)
  1182. {
  1183. CMachine* pMachine = m_pComponentData->m_pMachine;
  1184. CFolder* pFolder;
  1185. POSITION pos = m_listFolder.GetHeadPosition();
  1186. while (NULL != pos)
  1187. {
  1188. pFolder = m_listFolder.GetNext(pos);
  1189. pMachine->DetachFolder(pFolder);
  1190. }
  1191. }
  1192. }
  1193. HRESULT
  1194. CComponent::CreateFolderList(
  1195. CCookie* pCookie
  1196. )
  1197. {
  1198. CCookie* pCookieChild;
  1199. CScopeItem* pScopeItem;
  1200. CFolder* pFolder;
  1201. ASSERT(pCookie);
  1202. HRESULT hr = S_OK;
  1203. do
  1204. {
  1205. pScopeItem = pCookie->GetScopeItem();
  1206. ASSERT(pScopeItem);
  1207. pFolder = pScopeItem->CreateFolder(this);
  1208. if (pFolder)
  1209. {
  1210. m_listFolder.AddTail(pFolder);
  1211. pFolder->AddRef();
  1212. pCookieChild = pCookie->GetChild();
  1213. if (pCookieChild)
  1214. {
  1215. hr = CreateFolderList(pCookieChild);
  1216. }
  1217. pCookie = pCookie->GetSibling();
  1218. }
  1219. else
  1220. {
  1221. hr = E_OUTOFMEMORY;
  1222. }
  1223. } while (SUCCEEDED(hr) && pCookie);
  1224. return hr;
  1225. }
  1226. BOOL
  1227. CComponent::DestroyFolderList(
  1228. MMC_COOKIE cookie
  1229. )
  1230. {
  1231. if (!m_listFolder.IsEmpty())
  1232. {
  1233. POSITION pos = m_listFolder.GetHeadPosition();
  1234. while (NULL != pos)
  1235. {
  1236. CFolder* pFolder = m_listFolder.GetNext(pos);
  1237. //
  1238. // DONOT delete it!!!!!!!
  1239. //
  1240. pFolder->Release();
  1241. }
  1242. m_listFolder.RemoveAll();
  1243. }
  1244. return TRUE;
  1245. }
  1246. CFolder*
  1247. CComponent::FindFolder(
  1248. MMC_COOKIE cookie
  1249. )
  1250. {
  1251. CCookie* pCookie = GetActiveCookie(cookie);
  1252. CFolder* pFolder;
  1253. POSITION pos = m_listFolder.GetHeadPosition();
  1254. while (NULL != pos)
  1255. {
  1256. pFolder = m_listFolder.GetNext(pos);
  1257. if (pCookie->GetScopeItem() == pFolder->m_pScopeItem)
  1258. {
  1259. return pFolder;
  1260. }
  1261. }
  1262. return NULL;
  1263. }
  1264. int
  1265. CComponent::MessageBox(
  1266. LPCTSTR Msg,
  1267. LPCTSTR Caption,
  1268. DWORD Flags
  1269. )
  1270. {
  1271. int Result;
  1272. ASSERT(m_pConsole);
  1273. if (SUCCEEDED(m_pConsole->MessageBox(Msg, Caption, Flags, &Result)))
  1274. {
  1275. return Result;
  1276. }
  1277. else
  1278. {
  1279. return IDCANCEL;
  1280. }
  1281. }