[SHELL32]

- CDefaultContextMenu: Add rudimentary support for callbacks so as to let folders have item specific commands and remove all item specific code from this class.
- Implement context menu callbacks for CFSFolder, CRegFolder, CDrivesFolder in order to let them handle the properties item and let the CDrivesFolder add and handle the Format item itself.

svn path=/trunk/; revision=73243
This commit is contained in:
Giannis Adamopoulos 2016-11-17 14:35:19 +00:00
parent bdf445d754
commit 1d4fcbf920
13 changed files with 276 additions and 156 deletions

View file

@ -61,6 +61,8 @@ class CDefaultContextMenu :
private: private:
CComPtr<IUnknown> m_site; CComPtr<IUnknown> m_site;
CComPtr<IShellFolder> m_psf; CComPtr<IShellFolder> m_psf;
CComPtr<IContextMenuCB> m_pmcb;
LPFNDFMCALLBACK m_pfnmcb;
UINT m_cidl; UINT m_cidl;
PCUITEMID_CHILD_ARRAY m_apidl; PCUITEMID_CHILD_ARRAY m_apidl;
CComPtr<IDataObject> m_pDataObj; CComPtr<IDataObject> m_pDataObj;
@ -75,6 +77,7 @@ class CDefaultContextMenu :
UINT m_iIdSCMFirst; /* first static used id */ UINT m_iIdSCMFirst; /* first static used id */
UINT m_iIdSCMLast; /* last static used id */ UINT m_iIdSCMLast; /* last static used id */
HRESULT _DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam);
void AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb); void AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb);
void AddStaticEntriesForKey(HKEY hKey); void AddStaticEntriesForKey(HKEY hKey);
BOOL IsShellExtensionAlreadyLoaded(const CLSID *pclsid); BOOL IsShellExtensionAlreadyLoaded(const CLSID *pclsid);
@ -93,7 +96,6 @@ class CDefaultContextMenu :
HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy); HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy);
HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoFormat(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFO lpici); HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFO lpici);
HRESULT DoDynamicShellExtensions(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoDynamicShellExtensions(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoStaticShellExtensions(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoStaticShellExtensions(LPCMINVOKECOMMANDINFO lpcmi);
@ -106,7 +108,7 @@ class CDefaultContextMenu :
public: public:
CDefaultContextMenu(); CDefaultContextMenu();
~CDefaultContextMenu(); ~CDefaultContextMenu();
HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm); HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn);
// IContextMenu // IContextMenu
virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
@ -133,6 +135,8 @@ class CDefaultContextMenu :
CDefaultContextMenu::CDefaultContextMenu() : CDefaultContextMenu::CDefaultContextMenu() :
m_psf(NULL), m_psf(NULL),
m_pmcb(NULL),
m_pfnmcb(NULL),
m_cidl(0), m_cidl(0),
m_apidl(NULL), m_apidl(NULL),
m_pDataObj(NULL), m_pDataObj(NULL),
@ -180,7 +184,7 @@ CDefaultContextMenu::~CDefaultContextMenu()
_ILFreeaPidl(const_cast<PITEMID_CHILD *>(m_apidl), m_cidl); _ILFreeaPidl(const_cast<PITEMID_CHILD *>(m_apidl), m_cidl);
} }
HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm) HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn)
{ {
TRACE("cidl %u\n", pdcm->cidl); TRACE("cidl %u\n", pdcm->cidl);
@ -189,6 +193,8 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm)
if (m_cidl && !m_apidl) if (m_cidl && !m_apidl)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
m_psf = pdcm->psf; m_psf = pdcm->psf;
m_pmcb = pdcm->pcmcb;
m_pfnmcb = lpfn;
m_cKeys = pdcm->cKeys; m_cKeys = pdcm->cKeys;
if (pdcm->cKeys) if (pdcm->cKeys)
@ -219,6 +225,20 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm)
return S_OK; return S_OK;
} }
HRESULT CDefaultContextMenu::_DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam)
{
if (m_pmcb)
{
return m_pmcb->CallBack(m_psf, NULL, m_pDataObj, uMsg, wParam, (LPARAM)lParam);
}
else if(m_pfnmcb)
{
return m_pfnmcb(m_psf, NULL, m_pDataObj, uMsg, wParam, (LPARAM)lParam);
}
return S_OK;
}
void CDefaultContextMenu::AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb) void CDefaultContextMenu::AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb)
{ {
PStaticShellEntry pEntry = m_pStaticEntries, pLastEntry = NULL; PStaticShellEntry pEntry = m_pStaticEntries, pLastEntry = NULL;
@ -712,23 +732,15 @@ CDefaultContextMenu::BuildShellItemContextMenu(
IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, iIdCmdFirst, iIdCmdLast); IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, iIdCmdFirst, iIdCmdLast);
TRACE("IndexMenu %d\n", IndexMenu); TRACE("IndexMenu %d\n", IndexMenu);
if (_ILIsDrive(m_apidl[0])) /* Now let the callback add its own items */
{ QCMINFO qcminfo;
char szDrive[8] = {0}; qcminfo.hmenu = hMenu;
DWORD dwFlags; qcminfo.indexMenu = IndexMenu;
qcminfo.idCmdFirst = iIdCmdFirst;
_ILGetDrive(m_apidl[0], szDrive, sizeof(szDrive)); qcminfo.idCmdLast = iIdCmdLast;
if (GetVolumeInformationA(szDrive, NULL, 0, NULL, NULL, &dwFlags, NULL, 0)) qcminfo.pIdMap = NULL;
{ _DoCallback(DFM_MERGECONTEXTMENU, uFlags, &qcminfo);
/* Disable format if read only */ IndexMenu = GetMenuItemCount(hMenu);
if (!(dwFlags & FILE_READ_ONLY_VOLUME))
{
_InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
_InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED);
bAddSep = TRUE;
}
}
}
BOOL bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM)); BOOL bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM));
if (rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE) || bClipboardData) if (rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE) || bClipboardData)
@ -971,105 +983,8 @@ HRESULT
CDefaultContextMenu::DoProperties( CDefaultContextMenu::DoProperties(
LPCMINVOKECOMMANDINFO lpcmi) LPCMINVOKECOMMANDINFO lpcmi)
{ {
HRESULT hr = S_OK; _DoCallback(DFM_INVOKECOMMAND, DFM_CMD_PROPERTIES, NULL);
const ITEMIDLIST *pidlParent = m_pidlFolder, *pidlChild;
if (!pidlParent)
{
CComPtr<IPersistFolder2> pf;
/* pidlFolder is optional */
if (SUCCEEDED(m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf))))
{
pf->GetCurFolder((_ITEMIDLIST**)&pidlParent);
}
}
if (m_cidl > 0)
pidlChild = m_apidl[0];
else
{
/* Set pidlChild to last pidl of current folder */
if (pidlParent == m_pidlFolder)
pidlParent = (ITEMIDLIST*)ILClone(pidlParent);
pidlChild = (ITEMIDLIST*)ILClone(ILFindLastID(pidlParent));
ILRemoveLastID((ITEMIDLIST*)pidlParent);
}
if (_ILIsMyComputer(pidlChild))
{
if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL))
hr = E_FAIL;
}
else if (_ILIsDesktop(pidlChild))
{
if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL))
hr = E_FAIL;
}
else if (_ILIsDrive(pidlChild))
{
WCHAR wszBuf[MAX_PATH];
ILGetDisplayName(pidlChild, wszBuf);
if (!SH_ShowDriveProperties(wszBuf, pidlParent, &pidlChild))
hr = E_FAIL;
}
else if (_ILIsNetHood(pidlChild))
{
// FIXME path!
if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe",
L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
NULL, SW_SHOWDEFAULT))
hr = E_FAIL;
}
else if (_ILIsBitBucket(pidlChild))
{
/* FIXME: detect the drive path of bitbucket if appropiate */
if (!SH_ShowRecycleBinProperties(L'C'))
hr = E_FAIL;
}
else
{
if (m_cidl > 1)
WARN("SHMultiFileProperties is not yet implemented\n");
STRRET strFile;
hr = m_psf->GetDisplayNameOf(pidlChild, SHGDN_FORPARSING, &strFile);
if (SUCCEEDED(hr))
{
WCHAR wszBuf[MAX_PATH];
hr = StrRetToBufW(&strFile, pidlChild, wszBuf, _countof(wszBuf));
if (SUCCEEDED(hr))
hr = SH_ShowPropertiesDialog(wszBuf, pidlParent, &pidlChild);
else
ERR("StrRetToBufW failed\n");
}
else
ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
}
/* Free allocated PIDLs */
if (pidlParent != m_pidlFolder)
ILFree((ITEMIDLIST*)pidlParent);
if (m_cidl < 1 || pidlChild != m_apidl[0])
ILFree((ITEMIDLIST*)pidlChild);
return hr;
}
HRESULT
CDefaultContextMenu::DoFormat(
LPCMINVOKECOMMANDINFO lpcmi)
{
char szDrive[8] = {0};
if (!_ILGetDrive(m_apidl[0], szDrive, sizeof(szDrive)))
{
ERR("pidl is not a drive\n");
return E_FAIL;
}
SHFormatDrive(lpcmi->hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
return S_OK; return S_OK;
} }
@ -1411,13 +1326,13 @@ CDefaultContextMenu::InvokeCommand(
case FCIDM_SHVIEW_PROPERTIES: case FCIDM_SHVIEW_PROPERTIES:
Result = DoProperties(&LocalInvokeInfo); Result = DoProperties(&LocalInvokeInfo);
break; break;
case 0x7ABC:
Result = DoFormat(&LocalInvokeInfo);
break;
case FCIDM_SHVIEW_NEWFOLDER: case FCIDM_SHVIEW_NEWFOLDER:
Result = DoCreateNewFolder(&LocalInvokeInfo); Result = DoCreateNewFolder(&LocalInvokeInfo);
break; break;
default: default:
_DoCallback(DFM_INVOKECOMMAND, LOWORD(LocalInvokeInfo.lpVerb), NULL);
Result = E_UNEXPECTED; Result = E_UNEXPECTED;
break; break;
} }
@ -1561,9 +1476,9 @@ CDefaultContextMenu::GetSite(REFIID riid, void **ppvSite)
static static
HRESULT HRESULT
CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv) CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn, REFIID riid, void **ppv)
{ {
return ShellObjectCreatorInit<CDefaultContextMenu>(pdcm, riid, ppv); return ShellObjectCreatorInit<CDefaultContextMenu>(pdcm, lpfn, riid, ppv);
} }
/************************************************************************* /*************************************************************************
@ -1575,7 +1490,7 @@ HRESULT
WINAPI WINAPI
SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv) SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv)
{ {
HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, riid, ppv); HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, NULL, riid, ppv);
if (FAILED_UNEXPECTEDLY(hr)) if (FAILED_UNEXPECTEDLY(hr))
return hr; return hr;
@ -1600,18 +1515,18 @@ CDefFolderMenu_Create2(
const HKEY *ahkeyClsKeys, const HKEY *ahkeyClsKeys,
IContextMenu **ppcm) IContextMenu **ppcm)
{ {
DEFCONTEXTMENU pdcm; DEFCONTEXTMENU dcm;
pdcm.hwnd = hwnd; dcm.hwnd = hwnd;
pdcm.pcmcb = NULL; dcm.pcmcb = NULL;
pdcm.pidlFolder = pidlFolder; dcm.pidlFolder = pidlFolder;
pdcm.psf = psf; dcm.psf = psf;
pdcm.cidl = cidl; dcm.cidl = cidl;
pdcm.apidl = apidl; dcm.apidl = apidl;
pdcm.punkAssociationInfo = NULL; dcm.punkAssociationInfo = NULL;
pdcm.cKeys = nKeys; dcm.cKeys = nKeys;
pdcm.aKeys = ahkeyClsKeys; dcm.aKeys = ahkeyClsKeys;
HRESULT hr = SHCreateDefaultContextMenu(&pdcm, IID_PPV_ARG(IContextMenu, ppcm)); HRESULT hr = CDefaultContextMenu_CreateInstance(&dcm, lpfn, IID_PPV_ARG(IContextMenu, ppcm));
if (FAILED_UNEXPECTEDLY(hr)) if (FAILED_UNEXPECTEDLY(hr))
return hr; return hr;

View file

@ -123,7 +123,7 @@ typedef struct _DRIVE_PROP_PAGE
} DRIVE_PROP_PAGE; } DRIVE_PROP_PAGE;
BOOL BOOL
SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl) SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
{ {
HPSXA hpsx = NULL; HPSXA hpsx = NULL;
HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE]; HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];

View file

@ -95,7 +95,7 @@ LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW *pHeader, UINT cMaxPage
*/ */
BOOL BOOL
SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl) SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
{ {
HPSXA hpsxa[3] = {NULL, NULL, NULL}; HPSXA hpsxa[3] = {NULL, NULL, NULL};
CComObject<CFileDefExt> *pFileDefExt = NULL; CComObject<CFileDefExt> *pFileDefExt = NULL;

View file

@ -133,8 +133,8 @@ HRESULT CCPLExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, R
CComPtr<IDefaultExtractIconInit> initIcon; CComPtr<IDefaultExtractIconInit> initIcon;
HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
if (FAILED(hr)) if (FAILED_UNEXPECTEDLY(hr))
return NULL; return hr;
initIcon->SetNormalIcon(pData->szName, (int)pData->iconIdx != -1 ? pData->iconIdx : 0); initIcon->SetNormalIcon(pData->szName, (int)pData->iconIdx != -1 ? pData->iconIdx : 0);

View file

@ -39,6 +39,69 @@ CDrivesFolderEnum is only responsible for returning the physical items.
* IShellFolder implementation * IShellFolder implementation
*/ */
HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
HWND hwnd,
IDataObject *pdtobj,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
if (uMsg != DFM_MERGECONTEXTMENU && uMsg != DFM_INVOKECOMMAND)
return S_OK;
PIDLIST_ABSOLUTE pidlFolder;
PUITEMID_CHILD *apidl;
UINT cidl;
HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
char szDrive[8] = {0};
if (!_ILGetDrive(apidl[0], szDrive, sizeof(szDrive)))
{
ERR("pidl is not a drive\n");
SHFree(pidlFolder);
_ILFreeaPidl(apidl, cidl);
return E_FAIL;
}
if (uMsg == DFM_MERGECONTEXTMENU)
{
QCMINFO *pqcminfo = (QCMINFO *)lParam;
DWORD dwFlags;
if (GetVolumeInformationA(szDrive, NULL, 0, NULL, NULL, &dwFlags, NULL, 0))
{
/* Disable format if read only */
if (!(dwFlags & FILE_READ_ONLY_VOLUME) && GetDriveTypeA(szDrive) != DRIVE_REMOTE)
{
_InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
_InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED);
}
}
}
else if (uMsg == DFM_INVOKECOMMAND)
{
if(wParam == 0x7ABC)
{
SHFormatDrive(hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
}
else if (wParam == DFM_CMD_PROPERTIES)
{
WCHAR wszBuf[4];
wcscpy(wszBuf, L"A:\\");
wszBuf[0] = (WCHAR)szDrive[0];
if (!SH_ShowDriveProperties(wszBuf, pidlFolder, apidl))
hr = E_FAIL;
}
}
SHFree(pidlFolder);
_ILFreeaPidl(apidl, cidl);
return hr;
}
HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
HWND hwnd, HWND hwnd,
UINT cidl, UINT cidl,
@ -51,16 +114,15 @@ HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
AddClassKeyToArray(L"Drive", hKeys, &cKeys); AddClassKeyToArray(L"Drive", hKeys, &cKeys);
AddClassKeyToArray(L"Folder", hKeys, &cKeys); AddClassKeyToArray(L"Folder", hKeys, &cKeys);
/* TODO: also pass a callback here */ return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, DrivesContextMenuCallback, cKeys, hKeys, ppcm);
return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm);
} }
HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut) HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
{ {
CComPtr<IDefaultExtractIconInit> initIcon; CComPtr<IDefaultExtractIconInit> initIcon;
HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
if (FAILED(hr)) if (FAILED_UNEXPECTEDLY(hr))
return NULL; return hr;
CHAR* pszDrive = _ILGetDataPointer(pidl)->u.drive.szDriveName; CHAR* pszDrive = _ILGetDataPointer(pidl)->u.drive.szDriveName;
WCHAR wTemp[MAX_PATH]; WCHAR wTemp[MAX_PATH];

View file

@ -489,12 +489,21 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner,
if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1))
{ {
IContextMenu * pCm = NULL;
HKEY hKeys[16]; HKEY hKeys[16];
UINT cKeys = 0; UINT cKeys = 0;
AddFSClassKeysToArray(apidl[0], hKeys, &cKeys); AddFSClassKeysToArray(apidl[0], hKeys, &cKeys);
hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, cKeys, hKeys, &pCm);
pObj = pCm; DEFCONTEXTMENU dcm;
dcm.hwnd = hwndOwner;
dcm.pcmcb = this;
dcm.pidlFolder = pidlRoot;
dcm.psf = this;
dcm.cidl = cidl;
dcm.apidl = apidl;
dcm.cKeys = cKeys;
dcm.aKeys = hKeys;
dcm.punkAssociationInfo = NULL;
hr = SHCreateDefaultContextMenu (&dcm, riid, &pObj);
} }
else if (IsEqualIID (riid, IID_IDataObject)) else if (IsEqualIID (riid, IID_IDataObject))
{ {
@ -1089,3 +1098,37 @@ HRESULT WINAPI CFSFolder::_LoadDynamicDropTargetHandler(const CLSID *pclsid, LPC
} }
return hr; return hr;
} }
HRESULT WINAPI CFSFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES)
return S_OK;
PIDLIST_ABSOLUTE pidlFolder;
PUITEMID_CHILD *apidl;
UINT cidl;
HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (cidl > 1)
ERR("SHMultiFileProperties is not yet implemented\n");
STRRET strFile;
hr = GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strFile);
if (SUCCEEDED(hr))
{
hr = SH_ShowPropertiesDialog(strFile.pOleStr, pidlFolder, apidl);
if (FAILED(hr))
ERR("SH_ShowPropertiesDialog failed\n");
}
else
{
ERR("Failed to get display name\n");
}
SHFree(pidlFolder);
_ILFreeaPidl(apidl, cidl);
return hr;
}

