mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 04:20:46 +00:00
[SHELLFIND] Remove dependency on internal shell32 functions
This commit is contained in:
parent
6c6fd6d989
commit
312b628fe1
2 changed files with 166 additions and 87 deletions
|
@ -18,6 +18,72 @@ SHOpenFolderAndSelectItems(LPITEMIDLIST pidlFolder,
|
||||||
PCUITEMID_CHILD_ARRAY apidl,
|
PCUITEMID_CHILD_ARRAY apidl,
|
||||||
DWORD dwFlags);
|
DWORD dwFlags);
|
||||||
|
|
||||||
|
static HRESULT SHELL32_CoCreateInitSF(LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti,
|
||||||
|
LPCITEMIDLIST pidlChild, const GUID* clsid, REFIID riid, LPVOID *ppvOut)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
CComPtr<IShellFolder> pShellFolder;
|
||||||
|
|
||||||
|
hr = SHCoCreateInstance(NULL, clsid, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild);
|
||||||
|
CComPtr<IPersistFolder> ppf;
|
||||||
|
CComPtr<IPersistFolder3> ppf3;
|
||||||
|
|
||||||
|
if (ppfti && SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3))))
|
||||||
|
{
|
||||||
|
ppf3->InitializeEx(NULL, pidlAbsolute, ppfti);
|
||||||
|
}
|
||||||
|
else if (SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder, &ppf))))
|
||||||
|
{
|
||||||
|
ppf->Initialize(pidlAbsolute);
|
||||||
|
}
|
||||||
|
ILFree (pidlAbsolute);
|
||||||
|
|
||||||
|
return pShellFolder->QueryInterface(riid, ppvOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI _InsertMenuItemW(
|
||||||
|
HMENU hMenu,
|
||||||
|
UINT indexMenu,
|
||||||
|
BOOL fByPosition,
|
||||||
|
UINT wID,
|
||||||
|
UINT fType,
|
||||||
|
LPCWSTR dwTypeData,
|
||||||
|
UINT fState)
|
||||||
|
{
|
||||||
|
MENUITEMINFOW mii;
|
||||||
|
WCHAR wszText[100];
|
||||||
|
|
||||||
|
ZeroMemory(&mii, sizeof(mii));
|
||||||
|
mii.cbSize = sizeof(mii);
|
||||||
|
if (fType == MFT_SEPARATOR)
|
||||||
|
mii.fMask = MIIM_ID | MIIM_TYPE;
|
||||||
|
else if (fType == MFT_STRING)
|
||||||
|
{
|
||||||
|
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
|
||||||
|
if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0)
|
||||||
|
{
|
||||||
|
if (LoadStringW(_AtlBaseModule.GetResourceInstance(), LOWORD((ULONG_PTR)dwTypeData), wszText, _countof(wszText)))
|
||||||
|
mii.dwTypeData = wszText;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("failed to load string %p\n", dwTypeData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mii.dwTypeData = (LPWSTR)dwTypeData;
|
||||||
|
mii.fState = fState;
|
||||||
|
}
|
||||||
|
|
||||||
|
mii.wID = wID;
|
||||||
|
mii.fType = fType;
|
||||||
|
InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
|
||||||
|
}
|
||||||
|
|
||||||
struct FolderViewColumns
|
struct FolderViewColumns
|
||||||
{
|
{
|
||||||
int iResource;
|
int iResource;
|
||||||
|
@ -447,28 +513,93 @@ STDMETHODIMP CFindFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl
|
||||||
return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut);
|
return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CFindFolderContextMenu :
|
||||||
|
public IContextMenu,
|
||||||
|
public CComObjectRootEx<CComMultiThreadModelNoCS>
|
||||||
|
{
|
||||||
|
CComPtr<IContextMenu> m_pInner;
|
||||||
|
CComPtr<IShellFolderView> m_shellFolderView;
|
||||||
|
UINT m_firstCmdId;
|
||||||
|
static const UINT ADDITIONAL_MENU_ITEMS = 2;
|
||||||
|
|
||||||
|
//// *** IContextMenu methods ***
|
||||||
|
STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
|
||||||
|
{
|
||||||
|
m_firstCmdId = indexMenu;
|
||||||
|
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst++, MFT_STRING, MAKEINTRESOURCEW(IDS_SEARCH_OPEN_FOLDER), MFS_ENABLED);
|
||||||
|
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst++, MFT_SEPARATOR, NULL, 0);
|
||||||
|
return m_pInner->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
|
||||||
|
{
|
||||||
|
if (!IS_INTRESOURCE(lpcmi->lpVerb))
|
||||||
|
{
|
||||||
|
return m_pInner->InvokeCommand(lpcmi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LOWORD(lpcmi->lpVerb) < m_firstCmdId + ADDITIONAL_MENU_ITEMS)
|
||||||
|
{
|
||||||
|
PCUITEMID_CHILD *apidl;
|
||||||
|
UINT cidl;
|
||||||
|
HRESULT hResult = m_shellFolderView->GetSelectedObjects(&apidl, &cidl);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hResult))
|
||||||
|
return hResult;
|
||||||
|
|
||||||
|
for (UINT i = 0; i < cidl; i++)
|
||||||
|
{
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
wcscpy(path, (LPCWSTR) apidl[0]->mkid.abID);
|
||||||
|
PathRemoveFileSpecW(path);
|
||||||
|
CComHeapPtr<ITEMIDLIST> folderPidl(ILCreateFromPathW(path));
|
||||||
|
if (!folderPidl)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
CComHeapPtr<ITEMIDLIST> pidl(ILCreateFromPathW((LPCWSTR) apidl[i]->mkid.abID));
|
||||||
|
if (!pidl)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
SHOpenFolderAndSelectItems(folderPidl, 1, &pidl, 0);
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMINVOKECOMMANDINFOEX actualCmdInfo;
|
||||||
|
memcpy(&actualCmdInfo, lpcmi, lpcmi->cbSize);
|
||||||
|
actualCmdInfo.lpVerb -= ADDITIONAL_MENU_ITEMS;
|
||||||
|
return m_pInner->InvokeCommand((CMINVOKECOMMANDINFO *)&actualCmdInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
|
||||||
|
{
|
||||||
|
return m_pInner->GetCommandString(idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static HRESULT Create(IShellFolderView *pShellFolderView, IContextMenu *pInnerContextMenu, IContextMenu **pContextMenu)
|
||||||
|
{
|
||||||
|
CComObject<CFindFolderContextMenu> *pObj;
|
||||||
|
HRESULT hResult = CComObject<CFindFolderContextMenu>::CreateInstance(&pObj);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hResult))
|
||||||
|
return hResult;
|
||||||
|
pObj->m_shellFolderView = pShellFolderView;
|
||||||
|
pObj->m_pInner = pInnerContextMenu;
|
||||||
|
return pObj->QueryInterface(IID_PPV_ARG(IContextMenu, pContextMenu));
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CFindFolderContextMenu)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
|
||||||
|
END_COM_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
|
STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
|
||||||
UINT *prgfInOut, LPVOID *ppvOut)
|
UINT *prgfInOut, LPVOID *ppvOut)
|
||||||
{
|
{
|
||||||
if (riid == IID_IDataObject && cidl == 1)
|
|
||||||
{
|
|
||||||
WCHAR path[MAX_PATH];
|
|
||||||
wcscpy(path, (LPCWSTR) apidl[0]->mkid.abID);
|
|
||||||
PathRemoveFileSpecW(path);
|
|
||||||
CComHeapPtr<ITEMIDLIST> rootPidl(ILCreateFromPathW(path));
|
|
||||||
if (!rootPidl)
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
PCITEMID_CHILD aFSPidl[1];
|
|
||||||
aFSPidl[0] = _ILGetFSPidl(apidl[0]);
|
|
||||||
return IDataObject_Constructor(hwndOwner, rootPidl, aFSPidl, cidl, (IDataObject **) ppvOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cidl <= 0)
|
if (cidl <= 0)
|
||||||
{
|
{
|
||||||
return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
|
return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
PCITEMID_CHILD *aFSPidl = new PCITEMID_CHILD[cidl];
|
CComHeapPtr<PCITEMID_CHILD> aFSPidl;
|
||||||
|
aFSPidl.Allocate(cidl);
|
||||||
for (UINT i = 0; i < cidl; i++)
|
for (UINT i = 0; i < cidl; i++)
|
||||||
{
|
{
|
||||||
aFSPidl[i] = _ILGetFSPidl(apidl[i]);
|
aFSPidl[i] = _ILGetFSPidl(apidl[i]);
|
||||||
|
@ -476,30 +607,28 @@ STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHI
|
||||||
|
|
||||||
if (riid == IID_IContextMenu)
|
if (riid == IID_IContextMenu)
|
||||||
{
|
{
|
||||||
HKEY hKeys[16];
|
WCHAR path[MAX_PATH];
|
||||||
UINT cKeys = 0;
|
wcscpy(path, (LPCWSTR) apidl[0]->mkid.abID);
|
||||||
AddFSClassKeysToArray(aFSPidl[0], hKeys, &cKeys);
|
PathRemoveFileSpecW(path);
|
||||||
|
CComHeapPtr<ITEMIDLIST> folderPidl(ILCreateFromPathW(path));
|
||||||
DEFCONTEXTMENU dcm;
|
if (!folderPidl)
|
||||||
dcm.hwnd = hwndOwner;
|
return E_OUTOFMEMORY;
|
||||||
dcm.pcmcb = this;
|
CComPtr<IShellFolder> pDesktopFolder;
|
||||||
dcm.pidlFolder = m_pidl;
|
HRESULT hResult = SHGetDesktopFolder(&pDesktopFolder);
|
||||||
dcm.psf = this;
|
if (FAILED_UNEXPECTEDLY(hResult))
|
||||||
dcm.cidl = cidl;
|
return hResult;
|
||||||
dcm.apidl = apidl;
|
CComPtr<IShellFolder> pShellFolder;
|
||||||
dcm.cKeys = cKeys;
|
hResult = pDesktopFolder->BindToObject(folderPidl, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
|
||||||
dcm.aKeys = hKeys;
|
if (FAILED_UNEXPECTEDLY(hResult))
|
||||||
dcm.punkAssociationInfo = NULL;
|
return hResult;
|
||||||
HRESULT hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut);
|
CComPtr<IContextMenu> pContextMenu;
|
||||||
delete[] aFSPidl;
|
hResult = pShellFolder->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, (LPVOID *)&pContextMenu);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hResult))
|
||||||
return hr;
|
return hResult;
|
||||||
|
return CFindFolderContextMenu::Create(m_shellFolderView, pContextMenu, (IContextMenu **)ppvOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut);
|
return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut);
|
||||||
delete[] aFSPidl;
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName)
|
STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName)
|
||||||
|
@ -541,50 +670,6 @@ STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//// *** IContextMenuCB method ***
|
|
||||||
STDMETHODIMP CFindFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
switch (uMsg)
|
|
||||||
{
|
|
||||||
case DFM_MERGECONTEXTMENU:
|
|
||||||
{
|
|
||||||
QCMINFO *pqcminfo = (QCMINFO *) lParam;
|
|
||||||
_InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0);
|
|
||||||
_InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_STRING, MAKEINTRESOURCEW(IDS_SEARCH_OPEN_FOLDER), MFS_ENABLED);
|
|
||||||
_InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
case DFM_INVOKECOMMAND:
|
|
||||||
case DFM_INVOKECOMMANDEX:
|
|
||||||
{
|
|
||||||
if (wParam != 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
PCUITEMID_CHILD *apidl;
|
|
||||||
UINT cidl;
|
|
||||||
HRESULT hr = m_shellFolderView->GetSelectedObjects(&apidl, &cidl);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
for (UINT i = 0; i < cidl; i++)
|
|
||||||
{
|
|
||||||
CComHeapPtr<ITEMIDLIST> pidl;
|
|
||||||
DWORD attrs = 0;
|
|
||||||
hr = SHILCreateFromPathW((LPCWSTR) apidl[i]->mkid.abID, &pidl, &attrs);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
SHOpenFolderAndSelectItems(NULL, 1, &pidl, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
case DFM_GETDEFSTATICID:
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
return Shell_DefaultContextMenuCallBack(m_pisfInner, pdtobj);
|
|
||||||
}
|
|
||||||
|
|
||||||
//// *** IPersistFolder2 methods ***
|
//// *** IPersistFolder2 methods ***
|
||||||
STDMETHODIMP CFindFolder::GetCurFolder(LPITEMIDLIST *pidl)
|
STDMETHODIMP CFindFolder::GetCurFolder(LPITEMIDLIST *pidl)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,8 +17,7 @@ class CFindFolder :
|
||||||
public IPersistFolder2,
|
public IPersistFolder2,
|
||||||
public IShellFolderViewCB,
|
public IShellFolderViewCB,
|
||||||
public IConnectionPointContainerImpl<CFindFolder>,
|
public IConnectionPointContainerImpl<CFindFolder>,
|
||||||
public IConnectionPointImpl<CFindFolder, &DIID_DSearchCommandEvents>,
|
public IConnectionPointImpl<CFindFolder, &DIID_DSearchCommandEvents>
|
||||||
public IContextMenuCB
|
|
||||||
{
|
{
|
||||||
// *** IShellFolder2 methods ***
|
// *** IShellFolder2 methods ***
|
||||||
STDMETHODIMP GetDefaultSearchGUID(GUID *pguid);
|
STDMETHODIMP GetDefaultSearchGUID(GUID *pguid);
|
||||||
|
@ -63,10 +62,6 @@ class CFindFolder :
|
||||||
//// *** IShellFolderViewCB methods ***
|
//// *** IShellFolderViewCB methods ***
|
||||||
STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
//// *** IContextMenuCB method ***
|
|
||||||
STDMETHODIMP CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam,
|
|
||||||
LPARAM lParam);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LPITEMIDLIST m_pidl;
|
LPITEMIDLIST m_pidl;
|
||||||
CComPtr<IShellFolder2> m_pisfInner;
|
CComPtr<IShellFolder2> m_pisfInner;
|
||||||
|
@ -125,7 +120,6 @@ public:
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IConnectionPointContainer, IConnectionPointContainer)
|
COM_INTERFACE_ENTRY_IID(IID_IConnectionPointContainer, IConnectionPointContainer)
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IContextMenuCB, IContextMenuCB)
|
|
||||||
END_COM_MAP()
|
END_COM_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue