[SHELL32][NTOBJSHEX] CDefaultContextMenu cannot close keys it does not own (#8233)

This commit is contained in:
Whindmar Saksit 2025-07-12 15:18:39 +02:00 committed by GitHub
parent 3fb2905c37
commit 8edf4f0926
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 50 additions and 104 deletions

View file

@ -422,7 +422,7 @@ public:
LPCITEMIDLIST child; LPCITEMIDLIST child;
int nkeys = _countof(keys); UINT nkeys = 0;
if (cidl == 1 && IsSymLink(apidl[0])) if (cidl == 1 && IsSymLink(apidl[0]))
{ {
const TItemId * info; const TItemId * info;
@ -452,16 +452,15 @@ public:
if (cidl == 1 && IsFolder(apidl[0])) if (cidl == 1 && IsFolder(apidl[0]))
{ {
res = RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0); res = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Folder", 0, KEY_READ, &keys[0]);
if (!NT_SUCCESS(res)) if (!NT_SUCCESS(res))
return HRESULT_FROM_NT(res); return HRESULT_FROM_WIN32(res);
} nkeys++;
else
{
nkeys = 0;
} }
HRESULT hr = CDefFolderMenu_Create2(parent, hwndOwner, cidl, apidl, psfParent, DefCtxMenuCallback, nkeys, keys, &pcm); HRESULT hr = CDefFolderMenu_Create2(parent, hwndOwner, cidl, apidl, psfParent, DefCtxMenuCallback, nkeys, keys, &pcm);
for (UINT i = 0; i < nkeys; ++i)
RegCloseKey(keys[i]);
if (FAILED_UNEXPECTEDLY(hr)) if (FAILED_UNEXPECTEDLY(hr))
return hr; return hr;

View file

@ -299,7 +299,7 @@ class CDefaultContextMenu :
UINT m_cidl; UINT m_cidl;
PCUITEMID_CHILD_ARRAY m_apidl; PCUITEMID_CHILD_ARRAY m_apidl;
CComPtr<IDataObject> m_pDataObj; CComPtr<IDataObject> m_pDataObj;
HKEY* m_aKeys; HKEY m_aKeys[16]; // This limit is documented for both the old API and for DEFCONTEXTMENU
UINT m_cKeys; UINT m_cKeys;
PIDLIST_ABSOLUTE m_pidlFolder; PIDLIST_ABSOLUTE m_pidlFolder;
DWORD m_bGroupPolicyActive; DWORD m_bGroupPolicyActive;
@ -387,8 +387,7 @@ CDefaultContextMenu::CDefaultContextMenu() :
m_cidl(0), m_cidl(0),
m_apidl(NULL), m_apidl(NULL),
m_pDataObj(NULL), m_pDataObj(NULL),
m_aKeys(NULL), m_cKeys(0),
m_cKeys(NULL),
m_pidlFolder(NULL), m_pidlFolder(NULL),
m_bGroupPolicyActive(0), m_bGroupPolicyActive(0),
m_iIdQCMFirst(0), m_iIdQCMFirst(0),
@ -417,7 +416,6 @@ CDefaultContextMenu::~CDefaultContextMenu()
for (UINT i = 0; i < m_cKeys; i++) for (UINT i = 0; i < m_cKeys; i++)
RegCloseKey(m_aKeys[i]); RegCloseKey(m_aKeys[i]);
HeapFree(GetProcessHeap(), 0, m_aKeys);
if (m_pidlFolder) if (m_pidlFolder)
CoTaskMemFree(m_pidlFolder); CoTaskMemFree(m_pidlFolder);
@ -428,6 +426,7 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm, LPFND
{ {
TRACE("cidl %u\n", pdcm->cidl); TRACE("cidl %u\n", pdcm->cidl);
HRESULT hr = S_OK;
if (!pdcm->pcmcb && !lpfn) if (!pdcm->pcmcb && !lpfn)
{ {
ERR("CDefaultContextMenu needs a callback!\n"); ERR("CDefaultContextMenu needs a callback!\n");
@ -443,13 +442,14 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm, LPFND
m_pfnmcb = lpfn; m_pfnmcb = lpfn;
m_hwnd = pdcm->hwnd; m_hwnd = pdcm->hwnd;
m_cKeys = pdcm->cKeys; for (UINT i = 0; i < pdcm->cKeys; ++i)
if (pdcm->cKeys)
{ {
m_aKeys = (HKEY*)HeapAlloc(GetProcessHeap(), 0, sizeof(HKEY) * pdcm->cKeys); if (i >= _countof(m_aKeys))
if (!m_aKeys) hr = E_INVALIDARG;
return E_OUTOFMEMORY; else if ((m_aKeys[i] = SHRegDuplicateHKey(pdcm->aKeys[i])) != NULL)
memcpy(m_aKeys, pdcm->aKeys, sizeof(HKEY) * pdcm->cKeys); m_cKeys++;
else
hr = E_OUTOFMEMORY;
} }
m_psf->GetUIObjectOf(pdcm->hwnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &m_pDataObj)); m_psf->GetUIObjectOf(pdcm->hwnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &m_pDataObj));
@ -469,7 +469,7 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm, LPFND
TRACE("pidlFolder %p\n", m_pidlFolder); TRACE("pidlFolder %p\n", m_pidlFolder);
} }
return S_OK; return hr;
} }
HRESULT CDefaultContextMenu::_DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam) HRESULT CDefaultContextMenu::_DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam)