View file

@ -27,7 +27,8 @@ class CFSFolder :
public CComCoClass<CFSFolder, &CLSID_ShellFSFolder>, public CComCoClass<CFSFolder, &CLSID_ShellFSFolder>,
public CComObjectRootEx<CComMultiThreadModelNoCS>, public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IShellFolder2, public IShellFolder2,
public IPersistFolder3 public IPersistFolder3,
public IContextMenuCB
{ {
private: private:
CLSID *pclsid; CLSID *pclsid;
@ -80,6 +81,9 @@ class CFSFolder :
virtual HRESULT WINAPI InitializeEx(IBindCtx *pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO *ppfti); virtual HRESULT WINAPI InitializeEx(IBindCtx *pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO *ppfti);
virtual HRESULT WINAPI GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO *ppfti); virtual HRESULT WINAPI GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO *ppfti);
// IContextMenuCB
virtual HRESULT WINAPI CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam);
DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER) DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER)
DECLARE_NOT_AGGREGATABLE(CFSFolder) DECLARE_NOT_AGGREGATABLE(CFSFolder)

View file

@ -53,8 +53,8 @@ HRESULT CNetFolderExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LP
{ {
CComPtr<IDefaultExtractIconInit> initIcon; CComPtr<IDefaultExtractIconInit> initIcon;
HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
if (FAILED(hr)) if (FAILED_UNEXPECTEDLY(hr))
return NULL; return hr;
initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_NETWORK_FOLDER); initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_NETWORK_FOLDER);

