[SHELL32]

- CDefaultContextMenu: Fix the implementation of the QueryContextMenu to respect how IContextMenu should function. Don't ignore idCmdFirst and idCmdLast parameters. Return a correct HRESULT. For now I'm not sure how 0 cmd ids should be handled and if the standard menu items should also be affected by these parameters.

svn path=/trunk/; revision=73591
This commit is contained in:
Giannis Adamopoulos 2017-01-24 16:35:36 +00:00
parent b40958162a
commit 2e07736507
2 changed files with 58 additions and 32 deletions

View file

@ -76,6 +76,8 @@ class CDefaultContextMenu :
PStaticShellEntry m_pStaticEntries; /* first static shell extension entry */
UINT m_iIdSCMFirst; /* first static used id */
UINT m_iIdSCMLast; /* last static used id */
UINT m_iIdCBFirst; /* first callback used id */
UINT m_iIdCBLast; /* last callback used id */
HRESULT _DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam);
void AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb);
@ -84,8 +86,7 @@ class CDefaultContextMenu :
HRESULT LoadDynamicContextMenuHandler(HKEY hKey, const CLSID *pclsid);
BOOL EnumerateDynamicContextHandlerForKey(HKEY hRootKey);
UINT InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, UINT IndexMenu, UINT idCmdFirst, UINT idCmdLast);
UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu);
UINT BuildShellItemContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu, UINT iIdCmdFirst, UINT iIdCmdLast);
HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink);
HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi);
@ -146,7 +147,9 @@ CDefaultContextMenu::CDefaultContextMenu() :
m_iIdSHELast(0),
m_pStaticEntries(NULL),
m_iIdSCMFirst(0),
m_iIdSCMLast(0)
m_iIdSCMLast(0),
m_iIdCBFirst(0),
m_iIdCBLast(0)
{
}
@ -470,8 +473,6 @@ CDefaultContextMenu::InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, U
}
PDynamicShellEntry pEntry = m_pDynamicEntries;
idCmdFirst = 0x5000;
idCmdLast = 0x6000;
m_iIdSHEFirst = idCmdFirst;
do
{
@ -482,6 +483,13 @@ CDefaultContextMenu::InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, U
pEntry->NumIds = LOWORD(hr);
IndexMenu += pEntry->NumIds;
idCmdFirst += pEntry->NumIds + 0x10;
if(idCmdFirst >= idCmdLast)
{
/* There is no more room for items */
idCmdFirst = idCmdLast;
break;
}
}
TRACE("pEntry %p hr %x contextmenu %p cmdfirst %x num ids %x\n", pEntry, hr, pEntry->pCM, pEntry->iIdCmdFirst, pEntry->NumIds);
pEntry = pEntry->pNext;
@ -495,7 +503,9 @@ CDefaultContextMenu::InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, U
UINT
CDefaultContextMenu::AddStaticContextMenusToMenu(
HMENU hMenu,
UINT IndexMenu)
UINT IndexMenu,
UINT iIdCmdFirst,
UINT iIdCmdLast)
{
MENUITEMINFOW mii;
UINT idResource;
@ -505,7 +515,7 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
mii.fType = MFT_STRING;
mii.wID = 0x4000;
mii.wID = iIdCmdFirst;
mii.dwTypeData = NULL;
m_iIdSCMFirst = mii.wID;
@ -590,6 +600,9 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
mii.wID++;
pEntry = pEntry->pNext;
if (mii.wID >= iIdCmdLast)
break;
}
m_iIdSCMLast = mii.wID - 1;
@ -645,6 +658,11 @@ CDefaultContextMenu::QueryContextMenu(
UINT uFlags)
{
HRESULT hr;
UINT idCmdNext = idCmdFirst;
/* Add a tiny hack to make all the shell happy until we understand how we should handle 0 ids */
if (!idCmdNext)
idCmdNext = 1;
TRACE("BuildShellItemContextMenu entered\n");
@ -656,35 +674,40 @@ CDefaultContextMenu::QueryContextMenu(
}
/* Add static context menu handlers */
IndexMenu = AddStaticContextMenusToMenu(hMenu, IndexMenu);
IndexMenu = AddStaticContextMenusToMenu(hMenu, IndexMenu, idCmdNext, idCmdLast);
if (m_iIdSCMLast && m_iIdSCMFirst != m_iIdSCMLast)
idCmdNext = m_iIdSCMLast + 1;
/* Add dynamic context menu handlers */
BOOL bAddSep = FALSE;
IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, idCmdFirst, idCmdLast);
TRACE("IndexMenu %d\n", IndexMenu);
IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, idCmdNext, idCmdLast);
if (m_iIdSHELast && m_iIdSHELast != m_iIdSHEFirst)
idCmdNext = m_iIdSHELast + 1;
/* Now let the callback add its own items */
QCMINFO qcminfo;
qcminfo.hmenu = hMenu;
qcminfo.indexMenu = IndexMenu;
qcminfo.idCmdFirst = idCmdFirst;
qcminfo.idCmdLast = idCmdLast;
qcminfo.pIdMap = NULL;
_DoCallback(DFM_MERGECONTEXTMENU, uFlags, &qcminfo);
QCMINFO qcminfo = {hMenu, IndexMenu, idCmdNext, idCmdLast, NULL};
if (SUCCEEDED(_DoCallback(DFM_MERGECONTEXTMENU, uFlags, &qcminfo)))
{
m_iIdCBFirst = idCmdNext;
m_iIdCBLast = qcminfo.idCmdFirst;
idCmdNext = m_iIdCBLast + 1;
}
/* The rest of the items will be added in the end of the menu */
IndexMenu = GetMenuItemCount(hMenu);
if (uFlags & CMF_VERBSONLY)
return S_OK;
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdNext - idCmdFirst);
/* If this is a background context menu we are done */
if (!m_cidl)
return S_OK;
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdNext - idCmdFirst);
/* Get the attributes of the items */
SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER;
hr = m_psf->GetAttributesOf(m_cidl, m_apidl, &rfg);
if (FAILED_UNEXPECTEDLY(hr))
return S_OK;
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdNext - idCmdFirst);
/* Add the standard menu entries based on the attributes of the items */
BOOL bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM));
@ -1206,9 +1229,6 @@ CDefaultContextMenu::InvokeCommand(
Result = DoCreateNewFolder(&LocalInvokeInfo);
break;
default:
_DoCallback(DFM_INVOKECOMMAND, LOWORD(LocalInvokeInfo.lpVerb), NULL);
Result = E_UNEXPECTED;
break;
}
@ -1216,21 +1236,27 @@ CDefaultContextMenu::InvokeCommand(
/* Check for ID's we didn't find a handler for */
if (Result == E_UNEXPECTED)
{
if (m_iIdSHEFirst && m_iIdSHELast)
if (m_pDynamicEntries)
{
if (LOWORD(LocalInvokeInfo.lpVerb) >= m_iIdSHEFirst && LOWORD(LocalInvokeInfo.lpVerb) <= m_iIdSHELast)
Result = DoDynamicShellExtensions(&LocalInvokeInfo);
}
if (m_iIdSCMFirst && m_iIdSCMLast)
if (m_pStaticEntries)
{
if (LOWORD(LocalInvokeInfo.lpVerb) >= m_iIdSCMFirst && LOWORD(LocalInvokeInfo.lpVerb) <= m_iIdSCMLast)
Result = DoStaticShellExtensions(&LocalInvokeInfo);
}
if (m_iIdCBFirst != m_iIdCBLast)
{
if (LOWORD(LocalInvokeInfo.lpVerb) >= m_iIdCBFirst && LOWORD(LocalInvokeInfo.lpVerb) <= m_iIdCBLast)
Result = _DoCallback(DFM_INVOKECOMMAND, LOWORD(LocalInvokeInfo.lpVerb), NULL);
}
}
if (Result == E_UNEXPECTED)
FIXME("Unhandled Verb %xl\n", LOWORD(LocalInvokeInfo.lpVerb));
ERR("Unhandled Verb %xl\n", LOWORD(LocalInvokeInfo.lpVerb));
return Result;
}

View file

@ -76,17 +76,13 @@ HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
if (!(dwFlags & FILE_READ_ONLY_VOLUME) && GetDriveTypeA(szDrive) != DRIVE_REMOTE)
{
_InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
_InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED);
_InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED);
}
}
}
else if (uMsg == DFM_INVOKECOMMAND)
{
if(wParam == 0x7ABC)
{
SHFormatDrive(hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
}
else if (wParam == DFM_CMD_PROPERTIES)
if (wParam == DFM_CMD_PROPERTIES)
{
WCHAR wszBuf[4];
wcscpy(wszBuf, L"A:\\");
@ -94,6 +90,10 @@ HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
if (!SH_ShowDriveProperties(wszBuf, pidlFolder, apidl))
hr = E_FAIL;
}
else
{
SHFormatDrive(hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
}
}
SHFree(pidlFolder);