Author: gadamopoulos Date: Thu Oct 22 15:23:21 2015 New Revision: 69647 URL: http://svn.reactos.org/svn/reactos?rev=69647&view=rev Log: [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
Modified: trunk/reactos/dll/win32/shell32/CDefView.cpp trunk/reactos/dll/win32/shell32/CDefaultContextMenu.cpp trunk/reactos/dll/win32/shell32/folders/CRecycleBin.cpp trunk/reactos/dll/win32/shell32/folders/CRecycleBin.h Modified: trunk/reactos/dll/win32/shell32/CDefView.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/CDefView.cpp?rev=69647&r1=69646&r2=69647&view=diff ============================================================================== --- trunk/reactos/dll/win32/shell32/CDefView.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/CDefView.cpp [iso-8859-1] Thu Oct 22 15:23:21 2015 @@ -151,6 +151,7 @@ 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 @@ 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 @@ 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 @@ WORD y; UINT uCommand; HMENU hMenu; - CMINVOKECOMMANDINFO cmi; HRESULT hResult; // for some reason I haven't figured out, we sometimes recurse into this method @@ -1339,9 +1351,6 @@ hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL); 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, @@ -1352,14 +1361,9 @@ 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 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection) { HRESULT hResult; - CMINVOKECOMMANDINFO cmi; HMENU hMenu; hMenu = CreatePopupMenu(); @@ -1387,14 +1390,9 @@ 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(); Modified: trunk/reactos/dll/win32/shell32/CDefaultContextMenu.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/CDefaultContextMenu.cpp?rev=69647&r1=69646&r2=69647&view=diff ============================================================================== --- trunk/reactos/dll/win32/shell32/CDefaultContextMenu.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/CDefaultContextMenu.cpp [iso-8859-1] Thu Oct 22 15:23:21 2015 @@ -1165,19 +1165,9 @@ 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; } Modified: trunk/reactos/dll/win32/shell32/folders/CRecycleBin.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/folders/CRecycleBin.cpp?rev=69647&r1=69646&r2=69647&view=diff ============================================================================== --- trunk/reactos/dll/win32/shell32/folders/CRecycleBin.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/folders/CRecycleBin.cpp [iso-8859-1] Thu Oct 22 15:23:21 2015 @@ -1030,10 +1030,14 @@ 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 @@ 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 @@ 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) { @@ -1174,6 +1166,35 @@ ReleaseStgMedium(&medium); 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); } /************************************************************************* Modified: trunk/reactos/dll/win32/shell32/folders/CRecycleBin.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/folders/CRecycleBin.h?rev=69647&r1=69646&r2=69647&view=diff ============================================================================== --- trunk/reactos/dll/win32/shell32/folders/CRecycleBin.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/folders/CRecycleBin.h [iso-8859-1] Thu Oct 22 15:23:21 2015 @@ -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);