|
|
//+---------------------------------------------------------------------------
//
// 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 <ncnetcon.h>
#include <nsres.h>
#include <wizentry.h>
#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"
#include <clusapi.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; HINSTANCE hInstNetShell = NULL;
// Create a new scope since FreeLibraryAndExitThread will not call destructors on global scope
{ PCONFOLDONCOMMANDPARAMS pcfocp = (PCONFOLDONCOMMANDPARAMS) lpParam; BOOL fCoInited = FALSE; IUnknown * punkExplorerProcess = NULL;
Assert(pcfocp);
hr = SHGetInstanceExplorer(&punkExplorerProcess); if (FAILED(hr)) { // This is ok. All we want to do, is if explorer is running, add a ref so that it doesn't
// disappear from under us. If it's NULL, not much we can do about it.
punkExplorerProcess = NULL; }
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.
//
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<HINSTANCE>(32)) { return S_OK; } else { return E_FAIL; } }
#include <mprapi.h>
#include <routprot.h>
// Fix IA64 conflict with Shell Macro
#undef IS_ALIGNED
#include <ipnat.h>
BOOL IsInUseByRRAS (LPOLESTR psz) { BOOL bInUse = FALSE;
HANDLE hServer = NULL; DWORD dwErr = MprConfigServerConnect (NULL, &hServer); if (hServer) { DWORD dwRead = 0, dwTotal = 0; MPR_INTERFACE_0 * pMI0 = NULL; dwErr = MprConfigInterfaceEnum (hServer, 0, // level
(LPBYTE*)&pMI0, // will return array of interface info 0s
-1, // all of 'em
&dwRead, &dwTotal, NULL); // resume handle
if (pMI0) { for (DWORD i=0; i<dwRead; i++) { if (!wcscmp (psz, pMI0[i].wszInterfaceName)) { // found it!
HANDLE hIfTransport = NULL; dwErr = MprConfigInterfaceTransportGetHandle (hServer, pMI0[i].hInterface, PID_IP, &hIfTransport); if (hIfTransport) { DWORD dwSize= 0; RTR_INFO_BLOCK_HEADER * pRIBH = NULL; dwErr = MprConfigInterfaceTransportGetInfo (hServer, pMI0[i].hInterface, hIfTransport, (LPBYTE*)&pRIBH, &dwSize); if (pRIBH) { DWORD dwCount = 0; dwSize = 0; IP_NAT_INTERFACE_INFO * pINII = NULL; dwErr = MprInfoBlockFind ((LPVOID)pRIBH, MS_IP_NAT, &dwSize, &dwCount, (LPBYTE*)&pINII); #ifdef KEEP_AROUND_FOR_DOC_PURPOSES
if (!pINII) ; // neither public or private
else if (pINII && (pINII->Flags == 0)) ; // private interface
else ; // public interface
#endif
if (pINII) bInUse = TRUE;
MprConfigBufferFree (pRIBH); } } break; // found it
} } MprConfigBufferFree (pMI0); } MprConfigServerDisconnect (hServer); } return bInUse; } BOOL InUseByRRAS ( IN const PCONFOLDPIDLVEC& apidlSelected ) { //
// Loop through each of the selected objects
//
for ( PCONFOLDPIDLVEC::const_iterator iterObjectLoop = apidlSelected.begin(); iterObjectLoop != apidlSelected.end(); iterObjectLoop++ ) { const PCONFOLDPIDL& pcfp = *iterObjectLoop; if ( !pcfp.empty() ) { // convert clsid to string
OLECHAR pole[64]; pole[0] = 0; StringFromGUID2 (pcfp->guidId, pole, 64); if (pole[0]) { if (IsInUseByRRAS (pole) == TRUE) return TRUE; } } } return FALSE; }
//
//
//
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<HINSTANCE>(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() { LPCWSTR szHelpUrl = NULL;
if (IsOS(OS_PROFESSIONAL) || IsOS(OS_PERSONAL)) { szHelpUrl = L"hcp://system/panels/Topics.htm?path=TopLevelBucket_4/Fixing_a_problem/Home_Networking_and_network_problems"; } else { szHelpUrl = L"hcp://help/tshoot/tshomenet.htm"; }
if (ShellExecute(NULL, NULL, szHelpUrl, L"", NULL, SW_SHOWNORMAL) > reinterpret_cast<HINSTANCE>(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<CConnectionFolder *>(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<LPSTR>(&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<CConnectionFolder *>(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<CConnectionFolder *>(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<VOID**>(&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<CConnectionFolder *>(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<VOID**>(&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()) || (NCS_INVALID_ADDRESS == ccfe.GetNetConStatus()) ) { 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<CConnectionFolder *>(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<VOID**>(&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<VOID**>(&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<CConnectionFolder *>(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<HINSTANCE>(32)) { hr = HRESULT_FROM_WIN32(static_cast<DWORD>(reinterpret_cast<DWORD_PTR>(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<VOID**>(&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<VOID**>(&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, "%S (%s): Refreshing Icon Shortcuts for startup", pidlItemOld->PszGetNamePointer(), DbgNcm(pidlItemOld->dwCharacteristics) );
// 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<void**>(&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<CCommandHandlerParams*>(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<void**>(&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<CCommandHandlerParams*>(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 ) { if (InUseByRRAS (apidl) == TRUE) { // tell user about this
NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_OBJECT_TYPE_BRIDGE, IDS_BRIDGE_EDUCATION_2, MB_ICONEXCLAMATION | MB_OK ); return S_FALSE; }
{ // see if local machine is a node in a cluster
DWORD dwClusterState = 0; GetNodeClusterState (NULL, &dwClusterState); if ((dwClusterState == ClusterStateNotRunning) || (dwClusterState == ClusterStateRunning ) ){ // pop up warning
NcMsgBox (_Module.GetResourceInstance(), NULL, IDS_CONFOLD_OBJECT_TYPE_BRIDGE, IDS_BRIDGE_CLUSTERING_CONFLICT_WARNING, MB_OK | MB_ICONWARNING); } }
CCommandHandlerParams CreateBridgeParams;
CreateBridgeParams.apidl = &apidl; CreateBridgeParams.hwndOwner = hwndOwner; CreateBridgeParams.psf = psf;
HRESULT hr = (HRESULT)DialogBoxParam( _Module.GetResourceInstance(), MAKEINTRESOURCE(IDD_STATUS), hwndOwner, CreateBridgeStatusDialogProc, reinterpret_cast<LPARAM>(&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 = (HRESULT)DialogBoxParam( _Module.GetResourceInstance(), MAKEINTRESOURCE(IDD_STATUS), hwndOwner, DeleteBridgeStatusDialogProc, reinterpret_cast<LPARAM>(&DeleteBridgeParams) );
TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandBridgeRemoveConnections"); return hr; }
|