View file

@ -657,21 +657,10 @@ HRESULT WINAPI CDesktopFolder::CreateViewObject(
} }
else if (IsEqualIID (riid, IID_IContextMenu)) else if (IsEqualIID (riid, IID_IContextMenu))
{ {
HKEY hKeys[16]; CRegKeyHandleArray keys;
UINT cKeys = 0; AddClassKeyToArray(L"Directory\\Background", keys, keys);
AddClassKeyToArray(L"Directory\\Background", hKeys, &cKeys); DEFCONTEXTMENU dcm = { hwndOwner, this, pidlRoot, this, 0, NULL, NULL, keys, keys };
hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut);
DEFCONTEXTMENU dcm;
dcm.hwnd = hwndOwner;
dcm.pcmcb = this;
dcm.pidlFolder = pidlRoot;
dcm.psf = this;
dcm.cidl = 0;
dcm.apidl = NULL;
dcm.cKeys = cKeys;
dcm.aKeys = hKeys;
dcm.punkAssociationInfo = NULL;
hr = SHCreateDefaultContextMenu (&dcm, riid, ppvOut);
} }
else if (IsEqualIID (riid, IID_IShellView)) else if (IsEqualIID (riid, IID_IShellView))
{ {
@ -795,29 +784,19 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
/* Do not use the context menu of the CFSFolder here. */ /* Do not use the context menu of the CFSFolder here. */
/* We need to pass a pointer of the CDesktopFolder so as the data object that the context menu gets is rooted to the desktop */ /* We need to pass a pointer of the CDesktopFolder so as the data object that the context menu gets is rooted to the desktop */
/* Otherwise operations like that involve items from both user and shared desktop will not work */ /* Otherwise operations like that involve items from both user and shared desktop will not work */
HKEY hKeys[16]; CRegKeyHandleArray keys;
UINT cKeys = 0;
if (self) if (self)
{ {
AddClsidKeyToArray(CLSID_ShellDesktop, hKeys, &cKeys); AddClsidKeyToArray(CLSID_ShellDesktop, keys, keys);
AddClassKeyToArray(L"Folder", hKeys, &cKeys); AddClassKeyToArray(L"Folder", keys, keys);
} }
else if (cidl > 0) else if (cidl > 0)
{ {
AddFSClassKeysToArray(cidl, apidl, hKeys, &cKeys); AddFSClassKeysToArray(cidl, apidl, keys, keys);
} }
DEFCONTEXTMENU dcm; DEFCONTEXTMENU dcm = { hwndOwner, this, pidlRoot, this, cidl, apidl, NULL, keys, keys };
dcm.hwnd = hwndOwner; hr = SHCreateDefaultContextMenu(&dcm, riid, &pObj);
dcm.pcmcb = this;
dcm.pidlFolder = pidlRoot;
dcm.psf = this;
dcm.cidl = cidl;
dcm.apidl = apidl;
dcm.cKeys = cKeys;
dcm.aKeys = hKeys;
dcm.punkAssociationInfo = NULL;
hr = SHCreateDefaultContextMenu (&dcm, riid, &pObj);
} }
} }
else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1)) else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))

View file

@ -459,12 +459,10 @@ HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
IShellFolder *psf, IShellFolder *psf,
IContextMenu **ppcm) IContextMenu **ppcm)
{ {
HKEY hKeys[2]; CRegKeyHandleArray keys;
UINT cKeys = 0; AddClassKeyToArray(L"Drive", keys, keys);
AddClassKeyToArray(L"Drive", hKeys, &cKeys); AddClassKeyToArray(L"Folder", keys, keys);
AddClassKeyToArray(L"Folder", hKeys, &cKeys); return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, DrivesContextMenuCallback, keys, keys, ppcm);
return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, DrivesContextMenuCallback, cKeys, hKeys, ppcm);
} }
static HRESULT static HRESULT

View file

