[SHELL32]

- Add DoDeleteAsync method that takes the data object and the fMask parameter from IContextMenu in order to distinguish if we need a permanent delete.
- CDefView: Properly add CMIC_MASK_SHIFT_DOWN and CMIC_MASK_CONTROL_DOWN flags when calling Invoke.
- CDefaultContextMenu: use DoDeleteAsync and pass fmask so as to make Shift+Delete shortcut to permanently delete files.
Note: GetKeyState sometimes returns wrong results but this doesn't concern the shell.
CORE-4365

svn path=/trunk/; revision=69647
This commit is contained in:
Giannis Adamopoulos 2015-10-22 15:23:21 +00:00
parent 359fa267cc
commit 3339ceb715
4 changed files with 66 additions and 58 deletions

View file

@ -151,6 +151,7 @@ class CDefView :
void OnDeactivate();
void DoActivate(UINT uState);
HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
HRESULT InvokeContextMenuCommand(UINT uCommand);
LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
// *** IOleWindow methods ***
@ -1250,13 +1251,30 @@ UINT CDefView::GetSelections()
return m_cidl;
}
HRESULT CDefView::InvokeContextMenuCommand(UINT uCommand)
{
CMINVOKECOMMANDINFO cmi;
ZeroMemory(&cmi, sizeof(cmi));
cmi.cbSize = sizeof(cmi);
cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
cmi.hwnd = m_hWnd;
if (GetKeyState(VK_SHIFT) & 0x8000)
cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
if (GetKeyState(VK_CONTROL) & 0x8000)
cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
return m_pCM->InvokeCommand(&cmi);
}
/**********************************************************
* ShellView_OpenSelectedItems()
*/
HRESULT CDefView::OpenSelectedItems()
{
HMENU hMenu;
CMINVOKECOMMANDINFO cmi;
UINT uCommand;
HRESULT hResult;
@ -1287,12 +1305,7 @@ HRESULT CDefView::OpenSelectedItems()
goto cleanup;
}
ZeroMemory(&cmi, sizeof(cmi));
cmi.cbSize = sizeof(cmi);
cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
cmi.hwnd = m_hWnd;
hResult = m_pCM->InvokeCommand(&cmi);
InvokeContextMenuCommand(uCommand);
cleanup:
@ -1314,7 +1327,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
WORD y;
UINT uCommand;
HMENU hMenu;
CMINVOKECOMMANDINFO cmi;
HRESULT hResult;
// for some reason I haven't figured out, we sometimes recurse into this method
@ -1340,9 +1352,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
if (FAILED( hResult))
goto cleanup;
if (m_FolderSettings.fFlags & FWF_DESKTOP)
SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
uCommand = TrackPopupMenu(hMenu,
TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
x, y, 0, m_hWnd, NULL);
@ -1352,14 +1361,9 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
goto cleanup;
ZeroMemory(&cmi, sizeof(cmi));
cmi.cbSize = sizeof(cmi);
cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
cmi.hwnd = m_hWnd;
m_pCM->InvokeCommand(&cmi);
InvokeContextMenuCommand(uCommand);
cleanup:
if (m_pCM)
m_pCM.Release();
@ -1372,7 +1376,6 @@ cleanup:
LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
{
HRESULT hResult;
CMINVOKECOMMANDINFO cmi;
HMENU hMenu;
hMenu = CreatePopupMenu();
@ -1387,14 +1390,9 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
if (FAILED( hResult))
goto cleanup;
ZeroMemory(&cmi, sizeof(cmi));
cmi.cbSize = sizeof(cmi);
cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
cmi.hwnd = m_hWnd;
m_pCM->InvokeCommand(&cmi);
InvokeContextMenuCommand(uCommand);
cleanup:
if (m_pCM)
m_pCM.Release();

View file

@ -1165,19 +1165,9 @@ CDefaultContextMenu::DoCreateLink(
return S_OK;
}
HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi) {
TRACE("(%p) Deleting\n", this);
CComPtr<IDataObject> pDataObject;
if (SUCCEEDED(SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObject))))
{
IStream *s;
CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &s);
SHCreateThread(DoDeleteThreadProc, s, NULL, NULL);
}
else
return E_FAIL;
HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi)
{
DoDeleteAsync(m_pDataObj, lpcmi->fMask);
return S_OK;
}

