Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1148 lines
26 KiB

  1. #include "pch.h"
  2. PPCI_TREE
  3. SoftPCI_BuildTree(
  4. VOID
  5. );
  6. VOID
  7. SoftPCI_DisplayTreeMenu(
  8. IN PPCI_DN Pdn,
  9. IN POINT Pt
  10. );
  11. VOID
  12. SoftPCI_DisplayStandardTreeMenu(
  13. IN PPCI_DN Pdn,
  14. IN POINT Pt
  15. );
  16. VOID
  17. SoftPCI_DisplayHotplugTreeMenu(
  18. IN PPCI_DN Pdn,
  19. IN POINT Pt
  20. );
  21. VOID
  22. SoftPCI_FreeBranch(
  23. IN PPCI_DN Dn
  24. );
  25. VOID
  26. SoftPCI_InsertTreeItem(
  27. IN PPCI_DN Pdn,
  28. IN HTREEITEM HtiParent
  29. );
  30. VOID
  31. SoftPCI_ExpandItem(
  32. IN HTREEITEM Hti,
  33. IN PVOID Arg1,
  34. IN PVOID Arg2
  35. );
  36. VOID
  37. SoftPCI_RestoreSelection(
  38. IN HTREEITEM Hti,
  39. IN PVOID Data1,
  40. IN PVOID Data2
  41. );
  42. BOOL g_TreeCreated = FALSE;
  43. BOOL g_TreeLocked = FALSE;
  44. BOOL g_PendingRefresh = FALSE;
  45. PPCI_TREE g_PciTree;
  46. LONG_PTR g_DefTreeWndProc;
  47. PWCHAR g_LastSelection = NULL;
  48. VOID
  49. SoftPCI_CreateTreeView(
  50. VOID
  51. )
  52. {
  53. HTREEITEM htiParent;
  54. TVITEM tvitem;
  55. PPCI_DN rootDevNode = NULL;
  56. HMENU menu = GetMenu(g_SoftPCIMainWnd);
  57. PPCI_DN pdn = NULL;
  58. PCI_DN selectedDevNode;
  59. BOOL selectionFound;
  60. PWCHAR p;
  61. //HCURSOR oldCursor;
  62. //
  63. // Empty the tree.
  64. //
  65. TreeView_DeleteAllItems(g_TreeViewWnd);
  66. if (g_TreeCreated) {
  67. SoftPCI_DestroyTree(g_PciTree);
  68. }
  69. g_PciTree = SoftPCI_BuildTree();
  70. if (!g_PciTree) {
  71. MessageBox(g_SoftPCIMainWnd, L"Failed to create g_PciTree!", L"ERROR", MB_OK);
  72. return;
  73. }
  74. g_TreeCreated = TRUE;
  75. SOFTPCI_ASSERT(g_PciTree->ClassImageListData.ImageList != INVALID_HANDLE_VALUE);
  76. TreeView_SetImageList(g_TreeViewWnd, g_PciTree->ClassImageListData.ImageList, TVSIL_NORMAL);
  77. //
  78. // Insert the rest of the items.
  79. //
  80. SoftPCI_InsertTreeItem(g_PciTree->RootDevNode, TVI_ROOT);
  81. //
  82. // Currently we always expand the entire tree when it is built. Should see
  83. // if there is a way to avoid this....
  84. //
  85. SoftPCI_WalkTree(
  86. g_PciTree->RootTreeItem,
  87. SoftPCI_ExpandItem,
  88. NULL,
  89. NULL
  90. );
  91. //
  92. // Restore last selection if any
  93. //
  94. if (g_LastSelection){
  95. selectionFound = FALSE;
  96. SoftPCI_WalkTree(
  97. g_PciTree->RootTreeItem,
  98. SoftPCI_RestoreSelection,
  99. &selectionFound,
  100. NULL
  101. );
  102. if (!selectionFound) {
  103. //
  104. // If the last selection no longer exists then we back up to the
  105. // parent and check one more time.
  106. //
  107. p = g_LastSelection;
  108. p += wcslen(g_LastSelection);
  109. while(*p != '\\'){
  110. p--;
  111. }
  112. *p = 0;
  113. //
  114. // Now run the tree one more time looking for the parent
  115. //
  116. SoftPCI_WalkTree(
  117. g_PciTree->RootTreeItem,
  118. SoftPCI_RestoreSelection,
  119. &selectionFound,
  120. NULL
  121. );
  122. }
  123. }else{
  124. TreeView_Select(g_TreeViewWnd, g_PciTree->RootTreeItem, TVGN_CARET);
  125. TreeView_EnsureVisible(g_TreeViewWnd, g_PciTree->RootTreeItem);
  126. }
  127. SoftPCI_UpdateTabCtrlWindow(g_CurrentTabSelection);
  128. }
  129. PPCI_TREE
  130. SoftPCI_BuildTree(VOID)
  131. /*++
  132. Routine Description:
  133. This function is the entry point for building our PCI_TREE
  134. Arguments:
  135. none
  136. Return Value:
  137. PPCI_TREE we have created
  138. --*/
  139. {
  140. DEVNODE dn = 0;
  141. PPCI_DN pdn;
  142. PPCI_TREE pcitree;
  143. pcitree = (PPCI_TREE) calloc(1, sizeof(PCI_TREE));
  144. if (!pcitree) return NULL;
  145. CM_Locate_DevNode(&dn, NULL, CM_LOCATE_DEVNODE_NORMAL);
  146. SOFTPCI_ASSERT(dn != 0);
  147. pcitree->ClassImageListData.ImageList = INVALID_HANDLE_VALUE ;
  148. pcitree->ClassImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA) ;
  149. if (!SetupDiGetClassImageList(&pcitree->ClassImageListData)){
  150. pcitree->ClassImageListData.ImageList = INVALID_HANDLE_VALUE;
  151. }
  152. pcitree->DevInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL) ;
  153. SOFTPCI_ASSERT(pcitree->DevInfoSet != INVALID_HANDLE_VALUE);
  154. //
  155. // Now find all things PCI and build a PCI_DN tree
  156. //
  157. pdn = NULL;
  158. SoftPCI_EnumerateDevices(pcitree, &pdn, dn, NULL);
  159. pcitree->RootDevNode = pdn;
  160. return pcitree;
  161. }
  162. VOID
  163. SoftPCI_DestroyTree(
  164. IN PPCI_TREE PciTree
  165. )
  166. /*++
  167. Routine Description:
  168. This routine frees all our allocations for the Tree
  169. Arguments:
  170. PciTree - Tree to distroy
  171. Return Value:
  172. none
  173. --*/
  174. {
  175. PPCI_DN dn = PciTree->RootDevNode;
  176. //
  177. // First set the tree view image list to NULL
  178. //
  179. TreeView_SetImageList(g_TreeViewWnd, NULL, TVSIL_NORMAL);
  180. //
  181. // Now free all our allocated PCI_DN structs
  182. //
  183. SoftPCI_FreeBranch(dn);
  184. //
  185. // Destroy our image and info lists
  186. //
  187. if (PciTree->ClassImageListData.ImageList != INVALID_HANDLE_VALUE){
  188. SetupDiDestroyClassImageList(&PciTree->ClassImageListData);
  189. PciTree->ClassImageListData.ImageList = INVALID_HANDLE_VALUE;
  190. }
  191. if (PciTree->DevInfoSet != INVALID_HANDLE_VALUE){
  192. SetupDiDestroyDeviceInfoList(PciTree->DevInfoSet);
  193. PciTree->DevInfoSet = INVALID_HANDLE_VALUE;
  194. }
  195. //
  196. // And finally....
  197. //
  198. free(PciTree);
  199. }
  200. VOID
  201. SoftPCI_DisplayTreeMenu(
  202. IN PPCI_DN Pdn,
  203. IN POINT Pt
  204. )
  205. /*++
  206. Routine Description:
  207. This routine dispatches the menu request to the appropriate menu function
  208. Arguments:
  209. Pdn - PCI_DN of the item we are displaying the menu for
  210. Pt - coordinates for the item
  211. Return Value:
  212. none
  213. --*/
  214. {
  215. if (Pdn->Flags & SOFTPCI_HOTPLUG_SLOT) {
  216. SoftPCI_DisplayHotplugTreeMenu(Pdn,Pt);
  217. } else if (Pdn->Flags & SOFTPCI_UNENUMERATED_DEVICE) {
  218. //
  219. // If it's an unenumerated device (in an unpowered hotplug slot),
  220. // you can't do anything with it.
  221. //
  222. return;
  223. } else {
  224. SoftPCI_DisplayStandardTreeMenu(Pdn, Pt);
  225. }
  226. return;
  227. }
  228. VOID
  229. SoftPCI_DisplayStandardTreeMenu(
  230. IN PPCI_DN Pdn,
  231. IN POINT Pt
  232. )
  233. /*++
  234. Routine Description:
  235. This routine displays the standard context menu when the user right-clicks a device
  236. Arguments:
  237. Pdn - PCI_DN of the slot
  238. Pt - coordinates for the device
  239. Return Value:
  240. none
  241. --*/
  242. {
  243. HMENU menu, popup;
  244. ULONG dnProblem;
  245. BOOL enableDevice = FALSE;
  246. INT selection = 0;
  247. menu = LoadMenu(g_Instance, MAKEINTRESOURCE(IDM_TREEMENU));
  248. if (!menu) {
  249. MessageBox(g_SoftPCIMainWnd, L"failed to display menu!", NULL, MB_OK);
  250. return;
  251. }
  252. popup = GetSubMenu(menu, 0);
  253. //
  254. // If SoftPCI support is not installed or this isnt a bridge device,
  255. // disable the option to add devices.
  256. //
  257. if ((g_DriverHandle == NULL) ||
  258. !SoftPCI_IsBridgeDevice(Pdn)) {
  259. SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
  260. }
  261. if (!SoftPCI_IsSoftPCIDevice(Pdn)) {
  262. SoftPCI_DisableMenuItem(menu, ID_DELETEDEVICE);
  263. SoftPCI_DisableMenuItem(menu, ID_STATICDEVICE);
  264. }
  265. if (SoftPCI_GetDeviceNodeProblem(Pdn->DevNode, &dnProblem)) {
  266. if (dnProblem == CM_PROB_DISABLED) {
  267. enableDevice = TRUE;
  268. SoftPCI_SetMenuItemText(menu, ID_ENABLEDISABLEDEVICE, L"E&nable Device");
  269. }else{
  270. //
  271. // For now we will not allow the option to disable a non-working device
  272. //
  273. SoftPCI_DisableMenuItem(menu, ID_ENABLEDISABLEDEVICE);
  274. }
  275. }
  276. //
  277. // If this device is in a hotplug slot, can't just rip out
  278. // the hardware. You have to go through the appropriate
  279. // mechanism.
  280. //
  281. if (Pdn->Parent && (Pdn->Parent->Flags & SOFTPCI_HOTPLUG_SLOT)) {
  282. SoftPCI_DisableMenuItem(menu, ID_DELETEDEVICE);
  283. }
  284. //
  285. // Make sure it pops up in the right place....
  286. //
  287. ClientToScreen(g_SoftPCIMainWnd, &Pt);
  288. //
  289. // lets see the menu
  290. //
  291. selection = TrackPopupMenuEx(
  292. popup,
  293. TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
  294. Pt.x, Pt.y,
  295. g_SoftPCIMainWnd,
  296. NULL
  297. );
  298. //
  299. // Now we will handle our Floating Tree View menu items
  300. //
  301. switch (selection) {
  302. case ID_INSTALLDEVICE:
  303. DISPLAY_NEWDEV_DLG(Pdn);
  304. break;
  305. case ID_ENABLEDISABLEDEVICE:
  306. SoftPCI_EnableDisableDeviceNode(
  307. Pdn->DevNode,
  308. enableDevice
  309. );
  310. break;
  311. case ID_DELETEDEVICE:
  312. if ((MessageBox(g_SoftPCIMainWnd,
  313. L"This option will delete or surprise remove the device from the system.",
  314. L"WARNING", MB_OKCANCEL)) == IDOK){
  315. //
  316. // Here we tell our driver to delete the specified device. This will
  317. // cause a re-enum of everything that will result in the cleanup
  318. // of this device in user mode.
  319. //
  320. if (!SoftPCI_DeleteDevice(Pdn->SoftDev)) {
  321. MessageBox(g_SoftPCIMainWnd, L"Failed to delete device!", NULL, MB_OK);
  322. }
  323. }
  324. break;
  325. case ID_STATICDEVICE:
  326. if (SoftPCI_SaveDeviceToRegisty(Pdn)){
  327. MessageBox(g_SoftPCIMainWnd, L"Successfully saved devices to registry!", NULL, MB_OK);
  328. }else{
  329. MessageBox(g_SoftPCIMainWnd, L"Failed to save devices to registry!", NULL, MB_OK);
  330. }
  331. break;
  332. case ID_REFRESHTREE:
  333. CM_Reenumerate_DevNode(Pdn->DevNode, 0);
  334. SoftPCI_CreateTreeView();
  335. break;
  336. default:
  337. break;
  338. }
  339. }
  340. VOID
  341. SoftPCI_DisplayHotplugTreeMenu(
  342. IN PPCI_DN Pdn,
  343. IN POINT Pt
  344. )
  345. /*++
  346. Routine Description:
  347. This routine displays the hotplug specific context menu when the user right-clicks a hotplug slot.
  348. Arguments:
  349. Pdn - PCI_DN of the slot
  350. Pt - coordinates for the slot
  351. Return Value:
  352. none
  353. --*/
  354. {
  355. HMENU menu, popup;
  356. INT selection;
  357. PPCI_DN parentDn;
  358. BOOL status;
  359. SHPC_SLOT_STATUS_REGISTER slotStatus;
  360. menu = LoadMenu(g_Instance, MAKEINTRESOURCE(IDM_HOTPLUGSLOTMENU));
  361. if (!menu) {
  362. MessageBox(g_SoftPCIMainWnd, L"failed to display menu!", NULL, MB_OK);
  363. return;
  364. }
  365. popup = GetSubMenu(menu, 0);
  366. //
  367. // If SoftPCI support is not installed disable the option to add devices.
  368. //
  369. if (!g_DriverHandle) {
  370. SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
  371. }
  372. //
  373. // If our Device Property dialog is open dont allow properties to be
  374. // selected again.
  375. //
  376. if (g_NewDevDlg) {
  377. //
  378. // ISSUE: BrandonA - Figure out why we hang if the first Dialog
  379. // launched is killed before the second...
  380. //
  381. SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
  382. }
  383. //
  384. // DWALKER
  385. // Get slot status from driver
  386. // appropriately grey out open/close MRL menu item.
  387. // if MRL is closed, disable removing the device.
  388. //
  389. parentDn = Pdn->Parent;
  390. status = SoftPCI_GetSlotStatus(parentDn,
  391. Pdn->Slot.Function,
  392. &slotStatus
  393. );
  394. if (status == FALSE) {
  395. MessageBox(g_SoftPCIMainWnd, L"failed to display menu!", NULL, MB_OK);
  396. return;
  397. }
  398. //
  399. // If the MRL is closed, you can't insert or remove the device.
  400. // Otherwise, disable the appropriate menu item based on the presence
  401. // of a device in the slot.
  402. //
  403. if (slotStatus.MRLSensorState == SHPC_MRL_CLOSED) {
  404. SoftPCI_DisableMenuItem(menu, ID_REMOVEHPDEVICE);
  405. SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
  406. } else if (Pdn->Child == NULL) {
  407. SoftPCI_DisableMenuItem(menu, ID_REMOVEHPDEVICE);
  408. } else {
  409. SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
  410. }
  411. if (slotStatus.MRLSensorState == SHPC_MRL_CLOSED) {
  412. RemoveMenu(menu, ID_CLOSEMRL, MF_BYCOMMAND);
  413. } else {
  414. RemoveMenu(menu, ID_OPENMRL, MF_BYCOMMAND);
  415. }
  416. AppendMenu(popup, MF_SEPARATOR, 0, NULL);
  417. switch (slotStatus.PowerIndicatorState) {
  418. case SHPC_INDICATOR_OFF:
  419. AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Power Indicator: Off");
  420. break;
  421. case SHPC_INDICATOR_ON:
  422. AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Power Indicator: On");
  423. break;
  424. case SHPC_INDICATOR_BLINK:
  425. AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Power Indicator: Blinking");
  426. break;
  427. case SHPC_INDICATOR_NOP:
  428. AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Power Indicator: Unspecified");
  429. break;
  430. }
  431. switch (slotStatus.AttentionIndicatorState) {
  432. case SHPC_INDICATOR_OFF:
  433. AppendMenu(popup, MF_STRING | MF_GRAYED, ID_ATTENINDICATOR, L"Attention Indicator: Off");
  434. break;
  435. case SHPC_INDICATOR_ON:
  436. AppendMenu(popup, MF_STRING | MF_GRAYED, ID_ATTENINDICATOR, L"Attention Indicator: On");
  437. break;
  438. case SHPC_INDICATOR_BLINK:
  439. AppendMenu(popup, MF_STRING | MF_GRAYED, ID_ATTENINDICATOR, L"Attention Indicator: Blinking");
  440. break;
  441. case SHPC_INDICATOR_NOP:
  442. AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Attention Indicator: Unspecified");
  443. break;
  444. }
  445. //
  446. // Get the menu updated after our additions.
  447. //
  448. //DrawMenuBar(g_SoftPCIMainWnd);
  449. //
  450. // Make sure it pops up in the right place....
  451. //
  452. ClientToScreen(g_SoftPCIMainWnd, &Pt);
  453. //
  454. // lets see the menu
  455. //
  456. selection = TrackPopupMenuEx(popup,
  457. TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
  458. Pt.x, Pt.y,
  459. g_SoftPCIMainWnd,
  460. NULL
  461. );
  462. //
  463. // Now we will handle our Floating Tree View menu items
  464. //
  465. switch (selection) {
  466. case ID_INSTALLDEVICE:
  467. //
  468. // For now kill any dialogs we may already have open before starting this one
  469. //
  470. //if (g_DevPropDlg) {
  471. // SendMessage(g_DevPropDlg, WM_CLOSE, 0L, 0L);
  472. //}
  473. DISPLAY_NEWDEV_DLG(Pdn);
  474. break;
  475. case ID_REMOVEHPDEVICE:
  476. SoftPCI_RemoveHotplugDevice(parentDn,
  477. Pdn->Slot.Function
  478. );
  479. SoftPCI_CreateTreeView();
  480. break;
  481. case ID_CLOSEMRL:
  482. SoftPCI_ExecuteHotplugSlotMethod(parentDn,
  483. Pdn->Slot.Function,
  484. MRLClose
  485. );
  486. break;
  487. case ID_OPENMRL:
  488. SoftPCI_ExecuteHotplugSlotMethod(parentDn,
  489. Pdn->Slot.Function,
  490. MRLOpen
  491. );
  492. break;
  493. case ID_ATTENBUTTON:
  494. SoftPCI_ExecuteHotplugSlotMethod(parentDn,
  495. Pdn->Slot.Function,
  496. AttentionButton
  497. );
  498. break;
  499. default:
  500. break;
  501. }
  502. //
  503. // Make sure we dont lose our focus
  504. //
  505. //SetFocus(g_TreeViewWnd);
  506. }
  507. VOID
  508. SoftPCI_FreeBranch(
  509. IN PPCI_DN Dn
  510. )
  511. /*++
  512. Routine Description:
  513. This routine will free the specified PCI_DN struct along with all siblings and children.
  514. Arguments:
  515. Dn - PCI_DN to free
  516. Return Value:
  517. none
  518. --*/
  519. {
  520. PPCI_DN child, sibling;
  521. if (Dn) {
  522. child = Dn->Child;
  523. sibling = Dn->Sibling;
  524. if (Dn->SoftDev) {
  525. free(Dn->SoftDev);
  526. }
  527. SetupDiDeleteDeviceInfo(Dn->PciTree->DevInfoSet, &Dn->DevInfoData) ;
  528. free(Dn);
  529. SoftPCI_FreeBranch(child);
  530. SoftPCI_FreeBranch(sibling);
  531. }
  532. }
  533. VOID
  534. SoftPCI_OnTreeSelectionChange(
  535. IN HWND Wnd
  536. )
  537. /*++
  538. Routine Description:
  539. This routine informs our properties sheet that the selection has changes so that it can update
  540. Arguments:
  541. Wnd -
  542. Return Value:
  543. none
  544. --*/
  545. {
  546. TV_ITEM tviItem;
  547. PPCI_DN pdn = NULL;
  548. RECT itemRect;
  549. ULONG slotCount;
  550. //
  551. // Get the Current Item
  552. //
  553. tviItem.mask = TVIF_PARAM;
  554. tviItem.hItem = TreeView_GetSelection(g_TreeViewWnd);
  555. tviItem.lParam = 0;
  556. TreeView_GetItem(g_TreeViewWnd, &tviItem);
  557. if (tviItem.lParam) {
  558. g_PdnToDisplay = (PPCI_DN)tviItem.lParam;
  559. if (g_LastSelection) {
  560. free(g_LastSelection);
  561. g_LastSelection = NULL;
  562. }
  563. //
  564. // Save the last selection so we can restore it if the tree
  565. // is rebuilt.
  566. //
  567. g_LastSelection = SoftPCI_GetPciPathFromDn(g_PdnToDisplay);
  568. SoftPCI_UpdateTabCtrlWindow(g_CurrentTabSelection);
  569. }
  570. }
  571. LRESULT
  572. WINAPI
  573. SoftPCI_TreeWndProc(
  574. IN HWND Wnd,
  575. IN UINT Message,
  576. IN WPARAM wParam,
  577. IN LPARAM lParam
  578. )
  579. /*++
  580. Routine Description:
  581. This routine hooks the Tree Window message proc and is responsible
  582. for resizing our pane window when it is resized.
  583. Arguments:
  584. hWnd - Window handle
  585. Message - Message to process
  586. wParam - Message param
  587. lParam - Message param
  588. Return Value:
  589. return value depends on message handled.
  590. --*/
  591. {
  592. RECT rectMain, rectTree;
  593. TV_ITEM tviItem;
  594. TVHITTESTINFO hitinfo;
  595. PPCI_DN pdn;
  596. PCI_DN dn;
  597. RECT itemRect;
  598. POINT pt;
  599. //
  600. // Get the Current Item
  601. //
  602. //
  603. switch (Message) {
  604. case WM_KEYDOWN:
  605. switch (wParam){
  606. case VK_APPS:
  607. //
  608. // Grab the PCI_DN from the current tree item
  609. //
  610. pdn = SoftPCI_GetDnFromTreeItem(NULL);
  611. //
  612. // We copy this to a new DN because the TREE is constantly being
  613. // rebuilt and we cannot rely on the TV_ITEM.lParam value to always
  614. // be accurate later (we may have changed it).
  615. //
  616. RtlCopyMemory(&dn, pdn, sizeof(PCI_DN));
  617. if (TreeView_GetItemRect(g_TreeViewWnd,
  618. TreeView_GetSelection(g_TreeViewWnd),
  619. &itemRect,
  620. TRUE)) {
  621. //
  622. // Adjust the location for our menu
  623. //
  624. pt.x = itemRect.right;
  625. pt.y = itemRect.top;
  626. SoftPCI_DisplayTreeMenu(&dn, pt);
  627. }
  628. break;
  629. default:
  630. return CallWindowProc((WNDPROC)g_DefTreeWndProc, Wnd, Message, wParam, lParam);
  631. }
  632. break;
  633. case WM_RBUTTONDOWN:
  634. ZeroMemory(&hitinfo, sizeof(TVHITTESTINFO));
  635. hitinfo.pt.x = GET_X_LPARAM(lParam);
  636. hitinfo.pt.y = GET_Y_LPARAM(lParam);
  637. if (TreeView_HitTest(g_TreeViewWnd, &hitinfo)) {
  638. g_TreeLocked = TRUE;
  639. pdn = SoftPCI_GetDnFromTreeItem(hitinfo.hItem);
  640. //
  641. // See comment above for reason why we copy this here....
  642. //
  643. RtlCopyMemory(&dn, pdn, sizeof(PCI_DN));
  644. //
  645. // If an item in the tree is already selected this will cause the selection to change
  646. // as each item is right clicked.
  647. //
  648. TreeView_Select(g_TreeViewWnd, hitinfo.hItem, TVGN_CARET);
  649. SoftPCI_DisplayTreeMenu(&dn, hitinfo.pt);
  650. g_TreeLocked = FALSE;
  651. if (g_PendingRefresh) {
  652. g_PendingRefresh = FALSE;
  653. SoftPCI_CreateTreeView();
  654. }
  655. }
  656. break;
  657. default:
  658. return CallWindowProc((WNDPROC)g_DefTreeWndProc, Wnd, Message, wParam, lParam);
  659. }
  660. return 0;
  661. }
  662. PPCI_DN
  663. SoftPCI_GetDnFromTreeItem(
  664. IN HTREEITEM TreeItem
  665. )
  666. /*++
  667. Routine Description:
  668. This routine returns a PCI_DN for either the currently selected TreeItem
  669. or the one specified by the caller.
  670. Arguments:
  671. TreeItem - Handle to TreeItem we want to query. If NULL then we default to current selection.
  672. Return Value:
  673. return value will be TV_ITEM.lParam value
  674. --*/
  675. {
  676. TV_ITEM tviItem;
  677. tviItem.mask = TVIF_PARAM;
  678. tviItem.hItem = (TreeItem ? TreeItem : TreeView_GetSelection(g_TreeViewWnd));
  679. tviItem.lParam = 0;
  680. TreeView_GetItem(g_TreeViewWnd, &tviItem);
  681. SOFTPCI_ASSERT(((PPCI_DN)tviItem.lParam) != NULL);
  682. return (PPCI_DN)tviItem.lParam;
  683. }
  684. VOID
  685. SoftPCI_InsertTreeItem(
  686. IN PPCI_DN Pdn,
  687. IN HTREEITEM HtiParent
  688. )
  689. /*++
  690. Routine Description:
  691. This routine takes our tree of PCI_DN structs and builds the UI representaion of it.
  692. Arguments:
  693. Pdn Current Pdn being intserted
  694. HtiParent The HTREEITEM that is to be the parent of this Pdn
  695. Return Value:
  696. none
  697. --*/
  698. {
  699. PPCI_DN childDevNode;
  700. PPCI_DN siblingDevNode;
  701. TV_INSERTSTRUCT tvInsertStruct;
  702. HTREEITEM htiNewParent;
  703. TV_ITEM tvi;
  704. INT index;
  705. ULONG problem;
  706. SOFTPCI_ASSERT(Pdn != NULL);
  707. do {
  708. childDevNode = Pdn->Child;
  709. siblingDevNode = Pdn->Sibling;
  710. //
  711. // Get the parent item, and tell it it has children now
  712. //
  713. if (HtiParent != TVI_ROOT) {
  714. tvi.mask = TVIF_CHILDREN;
  715. tvi.hItem = HtiParent;
  716. TreeView_GetItem(g_TreeViewWnd, &tvi);
  717. //
  718. // Increment the ChildCount;
  719. //
  720. ++tvi.cChildren;
  721. TreeView_SetItem(g_TreeViewWnd, &tvi);
  722. }
  723. //
  724. // Add This Device at the current Level
  725. //
  726. tvInsertStruct.hParent = HtiParent;
  727. tvInsertStruct.hInsertAfter = TVI_LAST;
  728. tvInsertStruct.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_CHILDREN | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
  729. tvInsertStruct.item.cChildren = 0;
  730. tvInsertStruct.item.lParam = (ULONG_PTR) Pdn;
  731. tvInsertStruct.item.state = INDEXTOOVERLAYMASK(0);
  732. //
  733. // If the device has a problem make let's reflect so....
  734. //
  735. if (SoftPCI_GetDeviceNodeProblem(Pdn->DevNode, &problem)){
  736. if (problem == CM_PROB_DISABLED) {
  737. tvInsertStruct.item.state = INDEXTOOVERLAYMASK(IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST + 1);
  738. }else{
  739. tvInsertStruct.item.state = INDEXTOOVERLAYMASK(IDI_PROBLEM_OVL - IDI_CLASSICON_OVERLAYFIRST + 1);
  740. }
  741. }
  742. tvInsertStruct.item.stateMask = TVIS_OVERLAYMASK | TVIS_CUT;
  743. tvInsertStruct.item.pszText = (LPTSTR) Pdn->FriendlyName;
  744. //
  745. // Figure out which icon goes which each device.
  746. //
  747. if (SetupDiGetClassImageIndex(&Pdn->PciTree->ClassImageListData, &Pdn->DevInfoData.ClassGuid, &index)){
  748. tvInsertStruct.item.iImage = tvInsertStruct.item.iSelectedImage = index ;
  749. }else{
  750. tvInsertStruct.item.iImage = tvInsertStruct.item.iSelectedImage = -1 ;
  751. }
  752. htiNewParent = TreeView_InsertItem(g_TreeViewWnd, &tvInsertStruct);
  753. if (g_PciTree->RootTreeItem == NULL) {
  754. g_PciTree->RootTreeItem = htiNewParent;
  755. }
  756. //
  757. // if this device has a child lets walk them next
  758. //
  759. if (childDevNode){
  760. SoftPCI_InsertTreeItem(childDevNode, htiNewParent);
  761. }
  762. }while ((Pdn = siblingDevNode) != NULL);
  763. }
  764. VOID
  765. SoftPCI_ExpandItem(
  766. IN HTREEITEM Hti,
  767. IN PULONG Data1,
  768. IN PULONG Data2
  769. )
  770. {
  771. //
  772. // Expand this item.
  773. //
  774. TreeView_Expand(g_TreeViewWnd, Hti, TVE_EXPAND);
  775. }
  776. VOID
  777. SoftPCI_RestoreSelection(
  778. IN HTREEITEM Hti,
  779. IN PVOID Data1,
  780. IN PVOID Data2
  781. )
  782. {
  783. PWCHAR slotPath, p;
  784. PPCI_DN pdn;
  785. PBOOL selectionFound;
  786. selectionFound = (PBOOL)Data1;
  787. pdn = SoftPCI_GetDnFromTreeItem(Hti);
  788. if (pdn == NULL) {
  789. return;
  790. }
  791. slotPath = SoftPCI_GetPciPathFromDn(pdn);
  792. if ((wcscmp(slotPath, g_LastSelection)) == 0) {
  793. //
  794. // Restore the selection to this point.
  795. //
  796. TreeView_Select(g_TreeViewWnd, Hti, TVGN_CARET);
  797. TreeView_EnsureVisible(g_TreeViewWnd, Hti);
  798. *selectionFound = TRUE;
  799. }
  800. free(slotPath);
  801. }
  802. VOID
  803. SoftPCI_WalkTree(
  804. IN HTREEITEM Hti,
  805. IN PSOFTPCI_TREECALLBACK TreeCallback,
  806. IN PVOID Arg1,
  807. IN PVOID Arg2
  808. )
  809. {
  810. if (Hti) {
  811. //
  812. // Call the CallBack.
  813. //
  814. (*TreeCallback)(Hti, Arg1, Arg2);
  815. //
  816. // Call this on my first child.
  817. //
  818. SoftPCI_WalkTree(TreeView_GetChild(g_TreeViewWnd, Hti),
  819. TreeCallback,
  820. Arg1,
  821. Arg2
  822. );
  823. //
  824. // Call this on my first sibling.
  825. //
  826. SoftPCI_WalkTree(TreeView_GetNextSibling(g_TreeViewWnd, Hti),
  827. TreeCallback,
  828. Arg1,
  829. Arg2
  830. );
  831. }
  832. }
  833. #if 0
  834. VOID
  835. SoftPCI_GetDnFromTree(
  836. IN HTREEITEM Hti,
  837. IN OUT PVOID Pdn, //PPCI_DN *
  838. IN PVOID PdnToFind
  839. )
  840. {
  841. TV_ITEM tvi;
  842. PPCI_DN pdn = NULL;
  843. PPCI_DN pdnToFind = (PPCI_DN)PdnToFind;
  844. tvi.lParam = 0;
  845. tvi.hItem = Hti;
  846. TreeView_GetItem(g_TreeViewWnd, &tvi);
  847. pdn = (PPCI_DN)tvi.lParam;
  848. if (pdn) {
  849. if ((pdnToFind->Bus == pdn->Bus) &&
  850. (pdnToFind->Device == pdn->Device) &&
  851. (pdnToFind->Function == pdn->Function)) {
  852. *(PPCI_DN *)Pdn = pdn;
  853. }
  854. }
  855. }
  856. #endif