Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433/* * IShellItem implementation * * Copyright 2008 Vincent Povirk for CodeWeavers * Copyright 2009 Andrew Hill * Copyright 2013 Katayama Hirofumi MZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
EXTERN_C HRESULT WINAPI SHCreateShellItem(PCIDLIST_ABSOLUTE pidlParent, IShellFolder *psfParent, PCUITEMID_CHILD pidl, IShellItem **ppsi);
CShellItem::CShellItem() : m_pidl(NULL){}
CShellItem::~CShellItem(){ ILFree(m_pidl);}
HRESULT CShellItem::get_parent_pidl(LPITEMIDLIST *parent_pidl){ *parent_pidl = ILClone(m_pidl); if (*parent_pidl) { if (ILRemoveLastID(*parent_pidl)) return S_OK; else { ILFree(*parent_pidl); *parent_pidl = NULL; return E_INVALIDARG; } } else { *parent_pidl = NULL; return E_OUTOFMEMORY; }}
HRESULT CShellItem::get_parent_shellfolder(IShellFolder **ppsf){ HRESULT hr; LPITEMIDLIST parent_pidl; CComPtr<IShellFolder> desktop;
hr = get_parent_pidl(&parent_pidl); if (SUCCEEDED(hr)) { hr = SHGetDesktopFolder(&desktop); if (SUCCEEDED(hr)) hr = desktop->BindToObject(parent_pidl, NULL, IID_PPV_ARG(IShellFolder, ppsf)); ILFree(parent_pidl); }
return hr;}
HRESULT CShellItem::get_shellfolder(IBindCtx *pbc, REFIID riid, void **ppvOut){ CComPtr<IShellFolder> psf; CComPtr<IShellFolder> psfDesktop; HRESULT ret;
ret = SHGetDesktopFolder(&psfDesktop); if (FAILED_UNEXPECTEDLY(ret)) return ret;
if (_ILIsDesktop(m_pidl)) psf = psfDesktop; else { ret = psfDesktop->BindToObject(m_pidl, pbc, IID_PPV_ARG(IShellFolder, &psf)); if (FAILED_UNEXPECTEDLY(ret)) return ret; }
return psf->QueryInterface(riid, ppvOut);}
HRESULT WINAPI CShellItem::BindToHandler(IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppvOut){ HRESULT ret; TRACE("(%p, %p,%s,%p,%p)\n", this, pbc, shdebugstr_guid(&rbhid), riid, ppvOut);
*ppvOut = NULL; if (IsEqualGUID(rbhid, BHID_SFObject)) { return get_shellfolder(pbc, riid, ppvOut); } else if (IsEqualGUID(rbhid, BHID_SFUIObject)) { CComPtr<IShellFolder> psf_parent; if (_ILIsDesktop(m_pidl)) ret = SHGetDesktopFolder(&psf_parent); else ret = get_parent_shellfolder(&psf_parent); if (FAILED_UNEXPECTEDLY(ret)) return ret;
LPCITEMIDLIST pidl = ILFindLastID(m_pidl); return psf_parent->GetUIObjectOf(NULL, 1, &pidl, riid, NULL, ppvOut); } else if (IsEqualGUID(rbhid, BHID_DataObject)) { return BindToHandler(pbc, BHID_SFUIObject, IID_IDataObject, ppvOut); } else if (IsEqualGUID(rbhid, BHID_SFViewObject)) { CComPtr<IShellFolder> psf; ret = get_shellfolder(NULL, IID_PPV_ARG(IShellFolder, &psf)); if (FAILED_UNEXPECTEDLY(ret)) return ret;
return psf->CreateViewObject(NULL, riid, ppvOut); }
FIXME("Unsupported BHID %s.\n", debugstr_guid(&rbhid));
return MK_E_NOOBJECT;}
HRESULT WINAPI CShellItem::GetParent(IShellItem **ppsi){ HRESULT hr; LPITEMIDLIST parent_pidl;
TRACE("(%p,%p)\n", this, ppsi);
hr = get_parent_pidl(&parent_pidl); if (SUCCEEDED(hr)) { hr = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi); ILFree(parent_pidl); }
return hr;}
HRESULT WINAPI CShellItem::GetDisplayName(SIGDN sigdnName, LPWSTR *ppszName){ return SHGetNameFromIDList(m_pidl, sigdnName, ppszName);}
HRESULT WINAPI CShellItem::GetAttributes(SFGAOF sfgaoMask, SFGAOF *psfgaoAttribs){ CComPtr<IShellFolder> parent_folder; LPCITEMIDLIST child_pidl; HRESULT hr;
TRACE("(%p,%x,%p)\n", this, sfgaoMask, psfgaoAttribs);
if (_ILIsDesktop(m_pidl)) hr = SHGetDesktopFolder(&parent_folder); else hr = get_parent_shellfolder(&parent_folder); if (FAILED_UNEXPECTEDLY(hr)) return hr;
child_pidl = ILFindLastID(m_pidl); *psfgaoAttribs = sfgaoMask; hr = parent_folder->GetAttributesOf(1, &child_pidl, psfgaoAttribs); *psfgaoAttribs &= sfgaoMask;
if (FAILED_UNEXPECTEDLY(hr)) return hr;
return (sfgaoMask == *psfgaoAttribs) ? S_OK : S_FALSE;}
HRESULT WINAPI CShellItem::Compare(IShellItem *oth, SICHINTF hint, int *piOrder){ HRESULT hr; CComPtr<IPersistIDList> pIDList; CComPtr<IShellFolder> psfDesktop; LPITEMIDLIST pidl;
TRACE("(%p,%p,%x,%p)\n", this, oth, hint, piOrder);
if (piOrder == NULL || oth == NULL) return E_POINTER;
hr = oth->QueryInterface(IID_PPV_ARG(IPersistIDList, &pIDList)); if (SUCCEEDED(hr)) { hr = pIDList->GetIDList(&pidl); if (SUCCEEDED(hr)) { hr = SHGetDesktopFolder(&psfDesktop); if (SUCCEEDED(hr)) { hr = psfDesktop->CompareIDs(hint, m_pidl, pidl); *piOrder = (int)(short)SCODE_CODE(hr); } ILFree(pidl); } }
if(FAILED(hr)) return hr;
if(*piOrder) return S_FALSE; else return S_OK;}
HRESULT WINAPI CShellItem::GetClassID(CLSID *pClassID){ TRACE("(%p,%p)\n", this, pClassID);
*pClassID = CLSID_ShellItem; return S_OK;}
HRESULT WINAPI CShellItem::SetIDList(PCIDLIST_ABSOLUTE pidlx){ LPITEMIDLIST new_pidl;
TRACE("(%p,%p)\n", this, pidlx);
new_pidl = ILClone(pidlx); if (new_pidl) { ILFree(m_pidl); m_pidl = new_pidl; return S_OK; } else return E_OUTOFMEMORY;}
HRESULT WINAPI CShellItem::GetIDList(PIDLIST_ABSOLUTE *ppidl){ TRACE("(%p,%p)\n", this, ppidl);
*ppidl = ILClone(m_pidl); if (*ppidl) return S_OK; else return E_OUTOFMEMORY;}
HRESULT WINAPI SHCreateShellItem(PCIDLIST_ABSOLUTE pidlParent, IShellFolder *psfParent, PCUITEMID_CHILD pidl, IShellItem **ppsi){ HRESULT hr; CComPtr<IShellItem> newShellItem; LPITEMIDLIST new_pidl; CComPtr<IPersistIDList> newPersistIDList;
TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
*ppsi = NULL;
if (!pidl) return E_INVALIDARG;
if (pidlParent || psfParent) { LPITEMIDLIST temp_parent = NULL; if (!pidlParent) { CComPtr<IPersistFolder2> ppf2Parent;
if (FAILED(psfParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2Parent)))) { FIXME("couldn't get IPersistFolder2 interface of parent\n"); return E_NOINTERFACE; }
if (FAILED(ppf2Parent->GetCurFolder(&temp_parent))) { FIXME("couldn't get parent PIDL\n"); return E_NOINTERFACE; }
pidlParent = temp_parent; }
new_pidl = ILCombine(pidlParent, pidl); ILFree(temp_parent);
if (!new_pidl) return E_OUTOFMEMORY; } else { new_pidl = ILClone(pidl); if (!new_pidl) return E_OUTOFMEMORY; }
hr = CShellItem::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellItem, &newShellItem)); if (FAILED(hr)) { ILFree(new_pidl); return hr; } hr = newShellItem->QueryInterface(IID_PPV_ARG(IPersistIDList, &newPersistIDList)); if (FAILED(hr)) { ILFree(new_pidl); return hr; } hr = newPersistIDList->SetIDList(new_pidl); if (FAILED(hr)) { ILFree(new_pidl); return hr; } ILFree(new_pidl);
*ppsi = newShellItem.Detach();
return hr;}
class CShellItemArray : public CComCoClass<CShellItemArray, &CLSID_NULL>, public CComObjectRootEx<CComMultiThreadModelNoCS>, public IShellItemArray{ CIDA *m_pCIDA; STGMEDIUM m_Medium;
public: CShellItemArray() : m_pCIDA(NULL) { m_Medium.tymed = TYMED_NULL; }
virtual ~CShellItemArray() { CDataObjectHIDA::DestroyCIDA(m_pCIDA, m_Medium); }
HRESULT Initialize(IDataObject *pdo) { return CDataObjectHIDA::CreateCIDA(pdo, &m_pCIDA, m_Medium); }
inline UINT GetCount() const { return m_pCIDA->cidl; }
// IShellItemArray STDMETHODIMP BindToHandler(IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppv) override { UNIMPLEMENTED; *ppv = NULL; return E_NOTIMPL; }
STDMETHODIMP GetPropertyStore(GETPROPERTYSTOREFLAGS flags, REFIID riid, void **ppv) override { UNIMPLEMENTED; *ppv = NULL; return E_NOTIMPL; }
STDMETHODIMP GetPropertyDescriptionList(REFPROPERTYKEY keyType, REFIID riid, void **ppv) override { UNIMPLEMENTED; *ppv = NULL; return E_NOTIMPL; }
STDMETHODIMP GetAttributes(SIATTRIBFLAGS dwAttribFlags, SFGAOF sfgaoMask, SFGAOF *psfgaoAttribs) override { UNIMPLEMENTED; *psfgaoAttribs = 0; return E_NOTIMPL; }
STDMETHODIMP GetCount(DWORD*pCount) override { *pCount = m_pCIDA ? GetCount() : 0; return S_OK; }
STDMETHODIMP GetItemAt(DWORD nIndex, IShellItem **ppItem) override { if (!ppItem) return E_INVALIDARG; *ppItem = NULL; if (!m_pCIDA) return E_UNEXPECTED; if (nIndex >= GetCount()) return E_FAIL; return SHCreateShellItem(HIDA_GetPIDLFolder(m_pCIDA), NULL, HIDA_GetPIDLItem(m_pCIDA, nIndex), ppItem); }
STDMETHODIMP EnumItems(IEnumShellItems **ppESI) override { UNIMPLEMENTED; *ppESI = NULL; return E_NOTIMPL; }
DECLARE_NO_REGISTRY()DECLARE_NOT_AGGREGATABLE(CShellItemArray)
BEGIN_COM_MAP(CShellItemArray) COM_INTERFACE_ENTRY_IID(IID_IShellItemArray, IShellItemArray)END_COM_MAP()};
EXTERN_C HRESULT WINAPISHCreateShellItemArrayFromDataObject(_In_ IDataObject *pdo, _In_ REFIID riid, _Out_ void **ppv){ return ShellObjectCreatorInit<CShellItemArray>(pdo, riid, ppv);}