View file

@ -67,8 +67,8 @@ HRESULT CRecyclerExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LPV
{ {
CComPtr<IDefaultExtractIconInit> initIcon; CComPtr<IDefaultExtractIconInit> initIcon;
HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
if (FAILED(hr)) if (FAILED_UNEXPECTEDLY(hr))
return NULL; return hr;
/* FIXME: This is completely unimplemented */ /* FIXME: This is completely unimplemented */
initIcon->SetNormalIcon(swShell32Name, 0); initIcon->SetNormalIcon(swShell32Name, 0);

View file

@ -22,6 +22,54 @@
WINE_DEFAULT_DEBUG_CHANNEL (shell); WINE_DEFAULT_DEBUG_CHANNEL (shell);
HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf,
HWND hwnd,
IDataObject *pdtobj,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES)
return S_OK;
PIDLIST_ABSOLUTE pidlFolder;
PUITEMID_CHILD *apidl;
UINT cidl;
HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (_ILIsMyComputer(apidl[0]))
{
if (32 >= (UINT)ShellExecuteW(hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL))
hr = E_FAIL;
}
else if (_ILIsDesktop(apidl[0]))
{
if (32 >= (UINT)ShellExecuteW(hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL))
hr = E_FAIL;
}
else if (_ILIsNetHood(apidl[0]))
{
// FIXME path!
if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe",
L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
NULL, SW_SHOWDEFAULT))
hr = E_FAIL;
}
else if (_ILIsBitBucket(apidl[0]))
{
/* FIXME: detect the drive path of bitbucket if appropiate */
if (!SH_ShowRecycleBinProperties(L'C'))
hr = E_FAIL;
}
SHFree(pidlFolder);
_ILFreeaPidl(apidl, cidl);
return hr;
}
HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
HWND hwnd, HWND hwnd,
UINT cidl, UINT cidl,
@ -48,7 +96,7 @@ HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
} }
AddClassKeyToArray(L"Folder", hKeys, &cKeys); AddClassKeyToArray(L"Folder", hKeys, &cKeys);
return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm); return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, RegFolderContextMenuCallback, cKeys, hKeys, ppcm);
} }
HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut) HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut)
@ -398,6 +446,10 @@ HRESULT WINAPI CRegFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CH
hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj); hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj);
} }
else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
{
hr = IDataObject_Constructor (hwndOwner, m_pidlRoot, apidl, cidl, (IDataObject **)&pObj);
}
else else
{ {
hr = E_NOINTERFACE; hr = E_NOINTERFACE;

View file

@ -63,6 +63,8 @@ BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey);
void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys); void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys);
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl);
static __inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str) static __inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str)
{ {
return sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", return sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",

View file

@ -547,6 +547,49 @@ void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys)
} }
} }
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl)
{
UINT cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
if (!cfShellIDList)
return E_FAIL;
FORMATETC fmt;
InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
HRESULT hr = pDataObject->QueryGetData(&fmt);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
STGMEDIUM medium;
hr = pDataObject->GetData(&fmt, &medium);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
/* lock the handle */
LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
if (!lpcida)
{
ReleaseStgMedium(&medium);
return E_FAIL;
}
/* convert the data into pidl */
LPITEMIDLIST pidl;
LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
if (!apidl)
{
ReleaseStgMedium(&medium);
return E_OUTOFMEMORY;
}
*ppidlfolder = pidl;
*apidlItems = apidl;
*pcidl = lpcida->cidl;
ReleaseStgMedium(&medium);
return S_OK;
}
/*********************************************************************** /***********************************************************************
* SHCreateLinks * SHCreateLinks
* *

View file

@ -189,10 +189,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);
BOOL SH_ShowDriveProperties(WCHAR *drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl); BOOL SH_ShowDriveProperties(WCHAR *drive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl);
BOOL SH_ShowRecycleBinProperties(WCHAR sDrive); BOOL SH_ShowRecycleBinProperties(WCHAR sDrive);
BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl); BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl);
BOOL SH_ShowFolderProperties(LPWSTR pwszFolder, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl);
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);