View file

@ -1030,10 +1030,14 @@ HRESULT WINAPI CRecycleBin::Drop(IDataObject *pDataObject,
InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
/* Handle cfShellIDList Drop objects here, otherwise send the approriate message to other software */
if (SUCCEEDED(pDataObject->QueryGetData(&fmt))) {
IStream *s;
CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &s);
SHCreateThread(DoDeleteThreadProc, s, NULL, NULL);
if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
{
DWORD fMask = 0;
if ((dwKeyState & MK_SHIFT) == MK_SHIFT)
fMask |= CMIC_MASK_SHIFT_DOWN;
DoDeleteAsync(pDataObject, fMask);
}
else
{
@ -1045,20 +1049,7 @@ HRESULT WINAPI CRecycleBin::Drop(IDataObject *pDataObject,
return S_OK;
}
DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter)
{
CoInitialize(NULL);
CComPtr<IDataObject> pDataObject;
HRESULT hr = CoGetInterfaceAndReleaseStream (static_cast<IStream*>(lpParameter), IID_PPV_ARG(IDataObject, &pDataObject));
if (SUCCEEDED(hr))
{
DoDeleteDataObject(pDataObject);
}
CoUninitialize();
return 0;
}
HRESULT WINAPI DoDeleteDataObject(IDataObject *pda)
HRESULT WINAPI DoDeleteDataObject(IDataObject *pda, DWORD fMask)
{
TRACE("performing delete");
HRESULT hr;
@ -1160,7 +1151,8 @@ HRESULT WINAPI DoDeleteDataObject(IDataObject *pda)
ZeroMemory(&FileOp, sizeof(FileOp));
FileOp.wFunc = FO_DELETE;
FileOp.pFrom = pwszPaths;
FileOp.fFlags = FOF_ALLOWUNDO;
if ((fMask & CMIC_MASK_SHIFT_DOWN) == 0)
FileOp.fFlags = FOF_ALLOWUNDO;
if (SHFileOperationW(&FileOp) != 0)
{
@ -1176,6 +1168,35 @@ HRESULT WINAPI DoDeleteDataObject(IDataObject *pda)
return hr;
}
struct DeleteThreadData {
IStream *s;
DWORD fMask;
};
DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter)
{
DeleteThreadData *data = static_cast<DeleteThreadData*>(lpParameter);
CoInitialize(NULL);
IDataObject *pDataObject;
HRESULT hr = CoGetInterfaceAndReleaseStream (data->s, IID_PPV_ARG(IDataObject, &pDataObject));
if (SUCCEEDED(hr))
{
DoDeleteDataObject(pDataObject, data->fMask);
}
pDataObject->Release();
CoUninitialize();
HeapFree(GetProcessHeap(), 0, data);
return 0;
}
void DoDeleteAsync(IDataObject *pda, DWORD fMask)
{
DeleteThreadData *data = static_cast<DeleteThreadData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(DeleteThreadData)));
data->fMask = fMask;
CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pda, &data->s);
SHCreateThread(DoDeleteThreadProc, data, NULL, NULL);
}
/*************************************************************************
* SHEmptyRecycleBinA (SHELL32.@)
*/

View file

@ -22,8 +22,7 @@
#ifndef _SHFLDR_RECYCLEBIN_H_
#define _SHFLDR_RECYCLEBIN_H_
DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter);
HRESULT WINAPI DoDeleteDataObject(IDataObject *pda);
void DoDeleteAsync(IDataObject *pda, DWORD fMask);
BOOL TRASH_CanTrashFile(LPCWSTR wszPath);
BOOL TRASH_TrashFile(LPCWSTR wszPath);