874 lines
26 KiB
C++
874 lines
26 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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 "upsres.h"
|
|
#include "oncommand.h"
|
|
|
|
#if DBG // Debug menu commands
|
|
#include "oncommand_dbg.h" //
|
|
#endif
|
|
|
|
#include "shutil.h"
|
|
#include <upsres.h>
|
|
#include "tfind.h"
|
|
|
|
//---[ Externs ]--------------------------------------------------------------
|
|
|
|
extern const WCHAR c_szUPnPUIDll[];
|
|
extern const TCHAR c_sztUPnPUIDll[];
|
|
|
|
//---[ Prototypes ]-----------------------------------------------------------
|
|
|
|
HRESULT HrCreateDevicePropertySheets(
|
|
HWND hwndOwner,
|
|
NewDeviceNode * pNDN);
|
|
|
|
//---[ Constants ]------------------------------------------------------------
|
|
|
|
|
|
HRESULT HrCommandHandlerThread(
|
|
FOLDERONCOMMANDPROC pfnCommandHandler,
|
|
LPITEMIDLIST * apidl,
|
|
ULONG cidl,
|
|
HWND hwndOwner,
|
|
LPSHELLFOLDER psf)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPITEMIDLIST * apidlCopy = NULL;
|
|
ULONG cidlCopy = 0;
|
|
|
|
// If there are pidls to copy, copy them
|
|
//
|
|
if (apidl)
|
|
{
|
|
hr = HrCloneRgIDL((LPCITEMIDLIST *) apidl, cidl, &apidlCopy, &cidlCopy);
|
|
}
|
|
|
|
// If either there were no pidls, or the Clone succeeded, then we want to continue
|
|
//
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PFOLDONCOMMANDPARAMS pfocp = new FOLDONCOMMANDPARAMS;
|
|
|
|
if (pfocp)
|
|
{
|
|
pfocp->pfnfocp = pfnCommandHandler;
|
|
pfocp->apidl = apidlCopy;
|
|
pfocp->cidl = cidlCopy;
|
|
pfocp->hwndOwner = hwndOwner;
|
|
pfocp->psf = psf;
|
|
pfocp->hInstFolder = 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 hInstFolder = LoadLibrary(c_sztUPnPUIDll);
|
|
|
|
if (hInstFolder)
|
|
{
|
|
pfocp->hInstFolder = hInstFolder;
|
|
|
|
DWORD dwThreadId;
|
|
hthrd = CreateThread(NULL, 0,
|
|
(LPTHREAD_START_ROUTINE)FolderCommandHandlerThreadProc,
|
|
(LPVOID)pfocp, 0, &dwThreadId);
|
|
}
|
|
|
|
if (NULL != hthrd)
|
|
{
|
|
CloseHandle(hthrd);
|
|
}
|
|
else
|
|
{
|
|
pfocp->hInstFolder = NULL;
|
|
FolderCommandHandlerThreadProc(pfocp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Run directly in this same thread
|
|
//
|
|
FolderCommandHandlerThreadProc((PVOID) pfocp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
|
|
// Don't release the psf here. This should have been taken care of by the called ThreadProc
|
|
//
|
|
TraceError("HrCommandHandlerThread", hr);
|
|
return hr;
|
|
}
|
|
|
|
DWORD WINAPI FolderCommandHandlerThreadProc(LPVOID lpParam)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PFOLDONCOMMANDPARAMS pfocp = (PFOLDONCOMMANDPARAMS) lpParam;
|
|
BOOL fCoInited = FALSE;
|
|
|
|
Assert(pfocp);
|
|
|
|
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 = pfocp->pfnfocp(
|
|
pfocp->apidl,
|
|
pfocp->cidl,
|
|
pfocp->hwndOwner,
|
|
pfocp->psf);
|
|
}
|
|
|
|
// Remove the ref that we have on this object. The thread handler would have addref'd
|
|
// this before queueing our action
|
|
//
|
|
if (pfocp->psf)
|
|
{
|
|
ReleaseObj(pfocp->psf);
|
|
}
|
|
|
|
// Release apidl
|
|
//
|
|
if (pfocp->apidl)
|
|
{
|
|
FreeRgIDL(pfocp->cidl, pfocp->apidl);
|
|
}
|
|
|
|
// Remove this object. We're responsible for this now.
|
|
//
|
|
HINSTANCE hInstFolder = pfocp->hInstFolder;
|
|
pfocp->hInstFolder = NULL;
|
|
|
|
delete pfocp;
|
|
|
|
if (fCoInited)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
|
|
if (hInstFolder)
|
|
{
|
|
FreeLibraryAndExitThread(hInstFolder, hr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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,
|
|
LPITEMIDLIST * apidl,
|
|
ULONG cidl,
|
|
HWND hwndOwner,
|
|
LPCMINVOKECOMMANDINFO lpici,
|
|
LPSHELLFOLDER psf)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CWaitCursor wc; // Bring up wait cursor now. Remove when we go out of scope.
|
|
|
|
#if 0
|
|
// refresh all permission so subsequent calls can use cached value
|
|
RefreshAllPermission();
|
|
#endif
|
|
|
|
switch(uiCommand)
|
|
{
|
|
case CMIDM_INVOKE:
|
|
Assert(apidl);
|
|
hr = HrCommandHandlerThread(HrOnCommandInvoke, apidl, cidl, hwndOwner, psf);
|
|
break;
|
|
|
|
case CMIDM_ARRANGE_BY_NAME:
|
|
ShellFolderView_ReArrange(hwndOwner, ICOL_NAME);
|
|
break;
|
|
|
|
case CMIDM_ARRANGE_BY_URL:
|
|
ShellFolderView_ReArrange(hwndOwner, ICOL_URL);
|
|
break;
|
|
|
|
case CMIDM_CREATE_SHORTCUT:
|
|
Assert(apidl);
|
|
hr = HrCommandHandlerThread(HrOnCommandCreateShortcut, apidl, cidl, hwndOwner, psf);
|
|
break;
|
|
|
|
case CMIDM_DELETE:
|
|
Assert(apidl);
|
|
hr = HrCommandHandlerThread(HrOnCommandDelete, apidl, cidl, hwndOwner, psf);
|
|
break;
|
|
|
|
case CMIDM_PROPERTIES:
|
|
Assert(apidl);
|
|
hr = HrCommandHandlerThread(HrOnCommandProperties, apidl, cidl, hwndOwner, psf);
|
|
break;
|
|
|
|
#if DBG
|
|
case CMIDM_DEBUG_TRACING:
|
|
hr = HrOnCommandDebugTracing(apidl, cidl, hwndOwner, psf);
|
|
break;
|
|
|
|
case CMIDM_DEBUG_REFRESH:
|
|
hr = HrOnCommandDebugRefresh(apidl, cidl, hwndOwner, psf);
|
|
break;
|
|
|
|
case CMIDM_DEBUG_TESTASYNCFIND:
|
|
hr = HrOnCommandDebugTestAsyncFind(apidl, cidl, hwndOwner, psf);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
AssertSz(FALSE, "Unknown command in HrFolderCommandHandler");
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrFolderCommandHandler");
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrOnCommandInvoke
|
|
//
|
|
// Purpose: Command handler for CMIDM_INVOKE
|
|
//
|
|
// 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 IShellFolder *
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 8 Sep 1999
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT HrOnCommandInvoke(
|
|
LPITEMIDLIST * apidl,
|
|
ULONG cidl,
|
|
HWND hwndOwner,
|
|
LPSHELLFOLDER psf)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fResult = FALSE;
|
|
PUPNPDEVICEFOLDPIDL pudfp = ConvertToUPnPDevicePIDL(apidl[0]);
|
|
IUPnPDeviceFinder * pdf = NULL;
|
|
LPTSTR szUrl = NULL;
|
|
|
|
Assert(pudfp);
|
|
Assert(cidl > 0);
|
|
|
|
hr = CoCreateInstance(CLSID_UPnPDeviceFinder, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IUPnPDeviceFinder, (LPVOID *)&pdf);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IUPnPDevice * pdev = NULL;
|
|
CUPnPDeviceFoldPidl udfp;
|
|
|
|
hr = udfp.HrInit(pudfp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PCWSTR szUDN = udfp.PszGetUDNPointer();
|
|
Assert(szUDN);
|
|
BSTR bstrUDN = ::SysAllocString(szUDN);
|
|
if (bstrUDN)
|
|
{
|
|
hr = pdf->FindByUDN(bstrUDN, &pdev);
|
|
if (S_OK == hr)
|
|
{
|
|
BSTR bstrUrl;
|
|
|
|
hr = pdev->get_PresentationURL(&bstrUrl);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Note: PresentationURL might be NULL
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
Assert(bstrUrl);
|
|
|
|
szUrl = TszFromWsz(bstrUrl);
|
|
}
|
|
|
|
SysFreeString(bstrUrl);
|
|
}
|
|
|
|
ReleaseObj(pdev);
|
|
}
|
|
else if (hr == S_FALSE)
|
|
{
|
|
PTSTR pszText = NULL;
|
|
PTSTR pszTitle = NULL;
|
|
|
|
pszText = TszFromWsz(WszLoadIds(IDS_UPNPTRAYUI_DEVICE_OFFLINE_MSG));
|
|
pszTitle = TszFromWsz(WszLoadIds(IDS_UPNPTRAYUI_DEVICE_OFFLINE_TITLE));
|
|
|
|
if( pszText && pszTitle )
|
|
{
|
|
MessageBox(hwndOwner, pszText, pszTitle, MB_OK | MB_ICONWARNING );
|
|
|
|
}
|
|
|
|
delete pszText;
|
|
delete pszTitle;
|
|
|
|
TraceTag(ttidError,
|
|
"Can not bring up control page for device UDN=%S because FindByUDN returns S_FALSE.",
|
|
szUDN);
|
|
}
|
|
|
|
::SysFreeString(bstrUDN);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
TraceError("HrOnCommandInvoke: SysAllocString", hr);
|
|
}
|
|
}
|
|
|
|
ReleaseObj(pdf);
|
|
}
|
|
|
|
if (szUrl)
|
|
{
|
|
SHELLEXECUTEINFO sei = {0};
|
|
|
|
// Check these masks if we ever need to use different icons and such
|
|
// for the instances that we launch. SEE_MASK_ICON is a possibility.
|
|
// SEE_MASK_FLAG_NO_UI can be used if we don't want to show an error
|
|
// on failure.
|
|
//
|
|
sei.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
sei.fMask = SEE_MASK_FLAG_DDEWAIT;
|
|
sei.hwnd = hwndOwner;
|
|
sei.lpFile = szUrl;
|
|
sei.nShow = SW_SHOW;
|
|
|
|
fResult = ShellExecuteEx(&sei);
|
|
if (!fResult)
|
|
{
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
|
|
delete [] szUrl;
|
|
}
|
|
|
|
TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandInvoke");
|
|
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(
|
|
LPITEMIDLIST * apidl,
|
|
ULONG cidl,
|
|
HWND hwndOwner,
|
|
LPSHELLFOLDER psf)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PUPNPDEVICEFOLDPIDL pudfp = ConvertToUPnPDevicePIDL(apidl[0]);
|
|
IUPnPDeviceFinder * pdf = NULL;
|
|
|
|
Assert(pudfp);
|
|
Assert(cidl > 0);
|
|
|
|
// instantiate device finder
|
|
hr = CoCreateInstance(
|
|
CLSID_UPnPDeviceFinder,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IUPnPDeviceFinder,
|
|
(LPVOID *)&pdf
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CUPnPDeviceFoldPidl udfp;
|
|
|
|
hr = udfp.HrInit(pudfp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// retrieve the device object associated with UDN
|
|
|
|
IUPnPDevice * pdev = NULL;
|
|
PCWSTR szUDN = udfp.PszGetUDNPointer();
|
|
Assert(szUDN);
|
|
BSTR bstrUDN = ::SysAllocString(szUDN);
|
|
if (bstrUDN)
|
|
{
|
|
hr = pdf->FindByUDN(bstrUDN, &pdev);
|
|
if (hr == S_OK)
|
|
{
|
|
NewDeviceNode * pNDN = NULL;
|
|
|
|
// convert device object to device node
|
|
hr = HrCreateDeviceNodeFromDevice(pdev, &pNDN);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// display property pages for given device node
|
|
hr = HrCreateDevicePropertySheets(hwndOwner, pNDN);
|
|
|
|
// nuke device node
|
|
delete pNDN;
|
|
}
|
|
|
|
ReleaseObj(pdev);
|
|
}
|
|
else if (hr == S_FALSE)
|
|
{
|
|
PTSTR pszText = NULL;
|
|
PTSTR pszTitle = NULL;
|
|
|
|
pszText = TszFromWsz(WszLoadIds(IDS_UPNPTRAYUI_DEVICE_OFFLINE_MSG));
|
|
pszTitle = TszFromWsz(WszLoadIds(IDS_UPNPTRAYUI_DEVICE_OFFLINE_TITLE));
|
|
|
|
if( pszText && pszTitle )
|
|
{
|
|
MessageBox(hwndOwner, pszText, pszTitle, MB_OK | MB_ICONWARNING);
|
|
}
|
|
|
|
delete pszText;
|
|
delete pszTitle;
|
|
|
|
TraceTag(ttidError,
|
|
"Can not bring up property for device UDN=%S because"
|
|
" FindByUDN returns S_FALSE.",
|
|
szUDN);
|
|
}
|
|
::SysFreeString(bstrUDN);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
TraceError("HrOnCommandInvoke: SysAllocString", hr);
|
|
}
|
|
}
|
|
|
|
ReleaseObj(pdf);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandProperties");
|
|
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(
|
|
LPITEMIDLIST * apidl,
|
|
ULONG cidl,
|
|
HWND hwndOwner,
|
|
LPSHELLFOLDER psf)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwLoop = 0;
|
|
INT iMBResult = 0;
|
|
|
|
#if 0
|
|
// Bring up the prompt for the delete
|
|
//
|
|
if (cidl > 1)
|
|
{
|
|
WCHAR wszItemCount[8];
|
|
|
|
// Convert the item count to a string
|
|
//
|
|
_itow( cidl, 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);
|
|
}
|
|
else if (cidl == 1)
|
|
{
|
|
PCCONFOLDENTRY pccfe = NULL;
|
|
|
|
// Convert the pidl to a confoldentry, and use the name
|
|
// to bring up the confirm message box
|
|
//
|
|
hr = HrPidlToCConFoldEntry(apidl[0], &pccfe);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Don't let them try to delete a wizard
|
|
//
|
|
if (pccfe->m_fWizard)
|
|
{
|
|
NcMsgBox(
|
|
_Module.GetResourceInstance(),
|
|
NULL,
|
|
IDS_CONFOLD_ERROR_DELETE_CAPTION,
|
|
IDS_CONFOLD_ERROR_DELETE_WIZARD,
|
|
MB_ICONEXCLAMATION);
|
|
|
|
delete pccfe;
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
// Check to see if this connection is in the process of activating.
|
|
// If so, then we won't allow the delete.
|
|
//
|
|
hr = HrCheckForActivation(NULL, pccfe, &fActivating);
|
|
if (S_OK == hr)
|
|
{
|
|
if (!fActivating)
|
|
{
|
|
if ((pccfe->m_ncs == NCS_CONNECTING) ||
|
|
(pccfe->m_ncs == NCS_CONNECTED) ||
|
|
(pccfe->m_ncs == 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);
|
|
|
|
delete pccfe;
|
|
goto Exit;
|
|
}
|
|
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,
|
|
pccfe->m_pszName);
|
|
}
|
|
}
|
|
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);
|
|
|
|
delete pccfe;
|
|
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)
|
|
{
|
|
delete pccfe;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
delete pccfe;
|
|
pccfe = NULL;
|
|
}
|
|
}
|
|
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);
|
|
LPITEMIDLIST pidlFolder = pcf ? pcf->PidlGetFolderRoot() : NULL;
|
|
BOOL fShowActivationWarning = FALSE;
|
|
BOOL fShowNotDeletableWarning = FALSE;
|
|
|
|
Assert(pidlFolder);
|
|
|
|
for (dwLoop = 0; dwLoop < cidl; dwLoop++)
|
|
{
|
|
PCCONFOLDENTRY pccfe = NULL;
|
|
|
|
hr = HrPidlToCConFoldEntry(apidl[dwLoop], &pccfe);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// If this is a LAN connection the user doesn't have rights
|
|
//
|
|
if ((NCM_LAN == pccfe->m_ncm) || (pccfe->m_fWizard))
|
|
{
|
|
fShowNotDeletableWarning = TRUE;
|
|
continue;
|
|
}
|
|
|
|
// If this is a RAS connection and the user doesn't have rights
|
|
// then skip
|
|
//
|
|
if (NCM_LAN != pccfe->m_ncm)
|
|
{
|
|
if ((!FHasPermission(NCPERM_DeleteConnection)) ||
|
|
((pccfe->m_dwCharacteristics & NCCF_ALL_USERS) &&
|
|
!FHasPermission(NCPERM_DeleteAllUserConnection)))
|
|
{
|
|
fShowNotDeletableWarning = TRUE;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
hr = HrCheckForActivation(NULL, pccfe, &fActivating);
|
|
if (S_OK == hr)
|
|
{
|
|
// Only allow deletion if this connection is inactive and
|
|
// it allows removal.
|
|
//
|
|
if (fActivating || (pccfe->m_ncs == NCS_CONNECTING) ||
|
|
(pccfe->m_ncs == NCS_CONNECTED) ||
|
|
(pccfe->m_ncs == NCS_DISCONNECTING))
|
|
{
|
|
fShowActivationWarning = TRUE;
|
|
}
|
|
else if (pccfe->m_dwCharacteristics & NCCF_ALLOW_REMOVAL)
|
|
{
|
|
hr = HrNetConFromPidl(apidl[dwLoop], &pNetCon);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pNetCon->Delete();
|
|
if (SUCCEEDED(hr) && pcf)
|
|
{
|
|
hr = HrDeleteFromCclAndNotifyShell(pidlFolder, apidl[dwLoop], pccfe);
|
|
}
|
|
|
|
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 == cidl) ?
|
|
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 == cidl) ?
|
|
IDS_CONFOLD_ERROR_DELETE_ACTIVE :
|
|
IDS_CONFOLD_ERROR_DELETE_ACTIVE_MULTI,
|
|
MB_ICONEXCLAMATION);
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
#endif
|
|
TraceError("HrOnCommandDelete", hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrCreateShortcutWithPath(
|
|
LPITEMIDLIST * apidl,
|
|
ULONG cidl,
|
|
HWND hwndOwner,
|
|
LPSHELLFOLDER psf,
|
|
PCWSTR pszDir)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPDATAOBJECT pdtobj = NULL;
|
|
LPITEMIDLIST * apidlInternal = NULL;
|
|
ULONG cidlInternal = 0;
|
|
DWORD dwLoop = 0;
|
|
|
|
if (cidl > 0)
|
|
{
|
|
apidlInternal = new LPITEMIDLIST[cidl];
|
|
if (apidlInternal)
|
|
{
|
|
for (;dwLoop < cidl; dwLoop++)
|
|
{
|
|
apidlInternal[cidlInternal++] = apidl[dwLoop];
|
|
}
|
|
|
|
hr = psf->GetUIObjectOf(
|
|
hwndOwner,
|
|
cidlInternal,
|
|
(LPCITEMIDLIST *) 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: 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(
|
|
LPITEMIDLIST * apidl,
|
|
ULONG cidl,
|
|
HWND hwndOwner,
|
|
LPSHELLFOLDER psf)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrCreateShortcutWithPath( apidl,
|
|
cidl,
|
|
hwndOwner,
|
|
psf,
|
|
NULL);
|
|
|
|
TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandCreateShortcut");
|
|
return hr;
|
|
}
|
|
|