Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3625 lines
107 KiB

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