2 * IShellItem implementation
4 * Copyright 2008 Vincent Povirk for CodeWeavers
5 * Copyright 2009 Andrew Hill
6 * Copyright 2013 Katayama Hirofumi MZ
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
27 EXTERN_C HRESULT WINAPI
SHCreateShellItem(LPCITEMIDLIST pidlParent
,
28 IShellFolder
*psfParent
, LPCITEMIDLIST pidl
, IShellItem
**ppsi
);
30 CShellItem::CShellItem() :
35 CShellItem::~CShellItem()
40 HRESULT
CShellItem::get_parent_pidl(LPITEMIDLIST
*parent_pidl
)
42 *parent_pidl
= ILClone(m_pidl
);
45 if (ILRemoveLastID(*parent_pidl
))
61 HRESULT
CShellItem::get_parent_shellfolder(IShellFolder
**ppsf
)
64 LPITEMIDLIST parent_pidl
;
65 CComPtr
<IShellFolder
> desktop
;
67 hr
= get_parent_pidl(&parent_pidl
);
70 hr
= SHGetDesktopFolder(&desktop
);
72 hr
= desktop
->BindToObject(parent_pidl
, NULL
, IID_PPV_ARG(IShellFolder
, ppsf
));
79 HRESULT
CShellItem::get_shellfolder(IBindCtx
*pbc
, REFIID riid
, void **ppvOut
)
81 CComPtr
<IShellFolder
> psf
;
82 CComPtr
<IShellFolder
> psfDesktop
;
85 ret
= SHGetDesktopFolder(&psfDesktop
);
86 if (FAILED_UNEXPECTEDLY(ret
))
89 if (_ILIsDesktop(m_pidl
))
93 ret
= psfDesktop
->BindToObject(m_pidl
, pbc
, IID_PPV_ARG(IShellFolder
, &psf
));
94 if (FAILED_UNEXPECTEDLY(ret
))
98 return psf
->QueryInterface(riid
, ppvOut
);
101 HRESULT WINAPI
CShellItem::BindToHandler(IBindCtx
*pbc
, REFGUID rbhid
, REFIID riid
, void **ppvOut
)
104 TRACE("(%p, %p,%s,%p,%p)\n", this, pbc
, shdebugstr_guid(&rbhid
), riid
, ppvOut
);
107 if (IsEqualGUID(rbhid
, BHID_SFObject
))
109 return get_shellfolder(pbc
, riid
, ppvOut
);
111 else if (IsEqualGUID(rbhid
, BHID_SFUIObject
))
113 CComPtr
<IShellFolder
> psf_parent
;
114 if (_ILIsDesktop(m_pidl
))
115 ret
= SHGetDesktopFolder(&psf_parent
);
117 ret
= get_parent_shellfolder(&psf_parent
);
118 if (FAILED_UNEXPECTEDLY(ret
))
121 LPCITEMIDLIST pidl
= ILFindLastID(m_pidl
);
122 return psf_parent
->GetUIObjectOf(NULL
, 1, &pidl
, riid
, NULL
, ppvOut
);
124 else if (IsEqualGUID(rbhid
, BHID_DataObject
))
126 return BindToHandler(pbc
, BHID_SFUIObject
, IID_IDataObject
, ppvOut
);
128 else if (IsEqualGUID(rbhid
, BHID_SFViewObject
))
130 CComPtr
<IShellFolder
> psf
;
131 ret
= get_shellfolder(NULL
, IID_PPV_ARG(IShellFolder
, &psf
));
132 if (FAILED_UNEXPECTEDLY(ret
))
135 return psf
->CreateViewObject(NULL
, riid
, ppvOut
);
138 FIXME("Unsupported BHID %s.\n", debugstr_guid(&rbhid
));
140 return MK_E_NOOBJECT
;
143 HRESULT WINAPI
CShellItem::GetParent(IShellItem
**ppsi
)
146 LPITEMIDLIST parent_pidl
;
148 TRACE("(%p,%p)\n", this, ppsi
);
150 hr
= get_parent_pidl(&parent_pidl
);
153 hr
= SHCreateShellItem(NULL
, NULL
, parent_pidl
, ppsi
);
160 HRESULT WINAPI
CShellItem::GetDisplayName(SIGDN sigdnName
, LPWSTR
*ppszName
)
162 return SHGetNameFromIDList(m_pidl
, sigdnName
, ppszName
);
165 HRESULT WINAPI
CShellItem::GetAttributes(SFGAOF sfgaoMask
, SFGAOF
*psfgaoAttribs
)
167 CComPtr
<IShellFolder
> parent_folder
;
168 LPCITEMIDLIST child_pidl
;
171 TRACE("(%p,%x,%p)\n", this, sfgaoMask
, psfgaoAttribs
);
173 if (_ILIsDesktop(m_pidl
))
174 hr
= SHGetDesktopFolder(&parent_folder
);
176 hr
= get_parent_shellfolder(&parent_folder
);
177 if (FAILED_UNEXPECTEDLY(hr
))
180 child_pidl
= ILFindLastID(m_pidl
);
181 *psfgaoAttribs
= sfgaoMask
;
182 hr
= parent_folder
->GetAttributesOf(1, &child_pidl
, psfgaoAttribs
);
183 *psfgaoAttribs
&= sfgaoMask
;
185 if (FAILED_UNEXPECTEDLY(hr
))
188 return (sfgaoMask
== *psfgaoAttribs
) ? S_OK
: S_FALSE
;
191 HRESULT WINAPI
CShellItem::Compare(IShellItem
*oth
, SICHINTF hint
, int *piOrder
)
194 CComPtr
<IPersistIDList
> pIDList
;
195 CComPtr
<IShellFolder
> psfDesktop
;
198 TRACE("(%p,%p,%x,%p)\n", this, oth
, hint
, piOrder
);
200 if (piOrder
== NULL
|| oth
== NULL
)
203 hr
= oth
->QueryInterface(IID_PPV_ARG(IPersistIDList
, &pIDList
));
206 hr
= pIDList
->GetIDList(&pidl
);
209 hr
= SHGetDesktopFolder(&psfDesktop
);
212 hr
= psfDesktop
->CompareIDs(hint
, m_pidl
, pidl
);
213 *piOrder
= (int)(short)SCODE_CODE(hr
);
228 HRESULT WINAPI
CShellItem::GetClassID(CLSID
*pClassID
)
230 TRACE("(%p,%p)\n", this, pClassID
);
232 *pClassID
= CLSID_ShellItem
;
236 HRESULT WINAPI
CShellItem::SetIDList(LPCITEMIDLIST pidlx
)
238 LPITEMIDLIST new_pidl
;
240 TRACE("(%p,%p)\n", this, pidlx
);
242 new_pidl
= ILClone(pidlx
);
250 return E_OUTOFMEMORY
;
253 HRESULT WINAPI
CShellItem::GetIDList(LPITEMIDLIST
*ppidl
)
255 TRACE("(%p,%p)\n", this, ppidl
);
257 *ppidl
= ILClone(m_pidl
);
261 return E_OUTOFMEMORY
;
264 HRESULT WINAPI
SHCreateShellItem(LPCITEMIDLIST pidlParent
,
265 IShellFolder
*psfParent
, LPCITEMIDLIST pidl
, IShellItem
**ppsi
)
268 CComPtr
<IShellItem
> newShellItem
;
269 LPITEMIDLIST new_pidl
;
270 CComPtr
<IPersistIDList
> newPersistIDList
;
272 TRACE("(%p,%p,%p,%p)\n", pidlParent
, psfParent
, pidl
, ppsi
);
279 if (pidlParent
|| psfParent
)
281 LPITEMIDLIST temp_parent
= NULL
;
284 CComPtr
<IPersistFolder2
> ppf2Parent
;
286 if (FAILED(psfParent
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &ppf2Parent
))))
288 FIXME("couldn't get IPersistFolder2 interface of parent\n");
289 return E_NOINTERFACE
;
292 if (FAILED(ppf2Parent
->GetCurFolder(&temp_parent
)))
294 FIXME("couldn't get parent PIDL\n");
295 return E_NOINTERFACE
;
298 pidlParent
= temp_parent
;
301 new_pidl
= ILCombine(pidlParent
, pidl
);
305 return E_OUTOFMEMORY
;
309 new_pidl
= ILClone(pidl
);
311 return E_OUTOFMEMORY
;
314 hr
= CShellItem::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellItem
, &newShellItem
));
320 hr
= newShellItem
->QueryInterface(IID_PPV_ARG(IPersistIDList
, &newPersistIDList
));
326 hr
= newPersistIDList
->SetIDList(new_pidl
);
334 *ppsi
= newShellItem
.Detach();