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

View file

@ -76,17 +76,13 @@ HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
if (!(dwFlags & FILE_READ_ONLY_VOLUME) && GetDriveTypeA(szDrive) != DRIVE_REMOTE) 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, 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) else if (uMsg == DFM_INVOKECOMMAND)
{ {
if(wParam == 0x7ABC) if (wParam == DFM_CMD_PROPERTIES)
{
SHFormatDrive(hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
}
else if (wParam == DFM_CMD_PROPERTIES)
{ {
WCHAR wszBuf[4]; WCHAR wszBuf[4];
wcscpy(wszBuf, L"A:\\"); wcscpy(wszBuf, L"A:\\");
@ -94,6 +90,10 @@ HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
if (!SH_ShowDriveProperties(wszBuf, pidlFolder, apidl)) if (!SH_ShowDriveProperties(wszBuf, pidlFolder, apidl))
hr = E_FAIL; hr = E_FAIL;
} }
else
{
SHFormatDrive(hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
}
} }
SHFree(pidlFolder); SHFree(pidlFolder);