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);


Reply via email to