[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)); hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_PPV_ARG(IDropTarget, &pDT));
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
CScopedSetObjectWithSite site(pDT, static_cast<IContextMenu*>(this));
CComPtr<IPropertyBag> pPB; CComPtr<IPropertyBag> pPB;
SHCreatePropertyBagOnRegKey(VerbKey, NULL, STGM_READ, IID_PPV_ARG(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); IUnknown_InitializeCommand(pDT, pEntry->Verb.GetString(), pPB);
hr = SHSimulateDrop(pDT, m_pDataObj, KeyState, pPtl, NULL); hr = SHSimulateDrop(pDT, m_pDataObj, KeyState, pPtl, NULL);
IUnknown_SetSite(pDT, NULL);
return hr; return hr;
} }
} }

View file

@ -77,3 +77,22 @@ HRESULT WINAPI CDropTargetHelper::Show(BOOL fShow)
FIXME ("(%p)->(%u)\n", this, fShow); FIXME ("(%p)->(%u)\n", this, fShow);
return E_NOTIMPL; 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) 748 stdcall -noname SHLimitInputCombo(ptr ptr)
749 stdcall -noname -version=0x501-0x502 SHGetShellStyleHInstance() 749 stdcall -noname -version=0x501-0x502 SHGetShellStyleHInstance()
750 stdcall -noname SHGetAttributesFromDataObject(ptr long ptr ptr) 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) 752 stdcall -noname SHGetComputerDisplayNameW(wstr long ptr long)
753 stdcall -noname CheckStagingArea() 753 stdcall -noname CheckStagingArea()
754 stub -noname SHLimitInputEditWithFlags 754 stub -noname SHLimitInputEditWithFlags
@ -468,3 +468,4 @@
756 stub -noname DeleteFileThumbnail 756 stub -noname DeleteFileThumbnail
757 stdcall -noname -version=0x600+ DisplayNameOfW(ptr ptr long ptr long) 757 stdcall -noname -version=0x600+ DisplayNameOfW(ptr ptr long ptr long)
866 stdcall -noname -version=0x600+ SHExtCoCreateInstance(wstr ptr ptr ptr ptr) 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) if (!pEC)
return E_INVALIDARG; return E_INVALIDARG;
if (pSite) CScopedSetObjectWithSite site(pEC, pSite);
IUnknown_SetSite(pEC, pSite);
IUnknown_InitializeCommand(pEC, pszCommandName, pPB); IUnknown_InitializeCommand(pEC, pszCommandName, pPB);
CComPtr<IObjectWithSelection> pOWS; CComPtr<IObjectWithSelection> pOWS;
@ -1721,10 +1720,7 @@ InvokeIExecuteCommand(
if (fMask & CMIC_MASK_PTINVOKE) if (fMask & CMIC_MASK_PTINVOKE)
pEC->SetPosition(pICI->ptInvoke); pEC->SetPosition(pICI->ptInvoke);
HRESULT hr = pEC->Execute(); return pEC->Execute();
if (pSite)
IUnknown_SetSite(pEC, NULL);
return hr;
} }
EXTERN_C HRESULT EXTERN_C HRESULT

View file

@ -42,6 +42,16 @@ enum {
}; };
DWORD SH32_InternalRestricted(DWORD rest); 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 */ /* Iconcache */
#define INVALID_INDEX -1 #define INVALID_INDEX -1
BOOL SIC_Initialize(void); BOOL SIC_Initialize(void);

View file

@ -86,28 +86,13 @@ static const struct {
#endif /* !__REACTOS__ */ #endif /* !__REACTOS__ */
/************************************************************************* HRESULT WINAPI SH32_CoCreateInstance(
* SHCoCreateInstance [SHELL32.102] LPCWSTR aclsid,
* const CLSID *clsid,
* Equivalent to CoCreateInstance. Under Windows 9x this function could sometimes LPUNKNOWN pUnkOuter,
* use the shell32 built-in "mini-COM" without the need to load ole32.dll - see DWORD dwClsCtx,
* SHLoadOLE for details. REFIID refiid,
* LPVOID *ppv)
* 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)
{ {
DWORD hres; DWORD hres;
CLSID iid; CLSID iid;
@ -148,7 +133,7 @@ HRESULT WINAPI SHCoCreateInstance(
return E_ACCESSDENIED; return E_ACCESSDENIED;
/* if a special registry key is set, we load a shell extension without help of OLE32 */ /* 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 */ /* load an external dll without ole32 */
HANDLE hLibrary; HANDLE hLibrary;
@ -177,7 +162,7 @@ HRESULT WINAPI SHCoCreateInstance(
} else { } else {
/* load an external dll in the usual way */ /* 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: end:
@ -193,17 +178,65 @@ end:
return hres; 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( HRESULT WINAPI SHExtCoCreateInstance(
_In_opt_ LPCWSTR aclsid, _In_opt_ LPCWSTR aclsid,
_In_opt_ const CLSID *clsid, _In_opt_ const CLSID *clsid,
_In_opt_ LPUNKNOWN pUnkOuter, _In_opt_ LPUNKNOWN pUnkOuter,
_In_ REFIID refiid, _In_ REFIID riid,
_Out_ LPVOID *ppv) _Out_ LPVOID *ppv)
{ {
// TODO: Verify that this CLSID is allowed if REST_ENFORCESHELLEXTSECURITY is active return SH32_ExtCoCreateInstance(aclsid, clsid, pUnkOuter, CLSCTX_INPROC_SERVER, riid, ppv);
return SHCoCreateInstance(aclsid, clsid, pUnkOuter, refiid, ppv);
} }
#if 0
/*************************************************************************
* SHExtCoCreateInstanceCheckCategory [SHELL32.887]
*/
// TODO: ICatInformation::IsClassOfCategories?
// return SH32_ExtCoCreateInstance()
#endif
#ifndef __REACTOS__ #ifndef __REACTOS__
/************************************************************************* /*************************************************************************
* DllGetClassObject [SHELL32.@] * DllGetClassObject [SHELL32.@]

View file

@ -652,6 +652,24 @@ public:
return m_pUnkSite ? m_pUnkSite->QueryInterface(riid, ppvSite) : E_FAIL; 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 */ #endif /* __cplusplus */
#define S_LESSTHAN 0xffff #define S_LESSTHAN 0xffff