https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6a1f287820e6ada7d957a6451a7ecc54f73c1876

commit 6a1f287820e6ada7d957a6451a7ecc54f73c1876
Author:     Mark Jansen <[email protected]>
AuthorDate: Thu Sep 22 19:27:33 2022 +0200
Commit:     Mark Jansen <[email protected]>
CommitDate: Fri Oct 14 21:02:33 2022 +0200

    [SHELL32] Show file / drive properties at the position where the mouse was.
    
    CORE-18386
---
 dll/win32/shell32/CDefView.cpp              | 36 +++++++------
 dll/win32/shell32/CDefaultContextMenu.cpp   | 76 ++++++++++++++-------------
 dll/win32/shell32/dialogs/drive.cpp         | 79 +++++++++++++++--------------
 dll/win32/shell32/dialogs/fprop.cpp         | 61 +++++++++++++---------
 dll/win32/shell32/folders/CDrivesFolder.cpp |  4 +-
 dll/win32/shell32/folders/CFSFolder.cpp     | 24 ++++++---
 dll/win32/shell32/shlfolder.cpp             | 27 +++-------
 dll/win32/shell32/wine/shell32_main.h       |  4 +-
 sdk/include/reactos/shellutils.h            | 26 ++++++++++
 9 files changed, 196 insertions(+), 141 deletions(-)

diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp
index 0bff83e1c9f..fbee323ee7d 100644
--- a/dll/win32/shell32/CDefView.cpp
+++ b/dll/win32/shell32/CDefView.cpp
@@ -197,7 +197,7 @@ class CDefView :
         void OnDeactivate();
         void DoActivate(UINT uState);
         HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD 
*pdwEffect);
-        HRESULT InvokeContextMenuCommand(CComPtr<IContextMenu> &pCM, UINT 
uCommand);
+        HRESULT InvokeContextMenuCommand(CComPtr<IContextMenu> &pCM, UINT 
uCommand, POINT* pt);
         LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
 
         // *** IOleWindow methods ***
@@ -1496,9 +1496,9 @@ UINT CDefView::GetSelections()
     return m_cidl;
 }
 
-HRESULT CDefView::InvokeContextMenuCommand(CComPtr<IContextMenu> &pCM, UINT 
uCommand)
+HRESULT CDefView::InvokeContextMenuCommand(CComPtr<IContextMenu> &pCM, UINT 
uCommand, POINT* pt)
 {
-    CMINVOKECOMMANDINFO cmi;
+    CMINVOKECOMMANDINFOEX cmi;
 
     ZeroMemory(&cmi, sizeof(cmi));
     cmi.cbSize = sizeof(cmi);
@@ -1511,7 +1511,13 @@ HRESULT 
CDefView::InvokeContextMenuCommand(CComPtr<IContextMenu> &pCM, UINT uCom
     if (GetKeyState(VK_CONTROL) & 0x8000)
         cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
 
-    HRESULT hr = pCM->InvokeCommand(&cmi);
+    if (pt)
+    {
+        cmi.fMask |= CMIC_MASK_PTINVOKE;
+        cmi.ptInvoke = *pt;
+    }
+
+    HRESULT hr = m_pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)&cmi);
     // Most of our callers will do this, but in case they don't do that (File 
menu!)
     IUnknown_SetSite(pCM, NULL);
     pCM.Release();
@@ -1560,7 +1566,7 @@ HRESULT CDefView::OpenSelectedItems()
         return E_FAIL;
     }
 
-    InvokeContextMenuCommand(pCM, uCommand);
+    InvokeContextMenuCommand(pCM, uCommand, NULL);
 
     return hResult;
 }
