mirror of
https://github.com/reactos/reactos.git
synced 2025-06-06 01:40:36 +00:00
[SHELL32] Clone properties IDataObject for unlimited lifetime (#7601)
Because SHOpenPropSheetW() is modal, there is no way for us to keep COM
alive on the original thread until the dialog completes, so a cloned
data object is used instead so that the property sheet handlers may access
the object even after ShellExecute() has returned (this is only relevant
for callers like Taskmgr that does not initialize COM even though MSDN
says they should).
Addendum to afc130ff3f
(PR #7571). CORE-19933
This commit is contained in:
parent
1dfba2a699
commit
03ee0756b8
3 changed files with 29 additions and 6 deletions
|
@ -27,7 +27,7 @@ struct ShellPropSheetDialog
|
||||||
HKEY *hKeys, UINT *cKeys);
|
HKEY *hKeys, UINT *cKeys);
|
||||||
|
|
||||||
static HRESULT Show(const CLSID *pClsidDefault, IDataObject *pDO,
|
static HRESULT Show(const CLSID *pClsidDefault, IDataObject *pDO,
|
||||||
PFNINITIALIZE InitFunc, LPCWSTR InitString, HANDLE hEvent = NULL)
|
PFNINITIALIZE InitFunc, LPCWSTR InitString)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
CRegKeyHandleArray keys;
|
CRegKeyHandleArray keys;
|
||||||
|
@ -36,8 +36,6 @@ struct ShellPropSheetDialog
|
||||||
WCHAR szCaption[MAX_PATH], *pszCaption = NULL;
|
WCHAR szCaption[MAX_PATH], *pszCaption = NULL;
|
||||||
if (SUCCEEDED(SHELL_GetCaptionFromDataObject(pDO, szCaption, _countof(szCaption))))
|
if (SUCCEEDED(SHELL_GetCaptionFromDataObject(pDO, szCaption, _countof(szCaption))))
|
||||||
pszCaption = szCaption;
|
pszCaption = szCaption;
|
||||||
if (hEvent)
|
|
||||||
SetEvent(hEvent);
|
|
||||||
hr = SHOpenPropSheetW(pszCaption, keys, keys, pClsidDefault, pDO, NULL, NULL) ? S_OK : E_FAIL;
|
hr = SHOpenPropSheetW(pszCaption, keys, keys, pClsidDefault, pDO, NULL, NULL) ? S_OK : E_FAIL;
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +94,8 @@ struct ShellPropSheetDialog
|
||||||
if (hEvent)
|
if (hEvent)
|
||||||
{
|
{
|
||||||
DWORD index;
|
DWORD index;
|
||||||
// Pump COM messages until InitFunc is done (for CORE-19933)
|
// Pump COM messages until the thread can create its own IDataObject (for CORE-19933).
|
||||||
|
// SHOpenPropSheetW is modal and we cannot wait for it to complete.
|
||||||
CoWaitForMultipleHandles(COWAIT_DEFAULT, INFINITE, 1, &hEvent, &index);
|
CoWaitForMultipleHandles(COWAIT_DEFAULT, INFINITE, 1, &hEvent, &index);
|
||||||
CloseHandle(hEvent);
|
CloseHandle(hEvent);
|
||||||
}
|
}
|
||||||
|
@ -111,10 +110,14 @@ struct ShellPropSheetDialog
|
||||||
static DWORD CALLBACK ShowPropertiesThread(LPVOID Param)
|
static DWORD CALLBACK ShowPropertiesThread(LPVOID Param)
|
||||||
{
|
{
|
||||||
DATA *pData = (DATA*)Param;
|
DATA *pData = (DATA*)Param;
|
||||||
CComPtr<IDataObject> pDO;
|
CComPtr<IDataObject> pDO, pLocalDO;
|
||||||
if (pData->pObjStream)
|
if (pData->pObjStream)
|
||||||
CoGetInterfaceAndReleaseStream(pData->pObjStream, IID_PPV_ARG(IDataObject, &pDO));
|
CoGetInterfaceAndReleaseStream(pData->pObjStream, IID_PPV_ARG(IDataObject, &pDO));
|
||||||
Show(pData->pClsidDefault, pDO, pData->InitFunc, pData->InitString, pData->hEvent);
|
if (pDO && SUCCEEDED(SHELL_CloneDataObject(pDO, &pLocalDO)))
|
||||||
|
pDO = pLocalDO;
|
||||||
|
if (pData->hEvent)
|
||||||
|
SetEvent(pData->hEvent);
|
||||||
|
Show(pData->pClsidDefault, pDO, pData->InitFunc, pData->InitString);
|
||||||
FreeData(pData);
|
FreeData(pData);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,6 +297,7 @@ HRESULT SHILAppend(_Inout_ LPITEMIDLIST pidl, _Inout_ LPITEMIDLIST *ppidl);
|
||||||
|
|
||||||
PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index);
|
PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index);
|
||||||
PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UINT Index);
|
PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UINT Index);
|
||||||
|
HRESULT SHELL_CloneDataObject(_In_ IDataObject *pDO, _Out_ IDataObject **ppDO);
|
||||||
|
|
||||||
EXTERN_C HRESULT
|
EXTERN_C HRESULT
|
||||||
IUnknown_InitializeCommand(
|
IUnknown_InitializeCommand(
|
||||||
|
|
|
@ -111,3 +111,22 @@ PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UI
|
||||||
CDataObjectHIDA cida(pDO);
|
CDataObjectHIDA cida(pDO);
|
||||||
return SUCCEEDED(cida.hr()) ? SHELL_CIDA_ILCloneFull(cida, Index) : NULL;
|
return SUCCEEDED(cida.hr()) ? SHELL_CIDA_ILCloneFull(cida, Index) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT SHELL_CloneDataObject(_In_ IDataObject *pDO, _Out_ IDataObject **ppDO)
|
||||||
|
{
|
||||||
|
*ppDO = NULL;
|
||||||
|
CDataObjectHIDA cida(pDO);
|
||||||
|
HRESULT hr = cida.hr();
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
PCUITEMID_CHILD items = HIDA_GetPIDLItem(cida, 0);
|
||||||
|
hr = SHCreateFileDataObject(HIDA_GetPIDLFolder(cida), cida->cidl, &items, NULL, ppDO);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
POINT pt;
|
||||||
|
if (SUCCEEDED(DataObject_GetOffset(pDO, &pt)))
|
||||||
|
DataObject_SetOffset(*ppDO, &pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue