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.

3624 lines
110 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation
  3. Module Name:
  4. cfolder.cpp
  5. Abstract:
  6. This module implements CFolder and its releated classes.
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "devmgr.h"
  12. #include "clsgenpg.h"
  13. #include "devgenpg.h"
  14. #include "devdrvpg.h"
  15. #include "devpopg.h"
  16. #include "devdetpg.h"
  17. #include "hwprof.h"
  18. #include "devrmdlg.h"
  19. #include "printer.h"
  20. #include <devguid.h>
  21. #include <initguid.h>
  22. #include <oleacc.h>
  23. const TCHAR* OCX_TREEVIEW = TEXT("{CD6C7868-5864-11D0-ABF0-0020AF6B0B7A}");
  24. const MMCMENUITEM ViewDevicesMenuItems[TOTAL_VIEWS] =
  25. {
  26. {IDS_VIEW_DEVICESBYTYPE, IDS_MENU_STATUS_DEVBYTYPE, IDM_VIEW_DEVICESBYTYPE, VIEW_DEVICESBYTYPE},
  27. {IDS_VIEW_DEVICESBYCONNECTION, IDS_MENU_STATUS_DEVBYCONNECTION, IDM_VIEW_DEVICESBYCONNECTION, VIEW_DEVICESBYCONNECTION},
  28. {IDS_VIEW_RESOURCESBYTYPE, IDS_MENU_STATUS_RESBYTYPE, IDM_VIEW_RESOURCESBYTYPE, VIEW_RESOURCESBYTYPE},
  29. {IDS_VIEW_RESOURCESBYCONNECTION, IDS_MENU_STATUS_RESBYCONNECTION, IDM_VIEW_RESOURCESBYCONNECTION, VIEW_RESOURCESBYCONNECTION}
  30. };
  31. const RESOURCEID ResourceTypes[TOTAL_RESOURCE_TYPES] =
  32. {
  33. ResType_Mem,
  34. ResType_IO,
  35. ResType_DMA,
  36. ResType_IRQ
  37. };
  38. ///////////////////////////////////////////////////////////////////
  39. /// CScopeItem implementations
  40. ///
  41. BOOL
  42. CScopeItem::Create()
  43. {
  44. m_strName.LoadString(g_hInstance, m_iNameStringId);
  45. m_strDesc.LoadString(g_hInstance, m_iDescStringId);
  46. return TRUE;
  47. }
  48. HRESULT
  49. CScopeItem::GetDisplayInfo(
  50. LPSCOPEDATAITEM pScopeDataItem
  51. )
  52. {
  53. if (!pScopeDataItem) {
  54. return E_INVALIDARG;
  55. }
  56. if (SDI_STR & pScopeDataItem->mask) {
  57. pScopeDataItem->displayname = (LPTSTR)(LPCTSTR)m_strName;
  58. }
  59. if (SDI_IMAGE & pScopeDataItem->mask) {
  60. pScopeDataItem->nImage = m_iImage;
  61. }
  62. if (SDI_OPENIMAGE & pScopeDataItem->mask) {
  63. pScopeDataItem->nOpenImage = m_iOpenImage;
  64. }
  65. return S_OK;
  66. }
  67. BOOL
  68. CScopeItem::EnumerateChildren(
  69. int Index,
  70. CScopeItem** ppScopeItem
  71. )
  72. {
  73. if (!ppScopeItem || Index >= m_listChildren.GetCount()) {
  74. return FALSE;
  75. }
  76. POSITION pos = m_listChildren.FindIndex(Index);
  77. *ppScopeItem = m_listChildren.GetAt(pos);
  78. return TRUE;
  79. }
  80. HRESULT
  81. CScopeItem::Reset()
  82. {
  83. //
  84. // We have not enumerated!
  85. //
  86. m_Enumerated = FALSE;
  87. //
  88. // If there are folders created from this scope item,
  89. // walk through all of them and tell each one
  90. // to reset the cached machine object
  91. //
  92. HRESULT hr = S_OK;
  93. if (!m_listFolder.IsEmpty()) {
  94. CFolder* pFolder;
  95. POSITION pos = m_listFolder.GetHeadPosition();
  96. while (NULL != pos) {
  97. pFolder = m_listFolder.GetNext(pos);
  98. hr = pFolder->Reset();
  99. }
  100. }
  101. return hr;
  102. }
  103. CCookie*
  104. CScopeItem::FindSelectedCookieData(
  105. CResultView** ppResultView
  106. )
  107. {
  108. CFolder* pFolder;
  109. CResultView* pResultView;
  110. //
  111. // This routine returns the Selected Cookie in the result view if it has
  112. // the focus. This is done by locating the folder from the scopeitem.
  113. // If the folder is not selected, the current result view is accessed to
  114. // get the current selected cookie. If any of these fail a NULL value is
  115. // returned. Optionally the current CResultView class is returned.
  116. //
  117. POSITION pos = m_listFolder.GetHeadPosition();
  118. while (NULL != pos) {
  119. pFolder = m_listFolder.GetNext(pos);
  120. if (this == pFolder->m_pScopeItem) {
  121. if (!pFolder->m_bSelect &&
  122. (pResultView = pFolder->GetCurResultView()) != NULL) {
  123. if (ppResultView) {
  124. *ppResultView = pResultView;
  125. }
  126. return pResultView->GetSelectedCookie();
  127. }
  128. }
  129. }
  130. return NULL;
  131. }
  132. CScopeItem::~CScopeItem()
  133. {
  134. if (!m_listChildren.IsEmpty()) {
  135. CScopeItem* pChild;
  136. POSITION pos;
  137. pos = m_listChildren.GetHeadPosition();
  138. while (NULL != pos) {
  139. pChild = m_listChildren.GetNext(pos);
  140. delete pChild;
  141. }
  142. m_listChildren.RemoveAll();
  143. }
  144. if (!m_listFolder.IsEmpty()) {
  145. POSITION pos;
  146. pos = m_listFolder.GetHeadPosition();
  147. while (NULL != pos) {
  148. //
  149. // DO NOT delete it!!!!
  150. //
  151. (m_listFolder.GetNext(pos))->Release();
  152. }
  153. m_listFolder.RemoveAll();
  154. }
  155. }
  156. CFolder*
  157. CScopeItem::CreateFolder(
  158. CComponent* pComponent
  159. )
  160. {
  161. ASSERT(pComponent);
  162. CFolder* pFolder;
  163. pFolder = new CFolder(this, pComponent);
  164. if (pFolder) {
  165. m_listFolder.AddTail(pFolder);
  166. pFolder->AddRef();
  167. }
  168. else {
  169. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  170. }
  171. return pFolder;
  172. }
  173. HRESULT
  174. CScopeItem::AddMenuItems(
  175. LPCONTEXTMENUCALLBACK pCallback,
  176. long* pInsertionAllowed
  177. )
  178. {
  179. CCookie* pSelectedCookie;
  180. CResultView* pResultView;
  181. if ((pSelectedCookie = FindSelectedCookieData(&pResultView)) != NULL) {
  182. //
  183. // Add menu items for the Action menu.
  184. //
  185. return pResultView->AddMenuItems(pSelectedCookie, pCallback,
  186. pInsertionAllowed, FALSE);
  187. }
  188. else {
  189. return S_OK;
  190. }
  191. }
  192. HRESULT
  193. CScopeItem::MenuCommand(
  194. long lCommandId
  195. )
  196. {
  197. CCookie* pSelectedCookie;
  198. CResultView* pResultView;
  199. if ((pSelectedCookie = FindSelectedCookieData(&pResultView)) != NULL) {
  200. //
  201. // Handle menu requests for the Action menu.
  202. //
  203. return pResultView->MenuCommand(pSelectedCookie, lCommandId);
  204. }
  205. else {
  206. return S_OK;
  207. }
  208. }
  209. HRESULT
  210. CScopeItem::QueryPagesFor()
  211. {
  212. //
  213. // We do not have property pages for scope item
  214. //
  215. CCookie* pSelectedCookie;
  216. if ((pSelectedCookie = FindSelectedCookieData(NULL)) != NULL) {
  217. return S_OK;
  218. }
  219. else {
  220. return S_FALSE;
  221. }
  222. }
  223. HRESULT
  224. CScopeItem::CreatePropertyPages(
  225. LPPROPERTYSHEETCALLBACK lpProvider,
  226. LONG_PTR handle
  227. )
  228. {
  229. CCookie* pSelectedCookie;
  230. CResultView* pResultView;
  231. if ((pSelectedCookie = FindSelectedCookieData(&pResultView)) != NULL) {
  232. return pResultView->CreatePropertyPages(pSelectedCookie, lpProvider, handle);
  233. }
  234. else {
  235. return S_OK;
  236. }
  237. }
  238. ///////////////////////////////////////////////////////////////////
  239. /// CFolder implementations
  240. ///
  241. CFolder::CFolder(
  242. CScopeItem* pScopeItem,
  243. CComponent* pComponent
  244. )
  245. {
  246. ASSERT(pScopeItem && pComponent);
  247. m_pScopeItem = pScopeItem;
  248. m_pComponent = pComponent;
  249. m_Show = FALSE;
  250. m_pMachine = NULL;
  251. m_bSelect = FALSE;
  252. m_pOleTaskString = NULL;
  253. m_Ref = 0;
  254. m_FirstTimeOnShow = TRUE;
  255. m_Signature = FOLDER_SIGNATURE_DEVMGR;
  256. m_pViewTreeByType = NULL;
  257. m_pViewTreeByConnection = NULL;
  258. m_pViewResourcesByType = NULL;
  259. m_pViewResourcesByConnection = NULL;
  260. m_CurViewType = VIEW_DEVICESBYTYPE;
  261. m_pCurView = m_pViewTreeByType;
  262. m_ShowHiddenDevices = FALSE;
  263. }
  264. CFolder::~CFolder()
  265. {
  266. if (m_pViewTreeByType) {
  267. delete m_pViewTreeByType;
  268. }
  269. if (m_pViewTreeByConnection) {
  270. delete m_pViewTreeByConnection;
  271. }
  272. if (m_pViewResourcesByType) {
  273. delete m_pViewResourcesByType;
  274. }
  275. if (m_pViewResourcesByConnection) {
  276. delete m_pViewResourcesByConnection;
  277. }
  278. }
  279. HRESULT
  280. CFolder::Compare(
  281. MMC_COOKIE cookieA,
  282. MMC_COOKIE cookieB,
  283. int nCol,
  284. int* pnResult
  285. )
  286. {
  287. UNREFERENCED_PARAMETER(cookieA);
  288. UNREFERENCED_PARAMETER(cookieB);
  289. UNREFERENCED_PARAMETER(nCol);
  290. ASSERT(pnResult);
  291. //
  292. // We do not have anything in the result pane, thus
  293. // comparision makes no sense.
  294. //
  295. *pnResult = 0;
  296. return S_OK;
  297. }
  298. HRESULT
  299. CFolder::GetDisplayInfo(
  300. LPRESULTDATAITEM pResultDataItem
  301. )
  302. {
  303. if (!pResultDataItem) {
  304. return E_POINTER;
  305. }
  306. ASSERT(m_pScopeItem);
  307. //
  308. // This only take care of scope pane item (displaying scope pane node
  309. // on the result pane). The derived classes should take care of
  310. // result items.
  311. //
  312. if (RDI_STR & pResultDataItem->mask) {
  313. if (0 == pResultDataItem->nCol) {
  314. if (m_pOleTaskString)
  315. FreeOleTaskString(m_pOleTaskString);
  316. m_pOleTaskString = AllocOleTaskString(m_pScopeItem->GetNameString());
  317. if (m_pOleTaskString) {
  318. pResultDataItem->str = m_pOleTaskString;
  319. }
  320. else {
  321. m_strScratch = m_pScopeItem->GetNameString();
  322. pResultDataItem->str = (LPTSTR)(LPCTSTR)m_strScratch;
  323. }
  324. }
  325. else if (2 == pResultDataItem->nCol) {
  326. if (m_pOleTaskString) {
  327. FreeOleTaskString(m_pOleTaskString);
  328. }
  329. m_pOleTaskString = AllocOleTaskString(m_pScopeItem->GetDescString());
  330. if (m_pOleTaskString) {
  331. pResultDataItem->str = m_pOleTaskString;
  332. }
  333. else {
  334. m_strScratch = m_pScopeItem->GetDescString();
  335. pResultDataItem->str = (LPTSTR)(LPCTSTR)m_strScratch;
  336. }
  337. }
  338. else {
  339. return S_FALSE;
  340. }
  341. }
  342. if (RDI_IMAGE & pResultDataItem->mask) {
  343. pResultDataItem->nImage = m_pScopeItem->GetImageIndex();
  344. }
  345. return S_OK;
  346. }
  347. HRESULT
  348. CFolder::AddMenuItems(
  349. CCookie* pCookie,
  350. LPCONTEXTMENUCALLBACK pCallback,
  351. long* pInsertionAllowed
  352. )
  353. {
  354. ASSERT(pCookie);
  355. HRESULT hr = S_OK;
  356. //
  357. // If the cookie points to a scope item, add view menu items
  358. //
  359. if (NULL == pCookie->GetResultItem()) {
  360. ASSERT(m_pScopeItem == pCookie->GetScopeItem());
  361. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) {
  362. long Flags;
  363. for (int i = 0; i < TOTAL_VIEWS; i++) {
  364. if (m_CurViewType == ViewDevicesMenuItems[i].Type) {
  365. Flags = MF_ENABLED | MF_CHECKED | MFT_RADIOCHECK;
  366. }
  367. else {
  368. Flags = MF_ENABLED;
  369. }
  370. hr = AddMenuItem(pCallback,
  371. ViewDevicesMenuItems[i].idName,
  372. ViewDevicesMenuItems[i].idStatusBar,
  373. ViewDevicesMenuItems[i].lCommandId,
  374. CCM_INSERTIONPOINTID_PRIMARY_VIEW,
  375. Flags,
  376. 0);
  377. if (FAILED(hr)) {
  378. break;
  379. }
  380. }
  381. //
  382. // Add "Show hidden devices" menu item
  383. //
  384. if (SUCCEEDED(hr)) {
  385. hr = AddMenuItem(pCallback, 0, 0, 0, CCM_INSERTIONPOINTID_PRIMARY_VIEW,
  386. MF_ENABLED, CCM_SPECIAL_SEPARATOR);
  387. if (SUCCEEDED(hr)) {
  388. if (m_ShowHiddenDevices) {
  389. Flags = MF_ENABLED | MF_CHECKED;
  390. }
  391. else {
  392. Flags = MF_ENABLED;
  393. }
  394. hr = AddMenuItem(pCallback, IDS_SHOW_ALL, IDS_MENU_STATUS_HIDDEN_DEVICES, IDM_SHOW_ALL,
  395. CCM_INSERTIONPOINTID_PRIMARY_VIEW, Flags, 0);
  396. }
  397. }
  398. }
  399. }
  400. else {
  401. if (m_pCurView) {
  402. //
  403. // Add menu items for the Context menu in the result pane.
  404. //
  405. hr = m_pCurView->AddMenuItems(pCookie, pCallback,
  406. pInsertionAllowed, TRUE);
  407. }
  408. else {
  409. hr = S_OK;
  410. }
  411. }
  412. return hr;
  413. }
  414. HRESULT
  415. CFolder::MenuCommand(
  416. CCookie* pCookie,
  417. long lCommandId
  418. )
  419. {
  420. if (NULL == pCookie->GetResultItem()) {
  421. ASSERT(m_pScopeItem == pCookie->GetScopeItem());
  422. //
  423. // Convert menu id to view type;
  424. //
  425. VIEWTYPE ViewType = m_CurViewType;
  426. BOOL fShowHiddenDevices = m_ShowHiddenDevices;
  427. switch (lCommandId) {
  428. case IDM_VIEW_DEVICESBYTYPE:
  429. ViewType = VIEW_DEVICESBYTYPE;
  430. break;
  431. case IDM_VIEW_DEVICESBYCONNECTION:
  432. ViewType = VIEW_DEVICESBYCONNECTION;
  433. break;
  434. case IDM_VIEW_RESOURCESBYTYPE:
  435. ViewType = VIEW_RESOURCESBYTYPE;
  436. break;
  437. case IDM_VIEW_RESOURCESBYCONNECTION:
  438. ViewType = VIEW_RESOURCESBYCONNECTION;
  439. break;
  440. case IDM_SHOW_ALL:
  441. fShowHiddenDevices = !fShowHiddenDevices;
  442. break;
  443. default:
  444. //not view menu. do nothing
  445. return S_OK;
  446. break;
  447. }
  448. if (!SelectView(ViewType, fShowHiddenDevices)) {
  449. return HRESULT_FROM_WIN32(GetLastError());
  450. }
  451. //
  452. // Reselect the scopeitem
  453. //
  454. return m_pComponent->m_pConsole->SelectScopeItem(*m_pScopeItem);
  455. }
  456. else {
  457. if (m_pCurView) {
  458. //
  459. // Handle menu requests for the Context menu in the result pane.
  460. //
  461. return m_pCurView->MenuCommand(pCookie, lCommandId);
  462. }
  463. else {
  464. return S_OK;
  465. }
  466. }
  467. }
  468. HRESULT
  469. CFolder::QueryPagesFor(
  470. CCookie* pCookie
  471. )
  472. {
  473. //
  474. // We do not have property pages for scope item
  475. //
  476. if (NULL == pCookie->GetResultItem()) {
  477. ASSERT(m_pScopeItem == pCookie->GetScopeItem());
  478. return S_FALSE;
  479. }
  480. //
  481. // The cookie points to result item, let the current
  482. // view handle it
  483. //
  484. if (m_pCurView) {
  485. return m_pCurView->QueryPagesFor(pCookie);
  486. }
  487. else {
  488. return S_FALSE;
  489. }
  490. }
  491. HRESULT
  492. CFolder::CreatePropertyPages(
  493. CCookie* pCookie,
  494. LPPROPERTYSHEETCALLBACK lpProvider,
  495. LONG_PTR handle
  496. )
  497. {
  498. if (NULL == pCookie->GetResultItem()) {
  499. ASSERT(m_pScopeItem == pCookie->GetScopeItem());
  500. return S_OK;
  501. }
  502. if (m_pCurView) {
  503. return m_pCurView->CreatePropertyPages(pCookie, lpProvider, handle);
  504. }
  505. else {
  506. return S_OK;
  507. }
  508. }
  509. BOOL
  510. CFolder::SelectView(
  511. VIEWTYPE ViewType,
  512. BOOL fShowHiddenDevices
  513. )
  514. {
  515. CResultView* pNewView;
  516. if (m_CurViewType == ViewType &&
  517. m_ShowHiddenDevices == fShowHiddenDevices &&
  518. m_pCurView) {
  519. return TRUE;
  520. }
  521. switch (ViewType) {
  522. case VIEW_DEVICESBYTYPE:
  523. if (!m_pViewTreeByType) {
  524. m_pViewTreeByType = new CViewTreeByType();
  525. if (m_pViewTreeByType) {
  526. m_pViewTreeByType->SetFolder(this);
  527. }
  528. }
  529. pNewView = m_pViewTreeByType;
  530. break;
  531. case VIEW_DEVICESBYCONNECTION:
  532. if (!m_pViewTreeByConnection) {
  533. m_pViewTreeByConnection = new CViewTreeByConnection();
  534. if (m_pViewTreeByConnection) {
  535. m_pViewTreeByConnection->SetFolder(this);
  536. }
  537. }
  538. pNewView = m_pViewTreeByConnection;
  539. break;
  540. case VIEW_RESOURCESBYTYPE:
  541. if (!m_pViewResourcesByType) {
  542. m_pViewResourcesByType = new CViewResourceTree(IDS_STATUS_RESOURCES_BYTYPE);
  543. if (m_pViewResourcesByType) {
  544. m_pViewResourcesByType->SetFolder(this);
  545. }
  546. }
  547. pNewView = m_pViewResourcesByType;
  548. break;
  549. case VIEW_RESOURCESBYCONNECTION:
  550. if (!m_pViewResourcesByConnection) {
  551. m_pViewResourcesByConnection = new CViewResourceTree(IDS_STATUS_RESOURCES_BYCONN);
  552. if (m_pViewResourcesByConnection) {
  553. m_pViewResourcesByConnection->SetFolder(this);
  554. }
  555. }
  556. pNewView = m_pViewResourcesByConnection;
  557. break;
  558. default:
  559. pNewView = NULL;
  560. break;
  561. }
  562. if (pNewView) {
  563. //
  564. // Let the view know that it is being diselected.
  565. //
  566. if (m_pCurView) {
  567. if (m_CurViewType != ViewType) {
  568. m_pComponent->SetDirty();
  569. }
  570. }
  571. //
  572. // Let the new active view know that it is being selected.
  573. //
  574. m_pCurView = pNewView;
  575. m_CurViewType = ViewType;
  576. m_ShowHiddenDevices = fShowHiddenDevices;
  577. }
  578. return TRUE;
  579. }
  580. HRESULT
  581. CFolder::OnShow(
  582. BOOL fShow
  583. )
  584. {
  585. if (fShow && !m_pMachine) {
  586. ASSERT(m_pComponent);
  587. if (!m_pComponent->AttachFolderToMachine(this, &m_pMachine)) {
  588. return HRESULT_FROM_WIN32(GetLastError());
  589. }
  590. }
  591. m_Show = fShow;
  592. if (m_pMachine) {
  593. if (!SelectView(m_CurViewType, m_ShowHiddenDevices)) {
  594. return E_UNEXPECTED;
  595. }
  596. if (m_pCurView) {
  597. if (m_FirstTimeOnShow && m_Show) {
  598. int ReturnValue;
  599. //
  600. // Subsequent calls are not the first time anymore.
  601. //
  602. m_FirstTimeOnShow = FALSE;
  603. //
  604. // This is the first time we show the folder.
  605. // Put up a message box to warn user if
  606. // (1) The machine is a remote machine or
  607. // (2) The user does not have the Adminstator privilege.
  608. // (3) We can not connect to the remote machine
  609. //
  610. ASSERT(m_pComponent && m_pComponent->m_pConsole);
  611. //
  612. // Connect to a remote machine
  613. //
  614. if (!m_pMachine->IsLocal()) {
  615. if (!VerifyMachineName(m_pMachine->GetRemoteMachineFullName())) {
  616. //
  617. // Display a warning if we cannot connect to the remote machine
  618. //
  619. String strWarningFormat;
  620. String strWarningMsg;
  621. LPVOID lpLastError = NULL;
  622. if (strWarningFormat.LoadString(g_hInstance, IDS_INVALID_COMPUTER_NAME) &&
  623. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  624. FORMAT_MESSAGE_FROM_SYSTEM |
  625. FORMAT_MESSAGE_IGNORE_INSERTS,
  626. NULL,
  627. GetLastError(),
  628. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  629. (LPTSTR)&lpLastError,
  630. 0,
  631. NULL)) {
  632. strWarningMsg.Format((LPTSTR)strWarningFormat,
  633. m_pMachine->GetMachineDisplayName(),
  634. lpLastError);
  635. m_pComponent->m_pConsole->MessageBox((LPTSTR)strWarningMsg,
  636. (LPCTSTR)g_strDevMgr,
  637. MB_ICONERROR | MB_OK,
  638. &ReturnValue);
  639. }
  640. if (lpLastError) {
  641. LocalFree(lpLastError);
  642. }
  643. } else {
  644. //
  645. // Otherwise display a warning that we are connect to a remote machine and
  646. // device manager will run in a neutered mode.
  647. //
  648. String strMsg;
  649. String strWarningMsg;
  650. if (strMsg.LoadString(g_hInstance, IDS_REMOTE_WARNING2) &&
  651. strWarningMsg.LoadString(g_hInstance, IDS_REMOTE_WARNING1)) {
  652. strWarningMsg += strMsg;
  653. m_pComponent->m_pConsole->MessageBox((LPCTSTR)strWarningMsg,
  654. (LPCTSTR)g_strDevMgr,
  655. MB_ICONEXCLAMATION | MB_OK,
  656. &ReturnValue);
  657. }
  658. }
  659. } else if (!g_IsAdmin) {
  660. //
  661. // If we are running locally but the user does not have
  662. // sufficient privileges then tell the user we will run
  663. // in read-only mode.
  664. //
  665. String strWarningMsg;
  666. strWarningMsg.LoadString(g_hInstance, IDS_NOADMIN_WARNING);
  667. m_pComponent->m_pConsole->MessageBox(strWarningMsg,
  668. (LPCTSTR)g_strDevMgr,
  669. MB_ICONEXCLAMATION | MB_OK,
  670. &ReturnValue);
  671. }
  672. }
  673. return m_pCurView->OnShow(fShow);
  674. }
  675. }
  676. return S_OK;
  677. }
  678. HRESULT
  679. CFolder::OnRestoreView(
  680. BOOL* pfHandled
  681. )
  682. {
  683. ASSERT(pfHandled);
  684. if (!pfHandled) {
  685. return E_INVALIDARG;
  686. }
  687. HRESULT hr = OnShow(TRUE);
  688. if (SUCCEEDED(hr)) {
  689. *pfHandled = TRUE;
  690. }
  691. return hr;
  692. }
  693. HRESULT
  694. CFolder::GetResultViewType(
  695. LPOLESTR* ppViewType,
  696. long* pViewOptions
  697. )
  698. {
  699. ASSERT(pViewOptions);
  700. if (!SelectView(m_CurViewType, m_ShowHiddenDevices)) {
  701. return E_UNEXPECTED;
  702. }
  703. if (m_pCurView) {
  704. return m_pCurView->GetResultViewType(ppViewType, pViewOptions);
  705. }
  706. *pViewOptions = MMC_VIEW_OPTIONS_NONE;
  707. return S_FALSE;
  708. }
  709. HRESULT
  710. CFolder::Reset()
  711. {
  712. //
  713. // Delete all views so that we will create new ones
  714. // when OnShow is called.
  715. //
  716. if (m_pViewTreeByType) {
  717. delete m_pViewTreeByType;
  718. m_pViewTreeByType = NULL;
  719. }
  720. if (m_pViewTreeByConnection) {
  721. delete m_pViewTreeByConnection;
  722. m_pViewTreeByConnection = NULL;
  723. }
  724. if (m_pViewResourcesByType) {
  725. delete m_pViewResourcesByType;
  726. m_pViewResourcesByType = NULL;
  727. }
  728. if (m_pViewResourcesByConnection) {
  729. delete m_pViewResourcesByConnection;
  730. m_pViewResourcesByConnection = NULL;
  731. }
  732. m_pCurView = NULL;
  733. m_FirstTimeOnShow = TRUE;
  734. m_pMachine = NULL;
  735. return S_OK;
  736. }
  737. HRESULT
  738. CFolder::MachinePropertyChanged(
  739. CMachine* pMachine
  740. )
  741. {
  742. //
  743. // Ignore the tvNotify(SELCHANGED) messages while the tree is changed.
  744. //
  745. if (m_pCurView) {
  746. m_pCurView->SetSelectOk(FALSE);
  747. }
  748. if (pMachine) {
  749. m_pMachine = pMachine;
  750. }
  751. if (m_pViewTreeByType) {
  752. m_pViewTreeByType->MachinePropertyChanged(pMachine);
  753. }
  754. if (m_pViewTreeByConnection) {
  755. m_pViewTreeByConnection->MachinePropertyChanged(pMachine);
  756. }
  757. if (m_pViewResourcesByType) {
  758. m_pViewResourcesByType->MachinePropertyChanged(pMachine);
  759. }
  760. if (m_pViewResourcesByConnection) {
  761. m_pViewResourcesByConnection->MachinePropertyChanged(pMachine);
  762. }
  763. if (m_pCurView) {
  764. m_pCurView->SetSelectOk(TRUE);
  765. }
  766. if (m_Show && pMachine) {
  767. OnShow(TRUE);
  768. }
  769. return S_OK;
  770. }
  771. HRESULT
  772. CFolder::GetPersistData(
  773. PBYTE pBuffer,
  774. int BufferSize
  775. )
  776. {
  777. DEVMGRFOLDER_STATES states;
  778. states.Type = COOKIE_TYPE_SCOPEITEM_DEVMGR;
  779. states.CurViewType = m_CurViewType;
  780. states.ShowHiddenDevices = m_ShowHiddenDevices;
  781. if (BufferSize && !pBuffer) {
  782. return E_INVALIDARG;
  783. }
  784. if (BufferSize >= sizeof(states)) {
  785. ::memcpy(pBuffer, &states, sizeof(states));
  786. return S_OK;
  787. }
  788. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  789. }
  790. HRESULT
  791. CFolder::SetPersistData(
  792. PBYTE pData,
  793. int Size
  794. )
  795. {
  796. if (!pData) {
  797. return E_POINTER;
  798. }
  799. if (!Size) {
  800. ASSERT(FALSE);
  801. return E_INVALIDARG;
  802. }
  803. PDEVMGRFOLDER_STATES pStates = (PDEVMGRFOLDER_STATES)pData;
  804. if (COOKIE_TYPE_SCOPEITEM_DEVMGR == pStates->Type) {
  805. if ((VIEW_DEVICESBYTYPE == pStates->CurViewType) ||
  806. (VIEW_DEVICESBYCONNECTION == pStates->CurViewType) ||
  807. (VIEW_RESOURCESBYTYPE == pStates->CurViewType) ||
  808. (VIEW_RESOURCESBYCONNECTION == pStates->CurViewType)) {
  809. m_CurViewType = pStates->CurViewType;
  810. if (m_pCurView) {
  811. m_pCurView->OnShow(TRUE);
  812. }
  813. m_ShowHiddenDevices = pStates->ShowHiddenDevices;
  814. return S_OK;
  815. }
  816. }
  817. return E_UNEXPECTED;
  818. }
  819. HRESULT
  820. CFolder::tvNotify(
  821. HWND hwndTV,
  822. CCookie* pCookie,
  823. TV_NOTIFY_CODE Code,
  824. LPARAM arg,
  825. LPARAM param
  826. )
  827. {
  828. if (m_pCurView) {
  829. return m_pCurView->tvNotify(hwndTV, pCookie, Code, arg, param);
  830. }
  831. else {
  832. return S_FALSE;
  833. }
  834. }
  835. HRESULT
  836. CFolder::OnOcxNotify(
  837. MMC_NOTIFY_TYPE event,
  838. LPARAM arg,
  839. LPARAM param
  840. )
  841. {
  842. if (m_pCurView) {
  843. return m_pCurView->OnOcxNotify(event, arg, param);
  844. }
  845. return S_OK;
  846. }
  847. /////////////////////////////////////////////////////////////////////
  848. //// CResultView implementations
  849. ////
  850. CResultView::~CResultView()
  851. {
  852. if (m_pCookieComputer) {
  853. if (m_pIDMTVOCX) {
  854. m_pIDMTVOCX->DeleteAllItems();
  855. }
  856. delete m_pCookieComputer;
  857. }
  858. if (m_pIDMTVOCX) {
  859. m_pIDMTVOCX->Release();
  860. }
  861. DestroySavedTreeStates();
  862. }
  863. HRESULT
  864. CResultView::OnShow(
  865. BOOL fShow
  866. )
  867. {
  868. if (!fShow) {
  869. return S_OK;
  870. }
  871. SafeInterfacePtr<IUnknown> pUnk;
  872. HRESULT hr;
  873. CComponent* pComponent = m_pFolder->m_pComponent;
  874. ASSERT(pComponent);
  875. ASSERT(pComponent->m_pConsole);
  876. hr = S_OK;
  877. if (NULL == m_pIDMTVOCX) {
  878. hr = pComponent->m_pConsole->QueryResultView(&pUnk);
  879. if (SUCCEEDED(hr)) {
  880. //
  881. // Get our OCX private interface
  882. //
  883. hr = pUnk->QueryInterface(IID_IDMTVOCX, (void**)&m_pIDMTVOCX);
  884. }
  885. if (SUCCEEDED(hr)) {
  886. m_pIDMTVOCX->Connect(pComponent, (MMC_COOKIE)this);
  887. m_hwndTV = m_pIDMTVOCX->GetWindowHandle();
  888. m_pIDMTVOCX->SetActiveConnection((MMC_COOKIE)this);
  889. //
  890. // Set up the annotation map for screen readers.
  891. //
  892. IAccPropServices *pAccPropSvc = NULL;
  893. hr = CoCreateInstance(CLSID_AccPropServices,
  894. NULL,
  895. CLSCTX_SERVER,
  896. IID_IAccPropServices,
  897. (void**)&pAccPropSvc);
  898. if ((hr == S_OK) && pAccPropSvc) {
  899. pAccPropSvc->SetHwndPropStr(m_hwndTV, (DWORD)OBJID_CLIENT, 0, PROPID_ACC_DESCRIPTIONMAP, (LPTSTR)m_stringAnnotationMap);
  900. pAccPropSvc->Release();
  901. }
  902. DisplayTree();
  903. String strStartupCommand;
  904. String strStartupDeviceId;
  905. strStartupCommand = GetStartupCommand();
  906. strStartupDeviceId = GetStartupDeviceId();
  907. if (!strStartupCommand.IsEmpty() && !strStartupDeviceId.IsEmpty() &&
  908. !strStartupCommand.CompareNoCase(DEVMGR_COMMAND_PROPERTY)) {
  909. hr = DoProperties(m_hwndTV, m_pSelectedCookie);
  910. }
  911. }
  912. }
  913. else {
  914. m_pIDMTVOCX->SetActiveConnection((MMC_COOKIE)this);
  915. if (!DisplayTree()) {
  916. hr = HRESULT_FROM_WIN32(GetLastError());
  917. }
  918. }
  919. return hr;
  920. }
  921. inline
  922. LPCTSTR
  923. CResultView::GetStartupDeviceId()
  924. {
  925. return m_pFolder->m_pComponent->GetStartupDeviceId();
  926. }
  927. inline
  928. LPCTSTR
  929. CResultView::GetStartupCommand()
  930. {
  931. return m_pFolder->m_pComponent->GetStartupCommand();
  932. }
  933. //
  934. // This function is called when machine states have changed.
  935. //
  936. // INPUT:
  937. // pMachine -- if NULL, the machine is being destroy.
  938. //
  939. // OUTPUT:
  940. // stanard OLE return code
  941. HRESULT
  942. CResultView::MachinePropertyChanged(
  943. CMachine* pMachine
  944. )
  945. {
  946. if (pMachine) {
  947. m_pMachine = pMachine;
  948. }
  949. else {
  950. //
  951. // pMachine is NULL, the CMachine we associated with is being destroyed.
  952. //
  953. if (m_pCookieComputer) {
  954. ASSERT(!m_pSelectedItem && m_listExpandedItems.IsEmpty());
  955. //
  956. // Save the expanded states
  957. //
  958. SaveTreeStates(m_pCookieComputer);
  959. m_pIDMTVOCX->DeleteAllItems();
  960. m_pIDMTVOCX->SetImageList(TVSIL_NORMAL, NULL);
  961. delete m_pCookieComputer;
  962. //
  963. // Reset these because they are no longer valid.
  964. //
  965. m_pCookieComputer = NULL;
  966. }
  967. }
  968. return S_OK;
  969. }
  970. //
  971. // This function saves the subtree states rooted by pCookieStart.
  972. // It creates an identifier for each expanded node and inserts
  973. // the identifier to the class memember, m_listExpandedItems.
  974. //
  975. // It also saves the selected cookie by creating an identifier and
  976. // saving it in m_pSelectedItem.
  977. //
  978. // This function may throw CMemoryException
  979. //
  980. // INPUT:
  981. // pCookieStart -- subtree root
  982. // OUTPUT:
  983. // NONE
  984. void
  985. CResultView::SaveTreeStates(
  986. CCookie* pCookieStart
  987. )
  988. {
  989. CItemIdentifier* pItem;
  990. //
  991. // If we have a selected item, create an identifier for it
  992. //
  993. if (m_pSelectedCookie) {
  994. m_pSelectedItem = m_pSelectedCookie->GetResultItem()->CreateIdentifier();
  995. m_pSelectedCookie = NULL;
  996. }
  997. while (pCookieStart) {
  998. if (pCookieStart->IsFlagsOn(COOKIE_FLAGS_EXPANDED)) {
  999. pItem = pCookieStart->GetResultItem()->CreateIdentifier();
  1000. m_listExpandedItems.AddTail(pItem);
  1001. }
  1002. if (pCookieStart->GetChild()) {
  1003. SaveTreeStates(pCookieStart->GetChild());
  1004. }
  1005. pCookieStart = pCookieStart->GetSibling();
  1006. }
  1007. }
  1008. void
  1009. CResultView::DestroySavedTreeStates()
  1010. {
  1011. if (!m_listExpandedItems.IsEmpty()) {
  1012. POSITION pos;
  1013. pos = m_listExpandedItems.GetHeadPosition();
  1014. while (NULL != pos) {
  1015. delete m_listExpandedItems.GetNext(pos);
  1016. }
  1017. m_listExpandedItems.RemoveAll();
  1018. }
  1019. if (m_pSelectedItem) {
  1020. delete m_pSelectedItem;
  1021. m_pSelectedItem = NULL;
  1022. }
  1023. }
  1024. //
  1025. // This function restores the expanded and selected state for the cookie.
  1026. //
  1027. // INPUT:
  1028. // pCookie -- cookie to restore states for
  1029. // OUTPUT:
  1030. // NONE
  1031. void
  1032. CResultView::RestoreSavedTreeState(
  1033. CCookie* pCookie
  1034. )
  1035. {
  1036. //
  1037. // If the cookie was expanded before, mark it so that DisplayTree
  1038. // will expand it.
  1039. //
  1040. if (!m_listExpandedItems.IsEmpty()) {
  1041. POSITION pos = m_listExpandedItems.GetHeadPosition();
  1042. CItemIdentifier* pItem;
  1043. while (NULL != pos) {
  1044. pItem = m_listExpandedItems.GetNext(pos);
  1045. if (*pItem == *pCookie) {
  1046. pCookie->TurnOnFlags(COOKIE_FLAGS_EXPANDED);
  1047. break;
  1048. }
  1049. }
  1050. }
  1051. if (m_pSelectedItem && (*m_pSelectedItem == *pCookie)) {
  1052. m_pSelectedCookie = pCookie;
  1053. }
  1054. }
  1055. BOOL
  1056. CResultView::DisplayTree()
  1057. {
  1058. BOOL Result = FALSE;
  1059. ASSERT(m_pIDMTVOCX);
  1060. ::SendMessage(m_hwndTV, WM_SETREDRAW, FALSE, 0L);
  1061. //
  1062. // Ignore the tvNotify(SELCHANGED) messages while the tree is changed.
  1063. //
  1064. SetSelectOk(FALSE);
  1065. m_pIDMTVOCX->DeleteAllItems();
  1066. //
  1067. // Only display the tree if there is something to display
  1068. //
  1069. if (m_pCookieComputer) {
  1070. m_pIDMTVOCX->SetImageList(TVSIL_NORMAL, m_pMachine->DiGetClassImageList());
  1071. m_pIDMTVOCX->SetStyle(TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT);
  1072. BOOL HasProblem = FALSE;
  1073. //
  1074. // Walks down the tree started from m_pCookieComputer
  1075. //
  1076. Result = DisplaySubtree(NULL, m_pCookieComputer, &HasProblem);
  1077. if (HasProblem && Result) {
  1078. m_pIDMTVOCX->Expand(TVE_EXPAND, (HTREEITEM)m_pCookieComputer->m_lParam);
  1079. }
  1080. //
  1081. // If we have a pre-selected item, use it. Otherwise, use computer
  1082. // as the selected node.
  1083. //
  1084. HTREEITEM hSelectedItem = (m_pSelectedCookie && m_pSelectedCookie->m_lParam) ?
  1085. (HTREEITEM)m_pSelectedCookie->m_lParam :
  1086. (HTREEITEM)m_pCookieComputer->m_lParam;
  1087. SetSelectOk(TRUE);
  1088. if (hSelectedItem) {
  1089. m_pIDMTVOCX->SelectItem(TVGN_CARET, hSelectedItem);
  1090. m_pIDMTVOCX->EnsureVisible(hSelectedItem);
  1091. }
  1092. }
  1093. ::SendMessage(m_hwndTV, WM_SETREDRAW, TRUE, 0L);
  1094. InvalidateRect(m_hwndTV, NULL, TRUE);
  1095. return Result;
  1096. }
  1097. //
  1098. // This function walks through the given cookie subtree rooted by pCookie
  1099. // and insert each node into the TreeView OCX.
  1100. // INPUT:
  1101. // htiParent -- HTREEITEM for the new cookie to be inserted
  1102. // if NULL is given, TVI_ROOT is assumed.
  1103. // pCookie -- the subtree root cookie to be displayed.
  1104. // OUTPUT:
  1105. // none.
  1106. //
  1107. BOOL
  1108. CResultView::DisplaySubtree(
  1109. HTREEITEM htiParent,
  1110. CCookie* pCookie,
  1111. BOOL* pReportProblem
  1112. )
  1113. {
  1114. TV_INSERTSTRUCT ti;
  1115. CResultItem* pRltItem;
  1116. HTREEITEM hti;
  1117. BOOL bResource;
  1118. BOOL fShowHiddenDevices = m_pFolder->ShowHiddenDevices();
  1119. while (pCookie) {
  1120. pRltItem = pCookie->GetResultItem();
  1121. ti.item.state = INDEXTOOVERLAYMASK(0);
  1122. bResource = FALSE;
  1123. //
  1124. // The cookie is not yet in the treeview.
  1125. //
  1126. pCookie->m_lParam = 0;
  1127. if (COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType()) {
  1128. CDevice* pDevice = (CDevice*)pRltItem;
  1129. //
  1130. // This is a hidden device and we are not showing hidden devices
  1131. //
  1132. // Note that we need to special case these devices because they
  1133. // are not shown in the tree view, but their visible children are shown.
  1134. //
  1135. if (!fShowHiddenDevices && pDevice->IsHidden()) {
  1136. //
  1137. // If the cookie has children, display them
  1138. //
  1139. CCookie* pCookieChild = pCookie->GetChild();
  1140. BOOL ChildProblem = FALSE;
  1141. if (pCookieChild) {
  1142. DisplaySubtree(htiParent, pCookieChild, &ChildProblem);
  1143. }
  1144. //
  1145. // Continue on with the next device. This will skip all of the display
  1146. // code below.
  1147. //
  1148. pCookie = pCookie->GetSibling();
  1149. continue;
  1150. }
  1151. //
  1152. // If the device is disabled then set the OVERLAYMASK to the Red X
  1153. //
  1154. if (pDevice->IsDisabled()) {
  1155. ti.item.state = INDEXTOOVERLAYMASK(IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST + 1);
  1156. *pReportProblem = TRUE;
  1157. }
  1158. //
  1159. // If the device has a problem then set the OVERLAYMASK to the Yellow !
  1160. //
  1161. else if (pDevice->HasProblem()) {
  1162. ti.item.state = INDEXTOOVERLAYMASK(IDI_PROBLEM_OVL - IDI_CLASSICON_OVERLAYFIRST + 1);
  1163. *pReportProblem = TRUE;
  1164. }
  1165. //
  1166. // if the device does not present, then set the state to TVIS_CUT. This grays out
  1167. // the icon a bit so it looks like a ghost icon.
  1168. //
  1169. else if (pDevice->IsPhantom()) {
  1170. ti.item.state = TVIS_CUT;
  1171. }
  1172. }
  1173. else if (COOKIE_TYPE_RESULTITEM_CLASS == pCookie->GetType()) {
  1174. CClass* pClass = (CClass*)pRltItem;
  1175. //
  1176. // If we don't have any devices to show for this class, or this
  1177. // is a NoDisplayClass and we are not showing hidden devices,
  1178. // then just get our next sibling and continue without showing
  1179. // this class.
  1180. //
  1181. if ((0 == pClass->GetNumberOfDevices(fShowHiddenDevices)) ||
  1182. (!fShowHiddenDevices && pClass->NoDisplay())) {
  1183. //
  1184. // Continue on with the next device. This will skip all of the display
  1185. // code below.
  1186. //
  1187. pCookie = pCookie->GetSibling();
  1188. continue;
  1189. }
  1190. }
  1191. //
  1192. // Is this a resource?
  1193. //
  1194. else if (COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY == pCookie->GetType() ||
  1195. COOKIE_TYPE_RESULTITEM_RESOURCE_IO == pCookie->GetType() ||
  1196. COOKIE_TYPE_RESULTITEM_RESOURCE_DMA == pCookie->GetType() ||
  1197. COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ == pCookie->GetType()) {
  1198. bResource = TRUE;
  1199. //
  1200. // If this is a FORCED CONFIG resource then overlay the forced
  1201. // config icon
  1202. //
  1203. if (((CResource*)pCookie->GetResultItem())->IsForced()) {
  1204. ti.item.state = INDEXTOOVERLAYMASK(IDI_FORCED_OVL-IDI_CLASSICON_OVERLAYFIRST+1);
  1205. }
  1206. }
  1207. ti.hParent = (htiParent != NULL) ? htiParent : TVI_ROOT;
  1208. ti.hInsertAfter = TVI_SORT;
  1209. ti.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
  1210. ti.item.iImage = ti.item.iSelectedImage = pRltItem->GetImageIndex();
  1211. if (bResource) {
  1212. ti.item.pszText = (LPTSTR)((CResource*)pRltItem)->GetViewName();
  1213. }
  1214. else {
  1215. ti.item.pszText = (LPTSTR)pRltItem->GetDisplayName();
  1216. }
  1217. ti.item.lParam = (LPARAM)pCookie;
  1218. ti.item.stateMask = TVIS_OVERLAYMASK | TVIS_CUT;
  1219. hti = m_pIDMTVOCX->InsertItem(&ti);
  1220. //
  1221. // Save the HTREEITEM
  1222. //
  1223. pCookie->m_lParam = (LPARAM)hti;
  1224. if (NULL != hti) {
  1225. //
  1226. // If the cookie has children, display them
  1227. //
  1228. CCookie* pCookieChild = pCookie->GetChild();
  1229. BOOL ChildProblem = FALSE;
  1230. if (pCookieChild) {
  1231. if (bResource && htiParent &&
  1232. GetDescriptionStringID() == IDS_STATUS_RESOURCES_BYTYPE) {
  1233. //
  1234. // This is a child of a resource being viewed by type,
  1235. // so the tree needs to be flattened. This is done by
  1236. // using the same parent.
  1237. //
  1238. DisplaySubtree(htiParent, pCookieChild, &ChildProblem);
  1239. }
  1240. else {
  1241. DisplaySubtree(hti, pCookieChild, &ChildProblem);
  1242. }
  1243. }
  1244. //
  1245. // If any of the device's children have a problem, or if
  1246. // it was previously expanded, then expand it.
  1247. //
  1248. if (ChildProblem || pCookie->IsFlagsOn(COOKIE_FLAGS_EXPANDED)) {
  1249. m_pIDMTVOCX->Expand(TVE_EXPAND, hti);
  1250. }
  1251. //
  1252. // Propogate the child's problem state back to the parent
  1253. //
  1254. *pReportProblem |= ChildProblem;
  1255. }
  1256. pCookie = pCookie->GetSibling();
  1257. }
  1258. return TRUE;
  1259. }
  1260. HRESULT
  1261. CResultView::GetResultViewType(
  1262. LPOLESTR* ppViewType,
  1263. long* pViewOptions
  1264. )
  1265. {
  1266. ASSERT(ppViewType && pViewOptions);
  1267. //
  1268. // The caller is responsible for freeing the memory we allocated.
  1269. //
  1270. LPOLESTR polestr;
  1271. polestr = AllocOleTaskString(OCX_TREEVIEW);
  1272. if (!polestr) {
  1273. return E_OUTOFMEMORY;
  1274. }
  1275. *ppViewType = polestr;
  1276. //
  1277. // We have not list view options
  1278. //
  1279. *pViewOptions = MMC_VIEW_OPTIONS_NOLISTVIEWS;
  1280. return S_OK;
  1281. }
  1282. HRESULT
  1283. CResultView::AddMenuItems(
  1284. CCookie* pCookie,
  1285. LPCONTEXTMENUCALLBACK pCallback,
  1286. long* pInsertionAllowed,
  1287. BOOL fContextMenu // True if for result view context menu
  1288. )
  1289. {
  1290. HRESULT hr = S_OK;
  1291. CDevice* pDevice = NULL;
  1292. if (CCM_INSERTIONALLOWED_TOP & *pInsertionAllowed) {
  1293. switch (pCookie->GetType()) {
  1294. case COOKIE_TYPE_RESULTITEM_DEVICE:
  1295. case COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ:
  1296. case COOKIE_TYPE_RESULTITEM_RESOURCE_DMA:
  1297. case COOKIE_TYPE_RESULTITEM_RESOURCE_IO:
  1298. case COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY:
  1299. if (m_pMachine->IsLocal() && g_IsAdmin) {
  1300. if (COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType()) {
  1301. pDevice = (CDevice*) pCookie->GetResultItem();
  1302. } else {
  1303. //
  1304. // This is a resource item, get the pointer for the device
  1305. // object from the resource object.
  1306. //
  1307. CResource* pResource = (CResource*) pCookie->GetResultItem();
  1308. if (pResource) {
  1309. pDevice = pResource->GetDevice();
  1310. }
  1311. }
  1312. if (pDevice == NULL) {
  1313. break;
  1314. }
  1315. CClass* pClass = pDevice->GetClass();
  1316. //
  1317. // All devices can have their driver's updated except for legacy devices.
  1318. //
  1319. if (!IsEqualGUID(*pClass, GUID_DEVCLASS_LEGACYDRIVER)) {
  1320. hr = AddMenuItem(pCallback, IDS_UPDATEDRIVER,
  1321. IDS_MENU_STATUS_UPDATEDRIVER, IDM_UPDATEDRIVER,
  1322. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1323. MF_ENABLED, 0);
  1324. }
  1325. //
  1326. // Only show the Enable/Disable menu item if the device
  1327. // can be disabled.
  1328. //
  1329. if (pDevice->IsDisableable()) {
  1330. if (pDevice->IsStateDisabled()) {
  1331. hr = AddMenuItem(pCallback, IDS_ENABLE,
  1332. IDS_MENU_STATUS_ENABLE, IDM_ENABLE,
  1333. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1334. MF_ENABLED, 0);
  1335. } else {
  1336. hr = AddMenuItem(pCallback, IDS_DISABLE,
  1337. IDS_MENU_STATUS_DISABLE, IDM_DISABLE,
  1338. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1339. MF_ENABLED, 0);
  1340. }
  1341. }
  1342. //
  1343. // Only show the uninstall menu item if the device can be
  1344. // uninstalled.
  1345. //
  1346. if (SUCCEEDED(hr) &&
  1347. pDevice->IsUninstallable()) {
  1348. hr = AddMenuItem(pCallback, IDS_REMOVE,
  1349. IDS_MENU_STATUS_REMOVE, IDM_REMOVE,
  1350. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1351. MF_ENABLED, 0);
  1352. }
  1353. }
  1354. // FALL THROUGH........
  1355. case COOKIE_TYPE_RESULTITEM_CLASS:
  1356. if (g_IsAdmin) {
  1357. if (SUCCEEDED(hr)) {
  1358. hr = AddMenuItem(pCallback, 0, 0, 0,
  1359. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1360. MF_ENABLED, CCM_SPECIAL_SEPARATOR);
  1361. }
  1362. if (SUCCEEDED(hr)) {
  1363. hr = AddMenuItem(pCallback, IDS_REFRESH,
  1364. IDS_MENU_STATUS_SCAN_CHANGES, IDM_REFRESH,
  1365. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1366. MF_ENABLED, 0);
  1367. }
  1368. }
  1369. if (fContextMenu) {
  1370. if (SUCCEEDED(hr)) {
  1371. hr = AddMenuItem(pCallback, 0, 0, 0,
  1372. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1373. MF_ENABLED, CCM_SPECIAL_SEPARATOR);
  1374. }
  1375. if (SUCCEEDED(hr)) {
  1376. hr = AddMenuItem(pCallback, IDS_PROPERTIES,
  1377. IDS_MENU_STATUS_PROPERTIES, IDM_PROPERTIES,
  1378. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1379. MF_DEFAULT, CCM_SPECIAL_DEFAULT_ITEM);
  1380. }
  1381. }
  1382. break;
  1383. case COOKIE_TYPE_RESULTITEM_COMPUTER:
  1384. case COOKIE_TYPE_RESULTITEM_RESTYPE:
  1385. if (g_IsAdmin) {
  1386. hr = AddMenuItem(pCallback, IDS_REFRESH,
  1387. IDS_MENU_STATUS_SCAN_CHANGES, IDM_REFRESH,
  1388. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  1389. MF_ENABLED, 0);
  1390. }
  1391. break;
  1392. default:
  1393. break;
  1394. }
  1395. }
  1396. return hr;
  1397. }
  1398. // This function handles menu command for the device tree.
  1399. //
  1400. // INPUT: pCookie -- the cookie
  1401. // lCommandId -- the command. See AddMenuItems for valid command
  1402. // id for each type of cookie.
  1403. //
  1404. // OUTPUT: HRESULT S_OK if succeeded.
  1405. // S_XXX error code.
  1406. HRESULT
  1407. CResultView::MenuCommand(
  1408. CCookie* pCookie,
  1409. long lCommandId
  1410. )
  1411. {
  1412. HRESULT hr = S_OK;
  1413. //TRACE1(TEXT("Menu command, commandid = %lx\n"), lCommandId);
  1414. ASSERT(pCookie);
  1415. CResultItem* pResultItem = pCookie->GetResultItem();
  1416. ASSERT(pResultItem);
  1417. CDevice* pDevice = NULL;
  1418. switch (pCookie->GetType()) {
  1419. case COOKIE_TYPE_RESULTITEM_DEVICE:
  1420. pDevice = (CDevice*)pResultItem;
  1421. break;
  1422. case COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ:
  1423. case COOKIE_TYPE_RESULTITEM_RESOURCE_DMA:
  1424. case COOKIE_TYPE_RESULTITEM_RESOURCE_IO:
  1425. case COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY:
  1426. CResource* pResource = (CResource*)pResultItem;
  1427. if (pResource) {
  1428. pDevice = pResource->GetDevice();
  1429. }
  1430. break;
  1431. }
  1432. switch (lCommandId) {
  1433. case IDM_UPDATEDRIVER:
  1434. if (pDevice) {
  1435. BOOL Installed;
  1436. DWORD RestartFlags = 0;
  1437. DWORD Status = 0, Problem = 0;
  1438. //
  1439. // If the device has the DN_WILL_BE_REMOVED flag set and the user is
  1440. // attempting to update the driver then we will prompt them for a
  1441. // reboot and include text in the prompt that explains this device
  1442. // is in the process of being removed.
  1443. //
  1444. if (pDevice->GetStatus(&Status, &Problem) &&
  1445. (Status & DN_WILL_BE_REMOVED)) {
  1446. PromptForRestart(m_hwndTV, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_UPDATE_DRIVER);
  1447. } else {
  1448. //
  1449. // Disable Refreshing while the Update Driver Wizard is up.
  1450. //
  1451. pDevice->m_pMachine->EnableRefresh(FALSE);
  1452. HCURSOR hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1453. Installed = pDevice->m_pMachine->InstallDevInst(m_hwndTV, pDevice->GetDeviceID(), TRUE, &RestartFlags);
  1454. if (hCursorOld) {
  1455. SetCursor(hCursorOld);
  1456. }
  1457. //
  1458. // Prompt for a restart if one is needed. If the user does NOT answer
  1459. // YES to the restart dialog then schedule a refresh since we might not
  1460. // get one from a WM_DEVICECHANGE.
  1461. //
  1462. if (m_pMachine->IsLocal()) {
  1463. if (PromptForRestart(NULL, RestartFlags) == IDNO) {
  1464. pDevice->m_pMachine->ScheduleRefresh();
  1465. }
  1466. }
  1467. //
  1468. // Enable Refreshing now that we are done updating the driver.
  1469. //
  1470. pDevice->m_pMachine->EnableRefresh(TRUE);
  1471. }
  1472. }
  1473. break;
  1474. case IDM_ENABLE:
  1475. case IDM_DISABLE:
  1476. if (pDevice) {
  1477. DWORD RestartFlags = 0;
  1478. DWORD Status = 0, Problem = 0;
  1479. //
  1480. // If the device has the DN_WILL_BE_REMOVED flag set and the user is
  1481. // attempting to enable/disable the driver then we will prompt them for a
  1482. // reboot and include text in the prompt that explains this device
  1483. // is in the process of being removed.
  1484. //
  1485. if (pDevice->GetStatus(&Status, &Problem) &&
  1486. (Status & DN_WILL_BE_REMOVED)) {
  1487. PromptForRestart(m_hwndTV, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_CHANGE_SETTINGS);
  1488. } else {
  1489. RestartFlags = pDevice->EnableDisableDevice(m_hwndTV,
  1490. (lCommandId == IDM_ENABLE));
  1491. //
  1492. // Update the toolbar buttons since the device just changed.
  1493. //
  1494. m_pFolder->m_pComponent->UpdateToolbar(pCookie);
  1495. //
  1496. // Prompt for a Restart if we are running locally.
  1497. // The PromptForRestart() API checks the flags to determine
  1498. // if a restart is actually needed.
  1499. //
  1500. if (m_pMachine->IsLocal()) {
  1501. if (PromptForRestart(NULL, RestartFlags) == IDNO) {
  1502. m_pMachine->ScheduleRefresh();
  1503. }
  1504. }
  1505. }
  1506. }
  1507. break;
  1508. case IDM_REMOVE:
  1509. if (pDevice) {
  1510. hr = RemoveDevice(pDevice);
  1511. }
  1512. break;
  1513. case IDM_REFRESH:
  1514. //
  1515. // This will force every attached folder to recreate
  1516. // its machine data
  1517. //
  1518. ASSERT(m_pMachine);
  1519. if (!m_pMachine->Reenumerate()) {
  1520. hr = HRESULT_FROM_WIN32(GetLastError());
  1521. }
  1522. break;
  1523. case IDM_PROPERTIES:
  1524. hr = DoProperties(m_hwndTV, pCookie);
  1525. break;
  1526. default:
  1527. hr = S_OK;
  1528. break;
  1529. }
  1530. return hr;
  1531. }
  1532. // This function reports if property pages are available for the
  1533. // given cookie. Returning S_FALSE, the cookie's "properties" menu
  1534. // item will not displayed.
  1535. //
  1536. // INPUT: pCookie -- the cookie
  1537. //
  1538. // OUTPUT: HRESULT S_OK if pages are available for the cookie.
  1539. // S_FALSE if no pages are available for the cookie.
  1540. HRESULT
  1541. CResultView::QueryPagesFor(
  1542. CCookie* pCookie
  1543. )
  1544. {
  1545. ASSERT(pCookie);
  1546. if (COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ == pCookie->GetType() ||
  1547. COOKIE_TYPE_RESULTITEM_RESOURCE_DMA == pCookie->GetType() ||
  1548. COOKIE_TYPE_RESULTITEM_RESOURCE_IO == pCookie->GetType() ||
  1549. COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY == pCookie->GetType() ||
  1550. COOKIE_TYPE_RESULTITEM_CLASS == pCookie->GetType() ||
  1551. COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType()) {
  1552. return S_OK;
  1553. }
  1554. return S_FALSE;
  1555. }
  1556. // This function creates property page(s) for the given cookie.
  1557. //
  1558. // INPUT: pCookie -- the cookie
  1559. // lpProvider -- interface pointer to IPROPERTYSHEETCALLBACK
  1560. // used to add HPROPSHEETPAGE to the property sheet.
  1561. // handle -- handle for property change notification
  1562. // The handle is required for MMCPropertyChangeNotify
  1563. // API.
  1564. // OUTPUT: HRESULT S_OK if succeeded.
  1565. // S_FALSE if no pages are added.
  1566. // S_XXX error code.
  1567. HRESULT
  1568. CResultView::CreatePropertyPages(
  1569. CCookie* pCookie,
  1570. LPPROPERTYSHEETCALLBACK lpProvider,
  1571. LONG_PTR handle
  1572. )
  1573. {
  1574. //
  1575. // Design issue:
  1576. // We depend on the general page to do some houeskeeping works on the
  1577. // property sheet which is owned and controlled by MMC running in a
  1578. // separate thread. General page is always the first page and its window
  1579. // is always created. If we need to subclass the property sheet someday,
  1580. // having our own General page always assure that we will get the window
  1581. // handle to the property sheet.
  1582. //
  1583. // The most important housekeeping work the General page does is to inform the
  1584. // associate device or class when a property sheet is being created
  1585. // or destroyed. A device can not be removed if it has a property sheet
  1586. // running. The machine can not refresh the device tree if there are property
  1587. // sheet(s) running on any devices/classes it contains. Property sheets
  1588. // created by a folder should be canceled when the folder is being
  1589. // destroyed.
  1590. //
  1591. // So far, no class installers have attempted to add their own General
  1592. // page and I believe it will be true in the future because 1). the page
  1593. // is too complicated and overloaded with features(and hard to implement) and
  1594. // 2). no major gains can be obtained by implementing a new one.
  1595. // To warn the developers who does their own General page,we will have a
  1596. // message box warn them about this and proceed with OUR general page.
  1597. //
  1598. ASSERT(pCookie);
  1599. CPropSheetData* ppsd = NULL;
  1600. CMachine* pNewMachine = NULL;
  1601. switch (pCookie->GetType()) {
  1602. case COOKIE_TYPE_RESULTITEM_CLASS:
  1603. CClass* pClass;
  1604. pClass = (CClass*) pCookie->GetResultItem();
  1605. ASSERT(pClass);
  1606. //
  1607. // Create a new CMachine object that just contains this specific device
  1608. // and it's class. We need to do this since the CDevice and CClass of
  1609. // the cookie that was passed into this API will get destroyed whenever
  1610. // we get a WM_DEVICECHANGE notification.
  1611. //
  1612. PVOID Context;
  1613. pNewMachine = new CMachine(m_pMachine->GetMachineFullName());
  1614. CClass* pNewClass;
  1615. if (pNewMachine->Initialize(NULL, NULL, *pClass) &&
  1616. pNewMachine->GetFirstClass(&pNewClass, Context) &&
  1617. pNewClass) {
  1618. pNewMachine->m_ParentMachine = m_pMachine;
  1619. m_pMachine->AttachChildMachine(pNewMachine);
  1620. pNewMachine->SetPropertySheetShouldDestroy();
  1621. ppsd = &pNewClass->m_psd;
  1622. if (ppsd->Create(g_hInstance, m_hwndTV, MAX_PROP_PAGES, handle)) {
  1623. CDevInfoList* pClassDevInfo;
  1624. //
  1625. // The CDevInfoList object is maintained by the CClass
  1626. // object.
  1627. //
  1628. pClassDevInfo = pNewClass->GetDevInfoList();
  1629. if (pClassDevInfo && pClassDevInfo->DiGetClassDevPropertySheet(NULL,
  1630. &ppsd->m_psh,
  1631. MAX_PROP_PAGES,
  1632. pNewMachine->IsLocal() ?
  1633. DIGCDP_FLAG_ADVANCED :
  1634. DIGCDP_FLAG_REMOTE_ADVANCED)) {
  1635. if (pClassDevInfo->DiGetFlags(NULL) & DI_GENERALPAGE_ADDED) {
  1636. TCHAR szText[MAX_PATH];
  1637. LoadResourceString(IDS_GENERAL_PAGE_WARNING, szText,
  1638. ARRAYLEN(szText));
  1639. int ReturnValue;
  1640. m_pFolder->m_pComponent->m_pConsole->MessageBox(
  1641. szText, pNewClass->GetDisplayName(),
  1642. MB_ICONEXCLAMATION | MB_OK, &ReturnValue);
  1643. //
  1644. // fall through to create our general page.
  1645. //
  1646. }
  1647. SafePtr<CClassGeneralPage> GenPagePtr;
  1648. CClassGeneralPage* pGenPage;
  1649. pGenPage = new CClassGeneralPage;
  1650. if (pGenPage) {
  1651. GenPagePtr.Attach(pGenPage);
  1652. HPROPSHEETPAGE hPage = pGenPage->Create(pNewClass);
  1653. //
  1654. // General page has to be the first page
  1655. //
  1656. if (ppsd->InsertPage(hPage, 0)) {
  1657. GenPagePtr.Detach();
  1658. } else {
  1659. ::DestroyPropertySheetPage(hPage);
  1660. }
  1661. }
  1662. }
  1663. }
  1664. }
  1665. break;
  1666. case COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ:
  1667. case COOKIE_TYPE_RESULTITEM_RESOURCE_DMA:
  1668. case COOKIE_TYPE_RESULTITEM_RESOURCE_IO:
  1669. case COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY:
  1670. case COOKIE_TYPE_RESULTITEM_DEVICE:
  1671. CDevice* pDevice;
  1672. CDevice* pNewDevice;
  1673. pNewDevice = NULL;
  1674. if (COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType()) {
  1675. pDevice = (CDevice*) pCookie->GetResultItem();
  1676. } else {
  1677. //
  1678. // This is a resource item, get the pointer for the device
  1679. // object from the resource object.
  1680. //
  1681. CResource* pResource = (CResource*) pCookie->GetResultItem();
  1682. ASSERT(pResource);
  1683. pDevice = pResource->GetDevice();
  1684. }
  1685. ASSERT(pDevice);
  1686. //
  1687. // Create a new CMachine object that just contains this specific device
  1688. // and it's class. We need to do this since the CDevice and CClass of
  1689. // the cookie that was passed into this API will get destroyed whenever
  1690. // we get a WM_DEVICECHANGE notification.
  1691. //
  1692. PVOID DeviceContext;
  1693. pNewMachine = new CMachine(m_pMachine->GetMachineFullName());
  1694. if (pNewMachine->Initialize(NULL, pDevice->GetDeviceID()) &&
  1695. pNewMachine->GetFirstDevice(&pNewDevice, DeviceContext) &&
  1696. pNewDevice) {
  1697. pNewMachine->m_ParentMachine = m_pMachine;
  1698. m_pMachine->AttachChildMachine(pNewMachine);
  1699. pNewMachine->SetPropertySheetShouldDestroy();
  1700. ppsd = &pNewDevice->m_psd;
  1701. if (ppsd->Create(g_hInstance, m_hwndTV, MAX_PROP_PAGES, handle)) {
  1702. //
  1703. // Add any class/device specific property pages
  1704. //
  1705. pNewMachine->DiGetClassDevPropertySheet(*pNewDevice,
  1706. &ppsd->m_psh,
  1707. MAX_PROP_PAGES,
  1708. pNewMachine->IsLocal() ?
  1709. DIGCDP_FLAG_ADVANCED :
  1710. DIGCDP_FLAG_REMOTE_ADVANCED);
  1711. //
  1712. // Add the general tab
  1713. //
  1714. DWORD DiFlags = pNewMachine->DiGetFlags(*pNewDevice);
  1715. SafePtr<CDeviceGeneralPage> GenPagePtr;
  1716. if (DiFlags & DI_GENERALPAGE_ADDED) {
  1717. TCHAR szText[MAX_PATH];
  1718. LoadResourceString(IDS_GENERAL_PAGE_WARNING, szText,
  1719. ARRAYLEN(szText));
  1720. int ReturnValue;
  1721. m_pFolder->m_pComponent->m_pConsole->MessageBox(
  1722. szText, pNewDevice->GetDisplayName(),
  1723. MB_ICONEXCLAMATION | MB_OK, &ReturnValue);
  1724. //
  1725. // fall through to create our general page.
  1726. //
  1727. }
  1728. CDeviceGeneralPage* pGenPage = new CDeviceGeneralPage;
  1729. if (pGenPage) {
  1730. GenPagePtr.Attach(pGenPage);
  1731. HPROPSHEETPAGE hPage = pGenPage->Create(pNewDevice);
  1732. if (hPage) {
  1733. //
  1734. // General page has to be the first page
  1735. //
  1736. if (ppsd->InsertPage(hPage, 0)) {
  1737. GenPagePtr.Detach();
  1738. } else {
  1739. ::DestroyPropertySheetPage(hPage);
  1740. }
  1741. }
  1742. }
  1743. //
  1744. // Add the driver tab
  1745. //
  1746. SafePtr<CDeviceDriverPage> DrvPagePtr;
  1747. if (!(DiFlags & DI_DRIVERPAGE_ADDED)) {
  1748. CDeviceDriverPage* pPage = new CDeviceDriverPage;
  1749. if (pPage) {
  1750. DrvPagePtr.Attach(pPage);
  1751. HPROPSHEETPAGE hPage = pPage->Create(pNewDevice);
  1752. if (hPage) {
  1753. if (ppsd->InsertPage(hPage)) {
  1754. DrvPagePtr.Detach();
  1755. } else {
  1756. ::DestroyPropertySheetPage(hPage);
  1757. }
  1758. }
  1759. }
  1760. }
  1761. //
  1762. // add the details tab
  1763. //
  1764. // If the environment variable DEVMGR_SHOW_DETAILS does exist and it
  1765. // is not 0 then we will show the details tab
  1766. //
  1767. TCHAR Buffer[MAX_PATH];
  1768. DWORD BufferLen;
  1769. if (((BufferLen = ::GetEnvironmentVariable(TEXT("DEVMGR_SHOW_DETAILS"),
  1770. Buffer,
  1771. ARRAYLEN(Buffer))) != 0) &&
  1772. ((BufferLen > 1) ||
  1773. (lstrcmp(Buffer, TEXT("0"))))) {
  1774. SafePtr<CDeviceDetailsPage> DetailsPagePtr;
  1775. CDeviceDetailsPage* pDetailsPage = new CDeviceDetailsPage;
  1776. DetailsPagePtr.Attach(pDetailsPage);
  1777. HPROPSHEETPAGE hPage = pDetailsPage->Create(pNewDevice);
  1778. if (hPage) {
  1779. if (ppsd->InsertPage(hPage)) {
  1780. DetailsPagePtr.Detach();
  1781. } else {
  1782. ::DestroyPropertySheetPage(hPage);
  1783. }
  1784. }
  1785. }
  1786. //
  1787. // Add the resource tab
  1788. //
  1789. if (pNewDevice->HasResources() && !(DiFlags & DI_RESOURCEPAGE_ADDED)) {
  1790. pNewMachine->DiGetExtensionPropSheetPage(*pNewDevice,
  1791. AddPropPageCallback,
  1792. SPPSR_SELECT_DEVICE_RESOURCES,
  1793. (LPARAM)ppsd
  1794. );
  1795. }
  1796. #ifndef _WIN64
  1797. DWORD DiFlagsEx = pNewMachine->DiGetExFlags(*pNewDevice);
  1798. //
  1799. // Add the power management tab
  1800. //
  1801. if (pNewMachine->IsLocal() && !(DiFlagsEx & DI_FLAGSEX_POWERPAGE_ADDED)) {
  1802. //
  1803. // Check if the device support power management
  1804. //
  1805. CPowerShutdownEnable ShutdownEnable;
  1806. CPowerWakeEnable WakeEnable;
  1807. if (ShutdownEnable.Open(pNewDevice->GetDeviceID()) || WakeEnable.Open(pNewDevice->GetDeviceID())) {
  1808. ShutdownEnable.Close();
  1809. WakeEnable.Close();
  1810. SafePtr<CDevicePowerMgmtPage> PowerMgmtPagePtr;
  1811. CDevicePowerMgmtPage* pPowerPage = new CDevicePowerMgmtPage;
  1812. if (pPowerPage) {
  1813. PowerMgmtPagePtr.Attach(pPowerPage);
  1814. HPROPSHEETPAGE hPage = pPowerPage->Create(pNewDevice);
  1815. if (hPage) {
  1816. if (ppsd->InsertPage(hPage)) {
  1817. PowerMgmtPagePtr.Detach();
  1818. } else {
  1819. ::DestroyPropertySheetPage(hPage);
  1820. }
  1821. }
  1822. }
  1823. }
  1824. }
  1825. #endif
  1826. //
  1827. // Add any Bus specific property pages if this is the local machine
  1828. //
  1829. if (pNewMachine->IsLocal()) {
  1830. CBusPropPageProvider* pBusPropPageProvider = new CBusPropPageProvider();
  1831. if (pBusPropPageProvider) {
  1832. SafePtr<CBusPropPageProvider> ProviderPtr;
  1833. ProviderPtr.Attach(pBusPropPageProvider);
  1834. if (pBusPropPageProvider->EnumPages(pNewDevice, ppsd)) {
  1835. ppsd->AddProvider(pBusPropPageProvider);
  1836. ProviderPtr.Detach();
  1837. }
  1838. }
  1839. }
  1840. }
  1841. }
  1842. break;
  1843. default:
  1844. break;
  1845. }
  1846. if (ppsd &&
  1847. ppsd->m_psh.nPages) {
  1848. PROPSHEETHEADER& psh = ppsd->m_psh;
  1849. for (UINT Index = 0; Index < psh.nPages; Index++) {
  1850. lpProvider->AddPage(psh.phpage[Index]);
  1851. }
  1852. return S_OK;
  1853. }
  1854. //
  1855. // If we didn't add any pages then we need to delete the new CMachine we
  1856. // created.
  1857. //
  1858. if (pNewMachine) {
  1859. delete pNewMachine;
  1860. }
  1861. //
  1862. // No pages are added, return S_FALSE so that the responsible
  1863. // Component can do its clean up
  1864. //
  1865. return S_FALSE;
  1866. }
  1867. // This function handles notification codes from the TV OCX.
  1868. //
  1869. // INPUT:
  1870. // hwndTV -- the Window handle of the TV OCX.
  1871. // pCookie -- the cookie
  1872. // Code -- notification code.
  1873. // arg -- argument to the given notification code.
  1874. // param -- another parameter to the given notificaton code.
  1875. //
  1876. // OUTPUT:
  1877. // HRESULT -- S_OK if this function has processed the notification
  1878. // and the caller should not do any further processing.
  1879. // S_FALSE if the caller should do more processing.
  1880. HRESULT
  1881. CResultView::tvNotify(
  1882. HWND hwndTV,
  1883. CCookie* pCookie,
  1884. TV_NOTIFY_CODE Code,
  1885. LPARAM arg,
  1886. LPARAM param
  1887. )
  1888. {
  1889. HRESULT hr;
  1890. UNREFERENCED_PARAMETER(arg);
  1891. if (m_hwndTV != hwndTV) {
  1892. return S_FALSE;
  1893. }
  1894. //
  1895. // Presume that we do not handle the notification
  1896. //
  1897. hr = S_FALSE;
  1898. switch (Code) {
  1899. case TV_NOTIFY_CODE_DBLCLK:
  1900. if ((TVHT_ONITEM & param) &&
  1901. (COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ == pCookie->GetType() ||
  1902. COOKIE_TYPE_RESULTITEM_RESOURCE_DMA == pCookie->GetType() ||
  1903. COOKIE_TYPE_RESULTITEM_RESOURCE_IO == pCookie->GetType() ||
  1904. COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY == pCookie->GetType() ||
  1905. COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType())) {
  1906. if (SUCCEEDED(DoProperties(hwndTV, pCookie)))
  1907. hr = S_OK;
  1908. }
  1909. break;
  1910. case TV_NOTIFY_CODE_CONTEXTMENU:
  1911. if (SUCCEEDED(DoContextMenu(hwndTV, pCookie, (POINT*)param)))
  1912. hr = S_OK;
  1913. break;
  1914. case TV_NOTIFY_CODE_EXPANDED:
  1915. if (TVE_EXPAND & param) {
  1916. pCookie->TurnOnFlags(COOKIE_FLAGS_EXPANDED);
  1917. } else if (TVE_COLLAPSE & param) {
  1918. pCookie->TurnOffFlags(COOKIE_FLAGS_EXPANDED);
  1919. }
  1920. ASSERT(S_FALSE == hr);
  1921. break;
  1922. case TV_NOTIFY_CODE_FOCUSCHANGED:
  1923. // gaining the focus, set the console verbs and toolbar buttons
  1924. if (param) {
  1925. UpdateConsoleVerbs(pCookie);
  1926. m_pFolder->m_pComponent->UpdateToolbar(pCookie);
  1927. }
  1928. break;
  1929. case TV_NOTIFY_CODE_SELCHANGED:
  1930. if (m_SelectOk) {
  1931. // These messages are ignored while the tree is being changed.
  1932. m_pSelectedCookie = pCookie;
  1933. UpdateConsoleVerbs(pCookie);
  1934. m_pFolder->m_pComponent->UpdateToolbar(pCookie);
  1935. }
  1936. break;
  1937. case TV_NOTIFY_CODE_KEYDOWN:
  1938. if (VK_RETURN == param) {
  1939. if (COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ == pCookie->GetType() ||
  1940. COOKIE_TYPE_RESULTITEM_RESOURCE_DMA == pCookie->GetType() ||
  1941. COOKIE_TYPE_RESULTITEM_RESOURCE_IO == pCookie->GetType() ||
  1942. COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY == pCookie->GetType() ||
  1943. COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType() ||
  1944. COOKIE_TYPE_RESULTITEM_CLASS == pCookie->GetType()) {
  1945. if (SUCCEEDED(DoProperties(hwndTV, pCookie)))
  1946. hr = S_OK;
  1947. }
  1948. }
  1949. else if (VK_DELETE == param &&
  1950. COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType()) {
  1951. //
  1952. // Remove the selected device
  1953. //
  1954. CDevice* pDevice = (CDevice*)pCookie->GetResultItem();
  1955. RemoveDevice(pDevice);
  1956. }
  1957. break;
  1958. case TV_NOTIFY_CODE_RCLICK:
  1959. case TV_NOTIFY_CODE_CLICK:
  1960. if (pCookie && pCookie->m_lParam) {
  1961. m_pIDMTVOCX->SelectItem(TVGN_CARET, (HTREEITEM)pCookie->m_lParam);
  1962. }
  1963. case TV_NOTIFY_CODE_GETDISPINFO:
  1964. default:
  1965. ASSERT(S_FALSE == hr);
  1966. break;
  1967. }
  1968. return hr;
  1969. }
  1970. //
  1971. // This function updates console verbs based on the selected cookie type.
  1972. //
  1973. HRESULT
  1974. CResultView::UpdateConsoleVerbs(
  1975. CCookie* pCookie
  1976. )
  1977. {
  1978. BOOL bPropertiesEnabled = FALSE;
  1979. BOOL bPrintEnabled = FALSE;
  1980. if (!m_pFolder->m_bSelect) {
  1981. switch (pCookie->GetType()) {
  1982. case COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ:
  1983. case COOKIE_TYPE_RESULTITEM_RESOURCE_DMA:
  1984. case COOKIE_TYPE_RESULTITEM_RESOURCE_IO:
  1985. case COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY:
  1986. case COOKIE_TYPE_RESULTITEM_CLASS:
  1987. case COOKIE_TYPE_RESULTITEM_DEVICE:
  1988. bPropertiesEnabled = TRUE;
  1989. bPrintEnabled = TRUE;
  1990. break;
  1991. case COOKIE_TYPE_RESULTITEM_COMPUTER:
  1992. bPrintEnabled = TRUE;
  1993. break;
  1994. default:
  1995. break;
  1996. }
  1997. }
  1998. //
  1999. // Only show the Print button/Action menu item when a something is selected.
  2000. //
  2001. if (bPrintEnabled) {
  2002. m_pFolder->m_pComponent->m_pConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, FALSE);
  2003. m_pFolder->m_pComponent->m_pConsoleVerb->SetVerbState(MMC_VERB_PRINT, ENABLED, TRUE);
  2004. } else {
  2005. m_pFolder->m_pComponent->m_pConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, TRUE);
  2006. }
  2007. //
  2008. // Only show the properties button/Action menu item when a device/class is selected.
  2009. //
  2010. if (bPropertiesEnabled) {
  2011. m_pFolder->m_pComponent->m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE);
  2012. m_pFolder->m_pComponent->m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  2013. m_pFolder->m_pComponent->m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
  2014. } else {
  2015. m_pFolder->m_pComponent->m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, TRUE);
  2016. m_pFolder->m_pComponent->m_pConsoleVerb->SetDefaultVerb(MMC_VERB_NONE);
  2017. }
  2018. return S_OK;
  2019. }
  2020. HRESULT
  2021. CResultView::OnOcxNotify(
  2022. MMC_NOTIFY_TYPE event,
  2023. LPARAM arg,
  2024. LPARAM param
  2025. )
  2026. {
  2027. HRESULT hr = S_OK;
  2028. TV_ITEM TI;
  2029. UNREFERENCED_PARAMETER(arg);
  2030. switch (event) {
  2031. case MMCN_BTN_CLICK:
  2032. if ((MMC_CONSOLE_VERB)param == MMC_VERB_PROPERTIES) {
  2033. ASSERT(m_pIDMTVOCX);
  2034. TI.hItem = m_pIDMTVOCX->GetSelectedItem();
  2035. if (TI.hItem) {
  2036. TI.mask = TVIF_PARAM;
  2037. hr = m_pIDMTVOCX->GetItem(&TI);
  2038. if (SUCCEEDED(hr)) {
  2039. hr = DoProperties(m_hwndTV, (CCookie*)TI.lParam);
  2040. }
  2041. }
  2042. }
  2043. break;
  2044. case MMCN_PRINT:
  2045. hr = DoPrint();
  2046. break;
  2047. case MMCN_SELECT:
  2048. ASSERT(m_pIDMTVOCX);
  2049. TI.hItem = m_pIDMTVOCX->GetSelectedItem();
  2050. if (TI.hItem) {
  2051. TI.mask = TVIF_PARAM;
  2052. hr = m_pIDMTVOCX->GetItem(&TI);
  2053. if (SUCCEEDED(hr)) {
  2054. hr = UpdateConsoleVerbs((CCookie*)TI.lParam);
  2055. }
  2056. }
  2057. break;
  2058. default:
  2059. break;
  2060. }
  2061. return hr;
  2062. }
  2063. // This function creates the propperty sheet for the given cookie.
  2064. // INPUT:
  2065. // hwndTV -- the window handle to the TV OCX, used as the parent
  2066. // window of the property sheet.
  2067. // pCookie -- the cookie.
  2068. // OUTPUT:
  2069. // HRESULT S_OK if the function succeeded.
  2070. // S_FALSE if no property sheet will be created.
  2071. // S_XXXX other error.
  2072. HRESULT
  2073. CResultView::DoProperties(
  2074. HWND hwndTV,
  2075. CCookie* pCookie
  2076. )
  2077. {
  2078. HRESULT hr;
  2079. //
  2080. // If a property sheet is aleady up for the node, bring the
  2081. // property sheet to the foreground.
  2082. //
  2083. HWND hWnd = NULL;
  2084. if (COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType()) {
  2085. CDevice* pDevice = (CDevice*)pCookie->GetResultItem();
  2086. ASSERT(pDevice);
  2087. hWnd = pDevice->m_pMachine->GetDeviceWindowHandle(pDevice->GetDeviceID());
  2088. }
  2089. else if (COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ == pCookie->GetType() ||
  2090. COOKIE_TYPE_RESULTITEM_RESOURCE_DMA == pCookie->GetType() ||
  2091. COOKIE_TYPE_RESULTITEM_RESOURCE_IO == pCookie->GetType() ||
  2092. COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY == pCookie->GetType()) {
  2093. //
  2094. // This is a resource item, get the pointer for the device
  2095. // object from the resource object.
  2096. //
  2097. CResource* pResource = (CResource*) pCookie->GetResultItem();
  2098. ASSERT(pResource);
  2099. CDevice* pDevice = pResource->GetDevice();
  2100. ASSERT(pDevice);
  2101. hWnd = pDevice->m_pMachine->GetDeviceWindowHandle(pDevice->GetDeviceID());
  2102. }
  2103. else if (COOKIE_TYPE_RESULTITEM_CLASS == pCookie->GetType()) {
  2104. CClass* pClass = (CClass*)pCookie->GetResultItem();
  2105. ASSERT(pClass);
  2106. hWnd = pClass->m_pMachine->GetClassWindowHandle(*pClass);
  2107. }
  2108. if (hWnd) {
  2109. //
  2110. // Notify the property sheet that it should go to foreground
  2111. // Do not call SetForegroundWindow here because the subclassed
  2112. // treeview control will grab the focus right after
  2113. // we have brought the property sheet to foreground.
  2114. //
  2115. ::PostMessage(hWnd, PSM_QUERYSIBLINGS, QSC_TO_FOREGROUND, 0L);
  2116. return S_OK;
  2117. }
  2118. //
  2119. // No property sheet is up for this cookie, create a brand new property
  2120. // sheet for it.
  2121. //
  2122. SafeInterfacePtr<IComponent> pComponent;
  2123. SafeInterfacePtr<IPropertySheetProvider> pSheetProvider;
  2124. SafeInterfacePtr<IDataObject> pDataObject;
  2125. SafeInterfacePtr<IExtendPropertySheet> pExtendSheet;
  2126. pComponent.Attach((IComponent*) m_pFolder->m_pComponent);
  2127. if (FAILED(pComponent->QueryInterface(IID_IExtendPropertySheet, (void**) &pExtendSheet)) ||
  2128. FAILED(pComponent->QueryDataObject((MMC_COOKIE)pCookie, CCT_RESULT, &pDataObject)) ||
  2129. FAILED(m_pFolder->m_pComponent->m_pConsole->QueryInterface(IID_IPropertySheetProvider,
  2130. (void**) &pSheetProvider)) ||
  2131. S_OK == pSheetProvider->FindPropertySheet((MMC_COOKIE)pCookie, pComponent, pDataObject) ||
  2132. S_OK != pExtendSheet->QueryPagesFor(pDataObject)) {
  2133. return S_FALSE;
  2134. }
  2135. hr = pSheetProvider->CreatePropertySheet(
  2136. pCookie->GetResultItem()->GetDisplayName(),
  2137. TRUE, // not wizard
  2138. (MMC_COOKIE)pCookie, pDataObject,
  2139. MMC_PSO_NOAPPLYNOW // do not want the apply button
  2140. );
  2141. if (SUCCEEDED(hr)) {
  2142. HWND hNotifyWindow;
  2143. if (!SUCCEEDED(m_pFolder->m_pComponent->m_pConsole->GetMainWindow(&hNotifyWindow)))
  2144. hNotifyWindow = NULL;
  2145. hNotifyWindow = FindWindowEx(hNotifyWindow, NULL, TEXT("MDIClient"), NULL);
  2146. hNotifyWindow = FindWindowEx(hNotifyWindow, NULL, TEXT("MMCChildFrm"), NULL);
  2147. hNotifyWindow = FindWindowEx(hNotifyWindow, NULL, TEXT("MMCView"), NULL);
  2148. hr = pSheetProvider->AddPrimaryPages(pComponent, TRUE, hNotifyWindow, FALSE);
  2149. if (SUCCEEDED(hr)) {
  2150. pSheetProvider->AddExtensionPages();
  2151. hr = pSheetProvider->Show((LONG_PTR)hwndTV, 0);
  2152. } else {
  2153. //
  2154. // Failed to add primary Component's property page, destroy
  2155. // the property sheet
  2156. //
  2157. pSheetProvider->Show(-1, 0);
  2158. }
  2159. }
  2160. return hr;
  2161. }
  2162. // This function creates a context menu for the given cookie
  2163. // INPUT:
  2164. // hwndTV -- the TV OCX window, as the window the context menu to be
  2165. // attached to.
  2166. // pCookie -- the cookie
  2167. // pPoint -- the location where the context menu should anchor in
  2168. // screen coordinate.
  2169. HRESULT
  2170. CResultView::DoContextMenu(
  2171. HWND hwndTV,
  2172. CCookie* pCookie,
  2173. POINT* pPoint
  2174. )
  2175. {
  2176. HRESULT hr = S_FALSE;
  2177. CMachine *pMachine = NULL;
  2178. //
  2179. // ISSUE: JasonC 8/14/99
  2180. //
  2181. // If we have a valid cookie then we need to get the CMachine for the given
  2182. // cookie if there is one. Then we need to disable refreshing while the
  2183. // context menu is being displayed. The reason for this is that if we
  2184. // refresh while the menu is displayed but before the user chooses an option
  2185. // then the cookie is no longer valid. The real problem here is that we rebuild
  2186. // all of the classes on a refresh which makes any cookie floating around invalid.
  2187. // I am sure that there is more of these bugs lurking around in the code and this
  2188. // needs to be addressed by a better overall change after NT 5.0.
  2189. //
  2190. if (pCookie) {
  2191. CDevice *pDevice;
  2192. CResource *pResource;
  2193. CClass *pClass;
  2194. switch (pCookie->GetType()) {
  2195. case COOKIE_TYPE_RESULTITEM_DEVICE:
  2196. pDevice = (CDevice*)pCookie->GetResultItem();
  2197. if (pDevice) {
  2198. pMachine = pDevice->m_pMachine;
  2199. }
  2200. break;
  2201. case COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ:
  2202. case COOKIE_TYPE_RESULTITEM_RESOURCE_DMA:
  2203. case COOKIE_TYPE_RESULTITEM_RESOURCE_IO:
  2204. case COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY:
  2205. pResource = (CResource*)pCookie->GetResultItem();
  2206. if (pResource) {
  2207. pDevice = pResource->GetDevice();
  2208. if (pDevice) {
  2209. pMachine = pDevice->m_pMachine;
  2210. }
  2211. }
  2212. break;
  2213. case COOKIE_TYPE_RESULTITEM_CLASS:
  2214. pClass = (CClass*)pCookie->GetResultItem();
  2215. if (pClass) {
  2216. pMachine = pClass->m_pMachine;
  2217. }
  2218. break;
  2219. default:
  2220. pMachine = NULL;
  2221. }
  2222. }
  2223. //
  2224. // Disable Refreshing while the context menu is up.
  2225. //
  2226. if (pMachine) {
  2227. pMachine->EnableRefresh(FALSE);
  2228. }
  2229. SafeInterfacePtr<IDataObject> pDataObject;
  2230. SafeInterfacePtr<IContextMenuProvider> pMenuProvider;
  2231. SafeInterfacePtr<IComponent> pComponent;
  2232. pComponent.Attach((IComponent*)m_pFolder->m_pComponent);
  2233. m_hwndTV = hwndTV;
  2234. if (FAILED(pComponent->QueryDataObject((MMC_COOKIE)pCookie, CCT_RESULT, &pDataObject)) ||
  2235. FAILED(m_pFolder->m_pComponent->m_pConsole->QueryInterface(IID_IContextMenuProvider,
  2236. (void**)&pMenuProvider))) {
  2237. hr = S_FALSE;
  2238. goto clean0;
  2239. }
  2240. pMenuProvider->EmptyMenuList();
  2241. CONTEXTMENUITEM MenuItem;
  2242. MenuItem.strName = NULL;
  2243. MenuItem.strStatusBarText = NULL;
  2244. MenuItem.lCommandID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
  2245. MenuItem.lInsertionPointID = 0;
  2246. MenuItem.fFlags = 0;
  2247. MenuItem.fSpecialFlags = CCM_SPECIAL_INSERTION_POINT;
  2248. if (SUCCEEDED(pMenuProvider->AddItem(&MenuItem)) &&
  2249. SUCCEEDED(pMenuProvider->AddPrimaryExtensionItems(pComponent,
  2250. pDataObject)) &&
  2251. SUCCEEDED(pMenuProvider->AddThirdPartyExtensionItems(pDataObject))) {
  2252. long Selected;
  2253. pMenuProvider->ShowContextMenu(hwndTV, pPoint->x, pPoint->y, &Selected);
  2254. hr = S_OK;
  2255. goto clean0;
  2256. }
  2257. clean0:
  2258. //
  2259. // Enable Refreshing again now that the context menu is gone
  2260. //
  2261. if (pMachine) {
  2262. pMachine->EnableRefresh(TRUE);
  2263. }
  2264. return hr;
  2265. }
  2266. HRESULT
  2267. CResultView::DoPrint()
  2268. {
  2269. DWORD ReportTypeEnableMask;
  2270. ReportTypeEnableMask = REPORT_TYPE_MASK_ALL;
  2271. HTREEITEM hSelectedItem;
  2272. CCookie* pCookie = NULL;
  2273. m_pMachine->EnableRefresh(FALSE);
  2274. if (m_pIDMTVOCX) {
  2275. hSelectedItem = m_pIDMTVOCX->GetSelectedItem();
  2276. if (hSelectedItem) {
  2277. TV_ITEM TI;
  2278. TI.hItem = hSelectedItem;
  2279. TI.mask = TVIF_PARAM;
  2280. if (SUCCEEDED(m_pIDMTVOCX->GetItem(&TI))) {
  2281. pCookie = (CCookie*)TI.lParam;
  2282. }
  2283. }
  2284. }
  2285. if (!pCookie || (COOKIE_TYPE_RESULTITEM_RESOURCE_IRQ != pCookie->GetType() &&
  2286. COOKIE_TYPE_RESULTITEM_RESOURCE_DMA != pCookie->GetType() &&
  2287. COOKIE_TYPE_RESULTITEM_RESOURCE_IO != pCookie->GetType() &&
  2288. COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY != pCookie->GetType() &&
  2289. COOKIE_TYPE_RESULTITEM_DEVICE != pCookie->GetType() &&
  2290. COOKIE_TYPE_RESULTITEM_CLASS != pCookie->GetType())) {
  2291. ReportTypeEnableMask &= ~(REPORT_TYPE_MASK_CLASSDEVICE);
  2292. }
  2293. if (!g_PrintDlg.PrintDlg(m_pMachine->OwnerWindow(), ReportTypeEnableMask)) {
  2294. m_pMachine->EnableRefresh(TRUE);
  2295. return S_OK;
  2296. }
  2297. if (!g_PrintDlg.HDC()) {
  2298. m_pMachine->EnableRefresh(TRUE);
  2299. return E_OUTOFMEMORY;
  2300. }
  2301. //
  2302. // Create the printer
  2303. //
  2304. CPrinter ThePrinter(m_pMachine->OwnerWindow(), g_PrintDlg.HDC());
  2305. TCHAR DocTitle[MAX_PATH];
  2306. LoadString(g_hInstance, IDS_PRINT_DOC_TITLE, DocTitle, ARRAYLEN(DocTitle));
  2307. int PrintStatus = 0;
  2308. switch (g_PrintDlg.ReportType()) {
  2309. case REPORT_TYPE_SUMMARY:
  2310. PrintStatus = ThePrinter.StartDoc(DocTitle);
  2311. if (PrintStatus) {
  2312. ThePrinter.SetPageTitle(IDS_PRINT_SUMMARY_PAGE_TITLE);
  2313. PrintStatus = ThePrinter.PrintResourceSummary(*m_pMachine);
  2314. }
  2315. break;
  2316. case REPORT_TYPE_CLASSDEVICE:
  2317. ASSERT(pCookie);
  2318. PrintStatus = ThePrinter.StartDoc(DocTitle);
  2319. if (PrintStatus) {
  2320. ThePrinter.SetPageTitle(IDS_PRINT_CLASSDEVICE_PAGE_TITLE);
  2321. if (COOKIE_TYPE_RESULTITEM_CLASS == pCookie->GetType()) {
  2322. PrintStatus = ThePrinter.PrintClass((CClass*)pCookie->GetResultItem());
  2323. } else {
  2324. CDevice* pDevice;
  2325. if (COOKIE_TYPE_RESULTITEM_DEVICE == pCookie->GetType()) {
  2326. pDevice = (CDevice*) pCookie->GetResultItem();
  2327. } else {
  2328. //
  2329. // This is a resource item, get the pointer for the
  2330. // device object from the resource object.
  2331. //
  2332. CResource* pResource = (CResource*) pCookie->GetResultItem();
  2333. ASSERT(pResource);
  2334. pDevice = pResource->GetDevice();
  2335. }
  2336. ASSERT(pDevice);
  2337. PrintStatus = ThePrinter.PrintDevice(pDevice);
  2338. }
  2339. }
  2340. break;
  2341. case REPORT_TYPE_SUMMARY_CLASSDEVICE:
  2342. PrintStatus = ThePrinter.StartDoc(DocTitle);
  2343. if (PrintStatus) {
  2344. ThePrinter.SetPageTitle(IDS_PRINT_SUMMARY_CLASSDEVICE_PAGE_TITLE);
  2345. PrintStatus = ThePrinter.PrintAll(*m_pMachine);
  2346. }
  2347. break;
  2348. default:
  2349. ASSERT(FALSE);
  2350. break;
  2351. }
  2352. //
  2353. // Flush the last page
  2354. //
  2355. ThePrinter.FlushPage();
  2356. if (PrintStatus) {
  2357. ThePrinter.EndDoc();
  2358. } else {
  2359. ThePrinter.AbortDoc();
  2360. }
  2361. m_pMachine->EnableRefresh(TRUE);
  2362. return S_OK;
  2363. }
  2364. HRESULT
  2365. CResultView::RemoveDevice(
  2366. CDevice* pDevice
  2367. )
  2368. {
  2369. //
  2370. // Must be an admin and on the local machine to remove a device.
  2371. //
  2372. if (!m_pMachine->IsLocal() || !g_IsAdmin) {
  2373. return S_FALSE;
  2374. }
  2375. //
  2376. // Make sure the device can be uninstalled
  2377. //
  2378. if (!pDevice->IsUninstallable()) {
  2379. return S_FALSE;
  2380. }
  2381. //
  2382. // Make sure there is no property sheet up for this device.
  2383. // If it does exist, show a message box for the user and bring up
  2384. // the property sheet to the foreground if the user
  2385. // agree to do so.
  2386. //
  2387. HWND hwndPropSheet;
  2388. hwndPropSheet = pDevice->m_psd.GetWindowHandle();
  2389. int MsgBoxResult;
  2390. TCHAR szText[MAX_PATH];
  2391. if (hwndPropSheet) {
  2392. LoadResourceString(IDS_PROPSHEET_WARNING, szText, ARRAYLEN(szText));
  2393. MsgBoxResult = m_pFolder->m_pComponent->MessageBox(szText,
  2394. pDevice->GetDisplayName(),
  2395. MB_ICONEXCLAMATION | MB_OKCANCEL);
  2396. if (IDOK == MsgBoxResult) {
  2397. SetForegroundWindow(hwndPropSheet);
  2398. }
  2399. //
  2400. // Can not wait for the property sheet because it is running
  2401. // in a separate thread.
  2402. //
  2403. return S_OK;
  2404. }
  2405. BOOL Refresh = (pDevice->IsPhantom() ||
  2406. pDevice->HasProblem() ||
  2407. !pDevice->IsStarted());
  2408. CRemoveDevDlg TheDlg(pDevice);
  2409. //
  2410. // Before removing device, disable refresh. This effectively disables
  2411. // device change notification processing. While we are in the middle
  2412. // of removing device, it is not a good idea to process any
  2413. // device change notification. When the removal is done,
  2414. // we will re-enable the refresh.
  2415. //
  2416. m_pMachine->EnableRefresh(FALSE);
  2417. if (IDOK == TheDlg.DoModal(m_hwndTV, (LPARAM) &TheDlg)) {
  2418. DWORD DiFlags;
  2419. DiFlags = m_pMachine->DiGetFlags(*pDevice);
  2420. //
  2421. // We don't check to see if we are running locally at this
  2422. // point because we won't let the user remove the device in
  2423. // the first place if we are not running locally.
  2424. //
  2425. if (PromptForRestart(NULL, DiFlags, IDS_REMOVEDEV_RESTART) == IDNO) {
  2426. Refresh = TRUE;
  2427. }
  2428. //
  2429. // Enable refresh since we disabled it in the beginning.
  2430. //
  2431. // We only need to force a refresh here if the device that
  2432. // was removed was a Phantom device or a device that is not
  2433. // started. This is because Phantom devices don't have kernel
  2434. // devnodes and so they won't generate a WM_DEVICECHANGE like
  2435. // live started devnodes will.
  2436. //
  2437. if (Refresh) {
  2438. m_pMachine->ScheduleRefresh();
  2439. }
  2440. m_pMachine->EnableRefresh(TRUE);
  2441. }
  2442. else {
  2443. m_pMachine->EnableRefresh(TRUE);
  2444. }
  2445. return S_OK;
  2446. }
  2447. /////////////////////////////////////////////////////////////////////
  2448. //// CViewDeviceTree implementations
  2449. ////
  2450. HRESULT
  2451. CViewDeviceTree::OnShow(
  2452. BOOL fShow
  2453. )
  2454. {
  2455. if (!fShow) {
  2456. return S_OK;
  2457. }
  2458. if (!m_pCookieComputer) {
  2459. CreateDeviceTree();
  2460. }
  2461. return CResultView::OnShow(fShow);
  2462. }
  2463. // This function creates a the root device for the device tree.
  2464. // INPUT:
  2465. // NONE.
  2466. // OUTPUT:
  2467. // TRUE if the device is created(Rooted at m_pCookieComputer).
  2468. // FALSE if the device is not created.
  2469. BOOL
  2470. CViewDeviceTree::CreateDeviceTree()
  2471. {
  2472. ASSERT(NULL == m_pCookieComputer);
  2473. m_pMachine = m_pFolder->m_pMachine;
  2474. //
  2475. // We shouldn't be here if there is not a machine created.
  2476. //
  2477. ASSERT(m_pMachine);
  2478. CComputer* pComputer = m_pMachine->m_pComputer;
  2479. //
  2480. // Make sure there is at least a computer
  2481. //
  2482. if (pComputer) {
  2483. m_pCookieComputer = new CCookie(COOKIE_TYPE_RESULTITEM_COMPUTER);
  2484. if (m_pCookieComputer) {
  2485. m_pCookieComputer->SetResultItem(pComputer);
  2486. m_pCookieComputer->SetScopeItem(m_pFolder->m_pScopeItem);
  2487. //
  2488. // Make sure that the computer is expanded and selected.
  2489. //
  2490. m_pCookieComputer->TurnOnFlags(COOKIE_FLAGS_EXPANDED);
  2491. //
  2492. // If there was no selection, choose the computer
  2493. //
  2494. if (!m_pSelectedItem || (*m_pSelectedItem == *m_pCookieComputer)) {
  2495. m_pSelectedCookie = m_pCookieComputer;
  2496. }
  2497. return TRUE;
  2498. }
  2499. }
  2500. return FALSE;
  2501. }
  2502. /////////////////////////////////////////////////////////////////////
  2503. //// CViewTreeByType implementations
  2504. ////
  2505. // This function creates a "view-by-type: device tree rooted at
  2506. // m_pCookieComputer.
  2507. //
  2508. // INPUT:
  2509. // NONE.
  2510. // OUTPUT:
  2511. // TRUE if the tree is created successfully.
  2512. // FALSE if tree is not created.
  2513. BOOL
  2514. CViewTreeByType::CreateDeviceTree()
  2515. {
  2516. if (!CViewDeviceTree::CreateDeviceTree()) {
  2517. return FALSE;
  2518. }
  2519. ASSERT(m_pCookieComputer);
  2520. CClass* pClass;
  2521. CDevice* pDevice;
  2522. CCookie* pCookieClass;
  2523. CCookie* pCookieClassParent;
  2524. CCookie* pCookieClassSibling;
  2525. CCookie* pCookieDevice;
  2526. CCookie* pCookieDeviceParent;
  2527. CCookie* pCookieDeviceSibling;
  2528. //
  2529. // Do not have sibling at this moment;
  2530. //
  2531. pCookieClassSibling = NULL;
  2532. //
  2533. // All classes are children of computer
  2534. //
  2535. pCookieClassParent = m_pCookieComputer;
  2536. pCookieDeviceParent;
  2537. pCookieDeviceSibling;
  2538. String strStartupDeviceId;
  2539. strStartupDeviceId = GetStartupDeviceId();
  2540. PVOID ContextClass, ContextDevice;
  2541. if (m_pMachine->GetFirstClass(&pClass, ContextClass)) {
  2542. do {
  2543. //
  2544. // We do not display a class if it does not have any
  2545. // devices in it.
  2546. //
  2547. if (pClass->GetNumberOfDevices(TRUE)) {
  2548. pCookieClass = new CCookie(COOKIE_TYPE_RESULTITEM_CLASS);
  2549. pCookieClass->SetResultItem(pClass);
  2550. pCookieClass->SetScopeItem(m_pFolder->m_pScopeItem);
  2551. //
  2552. // If the class was expanded before, mark it
  2553. // so that DisplayTree will expand it
  2554. //
  2555. RestoreSavedTreeState(pCookieClass);
  2556. //
  2557. // No sibling: this is the first child
  2558. //
  2559. if (pCookieClassParent && !pCookieClassSibling) {
  2560. pCookieClassParent->SetChild(pCookieClass);
  2561. }
  2562. pCookieClass->SetParent(pCookieClassParent);
  2563. if (pCookieClassSibling) {
  2564. pCookieClassSibling->SetSibling(pCookieClass);
  2565. }
  2566. pCookieClassSibling = pCookieClass;
  2567. //
  2568. // Classes are parent of devices
  2569. //
  2570. pCookieDeviceParent = pCookieClass;
  2571. pCookieDeviceSibling = NULL;
  2572. if (pClass->GetFirstDevice(&pDevice, ContextDevice)) {
  2573. do {
  2574. pCookieDevice = new CCookie(COOKIE_TYPE_RESULTITEM_DEVICE);
  2575. pCookieDevice->SetResultItem(pDevice);
  2576. pCookieDevice->SetScopeItem(m_pFolder->m_pScopeItem);
  2577. if (!strStartupDeviceId.IsEmpty() &&
  2578. !strStartupDeviceId.CompareNoCase(pDevice->GetDeviceID())) {
  2579. m_pSelectedCookie = pCookieDevice;
  2580. } else {
  2581. if (m_pSelectedItem && (*m_pSelectedItem == *pCookieDevice)) {
  2582. m_pSelectedCookie = pCookieDevice;
  2583. }
  2584. }
  2585. //
  2586. // No sibling: this is the first child
  2587. //
  2588. if (pCookieDeviceParent && !pCookieDeviceSibling) {
  2589. pCookieDeviceParent->SetChild(pCookieDevice);
  2590. }
  2591. pCookieDevice->SetParent(pCookieDeviceParent);
  2592. if (pCookieDeviceSibling) {
  2593. pCookieDeviceSibling->SetSibling(pCookieDevice);
  2594. }
  2595. pCookieDeviceSibling = pCookieDevice;
  2596. } while (pClass->GetNextDevice(&pDevice, ContextDevice));
  2597. }
  2598. }
  2599. } while (m_pMachine->GetNextClass(&pClass, ContextClass));
  2600. }
  2601. DestroySavedTreeStates();
  2602. return TRUE;
  2603. }
  2604. /////////////////////////////////////////////////////////////////////
  2605. //// CViewTreeByConnection implementations
  2606. ////
  2607. BOOL
  2608. CViewTreeByConnection::CreateDeviceTree()
  2609. {
  2610. if (!CViewDeviceTree::CreateDeviceTree()) {
  2611. return FALSE;
  2612. }
  2613. ASSERT(m_pCookieComputer);
  2614. CComputer* pComputer = (CComputer*)m_pCookieComputer->GetResultItem();
  2615. CDevice* pDeviceStart = pComputer->GetChild();
  2616. ASSERT(pDeviceStart);
  2617. //
  2618. // Collect all the normal devices.
  2619. //
  2620. CreateSubtree(m_pCookieComputer, NULL, pDeviceStart);
  2621. //
  2622. // Add phantom devices to m_pCookieComputer subtree.
  2623. //
  2624. PVOID Context;
  2625. if (m_pMachine->GetFirstDevice(&pDeviceStart, Context)) {
  2626. //
  2627. // Locate the end of the CookieComputer Sibling list to add the
  2628. // phantom devices to.
  2629. //
  2630. CCookie* pCookieSibling = NULL;
  2631. CCookie* pNext = m_pCookieComputer->GetChild();
  2632. while (pNext != NULL) {
  2633. pCookieSibling = pNext;
  2634. pNext = pCookieSibling->GetSibling();
  2635. }
  2636. do {
  2637. if (pDeviceStart->IsPhantom()) {
  2638. CCookie* pCookie;
  2639. pCookie = new CCookie(COOKIE_TYPE_RESULTITEM_DEVICE);
  2640. pCookie->SetResultItem(pDeviceStart);
  2641. pCookie->SetScopeItem(m_pFolder->m_pScopeItem);
  2642. if (pCookieSibling) {
  2643. pCookieSibling->SetSibling(pCookie);
  2644. } else {
  2645. m_pCookieComputer->SetChild(pCookie);
  2646. }
  2647. pCookie->SetParent(m_pCookieComputer);
  2648. pCookieSibling = pCookie;
  2649. //
  2650. // See if we have to expand the node
  2651. //
  2652. RestoreSavedTreeState(pCookie);
  2653. }
  2654. } while (m_pMachine->GetNextDevice(&pDeviceStart, Context));
  2655. }
  2656. DestroySavedTreeStates();
  2657. return TRUE;
  2658. }
  2659. //
  2660. //This function creates a cookie subtree by walking down the
  2661. //a device subtree led by the given pDeviceStart
  2662. //INPUT:
  2663. // pCookieParent -- the parent of the newly created subtree
  2664. // pCookieSibling -- the sibling of the newly create subtree
  2665. // pDeviceStart -- the device to start with
  2666. //
  2667. //OUTPUT:
  2668. // TRUE if the subtree is created and inserted successfully.
  2669. //
  2670. // This function may throw CMemoryException
  2671. //
  2672. BOOL
  2673. CViewTreeByConnection::CreateSubtree(
  2674. CCookie* pCookieParent,
  2675. CCookie* pCookieSibling,
  2676. CDevice* pDeviceStart
  2677. )
  2678. {
  2679. CCookie* pCookie;
  2680. CDevice* pDeviceChild;
  2681. String strStartupDeviceId;
  2682. CClass* pClass;
  2683. strStartupDeviceId = GetStartupDeviceId();
  2684. while (pDeviceStart) {
  2685. pClass = pDeviceStart->GetClass();
  2686. pCookie = new CCookie(COOKIE_TYPE_RESULTITEM_DEVICE);
  2687. if (pCookie) {
  2688. pCookie->SetResultItem(pDeviceStart);
  2689. pCookie->SetScopeItem(m_pFolder->m_pScopeItem);
  2690. if (!strStartupDeviceId.IsEmpty() &&
  2691. !strStartupDeviceId.CompareNoCase(pDeviceStart->GetDeviceID())) {
  2692. m_pSelectedCookie = pCookie;
  2693. }
  2694. //
  2695. // No sibling: this is the first child
  2696. //
  2697. if (pCookieParent && !pCookieSibling) {
  2698. pCookieParent->SetChild(pCookie);
  2699. }
  2700. pCookie->SetParent(pCookieParent);
  2701. if (pCookieSibling) {
  2702. pCookieSibling->SetSibling(pCookie);
  2703. }
  2704. //
  2705. // See if we have to expand the node
  2706. //
  2707. RestoreSavedTreeState(pCookie);
  2708. pDeviceChild = pDeviceStart->GetChild();
  2709. if (pDeviceChild) {
  2710. CreateSubtree(pCookie, NULL, pDeviceChild);
  2711. }
  2712. pCookieSibling = pCookie;
  2713. }
  2714. pDeviceStart = pDeviceStart->GetSibling();
  2715. }
  2716. return TRUE;
  2717. }
  2718. /////////////////////////////////////////////////////////////////////
  2719. //// CViewResourceTree implementations
  2720. ////
  2721. CViewResourceTree::~CViewResourceTree()
  2722. {
  2723. int i;
  2724. //
  2725. // Destroy all the CResource objects
  2726. //
  2727. for (i = 0; i < TOTAL_RESOURCE_TYPES; i++) {
  2728. if (m_pResourceList[i]) {
  2729. delete m_pResourceList[i];
  2730. m_pResourceList[i] = NULL;
  2731. }
  2732. if (m_pResourceType[i]) {
  2733. delete m_pResourceType[i];
  2734. m_pResourceType[i] = NULL;
  2735. }
  2736. }
  2737. }
  2738. //
  2739. // This functions handle MMC standard MMCN_SHOW command
  2740. //
  2741. // This function may throw CMemoryException
  2742. //
  2743. HRESULT
  2744. CViewResourceTree::OnShow(
  2745. BOOL fShow
  2746. )
  2747. {
  2748. if (!fShow) {
  2749. return S_OK;
  2750. }
  2751. if (!m_pCookieComputer) {
  2752. CreateResourceTree();
  2753. }
  2754. return CResultView::OnShow(fShow);
  2755. }
  2756. //
  2757. // This function creates resource lists and cookie trees.
  2758. // The resources are recorded in the member m_pResourceList[]
  2759. // and the cookie tree is rooted at m_pCookieComputer[];
  2760. //
  2761. // This function may throw CMemoryException
  2762. //
  2763. void
  2764. CViewResourceTree::CreateResourceTree()
  2765. {
  2766. int i;
  2767. CCookie* pCookieTypeSibling = NULL;
  2768. ASSERT(!m_pCookieComputer);
  2769. m_pMachine = m_pFolder->m_pMachine;
  2770. ASSERT(m_pMachine);
  2771. //
  2772. // Make sure there is at least a computer.
  2773. //
  2774. if (!m_pMachine->m_pComputer) {
  2775. return;
  2776. }
  2777. m_pCookieComputer = new CCookie(COOKIE_TYPE_RESULTITEM_COMPUTER);
  2778. if (!m_pCookieComputer) {
  2779. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2780. return;
  2781. }
  2782. m_pCookieComputer->SetResultItem(m_pMachine->m_pComputer);
  2783. m_pCookieComputer->SetScopeItem(m_pFolder->m_pScopeItem);
  2784. m_pCookieComputer->TurnOnFlags(COOKIE_FLAGS_EXPANDED);
  2785. //
  2786. // If no selected item recorded, default to the computer node
  2787. //
  2788. if (!m_pSelectedItem || (*m_pSelectedItem == *m_pCookieComputer)) {
  2789. m_pSelectedCookie = m_pCookieComputer;
  2790. }
  2791. //
  2792. // Check each resource type (mem, io, dma, irq) and create a result item
  2793. // if resources exist for the resource type.
  2794. //
  2795. for (i = 0; i < TOTAL_RESOURCE_TYPES; i++) {
  2796. RESOURCEID ResType = ResourceTypes[i];
  2797. //
  2798. // If there is an existing m_pResourceList then delete it.
  2799. //
  2800. if (m_pResourceList[i]) {
  2801. delete m_pResourceList[i];
  2802. }
  2803. m_pResourceList[i] = new CResourceList(m_pMachine, ResType);
  2804. PVOID Context;
  2805. CResource* pRes;
  2806. if (m_pResourceList[i] &&
  2807. m_pResourceList[i]->GetFirst(&pRes, Context)) {
  2808. //
  2809. // Resource items exist, create the resource type result item.
  2810. //
  2811. CCookie* pCookieFirst = NULL;
  2812. //
  2813. // If there is an existing m_pResourceType then delete it.
  2814. //
  2815. if (m_pResourceType[i]) {
  2816. delete m_pResourceType[i];
  2817. }
  2818. m_pResourceType[i] = new CResourceType(m_pMachine, ResType);
  2819. CCookie* pCookieType = new CCookie(COOKIE_TYPE_RESULTITEM_RESTYPE);
  2820. if (pCookieType) {
  2821. pCookieType->SetResultItem(m_pResourceType[i]);
  2822. pCookieType->SetScopeItem(m_pFolder->m_pScopeItem);
  2823. pCookieType->SetParent(m_pCookieComputer);
  2824. if (pCookieTypeSibling) {
  2825. pCookieTypeSibling->SetSibling(pCookieType);
  2826. } else {
  2827. m_pCookieComputer->SetChild(pCookieType);
  2828. }
  2829. pCookieTypeSibling = pCookieType;
  2830. RestoreSavedTreeState(pCookieType);
  2831. //
  2832. // Create the resource result item for each resource.
  2833. //
  2834. while (pRes) {
  2835. CCookie* pCookie = new CCookie(CookieType(ResType));
  2836. pCookie->SetResultItem(pRes);
  2837. pCookie->SetScopeItem(m_pFolder->m_pScopeItem);
  2838. if (pCookieFirst) {
  2839. InsertCookieToTree(pCookie, pCookieFirst, TRUE);
  2840. } else {
  2841. pCookieFirst = pCookie;
  2842. pCookieType->SetChild(pCookie);
  2843. pCookie->SetParent(pCookieType);
  2844. }
  2845. RestoreSavedTreeState(pCookie);
  2846. //
  2847. // Get the next resource item.
  2848. //
  2849. m_pResourceList[i]->GetNext(&pRes, Context);
  2850. }
  2851. }
  2852. }
  2853. }
  2854. //
  2855. // The saved tree states have been merged into the newly
  2856. // create cookie tree. destroy the states
  2857. //
  2858. DestroySavedTreeStates();
  2859. }
  2860. //
  2861. // This function insert the given cookie into a existing cookie subtree
  2862. // rooted at pCookieRoot. If the resource is I/O or MEMORY then the cookie is
  2863. // inserted as a child of any resource it is enclosed by.
  2864. //
  2865. //INPUT:
  2866. // pCookie -- the cookie to be inserted.
  2867. // pCookieRoot -- the subtree root cookie
  2868. // ForcedInsert -- TRUE to insert the cookie as the sibling of
  2869. // of pCookieRoot.
  2870. //OUTPUT:
  2871. // None
  2872. BOOL
  2873. CViewResourceTree::InsertCookieToTree(
  2874. CCookie* pCookie,
  2875. CCookie* pCookieRoot,
  2876. BOOL ForcedInsert
  2877. )
  2878. {
  2879. CResource* pResRef;
  2880. CResource* pResThis = (CResource*)pCookie->GetResultItem();
  2881. CCookie* pCookieLast = NULL;
  2882. while (pCookieRoot) {
  2883. //
  2884. // Only check for enclosed resources for I/O and MEMORY.
  2885. //
  2886. if (COOKIE_TYPE_RESULTITEM_RESOURCE_IO == pCookie->GetType() ||
  2887. COOKIE_TYPE_RESULTITEM_RESOURCE_MEMORY == pCookie->GetType()) {
  2888. pResRef = (CResource*)pCookieRoot->GetResultItem();
  2889. if (pResThis->EnclosedBy(*pResRef)) {
  2890. //
  2891. // This cookie is either the pCookieRoot child or grand child
  2892. // figure out which one it is
  2893. //
  2894. if (!pCookieRoot->GetChild()) {
  2895. pCookieRoot->SetChild(pCookie);
  2896. pCookie->SetParent(pCookieRoot);
  2897. } else if (!InsertCookieToTree(pCookie, pCookieRoot->GetChild(), FALSE)) {
  2898. //
  2899. // The cookie is not a grand child of pCookieRoot.
  2900. // search for the last child of pCookieRoot
  2901. //
  2902. CCookie* pCookieSibling;
  2903. pCookieSibling = pCookieRoot->GetChild();
  2904. while (pCookieSibling->GetSibling()) {
  2905. pCookieSibling = pCookieSibling->GetSibling();
  2906. }
  2907. pCookieSibling->SetSibling(pCookie);
  2908. pCookie->SetParent(pCookieRoot);
  2909. }
  2910. return TRUE;
  2911. }
  2912. }
  2913. pCookieLast = pCookieRoot;
  2914. pCookieRoot = pCookieRoot->GetSibling();
  2915. }
  2916. if (ForcedInsert) {
  2917. if (pCookieLast) {
  2918. //
  2919. // When we reach here, pCookieLast is the last child
  2920. //
  2921. pCookieLast->SetSibling(pCookie);
  2922. pCookie->SetParent(pCookieLast->GetParent());
  2923. }
  2924. return TRUE;
  2925. }
  2926. return FALSE;
  2927. }
  2928. /////////////////////////////////////////////////////////////////////
  2929. //// CBusPropPageProvider implementations
  2930. ////
  2931. //
  2932. // This function loads the bus property sheet pages provider
  2933. // to enumerate pages for the device
  2934. // INPUT:
  2935. // pDevice -- object represents the device
  2936. // ppsd -- object represents where property pages should be added
  2937. // OUTPUT:
  2938. // TRUE if succeeded.
  2939. // FLASE if no pages are added.
  2940. BOOL
  2941. CBusPropPageProvider::EnumPages(
  2942. CDevice* pDevice,
  2943. CPropSheetData* ppsd
  2944. )
  2945. {
  2946. ASSERT(!m_hDll);
  2947. //
  2948. // Enum bus property pages if there are any
  2949. // if the a bus guid can not be found on the device, no bus property pages
  2950. //
  2951. String strBusGuid;
  2952. if (pDevice->m_pMachine->CmGetBusGuidString(pDevice->GetDevNode(), strBusGuid)) {
  2953. CSafeRegistry regDevMgr;
  2954. CSafeRegistry regBusTypes;
  2955. CSafeRegistry regBus;
  2956. if (regDevMgr.Open(HKEY_LOCAL_MACHINE, REG_PATH_DEVICE_MANAGER) &&
  2957. regBusTypes.Open(regDevMgr, REG_STR_BUS_TYPES) &&
  2958. regBus.Open(regBusTypes, strBusGuid)) {
  2959. String strEnumPropPage;
  2960. if (regBus.GetValue(REGSTR_VAL_ENUMPROPPAGES_32, strEnumPropPage)) {
  2961. PROPSHEET_PROVIDER_PROC PropPageProvider;
  2962. if (LoadEnumPropPage32(strEnumPropPage, &m_hDll, (FARPROC*)&PropPageProvider)) {
  2963. SP_PROPSHEETPAGE_REQUEST PropPageRequest;
  2964. PropPageRequest.cbSize = sizeof(PropPageRequest);
  2965. PropPageRequest.DeviceInfoSet = (HDEVINFO)*(pDevice->m_pMachine);
  2966. PropPageRequest.DeviceInfoData = *pDevice;
  2967. PropPageRequest.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
  2968. if (PropPageProvider(&PropPageRequest,
  2969. (LPFNADDPROPSHEETPAGE)AddPropPageCallback,
  2970. (LPARAM)ppsd
  2971. ))
  2972. return TRUE;
  2973. }
  2974. }
  2975. }
  2976. }
  2977. return FALSE;
  2978. }