mirror of
https://github.com/reactos/reactos.git
synced 2025-04-25 16:10:29 +00:00
[SHELL32] Separate CCopyAsPathMenu implementation from CCopyMoveToMenu
This commit is contained in:
parent
f9325370f5
commit
d4ca55f65e
6 changed files with 195 additions and 174 deletions
152
dll/win32/shell32/CCopyAsPathMenu.cpp
Normal file
152
dll/win32/shell32/CCopyAsPathMenu.cpp
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS shell32
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Copy as Path Menu implementation
|
||||||
|
* COPYRIGHT: Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
static DWORD
|
||||||
|
SetClipboard(UINT cf, const void* data, SIZE_T size)
|
||||||
|
{
|
||||||
|
BOOL succ = FALSE;
|
||||||
|
HGLOBAL handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
|
||||||
|
if (handle)
|
||||||
|
{
|
||||||
|
LPVOID clipdata = GlobalLock(handle);
|
||||||
|
if (clipdata)
|
||||||
|
{
|
||||||
|
CopyMemory(clipdata, data, size);
|
||||||
|
GlobalUnlock(handle);
|
||||||
|
if (OpenClipboard(NULL))
|
||||||
|
{
|
||||||
|
EmptyClipboard();
|
||||||
|
succ = SetClipboardData(cf, handle) != NULL;
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!succ)
|
||||||
|
{
|
||||||
|
GlobalFree(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return succ ? ERROR_SUCCESS : GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD
|
||||||
|
SetClipboardFromString(LPCWSTR str)
|
||||||
|
{
|
||||||
|
SIZE_T cch = lstrlenW(str) + 1, size = cch * sizeof(WCHAR);
|
||||||
|
if (size > cch)
|
||||||
|
return SetClipboard(CF_UNICODETEXT, str, size);
|
||||||
|
else
|
||||||
|
return ERROR_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AppendToPathList(CStringW &paths, LPCWSTR path, DWORD index)
|
||||||
|
{
|
||||||
|
if (index)
|
||||||
|
paths += L"\r\n";
|
||||||
|
LPCWSTR quote = StrChrW(path, L' ');
|
||||||
|
if (quote)
|
||||||
|
paths += L'\"';
|
||||||
|
paths += path;
|
||||||
|
if (quote)
|
||||||
|
paths += L'\"';
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP
|
||||||
|
CCopyAsPathMenu::Drop(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
CStringW paths;
|
||||||
|
DWORD i, count;
|
||||||
|
#if 0
|
||||||
|
CComPtr<IShellItemArray> array;
|
||||||
|
HRESULT hr = SHCreateShellItemArrayFromDataObject(pdto, IID_PPV_ARG(IShellItemArray, &array));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
for (i = 0, array->GetCount(&count); i < count && SUCCEEDED(hr); ++i)
|
||||||
|
{
|
||||||
|
CComPtr<IShellItem> item;
|
||||||
|
hr = array->GetItemAt(i, &item);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
CComHeapPtr<WCHAR> path;
|
||||||
|
hr = item->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &path);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
AppendToPathList(paths, path, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
FIXME("Implement and use SHCreateShellItemArrayFromDataObject\n");
|
||||||
|
CDataObjectHIDA pCIDA(pdto);
|
||||||
|
HRESULT hr = pCIDA.hr();
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
for (i = 0, count = pCIDA->cidl; i < count && SUCCEEDED(hr); ++i)
|
||||||
|
{
|
||||||
|
PCUIDLIST_ABSOLUTE folder = HIDA_GetPIDLFolder(pCIDA);
|
||||||
|
PCUIDLIST_RELATIVE item = HIDA_GetPIDLItem(pCIDA, i);
|
||||||
|
CComHeapPtr<ITEMIDLIST> full;
|
||||||
|
hr = SHILCombine(folder, item, &full);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
PCUITEMID_CHILD child;
|
||||||
|
CComPtr<IShellFolder> sf;
|
||||||
|
hr = SHBindToParent(full, IID_PPV_ARG(IShellFolder, &sf), &child);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
STRRET strret;
|
||||||
|
hr = sf->GetDisplayNameOf(child, SHGDN_FORPARSING, &strret);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
CComHeapPtr<WCHAR> path;
|
||||||
|
hr = StrRetToStrW(&strret, child, &path);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
AppendToPathList(paths, path, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FORMATETC fmte = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
STGMEDIUM stgm;
|
||||||
|
hr = pdto->GetData(&fmte, &stgm);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
for (i = 0, count = DragQueryFileW((HDROP)stgm.hGlobal, -1, NULL, 0); i < count && SUCCEEDED(hr); ++i)
|
||||||
|
{
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
if (DragQueryFileW((HDROP)stgm.hGlobal, i, path, _countof(path)))
|
||||||
|
{
|
||||||
|
AppendToPathList(paths, path, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReleaseStgMedium(&stgm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DWORD err = SetClipboardFromString(paths);
|
||||||
|
hr = HRESULT_FROM_WIN32(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
*pdwEffect &= DROPEFFECT_COPY;
|
||||||
|
else
|
||||||
|
*pdwEffect &= DROPEFFECT_NONE;
|
||||||
|
return hr;
|
||||||
|
}
|
41
dll/win32/shell32/CCopyAsPathMenu.h
Normal file
41
dll/win32/shell32/CCopyAsPathMenu.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS shell32
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Copy as Path Menu implementation
|
||||||
|
* COPYRIGHT: Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CCopyAsPathMenu :
|
||||||
|
public CComCoClass<CCopyAsPathMenu, &CLSID_CopyAsPathMenu>,
|
||||||
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
|
public IDropTarget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_REGISTRY_RESOURCEID(IDR_COPYASPATHMENU)
|
||||||
|
DECLARE_NOT_AGGREGATABLE(CCopyAsPathMenu)
|
||||||
|
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CCopyAsPathMenu)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
|
||||||
|
END_COM_MAP()
|
||||||
|
|
||||||
|
// IDropTarget
|
||||||
|
STDMETHODIMP DragEnter(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
*pdwEffect &= DROPEFFECT_COPY;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
STDMETHODIMP DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
*pdwEffect &= DROPEFFECT_COPY;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
STDMETHODIMP DragLeave()
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
STDMETHODIMP Drop(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect);
|
||||||
|
};
|
|
@ -436,145 +436,3 @@ CCopyMoveToMenu::GetSite(REFIID riid, void **ppvSite)
|
||||||
|
|
||||||
return m_pSite->QueryInterface(riid, ppvSite);
|
return m_pSite->QueryInterface(riid, ppvSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD
|
|
||||||
SetClipboard(UINT cf, const void* data, SIZE_T size)
|
|
||||||
{
|
|
||||||
BOOL succ = FALSE;
|
|
||||||
HGLOBAL handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
LPVOID clipdata = GlobalLock(handle);
|
|
||||||
if (clipdata)
|
|
||||||
{
|
|
||||||
CopyMemory(clipdata, data, size);
|
|
||||||
GlobalUnlock(handle);
|
|
||||||
if (OpenClipboard(NULL))
|
|
||||||
{
|
|
||||||
EmptyClipboard();
|
|
||||||
succ = SetClipboardData(cf, handle) != NULL;
|
|
||||||
CloseClipboard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!succ)
|
|
||||||
{
|
|
||||||
GlobalFree(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return succ ? ERROR_SUCCESS : GetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
static DWORD
|
|
||||||
SetClipboardFromString(LPCWSTR str)
|
|
||||||
{
|
|
||||||
SIZE_T cch = lstrlenW(str) + 1, size = cch * sizeof(WCHAR);
|
|
||||||
if (size > cch)
|
|
||||||
return SetClipboard(CF_UNICODETEXT, str, size);
|
|
||||||
else
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
AppendToPathList(CStringW &paths, LPCWSTR path, DWORD index)
|
|
||||||
{
|
|
||||||
if (index)
|
|
||||||
paths += L"\r\n";
|
|
||||||
LPCWSTR quote = StrChrW(path, L' ');
|
|
||||||
if (quote)
|
|
||||||
paths += L'\"';
|
|
||||||
paths += path;
|
|
||||||
if (quote)
|
|
||||||
paths += L'\"';
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP
|
|
||||||
CCopyAsPathMenu::Drop(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
|
|
||||||
{
|
|
||||||
CStringW paths;
|
|
||||||
DWORD i, count;
|
|
||||||
#if 0
|
|
||||||
CComPtr<IShellItemArray> array;
|
|
||||||
HRESULT hr = SHCreateShellItemArrayFromDataObject(pdto, IID_PPV_ARG(IShellItemArray, &array));
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
for (i = 0, array->GetCount(&count); i < count && SUCCEEDED(hr); ++i)
|
|
||||||
{
|
|
||||||
CComPtr<IShellItem> item;
|
|
||||||
hr = array->GetItemAt(i, &item);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
CComHeapPtr<WCHAR> path;
|
|
||||||
hr = item->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &path);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
AppendToPathList(paths, path, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
FIXME("Implement and use SHCreateShellItemArrayFromDataObject\n");
|
|
||||||
CDataObjectHIDA pCIDA(pdto);
|
|
||||||
HRESULT hr = pCIDA.hr();
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
for (i = 0, count = pCIDA->cidl; i < count && SUCCEEDED(hr); ++i)
|
|
||||||
{
|
|
||||||
PCUIDLIST_ABSOLUTE folder = HIDA_GetPIDLFolder(pCIDA);
|
|
||||||
PCUIDLIST_RELATIVE item = HIDA_GetPIDLItem(pCIDA, i);
|
|
||||||
CComHeapPtr<ITEMIDLIST> full;
|
|
||||||
hr = SHILCombine(folder, item, &full);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
PCUITEMID_CHILD child;
|
|
||||||
CComPtr<IShellFolder> sf;
|
|
||||||
hr = SHBindToParent(full, IID_PPV_ARG(IShellFolder, &sf), &child);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
STRRET strret;
|
|
||||||
hr = sf->GetDisplayNameOf(child, SHGDN_FORPARSING, &strret);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
CComHeapPtr<WCHAR> path;
|
|
||||||
hr = StrRetToStrW(&strret, child, &path);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
AppendToPathList(paths, path, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FORMATETC fmte = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
|
||||||
STGMEDIUM stgm;
|
|
||||||
hr = pdto->GetData(&fmte, &stgm);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
for (i = 0, count = DragQueryFileW((HDROP)stgm.hGlobal, -1, NULL, 0); i < count && SUCCEEDED(hr); ++i)
|
|
||||||
{
|
|
||||||
WCHAR path[MAX_PATH];
|
|
||||||
if (DragQueryFileW((HDROP)stgm.hGlobal, i, path, _countof(path)))
|
|
||||||
{
|
|
||||||
AppendToPathList(paths, path, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ReleaseStgMedium(&stgm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
DWORD err = SetClipboardFromString(paths);
|
|
||||||
hr = HRESULT_FROM_WIN32(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
*pdwEffect &= DROPEFFECT_COPY;
|
|
||||||
else
|
|
||||||
*pdwEffect &= DROPEFFECT_NONE;
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
|
@ -109,35 +109,3 @@ public:
|
||||||
UINT GetFileOp() const override { return FO_MOVE; }
|
UINT GetFileOp() const override { return FO_MOVE; }
|
||||||
LPCSTR GetVerb() const override { return "moveto"; }
|
LPCSTR GetVerb() const override { return "moveto"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class CCopyAsPathMenu
|
|
||||||
: public CComCoClass<CCopyAsPathMenu, &CLSID_CopyAsPathMenu>
|
|
||||||
, public CComObjectRootEx<CComMultiThreadModelNoCS>
|
|
||||||
, public IDropTarget
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DECLARE_REGISTRY_RESOURCEID(IDR_COPYASPATHMENU)
|
|
||||||
DECLARE_NOT_AGGREGATABLE(CCopyAsPathMenu)
|
|
||||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
|
||||||
|
|
||||||
BEGIN_COM_MAP(CCopyAsPathMenu)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
|
|
||||||
END_COM_MAP()
|
|
||||||
|
|
||||||
// IDropTarget
|
|
||||||
STDMETHODIMP DragEnter(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
|
|
||||||
{
|
|
||||||
*pdwEffect &= DROPEFFECT_COPY;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
STDMETHODIMP DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
|
|
||||||
{
|
|
||||||
*pdwEffect &= DROPEFFECT_COPY;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
STDMETHODIMP DragLeave()
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
STDMETHODIMP Drop(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect);
|
|
||||||
};
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ list(APPEND SOURCE
|
||||||
CNewMenu.cpp
|
CNewMenu.cpp
|
||||||
CSendToMenu.cpp
|
CSendToMenu.cpp
|
||||||
CCopyMoveToMenu.cpp
|
CCopyMoveToMenu.cpp
|
||||||
|
CCopyAsPathMenu.cpp
|
||||||
CShellDispatch.cpp
|
CShellDispatch.cpp
|
||||||
CFolder.cpp
|
CFolder.cpp
|
||||||
CFolderItems.cpp
|
CFolderItems.cpp
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
#include "CNewMenu.h"
|
#include "CNewMenu.h"
|
||||||
#include "CSendToMenu.h"
|
#include "CSendToMenu.h"
|
||||||
#include "CCopyMoveToMenu.h"
|
#include "CCopyMoveToMenu.h"
|
||||||
|
#include "CCopyAsPathMenu.h"
|
||||||
#include "dialogs/filedefext.h"
|
#include "dialogs/filedefext.h"
|
||||||
#include "dialogs/drvdefext.h"
|
#include "dialogs/drvdefext.h"
|
||||||
#include "CQueryAssociations.h"
|
#include "CQueryAssociations.h"
|
||||||
|
|
Loading…
Reference in a new issue