@@ -1570,7 +1576,7 @@ HRESULT CDefView::OpenSelectedItems()
  */
 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
 {
-    int     x, y;
+    POINT pt;
     UINT    uCommand;
     HRESULT hResult;
 
@@ -1588,10 +1594,10 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM 
wParam, LPARAM lParam, BOOL &b
 
     if (lParam != ~0)   // unless app key (menu key) was pressed
     {
-        x = GET_X_LPARAM(lParam);
-        y = GET_Y_LPARAM(lParam);
+        pt.x = GET_X_LPARAM(lParam);
+        pt.y = GET_Y_LPARAM(lParam);
 
-        LV_HITTESTINFO hittest = { { x, y } };
+        LV_HITTESTINFO hittest = { pt };
         ScreenToClient(&hittest.pt);
         m_ListView.HitTest(&hittest);
 
@@ -1621,7 +1627,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, 
LPARAM lParam, BOOL &b
     {
         HWND hFocus = ::GetFocus();
         int lvIndex = -1;
-        POINT pt;
 
         if (hFocus == m_ListView.m_hWnd || m_ListView.IsChild(hFocus))
         {
@@ -1648,21 +1653,19 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM 
wParam, LPARAM lParam, BOOL &b
         }
 
         m_ListView.ClientToScreen(&pt);
-        x = pt.x;
-        y = pt.y;
     }
 
     // This runs the message loop, calling back to us with f.e. WM_INITPOPUP 
(hence why m_hContextMenu and m_pCM exist) 
     uCommand = TrackPopupMenu(m_hContextMenu,
                               TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | 
TPM_RIGHTBUTTON,
-                              x, y, 0, m_hWnd, NULL);
+                              pt.x, pt.y, 0, m_hWnd, NULL);
     if (uCommand == 0)
         return 0;
 
     if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
         return 0;
 
-    InvokeContextMenuCommand(m_pCM, uCommand - CONTEXT_MENU_BASE_ID);
+    InvokeContextMenuCommand(m_pCM, uCommand - CONTEXT_MENU_BASE_ID, &pt);
 
     return 0;
 }
@@ -1710,7 +1713,8 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL 
bUseSelection)
             return 0;
     }
 
-    InvokeContextMenuCommand(pCM, uCommand);
+    // FIXME: We should probably use the objects position?
+    InvokeContextMenuCommand(pCM, uCommand, NULL);
     return 0;
 }
 
@@ -1950,7 +1954,7 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, 
LPARAM lParam, BOOL &bHand
             {
                 HMENU Dummy = NULL;
                 MenuCleanup _(m_pFileMenu, Dummy);
-                InvokeContextMenuCommand(m_pFileMenu, dwCmdID);
+                InvokeContextMenuCommand(m_pFileMenu, dwCmdID, NULL);
             }
     }
 
diff --git a/dll/win32/shell32/CDefaultContextMenu.cpp 
b/dll/win32/shell32/CDefaultContextMenu.cpp
index 6bddfafcb35..55aa8022af6 100644
--- a/dll/win32/shell32/CDefaultContextMenu.cpp
+++ b/dll/win32/shell32/CDefaultContextMenu.cpp
@@ -86,21 +86,21 @@ class CDefaultContextMenu :
         BOOL EnumerateDynamicContextHandlerForKey(HKEY hRootKey);
         UINT AddShellExtensionsToMenu(HMENU hMenu, UINT* pIndexMenu, UINT 
idCmdFirst, UINT idCmdLast);
         UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT* IndexMenu, UINT 
iIdCmdFirst, UINT iIdCmdLast);
-        HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink);
-        HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi);
-        HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi);
-        HRESULT DoDelete(LPCMINVOKECOMMANDINFO lpcmi);
-        HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy);
-        HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi);
-        HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi);
-        HRESULT DoUndo(LPCMINVOKECOMMANDINFO lpcmi);
-        HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFO lpici);
-        HRESULT DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFO lpici, BOOL bCopy);
-        HRESULT InvokeShellExt(LPCMINVOKECOMMANDINFO lpcmi);
-        HRESULT InvokeRegVerb(LPCMINVOKECOMMANDINFO lpcmi);
-        DWORD BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, 
PStaticShellEntry pEntry);
-        HRESULT TryToBrowse(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, 
DWORD wFlags);
-        HRESULT InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, 
PStaticShellEntry pEntry);
+        HRESULT DoPaste(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bLink);
+        HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFOEX lpcmi);
+        HRESULT DoCreateLink(LPCMINVOKECOMMANDINFOEX lpcmi);
+        HRESULT DoDelete(LPCMINVOKECOMMANDINFOEX lpcmi);
+        HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bCopy);
+        HRESULT DoRename(LPCMINVOKECOMMANDINFOEX lpcmi);
+        HRESULT DoProperties(LPCMINVOKECOMMANDINFOEX lpcmi);
+        HRESULT DoUndo(LPCMINVOKECOMMANDINFOEX lpcmi);
+        HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFOEX lpici);
+        HRESULT DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFOEX lpici, BOOL 
bCopy);
+        HRESULT InvokeShellExt(LPCMINVOKECOMMANDINFOEX lpcmi);
+        HRESULT InvokeRegVerb(LPCMINVOKECOMMANDINFOEX lpcmi);
+        DWORD BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, 
PStaticShellEntry pEntry);
+        HRESULT TryToBrowse(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, 
DWORD wFlags);
+        HRESULT InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, 
PStaticShellEntry pEntry);
         PDynamicShellEntry GetDynamicEntry(UINT idCmd);
         BOOL MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode);
 
