https://git.reactos.org/?p=reactos.git;a=commitdiff;h=03ee0756b872a8a487876a97e5152fffbd524c73

commit 03ee0756b872a8a487876a97e5152fffbd524c73
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Wed Jan 8 12:22:34 2025 +0100
Commit:     GitHub <nore...@github.com>
CommitDate: Wed Jan 8 14:22:34 2025 +0300

    [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 afc130ff3f5 (PR #7571). CORE-19933
---
 dll/win32/shell32/dialogs/item_prop.cpp | 15 +++++++++------
 dll/win32/shell32/precomp.h             |  1 +
 dll/win32/shell32/shldataobject.cpp     | 19 +++++++++++++++++++
 3 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/dll/win32/shell32/dialogs/item_prop.cpp 
b/dll/win32/shell32/dialogs/item_prop.cpp
index bcc6473144d..75039293c3c 100644
--- a/dll/win32/shell32/dialogs/item_prop.cpp
+++ b/dll/win32/shell32/dialogs/item_prop.cpp
@@ -27,7 +27,7 @@ struct ShellPropSheetDialog
                                           HKEY *hKeys, UINT *cKeys);
 
     static HRESULT Show(const CLSID *pClsidDefault, IDataObject *pDO,
-                        PFNINITIALIZE InitFunc, LPCWSTR InitString, HANDLE 
hEvent = NULL)
+                        PFNINITIALIZE InitFunc, LPCWSTR InitString)
     {
         HRESULT hr;
         CRegKeyHandleArray keys;
@@ -36,8 +36,6 @@ struct ShellPropSheetDialog
         WCHAR szCaption[MAX_PATH], *pszCaption = NULL;
         if (SUCCEEDED(SHELL_GetCaptionFromDataObject(pDO, szCaption, 
_countof(szCaption))))
             pszCaption = szCaption;
-        if (hEvent)
-            SetEvent(hEvent);
         hr = SHOpenPropSheetW(pszCaption, keys, keys, pClsidDefault, pDO, 
NULL, NULL) ? S_OK : E_FAIL;
         return hr;
     }
@@ -96,7 +94,8 @@ struct ShellPropSheetDialog
             if (hEvent)
             {
                 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);
                 CloseHandle(hEvent);
             }
@@ -111,10 +110,14 @@ struct ShellPropSheetDialog
     static DWORD CALLBACK ShowPropertiesThread(LPVOID Param)
     {
         DATA *pData = (DATA*)Param;
-        CComPtr<IDataObject> pDO;
+        CComPtr<IDataObject> pDO, pLocalDO;
         if (pData->pObjStream)
             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);
         return 0;
     }
diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h
index 48c636fe9f1..6d65aeac056 100644
--- a/dll/win32/shell32/precomp.h
+++ b/dll/win32/shell32/precomp.h
@@ -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_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ 
UINT Index);
+HRESULT SHELL_CloneDataObject(_In_ IDataObject *pDO, _Out_ IDataObject **ppDO);
 
 EXTERN_C HRESULT
 IUnknown_InitializeCommand(
diff --git a/dll/win32/shell32/shldataobject.cpp 
b/dll/win32/shell32/shldataobject.cpp
index 3a7d651424f..728cca0dbf3 100644
--- a/dll/win32/shell32/shldataobject.cpp
+++ b/dll/win32/shell32/shldataobject.cpp
@@ -111,3 +111,22 @@ PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ 
IDataObject *pDO, _In_ UI
     CDataObjectHIDA cida(pDO);
     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;
+}

Reply via email to