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.

1541 lines
36 KiB

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