@@ -695,7 +695,7 @@ CDefaultContextMenu::QueryContextMenu(
     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds);
 }
 
-HRESULT CDefaultContextMenu::DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink)
+HRESULT CDefaultContextMenu::DoPaste(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bLink)
 {
     HRESULT hr;
 
@@ -748,13 +748,13 @@ HRESULT 
CDefaultContextMenu::DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink)
 }
 
 HRESULT
-CDefaultContextMenu::DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi)
+CDefaultContextMenu::DoOpenOrExplore(LPCMINVOKECOMMANDINFOEX lpcmi)
 {
     UNIMPLEMENTED;
     return E_FAIL;
 }
 
-HRESULT CDefaultContextMenu::DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi)
+HRESULT CDefaultContextMenu::DoCreateLink(LPCMINVOKECOMMANDINFOEX lpcmi)
 {
     if (!m_cidl || !m_pDataObj)
         return E_FAIL;
@@ -769,7 +769,7 @@ HRESULT 
CDefaultContextMenu::DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi)
     return S_OK;
 }
 
-HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi)
+HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFOEX lpcmi)
 {
     if (!m_cidl || !m_pDataObj)
         return E_FAIL;
@@ -785,7 +785,7 @@ HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO 
lpcmi)
     return S_OK;
 }
 
-HRESULT CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL 
bCopy)
+HRESULT CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL 
bCopy)
 {
     if (!m_cidl || !m_pDataObj)
         return E_FAIL;
@@ -808,7 +808,7 @@ HRESULT 
CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy
     return S_OK;
 }
 
-HRESULT CDefaultContextMenu::DoRename(LPCMINVOKECOMMANDINFO lpcmi)
+HRESULT CDefaultContextMenu::DoRename(LPCMINVOKECOMMANDINFOEX lpcmi)
 {
     CComPtr<IShellBrowser> psb;
     HRESULT hr;
@@ -836,7 +836,7 @@ HRESULT CDefaultContextMenu::DoRename(LPCMINVOKECOMMANDINFO 
lpcmi)
 
 HRESULT
 CDefaultContextMenu::DoProperties(
-    LPCMINVOKECOMMANDINFO lpcmi)
+    LPCMINVOKECOMMANDINFOEX lpcmi)
 {
     HRESULT hr = _DoCallback(DFM_INVOKECOMMAND, DFM_CMD_PROPERTIES, NULL);
 
@@ -850,14 +850,14 @@ CDefaultContextMenu::DoProperties(
 }
 
 HRESULT
-CDefaultContextMenu::DoUndo(LPCMINVOKECOMMANDINFO lpcmi)
+CDefaultContextMenu::DoUndo(LPCMINVOKECOMMANDINFOEX lpcmi)
 {
     ERR("TODO: Undo\n");
     return E_NOTIMPL;
 }
 
 HRESULT
-CDefaultContextMenu::DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFO lpici, BOOL 
bCopy)
+CDefaultContextMenu::DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFOEX lpici, BOOL 
bCopy)
 {
     HRESULT hr = E_FAIL;
     if (!m_pDataObj)
@@ -890,13 +890,13 @@ 
CDefaultContextMenu::DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFO lpici, BOOL bCop
     else
         lpici->lpVerb = "moveto";
 
-    return pContextMenu->InvokeCommand(lpici);
+    return pContextMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)lpici);
 }
 
 // This code is taken from CNewMenu and should be shared between the 2 classes
 HRESULT
 CDefaultContextMenu::DoCreateNewFolder(
-    LPCMINVOKECOMMANDINFO lpici)
+    LPCMINVOKECOMMANDINFOEX lpici)
 {
     WCHAR wszPath[MAX_PATH];
     WCHAR wszName[MAX_PATH];
@@ -1009,7 +1009,7 @@ CDefaultContextMenu::MapVerbToCmdId(PVOID Verb, PUINT 
idCmd, BOOL IsUnicode)
 
 HRESULT
 CDefaultContextMenu::InvokeShellExt(
-    LPCMINVOKECOMMANDINFO lpcmi)
+    LPCMINVOKECOMMANDINFOEX lpcmi)
 {
     TRACE("verb %p first %x last %x\n", lpcmi->lpVerb, m_iIdSHEFirst, 
m_iIdSHELast);
 
@@ -1020,11 +1020,11 @@ CDefaultContextMenu::InvokeShellExt(
 
     /* invoke the dynamic context menu */
     lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd - pEntry->iIdCmdFirst);
-    return pEntry->pCM->InvokeCommand(lpcmi);
+    return pEntry->pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)lpcmi);
 }
 
 DWORD
-CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, 
PStaticShellEntry pEntry)
+CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, 
PStaticShellEntry pEntry)
 {
     CComPtr<IShellBrowser> psb;
     HWND hwndTree;
@@ -1064,7 +1064,7 @@ 
CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticSh
 
 HRESULT
 CDefaultContextMenu::TryToBrowse(
-    LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags)
+    LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, DWORD wFlags)
 {
     CComPtr<IShellBrowser> psb;
     HRESULT hr;
@@ -1081,7 +1081,7 @@ CDefaultContextMenu::TryToBrowse(
 }
 
 HRESULT
-CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST 
pidl, PStaticShellEntry pEntry)
+CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST 
pidl, PStaticShellEntry pEntry)
 {
     LPITEMIDLIST pidlFull = ILCombine(m_pidlFolder, pidl);
     if (pidlFull == NULL)
@@ -1127,7 +1127,7 @@ CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFO 
lpcmi, LPCITEMIDLIST pidl,
 
 HRESULT
 CDefaultContextMenu::InvokeRegVerb(
-    LPCMINVOKECOMMANDINFO lpcmi)
+    LPCMINVOKECOMMANDINFOEX lpcmi)
 {
     INT iCmd = LOWORD(lpcmi->lpVerb);
     HRESULT hr;
@@ -1174,13 +1174,13 @@ WINAPI
 CDefaultContextMenu::InvokeCommand(
     LPCMINVOKECOMMANDINFO lpcmi)
 {
-    CMINVOKECOMMANDINFO LocalInvokeInfo;
+    CMINVOKECOMMANDINFOEX LocalInvokeInfo = {};
     HRESULT Result;
     UINT CmdId;
 
     /* Take a local copy of the fixed members of the
        struct as we might need to modify the verb */
-    LocalInvokeInfo = *lpcmi;
+    memcpy(&LocalInvokeInfo, lpcmi, min(sizeof(LocalInvokeInfo), 
lpcmi->cbSize));
 
     /* Check if this is a string verb */
     if (HIWORD(LocalInvokeInfo.lpVerb))
@@ -1219,6 +1219,14 @@ CDefaultContextMenu::InvokeCommand(
         CmdId += 0x7000;
     }
 
+    if (LocalInvokeInfo.cbSize >= sizeof(CMINVOKECOMMANDINFOEX) && 
(LocalInvokeInfo.fMask & CMIC_MASK_PTINVOKE))
+    {
+        if (FAILED_UNEXPECTEDLY(DataObject_SetOffset(m_pDataObj, 
&LocalInvokeInfo.ptInvoke)))
+        {
+            ERR("Unable to add OFFSET to DataObject!\n");
+        }
+    }
+
     /* Check if this is a Id */
     switch (CmdId)
     {
diff --git a/dll/win32/shell32/dialogs/drive.cpp 
b/dll/win32/shell32/dialogs/drive.cpp
index 8f2484e298a..1a09a6ed712 100644
--- a/dll/win32/shell32/dialogs/drive.cpp
+++ b/dll/win32/shell32/dialogs/drive.cpp
@@ -166,59 +166,62 @@ typedef struct _DRIVE_PROP_PAGE
     UINT DriveType;
 } DRIVE_PROP_PAGE;
 
-HRESULT
-SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, 
PCUITEMID_CHILD_ARRAY apidl)
+BOOL
+SH_ShowDriveProperties(WCHAR *pwszDrive, IDataObject *pDataObj)
 {
     HPSXA hpsx = NULL;
     HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
-    PROPSHEETHEADERW psh;
     CComObject<CDrvDefExt> *pDrvDefExt = NULL;
-    WCHAR wszName[256];
 
-    ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
-    psh.dwSize = sizeof(PROPSHEETHEADERW);
-    psh.dwFlags = 0; // FIXME: make it modeless
-    psh.hwndParent = NULL;
-    psh.nStartPage = 0;
-    psh.phpage = hpsp;
+    CDataObjectHIDA cida(pDataObj);
+    if (FAILED_UNEXPECTEDLY(cida.hr()))
+        return cida.hr();
 
-    LPITEMIDLIST completePidl = ILCombine(pidlFolder, apidl[0]);
-    if (!completePidl)
-        return E_OUTOFMEMORY;
-
-    if (ILGetDisplayNameExW(NULL, completePidl, wszName, ILGDN_NORMAL))
+    RECT rcPosition = {CW_USEDEFAULT, CW_USEDEFAULT, 0, 0};
+    POINT pt;
+    if (SUCCEEDED(DataObject_GetOffset(pDataObj, &pt)))
     {
-        psh.pszCaption = wszName;
-        psh.dwFlags |= PSH_PROPTITLE;
+        rcPosition.left = pt.x;
+        rcPosition.top = pt.y;
     }
 
-    ILFree(completePidl);
+    DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
+    DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW;
+    CStubWindow32 stub;
+    if (!stub.Create(NULL, rcPosition, NULL, style, exstyle))
+    {
+        ERR("StubWindow32 creation failed\n");
+        return FALSE;
+    }
 
-    CComPtr<IDataObject> pDataObj;
-    HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, 
IID_PPV_ARG(IDataObject, &pDataObj));
+    PROPSHEETHEADERW psh = {sizeof(PROPSHEETHEADERW)};
+    psh.dwFlags = PSH_PROPTITLE;
+    psh.pszCaption = pwszDrive;
+    psh.hwndParent = stub;
+    psh.nStartPage = 0;
+    psh.phpage = hpsp;
 
+    HRESULT hr = CComObject<CDrvDefExt>::CreateInstance(&pDrvDefExt);
     if (SUCCEEDED(hr))
     {
-        hr = CComObject<CDrvDefExt>::CreateInstance(&pDrvDefExt);
+        pDrvDefExt->AddRef(); // CreateInstance returns object with 0 ref count
+        hr = pDrvDefExt->Initialize(HIDA_GetPIDLFolder(cida), pDataObj, NULL);
         if (SUCCEEDED(hr))
         {
-            pDrvDefExt->AddRef(); // CreateInstance returns object with 0 ref 
count
-            hr = pDrvDefExt->Initialize(pidlFolder, pDataObj, NULL);
-            if (SUCCEEDED(hr))
-            {
-                hr = pDrvDefExt->AddPages(AddPropSheetPageCallback, 
(LPARAM)&psh);
-                if (FAILED(hr))
-                    ERR("AddPages failed\n");
-            } else
-                ERR("Initialize failed\n");
+            hr = pDrvDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&psh);
+            if (FAILED(hr))
+                ERR("AddPages failed\n");
+        }
+        else
+        {
+            ERR("Initialize failed\n");
         }
-
-        hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", 
MAX_PROPERTY_SHEET_PAGE, pDataObj);
-        if (hpsx)
-            SHAddFromPropSheetExtArray(hpsx, 
(LPFNADDPROPSHEETPAGE)AddPropSheetPageCallback, (LPARAM)&psh);
     }
 
