//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 2001. // // File: B I N D V I E W . C P P // // Contents: // // Notes: // // Author: Alok Sinha 15-Amy-01 // //---------------------------------------------------------------------------- #include "BindView.h" //---------------------------------------------------------------------------- // Globals // // // Image list for devices of various setup class. // SP_CLASSIMAGELIST_DATA ClassImageListData; HINSTANCE hInstance; HMENU hMainMenu; HMENU hComponentSubMenu; HMENU hBindingPathSubMenu; // // Network components whose bindings are enumerated. // LPWSTR lpszNetClass[] = { L"All Clients", L"All Services", L"All Protocols" }; // // GUIDs of network components. // const GUID *pguidNetClass [] = { &GUID_DEVCLASS_NETCLIENT, &GUID_DEVCLASS_NETSERVICE, &GUID_DEVCLASS_NETTRANS, &GUID_DEVCLASS_NET }; // // Program entry point. // int APIENTRY WinMain (HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // // Make sure common control DLL is loaded. // hInstance = hInst; InitCommonControls(); if ( DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_MAIN), NULL, MainDlgProc) == -1 ) { ErrMsg( HRESULT_FROM_WIN32(GetLastError()), L"Failed to create the main dialog box, exiting..." ); } return 0; } // // WndProc for the main dialog box. // INT_PTR CALLBACK MainDlgProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { HWND hwndBindingTree; HICON hIcon; switch (uMsg) { case WM_INITDIALOG: hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_BINDVIEW) ); if ( !hIcon ) { ErrMsg( HRESULT_FROM_WIN32(GetLastError()), L"Couldn't load the program icon, exiting..." ); return FALSE; } SetClassLongPtr( hwndDlg, GCLP_HICON, (LONG_PTR)hIcon ); hMainMenu = LoadMenu( hInstance, MAKEINTRESOURCE(IDM_OPTIONS) ); if ( !hMainMenu ) { ErrMsg( HRESULT_FROM_WIN32(GetLastError()), L"Couldn't load the program menu, exiting..." ); return FALSE; } hComponentSubMenu = GetSubMenu( hMainMenu, 0 ); hBindingPathSubMenu = GetSubMenu( hMainMenu, 1 ); if ( !hComponentSubMenu || !hBindingPathSubMenu ) { ErrMsg( HRESULT_FROM_WIN32(GetLastError()), L"Couldn't load the program menu, exiting..." ); DestroyMenu( hMainMenu ); return FALSE; } // // Add the network components types whose bindings are shown. // UpdateComponentTypeList( GetDlgItem(hwndDlg, IDL_COMPONENT_TYPES) ); // // Load and associate the image list of all device classes with // tree. // hwndBindingTree = GetDlgItem( hwndDlg, IDT_BINDINGS ); ZeroMemory( &ClassImageListData, sizeof(SP_CLASSIMAGELIST_DATA) ); ClassImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA); if ( SetupDiGetClassImageList(&ClassImageListData) == TRUE ) { TreeView_SetImageList( hwndBindingTree, ClassImageListData.ImageList, LVSIL_NORMAL ); } else { // // In case, we failed to load the image list, abort. // ErrMsg( HRESULT_FROM_WIN32(GetLastError()), L"Couldn't load the image list of " L"device classes, exiting..." ); DestroyMenu( hMainMenu ); return FALSE; } // // Enumerate the bindings of the network component selected by default. // EnumNetBindings( hwndBindingTree, DEFAULT_COMPONENT_SELECTED ); return TRUE; // Tell Windows to continue creating the dialog box. case WM_COMMAND: switch( LOWORD(wParam) ) { case IDL_COMPONENT_TYPES: if ( HIWORD(wParam) == CBN_SELCHANGE ) { // // User has selected a new network component type. // RefreshAll( hwndDlg ); } break; case IDB_EXPAND_ALL: case IDB_COLLAPSE_ALL: if ( HIWORD(wParam) == BN_CLICKED ) { HTREEITEM hItem; // // Expand/Collapse the entire tree. // hwndBindingTree = GetDlgItem( hwndDlg, IDT_BINDINGS ); hItem = TreeView_GetSelection( hwndBindingTree ); ExpandCollapseAll( hwndBindingTree, TVI_ROOT, (LOWORD(wParam) == IDB_EXPAND_ALL) ? TVE_EXPAND : TVE_COLLAPSE ); TreeView_SelectSetFirstVisible( hwndBindingTree, hItem ); } break; case IDB_SAVE: if ( HIWORD(wParam) == BN_CLICKED ) { // // Save the binding information to a file. // WCHAR lpszFile[MAX_PATH+1]; if ( GetFileName(hwndDlg, NULL, L"Select a file name", OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT, lpszFile) ) { DumpBindings( lpszFile ); } } break; case IDB_INSTALL: if ( HIWORD(wParam) == BN_CLICKED ) { // // Install a network component. // if ( (BOOL)DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_INSTALL), hwndDlg, InstallDlg) == TRUE ) { RefreshAll( hwndDlg ); } } break; case IDB_UNINSTALL: if ( HIWORD(wParam) == BN_CLICKED ) { // // Uninstall a network component. // if ( (BOOL)DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_UNINSTALL), hwndDlg, UninstallDlg) == TRUE ) { RefreshAll( hwndDlg ); } } } break; case WM_NOTIFY: { LPNMHDR lpnm; lpnm = (LPNMHDR)lParam; if ( (lpnm->idFrom == IDT_BINDINGS) && (lpnm->code == NM_RCLICK) ) { // // A network component or a binding path is selected // with a righ-click. // ProcessRightClick( lpnm ); // // Tell Windows that the righ-click has been handled // us. // return TRUE; } } break; case WM_SYSCOMMAND: if ( (0xFFF0 & wParam) == SC_CLOSE ) { // // Before exiting, make sure to delete the image list // and the buffers associated with each item in the tree. // SetupDiDestroyClassImageList( &ClassImageListData ); ReleaseMemory( GetDlgItem(hwndDlg, IDT_BINDINGS), TVI_ROOT ); DestroyMenu( hMainMenu ); EndDialog( hwndDlg, 0 ); } } return FALSE; } // // WndProc of the dialog box for binding/unbinding compoents. // INT_PTR CALLBACK BindComponentDlg (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { LPBIND_UNBIND_INFO lpBindUnbind; switch (uMsg) { case WM_INITDIALOG: { DWORD dwCount; // // Save the lParam which is an index to the selected network // component. // SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)lParam ); lpBindUnbind = (LPBIND_UNBIND_INFO)lParam; // // fBindTo is TRUE when the user wants to bind the selected // component to other components. So, we list the components // that are not bound and can bind. // // // fBindTo is FALSE when the user wants to unbind the selected // component from other components. So, we list the components // that are bound to it. // // // ListCompToBindUnbind returns number of components added to // the list. Keep track of it. If it zero then, we don't want to // show this dialog box. // dwCount = ListCompToBindUnbind( lpBindUnbind->lpszInfId, ADAPTERS_SELECTED, GetDlgItem(hwndDlg, IDT_COMPONENT_LIST), lpBindUnbind->fBindTo == FALSE ); dwCount += ListCompToBindUnbind( lpBindUnbind->lpszInfId, CLIENTS_SELECTED, GetDlgItem(hwndDlg, IDT_COMPONENT_LIST), lpBindUnbind->fBindTo == FALSE ); dwCount += ListCompToBindUnbind( lpBindUnbind->lpszInfId, SERVICES_SELECTED, GetDlgItem(hwndDlg, IDT_COMPONENT_LIST), lpBindUnbind->fBindTo == FALSE ); dwCount += ListCompToBindUnbind( lpBindUnbind->lpszInfId, PROTOCOLS_SELECTED, GetDlgItem(hwndDlg, IDT_COMPONENT_LIST), lpBindUnbind->fBindTo == FALSE ); if ( dwCount > 0 ) { // // Since the same dialog box is used for unbind opration, // we need to update the text on the button to reflect that // it is a bind operation. // if ( lpBindUnbind->fBindTo == FALSE ) { SetWindowTextW( hwndDlg, L"Unbind From Network Components" ); SetWindowTextW( GetDlgItem(hwndDlg, IDB_BIND_UNBIND), L"Unbind" ); SetWindowTextW( GetDlgItem(hwndDlg, IDG_COMPONENT_LIST), L"Select components to unbind from" ); } } else { if ( lpBindUnbind->fBindTo == TRUE ) { ErrMsg( 0, L"There no network components that can " L"bind to the selected component." ); } else { ErrMsg( 0, L"There no network components that are " L"bound to the selected component." ); } PostMessage( hwndDlg, WM_NO_COMPONENTS, 0, 0 ); } return TRUE; } case WM_NO_COMPONENTS: EndDialog( hwndDlg, 0 ); break; case WM_COMMAND: if ( (LOWORD(wParam) == IDB_CLOSE) && (HIWORD(wParam) == BN_CLICKED) ) { // // Before deleting the list in the tree, free the buffer // associated with each item. The buffer holds the // INF Id of network components. // ReleaseMemory( GetDlgItem(hwndDlg, IDT_COMPONENT_LIST), TVI_ROOT ); EndDialog( hwndDlg, 0 ); } else { // // User wants to bind/unbind. // if ( (LOWORD(wParam) == IDB_BIND_UNBIND) && (HIWORD(wParam) == BN_CLICKED) ) { lpBindUnbind = (LPBIND_UNBIND_INFO)GetWindowLongPtr( hwndDlg, DWLP_USER ); if ( BindUnbind(lpBindUnbind->lpszInfId, GetDlgItem(hwndDlg, IDT_COMPONENT_LIST), lpBindUnbind->fBindTo) ) { RefreshBindings( hwndDlg, lpBindUnbind->lpszInfId ); } ReleaseMemory( GetDlgItem(hwndDlg, IDT_COMPONENT_LIST), TVI_ROOT ); EndDialog( hwndDlg, 0 ); } } break; case WM_SYSCOMMAND: if ( (0xFFF0 & wParam) == SC_CLOSE ) { // // Before deleting the list in the tree, free the buffer // associated with each item. The buffer holds the // INF Id of network components. // ReleaseMemory( GetDlgItem(hwndDlg, IDT_COMPONENT_LIST), TVI_ROOT ); EndDialog( hwndDlg, 0 ); } } return FALSE; } // //WndProc of the dialog box for installing network components. // INT_PTR CALLBACK InstallDlg (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: { HWND hwndTree; // // List types of network components e.g. client, // protocol and service. // hwndTree = GetDlgItem( hwndDlg, IDT_COMPONENT_LIST ); TreeView_SetImageList( hwndTree, ClassImageListData.ImageList, LVSIL_NORMAL ); // // Insert and select client by default. // TreeView_Select( hwndTree, InsertItem(hwndTree, CLIENTS_SELECTED), TVGN_CARET ); InsertItem( hwndTree, SERVICES_SELECTED ); InsertItem( hwndTree, PROTOCOLS_SELECTED ); // // Initialize it to FALSE. It will be set to TRUE when // at least one component is installed. // SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)FALSE ); return TRUE; } case WM_COMMAND: switch( LOWORD(wParam) ) { case IDB_INSTALL: // // Install from Windows system directory. // if ( HIWORD(wParam) == BN_CLICKED ) { InstallSelectedComponentType( hwndDlg, NULL ); } break; case IDB_BROWSE: // // User wants to specify an INF file for the network // to install. // if ( HIWORD(wParam) == BN_CLICKED ) { WCHAR lpszInfFile[MAX_PATH+1]; if ( GetFileName(hwndDlg, L"INF files (*.inf)\0*.inf\0", L"Select the INF file of the network component to install", OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST, lpszInfFile) ) { InstallSelectedComponentType( hwndDlg, lpszInfFile ); } } break; case IDB_CLOSE: if ( HIWORD(wParam) == BN_CLICKED ) { // // Return the value of DWLP_USER to indicate whether one or // more components have been installed. Accordingly, the // the list will be refreshed. // EndDialog( hwndDlg, GetWindowLongPtr(hwndDlg, DWLP_USER) ); } } break; case WM_NOTIFY: { LPNMHDR lpnm; lpnm = (LPNMHDR)lParam; if ( (lpnm->idFrom == IDT_COMPONENT_LIST) && (lpnm->code == NM_DBLCLK) ) { // // On double-click, install from Windows system directory. // InstallSelectedComponentType( hwndDlg, NULL ); } } break; case WM_SYSCOMMAND: if ( (0xFFF0 & wParam) == SC_CLOSE ) { // // Return the value of DWLP_USER to indicate whether one or // more components have been installed. Accordingly, the // the list will be refreshed. // EndDialog( hwndDlg, GetWindowLongPtr(hwndDlg, DWLP_USER) ); } } return FALSE; } // // WndProc of the dialog box for uninstalling a network component. // INT_PTR CALLBACK UninstallDlg (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { HWND hwndTree; switch (uMsg) { case WM_INITDIALOG: hwndTree = GetDlgItem( hwndDlg, IDT_COMPONENT_LIST ); TreeView_SetImageList( hwndTree, ClassImageListData.ImageList, LVSIL_NORMAL ); // // List all the compoents currently installed. // ListInstalledComponents( hwndTree, &GUID_DEVCLASS_NETCLIENT); ListInstalledComponents( hwndTree, &GUID_DEVCLASS_NETSERVICE ); ListInstalledComponents( hwndTree, &GUID_DEVCLASS_NETTRANS ); // // Initialize it to FALSE. It will be set to TRUE when // at least one component is installed. // SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)FALSE ); return TRUE; case WM_COMMAND: switch( LOWORD(wParam) ) { case IDB_REMOVE: if ( HIWORD(wParam) == BN_CLICKED ) { // // Uninstall the selected component. // UninstallSelectedComponent( hwndDlg ); } break; case IDB_CLOSE: if ( HIWORD(wParam) == BN_CLICKED ) { hwndTree = GetDlgItem( hwndDlg, IDT_COMPONENT_LIST ); ReleaseMemory( hwndTree, TVI_ROOT ); // // Return the value of DWLP_USER to indicate whether one or // more components have been installed. Accordingly, the // the list will be refreshed. // EndDialog( hwndDlg, GetWindowLongPtr(hwndDlg, DWLP_USER) ); } } break; case WM_NOTIFY: { LPNMHDR lpnm; lpnm = (LPNMHDR)lParam; if ( (lpnm->idFrom == IDT_COMPONENT_LIST) && (lpnm->code == NM_DBLCLK) ) { UninstallSelectedComponent( hwndDlg ); } } break; case WM_SYSCOMMAND: if ( (0xFFF0 & wParam) == SC_CLOSE ) { hwndTree = GetDlgItem( hwndDlg, IDT_COMPONENT_LIST ); ReleaseMemory( hwndTree, TVI_ROOT ); // // Return the value of DWLP_USER to indicate whether one or // more components have been installed. Accordingly, the // the list will be refreshed. // EndDialog( hwndDlg, GetWindowLongPtr(hwndDlg, DWLP_USER) ); } } return FALSE; } //+--------------------------------------------------------------------------- // // Function: DumpBindings // // Purpose: Write the binding information. // // Arguments: // lpszFile [in] Name of the file in which to write. // // Returns: None // // Notes: // VOID DumpBindings (LPWSTR lpszFile) { FILE *fp; fp = _wfopen( lpszFile, L"w" ); if ( fp == NULL ) { ErrMsg( 0, L"Unable to open %s.", lpszFile ); } else { WriteBindings( fp ); fclose( fp ); } return; } // // Function: InstallSelectedComponentType // // Purpose: Install a network component. // // Arguments: // hwndDlg [in] Handle to Install dialog box. // lpszInfFile [in] Inf file of the network component. // // Returns: None // // Notes: // If lpszInfFile is NULL, network components are installed from the // system directory. // VOID InstallSelectedComponentType (HWND hwndDlg, LPWSTR lpszInfFile) { HWND hwndTree; HTREEITEM hItem; LPARAM lParam; HCURSOR hPrevCursor; HCURSOR hWaitCursor; HWND hwndFocus; DWORD dwType; BOOL fEnable; HRESULT hr; hwndTree = GetDlgItem( hwndDlg, IDT_COMPONENT_LIST ); // // Find out the type of component selected. // hItem = TreeView_GetSelection( hwndTree ); if ( hItem ) { if ( GetItemInfo( hwndTree, hItem, &lParam, &dwType, &fEnable) ) { // // Disable the install dialog controls. // hwndFocus = GetFocus(); EnableWindow( hwndTree, FALSE ); EnableWindow( GetDlgItem(hwndDlg,IDB_OK), FALSE ); EnableWindow( GetDlgItem(hwndDlg,IDB_CLOSE), FALSE ); hWaitCursor = LoadCursor( NULL, IDC_WAIT ); if ( hWaitCursor ) { hPrevCursor = SetCursor( hWaitCursor ); } if ( lpszInfFile ) { LPWSTR lpszPnpID; // // Inf file name specified, install the network component // from this file. // hr = GetPnpID( lpszInfFile, &lpszPnpID ); if ( hr == S_OK ) { hr = InstallSpecifiedComponent( lpszInfFile, lpszPnpID, pguidNetClass[(UINT)lParam] ); CoTaskMemFree( lpszPnpID ); } else { ErrMsg( hr, L"Error reading the INF file %s.", lpszInfFile ); } } else { // // Install from system directory. // hr = InstallComponent( hwndTree, pguidNetClass[(UINT)lParam] ); } if ( hWaitCursor ) { SetCursor( hPrevCursor ); } switch( hr ) { case S_OK: MessageBoxW( hwndTree, L"Component installed successfully.", L"Network Component Installation", MB_OK | MB_ICONINFORMATION ); SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)TRUE ); break; case NETCFG_S_REBOOT: MessageBoxW( hwndTree, L"Component installed successfully: " L"Reboot required.", L"Network Component Installation", MB_OK | MB_ICONINFORMATION ); SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)TRUE ); } // // Enable the install dialog controls. // EnableWindow( hwndTree, TRUE ); EnableWindow( GetDlgItem(hwndDlg,IDB_OK), TRUE ); EnableWindow( GetDlgItem(hwndDlg,IDB_CLOSE), TRUE ); SetFocus( hwndFocus ); } } return; } // // Function: GetPnpID // // Purpose: Retrieve PnpID from an inf file. // // Arguments: // lpszInfFile [in] Inf file to search. // lppszPnpID [out] PnpID found. // // Returns: TRUE on success. // // Notes: // HRESULT GetPnpID (LPWSTR lpszInfFile, LPWSTR *lppszPnpID) { HINF hInf; LPWSTR lpszModelSection; HRESULT hr; *lppszPnpID = NULL; hInf = SetupOpenInfFileW( lpszInfFile, NULL, INF_STYLE_WIN4, NULL ); if ( hInf == INVALID_HANDLE_VALUE ) { return HRESULT_FROM_WIN32(GetLastError()); } // // Read the Model section name from Manufacturer section. // hr = GetKeyValue( hInf, L"Manufacturer", NULL, 1, &lpszModelSection ); if ( hr == S_OK ) { // // Read PnpID from the Model section. // hr = GetKeyValue( hInf, lpszModelSection, NULL, 2, lppszPnpID ); CoTaskMemFree( lpszModelSection ); } SetupCloseInfFile( hInf ); return hr; } // // Function: GetKeyValue // // Purpose: Retrieve the value of a key from the inf file. // // Arguments: // hInf [in] Inf file handle. // lpszSection [in] Section name. // lpszKey [in] Key name. // dwIndex [in] Key index. // lppszValue [out] Key value. // // Returns: S_OK on success, otherwise and error code. // // Notes: // HRESULT GetKeyValue (HINF hInf, LPCWSTR lpszSection, LPCWSTR lpszKey, DWORD dwIndex, LPWSTR *lppszValue) { INFCONTEXT infCtx; DWORD dwSizeNeeded; HRESULT hr; *lppszValue = NULL; if ( SetupFindFirstLineW(hInf, lpszSection, lpszKey, &infCtx) == FALSE ) { return HRESULT_FROM_WIN32(GetLastError()); } SetupGetStringFieldW( &infCtx, dwIndex, NULL, 0, &dwSizeNeeded ); *lppszValue = (LPWSTR)CoTaskMemAlloc( sizeof(WCHAR) * dwSizeNeeded ); if ( !*lppszValue ) { return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); } if ( SetupGetStringFieldW(&infCtx, dwIndex, *lppszValue, dwSizeNeeded, NULL) == FALSE ) { hr = HRESULT_FROM_WIN32(GetLastError()); CoTaskMemFree( *lppszValue ); *lppszValue = NULL; } else { hr = S_OK; } return hr; } // // Function: UninstallSelectedComponent // // Purpose: Uninstall the selected network component. // // Arguments: // hwndDlg [in] Window handle of the uninstall dialog box. // // Returns: TRUE on success. // // Notes: // VOID UninstallSelectedComponent (HWND hwndDlg) { HWND hwndTree; HTREEITEM hItem; LPARAM lParam; HCURSOR hPrevCursor; HCURSOR hWaitCursor; DWORD dwType; BOOL fEnable; HRESULT hr; hwndTree = GetDlgItem( hwndDlg, IDT_COMPONENT_LIST ); // // Get the selected item to get its lParam which is the // PnpID of the network component. // hItem = TreeView_GetSelection( hwndTree ); if ( hItem ) { if ( GetItemInfo( hwndTree, hItem, &lParam, &dwType, &fEnable) ) { hWaitCursor = LoadCursor( NULL, IDC_WAIT ); if ( hWaitCursor ) { hPrevCursor = SetCursor( hWaitCursor ); } // // Uninstall the selected component. // hr = UninstallComponent( (LPWSTR)lParam ); if ( hWaitCursor ) { SetCursor( hPrevCursor ); } switch( hr ) { case S_OK: MessageBoxW( hwndTree, L"Uninstallation successful.", L"Network Component Uninstallation", MB_OK | MB_ICONINFORMATION ); CoTaskMemFree( (LPVOID)lParam ); TreeView_DeleteItem( hwndTree, hItem ); SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)TRUE ); break; case NETCFG_S_REBOOT: MessageBoxW( hwndTree, L"Uninstallation successful: " L"Reboot required.", L"Network Component Uninstallation", MB_OK | MB_ICONINFORMATION ); CoTaskMemFree( (LPVOID)lParam ); TreeView_DeleteItem( hwndTree, hItem ); SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)TRUE ); } } } return; } // // Function: ExpandCollapseAll // // Purpose: Expand or collapse a tree. // // Arguments: // hwndTree [in] Window handle of the tree. // hTreeItem [in] Handle of root item. // uiFlag [in] Flag indicating whether to expand or collapse. // // Returns: None. // // Notes: // VOID ExpandCollapseAll (HWND hwndTree, HTREEITEM hTreeItem, UINT uiFlag) { HTREEITEM hItemChild; hItemChild = TreeView_GetChild( hwndTree, hTreeItem ); if ( hItemChild ) { // // If the root has one or more children, expand/collapse the root. // TreeView_Expand( hwndTree, hTreeItem, uiFlag ); } while ( hItemChild ) { // // Expand/collapse all the children. // ExpandCollapseAll( hwndTree, hItemChild, uiFlag ); // // Expand/collapse all the siblings. // hItemChild = TreeView_GetNextSibling( hwndTree, hItemChild ); } return; } // // Function: GetFileName // // Purpose: Prompt for a filename. // // Arguments: // hwndDlg [in] Window handle of the parent. // lpszFilter [in] See documentation for GetOpenFileName. // lpszTitle [in] See documentation for GetOpenFileName. // dwFlags [in] See documentation for GetOpenFileName. // lpszFile [in] See documentation for GetOpenFileName. // // Returns: See documentation for GetOpenFileName. // // Notes: // BOOL GetFileName (HWND hwndDlg, LPWSTR lpszFilter, LPWSTR lpszTitle, DWORD dwFlags, LPWSTR lpszFile) { OPENFILENAMEW ofn; lpszFile[0] = NULL; ZeroMemory( &ofn, sizeof(OPENFILENAMEW) ); ofn.lStructSize = sizeof(OPENFILENAMEW); ofn.hwndOwner = hwndDlg; ofn.lpstrFilter = lpszFilter; ofn.lpstrFile = lpszFile; ofn.nMaxFile = MAX_PATH+1; ofn.lpstrTitle = lpszTitle; ofn.Flags = dwFlags; return GetOpenFileName( &ofn ); } // // Function: ProcessRightClick // // Purpose: Handle righ mouse button click. // // Arguments: // lpnm [in] LPNMHDR info // // Returns: None. // // Notes: // VOID ProcessRightClick (LPNMHDR lpnm) { HTREEITEM hItemSelected; LPARAM lParam; DWORD dwItemType; BOOL fEnabled; // // Determine the item on which user clicked the right mouse button. // hItemSelected = TreeView_GetDropHilight( lpnm->hwndFrom ); if ( !hItemSelected ) { hItemSelected = TreeView_GetSelection( lpnm->hwndFrom ); } else { // // User has right-clicked an unselected item, make that a selected // item. // TreeView_Select( lpnm->hwndFrom, hItemSelected, TVGN_CARET ); } if ( hItemSelected ) { // // Get the lParam of the selected node in the tree which points to inf id or // pathtoken name depending on if the node represents a network component or // a binding path. // if ( GetItemInfo(lpnm->hwndFrom, hItemSelected, &lParam, &dwItemType, &fEnabled) ) { if ( dwItemType & ITEM_NET_COMPONENTS ) { // // Show the shortcut menu of operations for a network component. // ShowComponentMenu( lpnm->hwndFrom, hItemSelected, lParam); } else { if ( dwItemType & ITEM_NET_BINDINGS ) { // // Show the shortcut menu of operations for a binding path. // ShowBindingPathMenu( lpnm->hwndFrom, hItemSelected, lParam, fEnabled ); } } } } return; } // // Function: ShowComponentMenu // // Purpose: Show shortcut menu of options for a network component. // // Arguments: // hwndOwner [in] Owner window. // hItem [in] Selected item representing a network component. // lParam [in] PnpID of the network component. // // Returns: None. // // Notes: // VOID ShowComponentMenu (HWND hwndOwner, HTREEITEM hItem, LPARAM lParam) { ULONG ulSelection; POINT pt; GetCursorPos( &pt ); ulSelection = (ULONG)TrackPopupMenu( hComponentSubMenu, TPM_RIGHTALIGN | TPM_BOTTOMALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwndOwner, NULL ); if ( ulSelection ) { // // Do the selected action. // HandleComponentOperation( hwndOwner, ulSelection, hItem, lParam ); } return; } // // Function: ShowBindingPathMenu // // Purpose: Show shortcut menu of options for a network component. // // Arguments: // hwndOwner [in] Owner window. // hItem [in] Selected item representing a binding path. // lParam [in] PnpID of the network component. // fEnabled [in] TRUE when the path is enabled. // // Returns: None. // // Notes: // VOID ShowBindingPathMenu (HWND hwndOwner, HTREEITEM hItem, LPARAM lParam, BOOL fEnabled) { MENUITEMINFOW menuItemInfo; ULONG ulSelection; POINT pt; // // Build the shortcut menu depending on whether path is // disabled or enabled. // ZeroMemory( &menuItemInfo, sizeof(MENUITEMINFOW) ); menuItemInfo.cbSize = sizeof( MENUITEMINFOW ); menuItemInfo.fMask = MIIM_TYPE | MIIM_ID; menuItemInfo.fType = MFT_STRING; menuItemInfo.fState = MFS_ENABLED; if ( fEnabled ) { menuItemInfo.dwTypeData = MENUITEM_DISABLE; menuItemInfo.wID = IDI_DISABLE; } else { menuItemInfo.dwTypeData = MENUITEM_ENABLE; menuItemInfo.wID = IDI_ENABLE; } SetMenuItemInfoW( hBindingPathSubMenu, 0, TRUE, &menuItemInfo ); GetCursorPos( &pt ); ulSelection = (ULONG)TrackPopupMenu( hBindingPathSubMenu, TPM_RIGHTALIGN | TPM_BOTTOMALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwndOwner, NULL ); if ( ulSelection ) { // // Do the selected action. // HandleBindingPathOperation( hwndOwner, ulSelection, hItem, lParam ); } return; } // // Function: GetItemInfo // // Purpose: Returns information about an item. // // Arguments: // hwndTree [in] Window handle of the tree. // hItem [in] Item handle. // lParam [out] lParam // lpdwItemType [out] Type, binding path or network component. // fEnabled [out] TRUE if the binding path or component is enabled. // // Returns: TRUE on sucess. // // Notes: // BOOL GetItemInfo (HWND hwndTree, HTREEITEM hItem, LPARAM *lParam, LPDWORD lpdwItemType, BOOL *fEnabled) { TVITEMW tvItem; int iImage; BOOL fSuccess; fSuccess = FALSE; // // Get item's information. // ZeroMemory( &tvItem, sizeof(TVITEMW) ); tvItem.hItem = hItem; tvItem.mask = TVIF_PARAM | TVIF_IMAGE | TVIF_STATE; tvItem.stateMask = TVIS_OVERLAYMASK ; if ( TreeView_GetItem(hwndTree, &tvItem) ) { *lParam = tvItem.lParam; if ( SetupDiGetClassImageIndex(&ClassImageListData, &GUID_DEVCLASS_SYSTEM, &iImage) ) { // // Is it a binding path? // if ( tvItem.iImage == iImage ) { *lpdwItemType = ITEM_NET_BINDINGS; *fEnabled = !(TVIS_OVERLAYMASK & tvItem.state); fSuccess = TRUE; } else { // // Item is a network component. // if ( SetupDiGetClassImageIndex(&ClassImageListData, &GUID_DEVCLASS_NET, &iImage) ) { if ( tvItem.iImage == iImage ) { *lpdwItemType = ITEM_NET_ADAPTERS; } else { *lpdwItemType = ITEM_NET_COMPONENTS; } *fEnabled = !(TVIS_OVERLAYMASK & tvItem.state); fSuccess = TRUE; } else { ErrMsg( HRESULT_FROM_WIN32(GetLastError()), L"Couldn't load the images of network adapters." ); } } } else { ErrMsg( HRESULT_FROM_WIN32(GetLastError()), L"Couldn't load the images of system devices." ); } } return fSuccess; } // // Function: AddBindNameToTree // // Purpose: Adds an item representing the binding path. // // Arguments: // pncbp [in] Binding path to add. // hwndTree [in] Tree handle. // hParent [in] Parent item. // ulIndex [in] Index of the binding path. // // Returns: Handle of the item added on success, otherwise NULL. // // Notes: // HTREEITEM AddBindNameToTree (INetCfgBindingPath *pncbp, HWND hwndTree, HTREEITEM hParent, ULONG ulIndex) { WCHAR lpszBindName[40]; LPWSTR lpszPathToken; HTREEITEM hTreeItem; TV_INSERTSTRUCTW tvInsertStruc; HRESULT hr; hTreeItem = NULL; // // Store the path token as lParam. // hr = pncbp->GetPathToken( &lpszPathToken ); if ( hr == S_OK ) { swprintf( lpszBindName, L"Binding Path %d", ulIndex ); ZeroMemory( &tvInsertStruc, sizeof(TV_INSERTSTRUCTW) ); tvInsertStruc.hParent = hParent; tvInsertStruc.hInsertAfter = TVI_LAST; tvInsertStruc.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; tvInsertStruc.item.pszText = lpszBindName; tvInsertStruc.item.cchTextMax = wcslen( lpszBindName ) + sizeof(WCHAR); SetupDiGetClassImageIndex( &ClassImageListData, &GUID_DEVCLASS_SYSTEM, &tvInsertStruc.item.iImage ); tvInsertStruc.item.iSelectedImage = tvInsertStruc.item.iImage; tvInsertStruc.item.stateMask = TVIS_OVERLAYMASK; if ( pncbp->IsEnabled() == S_FALSE ) { tvInsertStruc.item.state = INDEXTOOVERLAYMASK( IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST + 1); } tvInsertStruc.item.lParam = (LPARAM)lpszPathToken; hTreeItem = TreeView_InsertItem( hwndTree, &tvInsertStruc ); if ( !hTreeItem ) { ErrMsg( hr, L"Couldn't add the binding path %d to the list." L" The binding path will not be shown.", ulIndex ); CoTaskMemFree( lpszPathToken ); } } else { ErrMsg( hr, L"Couldn't get the PathToken of the binding path %d." L" The binding path will not be shown.", ulIndex ); } return hTreeItem; } // // Function: AddToTree // // Purpose: Adds an item representing the network component. // // Arguments: // hwndTree [in] Tree handle. // hParent [in] Parent item. // pncc [in] Network component. // // Returns: Handle of the item added on success, otherwise NULL. // // Notes: // HTREEITEM AddToTree (HWND hwndTree, HTREEITEM hParent, INetCfgComponent *pncc) { LPWSTR lpszItemName; LPWSTR lpszId; GUID guidClass; BOOL fEnabled; ULONG ulStatus; HTREEITEM hTreeItem; TV_INSERTSTRUCTW tvInsertStruc; HRESULT hr; hTreeItem = NULL; hr = pncc->GetDisplayName( &lpszItemName ); if ( hr == S_OK ) { // // Get the inf id of the network component. We store it at lParam // and use it later to retrieve its interface pointer. // hr = pncc->GetId( &lpszId ); if ( hr == S_OK ) { // // If it is a network adapter then, find out if it enabled/disabled. // hr = pncc->GetClassGuid( &guidClass ); if ( hr == S_OK ) { if ( IsEqualGUID(guidClass, GUID_DEVCLASS_NET) ) { hr = pncc->GetDeviceStatus( &ulStatus ); fEnabled = ulStatus == 0; } else { fEnabled = TRUE; } } else { // // We can't get the status, so assume that it is disabled. // fEnabled = FALSE; } ZeroMemory( &tvInsertStruc, sizeof(TV_INSERTSTRUCTW) ); tvInsertStruc.hParent = hParent; tvInsertStruc.hInsertAfter = TVI_LAST; tvInsertStruc.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; tvInsertStruc.item.pszText = lpszItemName; tvInsertStruc.item.cchTextMax = wcslen( lpszItemName ) + sizeof(WCHAR); SetupDiGetClassImageIndex( &ClassImageListData, &guidClass, &tvInsertStruc.item.iImage ); tvInsertStruc.item.iSelectedImage = tvInsertStruc.item.iImage; tvInsertStruc.item.stateMask = TVIS_OVERLAYMASK; if ( fEnabled == FALSE ) { tvInsertStruc.item.state = INDEXTOOVERLAYMASK( IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST + 1); } tvInsertStruc.item.lParam = (LPARAM)lpszId; hTreeItem = TreeView_InsertItem( hwndTree, &tvInsertStruc ); if ( !hTreeItem ) { ErrMsg( hr, L"Failed to add %s to the list.", lpszItemName ); CoTaskMemFree( lpszId ); } } else { ErrMsg( hr, L"Couldn't get the inf id of %s." L" It will not be added to the list.", lpszItemName ); } CoTaskMemFree( lpszItemName ); } else { ErrMsg( hr, L"Couldn't get the display name of a network component." L" It will not be added to the list." ); } return hTreeItem; } // // Function: RefreshAll // // Purpose: Refreshes the main dialog box. // // Arguments: // hwndDlg [in] Dialog box handle. // // Returns: None. // // Notes: // VOID RefreshAll (HWND hwndDlg) { HWND hwndTypeList; INT iSelected; // // Find the selected network component type. // hwndTypeList = GetDlgItem( hwndDlg, IDL_COMPONENT_TYPES ); iSelected = (int)SendMessage( hwndTypeList, CB_GETCURSEL, 0, 0 ); if ( iSelected != CB_ERR ) { // // Before deleting the list in the tree, free the buffer // associated with each item. The buffer holds either the // INF Id or the pathtoken depending on whether it is a // network component or a binding path. // ReleaseMemory( GetDlgItem(hwndDlg, IDT_BINDINGS), TVI_ROOT ); TreeView_DeleteItem ( GetDlgItem(hwndDlg, IDT_BINDINGS), TVI_ROOT ); // // Repopulate the tree with the selected network compnent // type. // EnumNetBindings( GetDlgItem(hwndDlg, IDT_BINDINGS), (UINT)iSelected ); } return; } // // Function: RefreshItemState // // Purpose: Refreshes the specified item. // // Arguments: // hwndTree [in] Dialog box handle. // hItem [in] Item to refresh. // fEnable [in] TRUE if component is enabled. // // Returns: None. // // Notes: // VOID RefreshItemState (HWND hwndTree, HTREEITEM hItem, BOOL fEnable) { TVITEMW tvItem; ZeroMemory( &tvItem, sizeof(TVITEMW) ); tvItem.hItem = hItem; tvItem.mask = TVIF_STATE; tvItem.stateMask = TVIS_OVERLAYMASK; if ( fEnable ) tvItem.state = INDEXTOOVERLAYMASK( 0 ); else tvItem.state = INDEXTOOVERLAYMASK( IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST + 1); TreeView_SetItem( hwndTree, &tvItem ); return; } // // Function: RefreshBindings // // Purpose: Refreshes bindings of a specific component. // // Arguments: // hwndBindUnBindDlg [in] Dialog box handle. // lpszInfId [in] PnpID of the component whose bindings changed. // // Returns: None. // // Notes: // VOID RefreshBindings (HWND hwndBindUnBindDlg, LPWSTR lpszInfId) { INetCfg *pnc; INetCfgComponent *pncc; HWND hwndParent; HWND hwndTree; HTREEITEM hItem; HRESULT hr; hwndParent = GetParent( hwndBindUnBindDlg ); hwndTree = GetDlgItem( hwndParent, IDT_BINDINGS ); hItem = TreeView_GetSelection( hwndTree ); hr = HrGetINetCfg( FALSE, APP_NAME, &pnc, NULL ); if ( hr == S_OK ) { hr = pnc->FindComponent( lpszInfId, &pncc ); if ( hr == S_OK ) { // // Delete all the children. // ReleaseMemory( hwndTree, hItem ); DeleteChildren( hwndTree, hItem ); ListBindings( pncc, hwndTree, hItem ); ReleaseRef( pncc ); } HrReleaseINetCfg( pnc, FALSE ); } return; } // // Function: ReleaseMemory // // Purpose: Free memory associated with each item in the tree. // // Arguments: // hwndTree [in] Tree handle. // hTreeItem [in] Root item. // // Returns: None. // // Notes: // // Each node of the tree represents a network component or a binding path. // At each node, lParam points to an allocated buffer wherein we store the // inf id if it is a network component or pathtoken name if it is a binding // path. // // VOID ReleaseMemory (HWND hwndTree, HTREEITEM hTreeItem) { HTREEITEM hItemChild; TVITEMW tvItem; hItemChild = TreeView_GetChild( hwndTree, hTreeItem ); while ( hItemChild ) { ZeroMemory( &tvItem, sizeof(TVITEMW) ); tvItem.hItem = hItemChild; tvItem.mask = TVIF_PARAM; TreeView_GetItem( hwndTree, &tvItem ); // // It should never be NULL but just in case... // if ( tvItem.lParam ) { CoTaskMemFree( (LPVOID)tvItem.lParam ); } ReleaseMemory( hwndTree, hItemChild ); hItemChild = TreeView_GetNextSibling( hwndTree, hItemChild ); } return; } // // Function: DeleteChildren // // Purpose: Delete childen of a specific item. // // Arguments: // hwndTree [in] Tree handle. // hTreeItem [in] Parent item. // // Returns: None. // // Notes: // VOID DeleteChildren (HWND hwndTree, HTREEITEM hTreeItem) { HTREEITEM hItemChild; HTREEITEM hItemSibling; hItemChild = TreeView_GetChild( hwndTree, hTreeItem ); while ( hItemChild ) { DeleteChildren( hwndTree, hItemChild ); hItemSibling = TreeView_GetNextSibling( hwndTree, hItemChild ); TreeView_DeleteItem( hwndTree, hItemChild ); hItemChild = hItemSibling; } return; } // // Function: InsertItem // // Purpose: Insert text for each network component type. // // Arguments: // hwndTree [in] Tree handle. // uiType [in] Item type, protocol, client, service. // // Returns: Item handle on success, otherwise NULL. // // Notes: // HTREEITEM InsertItem (HWND hwndTree, UINT uiType) { TV_INSERTSTRUCTW tvInsertStruc; ZeroMemory( &tvInsertStruc, sizeof(TV_INSERTSTRUCTW) ); tvInsertStruc.hParent = TVI_ROOT; tvInsertStruc.hInsertAfter = TVI_LAST; tvInsertStruc.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; switch( uiType ) { case CLIENTS_SELECTED: tvInsertStruc.item.pszText = L"Client"; break; case SERVICES_SELECTED: tvInsertStruc.item.pszText = L"Service"; break; default: tvInsertStruc.item.pszText = L"Protocol"; break; } tvInsertStruc.item.cchTextMax = wcslen( tvInsertStruc.item.pszText ) + sizeof(WCHAR); SetupDiGetClassImageIndex( &ClassImageListData, pguidNetClass[uiType], &tvInsertStruc.item.iImage ); tvInsertStruc.item.iSelectedImage = tvInsertStruc.item.iImage; tvInsertStruc.item.lParam = (LPARAM)uiType; return TreeView_InsertItem( hwndTree, &tvInsertStruc ); } // // Function: UpdateComponentTypeList // // Purpose: Insert text for each network component type. // // Arguments: // hwndTypeList [in] ListView handle. // // Returns: TRUE on success. // // Notes: // BOOL UpdateComponentTypeList (HWND hwndTypeList) { UINT i; for (i=0; i < 3; ++i) { SendMessage( hwndTypeList, CB_ADDSTRING, (WPARAM)0, (LPARAM)lpszNetClass[i] ); } SendMessage( hwndTypeList, CB_SETCURSEL, (WPARAM)DEFAULT_COMPONENT_SELECTED, (LPARAM)0 ); return TRUE; } // // Function: ErrMsg // // Purpose: Insert text for each network component type. // // Arguments: // hr [in] Error code. // // Returns: None. // // Notes: // VOID ErrMsg (HRESULT hr, LPCWSTR lpFmt, ...) { LPWSTR lpSysMsg; WCHAR buf[400]; ULONG offset; va_list vArgList; if ( hr != 0 ) { swprintf( buf, L"Error %#lx: ", hr ); } else { buf[0] = 0; } offset = wcslen( buf ); va_start( vArgList, lpFmt ); vswprintf( buf+offset, lpFmt, vArgList ); va_end( vArgList ); if ( hr != 0 ) { FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpSysMsg, 0, NULL ); if ( lpSysMsg ) { offset = wcslen( buf ); swprintf( buf+offset, L"\n\nPossible cause:\n\n" ); offset = wcslen( buf ); wcscat( buf+offset, lpSysMsg ); LocalFree( (HLOCAL)lpSysMsg ); } MessageBoxW( NULL, buf, L"Error", MB_ICONERROR | MB_OK ); } else { MessageBoxW( NULL, buf, L"BindView", MB_ICONINFORMATION | MB_OK ); } return; }