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

#include "pch.h"
PPCI_TREE
SoftPCI_BuildTree(
VOID
);
VOID
SoftPCI_DisplayTreeMenu(
IN PPCI_DN Pdn,
IN POINT Pt
);
VOID
SoftPCI_DisplayStandardTreeMenu(
IN PPCI_DN Pdn,
IN POINT Pt
);
VOID
SoftPCI_DisplayHotplugTreeMenu(
IN PPCI_DN Pdn,
IN POINT Pt
);
VOID
SoftPCI_FreeBranch(
IN PPCI_DN Dn
);
VOID
SoftPCI_InsertTreeItem(
IN PPCI_DN Pdn,
IN HTREEITEM HtiParent
);
VOID
SoftPCI_ExpandItem(
IN HTREEITEM Hti,
IN PVOID Arg1,
IN PVOID Arg2
);
VOID
SoftPCI_RestoreSelection(
IN HTREEITEM Hti,
IN PVOID Data1,
IN PVOID Data2
);
BOOL g_TreeCreated = FALSE;
BOOL g_TreeLocked = FALSE;
BOOL g_PendingRefresh = FALSE;
PPCI_TREE g_PciTree;
LONG_PTR g_DefTreeWndProc;
PWCHAR g_LastSelection = NULL;
VOID
SoftPCI_CreateTreeView(
VOID
)
{
HTREEITEM htiParent;
TVITEM tvitem;
PPCI_DN rootDevNode = NULL;
HMENU menu = GetMenu(g_SoftPCIMainWnd);
PPCI_DN pdn = NULL;
PCI_DN selectedDevNode;
BOOL selectionFound;
PWCHAR p;
//HCURSOR oldCursor;
//
// Empty the tree.
//
TreeView_DeleteAllItems(g_TreeViewWnd);
if (g_TreeCreated) {
SoftPCI_DestroyTree(g_PciTree);
}
g_PciTree = SoftPCI_BuildTree();
if (!g_PciTree) {
MessageBox(g_SoftPCIMainWnd, L"Failed to create g_PciTree!", L"ERROR", MB_OK);
return;
}
g_TreeCreated = TRUE;
SOFTPCI_ASSERT(g_PciTree->ClassImageListData.ImageList != INVALID_HANDLE_VALUE);
TreeView_SetImageList(g_TreeViewWnd, g_PciTree->ClassImageListData.ImageList, TVSIL_NORMAL);
//
// Insert the rest of the items.
//
SoftPCI_InsertTreeItem(g_PciTree->RootDevNode, TVI_ROOT);
//
// Currently we always expand the entire tree when it is built. Should see
// if there is a way to avoid this....
//
SoftPCI_WalkTree(
g_PciTree->RootTreeItem,
SoftPCI_ExpandItem,
NULL,
NULL
);
//
// Restore last selection if any
//
if (g_LastSelection){
selectionFound = FALSE;
SoftPCI_WalkTree(
g_PciTree->RootTreeItem,
SoftPCI_RestoreSelection,
&selectionFound,
NULL
);
if (!selectionFound) {
//
// If the last selection no longer exists then we back up to the
// parent and check one more time.
//
p = g_LastSelection;
p += wcslen(g_LastSelection);
while(*p != '\\'){
p--;
}
*p = 0;
//
// Now run the tree one more time looking for the parent
//
SoftPCI_WalkTree(
g_PciTree->RootTreeItem,
SoftPCI_RestoreSelection,
&selectionFound,
NULL
);
}
}else{
TreeView_Select(g_TreeViewWnd, g_PciTree->RootTreeItem, TVGN_CARET);
TreeView_EnsureVisible(g_TreeViewWnd, g_PciTree->RootTreeItem);
}
SoftPCI_UpdateTabCtrlWindow(g_CurrentTabSelection);
}
PPCI_TREE
SoftPCI_BuildTree(VOID)
/*++
Routine Description:
This function is the entry point for building our PCI_TREE
Arguments:
none
Return Value:
PPCI_TREE we have created
--*/
{
DEVNODE dn = 0;
PPCI_DN pdn;
PPCI_TREE pcitree;
pcitree = (PPCI_TREE) calloc(1, sizeof(PCI_TREE));
if (!pcitree) return NULL;
CM_Locate_DevNode(&dn, NULL, CM_LOCATE_DEVNODE_NORMAL);
SOFTPCI_ASSERT(dn != 0);
pcitree->ClassImageListData.ImageList = INVALID_HANDLE_VALUE ;
pcitree->ClassImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA) ;
if (!SetupDiGetClassImageList(&pcitree->ClassImageListData)){
pcitree->ClassImageListData.ImageList = INVALID_HANDLE_VALUE;
}
pcitree->DevInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL) ;
SOFTPCI_ASSERT(pcitree->DevInfoSet != INVALID_HANDLE_VALUE);
//
// Now find all things PCI and build a PCI_DN tree
//
pdn = NULL;
SoftPCI_EnumerateDevices(pcitree, &pdn, dn, NULL);
pcitree->RootDevNode = pdn;
return pcitree;
}
VOID
SoftPCI_DestroyTree(
IN PPCI_TREE PciTree
)
/*++
Routine Description:
This routine frees all our allocations for the Tree
Arguments:
PciTree - Tree to distroy
Return Value:
none
--*/
{
PPCI_DN dn = PciTree->RootDevNode;
//
// First set the tree view image list to NULL
//
TreeView_SetImageList(g_TreeViewWnd, NULL, TVSIL_NORMAL);
//
// Now free all our allocated PCI_DN structs
//
SoftPCI_FreeBranch(dn);
//
// Destroy our image and info lists
//
if (PciTree->ClassImageListData.ImageList != INVALID_HANDLE_VALUE){
SetupDiDestroyClassImageList(&PciTree->ClassImageListData);
PciTree->ClassImageListData.ImageList = INVALID_HANDLE_VALUE;
}
if (PciTree->DevInfoSet != INVALID_HANDLE_VALUE){
SetupDiDestroyDeviceInfoList(PciTree->DevInfoSet);
PciTree->DevInfoSet = INVALID_HANDLE_VALUE;
}
//
// And finally....
//
free(PciTree);
}
VOID
SoftPCI_DisplayTreeMenu(
IN PPCI_DN Pdn,
IN POINT Pt
)
/*++
Routine Description:
This routine dispatches the menu request to the appropriate menu function
Arguments:
Pdn - PCI_DN of the item we are displaying the menu for
Pt - coordinates for the item
Return Value:
none
--*/
{
if (Pdn->Flags & SOFTPCI_HOTPLUG_SLOT) {
SoftPCI_DisplayHotplugTreeMenu(Pdn,Pt);
} else if (Pdn->Flags & SOFTPCI_UNENUMERATED_DEVICE) {
//
// If it's an unenumerated device (in an unpowered hotplug slot),
// you can't do anything with it.
//
return;
} else {
SoftPCI_DisplayStandardTreeMenu(Pdn, Pt);
}
return;
}
VOID
SoftPCI_DisplayStandardTreeMenu(
IN PPCI_DN Pdn,
IN POINT Pt
)
/*++
Routine Description:
This routine displays the standard context menu when the user right-clicks a device
Arguments:
Pdn - PCI_DN of the slot
Pt - coordinates for the device
Return Value:
none
--*/
{
HMENU menu, popup;
ULONG dnProblem;
BOOL enableDevice = FALSE;
INT selection = 0;
menu = LoadMenu(g_Instance, MAKEINTRESOURCE(IDM_TREEMENU));
if (!menu) {
MessageBox(g_SoftPCIMainWnd, L"failed to display menu!", NULL, MB_OK);
return;
}
popup = GetSubMenu(menu, 0);
//
// If SoftPCI support is not installed or this isnt a bridge device,
// disable the option to add devices.
//
if ((g_DriverHandle == NULL) ||
!SoftPCI_IsBridgeDevice(Pdn)) {
SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
}
if (!SoftPCI_IsSoftPCIDevice(Pdn)) {
SoftPCI_DisableMenuItem(menu, ID_DELETEDEVICE);
SoftPCI_DisableMenuItem(menu, ID_STATICDEVICE);
}
if (SoftPCI_GetDeviceNodeProblem(Pdn->DevNode, &dnProblem)) {
if (dnProblem == CM_PROB_DISABLED) {
enableDevice = TRUE;
SoftPCI_SetMenuItemText(menu, ID_ENABLEDISABLEDEVICE, L"E&nable Device");
}else{
//
// For now we will not allow the option to disable a non-working device
//
SoftPCI_DisableMenuItem(menu, ID_ENABLEDISABLEDEVICE);
}
}
//
// If this device is in a hotplug slot, can't just rip out
// the hardware. You have to go through the appropriate
// mechanism.
//
if (Pdn->Parent && (Pdn->Parent->Flags & SOFTPCI_HOTPLUG_SLOT)) {
SoftPCI_DisableMenuItem(menu, ID_DELETEDEVICE);
}
//
// Make sure it pops up in the right place....
//
ClientToScreen(g_SoftPCIMainWnd, &Pt);
//
// lets see the menu
//
selection = TrackPopupMenuEx(
popup,
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
Pt.x, Pt.y,
g_SoftPCIMainWnd,
NULL
);
//
// Now we will handle our Floating Tree View menu items
//
switch (selection) {
case ID_INSTALLDEVICE:
DISPLAY_NEWDEV_DLG(Pdn);
break;
case ID_ENABLEDISABLEDEVICE:
SoftPCI_EnableDisableDeviceNode(
Pdn->DevNode,
enableDevice
);
break;
case ID_DELETEDEVICE:
if ((MessageBox(g_SoftPCIMainWnd,
L"This option will delete or surprise remove the device from the system.",
L"WARNING", MB_OKCANCEL)) == IDOK){
//
// Here we tell our driver to delete the specified device. This will
// cause a re-enum of everything that will result in the cleanup
// of this device in user mode.
//
if (!SoftPCI_DeleteDevice(Pdn->SoftDev)) {
MessageBox(g_SoftPCIMainWnd, L"Failed to delete device!", NULL, MB_OK);
}
}
break;
case ID_STATICDEVICE:
if (SoftPCI_SaveDeviceToRegisty(Pdn)){
MessageBox(g_SoftPCIMainWnd, L"Successfully saved devices to registry!", NULL, MB_OK);
}else{
MessageBox(g_SoftPCIMainWnd, L"Failed to save devices to registry!", NULL, MB_OK);
}
break;
case ID_REFRESHTREE:
CM_Reenumerate_DevNode(Pdn->DevNode, 0);
SoftPCI_CreateTreeView();
break;
default:
break;
}
}
VOID
SoftPCI_DisplayHotplugTreeMenu(
IN PPCI_DN Pdn,
IN POINT Pt
)
/*++
Routine Description:
This routine displays the hotplug specific context menu when the user right-clicks a hotplug slot.
Arguments:
Pdn - PCI_DN of the slot
Pt - coordinates for the slot
Return Value:
none
--*/
{
HMENU menu, popup;
INT selection;
PPCI_DN parentDn;
BOOL status;
SHPC_SLOT_STATUS_REGISTER slotStatus;
menu = LoadMenu(g_Instance, MAKEINTRESOURCE(IDM_HOTPLUGSLOTMENU));
if (!menu) {
MessageBox(g_SoftPCIMainWnd, L"failed to display menu!", NULL, MB_OK);
return;
}
popup = GetSubMenu(menu, 0);
//
// If SoftPCI support is not installed disable the option to add devices.
//
if (!g_DriverHandle) {
SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
}
//
// If our Device Property dialog is open dont allow properties to be
// selected again.
//
if (g_NewDevDlg) {
//
// ISSUE: BrandonA - Figure out why we hang if the first Dialog
// launched is killed before the second...
//
SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
}
//
// DWALKER
// Get slot status from driver
// appropriately grey out open/close MRL menu item.
// if MRL is closed, disable removing the device.
//
parentDn = Pdn->Parent;
status = SoftPCI_GetSlotStatus(parentDn,
Pdn->Slot.Function,
&slotStatus
);
if (status == FALSE) {
MessageBox(g_SoftPCIMainWnd, L"failed to display menu!", NULL, MB_OK);
return;
}
//
// If the MRL is closed, you can't insert or remove the device.
// Otherwise, disable the appropriate menu item based on the presence
// of a device in the slot.
//
if (slotStatus.MRLSensorState == SHPC_MRL_CLOSED) {
SoftPCI_DisableMenuItem(menu, ID_REMOVEHPDEVICE);
SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
} else if (Pdn->Child == NULL) {
SoftPCI_DisableMenuItem(menu, ID_REMOVEHPDEVICE);
} else {
SoftPCI_DisableMenuItem(menu, ID_INSTALLDEVICE);
}
if (slotStatus.MRLSensorState == SHPC_MRL_CLOSED) {
RemoveMenu(menu, ID_CLOSEMRL, MF_BYCOMMAND);
} else {
RemoveMenu(menu, ID_OPENMRL, MF_BYCOMMAND);
}
AppendMenu(popup, MF_SEPARATOR, 0, NULL);
switch (slotStatus.PowerIndicatorState) {
case SHPC_INDICATOR_OFF:
AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Power Indicator: Off");
break;
case SHPC_INDICATOR_ON:
AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Power Indicator: On");
break;
case SHPC_INDICATOR_BLINK:
AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Power Indicator: Blinking");
break;
case SHPC_INDICATOR_NOP:
AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Power Indicator: Unspecified");
break;
}
switch (slotStatus.AttentionIndicatorState) {
case SHPC_INDICATOR_OFF:
AppendMenu(popup, MF_STRING | MF_GRAYED, ID_ATTENINDICATOR, L"Attention Indicator: Off");
break;
case SHPC_INDICATOR_ON:
AppendMenu(popup, MF_STRING | MF_GRAYED, ID_ATTENINDICATOR, L"Attention Indicator: On");
break;
case SHPC_INDICATOR_BLINK:
AppendMenu(popup, MF_STRING | MF_GRAYED, ID_ATTENINDICATOR, L"Attention Indicator: Blinking");
break;
case SHPC_INDICATOR_NOP:
AppendMenu(popup, MF_STRING | MF_GRAYED, ID_POWERINDICATOR, L"Attention Indicator: Unspecified");
break;
}
//
// Get the menu updated after our additions.
//
//DrawMenuBar(g_SoftPCIMainWnd);
//
// Make sure it pops up in the right place....
//
ClientToScreen(g_SoftPCIMainWnd, &Pt);
//
// lets see the menu
//
selection = TrackPopupMenuEx(popup,
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
Pt.x, Pt.y,
g_SoftPCIMainWnd,
NULL
);
//
// Now we will handle our Floating Tree View menu items
//
switch (selection) {
case ID_INSTALLDEVICE:
//
// For now kill any dialogs we may already have open before starting this one
//
//if (g_DevPropDlg) {
// SendMessage(g_DevPropDlg, WM_CLOSE, 0L, 0L);
//}
DISPLAY_NEWDEV_DLG(Pdn);
break;
case ID_REMOVEHPDEVICE:
SoftPCI_RemoveHotplugDevice(parentDn,
Pdn->Slot.Function
);
SoftPCI_CreateTreeView();
break;
case ID_CLOSEMRL:
SoftPCI_ExecuteHotplugSlotMethod(parentDn,
Pdn->Slot.Function,
MRLClose
);
break;
case ID_OPENMRL:
SoftPCI_ExecuteHotplugSlotMethod(parentDn,
Pdn->Slot.Function,
MRLOpen
);
break;
case ID_ATTENBUTTON:
SoftPCI_ExecuteHotplugSlotMethod(parentDn,
Pdn->Slot.Function,
AttentionButton
);
break;
default:
break;
}
//
// Make sure we dont lose our focus
//
//SetFocus(g_TreeViewWnd);
}
VOID
SoftPCI_FreeBranch(
IN PPCI_DN Dn
)
/*++
Routine Description:
This routine will free the specified PCI_DN struct along with all siblings and children.
Arguments:
Dn - PCI_DN to free
Return Value:
none
--*/
{
PPCI_DN child, sibling;
if (Dn) {
child = Dn->Child;
sibling = Dn->Sibling;
if (Dn->SoftDev) {
free(Dn->SoftDev);
}
SetupDiDeleteDeviceInfo(Dn->PciTree->DevInfoSet, &Dn->DevInfoData) ;
free(Dn);
SoftPCI_FreeBranch(child);
SoftPCI_FreeBranch(sibling);
}
}
VOID
SoftPCI_OnTreeSelectionChange(
IN HWND Wnd
)
/*++
Routine Description:
This routine informs our properties sheet that the selection has changes so that it can update
Arguments:
Wnd -
Return Value:
none
--*/
{
TV_ITEM tviItem;
PPCI_DN pdn = NULL;
RECT itemRect;
ULONG slotCount;
//
// Get the Current Item
//
tviItem.mask = TVIF_PARAM;
tviItem.hItem = TreeView_GetSelection(g_TreeViewWnd);
tviItem.lParam = 0;
TreeView_GetItem(g_TreeViewWnd, &tviItem);
if (tviItem.lParam) {
g_PdnToDisplay = (PPCI_DN)tviItem.lParam;
if (g_LastSelection) {
free(g_LastSelection);
g_LastSelection = NULL;
}
//
// Save the last selection so we can restore it if the tree
// is rebuilt.
//
g_LastSelection = SoftPCI_GetPciPathFromDn(g_PdnToDisplay);
SoftPCI_UpdateTabCtrlWindow(g_CurrentTabSelection);
}
}
LRESULT
WINAPI
SoftPCI_TreeWndProc(
IN HWND Wnd,
IN UINT Message,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
This routine hooks the Tree Window message proc and is responsible
for resizing our pane window when it is resized.
Arguments:
hWnd - Window handle
Message - Message to process
wParam - Message param
lParam - Message param
Return Value:
return value depends on message handled.
--*/
{
RECT rectMain, rectTree;
TV_ITEM tviItem;
TVHITTESTINFO hitinfo;
PPCI_DN pdn;
PCI_DN dn;
RECT itemRect;
POINT pt;
//
// Get the Current Item
//
//
switch (Message) {
case WM_KEYDOWN:
switch (wParam){
case VK_APPS:
//
// Grab the PCI_DN from the current tree item
//
pdn = SoftPCI_GetDnFromTreeItem(NULL);
//
// We copy this to a new DN because the TREE is constantly being
// rebuilt and we cannot rely on the TV_ITEM.lParam value to always
// be accurate later (we may have changed it).
//
RtlCopyMemory(&dn, pdn, sizeof(PCI_DN));
if (TreeView_GetItemRect(g_TreeViewWnd,
TreeView_GetSelection(g_TreeViewWnd),
&itemRect,
TRUE)) {
//
// Adjust the location for our menu
//
pt.x = itemRect.right;
pt.y = itemRect.top;
SoftPCI_DisplayTreeMenu(&dn, pt);
}
break;
default:
return CallWindowProc((WNDPROC)g_DefTreeWndProc, Wnd, Message, wParam, lParam);
}
break;
case WM_RBUTTONDOWN:
ZeroMemory(&hitinfo, sizeof(TVHITTESTINFO));
hitinfo.pt.x = GET_X_LPARAM(lParam);
hitinfo.pt.y = GET_Y_LPARAM(lParam);
if (TreeView_HitTest(g_TreeViewWnd, &hitinfo)) {
g_TreeLocked = TRUE;
pdn = SoftPCI_GetDnFromTreeItem(hitinfo.hItem);
//
// See comment above for reason why we copy this here....
//
RtlCopyMemory(&dn, pdn, sizeof(PCI_DN));
//
// If an item in the tree is already selected this will cause the selection to change
// as each item is right clicked.
//
TreeView_Select(g_TreeViewWnd, hitinfo.hItem, TVGN_CARET);
SoftPCI_DisplayTreeMenu(&dn, hitinfo.pt);
g_TreeLocked = FALSE;
if (g_PendingRefresh) {
g_PendingRefresh = FALSE;
SoftPCI_CreateTreeView();
}
}
break;
default:
return CallWindowProc((WNDPROC)g_DefTreeWndProc, Wnd, Message, wParam, lParam);
}
return 0;
}
PPCI_DN
SoftPCI_GetDnFromTreeItem(
IN HTREEITEM TreeItem
)
/*++
Routine Description:
This routine returns a PCI_DN for either the currently selected TreeItem
or the one specified by the caller.
Arguments:
TreeItem - Handle to TreeItem we want to query. If NULL then we default to current selection.
Return Value:
return value will be TV_ITEM.lParam value
--*/
{
TV_ITEM tviItem;
tviItem.mask = TVIF_PARAM;
tviItem.hItem = (TreeItem ? TreeItem : TreeView_GetSelection(g_TreeViewWnd));
tviItem.lParam = 0;
TreeView_GetItem(g_TreeViewWnd, &tviItem);
SOFTPCI_ASSERT(((PPCI_DN)tviItem.lParam) != NULL);
return (PPCI_DN)tviItem.lParam;
}
VOID
SoftPCI_InsertTreeItem(
IN PPCI_DN Pdn,
IN HTREEITEM HtiParent
)
/*++
Routine Description:
This routine takes our tree of PCI_DN structs and builds the UI representaion of it.
Arguments:
Pdn Current Pdn being intserted
HtiParent The HTREEITEM that is to be the parent of this Pdn
Return Value:
none
--*/
{
PPCI_DN childDevNode;
PPCI_DN siblingDevNode;
TV_INSERTSTRUCT tvInsertStruct;
HTREEITEM htiNewParent;
TV_ITEM tvi;
INT index;
ULONG problem;
SOFTPCI_ASSERT(Pdn != NULL);
do {
childDevNode = Pdn->Child;
siblingDevNode = Pdn->Sibling;
//
// Get the parent item, and tell it it has children now
//
if (HtiParent != TVI_ROOT) {
tvi.mask = TVIF_CHILDREN;
tvi.hItem = HtiParent;
TreeView_GetItem(g_TreeViewWnd, &tvi);
//
// Increment the ChildCount;
//
++tvi.cChildren;
TreeView_SetItem(g_TreeViewWnd, &tvi);
}
//
// Add This Device at the current Level
//
tvInsertStruct.hParent = HtiParent;
tvInsertStruct.hInsertAfter = TVI_LAST;
tvInsertStruct.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_CHILDREN | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
tvInsertStruct.item.cChildren = 0;
tvInsertStruct.item.lParam = (ULONG_PTR) Pdn;
tvInsertStruct.item.state = INDEXTOOVERLAYMASK(0);
//
// If the device has a problem make let's reflect so....
//
if (SoftPCI_GetDeviceNodeProblem(Pdn->DevNode, &problem)){
if (problem == CM_PROB_DISABLED) {
tvInsertStruct.item.state = INDEXTOOVERLAYMASK(IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST + 1);
}else{
tvInsertStruct.item.state = INDEXTOOVERLAYMASK(IDI_PROBLEM_OVL - IDI_CLASSICON_OVERLAYFIRST + 1);
}
}
tvInsertStruct.item.stateMask = TVIS_OVERLAYMASK | TVIS_CUT;
tvInsertStruct.item.pszText = (LPTSTR) Pdn->FriendlyName;
//
// Figure out which icon goes which each device.
//
if (SetupDiGetClassImageIndex(&Pdn->PciTree->ClassImageListData, &Pdn->DevInfoData.ClassGuid, &index)){
tvInsertStruct.item.iImage = tvInsertStruct.item.iSelectedImage = index ;
}else{
tvInsertStruct.item.iImage = tvInsertStruct.item.iSelectedImage = -1 ;
}
htiNewParent = TreeView_InsertItem(g_TreeViewWnd, &tvInsertStruct);
if (g_PciTree->RootTreeItem == NULL) {
g_PciTree->RootTreeItem = htiNewParent;
}
//
// if this device has a child lets walk them next
//
if (childDevNode){
SoftPCI_InsertTreeItem(childDevNode, htiNewParent);
}
}while ((Pdn = siblingDevNode) != NULL);
}
VOID
SoftPCI_ExpandItem(
IN HTREEITEM Hti,
IN PULONG Data1,
IN PULONG Data2
)
{
//
// Expand this item.
//
TreeView_Expand(g_TreeViewWnd, Hti, TVE_EXPAND);
}
VOID
SoftPCI_RestoreSelection(
IN HTREEITEM Hti,
IN PVOID Data1,
IN PVOID Data2
)
{
PWCHAR slotPath, p;
PPCI_DN pdn;
PBOOL selectionFound;
selectionFound = (PBOOL)Data1;
pdn = SoftPCI_GetDnFromTreeItem(Hti);
if (pdn == NULL) {
return;
}
slotPath = SoftPCI_GetPciPathFromDn(pdn);
if ((wcscmp(slotPath, g_LastSelection)) == 0) {
//
// Restore the selection to this point.
//
TreeView_Select(g_TreeViewWnd, Hti, TVGN_CARET);
TreeView_EnsureVisible(g_TreeViewWnd, Hti);
*selectionFound = TRUE;
}
free(slotPath);
}
VOID
SoftPCI_WalkTree(
IN HTREEITEM Hti,
IN PSOFTPCI_TREECALLBACK TreeCallback,
IN PVOID Arg1,
IN PVOID Arg2
)
{
if (Hti) {
//
// Call the CallBack.
//
(*TreeCallback)(Hti, Arg1, Arg2);
//
// Call this on my first child.
//
SoftPCI_WalkTree(TreeView_GetChild(g_TreeViewWnd, Hti),
TreeCallback,
Arg1,
Arg2
);
//
// Call this on my first sibling.
//
SoftPCI_WalkTree(TreeView_GetNextSibling(g_TreeViewWnd, Hti),
TreeCallback,
Arg1,
Arg2
);
}
}
#if 0
VOID
SoftPCI_GetDnFromTree(
IN HTREEITEM Hti,
IN OUT PVOID Pdn, //PPCI_DN *
IN PVOID PdnToFind
)
{
TV_ITEM tvi;
PPCI_DN pdn = NULL;
PPCI_DN pdnToFind = (PPCI_DN)PdnToFind;
tvi.lParam = 0;
tvi.hItem = Hti;
TreeView_GetItem(g_TreeViewWnd, &tvi);
pdn = (PPCI_DN)tvi.lParam;
if (pdn) {
if ((pdnToFind->Bus == pdn->Bus) &&
(pdnToFind->Device == pdn->Device) &&
(pdnToFind->Function == pdn->Function)) {
*(PPCI_DN *)Pdn = pdn;
}
}
}
#endif