-    // NOTE: Currently property sheet is modal. If we make it modeless, then 
it returns HWND.
+    hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", 
MAX_PROPERTY_SHEET_PAGE, pDataObj);
+    if (hpsx)
+        SHAddFromPropSheetExtArray(hpsx, 
(LPFNADDPROPSHEETPAGE)AddPropSheetPageCallback, (LPARAM)&psh);
+
     INT_PTR ret = PropertySheetW(&psh);
 
     if (hpsx)
@@ -226,9 +229,9 @@ SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST 
pidlFolder, PCUITEMID_CHI
     if (pDrvDefExt)
         pDrvDefExt->Release();
 
-    if (ret >= 0)
-        return S_OK;
-    return E_FAIL;
+    stub.DestroyWindow();
+
+    return ret != -1;
 }
 
 static VOID
diff --git a/dll/win32/shell32/dialogs/fprop.cpp 
b/dll/win32/shell32/dialogs/fprop.cpp
index b43ee566e85..68872bc4c69 100644
--- a/dll/win32/shell32/dialogs/fprop.cpp
+++ b/dll/win32/shell32/dialogs/fprop.cpp
@@ -80,7 +80,7 @@ LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW 
*pHeader, UINT cMaxPage
  */
 
 BOOL
-SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, 
PCUITEMID_CHILD_ARRAY apidl)
+SH_ShowPropertiesDialog(LPCWSTR pwszPath, IDataObject *pDataObj)
 {
     HPSXA hpsxa[3] = {NULL, NULL, NULL};
     CComObject<CFileDefExt> *pFileDefExt = NULL;
@@ -100,14 +100,33 @@ SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST 
pidlFolder, PCUITEMID_CH
     /* remove trailing \\ at the end of path */
     PathRemoveBackslashW(wszPath);
 
+    CDataObjectHIDA cida(pDataObj);
+    if (FAILED_UNEXPECTEDLY(cida.hr()))
+        return FALSE;
+
+    if (cida->cidl == 0)
+    {
+        ERR("Empty HIDA\n");
+        return FALSE;
+    }
+
     /* Handle drives */
-    if (PathIsRootW(wszPath))
-        return SUCCEEDED(SH_ShowDriveProperties(wszPath, pidlFolder, apidl));
+    if (_ILIsDrive(HIDA_GetPIDLItem(cida, 0)))
+        return SH_ShowDriveProperties(wszPath, pDataObj);
+
+
+    RECT rcPosition = {CW_USEDEFAULT, CW_USEDEFAULT, 0, 0};
+    POINT pt;
+    if (SUCCEEDED(DataObject_GetOffset(pDataObj, &pt)))
+    {
+        rcPosition.left = pt.x;
+        rcPosition.top = pt.y;
+    }
 
     DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
     DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW;
     CStubWindow32 stub;
-    if (!stub.Create(NULL, NULL, NULL, style, exstyle))
+    if (!stub.Create(NULL, rcPosition, NULL, style, exstyle))
     {
         ERR("StubWindow32 creation failed\n");
         return FALSE;
@@ -122,35 +141,29 @@ SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST 
pidlFolder, PCUITEMID_CH
     Header.phpage = hppages;
     Header.pszCaption = PathFindFileNameW(wszPath);
 
-    CComPtr<IDataObject> pDataObj;
-    HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, 
IID_PPV_ARG(IDataObject, &pDataObj));
-
+    HRESULT hr = CComObject<CFileDefExt>::CreateInstance(&pFileDefExt);
     if (SUCCEEDED(hr))
     {
-        hr = CComObject<CFileDefExt>::CreateInstance(&pFileDefExt);
-        if (SUCCEEDED(hr))
+        pFileDefExt->AddRef(); // CreateInstance returns object with 0 ref 
count
+        hr = pFileDefExt->Initialize(HIDA_GetPIDLFolder(cida), pDataObj, NULL);
+        if (!FAILED_UNEXPECTEDLY(hr))
         {
-            pFileDefExt->AddRef(); // CreateInstance returns object with 0 ref 
count
-            hr = pFileDefExt->Initialize(pidlFolder, pDataObj, NULL);
-            if (!FAILED_UNEXPECTEDLY(hr))
-            {
-                hr = pFileDefExt->AddPages(AddPropSheetPageCallback, 
(LPARAM)&Header);
-                if (FAILED_UNEXPECTEDLY(hr))
-                {
-                    ERR("AddPages failed\n");
-                    return FALSE;
-                }
-            }
-            else
+            hr = pFileDefExt->AddPages(AddPropSheetPageCallback, 
(LPARAM)&Header);
+            if (FAILED_UNEXPECTEDLY(hr))
             {
-                ERR("Initialize failed\n");
+                ERR("AddPages failed\n");
                 return FALSE;
             }
         }
-
-        LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, 
hpsxa, pDataObj);
+        else
+        {
+            ERR("Initialize failed\n");
+            return FALSE;
+        }
     }
 
