//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997. // // File: O N C O M M A N D . C P P // // Contents: Command handlers for the context menus, etc. // // Notes: // // Author: jeffspr 4 Nov 1997 // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "foldinc.h" // Standard shell\folder includes #include "advcfg.h" #include "conprops.h" #include "foldres.h" #include "oncommand.h" #if DBG // Debug menu commands #include "oncommand_dbg.h" // #endif #include "shutil.h" #include "ncras.h" #include "traymsgs.h" #include #include #include #include "disconnect.h" #include "ncperms.h" #include "smcent.h" #include "cfutils.h" #include "HNetCfg.h" #include "..\lanui\lanui.h" #include "repair.h" #include "iconhandler.h" #include "wzcdlg.h" //---[ Externs ]-------------------------------------------------------------- extern HWND g_hwndTray; extern const WCHAR c_szNetShellDll[]; //---[ Constants ]------------------------------------------------------------ // Command-line for the control-panel applet. // static const WCHAR c_szRunDll32[] = L"rundll32.exe"; static const WCHAR c_szNetworkIdCmdLine[] = L"shell32.dll,Control_RunDLL sysdm.cpl,,1"; //---[ Local functions ]------------------------------------------------------ // None class CCommandHandlerParams { public: const PCONFOLDPIDLVEC* apidl; HWND hwndOwner; LPSHELLFOLDER psf; UINT_PTR nAdditionalParam; } ; HRESULT HrCommandHandlerThread( FOLDERONCOMMANDPROC pfnCommandHandler, IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; PCONFOLDPIDLVEC apidlCopy; // If there are pidls to copy, copy them // if (!apidl.empty()) { hr = HrCloneRgIDL(apidl, FALSE, TRUE, apidlCopy); } // If either there were no pidls, or the Clone succeeded, then we want to continue // if (SUCCEEDED(hr)) { PCONFOLDONCOMMANDPARAMS pcfocp = new CONFOLDONCOMMANDPARAMS; if (pcfocp) { pcfocp->pfnfocp = pfnCommandHandler; pcfocp->apidl = apidlCopy; pcfocp->hwndOwner = hwndOwner; pcfocp->psf = psf; pcfocp->hInstNetShell = NULL; // This should be Release'd in the thread called. // psf->AddRef(); // This will always succeed in retail, but will test the flag in debug // if (!FIsDebugFlagSet (dfidDisableShellThreading)) { // Run in a thread using the QueueUserWorkItem // HANDLE hthrd = NULL; HINSTANCE hInstNetShell = LoadLibrary(c_szNetShellDll); if (hInstNetShell) { pcfocp->hInstNetShell = hInstNetShell; DWORD dwThreadId; hthrd = CreateThread(NULL, STACK_SIZE_DEFAULT, (LPTHREAD_START_ROUTINE)FolderCommandHandlerThreadProc, (LPVOID)pcfocp, 0, &dwThreadId); } if (NULL != hthrd) { CloseHandle(hthrd); } else { pcfocp->hInstNetShell = NULL; FolderCommandHandlerThreadProc(pcfocp); } } else { // Run directly in this same thread // FolderCommandHandlerThreadProc((PVOID) pcfocp); } } else { hr = E_OUTOFMEMORY; } } // Don't release the psf here. This should have been taken care of by the called ThreadProc // return hr; } DWORD WINAPI FolderCommandHandlerThreadProc(LPVOID lpParam) { HRESULT hr = S_OK; PCONFOLDONCOMMANDPARAMS pcfocp = (PCONFOLDONCOMMANDPARAMS) lpParam; BOOL fCoInited = FALSE; IUnknown * punkExplorerProcess = NULL; Assert(pcfocp); SHGetInstanceExplorer(&punkExplorerProcess); hr = CoInitializeEx (NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED); if (SUCCEEDED(hr)) { // We don't care if this is S_FALSE or not, since we'll soon // overwrite the hr. If it's already initialized, great... fCoInited = TRUE; // Call the specific handler // hr = pcfocp->pfnfocp( pcfocp->apidl, pcfocp->hwndOwner, pcfocp->psf); } // Remove the ref that we have on this object. The thread handler would have addref'd // this before queueing our action // if (pcfocp->psf) { ReleaseObj(pcfocp->psf); } // Remove this object. We're responsible for this now. // HINSTANCE hInstNetShell = pcfocp->hInstNetShell; pcfocp->hInstNetShell = NULL; delete pcfocp; if (fCoInited) { CoUninitialize(); } ::ReleaseObj(punkExplorerProcess); if (hInstNetShell) FreeLibraryAndExitThread(hInstNetShell, hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrCommandHomeNetWizard // // Purpose: Command handler to start the home networking wizard // // Arguments: none // // Returns: S_OK if succeeded // E_FAIL otherwise // // Author: deonb 10 Feb 2001 // // Notes: // HRESULT HrCommandHomeNetWizard() { // ShellExecute returns <32 if an error if (ShellExecute(NULL, NULL, L"rundll32.exe", L"hnetwiz.dll,HomeNetWizardRunDll", NULL, SW_SHOWNORMAL) > reinterpret_cast(32)) { return S_OK; } else { return E_FAIL; } } // // // LONG TotalValidSelectedConnectionsForBridge( IN const PCONFOLDPIDLVEC& apidlSelected ) { int nTotalValidCandidateForBridge = 0; // // Loop through each of the selected objects // for ( PCONFOLDPIDLVEC::const_iterator iterObjectLoop = apidlSelected.begin(); iterObjectLoop != apidlSelected.end(); iterObjectLoop++ ) { // Validate the pidls // const PCONFOLDPIDL& pcfp = *iterObjectLoop; if ( !pcfp.empty() ) { // // needs to be a LAN Adapter and NOT (Firewalled/Shared or Bridge) // if ( (NCM_LAN == pcfp->ncm) ) if ( !( (NCCF_BRIDGED|NCCF_FIREWALLED|NCCF_SHARED) & pcfp->dwCharacteristics ) ) { // // Ok we have a winner it's a nice clean adapter // nTotalValidCandidateForBridge ++; } } } return nTotalValidCandidateForBridge; } //+--------------------------------------------------------------------------- // // Function: HrCommandNetworkDiagnostics // // Purpose: Command handler to start the Network Diagnostics page // // Arguments: none // // Returns: S_OK if succeeded // E_FAIL otherwise // // Author: deonb 10 Feb 2001 // // Notes: // HRESULT HrCommandNetworkDiagnostics() { // ShellExecute returns <32 if an error if (ShellExecute(NULL, NULL, L"hcp://system/netdiag/dglogs.htm", L"", NULL, SW_SHOWNORMAL) > reinterpret_cast(32)) { return S_OK; } else { return E_FAIL; } } //+--------------------------------------------------------------------------- // // Function: HrCommandNetworkTroubleShoot // // Purpose: Command handler to start the Network Troubleshooter page // // Arguments: none // // Returns: S_OK if succeeded // E_FAIL otherwise // // Author: deonb 4 April 2001 // // Notes: // HRESULT HrCommandNetworkTroubleShoot() { // ShellExecute returns <32 if an error if (ShellExecute(NULL, NULL, L"hcp://system/panels/Topics.htm?path=TopLevelBucket_4/Fixing_a_problem/Home_Networking_and_network_problems", L"", NULL, SW_SHOWNORMAL) > reinterpret_cast(32)) { return S_OK; } else { return E_FAIL; } } //+--------------------------------------------------------------------------- // // Function: HrFolderCommandHandler // // Purpose: Command handler switch -- all commands come through this // point. // // Arguments: // uiCommand [in] The command-id that's been invoked. // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // lpici [in] Command context info // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 11 Feb 1998 // // Notes: // HRESULT HrFolderCommandHandler( UINT uiCommand, IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPCMINVOKECOMMANDINFO lpici, LPSHELLFOLDER psf) { HRESULT hr = S_OK; CWaitCursor wc; // Bring up wait cursor now. Remove when we go out of scope. // refresh all permission so subsequent calls can use cached value RefreshAllPermission(); switch(uiCommand) { case CMIDM_ARRANGE_BY_NAME: ShellFolderView_ReArrange(hwndOwner, ICOL_NAME); break; case CMIDM_ARRANGE_BY_TYPE: ShellFolderView_ReArrange(hwndOwner, ICOL_TYPE); break; case CMIDM_ARRANGE_BY_STATUS: ShellFolderView_ReArrange(hwndOwner, ICOL_STATUS); break; case CMIDM_ARRANGE_BY_OWNER: ShellFolderView_ReArrange(hwndOwner, ICOL_OWNER); break; case CMIDM_ARRANGE_BY_PHONEORHOSTADDRESS: ShellFolderView_ReArrange(hwndOwner, ICOL_PHONEORHOSTADDRESS); break; case CMIDM_ARRANGE_BY_DEVICE_NAME: ShellFolderView_ReArrange(hwndOwner, ICOL_DEVICE_NAME); break; case CMIDM_NEW_CONNECTION: hr = HrCommandHandlerThread(HrOnCommandNewConnection, apidl, hwndOwner, psf); break; case CMIDM_HOMENET_WIZARD: hr = HrCommandHomeNetWizard(); break; case CMIDM_NET_DIAGNOSTICS: hr = HrCommandNetworkDiagnostics(); break; case CMIDM_NET_TROUBLESHOOT: hr = HrCommandNetworkTroubleShoot(); break; case CMIDM_CONNECT: case CMIDM_ENABLE: hr = HrCommandHandlerThread(HrOnCommandConnect, apidl, hwndOwner, psf); break; case CMIDM_DISCONNECT: case CMIDM_DISABLE: hr = HrCommandHandlerThread(HrOnCommandDisconnect, apidl, hwndOwner, psf); break; case CMIDM_STATUS: // the status monitor is already on its own thread // hr = HrOnCommandStatus(apidl, hwndOwner, psf); break; case CMIDM_FIX: hr = HrCommandHandlerThread(HrOnCommandFix, apidl, hwndOwner, psf); break; case CMIDM_CREATE_SHORTCUT: hr = HrCommandHandlerThread(HrOnCommandCreateShortcut, apidl, hwndOwner, psf); break; case CMIDM_DELETE: hr = HrCommandHandlerThread(HrOnCommandDelete, apidl, hwndOwner, psf); break; case CMIDM_PROPERTIES: hr = HrCommandHandlerThread(HrOnCommandProperties, apidl, hwndOwner, psf); break; case CMIDM_WZCPROPERTIES: hr = HrCommandHandlerThread(HrOnCommandWZCProperties, apidl, hwndOwner, psf); break; case CMIDM_WZCDLG_SHOW: hr = HrCommandHandlerThread(HrOnCommandWZCDlgShow, apidl, hwndOwner, psf); break; case CMIDM_CREATE_COPY: hr = HrOnCommandCreateCopy(apidl, hwndOwner, psf); break; case CMIDM_CONMENU_ADVANCED_CONFIG: hr = HrCommandHandlerThread(HrOnCommandAdvancedConfig, apidl, hwndOwner, psf); break; case CMIDM_SET_DEFAULT: hr = HrOnCommandSetDefault(apidl, hwndOwner, psf); break; case CMIDM_UNSET_DEFAULT: hr = HrOnCommandUnsetDefault(apidl, hwndOwner, psf); break; case CMIDM_CREATE_BRIDGE: case CMIDM_CONMENU_CREATE_BRIDGE: if ( TotalValidSelectedConnectionsForBridge(apidl) < 2 ) { // tell users that he/she needs select 2 or more valid connections in order to acomplish this NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_OBJECT_TYPE_BRIDGE, IDS_BRIDGE_EDUCATION, MB_ICONEXCLAMATION | MB_OK ); } else HrOnCommandBridgeAddConnections(apidl, hwndOwner, psf); break; case CMIDM_ADD_TO_BRIDGE: HrOnCommandBridgeAddConnections(apidl, hwndOwner, psf); break; case CMIDM_REMOVE_FROM_BRIDGE: HrOnCommandBridgeRemoveConnections(apidl, hwndOwner, psf, CMIDM_REMOVE_FROM_BRIDGE); break; case CMIDM_CONMENU_NETWORK_ID: hr = HrOnCommandNetworkId(apidl, hwndOwner, psf); break; case CMIDM_CONMENU_OPTIONALCOMPONENTS: hr = HrOnCommandOptionalComponents(apidl, hwndOwner, psf); break; case CMIDM_CONMENU_DIALUP_PREFS: hr = HrCommandHandlerThread(HrOnCommandDialupPrefs, apidl, hwndOwner, psf); break; case CMIDM_CONMENU_OPERATOR_ASSIST: hr = HrOnCommandOperatorAssist(apidl, hwndOwner, psf); break; #if DBG case CMIDM_DEBUG_TRAY: hr = HrOnCommandDebugTray(apidl, hwndOwner, psf); break; case CMIDM_DEBUG_TRACING: hr = HrOnCommandDebugTracing(apidl, hwndOwner, psf); break; case CMIDM_DEBUG_NOTIFYADD: hr = HrOnCommandDebugNotifyAdd(apidl, hwndOwner, psf); break; case CMIDM_DEBUG_NOTIFYREMOVE: hr = HrOnCommandDebugNotifyRemove(apidl, hwndOwner, psf); break; case CMIDM_DEBUG_NOTIFYTEST: hr = HrOnCommandDebugNotifyTest(apidl, hwndOwner, psf); break; case CMIDM_DEBUG_REFRESH: hr = HrOnCommandDebugRefresh(apidl, hwndOwner, psf); break; case CMIDM_DEBUG_REFRESHNOFLUSH: hr = HrOnCommandDebugRefreshNoFlush(apidl, hwndOwner, psf); break; case CMIDM_DEBUG_REFRESHSELECTED: hr = HrCommandHandlerThread(HrOnCommandDebugRefreshSelected, apidl, hwndOwner, psf); break; case CMIDM_DEBUG_REMOVETRAYICONS: hr = HrCommandHandlerThread(HrOnCommandDebugRemoveTrayIcons, apidl, hwndOwner, psf); break; #endif default: #if DBG char sz[128]; ZeroMemory(sz, 128); sprintf(sz, "Unknown command (%d) in HrFolderCommandHandler", uiCommand); TraceHr(ttidError, FAL, hr, FALSE, sz); #endif hr = E_INVALIDARG; } TraceHr(ttidError, FAL, hr, FALSE, "HrFolderCommandHandler"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandCreateCopy // // Purpose: Command handler for the CMIDM_CREATE_COPY command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // psf [in] The shell folder interface // // Returns: // // Author: jeffspr 31 Jan 1998 // // Notes: // HRESULT HrOnCommandCreateCopy( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; INetConnection * pNetCon = NULL; INetConnection * pNetConDupe = NULL; CConnectionFolder * pcf = static_cast(psf); NETCFG_TRY PCONFOLDPIDLFOLDER pidlFolder; if (pcf) { pidlFolder = pcf->PidlGetFolderRoot(); } PCONFOLDPIDL pidlConnection; PCONFOLDPIDLVEC::const_iterator iterLoop; for (iterLoop = apidl.begin(); iterLoop != apidl.end() ; iterLoop++) { // Get the INetConnection object from the persist data // hr = HrNetConFromPidl(*iterLoop, &pNetCon); if (SUCCEEDED(hr)) { CONFOLDENTRY ccfe; Assert(pNetCon); hr = iterLoop->ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { if (ccfe.GetCharacteristics() & NCCF_ALLOW_DUPLICATION) { PWSTR pszDupeName = NULL; hr = g_ccl.HrSuggestNameForDuplicate(ccfe.GetName(), &pszDupeName); if (SUCCEEDED(hr)) { Assert(pszDupeName); // Duplicate the connection // hr = pNetCon->Duplicate(pszDupeName, &pNetConDupe); if (SUCCEEDED(hr)) { Assert(pNetConDupe); if (pNetConDupe) { hr = g_ccl.HrInsertFromNetCon(pNetConDupe, pidlConnection); if (SUCCEEDED(hr)) { GenerateEvent(SHCNE_CREATE, pidlFolder, pidlConnection, NULL); pidlConnection.Clear(); } ReleaseObj(pNetConDupe); pNetConDupe = NULL; } } delete pszDupeName; } } else { AssertSz(ccfe.GetCharacteristics() & NCCF_ALLOW_DUPLICATION, "What menu supported duplicating this connection?"); } } ReleaseObj(pNetCon); pNetCon = NULL; } } NETCFG_CATCH(hr) TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandCreateCopy"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandProperties // // Purpose: Command handler for the CMIDM_PROPERTIES command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 4 Nov 1997 // // Notes: // HRESULT HrOnCommandProperties( IN const PCONFOLDPIDLVEC& apidl, IN HWND hwndOwner, LPSHELLFOLDER psf) { INT cch; HRESULT hr = S_OK; HANDLE hMutex = NULL; INetConnection * pNetCon = NULL; WCHAR szConnectionGuid [c_cchGuidWithTerm]; // Just skip out of here if no pidl was supplied if (apidl.empty()) { return S_OK; } // We can only deal with a single connection. If we have // multiple, then just use the first one. // const PCONFOLDPIDL& pcfp = apidl[0]; if (pcfp.empty()) { hr = E_INVALIDARG; goto Error; } // If this is an individual incoming connection - disallow this: if ( (NCCF_INCOMING_ONLY & pcfp->dwCharacteristics) && (NCM_NONE != pcfp->ncm) ) { hr = E_UNEXPECTED; goto Error; } // If this is a LAN connection and the user doesn't have rights // then disallow properties // if ((IsMediaLocalType(pcfp->ncm)) && !FHasPermission(NCPERM_LanProperties)) { hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); goto Error; } // If this is a RAS connection and the user doesn't have rights // then disallow properties // if (IsMediaRASType(pcfp->ncm)) { BOOL fAllowProperties = (TRUE == ((pcfp->dwCharacteristics & NCCF_ALL_USERS) ? (FHasPermission(NCPERM_RasAllUserProperties)) : (FHasPermission(NCPERM_RasMyProperties)))); if (!fAllowProperties) { hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); goto Error; } } hr = HrNetConFromPidl(apidl[0], &pNetCon); if (FAILED(hr)) { goto Error; } // Aquire a lock on this connection object // cch = StringFromGUID2 (pcfp->guidId, szConnectionGuid, c_cchGuidWithTerm); Assert (c_cchGuidWithTerm == cch); hMutex = CreateMutex(NULL, TRUE, szConnectionGuid); if ((NULL == hMutex) || (ERROR_ALREADY_EXISTS == GetLastError())) { // if the mutex already exists try to find the connection window // if (ERROR_ALREADY_EXISTS == GetLastError()) { Assert(pNetCon); ActivatePropertyDialog(pNetCon); Assert(S_OK == hr); // Don't let the error reporting below display the error. // We want the user to acknowledge the message box above // then we'll be nice an bring the property page to the // foreground. goto Error; } hr = HrFromLastWin32Error(); goto Error; } Assert(SUCCEEDED(hr)); // Bring up the connection Properties UI. // hr = HrRaiseConnectionPropertiesInternal( NULL, // ISSUE: Going modal -- hwndOwner ? hwndOwner : GetDesktopWindow(), 0, // First page pNetCon); Error: if (FAILED(hr)) { UINT ids = 0; switch(hr) { case E_UNEXPECTED: ids = IDS_CONFOLD_PROPERTIES_ON_RASSERVERINSTEAD; break; case HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED): ids = IDS_CONFOLD_PROPERTIES_NOACCESS; break; case HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY): ids = IDS_CONFOLD_OUTOFMEMORY; break; default: ids = IDS_CONFOLD_UNEXPECTED_ERROR; break; } NcMsgBox(_Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, ids, MB_ICONEXCLAMATION | MB_OK); } if (hMutex) { ReleaseMutex(hMutex); CloseHandle(hMutex); } ReleaseObj(pNetCon); TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandProperties"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandWZCProperties // // Purpose: Command handler for the CMIDM_WZCPROPERTIES command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: deonb 5 Apr 2001 // // Notes: // HRESULT HrOnCommandWZCProperties( IN const PCONFOLDPIDLVEC& apidl, IN HWND hwndOwner, LPSHELLFOLDER psf) { INT cch; HRESULT hr = S_OK; HANDLE hMutex = NULL; INetConnection * pNetCon = NULL; WCHAR szConnectionGuid [c_cchGuidWithTerm]; // Just skip out of here if no pidl was supplied if (apidl.empty()) { return S_OK; } // We can only deal with a single connection. If we have // multiple, then just use the first one. // const PCONFOLDPIDL& pcfp = apidl[0]; if (pcfp.empty()) { hr = E_INVALIDARG; goto Error; } // If this is a LAN connection and the user doesn't have rights // then disallow properties // if ((IsMediaLocalType(pcfp->ncm)) && !FHasPermission(NCPERM_LanProperties)) { hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); goto Error; } // If this is a RAS connection and the user doesn't have rights // then disallow properties // if (IsMediaRASType(pcfp->ncm)) { BOOL fAllowProperties = (TRUE == ((pcfp->dwCharacteristics & NCCF_ALL_USERS) ? (FHasPermission(NCPERM_RasAllUserProperties)) : (FHasPermission(NCPERM_RasMyProperties)))); if (!fAllowProperties) { hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); goto Error; } } hr = HrNetConFromPidl(apidl[0], &pNetCon); if (FAILED(hr)) { goto Error; } // Aquire a lock on this connection object // cch = StringFromGUID2 (pcfp->guidId, szConnectionGuid, c_cchGuidWithTerm); Assert (c_cchGuidWithTerm == cch); hMutex = CreateMutex(NULL, TRUE, szConnectionGuid); if ((NULL == hMutex) || (ERROR_ALREADY_EXISTS == GetLastError())) { // if the mutex already exists try to find the connection window // if (ERROR_ALREADY_EXISTS == GetLastError()) { Assert(pNetCon); ActivatePropertyDialog(pNetCon); Assert(S_OK == hr); // Don't let the error reporting below display the error. // We want the user to acknowledge the message box above // then we'll be nice an bring the property page to the // foreground. goto Error; } hr = HrFromLastWin32Error(); goto Error; } Assert(SUCCEEDED(hr)); // Bring up the connection Properties UI. // hr = HrRaiseConnectionPropertiesInternal( NULL, // ISSUE: Going modal -- hwndOwner ? hwndOwner : GetDesktopWindow(), 1, // Second page pNetCon); Error: if (FAILED(hr)) { UINT ids = 0; switch(hr) { case HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED): ids = IDS_CONFOLD_PROPERTIES_NOACCESS; break; case HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY): ids = IDS_CONFOLD_OUTOFMEMORY; break; default: ids = IDS_CONFOLD_UNEXPECTED_ERROR; break; } NcMsgBox(_Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, ids, MB_ICONEXCLAMATION | MB_OK); } if (hMutex) { ReleaseMutex(hMutex); CloseHandle(hMutex); } ReleaseObj(pNetCon); TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandProperties"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandWZCDlgShow // // Purpose: Command handler for the CMIDM_WZCDLG_SHOW command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: deonb 15 May 2001 // // Notes: // #define WZCDLG_FAILED 0x00010001 // 802.11 automatic configuration failed HRESULT HrOnCommandWZCDlgShow( IN const PCONFOLDPIDLVEC& apidl, IN HWND hwndOwner, LPSHELLFOLDER psf) { INT cch; HRESULT hr = S_OK; // Just skip out of here if no pidl was supplied if (apidl.empty()) { return S_OK; } // We can only deal with a single connection. If we have // multiple, then just use the first one. // const PCONFOLDPIDL& pcfp = apidl[0]; if (!pcfp.empty()) { WZCDLG_DATA wzcDlgData = {0}; wzcDlgData.dwCode = WZCDLG_FAILED; wzcDlgData.lParam = 1; BSTR szCookie = SysAllocStringByteLen(reinterpret_cast(&wzcDlgData), sizeof(wzcDlgData)); BSTR szName = SysAllocString(pcfp->PszGetNamePointer()); if (szCookie && szName) { GUID gdGuid = pcfp->guidId; hr = WZCOnBalloonClick(&gdGuid, szName, szCookie); } else { hr = E_OUTOFMEMORY; } SysFreeString(szName); SysFreeString(szCookie); } else { hr = E_INVALIDARG; } return hr; } //+--------------------------------------------------------------------------- // // Function: HrRaiseConnectionProperties // // Purpose: Public function for bringing up the propsheet page UI for // the passed in connection // // Arguments: // hwnd [in] Owner hwnd // pconn [in] Connection pointer passed in from the shell // // Returns: // // Author: scottbri 3 Nov 1998 // // Notes: Needs to convert the INetConnection * below into suitable // parameters for a call to HrOnCommandProperties above. // HRESULT HrRaiseConnectionProperties(HWND hwnd, INetConnection * pConn) { HRESULT hr = S_OK; PCONFOLDPIDL pidl; PCONFOLDPIDLFOLDER pidlFolder; LPSHELLFOLDER psfConnections = NULL; if (NULL == pConn) { hr = E_INVALIDARG; goto Error; } // Create a pidl for the connection // hr = HrCreateConFoldPidl(WIZARD_NOT_WIZARD, pConn, pidl); if (SUCCEEDED(hr)) { // Get the pidl for the Connections Folder // hr = HrGetConnectionsFolderPidl(pidlFolder); if (SUCCEEDED(hr)) { // Get the Connections Folder object // hr = HrGetConnectionsIShellFolder(pidlFolder, &psfConnections); if (SUCCEEDED(hr)) { PCONFOLDPIDLVEC vecPidls; vecPidls.push_back(pidl); hr = HrOnCommandProperties(vecPidls, hwnd, psfConnections); ReleaseObj(psfConnections); } } } Error: TraceHr(ttidError, FAL, hr, FALSE, "HrRaiseConnectionProperties"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandConnectInternal // // Purpose: The guts of the Connect code. This is called both from // HrOnCommandConnect and from HrOnCommandNewConnection, since // that now connects after creating the new connection // // Arguments: // pNetCon [in] INetConnection * of the connection to activate // hwndOwner [in] Our parent hwnd // pcfp [in] Our pidl structure // psf [in] Shell Folder // // Returns: // // Author: jeffspr 10 Jun 1998 // // Notes: // HRESULT HrOnCommandConnectInternal( INetConnection * pNetCon, HWND hwndOwner, const PCONFOLDPIDL& pcfp, LPSHELLFOLDER psf) { HRESULT hr = S_OK; CConnectionFolder * pcf = static_cast(psf); NETCFG_TRY PCONFOLDPIDLFOLDER pidlFolder; if (pcf) { pidlFolder = pcf->PidlGetFolderRoot(); } BOOL fActivating = FALSE; // Use a separate var so we can keep track of the result of the connect // and the result of the get_Status. // HRESULT hrConnect = S_OK; Assert(pNetCon); Assert(psf); // Get current activation state // CONFOLDENTRY cfEmpty; (void) HrCheckForActivation(pcfp, cfEmpty, &fActivating); // Check for rights to connect // if (((IsMediaLocalType(pcfp->ncm)) && !FHasPermission(NCPERM_LanConnect)) || ((IsMediaRASType(pcfp->ncm)) && !FHasPermission(NCPERM_RasConnect))) { (void) NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, IDS_CONFOLD_CONNECT_NOACCESS, MB_OK | MB_ICONEXCLAMATION); } // Drop out of this call unless we're currently disconnected. // else if (pcfp->ncs == NCS_DISCONNECTED && !fActivating) { // Ignore the return code. Failing to set this flag shouldn't keep // us from attempting to connect. // (void) HrSetActivationFlag(pcfp, cfEmpty, TRUE); // Get the INetConnectionConnectUi interface and make the connection // Get the hr (for debugging), but we want to update the status // of the connection even if the connect failed // hrConnect = HrConnectOrDisconnectNetConObject( // It's OK if the hwnd is NULL. We don't want to go modal // on the desktop. NULL, // FIXED -- Was going modal with hwndOwner ? hwndOwner : GetDesktopWindow(), pNetCon, CD_CONNECT); // Even on failure, we want to continue, because we might find that // the device is now listed as unavailable. On cancel (S_FALSE), we // don't have that concern. // if (S_FALSE != hrConnect) { // Even on failure, we want to continue, because we might find that // the device is now listed as unavailable. if (FAILED(hrConnect)) { TraceTag(ttidShellFolder, "HrOnCommandConnect: Connect failed, 0x%08x", hrConnect); } #if 0 // (JEFFSPR) - 11/20/98 turning this on until the notify COM failures are worked out. // Now taken care of by the notification engine. // // Get the new status from the connection // NETCON_PROPERTIES * pProps; hr = pNetCon->GetProperties(&pProps); if (SUCCEEDED(hr)) { // This won't necessarily be connected -- we used to assert here, but it's // actually possible for the connection to go dead between when we connect // and when we ask for the status. // hr = HrUpdateConnectionStatus(pcfp, pProps->Status, pidlFolder, TRUE, pProps->dwCharacter); FreeNetconProperties(pProps); } #endif } else { // hrConnect is S_FALSE. Pass that on. // hr = hrConnect; } // Set us as "not in the process of activating" // hr = HrSetActivationFlag(pcfp, cfEmpty, FALSE); } else { if ((IsMediaRASType(pcfp->ncm)) && (pcfp->ncm != NCM_NONE)) { // For non-LAN connections, attempt to bring the RAS dialer UI // into focus instead of putting up an error message HWND hwndDialer; LPWSTR pszTitle; NETCON_PROPERTIES * pProps; hr = pNetCon->GetProperties(&pProps); if (SUCCEEDED(hr)) { DwFormatStringWithLocalAlloc(SzLoadIds(IDS_CONFOLD_RAS_DIALER_TITLE_FMT), &pszTitle, pProps->pszwName); hwndDialer = FindWindowEx(NULL, NULL, L"#32770", pszTitle); if (hwndDialer) { SetForegroundWindow(hwndDialer); } FreeNetconProperties(pProps); MemFree(pszTitle); } } else if (fActivating) { (void) NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, IDS_CONFOLD_CONNECT_IN_PROGRESS, MB_OK | MB_ICONEXCLAMATION); } } NETCFG_CATCH(hr) TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandConnectInternal"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandFixInternal // // Purpose: handle the fix and bring up the progress dialog // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // HRESULT HrOnCommandFixInternal( const CONFOLDENTRY& ccfe, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; INetConnection * pNetCon = NULL; CConnectionFolder * pcf = static_cast(psf); Assert(!ccfe.empty()); NETCON_MEDIATYPE ncmType = ccfe.GetNetConMediaType(); //fix is only avalable for LAN and bridge connections if (NCM_LAN != ncmType && NCM_BRIDGE != ncmType) { return S_FALSE; } hr = ccfe.HrGetNetCon(IID_INetConnection, reinterpret_cast(&pNetCon)); if (SUCCEEDED(hr)) { NETCON_PROPERTIES* pProps; hr = pNetCon->GetProperties(&pProps); if (SUCCEEDED(hr)) { tstring strMessage = L""; CLanConnectionUiDlg dlg; HWND hwndDlg; //bring up the dialog to tell the user we're doing the fix dlg.SetConnection(pNetCon); hwndDlg = dlg.Create(hwndOwner); PCWSTR szw = SzLoadIds(IDS_FIX_REPAIRING); SetDlgItemText(hwndDlg, IDC_TXT_Caption, szw); //do the fix hr = HrTryToFix(pProps->guidId, strMessage); FreeNetconProperties(pProps); if (NULL != hwndDlg) { DestroyWindow(hwndDlg); } //tell users the results NcMsgBox(_Module.GetResourceInstance(), NULL, IDS_FIX_CAPTION, IDS_FIX_MESSAGE, MB_OK | MB_TOPMOST, strMessage.c_str()); } ReleaseObj(pNetCon); } TraceHr(ttidShellFolder, FAL, hr, (S_FALSE == hr), "HrOnCommandFixInternal"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandFix // // Purpose: Command handler for the CMIDM_FIX command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // HRESULT HrOnCommandFix( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; CONFOLDENTRY ccfe; if (!apidl.empty()) { hr = apidl[0].ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL)) { TraceTag(ttidError, "Could not set priority for Repair thread"); } // We don't care if whether the fix succeeds or not // if it fails, there will be a pop-up saying that HrOnCommandFixInternal(ccfe, hwndOwner, psf); } } TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandFix"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandConnect // // Purpose: Command handler for the CMIDM_CONNECT or CMIDM_ENABLE command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 12 Nov 1997 // // Notes: // HRESULT HrOnCommandConnect( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; INetConnection * pNetCon = NULL; NETCFG_TRY if (apidl.size() == 1) { PCONFOLDPIDL pcfp = apidl[0]; if (!pcfp.empty()) { // Get the cached pidl. If it's found, then use the copy. If not // then use whatever info we have (but this might be outdated) // PCONFOLDPIDL pcfpCopy; hr = g_ccl.HrGetCachedPidlCopyFromPidl(apidl[0], pcfpCopy); if (S_OK == hr) { pcfp.Swop(pcfpCopy); // pcfp = pcfpCopy; } else { TraceHr(ttidShellFolder, FAL, hr, FALSE, "Cached pidl not retrievable in HrOnCommandConnect"); } // Make sure that this connection is valid for connection (not a wizrd, // and not already connected. If so, then connect. // if ( (WIZARD_NOT_WIZARD == pcfp->wizWizard) && !(fIsConnectedStatus(pcfp->ncs)) ) { // Ignore this entry if we're getting a connect verb on an incoming connections // object // if (pcfp->ncm != NCM_NONE && (!(pcfp->dwCharacteristics & NCCF_INCOMING_ONLY))) { // Get the INetConnection object from the persist data // hr = HrNetConFromPidl(apidl[0], &pNetCon); if (SUCCEEDED(hr)) { hr = HrOnCommandConnectInternal(pNetCon, hwndOwner, pcfp, psf); ReleaseObj(pNetCon); } } } } // else if (FIsConFoldPidl98(apidl[0]) && FALSE ) // { // // ISSUE - FIsConFoldPidl98 doesn't give ua a wizWizard anymore! Used to be: // // FIsConFoldPidl98(apidl[0], &fIsWizard) && !fIsWizard) // // // raise an error that the connection is not found // // // NcMsgBox(_Module.GetResourceInstance(), NULL, // IDS_CONFOLD_WARNING_CAPTION, // IDS_CONFOLD_NO_CONNECTION, // MB_ICONEXCLAMATION | MB_OK); // } } NETCFG_CATCH(hr) TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandConnect"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandDisconnectInternal // // Purpose: Internal command handler for the CMIDM_DISCONNECT or CMIDM_DISABLE command. // This function is callable by the tray, which doesn't have // the data in pidls, but rather has the actual data that we're // concerned with. HrOnCommandDisconnect retrieves this data // and passes on the call to this function // // Arguments: // ccfe [in] Our ConFoldEntry (our connection data) // hwndOwner [in] Our parent hwnd // // Returns: // // Author: jeffspr 20 Mar 1998 // // Notes: // HRESULT HrOnCommandDisconnectInternal( const CONFOLDENTRY& ccfe, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; INetConnection * pNetCon = NULL; CConnectionFolder * pcf = static_cast(psf); Assert(!ccfe.empty()); // Check for rights to disconnect // if (((IsMediaLocalType(ccfe.GetNetConMediaType())) && !FHasPermission(NCPERM_LanConnect)) || ((IsMediaRASType(ccfe.GetNetConMediaType())) && !FHasPermission(NCPERM_RasConnect))) { (void) NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, IDS_CONFOLD_DISCONNECT_NOACCESS, MB_OK | MB_ICONEXCLAMATION); } else { PromptForSyncIfNeeded(ccfe, hwndOwner); { CWaitCursor wc; // Bring up wait cursor now. Remove when we go out of scope. // Get the INetConnection object from the persist data // hr = ccfe.HrGetNetCon(IID_INetConnection, reinterpret_cast(&pNetCon)); if (SUCCEEDED(hr)) { Assert(pNetCon); hr = HrConnectOrDisconnectNetConObject ( hwndOwner, pNetCon, CD_DISCONNECT); ReleaseObj(pNetCon); } } } TraceHr(ttidShellFolder, FAL, hr, (S_FALSE == hr), "HrOnCommandDisconnectInternal"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandDisconnect // // Purpose: Command handler for the CMIDM_DISCONNECT or CMIDM_DISABLE command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 12 Nov 1997 // // Notes: We only act on a single entry in this function // HRESULT HrOnCommandDisconnect( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; CONFOLDENTRY ccfe; if (!apidl.empty()) { hr = apidl[0].ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { hr = HrOnCommandDisconnectInternal(ccfe, hwndOwner, psf); // Normalize the return code. We don't care if whether the connection // was actually disconnected or not (if canceled, it would have \ // returned S_FALSE; // if (SUCCEEDED(hr)) { hr = S_OK; } } } TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandDisconnect"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandStatusInternal // // Purpose: Internal command handler for the CMIDM_STATUS command. // This function is callable by the tray, which doesn't have // the data in pidls, but rather has the actual data that we're // concerned with. HrOnCommandStatus retrieves this data // and passes on the call to this function // // Arguments: // ccfe [in] ConFoldEntry for the connection in question // fCreateEngine [in] Whether a status engine should be created if not exist // // Returns: // // Author: jeffspr 20 Mar 1998 // // Notes: // HRESULT HrOnCommandStatusInternal( const CONFOLDENTRY& ccfe, BOOL fCreateEngine) { HRESULT hr = S_OK; Assert(!ccfe.empty()); // see if we are in safe mode with networking int iRet = GetSystemMetrics(SM_CLEANBOOT); if (!iRet) { // normal boot Assert(g_hwndTray); // The permissions check will be done in the tray message processing. // PostMessage(g_hwndTray, MYWM_OPENSTATUS, (WPARAM) ccfe.TearOffItemIdList(), (LPARAM) fCreateEngine); } else if (2 == iRet) { // safemode with networking, statmon is not tied to tray icon if (FHasPermission(NCPERM_Statistics)) { INetStatisticsEngine* pnseNew; hr = HrGetStatisticsEngineForEntry(ccfe, &pnseNew, TRUE); if (SUCCEEDED(hr)) { hr = pnseNew->ShowStatusMonitor(); ReleaseObj(pnseNew); } } } TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandStatusInternal"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandStatus // // Purpose: Command handler for the CMIDM_STATUS command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 12 Nov 1997 // // Notes: // HRESULT HrOnCommandStatus( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; CONFOLDENTRY ccfe; if (apidl[0].empty()) { hr = E_INVALIDARG; } else { AssertSz(apidl.size() == 1, "We don't allow status on multi-selected items"); // Copy the pidl, as the PostMessage isn't sync, and the context menu's // copy of the pidl could be destroyed before the tray processed the // message. The tray is responsible for free'ing in the pidl. // hr = apidl[0].ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { if (fIsConnectedStatus(ccfe.GetNetConStatus()) || ccfe.IsConnected() ) { hr = HrOnCommandStatusInternal(ccfe, TRUE); } } } TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandStatus"); return hr; } VOID SetICWComplete(); //+--------------------------------------------------------------------------- // // Function: HrOnCommandNewConnection // // Purpose: Command handler for the CMIDM_NEW_CONNECTION command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 12 Nov 1997 // // Notes: // HRESULT HrOnCommandNewConnection( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; INetConnection * pNetCon = NULL; NETCFG_TRY PCONFOLDPIDL pidlConnection; // Don't use hwndOwner for anything. We shouldn't become modal! // hr = NetSetupAddRasConnection(NULL, &pNetCon); if (S_OK == hr) { CConnectionFolder * pcf = static_cast(psf); PCONFOLDPIDLFOLDER pidlFolder; if (pcf) { pidlFolder = pcf->PidlGetFolderRoot(); } Assert(pNetCon); hr = g_ccl.HrInsertFromNetCon(pNetCon, pidlConnection); if (SUCCEEDED(hr) && (!pidlConnection.empty()) ) { PCONFOLDPIDL pcfp = pidlConnection; GenerateEvent(SHCNE_CREATE, pidlFolder, pidlConnection, NULL); // Don't try to connect an object that's incoming only, and don't connect // it unless we're listed as disconnected // if (!(pcfp->dwCharacteristics & NCCF_INCOMING_ONLY) && (pcfp->ncs == NCS_DISCONNECTED)) { // If we have Ras connect permissions, then try to dial. Otherwise, don't // force the user into a failure here. // if (FHasPermission(NCPERM_RasConnect)) { hr = HrOnCommandConnectInternal(pNetCon, hwndOwner, pidlConnection, psf); } } } pNetCon->Release(); } else if (SUCCEEDED(hr)) { // Convert S_FALSE to S_OK // S_FALSE means no pages were displayed but nothing failed. // S_FALSE is returned when the wizard is already being displayed // hr = S_OK; } SetICWComplete(); NETCFG_CATCH(hr) TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandNewConnection"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandAdvancedConfig // // Purpose: Command handler for the CMIDM_ADVANCED_CONFIG command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 3 Dec 1997 // // Notes: // HRESULT HrOnCommandAdvancedConfig( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; hr = HrDoAdvCfgDlg(hwndOwner); TraceError("HrOnCommandAdvancedConfig", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandDelete // // Purpose: Command handler for the CMIDM_DELETE command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // psf [in] Our folder // // Returns: // // Author: jeffspr 3 Dec 1997 // // Notes: // HRESULT HrOnCommandDelete( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; INetConnection * pNetCon = NULL; INT iMBResult = 0; BOOL fActivating = FALSE; NETCFG_TRY PCONFOLDPIDLVEC::const_iterator iterLoop; HANDLE hMutex = NULL; for (iterLoop = apidl.begin(); iterLoop != apidl.end(); iterLoop++) { CConFoldEntry cfe; hr = iterLoop->ConvertToConFoldEntry(cfe); WCHAR szConnectionGuid [c_cchGuidWithTerm]; INT cch = StringFromGUID2 (cfe.GetGuidID(), szConnectionGuid, c_cchGuidWithTerm); Assert (c_cchGuidWithTerm == cch); BOOL fDuplicateMutex = FALSE; hMutex = CreateMutex(NULL, TRUE, szConnectionGuid); if (hMutex) { fDuplicateMutex = (ERROR_ALREADY_EXISTS == GetLastError()); ReleaseMutex(hMutex); CloseHandle(hMutex); } else { hr = E_ACCESSDENIED; break; } if (fDuplicateMutex) { // if the mutex already exists try to find the connection window // NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_ERROR_DELETE_CAPTION, IDS_CONFOLD_ERROR_DELETE_PROPERTYPAGEOPEN, MB_ICONEXCLAMATION); hr = cfe.HrGetNetCon(IID_INetConnection, reinterpret_cast(&pNetCon)); if (FAILED(hr)) { Assert(FALSE); break; } else { ActivatePropertyDialog(pNetCon); hr = E_ACCESSDENIED; break; } } } if (FAILED(hr)) { goto Exit; } // Bring up the prompt for the delete // if (apidl.size() > 1) { WCHAR wszItemCount[8]; // Convert the item count to a string // _itow( apidl.size(), wszItemCount, 10 ); // Bring up the message box // iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_MULTI_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_MULTI, MB_YESNO | MB_ICONQUESTION, wszItemCount); if (IDYES == iMBResult) { for (iterLoop = apidl.begin(); iterLoop != apidl.end(); iterLoop++) { CConFoldEntry cfe; hr = iterLoop->ConvertToConFoldEntry(cfe); if (SUCCEEDED(hr)) { if ( (NCCF_INCOMING_ONLY & cfe.GetCharacteristics()) && (NCM_NONE == cfe.GetNetConMediaType()) ) { DWORD dwActiveIncoming; if (SUCCEEDED(g_ccl.HasActiveIncomingConnections(&dwActiveIncoming)) && dwActiveIncoming) { if (1 == dwActiveIncoming ) { iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_MULTI_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_RASSERVER, MB_YESNO | MB_ICONQUESTION); } else { iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_MULTI_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_RASSERVER_MULTI, MB_YESNO | MB_ICONQUESTION, dwActiveIncoming); } } break; } } } } } else if (apidl.size() == 1) { CONFOLDENTRY ccfe; // Convert the pidl to a confoldentry, and use the name // to bring up the confirm message box // hr = apidl[0].ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { // Don't let them try to delete a wizard // if (ccfe.GetWizard()) { goto Exit; } else { // Check to see if this connection is in the process of activating. // If so, then we won't allow the delete. // PCONFOLDPIDL pidlEmpty; hr = HrCheckForActivation(pidlEmpty, ccfe, &fActivating); if (S_OK == hr) { if (!fActivating) { if (FALSE == (ccfe.GetNetConMediaType() == NCM_BRIDGE) && // we do allow the bridge to be deleted ((ccfe.GetNetConStatus() == NCS_CONNECTING) || fIsConnectedStatus(ccfe.GetNetConStatus()) || (ccfe.GetNetConStatus() == NCS_DISCONNECTING)) ) { // You can't delete an active connection // NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_ERROR_DELETE_CAPTION, IDS_CONFOLD_ERROR_DELETE_ACTIVE, MB_ICONEXCLAMATION); goto Exit; } else { if ( (NCCF_INCOMING_ONLY & ccfe.GetCharacteristics()) && (NCM_NONE == ccfe.GetNetConMediaType()) ) { DWORD dwActiveIncoming; if (SUCCEEDED(g_ccl.HasActiveIncomingConnections(&dwActiveIncoming)) && dwActiveIncoming) { if (1 == dwActiveIncoming ) { iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_RASSERVER, MB_YESNO | MB_ICONQUESTION); } else { iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_RASSERVER_MULTI, MB_YESNO | MB_ICONQUESTION, dwActiveIncoming); } } else { iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_SINGLE, MB_YESNO | MB_ICONQUESTION, ccfe.GetName()); } } else { // is it shared? // if it is warn the user RASSHARECONN rsc; hr = ccfe.HrGetNetCon(IID_INetConnection, reinterpret_cast(&pNetCon)); if (SUCCEEDED(hr)) { hr = HrNetConToSharedConnection(pNetCon, &rsc); if (SUCCEEDED(hr)) { BOOL pfShared; hr = HrRasIsSharedConnection(&rsc, &pfShared); if ((SUCCEEDED(hr)) && (pfShared == TRUE)) { // tell the user they are deleting a // shared connection and get confirmation iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_SHARED, MB_YESNO | MB_ICONQUESTION, ccfe.GetName()); } else { // Ask for delete confirmation iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_SINGLE, MB_YESNO | MB_ICONQUESTION, ccfe.GetName()); } } else { // Ask for delete confirmation iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION, IDS_CONFOLD_DELETE_CONFIRM_SINGLE, MB_YESNO | MB_ICONQUESTION, ccfe.GetName()); } } } } } else { // Bring up the MB about "Hey, you can't delete while // the connection is activating." // iMBResult = NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_ERROR_DELETE_CAPTION, IDS_CONFOLD_ERROR_DELETE_ACTIVE, MB_ICONEXCLAMATION); goto Exit; } } else { // If the connection wasn't found, then we should just drop out of here // because we sure can't delete it. // if (S_FALSE == hr) { goto Exit; } } } } else { AssertSz(FALSE, "Couldn't get ConFoldEntry from pidl in HrOnCommandDelete"); goto Exit; } } else { // No connections were specified. Take a hike. // goto Exit; } // If the user said "Yes" to the prompt // if (iMBResult == IDYES) { CConnectionFolder * pcf = static_cast(psf); PCONFOLDPIDLFOLDER pidlFolder; if (pcf) { pidlFolder = pcf->PidlGetFolderRoot(); } BOOL fShowActivationWarning = FALSE; BOOL fShowNotDeletableWarning = FALSE; for (iterLoop = apidl.begin(); iterLoop != apidl.end(); iterLoop++) { CONFOLDENTRY ccfe; hr = iterLoop->ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { // If this is a LAN connection the user doesn't have rights // if ((NCM_LAN == ccfe.GetNetConMediaType()) || (ccfe.GetWizard())) { fShowNotDeletableWarning = TRUE; continue; } // If this is a RAS connection and the user doesn't have rights // then skip // if (IsMediaRASType(ccfe.GetNetConMediaType())) { if ((!FHasPermission(NCPERM_DeleteConnection)) || ((ccfe.GetCharacteristics() & NCCF_ALL_USERS) && !FHasPermission(NCPERM_DeleteAllUserConnection))) { fShowNotDeletableWarning = TRUE; continue; } } PCONFOLDPIDL pidlEmpty; hr = HrCheckForActivation(pidlEmpty, ccfe, &fActivating); if (S_OK == hr) { // Only allow deletion if this connection is inactive and // it allows removal. // if (fActivating || ((FALSE == (ccfe.GetNetConMediaType() == NCM_BRIDGE))) && ((ccfe.GetNetConStatus() == NCS_CONNECTING) || fIsConnectedStatus(ccfe.GetNetConStatus()) || (ccfe.GetNetConStatus() == NCS_DISCONNECTING)) ) { fShowActivationWarning = TRUE; } else if (ccfe.GetCharacteristics() & NCCF_ALLOW_REMOVAL) { hr = HrNetConFromPidl(*iterLoop, &pNetCon); if (SUCCEEDED(hr)) { if ( NCM_BRIDGE == ccfe.GetNetConMediaType() ) { // // Special delete case Removing the Network bridge take so long that we display a status dialog // and prevent the user from changing anything will we process // hr = HrOnCommandBridgeRemoveConnections( apidl, hwndOwner, psf, 0 // Remove the Network bridge ); } else { hr = pNetCon->Delete(); } if (SUCCEEDED(hr) && pcf) { hr = HrDeleteFromCclAndNotifyShell(pidlFolder, *iterLoop, ccfe); } else if(E_ACCESSDENIED == hr && NCM_BRIDGE == ccfe.GetNetConMediaType()) { // can't delete the bridge while the netcfg lock is held NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_ERROR_DELETE_CAPTION, IDS_CONFOLD_ERROR_DELETE_BRIDGE_ACCESS, MB_ICONEXCLAMATION); } ReleaseObj(pNetCon); } } else { // The selected item is not deletable // fShowNotDeletableWarning = TRUE; } } } } if (fShowNotDeletableWarning) { // You can't delete an item that doesn't support it // NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_ERROR_DELETE_CAPTION, (1 == apidl.size()) ? IDS_CONFOLD_ERROR_DELETE_NOSUPPORT : IDS_CONFOLD_ERROR_DELETE_NOSUPPORT_MULTI, MB_ICONEXCLAMATION); } else if (fShowActivationWarning) { // You can't delete an active connection. Note, if more // than one are being deleted, then we put up the warning // that says 'one or more are being ignored'. // NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_ERROR_DELETE_CAPTION, (1 == apidl.size()) ? IDS_CONFOLD_ERROR_DELETE_ACTIVE : IDS_CONFOLD_ERROR_DELETE_ACTIVE_MULTI, MB_ICONEXCLAMATION); } } Exit: NETCFG_CATCH(hr) TraceError("HrOnCommandDelete", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandOptionalComponents // // Purpose: Command handler for the CMIDM_CONMENU_OPTIONALCOMPONENTS command. // Bring up the network optional components UI. // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // psf [in] Our folder // // Returns: // // Author: scottbri 29 Oct 1998 // // Notes: // HRESULT HrOnCommandOptionalComponents(IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { return HrLaunchNetworkOptionalComponents(); } //+--------------------------------------------------------------------------- // // Function: HrOnCommandNetworkId // // Purpose: Command handler for the CMIDM_CONMENU_NETORK_ID command. // Bring up the network ID UI // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 26 Feb 1998 // // Notes: // HRESULT HrOnCommandNetworkId( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { TraceFileFunc(ttidShellFolder); HRESULT hr = S_OK; WCHAR szPath[MAX_PATH]; hr = SHGetFolderPath( hwndOwner, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT, szPath); if (SUCCEEDED(hr)) { HINSTANCE hInst = ::ShellExecute(hwndOwner, NULL, c_szRunDll32, c_szNetworkIdCmdLine, szPath, SW_SHOW ); if (hInst <= reinterpret_cast(32)) { hr = HRESULT_FROM_WIN32(static_cast(reinterpret_cast(hInst))); } } TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandNetworkId"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandDialupPrefs // // Purpose: Command handler for the CMIDM_CONMENU_DIALUP_PREFS command. // Bring up the dialup prefs dialog // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 26 Feb 1998 // // Notes: // HRESULT HrOnCommandDialupPrefs( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; DWORD dwErr = 0; dwErr = RasUserPrefsDlg(hwndOwner); hr = HRESULT_FROM_WIN32 (dwErr); TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandDialupPrefs"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandOperatorAssist // // Purpose: Command handler for the CMIDM_CONMENU_OPERATOR_ASSIST command. // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 26 Feb 1998 // // Notes: // HRESULT HrOnCommandOperatorAssist( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; DWORD dwErr = 0; // Swap the flag // g_fOperatorAssistEnabled = !g_fOperatorAssistEnabled; // Set the state within RasDlg itself // dwErr = RasUserEnableManualDial(hwndOwner, FALSE, g_fOperatorAssistEnabled); hr = HRESULT_FROM_WIN32 (dwErr); TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandDialupPrefs"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandCreateShortcut // // Purpose: Command handler for the CMIDM_CREATE_SHORTCUT command. // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: jeffspr 13 Mar 1998 // // Notes: // HRESULT HrOnCommandCreateShortcut( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; hr = HrCreateShortcutWithPath( apidl, hwndOwner, psf, NULL); TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandCreateShortcut"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandSetDefault // // Purpose: Command handler for the CMIDM_SET_DEFAULT command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: deonb 27 Nov 2000 // // Notes: We only act on a single entry in this function // HRESULT HrOnCommandSetDefault( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; CONFOLDENTRY ccfe; if (!apidl.empty()) { hr = apidl[0].ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { INetDefaultConnection *pNetDefaultConnection = NULL; // Get the INetDefaultConnection object from the persist data // hr = ccfe.HrGetNetCon(IID_INetDefaultConnection, reinterpret_cast(&pNetDefaultConnection)); if (SUCCEEDED(hr)) { hr = pNetDefaultConnection->SetDefault(TRUE); ReleaseObj(pNetDefaultConnection); hr = S_OK; } else { if (E_NOINTERFACE == hr) { AssertSz(FALSE, "BUG: This connection type does not support INetDefaultConnection. Remove it from the menu"); } } } } TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandSetDefault"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandUnsetDefault // // Purpose: Command handler for the CMIDM_UNSET_DEFAULT command // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // cidl [in] Size of the array // hwndOwner [in] Owner hwnd // // Returns: // // Author: deonb 27 Nov 2000 // // Notes: We only act on a single entry in this function // HRESULT HrOnCommandUnsetDefault( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf) { HRESULT hr = S_OK; CONFOLDENTRY ccfe; if (!apidl.empty()) { hr = apidl[0].ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { INetDefaultConnection *pNetDefaultConnection = NULL; // Get the INetDefaultConnection object from the persist data // hr = ccfe.HrGetNetCon(IID_INetDefaultConnection, reinterpret_cast(&pNetDefaultConnection)); if (SUCCEEDED(hr)) { hr = pNetDefaultConnection->SetDefault(FALSE); ReleaseObj(pNetDefaultConnection); hr = S_OK; } else { if (E_NOINTERFACE == hr) { AssertSz(FALSE, "BUG: This connection type does not support INetDefaultConnection. Remove it from the menu"); } } } } TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandUnsetDefault"); return hr; } HRESULT HrCreateShortcutWithPath( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf, PCWSTR pszDir) { HRESULT hr = S_OK; LPDATAOBJECT pdtobj = NULL; LPCITEMIDLIST* apidlInternal = NULL; ULONG cidlInternal = 0; PCONFOLDPIDLVEC::const_iterator iterLoop; if (!apidl.empty()) { apidlInternal = new LPCITEMIDLIST[apidl.size()]; if (apidlInternal) { for (iterLoop = apidl.begin(); iterLoop != apidl.end(); iterLoop++) { const PCONFOLDPIDL& pcfp = *iterLoop; if (!(pcfp->dwCharacteristics & NCCF_INCOMING_ONLY)) { apidlInternal[cidlInternal++] = iterLoop->GetItemIdList(); } } hr = psf->GetUIObjectOf( hwndOwner, cidlInternal, apidlInternal, IID_IDataObject, NULL, (LPVOID *) &pdtobj); if (SUCCEEDED(hr)) { SHCreateLinks(hwndOwner, pszDir, pdtobj, SHCL_USEDESKTOP | SHCL_USETEMPLATE | SHCL_CONFIRM, NULL); ReleaseObj(pdtobj); } delete apidlInternal; } } TraceError("HrCreateShortcutWithPath", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: RefreshFolderItem // // Purpose: Refresh an item within a connections folder. Mostly, this will // be called after a connect or disconnect operation. // // Arguments: // pidlFolder [in] PIDL for the connections folder // pidlItemOld[in] PIDL for the item that's changed. // pidlItemNew[in] PIDL for the item that it's changing to. // fRestart [in] If this is called during system startup // // Returns: // // Author: jeffspr 13 Jun 1998 // // Notes: // VOID RefreshFolderItem(const PCONFOLDPIDLFOLDER& pidlFolder, const PCONFOLDPIDL& pidlItemOld, const PCONFOLDPIDL& pidlItemNew, BOOL fRestart) { TraceTag(ttidShellFolder, "RefreshFolderItem"); NETCFG_TRY HRESULT hr = S_OK; INT iCachedImage = 0; PCONFOLDPIDLFOLDER pidlFolderCopy; // If a folder pidl wasn't passed in, try to get one // if (pidlFolder.empty()) { hr = HrGetConnectionsFolderPidl(pidlFolderCopy); } else { pidlFolderCopy = pidlFolder; } // If we now have a pidl, send the GenerateEvent to update the item // if (SUCCEEDED(hr)) { GenerateEvent(SHCNE_UPDATEITEM, pidlFolderCopy, pidlItemNew, NULL); } // If we have a old item pidl, try to update its icon (useful for // shortcuts as well as folder items) // if (!pidlItemOld.empty()) { const PCONFOLDPIDL& pcfp = pidlItemOld; if (!pcfp.empty()) { CConFoldEntry cfe; hr = pcfp.ConvertToConFoldEntry(cfe); if (SUCCEEDED(hr)) { g_pNetConfigIcons->HrUpdateSystemImageListForPIDL(cfe); } if (fRestart) { TraceTag(ttidIcons, "Refreshing Icon Shortcuts for startup"); // RAS connection state will be changed between reboots, // we need to make sure icons for previously connected // or disconnected ras connections are also updated // If it's a ras connection, BOOL fInbound = !!(pidlItemOld->dwCharacteristics & NCCF_INCOMING_ONLY); if ((IsMediaRASType(pidlItemOld->ncm)) && !fInbound) { PCONFOLDPIDL pcfpTemp = pidlItemOld; if ((pcfpTemp->ncs == NCS_DISCONNECTED) || (pcfpTemp->ncs == NCS_CONNECTING)) { // get the connected icon pcfpTemp->ncs = NCS_CONNECTED; } else { // get the disconnected icon pcfpTemp->ncs = NCS_DISCONNECTED; } cfe.clear(); hr = pcfpTemp.ConvertToConFoldEntry(cfe); if (SUCCEEDED(hr)) { g_pNetConfigIcons->HrUpdateSystemImageListForPIDL(cfe); } } } } } NETCFG_CATCH_NOHR } // // // HRESULT HrOnCommandCreateBridge( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf ) { HRESULT hResult; IHNetCfgMgr* pHomeNetConfigManager; CWaitCursor wc; // display wait cursor hResult = HrCreateInstance(CLSID_HNetCfgMgr, CLSCTX_INPROC, &pHomeNetConfigManager); // REVIEW combine this with QI? if(SUCCEEDED(hResult)) { IHNetBridgeSettings* pNetBridgeSettings; hResult = pHomeNetConfigManager->QueryInterface(IID_IHNetBridgeSettings, reinterpret_cast(&pNetBridgeSettings)); if(SUCCEEDED(hResult)) { IHNetBridge* pNetBridge; IEnumHNetBridges* pNetBridgeEnum; hResult = pNetBridgeSettings->EnumBridges(&pNetBridgeEnum); if(SUCCEEDED(hResult)) { hResult = pNetBridgeEnum->Next(1, &pNetBridge, NULL); if(S_FALSE == hResult) // no existing bridges, make a new one { hResult = pNetBridgeSettings->CreateBridge(&pNetBridge); } if(S_OK == hResult) // can't use SUCCEEDED because someone returns S_FALSE { Assert(pNetBridge); // we better have gotten one from somewhere // Add any selected connections for ( PCONFOLDPIDLVEC::const_iterator i = apidl.begin(); (i != apidl.end()) && SUCCEEDED(hResult); i++ ) { const PCONFOLDPIDL& pcfp = *i; if ( pcfp.empty() ) continue; if ( NCM_LAN != pcfp->ncm ) continue; if ( (NCCF_BRIDGED|NCCF_FIREWALLED|NCCF_SHARED) & pcfp->dwCharacteristics ) continue; // // Ok we now have a LAN adapter the is valid to bind to the bridge // INetConnection* pNetConnection; hResult = HrNetConFromPidl(*i, &pNetConnection); if(SUCCEEDED(hResult)) { IHNetConnection* pHomeNetConnection; hResult = pHomeNetConfigManager->GetIHNetConnectionForINetConnection(pNetConnection, &pHomeNetConnection); if(SUCCEEDED(hResult)) { IHNetBridgedConnection* pBridgedConnection; hResult = pNetBridge->AddMember(pHomeNetConnection, &pBridgedConnection); if(SUCCEEDED(hResult)) { ReleaseObj(pBridgedConnection); } ReleaseObj(pHomeNetConnection); } ReleaseObj(pNetConnection); } // no cleanup needed } ReleaseObj(pNetBridge); } ReleaseObj(pNetBridgeEnum); } ReleaseObj(pNetBridgeSettings); } ReleaseObj(pHomeNetConfigManager); } SendMessage(hwndOwner, WM_COMMAND, IDCANCEL, 0); // destroy the status dialog // Show an error dialog on failure if( FAILED(hResult) ) { UINT ids; if( NETCFG_E_NO_WRITE_LOCK == hResult ) { ids = IDS_CONFOLD_BRIDGE_NOLOCK; } else { ids = IDS_CONFOLD_BRIDGE_UNEXPECTED; } NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, ids, MB_ICONEXCLAMATION | MB_OK); } return hResult; } // // // INT_PTR CALLBACK CreateBridgeStatusDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR nResult = FALSE; switch(uMsg) { case WM_INITDIALOG: { LPCWSTR pResourceStr = SzLoadIds(IDS_CONFOLD_OBJECT_TYPE_BRIDGE); SetWindowText(hwndDlg, pResourceStr); pResourceStr = SzLoadIds(IDS_STATUS_BRIDGE_CREATION); SetDlgItemText(hwndDlg, IDC_TXT_STATUS, pResourceStr); CCommandHandlerParams* pCreateBridgeParams = reinterpret_cast(lParam); HrCommandHandlerThread(HrOnCommandCreateBridge, *(pCreateBridgeParams->apidl), hwndDlg, pCreateBridgeParams->psf); // HrOnCommandCreateBridge will send a message to kill this dialog nResult = TRUE; } break; case WM_COMMAND: if(IDCANCEL == LOWORD(wParam)) { EndDialog(hwndDlg, 0); nResult = TRUE; } break; } return nResult; } // // // HRESULT HrOnCommandDeleteBridge( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf ) { HRESULT hr = S_FALSE; PCONFOLDPIDLVEC::const_iterator iterator; for ( iterator = apidl.begin(); iterator != apidl.end(); iterator++ ) { CONFOLDENTRY ccfe; hr = iterator->ConvertToConFoldEntry(ccfe); if ( SUCCEEDED(hr) ) { if ( NCM_BRIDGE == ccfe.GetNetConMediaType() ) { // // Stop at the first select BRIDGE item // The delete of the bridge is part of a bigger FOR LOOP see HrOnCommandDelete() // INetConnection* pNetConnection; hr = HrNetConFromPidl(*iterator, &pNetConnection); if ( SUCCEEDED(hr) ) { hr = pNetConnection->Delete(); ReleaseObj(pNetConnection); } break; } } } SendMessage(hwndOwner, WM_COMMAND, IDCANCEL, hr); // destroy the status dialog // Show an error dialog on failure if( FAILED(hr) ) { UINT ids; if( NETCFG_E_NO_WRITE_LOCK == hr ) { ids = IDS_CONFOLD_BRIDGE_NOLOCK; } else { ids = IDS_CONFOLD_BRIDGE_UNEXPECTED; } NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, ids, MB_ICONEXCLAMATION | MB_OK); } return S_OK; } // // // HRESULT HrOnCommandDeleteBridgeConnections( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf ) { CWaitCursor wc; // display wait cursor IHNetCfgMgr* pHomeNetConfigManager; HRESULT hResult = HrCreateInstance(CLSID_HNetCfgMgr, CLSCTX_INPROC, &pHomeNetConfigManager); // REVIEW combine this with QI? if ( SUCCEEDED(hResult) ) { // // Remove any selected connections // for ( PCONFOLDPIDLVEC::const_iterator i = apidl.begin(); i != apidl.end() && SUCCEEDED(hResult); i++ ) { INetConnection* pNetConnection; hResult = HrNetConFromPidl(*i, &pNetConnection); if(SUCCEEDED(hResult)) { IHNetConnection* pHomeNetConnection; hResult = pHomeNetConfigManager->GetIHNetConnectionForINetConnection(pNetConnection, &pHomeNetConnection); if(SUCCEEDED(hResult)) { IHNetBridgedConnection* pBridgedConnection; hResult = pHomeNetConnection->GetControlInterface(IID_IHNetBridgedConnection, reinterpret_cast(&pBridgedConnection)); if ( SUCCEEDED(hResult) ) { hResult = pBridgedConnection->RemoveFromBridge(); ReleaseObj(pBridgedConnection); } ReleaseObj(pHomeNetConnection); } ReleaseObj(pNetConnection); } // no cleanup needed } ReleaseObj(pHomeNetConfigManager); } SendMessage(hwndOwner, WM_COMMAND, IDCANCEL, hResult); // destroy the status dialog // Show an error dialog on failure if( FAILED(hResult) ) { UINT ids; if( NETCFG_E_NO_WRITE_LOCK == hResult ) { ids = IDS_CONFOLD_BRIDGE_NOLOCK; } else { ids = IDS_CONFOLD_BRIDGE_UNEXPECTED; } NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, ids, MB_ICONEXCLAMATION | MB_OK); } return S_OK; } // // // INT_PTR CALLBACK DeleteBridgeStatusDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { INT_PTR nResult = FALSE; switch(uMsg) { case WM_INITDIALOG: { LPCWSTR pResourceStr = SzLoadIds(IDS_CONFOLD_OBJECT_TYPE_BRIDGE); SetWindowText(hwndDlg, pResourceStr); CCommandHandlerParams* pDeleteBridgeParams = reinterpret_cast(lParam); if ( pDeleteBridgeParams->nAdditionalParam == CMIDM_REMOVE_FROM_BRIDGE ) { // // Only remove the currently selected connections from the Network bridge // pResourceStr = SzLoadIds(IDS_STATUS_BRIDGE_REMOVE_MEMBER); SetDlgItemText(hwndDlg, IDC_TXT_STATUS, pResourceStr); HrCommandHandlerThread(HrOnCommandDeleteBridgeConnections, *(pDeleteBridgeParams->apidl), hwndDlg, pDeleteBridgeParams->psf); } else { // // Full delete of the network bridge // pResourceStr = SzLoadIds(IDS_STATUS_BRIDGE_DELETING); SetDlgItemText(hwndDlg, IDC_TXT_STATUS, pResourceStr); HrCommandHandlerThread(HrOnCommandDeleteBridge, *(pDeleteBridgeParams->apidl), hwndDlg, pDeleteBridgeParams->psf); } // After the delete a HrOnCommandDeleteBridge will send a SendMessage(hwndOwner, WM_COMMAND, IDCANCEL, 0); // destroy the status dialog nResult = TRUE; } break; case WM_COMMAND: if(IDCANCEL == LOWORD(wParam)) { EndDialog(hwndDlg, lParam); nResult = TRUE; } break; } return nResult; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandBridgeAddConnections // // Purpose: Command handler for the CMIDM_CREATE_BRIDGE, CMDIDM_CONMENU_CREATE_BRIDGE, CMIDM_ADD_TO_BRIDGE. // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // psf [in] SHELLFOLDER // hwndOwner [in] Owner hwnd // // Returns: // // Author: jpdup 6 March 2000 // // Notes: // HRESULT HrOnCommandBridgeAddConnections( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf ) { CCommandHandlerParams CreateBridgeParams; CreateBridgeParams.apidl = &apidl; CreateBridgeParams.hwndOwner = hwndOwner; CreateBridgeParams.psf = psf; HRESULT hr = DialogBoxParam( _Module.GetResourceInstance(), MAKEINTRESOURCE(IDD_STATUS), hwndOwner, CreateBridgeStatusDialogProc, reinterpret_cast(&CreateBridgeParams) ); TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandBridgeAddConnections"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOnCommandBridgeRemoveConnections // // Purpose: Command handler for the CMIDM_REMOVE_FROM_BRIDGE and the DELETE command when done on the NetworkBridge object // // Arguments: // apidl [in] PIDL array (item 0 is our item to work on) // hwndOwner [in] Owner hwnd // psf [in] SHELLFOLDER // bDeleteTheNetworkBridge [in] true is the NetworkBridge needs to be totaly remove, false if only the currently select item found in apild needs to be remove // // Returns: // // Author: jpdup 6 March 2000 // // Notes: // HRESULT HrOnCommandBridgeRemoveConnections( IN const PCONFOLDPIDLVEC& apidl, HWND hwndOwner, LPSHELLFOLDER psf, UINT_PTR nDeleteTheNetworkBridgeMode ) { CCommandHandlerParams DeleteBridgeParams; DeleteBridgeParams.apidl = &apidl; DeleteBridgeParams.hwndOwner = hwndOwner; DeleteBridgeParams.psf = psf; DeleteBridgeParams.nAdditionalParam = nDeleteTheNetworkBridgeMode; HRESULT hr = DialogBoxParam( _Module.GetResourceInstance(), MAKEINTRESOURCE(IDD_STATUS), hwndOwner, DeleteBridgeStatusDialogProc, reinterpret_cast(&DeleteBridgeParams) ); TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandBridgeRemoveConnections"); return hr; }