https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6a1f287820e6ada7d957a…
commit 6a1f287820e6ada7d957a6451a7ecc54f73c1876
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Thu Sep 22 19:27:33 2022 +0200
Commit: Mark Jansen <mark.jansen(a)reactos.org>
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