+    LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, 
hpsxa, pDataObj);
+
     INT_PTR Result = PropertySheetW(&Header);
 
     for (UINT i = 0; i < 3; ++i)
diff --git a/dll/win32/shell32/folders/CDrivesFolder.cpp 
b/dll/win32/shell32/folders/CDrivesFolder.cpp
index b8ef36e2ea0..805bfee1ac0 100644
--- a/dll/win32/shell32/folders/CDrivesFolder.cpp
+++ b/dll/win32/shell32/folders/CDrivesFolder.cpp
@@ -329,7 +329,9 @@ HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder 
*psf,
 
         if (wParam == DFM_CMD_PROPERTIES)
         {
-            hr = SH_ShowDriveProperties(wszBuf, pidlFolder, apidl);
+            // pdtobj should be valid at this point!
+            ATLASSERT(pdtobj);
+            hr = SH_ShowDriveProperties(wszBuf, pdtobj);
             if (FAILED(hr))
             {
                 dwError = ERROR_CAN_NOT_COMPLETE;
diff --git a/dll/win32/shell32/folders/CFSFolder.cpp 
b/dll/win32/shell32/folders/CFSFolder.cpp
index cf8d0c99233..4b7d8b3990b 100644
--- a/dll/win32/shell32/folders/CFSFolder.cpp
+++ b/dll/win32/shell32/folders/CFSFolder.cpp
@@ -1811,14 +1811,24 @@ HRESULT WINAPI CFSFolder::CallBack(IShellFolder *psf, 
HWND hwndOwner, IDataObjec
     {
         if (uMsg == DFM_INVOKECOMMAND && wParam == 0)
         {
-            PUITEMID_CHILD pidlChild = ILClone(ILFindLastID(m_pidlRoot));
-            LPITEMIDLIST pidlParent = ILClone(m_pidlRoot);
+            // Create an data object
+            CComHeapPtr<ITEMID_CHILD> 
pidlChild(ILClone(ILFindLastID(m_pidlRoot)));
+            CComHeapPtr<ITEMIDLIST> pidlParent(ILClone(m_pidlRoot));
             ILRemoveLastID(pidlParent);
-            BOOL bSuccess = SH_ShowPropertiesDialog(m_sPathTarget, pidlParent, 
&pidlChild);
-            if (!bSuccess)
-                ERR("SH_ShowPropertiesDialog failed\n");
-            ILFree(pidlChild);
-            ILFree(pidlParent);
+
+            CComPtr<IDataObject> pDataObj;
+            HRESULT hr = SHCreateDataObject(pidlParent, 1, &pidlChild, NULL, 
IID_PPV_ARG(IDataObject, &pDataObj));
+            if (!FAILED_UNEXPECTEDLY(hr))
+            {
+                // Ask for a title to display
+                CComHeapPtr<WCHAR> wszName;
+                if (!FAILED_UNEXPECTEDLY(SHGetNameFromIDList(m_pidlRoot, 
SIGDN_PARENTRELATIVEPARSING, &wszName)))
+                {
+                    BOOL bSuccess = SH_ShowPropertiesDialog(wszName, pDataObj);
+                    if (!bSuccess)
+                        ERR("SH_ShowPropertiesDialog failed\n");
+                }
+            }
         }
         else if (uMsg == DFM_MERGECONTEXTMENU)
         {
diff --git a/dll/win32/shell32/shlfolder.cpp b/dll/win32/shell32/shlfolder.cpp
index 01018b44ede..315ad7d74c1 100644
--- a/dll/win32/shell32/shlfolder.cpp
+++ b/dll/win32/shell32/shlfolder.cpp
@@ -460,25 +460,14 @@ _ShowPropertiesDialogThread(LPVOID lpParameter)
         return E_FAIL;
     }
 
-    PCUIDLIST_ABSOLUTE pidlFolder = HIDA_GetPIDLFolder(cida);
-    CComPtr<IShellFolder> psfParent;
-    HRESULT hr = _SHBindToFolder(pidlFolder, &psfParent);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
-
-    STRRET strFile;
-    PCUIDLIST_RELATIVE apidl = HIDA_GetPIDLItem(cida, 0);
-    hr = psfParent->GetDisplayNameOf(apidl, SHGDN_FORPARSING, &strFile);
-    if (!FAILED_UNEXPECTEDLY(hr))
-    {
-        BOOL bSuccess = SH_ShowPropertiesDialog(strFile.pOleStr, pidlFolder, 
&apidl);
-        if (!bSuccess)
-            ERR("SH_ShowPropertiesDialog failed\n");
-    }
-    else
-    {
-        ERR("Failed to get display name\n");
-    }
+    CComHeapPtr<ITEMIDLIST> completePidl(ILCombine(HIDA_GetPIDLFolder(cida), 
HIDA_GetPIDLItem(cida, 0)));
+    CComHeapPtr<WCHAR> wszName;
+    if (FAILED_UNEXPECTEDLY(SHGetNameFromIDList(completePidl, 
SIGDN_PARENTRELATIVEPARSING, &wszName)))
+        return 0;
+
+    BOOL bSuccess = SH_ShowPropertiesDialog(wszName, pDataObject);
+    if (!bSuccess)
+        ERR("SH_ShowPropertiesDialog failed\n");
 
     return 0;
 }
diff --git a/dll/win32/shell32/wine/shell32_main.h 
b/dll/win32/shell32/wine/shell32_main.h
index 1585f60aedd..a9da0b2e10f 100644
--- a/dll/win32/shell32/wine/shell32_main.h
+++ b/dll/win32/shell32/wine/shell32_main.h
@@ -186,9 +186,9 @@ BOOL SHELL_IsShortcut(LPCITEMIDLIST) DECLSPEC_HIDDEN;
 INT_PTR CALLBACK SH_FileGeneralDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, 
LPARAM lParam);
 INT_PTR CALLBACK SH_FileVersionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, 
LPARAM lParam);
 HPROPSHEETPAGE SH_CreatePropertySheetPage(WORD wDialogId, DLGPROC pfnDlgProc, 
LPARAM lParam, LPCWSTR pwszTitle);
-HRESULT SH_ShowDriveProperties(WCHAR *drive, LPCITEMIDLIST pidlFolder, 
PCUITEMID_CHILD_ARRAY apidl);
+BOOL SH_ShowDriveProperties(WCHAR *drive, IDataObject *pDataObj);
 BOOL SH_ShowRecycleBinProperties(WCHAR sDrive);
-BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, 
PCUITEMID_CHILD_ARRAY apidl);
+BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, IDataObject *pDataObj);
 LPWSTR SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, 
