[SHELL32] Implement SHSimulateDropOnClsid (#8223)

This commit is contained in:
Whindmar Saksit 2025-07-05 18:18:51 +02:00 committed by GitHub
parent 2c0782d1e0
commit 375fca5058
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 112 additions and 36 deletions

View file

@ -1570,12 +1570,11 @@ CDefaultContextMenu::InvokeRegVerb(
hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_PPV_ARG(IDropTarget, &pDT));
if (SUCCEEDED(hr))
{
CScopedSetObjectWithSite site(pDT, static_cast<IContextMenu*>(this));
CComPtr<IPropertyBag> pPB;
SHCreatePropertyBagOnRegKey(VerbKey, NULL, STGM_READ, IID_PPV_ARG(IPropertyBag, &pPB));
IUnknown_SetSite(pDT, static_cast<IContextMenu*>(this));
IUnknown_InitializeCommand(pDT, pEntry->Verb.GetString(), pPB);
hr = SHSimulateDrop(pDT, m_pDataObj, KeyState, pPtl, NULL);
IUnknown_SetSite(pDT, NULL);
return hr;
}
}

View file

@ -77,3 +77,22 @@ HRESULT WINAPI CDropTargetHelper::Show(BOOL fShow)
FIXME ("(%p)->(%u)\n", this, fShow);
return E_NOTIMPL;
}
/*************************************************************************
* SH32_SimulateDropWithSite [SHELL32.INTERNAL]
*/
static HRESULT SH32_SimulateDropWithSite(IDropTarget *pDT, IDataObject *pDO, DWORD grfKeyState, PPOINTL pPtl, LPDWORD pdwEffect, IUnknown *pSite)
{
CScopedSetObjectWithSite site(pDT, pSite);
return SHSimulateDrop(pDT, pDO, grfKeyState, pPtl, pdwEffect);
}
/*************************************************************************
* SHSimulateDropOnClsid [SHELL32.751]
*/
EXTERN_C HRESULT WINAPI SHSimulateDropOnClsid(_In_ REFCLSID clsid, _In_opt_ IUnknown* pSite, _In_ IDataObject* pDO)
{
CComPtr<IDropTarget> pDT;
HRESULT hr = SH32_ExtCoCreateInstance(NULL, &clsid, NULL, CLSCTX_ALL, IID_PPV_ARG(IDropTarget, &pDT));
return SUCCEEDED(hr) ? SH32_SimulateDropWithSite(pDT, pDO, 0, NULL, NULL, pSite) : hr;
}

View file

@ -460,7 +460,7 @@
748 stdcall -noname SHLimitInputCombo(ptr ptr)
749 stdcall -noname -version=0x501-0x502 SHGetShellStyleHInstance()
750 stdcall -noname SHGetAttributesFromDataObject(ptr long ptr ptr)
751 stub -noname SHSimulateDropOnClsid
751 stdcall -noname SHSimulateDropOnClsid(ptr ptr ptr)
752 stdcall -noname SHGetComputerDisplayNameW(wstr long ptr long)
753 stdcall -noname CheckStagingArea()
754 stub -noname SHLimitInputEditWithFlags
@ -468,3 +468,4 @@
756 stub -noname DeleteFileThumbnail
757 stdcall -noname -version=0x600+ DisplayNameOfW(ptr ptr long ptr long)
866 stdcall -noname -version=0x600+ SHExtCoCreateInstance(wstr ptr ptr ptr ptr)
887 stub -noname -version=0x601+ SHExtCoCreateInstanceCheckCategory

View file

