reactos/dll/win32/shell32/CDefViewBckgrndMenu.cpp
Joachim Henze 93ccb203ef [0.4.10][SHELL32] Backport format+logging-trivia, ARRAYSIZE/_countof
Picks various trivial improvements from newer branches, does not fix specific JIRA-tickets and also doesn't
*entirely* cover a specific PR, therefore none of those are mentioned here.
Main motivation is to reduce large scale white-noise diff between the branches, to make
future commits diffs (with some fixes that actually matter) smaller in size and therefore easier to review.

Specifically:
- large-scale formatting & logging improvements, including but not limited to 0.4.15-dev-7653-g 6f91b6c0fe
- strip trailing whitespace
- also typos like 'unkown', missing \n as it was
  part of 0.4.15-dev-6323-g 3854a5d8e9 and
  0.4.15-dev-4492-g 03422451b3
  (I left out the MOUSE_MOVE-one from that, because I consider the missing \n there intentional)
- ports back many usages of ARRAYSIZE/_countof as it was added as part of some commits from Hermes, e.g.:
  *partial* pick of 0.4.13-dev-622-g 8a30801516 and
  *partial* pick of 0.4.15-dev-3642-g 83be315abf (I left out the literals here for now, ...
    I *might* pick them later on their own, but not now. I first want to verify their isolated impact on all compilers generated file-sizes.
    Some of those changes would even increase the binary size, especially those where the same literal is used multiple times,
    because string-pooling is currently not enabled for all toolchains and configurations.)
- COpenWithMenu.cpp: strip double-semicolon
- COpenWithMenu.cpp && folder_options.cpp: add \n to some dbg-prints without increasing their length
- CFSDropTarget.cpp: add \n to some dbg-prints, strip some good-path-traces that are no longer present in master in return to avoid size increase, fix indentation
- CShellLink.cpp: add \n to some dbg-prints without increasing their length
- iconcache.cpp: fix wrong indentation
- shlfileop.cpp: partially pick 0.4.15-dev-7388-g d689cfe158 just the stripping of #ifdef __REACTOS__ but NOT the actual fix! (the ifdefs were only present in 0.4.14)
- 0.4.10 and lower: shellpath.c Strip some TRACEs with wrong format-strings, strip unused string my_DocumentsW

binary size of shell32.dll has tendency to shrink slightly, which is caused solely by the logging changes:

master          RosBEWin2.2.2 GCC8.4.0 dbg x86               10.538.496 (0.4.15-dev-7640-gbdcfc6b)
releases/0.4.14 RosBEWin2.2.2 GCC8.4.0 dbg x86  9.317.888 ->  9.316.684
releases/0.4.14 RosBEWin2.1.6 GCC4.7.2 dbg x86  9.345.024 ->  9.345.024
releases/0.4.13 RosBEWin2.1.6 GCC4.7.2 dbg x86  9.201.152 ->  9.200.640
releases/0.4.12 RosBEWin2.1.6 GCC4.7.2 dbg x86  9.146.880 ->  9.146.880
releases/0.4.11 RosBEWin2.1.6 GCC4.7.2 dbg x86  9.077.760 ->  9.077.248
releases/0.4.10 RosBEWin2.1.6 GCC4.7.2 dbg x86  9.074.176 ->  9.072.128
releases/0.4. 9 RosBEWin2.1.6 GCC4.7.2 dbg x86  8.825.856 ->  8.824.832
releases/0.4. 8 RosBEWin2.1.6 GCC4.7.2 dbg x86  8.740.864 ->  8.738.816
releases/0.4. 7 RosBEWin2.1.6 GCC4.7.2 dbg x86  8.668.160 ->  8.666.624
2024-02-25 01:50:03 +01:00

337 lines
10 KiB
C++