UINT cchBuf);
 
 HRESULT WINAPI DoRegisterServer(void);
diff --git a/sdk/include/reactos/shellutils.h b/sdk/include/reactos/shellutils.h
index 7a3c7265059..f516d8c6830 100644
--- a/sdk/include/reactos/shellutils.h
+++ b/sdk/include/reactos/shellutils.h
@@ -560,6 +560,7 @@ static inline PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA 
const* pida, SIZE_T i)
 #ifdef __cplusplus
 
 DECLSPEC_SELECTANY CLIPFORMAT g_cfHIDA = NULL;
+DECLSPEC_SELECTANY CLIPFORMAT g_cfShellIdListOffsets = NULL;
 
 // Allow to use the HIDA from an IDataObject without copying it
 struct CDataObjectHIDA
@@ -684,6 +685,31 @@ HRESULT DataObject_SetData(IDataObject* pDataObject, 
CLIPFORMAT clipformat, PVOI
     return hr;
 }
 
+
+inline HRESULT
+DataObject_GetOffset(IDataObject *pDataObject, POINT *point)
+{
+    if (g_cfShellIdListOffsets == NULL)
+    {
+        g_cfShellIdListOffsets = 
(CLIPFORMAT)RegisterClipboardFormatW(CFSTR_SHELLIDLISTOFFSETW);
+    }
+
+    point->x = point->y = 0;
+
+    return DataObject_GetData(pDataObject, g_cfShellIdListOffsets, point, 
sizeof(point[0]));
+}
+
+inline HRESULT
+DataObject_SetOffset(IDataObject* pDataObject, POINT* point)
+{
+    if (g_cfShellIdListOffsets == NULL)
+    {
+        g_cfShellIdListOffsets = 
(CLIPFORMAT)RegisterClipboardFormatW(CFSTR_SHELLIDLISTOFFSETW);
+    }
+
+    return DataObject_SetData(pDataObject, g_cfShellIdListOffsets, point, 
sizeof(point[0]));
+}
+
 #endif
 
 

Reply via email to