/* * 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(LPCITEMIDLIST pidlParent, IShellFolder *psfParent, LPCITEMIDLIST 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 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 WINAPI CShellItem::BindToHandler(IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppvOut) { FIXME("(%p,%p,%s,%p,%p)\n", this, pbc, shdebugstr_guid(&rbhid), riid, ppvOut); *ppvOut = NULL; return E_NOTIMPL; } 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) { HRESULT hr; CComPtr parent_folder; STRRET name; DWORD uFlags; TRACE("(%p,%x,%p)\n", this, sigdnName, ppszName); if (sigdnName & SIGDN_URL) return E_NOTIMPL; if (ppszName == NULL) return E_POINTER; *ppszName = NULL; hr = get_parent_shellfolder(&parent_folder); if (SUCCEEDED(hr)) { switch (sigdnName) { case SIGDN_PARENTRELATIVEEDITING: uFlags = SHGDN_FOREDITING | SHGDN_INFOLDER; break; case SIGDN_DESKTOPABSOLUTEEDITING: uFlags = SHGDN_FOREDITING; break; case SIGDN_PARENTRELATIVEPARSING: uFlags = SHGDN_FORPARSING | SHGDN_INFOLDER; break; case SIGDN_DESKTOPABSOLUTEPARSING: uFlags = SHGDN_FORPARSING; break; default: uFlags = SHGDN_NORMAL; break; } hr = parent_folder->GetDisplayNameOf(m_pidl, uFlags, &name); if (SUCCEEDED(hr)) { StrRetToStrW(&name, m_pidl, ppszName); return S_OK; } } return hr; } HRESULT WINAPI CShellItem::GetAttributes(SFGAOF sfgaoMask, SFGAOF *psfgaoAttribs) { CComPtr parent_folder; LPCITEMIDLIST child_pidl; HRESULT hr; TRACE("(%p,%x,%p)\n", this, sfgaoMask, psfgaoAttribs); hr = get_parent_shellfolder(&parent_folder); if (SUCCEEDED(hr)) { child_pidl = ILFindLastID(m_pidl); *psfgaoAttribs = sfgaoMask; hr = parent_folder->GetAttributesOf(1, &child_pidl, psfgaoAttribs); } return hr; } HRESULT WINAPI CShellItem::Compare(IShellItem *oth, SICHINTF hint, int *piOrder) { HRESULT hr; CComPtr pIDList; CComPtr parent_folder; 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 = get_parent_shellfolder(&parent_folder); if (SUCCEEDED(hr)) { hr = parent_folder->CompareIDs(hint, m_pidl, pidl); *piOrder = static_cast(SCODE_CODE(hr)); } ILFree(pidl); } } if (SUCCEEDED(hr)) return S_OK; return hr; } HRESULT WINAPI CShellItem::GetClassID(CLSID *pClassID) { TRACE("(%p,%p)\n", this, pClassID); *pClassID = CLSID_ShellItem; return S_OK; } HRESULT WINAPI CShellItem::SetIDList(LPCITEMIDLIST 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(LPITEMIDLIST *ppidl) { TRACE("(%p,%p)\n", this, ppidl); *ppidl = ILClone(m_pidl); if (*ppidl) return S_OK; else return E_OUTOFMEMORY; } HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent, IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi) { HRESULT hr; CComPtr newShellItem; LPITEMIDLIST new_pidl; CComPtr newPersistIDList; TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi); if (!pidl) return E_INVALIDARG; if (pidlParent || psfParent) { LPITEMIDLIST temp_parent = NULL; if (!pidlParent) { CComPtr 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)) { *ppsi = NULL; 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; }