/*
* PROJECT: shell32
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll/win32/shell32/CDefViewBckgrndMenu.cpp
* PURPOSE: background context menu of the CDefView
* PROGRAMMERS: Giannis Adamopoulos
*/
#include <precomp.h>
WINE_DEFAULT_DEBUG_CHANNEL(shell);
class CDefViewBckgrndMenu :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IContextMenu3,
public IObjectWithSite
{
private:
CComPtr<IUnknown> m_site;
CComPtr<IShellFolder> m_psf;
CComPtr<IContextMenu> m_folderCM;
UINT m_idCmdFirst;
UINT m_LastFolderCMId;
BOOL _bIsDesktopBrowserMenu();
BOOL _bCanPaste();
public:
CDefViewBckgrndMenu();
~CDefViewBckgrndMenu();
HRESULT Initialize(IShellFolder* psf);
// IContextMenu
virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen);
// IContextMenu2
virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
// IContextMenu3
virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
// IObjectWithSite
virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
BEGIN_COM_MAP(CDefViewBckgrndMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
END_COM_MAP()
};
CDefViewBckgrndMenu::CDefViewBckgrndMenu()
{
m_idCmdFirst = 0;
m_LastFolderCMId = 0;
}
CDefViewBckgrndMenu::~CDefViewBckgrndMenu()
{
}
BOOL CDefViewBckgrndMenu::_bIsDesktopBrowserMenu()
{
if (!m_site)
return FALSE;
/* Get a pointer to the shell browser */
CComPtr<IShellView> psv;
HRESULT hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
if (FAILED_UNEXPECTEDLY(hr))
return FALSE;
FOLDERSETTINGS FolderSettings;
hr = psv->GetCurrentInfo(&FolderSettings);
if (FAILED_UNEXPECTEDLY(hr))
return FALSE;
return ((FolderSettings.fFlags & FWF_DESKTOP) == FWF_DESKTOP);
}
BOOL CDefViewBckgrndMenu::_bCanPaste()
{
/* If the folder doesn't have a drop target we can't paste */
CComPtr<IDropTarget> pdt;
HRESULT hr = m_psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt));
if (FAILED(hr))
return FALSE;
/* We can only paste if CFSTR_SHELLIDLIST is present in the clipboard */
CComPtr<IDataObject> pDataObj;
hr = OleGetClipboard(&pDataObj);
if (FAILED(hr))
return FALSE;
STGMEDIUM medium;
FORMATETC formatetc;
/* Set the FORMATETC structure*/
InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
hr = pDataObj->GetData(&formatetc, &medium);
if (FAILED(hr))
return FALSE;
ReleaseStgMedium(&medium);
return TRUE;
}
HRESULT
CDefViewBckgrndMenu::Initialize(IShellFolder* psf)
{
m_psf = psf;
/* Get the context menu of the folder. Do it here because someone may call
InvokeCommand without calling QueryContextMenu. It is fine if this fails */
m_psf->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &m_folderCM));
return S_OK;
}
HRESULT
WINAPI
CDefViewBckgrndMenu::SetSite(IUnknown *pUnkSite)
{
m_site = pUnkSite;
if(m_folderCM)
IUnknown_SetSite(m_folderCM, pUnkSite);
return S_OK;
}
HRESULT
WINAPI
CDefViewBckgrndMenu::GetSite(REFIID riid, void **ppvSite)
{
if (!m_site)
return E_FAIL;
return m_site->QueryInterface(riid, ppvSite);
}
HRESULT
WINAPI
CDefViewBckgrndMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
HRESULT hr;
HMENU hMenuPart;
UINT cIds = 0;
/* This is something the implementations of IContextMenu should never really do.
However CDefViewBckgrndMenu is more or less an overengineering result, its code could really be part of the
CDefView. Given this, I think that abusing the interface here is not that bad since only CDefView is the ony
user of this class. Here we need to do two things to keep things as simple as possible.
First we want the menu part added by the shell folder to be the first to add so as to make as few id translations
as possible. Second, we want to add the default part of the background menu without shifted ids, so as
to let the CDefView fill some parts like filling the arrange modes or checking the view mode. In order
for that to work we need to save idCmdFirst because our caller will pass id offsets to InvokeCommand.
This makes it impossible to concatenate the CDefViewBckgrndMenu with other menus since it abuses IContextMenu
but as stated above, its sole user is CDefView and should really be that way. */
m_idCmdFirst = idCmdFirst;
/* Let the shell folder add any items it wants to add in the background context menu */
if (m_folderCM)
{
hr = m_folderCM->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
if (SUCCEEDED(hr))
{
m_LastFolderCMId = LOWORD(hr);
cIds = m_LastFolderCMId;
}
else
{
WARN("QueryContextMenu failed!\n");
}
}
else
{
WARN("GetUIObjectOf didn't give any context menu!\n");
}
/* Load the default part of the background context menu */
hMenuPart = LoadMenuW(shell32_hInstance, L"MENU_002");
if (hMenuPart)
{
/* Don't show the view submenu for the desktop */
if (_bIsDesktopBrowserMenu())
{
DeleteMenu(hMenuPart, FCIDM_SHVIEW_VIEW, MF_BYCOMMAND);
}
/* Disable the paste options if it is not possible */
if (!_bCanPaste())
{
EnableMenuItem(hMenuPart, FCIDM_SHVIEW_INSERT, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hMenuPart, FCIDM_SHVIEW_INSERTLINK, MF_BYCOMMAND | MF_GRAYED);
}
/* merge general background context menu in */
Shell_MergeMenus(hMenu, GetSubMenu(hMenuPart, 0), indexMenu, 0, idCmdLast, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
DestroyMenu(hMenuPart);
}
else
{
ERR("Failed to load menu from resource!\n");
}
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds);
}
HRESULT
WINAPI
CDefViewBckgrndMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
UINT idCmd = LOWORD(lpcmi->lpVerb);
if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, CMDSTR_VIEWLISTA))
{
idCmd = FCIDM_SHVIEW_LISTVIEW;
}
else if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, CMDSTR_VIEWDETAILSA))
{
idCmd = FCIDM_SHVIEW_REPORTVIEW;
}
else if(HIWORD(lpcmi->lpVerb) != 0 || idCmd < m_LastFolderCMId)
{
if (m_folderCM)
{
return m_folderCM->InvokeCommand(lpcmi);
}
WARN("m_folderCM is NULL!\n");
return E_NOTIMPL;
}
else
{
/* The default part of the background menu doesn't have shifted ids so we need to convert the id offset to the real id */
idCmd += m_idCmdFirst;
}
/* The commands that are handled by the def view are forwarded to it */
switch (idCmd)
{
case FCIDM_SHVIEW_INSERT:
case FCIDM_SHVIEW_INSERTLINK:
if (m_folderCM)
{
lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd);
return m_folderCM->InvokeCommand(lpcmi);
}
WARN("m_folderCM is NULL!\n");
return E_NOTIMPL;
case FCIDM_SHVIEW_BIGICON:
case FCIDM_SHVIEW_SMALLICON:
case FCIDM_SHVIEW_LISTVIEW:
case FCIDM_SHVIEW_REPORTVIEW:
case 0x30: /* FIX IDS in resource files */
case 0x31:
case 0x32:
case 0x33:
case FCIDM_SHVIEW_AUTOARRANGE:
case FCIDM_SHVIEW_SNAPTOGRID:
case FCIDM_SHVIEW_REFRESH:
if (!m_site)
return E_FAIL;
/* Get a pointer to the shell browser */
CComPtr<IShellView> psv;
HRESULT hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
HWND hwndSV = NULL;
if (SUCCEEDED(psv->GetWindow(&hwndSV)))
SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(idCmd, 0), 0);
return S_OK;
}
ERR("Got unknown command id %ul\n", LOWORD(lpcmi->lpVerb));
return E_FAIL;
}
HRESULT
WINAPI
CDefViewBckgrndMenu::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
{
if (m_folderCM)
{
return m_folderCM->GetCommandString(idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
}
return E_NOTIMPL;
}
HRESULT
WINAPI
CDefViewBckgrndMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if(m_folderCM)
{
CComPtr<IContextMenu2> pfolderCM2;
HRESULT hr = m_folderCM->QueryInterface(IID_PPV_ARG(IContextMenu2, &pfolderCM2));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return pfolderCM2->HandleMenuMsg(uMsg, wParam, lParam);
}
return E_NOTIMPL;
}
HRESULT
WINAPI
CDefViewBckgrndMenu::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
{
if(m_folderCM)
{
CComPtr<IContextMenu3> pfolderCM3;
HRESULT hr = m_folderCM->QueryInterface(IID_PPV_ARG(IContextMenu3, &pfolderCM3));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return pfolderCM3->HandleMenuMsg2(uMsg, wParam, lParam, plResult);
}
return E_NOTIMPL;
}
HRESULT
CDefViewBckgrndMenu_CreateInstance(IShellFolder* psf, REFIID riid, void **ppv)
{
return ShellObjectCreatorInit<CDefViewBckgrndMenu>(psf, riid, ppv);
}