[SHELL32] Show file / drive properties at the position where the mouse was.

CORE-18386
This commit is contained in:
Mark Jansen 2022-09-22 19:27:33 +02:00
parent 26408144a1
commit 6a1f287820
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
9 changed files with 198 additions and 143 deletions

View file

@ -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);
}
}

View file

@ -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)
{

View file

@ -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;
CDataObjectHIDA cida(pDataObj);
if (FAILED_UNEXPECTEDLY(cida.hr()))
return cida.hr();
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, rcPosition, NULL, style, exstyle))
{
ERR("StubWindow32 creation failed\n");
return FALSE;
}
PROPSHEETHEADERW psh = {sizeof(PROPSHEETHEADERW)};
psh.dwFlags = PSH_PROPTITLE;
psh.pszCaption = pwszDrive;
psh.hwndParent = stub;
psh.nStartPage = 0;
psh.phpage = hpsp;
LPITEMIDLIST completePidl = ILCombine(pidlFolder, apidl[0]);
if (!completePidl)
return E_OUTOFMEMORY;
if (ILGetDisplayNameExW(NULL, completePidl, wszName, ILGDN_NORMAL))
{
psh.pszCaption = wszName;
psh.dwFlags |= PSH_PROPTITLE;
}
ILFree(completePidl);
CComPtr<IDataObject> pDataObj;
HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
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

View file

@ -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))
{
hr = pFileDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&Header);
if (FAILED_UNEXPECTEDLY(hr))
{
ERR("AddPages failed\n");
return FALSE;
}
}
else
{
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)

View file

@ -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;

View file

@ -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)
{

View file

@ -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;
CComHeapPtr<ITEMIDLIST> completePidl(ILCombine(HIDA_GetPIDLFolder(cida), HIDA_GetPIDLItem(cida, 0)));
CComHeapPtr<WCHAR> wszName;
if (FAILED_UNEXPECTEDLY(SHGetNameFromIDList(completePidl, SIGDN_PARENTRELATIVEPARSING, &wszName)))
return 0;
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");
}
BOOL bSuccess = SH_ShowPropertiesDialog(wszName, pDataObject);
if (!bSuccess)
ERR("SH_ShowPropertiesDialog failed\n");
return 0;
}

View file

@ -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);

View file

@ -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