usbview.c
上传用户:gzccxsp
上传日期:2015-07-14
资源大小:182k
文件大小:25k
源码类别:

MacOS编程

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 1997-1998 Microsoft Corporation
  3. Module Name:
  4.     USBVIEW.C
  5. Abstract:
  6.     This is the GUI goop for the USBVIEW application.
  7. Environment:
  8.     user mode
  9. Revision History:
  10.     04-25-97 : created
  11. --*/
  12. //*****************************************************************************
  13. // I N C L U D E S
  14. //*****************************************************************************
  15. #include <windows.h>
  16. #include <basetyps.h>
  17. #include <windowsx.h>
  18. #include <initguid.h>
  19. #include "devioctl.h"
  20. #include "usbioctl.h"
  21. #include <dbt.h>
  22. #include <stdio.h>
  23. #include "resource.h"
  24. #include "usbview.h"
  25. typedef  PVOID           HDEVNOTIFY;
  26. typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A {
  27.     DWORD       dbcc_size;
  28.     DWORD       dbcc_devicetype;
  29.     DWORD       dbcc_reserved;
  30.     GUID        dbcc_classguid;
  31.     char        dbcc_name[1];
  32. } DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A;
  33. typedef DEV_BROADCAST_DEVICEINTERFACE_A   DEV_BROADCAST_DEVICEINTERFACE;
  34. typedef PDEV_BROADCAST_DEVICEINTERFACE_A  PDEV_BROADCAST_DEVICEINTERFACE;
  35. #define DBT_DEVTYP_DEVICEINTERFACE      0x00000005  // device interface class
  36. #define DBT_DEVTYP_HANDLE               0x00000006  // file system handle
  37. #define DEVICE_NOTIFY_WINDOW_HANDLE     0x00000000
  38. #define DEVICE_NOTIFY_SERVICE_HANDLE    0x00000001
  39. WINUSERAPI
  40. HDEVNOTIFY
  41. WINAPI
  42. RegisterDeviceNotificationA(
  43.     IN HANDLE hRecipient,
  44.     IN LPVOID NotificationFilter,
  45.     IN DWORD Flags
  46.     );
  47. WINUSERAPI
  48. HDEVNOTIFY
  49. WINAPI
  50. RegisterDeviceNotificationW(
  51.     IN HANDLE hRecipient,
  52.     IN LPVOID NotificationFilter,
  53.     IN DWORD Flags
  54.     );
  55. #define RegisterDeviceNotification  RegisterDeviceNotificationA
  56. WINUSERAPI
  57. BOOL
  58. WINAPI
  59. UnregisterDeviceNotification(
  60.     IN HDEVNOTIFY Handle
  61.     );
  62. //*****************************************************************************
  63. // D E F I N E S
  64. //*****************************************************************************
  65. // window control defines
  66. //
  67. #define SIZEBAR             0
  68. #define WINDOWSCALEFACTOR   15
  69. //*****************************************************************************
  70. // L O C A L    F U N C T I O N    P R O T O T Y P E S
  71. //*****************************************************************************
  72. int WINAPI
  73. WinMain (
  74.     HINSTANCE hInstance,
  75.     HINSTANCE hPrevInstance,
  76.     LPSTR     lpszCmdLine,
  77.     int       nCmdShow
  78. );
  79. BOOL
  80. CreateMainWindow (
  81.     int nCmdShow
  82. );
  83. VOID
  84. ResizeWindows (
  85.     BOOL    bSizeBar,
  86.     int     BarLocation
  87. );
  88. LRESULT CALLBACK
  89. MainDlgProc (
  90.     HWND   hwnd,
  91.     UINT   uMsg,
  92.     WPARAM wParam,
  93.     LPARAM lParam
  94. );
  95. BOOL
  96. USBView_OnInitDialog (
  97.     HWND    hWnd,
  98.     HWND    hWndFocus,
  99.     LPARAM  lParam
  100. );
  101. VOID
  102. USBView_OnClose (
  103.     HWND hWnd
  104. );
  105. VOID
  106. USBView_OnCommand (
  107.     HWND hWnd,
  108.     int  id,
  109.     HWND hwndCtl,
  110.     UINT codeNotify
  111. );
  112. VOID
  113. USBView_OnLButtonDown (
  114.     HWND hWnd,
  115.     BOOL fDoubleClick,
  116.     int  x,
  117.     int  y,
  118.     UINT keyFlags
  119. );
  120. VOID
  121. USBView_OnLButtonUp (
  122.     HWND hWnd,
  123.     int  x,
  124.     int  y,
  125.     UINT keyFlags
  126. );
  127. VOID
  128. USBView_OnMouseMove (
  129.     HWND hWnd,
  130.     int  x,
  131.     int  y,
  132.     UINT keyFlags
  133. );
  134. VOID
  135. USBView_OnSize (
  136.     HWND hWnd,
  137.     UINT state,
  138.     int  cx,
  139.     int  cy
  140. );
  141. LRESULT
  142. USBView_OnNotify (
  143.     HWND    hWnd,
  144.     int     DlgItem,
  145.     LPNMHDR lpNMHdr
  146. );
  147. BOOL
  148. USBView_OnDeviceChange (
  149.     HWND  hwnd,
  150.     UINT  uEvent,
  151.     DWORD dwEventData
  152. );
  153. VOID DestroyTree (VOID);
  154. VOID RefreshTree (VOID);
  155. LRESULT CALLBACK
  156. AboutDlgProc (
  157.     HWND   hwnd,
  158.     UINT   uMsg,
  159.     WPARAM wParam,
  160.     LPARAM lParam
  161. );
  162. VOID
  163. WalkTree (
  164.     HTREEITEM        hTreeItem,
  165.     LPFNTREECALLBACK lpfnTreeCallback,
  166.     DWORD            dwRefData
  167. );
  168. VOID
  169. ExpandItem (
  170.     HWND      hTreeWnd,
  171.     HTREEITEM hTreeItem
  172. );
  173. //*****************************************************************************
  174. // G L O B A L S    P R I V A T E    T O    T H I S    F I L E
  175. //*****************************************************************************
  176. HINSTANCE       ghInstance;
  177. HWND            ghMainWnd;
  178. HMENU           ghMainMenu;
  179. HWND            ghTreeWnd;
  180. HWND            ghEditWnd;
  181. HWND            ghStatusWnd;
  182. HCURSOR         ghSplitCursor;
  183. int             gBarLocation    = 0;
  184. BOOL            gbButtonDown    = FALSE;
  185. HTREEITEM       ghTreeRoot      = NULL;
  186. BOOL            gDoAutoRefresh  = FALSE;
  187. BOOL            gDoConfigDesc   = FALSE;
  188. // added
  189. int             giGoodDevice;
  190. int             giBadDevice;
  191. int             giComputer;
  192. int             giHub;
  193. int             giNoDevice;
  194. HDEVNOTIFY      gNotifyDevHandle;
  195. HDEVNOTIFY      gNotifyHubHandle;
  196. //*****************************************************************************
  197. //
  198. // WinMain()
  199. //
  200. //*****************************************************************************
  201. int WINAPI
  202. WinMain (
  203.     HINSTANCE hInstance,
  204.     HINSTANCE hPrevInstance,
  205.     LPSTR     lpszCmdLine,
  206.     int       nCmdShow
  207. )
  208. {
  209.     MSG     msg;
  210.     HACCEL  hAccel;
  211.     ghInstance = hInstance;
  212.     ghSplitCursor = LoadCursor(ghInstance,
  213.                                MAKEINTRESOURCE(IDC_SPLIT));
  214.     if (!ghSplitCursor)
  215.     {
  216.         OOPS();
  217.         return 0;
  218.     }
  219.     hAccel = LoadAccelerators(ghInstance,
  220.                               MAKEINTRESOURCE(IDACCEL));
  221.     if (!hAccel)
  222.     {
  223.         OOPS();
  224.         return 0;
  225.     }
  226.     if (!CreateTextBuffer())
  227.     {
  228.         return 0;
  229.     }
  230.     if (!CreateMainWindow(nCmdShow))
  231.     {
  232.         return 0;
  233.     }
  234.     while (GetMessage(&msg, NULL, 0, 0))
  235.     {
  236.         if (!TranslateAccelerator(ghMainWnd,
  237.                                   hAccel,
  238.                                   &msg) &&
  239.             !IsDialogMessage(ghMainWnd,
  240.                              &msg))
  241.         {
  242.             TranslateMessage(&msg);
  243.             DispatchMessage(&msg);
  244.         }
  245.     }
  246.     DestroyTextBuffer();
  247.     CHECKFORLEAKS();
  248.     return 1;
  249. }
  250. //*****************************************************************************
  251. //
  252. // CreateMainWindow()
  253. //
  254. //*****************************************************************************
  255. BOOL
  256. CreateMainWindow (
  257.     int nCmdShow
  258. )
  259. {
  260.     RECT rc;
  261.     InitCommonControls();
  262.     ghMainWnd = CreateDialog(ghInstance,
  263.                              MAKEINTRESOURCE(IDD_MAINDIALOG),
  264.                              NULL,
  265.                              MainDlgProc);
  266.     if (ghMainWnd == NULL)
  267.     {
  268.         OOPS();
  269.         return FALSE;
  270.     }
  271.     GetWindowRect(ghMainWnd, &rc);
  272.     gBarLocation = (rc.right - rc.left) / 3;
  273.     ResizeWindows(FALSE, 0);
  274.     ShowWindow(ghMainWnd, nCmdShow);
  275.     UpdateWindow(ghMainWnd);
  276.     return TRUE;
  277. }
  278. //*****************************************************************************
  279. //
  280. // ResizeWindows()
  281. //
  282. // Handles resizing the two child windows of the main window.  If
  283. // bSizeBar is true, then the sizing is happening because the user is
  284. // moving the bar.  If bSizeBar is false, the sizing is happening
  285. // because of the WM_SIZE or something like that.
  286. //
  287. //*****************************************************************************
  288. VOID
  289. ResizeWindows (
  290.     BOOL    bSizeBar,
  291.     int     BarLocation
  292. )
  293. {
  294.     RECT    MainClientRect;
  295.     RECT    MainWindowRect;
  296.     RECT    TreeWindowRect;
  297.     RECT    StatusWindowRect;
  298.     int     right;
  299.     // Is the user moving the bar?
  300.     //
  301.     if (!bSizeBar)
  302.     {
  303.         BarLocation = gBarLocation;
  304.     }
  305.     GetClientRect(ghMainWnd, &MainClientRect);
  306.     GetWindowRect(ghStatusWnd, &StatusWindowRect);
  307.     // Make sure the bar is in a OK location
  308.     //
  309.     if (bSizeBar)
  310.     {
  311.         if (BarLocation <
  312.             GetSystemMetrics(SM_CXSCREEN)/WINDOWSCALEFACTOR)
  313.         {
  314.             return;
  315.         }
  316.         if ((MainClientRect.right - BarLocation) <
  317.             GetSystemMetrics(SM_CXSCREEN)/WINDOWSCALEFACTOR)
  318.         {
  319.             return;
  320.         }
  321.     }
  322.     // Save the bar location
  323.     //
  324.     gBarLocation = BarLocation;
  325.     // Move the tree window
  326.     //
  327.     MoveWindow(ghTreeWnd,
  328.                0,
  329.                0,
  330.                BarLocation,
  331.                MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top,
  332.                TRUE);
  333.     // Get the size of the window (in case move window failed
  334.     //
  335.     GetWindowRect(ghTreeWnd, &TreeWindowRect);
  336.     GetWindowRect(ghMainWnd, &MainWindowRect);
  337.     right = TreeWindowRect.right - MainWindowRect.left;
  338.     // Move the edit window with respect to the tree window
  339.     //
  340.     MoveWindow(ghEditWnd,
  341.                right+SIZEBAR,
  342.                0,
  343.                MainClientRect.right-(right+SIZEBAR),
  344.                MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top,
  345.                TRUE);
  346.     // Move the Status window with respect to the tree window
  347.     //
  348.     MoveWindow(ghStatusWnd,
  349.                0,
  350.                MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top,
  351.                MainClientRect.right,
  352.                StatusWindowRect.bottom - StatusWindowRect.top,
  353.                TRUE);
  354. }
  355. //*****************************************************************************
  356. //
  357. // MainWndProc()
  358. //
  359. //*****************************************************************************
  360. LRESULT CALLBACK
  361. MainDlgProc (
  362.     HWND   hWnd,
  363.     UINT   uMsg,
  364.     WPARAM wParam,
  365.     LPARAM lParam
  366. )
  367. {
  368.     switch (uMsg)
  369.     {        
  370.         HANDLE_MSG(hWnd, WM_INITDIALOG,     USBView_OnInitDialog);
  371.         HANDLE_MSG(hWnd, WM_CLOSE,          USBView_OnClose);
  372.         HANDLE_MSG(hWnd, WM_COMMAND,        USBView_OnCommand);
  373.         HANDLE_MSG(hWnd, WM_LBUTTONDOWN,    USBView_OnLButtonDown);
  374.         HANDLE_MSG(hWnd, WM_LBUTTONUP,      USBView_OnLButtonUp);
  375.         HANDLE_MSG(hWnd, WM_MOUSEMOVE,      USBView_OnMouseMove);
  376.         HANDLE_MSG(hWnd, WM_SIZE,           USBView_OnSize);
  377.         HANDLE_MSG(hWnd, WM_NOTIFY,         USBView_OnNotify);
  378.         HANDLE_MSG(hWnd, WM_DEVICECHANGE,   USBView_OnDeviceChange);
  379.     }
  380.     return 0;
  381. }
  382. //*****************************************************************************
  383. //
  384. // USBView_OnInitDialog()
  385. //
  386. //*****************************************************************************
  387. BOOL
  388. USBView_OnInitDialog (
  389.     HWND    hWnd,
  390.     HWND    hWndFocus,
  391.     LPARAM  lParam
  392. )
  393. {
  394.     HFONT                           hFont;
  395.     HIMAGELIST                      himl;
  396.     HICON                           hicon;
  397.     DEV_BROADCAST_DEVICEINTERFACE   broadcastInterface;    
  398.     // Register to receive notification when a USB device is plugged in.
  399.     broadcastInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  400.     broadcastInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  401.     memcpy( &(broadcastInterface.dbcc_classguid),
  402.             &(GUID_CLASS_USB_DEVICE),
  403.             sizeof(struct _GUID));
  404.     
  405.     gNotifyDevHandle = RegisterDeviceNotification(hWnd,
  406.                                                   &broadcastInterface,
  407.                                                   DEVICE_NOTIFY_WINDOW_HANDLE);
  408.     // Now register for Hub notifications.
  409.     memcpy( &(broadcastInterface.dbcc_classguid),
  410.             &(GUID_CLASS_USBHUB),
  411.             sizeof(struct _GUID));
  412.     
  413.     gNotifyHubHandle = RegisterDeviceNotification(hWnd,
  414.                                                   &broadcastInterface,
  415.                                                   DEVICE_NOTIFY_WINDOW_HANDLE);
  416.                                                
  417.     //end add    
  418.     ghTreeWnd = GetDlgItem(hWnd, IDC_TREE);
  419.     //added
  420.     if ((himl = ImageList_Create(15, 15,
  421.                                  FALSE, 2, 0)) == NULL)
  422.     {
  423.         OOPS();
  424.     }
  425.     hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_ICON));
  426.     giGoodDevice = ImageList_AddIcon(himl, hicon);
  427.     
  428.     hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_BADICON));
  429.     giBadDevice = ImageList_AddIcon(himl, hicon);
  430.     hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_COMPUTER));
  431.     giComputer = ImageList_AddIcon(himl, hicon);
  432.     hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_HUB));
  433.     giHub = ImageList_AddIcon(himl, hicon);
  434.     hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NODEVICE));
  435.     giNoDevice = ImageList_AddIcon(himl, hicon);
  436.     
  437.     TreeView_SetImageList(ghTreeWnd, himl, TVSIL_NORMAL);
  438.     // end add
  439.     ghEditWnd = GetDlgItem(hWnd, IDC_EDIT);
  440.     ghStatusWnd = GetDlgItem(hWnd, IDC_STATUS);
  441.     ghMainMenu = GetMenu(hWnd);
  442.     if (ghMainMenu == NULL)
  443.     {
  444.         OOPS();
  445.     }
  446.     hFont  = CreateFont(13,  8, 0, 0,
  447.                         400, 0, 0, 0,
  448.                         0,   1, 2, 1,
  449.                         49,  TEXT("Courier"));
  450.     SendMessage(ghEditWnd,
  451.                 WM_SETFONT,
  452.                 (WPARAM) hFont,
  453.                 0);
  454.     RefreshTree();    
  455.     return FALSE;
  456. }
  457. //*****************************************************************************
  458. //
  459. // USBView_OnClose()
  460. //
  461. //*****************************************************************************
  462. VOID
  463. USBView_OnClose (
  464.     HWND hWnd
  465. )
  466. {
  467.     DestroyTree();
  468.     PostQuitMessage(0);
  469.     EndDialog(hWnd, 0);
  470. }
  471. //*****************************************************************************
  472. //
  473. // USBView_OnCommand()
  474. //
  475. //*****************************************************************************
  476. VOID
  477. USBView_OnCommand (
  478.     HWND hWnd,
  479.     int  id,
  480.     HWND hwndCtl,
  481.     UINT codeNotify
  482. )
  483. {
  484.     MENUITEMINFO menuInfo;
  485.     switch (id)
  486.     {
  487.         case ID_AUTO_REFRESH:
  488.             gDoAutoRefresh = !gDoAutoRefresh;
  489.             menuInfo.cbSize = sizeof(menuInfo);
  490.             menuInfo.fMask  = MIIM_STATE;
  491.             menuInfo.fState = gDoAutoRefresh ? MFS_CHECKED : MFS_UNCHECKED;
  492.             SetMenuItemInfo(ghMainMenu,
  493.                             id,
  494.                             FALSE,
  495.                             &menuInfo);
  496.             break;
  497.         case ID_CONFIG_DESCRIPTORS:
  498.             gDoConfigDesc = !gDoConfigDesc;
  499.             menuInfo.cbSize = sizeof(menuInfo);
  500.             menuInfo.fMask  = MIIM_STATE;
  501.             menuInfo.fState = gDoConfigDesc ? MFS_CHECKED : MFS_UNCHECKED;
  502.             SetMenuItemInfo(ghMainMenu,
  503.                             id,
  504.                             FALSE,
  505.                             &menuInfo);
  506.             break;
  507.         case ID_ABOUT:
  508.             DialogBox(ghInstance,
  509.                       MAKEINTRESOURCE(IDD_ABOUT),
  510.                       ghMainWnd,
  511.                       AboutDlgProc);
  512.             break;
  513.         case ID_EXIT:
  514.             UnregisterDeviceNotification(gNotifyDevHandle);
  515.             UnregisterDeviceNotification(gNotifyHubHandle);
  516.             DestroyTree();
  517.             PostQuitMessage(0);
  518.             EndDialog(hWnd, 0);
  519.             break;
  520.         case ID_REFRESH:
  521.             RefreshTree();
  522.             break;
  523.     }
  524. }
  525. //*****************************************************************************
  526. //
  527. // USBView_OnLButtonDown()
  528. //
  529. //*****************************************************************************
  530. VOID
  531. USBView_OnLButtonDown (
  532.     HWND hWnd,
  533.     BOOL fDoubleClick,
  534.     int  x,
  535.     int  y,
  536.     UINT keyFlags
  537. )
  538. {
  539.     gbButtonDown = TRUE;
  540.     SetCapture(hWnd);
  541. }
  542. //*****************************************************************************
  543. //
  544. // USBView_OnLButtonUp()
  545. //
  546. //*****************************************************************************
  547. VOID
  548. USBView_OnLButtonUp (
  549.     HWND hWnd,
  550.     int  x,
  551.     int  y,
  552.     UINT keyFlags
  553. )
  554. {
  555.     gbButtonDown = FALSE;
  556.     ReleaseCapture();
  557. }
  558. //*****************************************************************************
  559. //
  560. // USBView_OnMouseMove()
  561. //
  562. //*****************************************************************************
  563. VOID
  564. USBView_OnMouseMove (
  565.     HWND hWnd,
  566.     int  x,
  567.     int  y,
  568.     UINT keyFlags
  569. )
  570. {
  571.     SetCursor(ghSplitCursor);
  572.     if (gbButtonDown)
  573.     {
  574.         ResizeWindows(TRUE, x);
  575.     }
  576. }
  577. //*****************************************************************************
  578. //
  579. // USBView_OnSize();
  580. //
  581. //*****************************************************************************
  582. VOID
  583. USBView_OnSize (
  584.     HWND hWnd,
  585.     UINT state,
  586.     int  cx,
  587.     int  cy
  588. )
  589. {
  590.     ResizeWindows(FALSE, 0);
  591. }
  592. //*****************************************************************************
  593. //
  594. // USBView_OnNotify()
  595. //
  596. //*****************************************************************************
  597. LRESULT
  598. USBView_OnNotify (
  599.     HWND    hWnd,
  600.     int     DlgItem,
  601.     LPNMHDR lpNMHdr
  602. )
  603. {
  604.     if (lpNMHdr->code == TVN_SELCHANGED)
  605.     {
  606.         HTREEITEM hTreeItem;
  607.         hTreeItem = ((NM_TREEVIEW *)lpNMHdr)->itemNew.hItem;
  608.         if (hTreeItem)
  609.         {
  610.             UpdateEditControl(ghEditWnd,
  611.                               ghTreeWnd,
  612.                               hTreeItem);
  613.         }
  614.     }
  615.     return 0;
  616. }
  617. //*****************************************************************************
  618. //
  619. // USBView_OnDeviceChange()
  620. //
  621. //*****************************************************************************
  622. BOOL
  623. USBView_OnDeviceChange (
  624.     HWND  hwnd,
  625.     UINT  uEvent,
  626.     DWORD dwEventData
  627. )
  628. {
  629.     if (gDoAutoRefresh)
  630.     {
  631.         switch (uEvent)
  632.         {
  633.             case DBT_DEVICEARRIVAL:
  634.             case DBT_DEVICEREMOVECOMPLETE:
  635.                 RefreshTree();
  636.                 break;
  637.         }
  638.     }
  639.     return TRUE;
  640. }
  641. //*****************************************************************************
  642. //
  643. // DestroyTree()
  644. //
  645. //*****************************************************************************
  646. VOID DestroyTree (VOID)
  647. {
  648.     // Clear the selection of the TreeView, so that when the tree is
  649.     // destroyed, the control won't try to constantly "shift" the
  650.     // selection to another item.
  651.     //
  652.     TreeView_SelectItem(ghTreeWnd, NULL);
  653.     // Destroy the current contents of the TreeView
  654.     //
  655.     if (ghTreeRoot)
  656.     {
  657.         WalkTree(ghTreeRoot, CleanupItem, 0);
  658.         TreeView_DeleteAllItems(ghTreeWnd);
  659.         ghTreeRoot = NULL;
  660.     }
  661. }
  662. //*****************************************************************************
  663. //
  664. // RefreshTree()
  665. //
  666. //*****************************************************************************
  667. VOID RefreshTree (VOID)
  668. {
  669.     CHAR  statusText[128];
  670.     ULONG devicesConnected;
  671.     // Clear the selection of the TreeView, so that when the tree is
  672.     // destroyed, the control won't try to constantly "shift" the
  673.     // selection to another item.
  674.     //
  675.     TreeView_SelectItem(ghTreeWnd, NULL);
  676.     // Clear the edit control
  677.     //
  678.     SetWindowText(ghEditWnd, "");
  679.     // Destroy the current contents of the TreeView
  680.     //
  681.     if (ghTreeRoot)
  682.     {
  683.         WalkTree(ghTreeRoot, CleanupItem, 0);
  684.         TreeView_DeleteAllItems(ghTreeWnd);
  685.         ghTreeRoot = NULL;
  686.     }
  687.     // Create the root tree node
  688.     //
  689.     ghTreeRoot = AddLeaf(TVI_ROOT, 0, "My Computer");
  690.     if (ghTreeRoot != NULL)
  691.     {
  692.         // Enumerate all USB buses and populate the tree
  693.         //
  694.         EnumerateHostControllers(ghTreeRoot, &devicesConnected);
  695.         //
  696.         // Expand all tree nodes
  697.         //
  698.         WalkTree(ghTreeRoot, ExpandItem, 0);
  699.         // Update Status Line with number of devices connected
  700.         //
  701.         wsprintf(statusText, "Devices Connected: %d   Hubs Connected: %d", 
  702.                  devicesConnected, TotalHubs);
  703.         SetWindowText(ghStatusWnd, statusText);
  704.     }
  705.     else
  706.     {
  707.         OOPS();
  708.     }
  709. }
  710. //*****************************************************************************
  711. //
  712. // AboutDlgProc()
  713. //
  714. //*****************************************************************************
  715. LRESULT CALLBACK
  716. AboutDlgProc (
  717.     HWND   hwnd,
  718.     UINT   uMsg,
  719.     WPARAM wParam,
  720.     LPARAM lParam
  721. )
  722. {
  723.     switch (uMsg)
  724.     {
  725.     case WM_COMMAND:
  726.         switch (LOWORD(wParam))
  727.         {
  728.         case IDOK:
  729.             EndDialog (hwnd, 0);
  730.             break;
  731.         }
  732.         break;
  733.     }
  734.     return FALSE;
  735. }
  736. //*****************************************************************************
  737. //
  738. // AddLeaf()
  739. //
  740. //*****************************************************************************
  741. HTREEITEM
  742. AddLeaf (
  743.     HTREEITEM hTreeParent,
  744.     LPARAM    lParam,
  745.     LPTSTR    lpszText,
  746.     ...
  747. )
  748. {
  749.     TCHAR           szBuffer[1024];
  750.     va_list         list;
  751.     TV_INSERTSTRUCT tvins;
  752.     HTREEITEM       hti;
  753.     // added for tree view icons
  754.     PUSB_NODE_CONNECTION_INFORMATION ConnectInfo = NULL;
  755.     if (lParam)
  756.     {
  757.         ConnectInfo = ((PUSBDEVICEINFO)lParam)->ConnectionInfo;
  758.     }
  759.     
  760.     // end add
  761.     va_start(list, lpszText);
  762.     vsprintf(szBuffer,
  763.              lpszText,
  764.              list);
  765.     memset(&tvins, 0, sizeof(tvins));
  766.     // Set the parent item
  767.     //
  768.     tvins.hParent = hTreeParent;
  769.     tvins.hInsertAfter = TVI_LAST;
  770.     // pszText and lParam members are valid
  771.     //
  772.     tvins.item.mask = TVIF_TEXT | TVIF_PARAM;
  773.     // Set the text of the item.
  774.     //
  775.     tvins.item.pszText = szBuffer;
  776.     // Set the user context item
  777.     //
  778.     tvins.item.lParam = lParam;
  779.     // Add the item to the tree-view control.
  780.     //
  781.     hti = TreeView_InsertItem(ghTreeWnd, &tvins);
  782.             // added
  783.     tvins.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  784.     tvins.item.hItem = hti;
  785.     // Determine which icon to display for the device
  786.     tvins.item.iImage = giGoodDevice;
  787.     tvins.item.iSelectedImage = giGoodDevice;
  788. /*    if (!lParam)
  789.     {
  790.         if (!(strcmp("My Computer", lpszText)))
  791.         {
  792.             tvins.item.iImage = giComputer;
  793.             tvins.item.iSelectedImage = giComputer;
  794.         }
  795.         else
  796.         {
  797.         //it is the host controller
  798.         }
  799.     }  */
  800.     if (!ConnectInfo)
  801.     {
  802.         if (!(strcmp("My Computer", lpszText)))
  803.             {
  804.                 tvins.item.iImage = giComputer;
  805.                 tvins.item.iSelectedImage = giComputer;
  806.             }
  807.             else
  808.             {
  809.             //it is the host controller
  810.             }
  811.     }
  812.     else
  813.     {
  814.         if (ConnectInfo->DeviceIsHub)  // Device is a Hub!!
  815.         {
  816.             tvins.item.iImage = giHub;
  817.             tvins.item.iSelectedImage = giHub;
  818.         }
  819.         if (!ConnectInfo->CurrentConfigurationValue)
  820.         {
  821.             tvins.item.iImage = giBadDevice;
  822.             tvins.item.iSelectedImage = giBadDevice;
  823.             if (NoDeviceConnected == ConnectInfo->ConnectionStatus) // Empty Port
  824.             {
  825.                 tvins.item.iImage = giNoDevice;
  826.                 tvins.item.iSelectedImage = giNoDevice;
  827.             }
  828.         }
  829.     }
  830.     
  831.     TreeView_SetItem(ghTreeWnd, &tvins.item);
  832.     return hti;
  833. }
  834. //*****************************************************************************
  835. //
  836. // WalkTree()
  837. //
  838. //*****************************************************************************
  839. VOID
  840. WalkTree (
  841.     HTREEITEM        hTreeItem,
  842.     LPFNTREECALLBACK lpfnTreeCallback,
  843.     DWORD            dwRefData
  844. )
  845. {
  846.     if (hTreeItem)
  847.     {
  848.         // Recursively call WalkTree on the node's first child.
  849.         //
  850.         WalkTree(TreeView_GetChild(ghTreeWnd, hTreeItem),
  851.                  lpfnTreeCallback,
  852.                  dwRefData);
  853.         //
  854.         // Call the lpfnCallBack on the node itself.
  855.         //
  856.         (*lpfnTreeCallback)(ghTreeWnd, hTreeItem);
  857.         //
  858.         //
  859.         // Recursively call WalkTree on the node's first sibling.
  860.         //
  861.         WalkTree(TreeView_GetNextSibling(ghTreeWnd, hTreeItem),
  862.                  lpfnTreeCallback,
  863.                  dwRefData);
  864.     }
  865. }
  866. //*****************************************************************************
  867. //
  868. // ExpandItem()
  869. //
  870. //*****************************************************************************
  871. VOID
  872. ExpandItem (
  873.     HWND      hTreeWnd,
  874.     HTREEITEM hTreeItem
  875. )
  876. {
  877.     //
  878.     // Make this node visible.
  879.     //
  880.     TreeView_Expand(hTreeWnd, hTreeItem, TVE_EXPAND);
  881. }
  882. #if DBG
  883. //*****************************************************************************
  884. //
  885. // Oops()
  886. //
  887. //*****************************************************************************
  888. VOID
  889. Oops
  890. (
  891.     CHAR *File,
  892.     ULONG Line
  893. )
  894. {
  895.     char szBuf[256];
  896.     wsprintf(szBuf, "File: %s, Line %d", File, Line);
  897.     MessageBox(ghMainWnd, szBuf, "Oops!", MB_OK);
  898. }
  899. #endif