@ -1698,8 +1698,7 @@ InvokeIExecuteCommand(
if (!pEC)
return E_INVALIDARG;
if (pSite)
IUnknown_SetSite(pEC, pSite);
CScopedSetObjectWithSite site(pEC, pSite);
IUnknown_InitializeCommand(pEC, pszCommandName, pPB);
CComPtr<IObjectWithSelection> pOWS;
@ -1721,10 +1720,7 @@ InvokeIExecuteCommand(
if (fMask & CMIC_MASK_PTINVOKE)
pEC->SetPosition(pICI->ptInvoke);
HRESULT hr = pEC->Execute();
if (pSite)
IUnknown_SetSite(pEC, NULL);
return hr;
return pEC->Execute();
}
EXTERN_C HRESULT

View file

@ -42,6 +42,16 @@ enum {
};
DWORD SH32_InternalRestricted(DWORD rest);
/* COM */
HRESULT WINAPI
SH32_ExtCoCreateInstance(
_In_opt_ LPCWSTR aclsid,
_In_opt_ const CLSID *clsid,
_In_opt_ LPUNKNOWN pUnkOuter,
_In_ DWORD dwClsCtx,
_In_ REFIID riid,
_Out_ LPVOID *ppv);
/* Iconcache */
#define INVALID_INDEX -1
BOOL SIC_Initialize(void);

View file

@ -86,28 +86,13 @@ static const struct {
#endif /* !__REACTOS__ */
/*************************************************************************
* SHCoCreateInstance [SHELL32.102]
*
* Equivalent to CoCreateInstance. Under Windows 9x this function could sometimes
* use the shell32 built-in "mini-COM" without the need to load ole32.dll - see
* SHLoadOLE for details.
*
* Under wine if a "LoadWithoutCOM" value is present or the object resides in
* shell32.dll the function will load the object manually without the help of ole32
*
* NOTES
* exported by ordinal
*
* SEE ALSO
* CoCreateInstance, SHLoadOLE
*/
HRESULT WINAPI SHCoCreateInstance(
LPCWSTR aclsid,
const CLSID *clsid,
LPUNKNOWN pUnkOuter,
REFIID refiid,
LPVOID *ppv)
HRESULT WINAPI SH32_CoCreateInstance(
LPCWSTR aclsid,
const CLSID *clsid,
LPUNKNOWN pUnkOuter,
DWORD dwClsCtx,
REFIID refiid,
LPVOID *ppv)
{
DWORD hres;
CLSID iid;
@ -148,7 +133,7 @@ HRESULT WINAPI SHCoCreateInstance(
return E_ACCESSDENIED;
/* if a special registry key is set, we load a shell extension without help of OLE32 */
if (!SHQueryValueExW(hKey, L"LoadWithoutCOM", 0, 0, 0, 0))
if ((dwClsCtx & CLSCTX_INPROC_SERVER) && !SHQueryValueExW(hKey, L"LoadWithoutCOM", 0, 0, 0, 0))
{
/* load an external dll without ole32 */
HANDLE hLibrary;
@ -177,7 +162,7 @@ HRESULT WINAPI SHCoCreateInstance(
} else {
/* load an external dll in the usual way */
hres = CoCreateInstance(myclsid, pUnkOuter, CLSCTX_INPROC_SERVER, refiid, ppv);
hres = CoCreateInstance(myclsid, pUnkOuter, dwClsCtx, refiid, ppv);
}
end:
@ -193,17 +178,65 @@ end:
return hres;
}
/*************************************************************************
* SHCoCreateInstance [SHELL32.102]
*
* Equivalent to CoCreateInstance. Under Windows 9x this function could sometimes
* use the shell32 built-in "mini-COM" without the need to load ole32.dll - see
* SHLoadOLE for details.
*
* Under wine if a "LoadWithoutCOM" value is present or the object resides in
* shell32.dll the function will load the object manually without the help of ole32
*
* NOTES
* exported by ordinal
*
* SEE ALSO
* CoCreateInstance, SHLoadOLE
*/
HRESULT WINAPI SHCoCreateInstance(
LPCWSTR aclsid,
const CLSID *clsid,
LPUNKNOWN pUnkOuter,
REFIID riid,
LPVOID *ppv)
{
return SH32_CoCreateInstance(aclsid, clsid, pUnkOuter, CLSCTX_INPROC_SERVER, riid, ppv);
}
HRESULT WINAPI SH32_ExtCoCreateInstance(
_In_opt_ LPCWSTR aclsid,
_In_opt_ const CLSID *clsid,
_In_opt_ LPUNKNOWN pUnkOuter,
_In_ DWORD dwClsCtx,
_In_ REFIID riid,
_Out_ LPVOID *ppv)
{
// TODO: Verify that this CLSID is allowed (..\CurrentVersion\Shell Extensions\Approved) if REST_ENFORCESHELLEXTSECURITY is active
return SH32_CoCreateInstance(aclsid, clsid, pUnkOuter, dwClsCtx, riid, ppv);
}
/*************************************************************************
* SHCoCreateInstance [SHELL32.866]
*/
HRESULT WINAPI SHExtCoCreateInstance(
_In_opt_ LPCWSTR aclsid,
_In_opt_ const CLSID *clsid,
_In_opt_ LPUNKNOWN pUnkOuter,
_In_ REFIID refiid,
_In_ REFIID riid,
_Out_ LPVOID *ppv)
{
// TODO: Verify that this CLSID is allowed if REST_ENFORCESHELLEXTSECURITY is active
return SHCoCreateInstance(aclsid, clsid, pUnkOuter, refiid, ppv);
return SH32_ExtCoCreateInstance(aclsid, clsid, pUnkOuter, CLSCTX_INPROC_SERVER, riid, ppv);
}
#if 0
/*************************************************************************
* SHExtCoCreateInstanceCheckCategory [SHELL32.887]
*/
// TODO: ICatInformation::IsClassOfCategories?
// return SH32_ExtCoCreateInstance()
#endif
#ifndef __REACTOS__
/*************************************************************************
* DllGetClassObject [SHELL32.@]

View file

@ -652,6 +652,24 @@ public:
return m_pUnkSite ? m_pUnkSite->QueryInterface(riid, ppvSite) : E_FAIL;
}
};
#if defined(__WINE_SHLWAPI_H) && !defined(NO_SHLWAPI)
struct CScopedSetObjectWithSite
{
IUnknown *m_pObj;
explicit CScopedSetObjectWithSite(IUnknown *pObj, IUnknown *pSite) : m_pObj(pObj)
{
if (pSite)
IUnknown_SetSite(pObj, pSite);
else
m_pObj = NULL;
}
~CScopedSetObjectWithSite()
{
IUnknown_SetSite(m_pObj, NULL);
}
};
#endif
#endif /* __cplusplus */
#define S_LESSTHAN 0xffff