[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 OnDeactivate();
void DoActivate(UINT uState); void DoActivate(UINT uState);
HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 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); LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
// *** IOleWindow methods *** // *** IOleWindow methods ***
@ -1496,9 +1496,9 @@ UINT CDefView::GetSelections()
return m_cidl; 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)); ZeroMemory(&cmi, sizeof(cmi));
cmi.cbSize = sizeof(cmi); cmi.cbSize = sizeof(cmi);
@ -1511,7 +1511,13 @@ HRESULT CDefView::InvokeContextMenuCommand(CComPtr<IContextMenu> &pCM, UINT uCom
if (GetKeyState(VK_CONTROL) & 0x8000) if (GetKeyState(VK_CONTROL) & 0x8000)
cmi.fMask |= CMIC_MASK_CONTROL_DOWN; 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!) // Most of our callers will do this, but in case they don't do that (File menu!)
IUnknown_SetSite(pCM, NULL); IUnknown_SetSite(pCM, NULL);
pCM.Release(); pCM.Release();
@ -1560,7 +1566,7 @@ HRESULT CDefView::OpenSelectedItems()
return E_FAIL; return E_FAIL;
} }
InvokeContextMenuCommand(pCM, uCommand); InvokeContextMenuCommand(pCM, uCommand, NULL);
return hResult; return hResult;
} }
@ -1570,7 +1576,7 @@ HRESULT CDefView::OpenSelectedItems()
*/ */
LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{ {
int x, y; POINT pt;
UINT uCommand; UINT uCommand;
HRESULT hResult; 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 if (lParam != ~0) // unless app key (menu key) was pressed
{ {
x = GET_X_LPARAM(lParam); pt.x = GET_X_LPARAM(lParam);
y = GET_Y_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
LV_HITTESTINFO hittest = { { x, y } }; LV_HITTESTINFO hittest = { pt };
ScreenToClient(&hittest.pt); ScreenToClient(&hittest.pt);
m_ListView.HitTest(&hittest); m_ListView.HitTest(&hittest);
@ -1621,7 +1627,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
{ {
HWND hFocus = ::GetFocus(); HWND hFocus = ::GetFocus();
int lvIndex = -1; int lvIndex = -1;
POINT pt;
if (hFocus == m_ListView.m_hWnd || m_ListView.IsChild(hFocus)) 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); 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) // 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, uCommand = TrackPopupMenu(m_hContextMenu,
TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, 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) if (uCommand == 0)
return 0; return 0;
if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK) if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
return 0; return 0;
InvokeContextMenuCommand(m_pCM, uCommand - CONTEXT_MENU_BASE_ID); InvokeContextMenuCommand(m_pCM, uCommand - CONTEXT_MENU_BASE_ID, &pt);
return 0; return 0;
} }
@ -1710,7 +1713,8 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
return 0; return 0;
} }
InvokeContextMenuCommand(pCM, uCommand); // FIXME: We should probably use the objects position?
InvokeContextMenuCommand(pCM, uCommand, NULL);
return 0; return 0;
} }
@ -1950,7 +1954,7 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand
{ {
HMENU Dummy = NULL; HMENU Dummy = NULL;
MenuCleanup _(m_pFileMenu, Dummy); 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); BOOL EnumerateDynamicContextHandlerForKey(HKEY hRootKey);
UINT AddShellExtensionsToMenu(HMENU hMenu, UINT* pIndexMenu, UINT idCmdFirst, UINT idCmdLast); UINT AddShellExtensionsToMenu(HMENU hMenu, UINT* pIndexMenu, UINT idCmdFirst, UINT idCmdLast);
UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT* IndexMenu, UINT iIdCmdFirst, UINT iIdCmdLast); UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT* IndexMenu, UINT iIdCmdFirst, UINT iIdCmdLast);
HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink); HRESULT DoPaste(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bLink);
HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFOEX lpcmi);
HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoCreateLink(LPCMINVOKECOMMANDINFOEX lpcmi);
HRESULT DoDelete(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoDelete(LPCMINVOKECOMMANDINFOEX lpcmi);
HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy); HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bCopy);
HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoRename(LPCMINVOKECOMMANDINFOEX lpcmi);
HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoProperties(LPCMINVOKECOMMANDINFOEX lpcmi);
HRESULT DoUndo(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoUndo(LPCMINVOKECOMMANDINFOEX lpcmi);
HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFO lpici); HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFOEX lpici);
HRESULT DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFO lpici, BOOL bCopy); HRESULT DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFOEX lpici, BOOL bCopy);
HRESULT InvokeShellExt(LPCMINVOKECOMMANDINFO lpcmi); HRESULT InvokeShellExt(LPCMINVOKECOMMANDINFOEX lpcmi);
HRESULT InvokeRegVerb(LPCMINVOKECOMMANDINFO lpcmi); HRESULT InvokeRegVerb(LPCMINVOKECOMMANDINFOEX lpcmi);
DWORD BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry); DWORD BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, PStaticShellEntry pEntry);
HRESULT TryToBrowse(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags); HRESULT TryToBrowse(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, DWORD wFlags);
HRESULT InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry); HRESULT InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry);
PDynamicShellEntry GetDynamicEntry(UINT idCmd); PDynamicShellEntry GetDynamicEntry(UINT idCmd);
BOOL MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode); BOOL MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode);
@ -695,7 +695,7 @@ CDefaultContextMenu::QueryContextMenu(
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds); return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds);
} }
HRESULT CDefaultContextMenu::DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink) HRESULT CDefaultContextMenu::DoPaste(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bLink)
{ {
HRESULT hr; HRESULT hr;
@ -748,13 +748,13 @@ HRESULT CDefaultContextMenu::DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink)
} }
HRESULT HRESULT
CDefaultContextMenu::DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi) CDefaultContextMenu::DoOpenOrExplore(LPCMINVOKECOMMANDINFOEX lpcmi)
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
return E_FAIL; return E_FAIL;
} }
HRESULT CDefaultContextMenu::DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi) HRESULT CDefaultContextMenu::DoCreateLink(LPCMINVOKECOMMANDINFOEX lpcmi)
{ {
if (!m_cidl || !m_pDataObj) if (!m_cidl || !m_pDataObj)
return E_FAIL; return E_FAIL;
@ -769,7 +769,7 @@ HRESULT CDefaultContextMenu::DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi)
return S_OK; return S_OK;
} }
HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi) HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFOEX lpcmi)
{ {
if (!m_cidl || !m_pDataObj) if (!m_cidl || !m_pDataObj)
return E_FAIL; return E_FAIL;
@ -785,7 +785,7 @@ HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi)
return S_OK; return S_OK;
} }
HRESULT CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy) HRESULT CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bCopy)
{ {
if (!m_cidl || !m_pDataObj) if (!m_cidl || !m_pDataObj)
return E_FAIL; return E_FAIL;
@ -808,7 +808,7 @@ HRESULT CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy
return S_OK; return S_OK;
} }
HRESULT CDefaultContextMenu::DoRename(LPCMINVOKECOMMANDINFO lpcmi) HRESULT CDefaultContextMenu::DoRename(LPCMINVOKECOMMANDINFOEX lpcmi)
{ {
CComPtr<IShellBrowser> psb; CComPtr<IShellBrowser> psb;
HRESULT hr; HRESULT hr;
@ -836,7 +836,7 @@ HRESULT CDefaultContextMenu::DoRename(LPCMINVOKECOMMANDINFO lpcmi)
HRESULT HRESULT
CDefaultContextMenu::DoProperties( CDefaultContextMenu::DoProperties(
LPCMINVOKECOMMANDINFO lpcmi) LPCMINVOKECOMMANDINFOEX lpcmi)
{ {
HRESULT hr = _DoCallback(DFM_INVOKECOMMAND, DFM_CMD_PROPERTIES, NULL); HRESULT hr = _DoCallback(DFM_INVOKECOMMAND, DFM_CMD_PROPERTIES, NULL);
@ -850,14 +850,14 @@ CDefaultContextMenu::DoProperties(
} }
HRESULT HRESULT
CDefaultContextMenu::DoUndo(LPCMINVOKECOMMANDINFO lpcmi) CDefaultContextMenu::DoUndo(LPCMINVOKECOMMANDINFOEX lpcmi)
{ {
ERR("TODO: Undo\n"); ERR("TODO: Undo\n");
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT HRESULT
CDefaultContextMenu::DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFO lpici, BOOL bCopy) CDefaultContextMenu::DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFOEX lpici, BOOL bCopy)
{ {
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
if (!m_pDataObj) if (!m_pDataObj)
@ -890,13 +890,13 @@ CDefaultContextMenu::DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFO lpici, BOOL bCop
else else
lpici->lpVerb = "moveto"; 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 // This code is taken from CNewMenu and should be shared between the 2 classes
HRESULT HRESULT
CDefaultContextMenu::DoCreateNewFolder( CDefaultContextMenu::DoCreateNewFolder(
LPCMINVOKECOMMANDINFO lpici) LPCMINVOKECOMMANDINFOEX lpici)
{ {
WCHAR wszPath[MAX_PATH]; WCHAR wszPath[MAX_PATH];
WCHAR wszName[MAX_PATH]; WCHAR wszName[MAX_PATH];
@ -1009,7 +1009,7 @@ CDefaultContextMenu::MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode)
HRESULT HRESULT
CDefaultContextMenu::InvokeShellExt( CDefaultContextMenu::InvokeShellExt(
LPCMINVOKECOMMANDINFO lpcmi) LPCMINVOKECOMMANDINFOEX lpcmi)
{ {
TRACE("verb %p first %x last %x\n", lpcmi->lpVerb, m_iIdSHEFirst, m_iIdSHELast); 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 */ /* invoke the dynamic context menu */
lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd - pEntry->iIdCmdFirst); lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd - pEntry->iIdCmdFirst);
return pEntry->pCM->InvokeCommand(lpcmi); return pEntry->pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)lpcmi);
} }
DWORD DWORD
CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry) CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, PStaticShellEntry pEntry)
{ {
CComPtr<IShellBrowser> psb; CComPtr<IShellBrowser> psb;
HWND hwndTree; HWND hwndTree;
@ -1064,7 +1064,7 @@ CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticSh
HRESULT HRESULT
CDefaultContextMenu::TryToBrowse( CDefaultContextMenu::TryToBrowse(
LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags) LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, DWORD wFlags)
{ {
CComPtr<IShellBrowser> psb; CComPtr<IShellBrowser> psb;
HRESULT hr; HRESULT hr;
@ -1081,7 +1081,7 @@ CDefaultContextMenu::TryToBrowse(
} }
HRESULT HRESULT
CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry) CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry)
{ {
LPITEMIDLIST pidlFull = ILCombine(m_pidlFolder, pidl); LPITEMIDLIST pidlFull = ILCombine(m_pidlFolder, pidl);
if (pidlFull == NULL) if (pidlFull == NULL)
@ -1127,7 +1127,7 @@ CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl,
HRESULT HRESULT
CDefaultContextMenu::InvokeRegVerb( CDefaultContextMenu::InvokeRegVerb(
LPCMINVOKECOMMANDINFO lpcmi) LPCMINVOKECOMMANDINFOEX lpcmi)
{ {
INT iCmd = LOWORD(lpcmi->lpVerb); INT iCmd = LOWORD(lpcmi->lpVerb);
HRESULT hr; HRESULT hr;
@ -1174,13 +1174,13 @@ WINAPI
CDefaultContextMenu::InvokeCommand( CDefaultContextMenu::InvokeCommand(
LPCMINVOKECOMMANDINFO lpcmi) LPCMINVOKECOMMANDINFO lpcmi)
{ {
CMINVOKECOMMANDINFO LocalInvokeInfo; CMINVOKECOMMANDINFOEX LocalInvokeInfo = {};
HRESULT Result; HRESULT Result;
UINT CmdId; UINT CmdId;
/* Take a local copy of the fixed members of the /* Take a local copy of the fixed members of the
struct as we might need to modify the verb */ 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 */ /* Check if this is a string verb */
if (HIWORD(LocalInvokeInfo.lpVerb)) if (HIWORD(LocalInvokeInfo.lpVerb))
@ -1219,6 +1219,14 @@ CDefaultContextMenu::InvokeCommand(
CmdId += 0x7000; 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 */ /* Check if this is a Id */
switch (CmdId) switch (CmdId)
{ {

View file

@ -166,59 +166,62 @@ typedef struct _DRIVE_PROP_PAGE
UINT DriveType; UINT DriveType;
} DRIVE_PROP_PAGE; } DRIVE_PROP_PAGE;
HRESULT BOOL
SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl) SH_ShowDriveProperties(WCHAR *pwszDrive, IDataObject *pDataObj)
{ {
HPSXA hpsx = NULL; HPSXA hpsx = NULL;
HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE]; HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
PROPSHEETHEADERW psh;
CComObject<CDrvDefExt> *pDrvDefExt = NULL; CComObject<CDrvDefExt> *pDrvDefExt = NULL;
WCHAR wszName[256];
ZeroMemory(&psh, sizeof(PROPSHEETHEADERW)); CDataObjectHIDA cida(pDataObj);
psh.dwSize = sizeof(PROPSHEETHEADERW); if (FAILED_UNEXPECTEDLY(cida.hr()))
psh.dwFlags = 0; // FIXME: make it modeless return cida.hr();
psh.hwndParent = NULL;
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.nStartPage = 0;
psh.phpage = hpsp; psh.phpage = hpsp;
LPITEMIDLIST completePidl = ILCombine(pidlFolder, apidl[0]); HRESULT hr = CComObject<CDrvDefExt>::CreateInstance(&pDrvDefExt);
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));
if (SUCCEEDED(hr)) 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)) if (SUCCEEDED(hr))
{ {
pDrvDefExt->AddRef(); // CreateInstance returns object with 0 ref count hr = pDrvDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&psh);
hr = pDrvDefExt->Initialize(pidlFolder, pDataObj, NULL); if (FAILED(hr))
if (SUCCEEDED(hr)) ERR("AddPages failed\n");
{ }
hr = pDrvDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&psh); else
if (FAILED(hr)) {
ERR("AddPages failed\n"); ERR("Initialize 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); INT_PTR ret = PropertySheetW(&psh);
if (hpsx) if (hpsx)
@ -226,9 +229,9 @@ SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHI
if (pDrvDefExt) if (pDrvDefExt)
pDrvDefExt->Release(); pDrvDefExt->Release();
if (ret >= 0) stub.DestroyWindow();
return S_OK;
return E_FAIL; return ret != -1;
} }
static VOID static VOID

View file

@ -80,7 +80,7 @@ LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW *pHeader, UINT cMaxPage
*/ */
BOOL BOOL
SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl) SH_ShowPropertiesDialog(LPCWSTR pwszPath, IDataObject *pDataObj)
{ {
HPSXA hpsxa[3] = {NULL, NULL, NULL}; HPSXA hpsxa[3] = {NULL, NULL, NULL};
CComObject<CFileDefExt> *pFileDefExt = NULL; CComObject<CFileDefExt> *pFileDefExt = NULL;
@ -100,14 +100,33 @@ SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CH
/* remove trailing \\ at the end of path */ /* remove trailing \\ at the end of path */
PathRemoveBackslashW(wszPath); PathRemoveBackslashW(wszPath);
CDataObjectHIDA cida(pDataObj);
if (FAILED_UNEXPECTEDLY(cida.hr()))
return FALSE;
if (cida->cidl == 0)
{
ERR("Empty HIDA\n");
return FALSE;
}
/* Handle drives */ /* Handle drives */
if (PathIsRootW(wszPath)) if (_ILIsDrive(HIDA_GetPIDLItem(cida, 0)))
return SUCCEEDED(SH_ShowDriveProperties(wszPath, pidlFolder, apidl)); 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 style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW; DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW;
CStubWindow32 stub; CStubWindow32 stub;
if (!stub.Create(NULL, NULL, NULL, style, exstyle)) if (!stub.Create(NULL, rcPosition, NULL, style, exstyle))
{ {
ERR("StubWindow32 creation failed\n"); ERR("StubWindow32 creation failed\n");
return FALSE; return FALSE;
@ -122,35 +141,29 @@ SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CH
Header.phpage = hppages; Header.phpage = hppages;
Header.pszCaption = PathFindFileNameW(wszPath); Header.pszCaption = PathFindFileNameW(wszPath);
CComPtr<IDataObject> pDataObj; HRESULT hr = CComObject<CFileDefExt>::CreateInstance(&pFileDefExt);
HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = CComObject<CFileDefExt>::CreateInstance(&pFileDefExt); pFileDefExt->AddRef(); // CreateInstance returns object with 0 ref count
if (SUCCEEDED(hr)) hr = pFileDefExt->Initialize(HIDA_GetPIDLFolder(cida), pDataObj, NULL);
if (!FAILED_UNEXPECTEDLY(hr))
{ {
pFileDefExt->AddRef(); // CreateInstance returns object with 0 ref count hr = pFileDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&Header);
hr = pFileDefExt->Initialize(pidlFolder, pDataObj, NULL); if (FAILED_UNEXPECTEDLY(hr))
if (!FAILED_UNEXPECTEDLY(hr))
{ {
hr = pFileDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&Header); ERR("AddPages failed\n");
if (FAILED_UNEXPECTEDLY(hr))
{
ERR("AddPages failed\n");
return FALSE;
}
}
else
{
ERR("Initialize failed\n");
return FALSE; return FALSE;
} }
} }
else
LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, hpsxa, pDataObj); {
ERR("Initialize failed\n");
return FALSE;
}
} }
LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, hpsxa, pDataObj);
INT_PTR Result = PropertySheetW(&Header); INT_PTR Result = PropertySheetW(&Header);
for (UINT i = 0; i < 3; ++i) for (UINT i = 0; i < 3; ++i)

View file

@ -329,7 +329,9 @@ HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
if (wParam == DFM_CMD_PROPERTIES) 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)) if (FAILED(hr))
{ {
dwError = ERROR_CAN_NOT_COMPLETE; 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) if (uMsg == DFM_INVOKECOMMAND && wParam == 0)
{ {
PUITEMID_CHILD pidlChild = ILClone(ILFindLastID(m_pidlRoot)); // Create an data object
LPITEMIDLIST pidlParent = ILClone(m_pidlRoot); CComHeapPtr<ITEMID_CHILD> pidlChild(ILClone(ILFindLastID(m_pidlRoot)));
CComHeapPtr<ITEMIDLIST> pidlParent(ILClone(m_pidlRoot));
ILRemoveLastID(pidlParent); ILRemoveLastID(pidlParent);
BOOL bSuccess = SH_ShowPropertiesDialog(m_sPathTarget, pidlParent, &pidlChild);
if (!bSuccess) CComPtr<IDataObject> pDataObj;
ERR("SH_ShowPropertiesDialog failed\n"); HRESULT hr = SHCreateDataObject(pidlParent, 1, &pidlChild, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
ILFree(pidlChild); if (!FAILED_UNEXPECTEDLY(hr))
ILFree(pidlParent); {
// 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) else if (uMsg == DFM_MERGECONTEXTMENU)
{ {

View file

@ -460,25 +460,14 @@ _ShowPropertiesDialogThread(LPVOID lpParameter)
return E_FAIL; return E_FAIL;
} }
PCUIDLIST_ABSOLUTE pidlFolder = HIDA_GetPIDLFolder(cida); CComHeapPtr<ITEMIDLIST> completePidl(ILCombine(HIDA_GetPIDLFolder(cida), HIDA_GetPIDLItem(cida, 0)));
CComPtr<IShellFolder> psfParent; CComHeapPtr<WCHAR> wszName;
HRESULT hr = _SHBindToFolder(pidlFolder, &psfParent); if (FAILED_UNEXPECTEDLY(SHGetNameFromIDList(completePidl, SIGDN_PARENTRELATIVEPARSING, &wszName)))
if (FAILED_UNEXPECTEDLY(hr)) return 0;
return hr;
STRRET strFile; BOOL bSuccess = SH_ShowPropertiesDialog(wszName, pDataObject);
PCUIDLIST_RELATIVE apidl = HIDA_GetPIDLItem(cida, 0); if (!bSuccess)
hr = psfParent->GetDisplayNameOf(apidl, SHGDN_FORPARSING, &strFile); ERR("SH_ShowPropertiesDialog failed\n");
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");
}
return 0; 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_FileGeneralDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK SH_FileVersionDlgProc(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); 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_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); LPWSTR SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT cchBuf);
HRESULT WINAPI DoRegisterServer(void); HRESULT WINAPI DoRegisterServer(void);

View file

@ -560,6 +560,7 @@ static inline PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA const* pida, SIZE_T i)
#ifdef __cplusplus #ifdef __cplusplus
DECLSPEC_SELECTANY CLIPFORMAT g_cfHIDA = NULL; DECLSPEC_SELECTANY CLIPFORMAT g_cfHIDA = NULL;
DECLSPEC_SELECTANY CLIPFORMAT g_cfShellIdListOffsets = NULL;
// Allow to use the HIDA from an IDataObject without copying it // Allow to use the HIDA from an IDataObject without copying it
struct CDataObjectHIDA struct CDataObjectHIDA
@ -684,6 +685,31 @@ HRESULT DataObject_SetData(IDataObject* pDataObject, CLIPFORMAT clipformat, PVOI
return hr; 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 #endif