[SHELL32]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Thu, 22 Oct 2015 15:23:21 +0000 (15:23 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Thu, 22 Oct 2015 15:23:21 +0000 (15:23 +0000)
- 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

reactos/dll/win32/shell32/CDefView.cpp
reactos/dll/win32/shell32/CDefaultContextMenu.cpp
reactos/dll/win32/shell32/folders/CRecycleBin.cpp
reactos/dll/win32/shell32/folders/CRecycleBin.h

index 84c718a..1bb5b49 100644 (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();
 
index edfbb40..5f041cd 100644 (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;
 }
 
index 54bd366..374cd1a 100644 (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.@)
  */
index 5a0a9ec..ba32ff5 100644 (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);