@ -1237,29 +1237,18 @@ HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner,
{ {
hr = CFSDropTarget_CreateInstance(m_sPathTarget, riid, ppvOut); hr = CFSDropTarget_CreateInstance(m_sPathTarget, riid, ppvOut);
} }
else if (IsEqualIID (riid, IID_IContextMenu))
{
HKEY hKeys[16];
UINT cKeys = 0;
AddClassKeyToArray(L"Directory\\Background", hKeys, &cKeys);
DEFCONTEXTMENU dcm;
dcm.hwnd = hwndOwner;
dcm.pcmcb = this;
dcm.pidlFolder = m_pidlRoot;
dcm.psf = this;
dcm.cidl = 0;
dcm.apidl = NULL;
dcm.cKeys = cKeys;
dcm.aKeys = hKeys;
dcm.punkAssociationInfo = NULL;
hr = SHCreateDefaultContextMenu (&dcm, riid, ppvOut);
}
else if (bIsShellView) else if (bIsShellView)
{ {
SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this, NULL, this}; SFV_CREATE sfvparams = { sizeof(SFV_CREATE), this, NULL, this };
hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut); hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut);
} }
else if (IsEqualIID(riid, IID_IContextMenu))
{
CRegKeyHandleArray keys;
AddClassKeyToArray(L"Directory\\Background", keys, keys);
DEFCONTEXTMENU dcm = { hwndOwner, this, m_pidlRoot, this, 0, NULL, NULL, keys, keys };
hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut);
}
else else
{ {
hr = E_INVALIDARG; hr = E_INVALIDARG;
@ -1383,21 +1372,10 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner,
if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1))
{ {
HKEY hKeys[16]; CRegKeyHandleArray keys;
UINT cKeys = 0; AddFSClassKeysToArray(cidl, apidl, keys, keys);
AddFSClassKeysToArray(cidl, apidl, hKeys, &cKeys); DEFCONTEXTMENU dcm = { hwndOwner, this, m_pidlRoot, this, cidl, apidl, NULL, keys, keys };
hr = SHCreateDefaultContextMenu(&dcm, riid, &pObj);
DEFCONTEXTMENU dcm;
dcm.hwnd = hwndOwner;
dcm.pcmcb = this;
dcm.pidlFolder = m_pidlRoot;
dcm.psf = this;
dcm.cidl = cidl;
dcm.apidl = apidl;
dcm.cKeys = cKeys;
dcm.aKeys = hKeys;
dcm.punkAssociationInfo = NULL;
hr = SHCreateDefaultContextMenu (&dcm, riid, &pObj);
} }
else if (IsEqualIID (riid, IID_IDataObject)) else if (IsEqualIID (riid, IID_IDataObject))
{ {

View file

@ -435,11 +435,10 @@ HRESULT WINAPI CNetFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CH
if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1))
{ {
CRegKeyHandleArray keys;
IContextMenu * pCm = NULL; IContextMenu * pCm = NULL;
HKEY hkey; AddClassKeyToArray(L"Folder", keys, keys);
UINT cKeys = 0; hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, this, NetFolderMenuCallback, keys, keys, &pCm);
AddClassKeyToArray(L"Folder", &hkey, &cKeys);
hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, this, NetFolderMenuCallback, cKeys, &hkey, &pCm);
pObj = pCm; pObj = pCm;
} }
else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1)) else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1))

View file

@ -972,17 +972,10 @@ static HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf, HWND hwn
static HRESULT CRegItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HWND hwnd, UINT cidl, static HRESULT CRegItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HWND hwnd, UINT cidl,
PCUITEMID_CHILD_ARRAY apidl, IShellFolder *psf, IContextMenu **ppcm) PCUITEMID_CHILD_ARRAY apidl, IShellFolder *psf, IContextMenu **ppcm)
{ {
HKEY hKeys[3]; CRegKeyHandleArray keys;
UINT cKeys = 0;
const GUID *pGuid = _ILGetGUIDPointer(apidl[0]); const GUID *pGuid = _ILGetGUIDPointer(apidl[0]);
if (pGuid) if (pGuid)
{ AddClsidKeyToArray(*pGuid, keys, keys);
WCHAR key[sizeof("CLSID\\") + 38];
wcscpy(key, L"CLSID\\");
StringFromGUID2(*pGuid, &key[6], 39);
AddClassKeyToArray(key, hKeys, &cKeys);
}
// FIXME: CRegFolder should be aggregated by its outer folder and should // FIXME: CRegFolder should be aggregated by its outer folder and should
// provide the attributes for all required non-registry folders. // provide the attributes for all required non-registry folders.
@ -993,9 +986,9 @@ static HRESULT CRegItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
SFGAOF att = (psf && cidl) ? SHGetAttributes(pOuterSF ? pOuterSF.p : psf, apidl[0], SFGAO_FOLDER) : 0; SFGAOF att = (psf && cidl) ? SHGetAttributes(pOuterSF ? pOuterSF.p : psf, apidl[0], SFGAO_FOLDER) : 0;
if ((att & SFGAO_FOLDER) && (!pGuid || !HasCLSIDShellFolderValue(*pGuid, L"HideFolderVerbs"))) if ((att & SFGAO_FOLDER) && (!pGuid || !HasCLSIDShellFolderValue(*pGuid, L"HideFolderVerbs")))
AddClassKeyToArray(L"Folder", hKeys, &cKeys); AddClassKeyToArray(L"Folder", keys, keys);
return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, RegFolderContextMenuCallback, cKeys, hKeys, ppcm); return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, RegFolderContextMenuCallback, keys, keys, ppcm);
} }
/* In latest windows version this is exported but it takes different arguments! */ /* In latest windows version this is exported but it takes different arguments! */