[SHELL32] Sync CShellDispatch and family with wine.

Incorporates work from Ivan Rodionov.
CORE-12955
This commit is contained in:
Mark Jansen
2018-04-13 22:59:04 +02:00
parent fd87f0ad87
commit e8dcbcc61d
7 changed files with 261 additions and 186 deletions

View File

@@ -1,21 +1,8 @@
/*
* FolderItem(s) implementation
*
* Copyright 2015,2016 Mark Jansen
*
* 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
* PROJECT: shell32
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
* PURPOSE: FolderItem(s) implementation
* COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org)
*/
#include "precomp.h"
@@ -31,28 +18,49 @@ CFolderItem::~CFolderItem()
{
}
void CFolderItem::Init(LPITEMIDLIST idlist)
HRESULT CFolderItem::Initialize(Folder* folder, LPITEMIDLIST idlist)
{
m_idlist.Attach(idlist);
m_idlist.Attach(ILClone(idlist));
m_Folder = folder;
return S_OK;
}
// *** FolderItem methods ***
HRESULT STDMETHODCALLTYPE CFolderItem::get_Application(IDispatch **ppid)
{
TRACE("(%p, %p)\n", this, ppid);
return E_NOTIMPL;
return m_Folder->get_Application(ppid);
}
HRESULT STDMETHODCALLTYPE CFolderItem::get_Parent(IDispatch **ppid)
{
TRACE("(%p, %p)\n", this, ppid);
if (ppid)
{
*ppid = m_Folder;
m_Folder->AddRef();
}
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CFolderItem::get_Name(BSTR *pbs)
{
TRACE("(%p, %p)\n", this, pbs);
return E_NOTIMPL;
*pbs = NULL;
CComPtr<IShellFolder2> Parent;
LPCITEMIDLIST last_part;
HRESULT hr = SHBindToParent(m_idlist, IID_PPV_ARG(IShellFolder2, &Parent), &last_part);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
STRRET strret;
hr = Parent->GetDisplayNameOf(last_part, SHGDN_INFOLDER, &strret);
if (!FAILED_UNEXPECTEDLY(hr))
hr = StrRetToBSTR(&strret, last_part, pbs);
return hr;
}
HRESULT STDMETHODCALLTYPE CFolderItem::put_Name(BSTR bs)
@@ -170,11 +178,11 @@ CFolderItems::~CFolderItems()
{
}
HRESULT CFolderItems::Init(LPITEMIDLIST idlist)
HRESULT CFolderItems::Initialize(LPITEMIDLIST idlist, Folder* parent)
{
CComPtr<IShellFolder> psfDesktop, psfTarget;
m_idlist.Attach(idlist);
m_idlist.Attach(ILClone(idlist));
HRESULT hr = SHGetDesktopFolder(&psfDesktop);
if (FAILED_UNEXPECTEDLY(hr))
@@ -189,6 +197,7 @@ HRESULT CFolderItems::Init(LPITEMIDLIST idlist)
if (FAILED_UNEXPECTEDLY(hr))
return hr;
m_Folder = parent;
return S_OK;
}
@@ -210,8 +219,7 @@ HRESULT STDMETHODCALLTYPE CFolderItems::get_Count(long *plCount)
return hr;
CComHeapPtr<ITEMIDLIST> Pidl;
hr = m_EnumIDList->Next(1, &Pidl, 0);
while (hr != S_FALSE)
while ((hr = m_EnumIDList->Next(1, &Pidl, 0)) != S_FALSE)
{
count++;
Pidl.Free();
@@ -226,12 +234,16 @@ HRESULT STDMETHODCALLTYPE CFolderItems::get_Count(long *plCount)
HRESULT STDMETHODCALLTYPE CFolderItems::get_Application(IDispatch **ppid)
{
TRACE("(%p, %p)\n", this, ppid);
return E_NOTIMPL;
return m_Folder->get_Application(ppid);
}
HRESULT STDMETHODCALLTYPE CFolderItems::get_Parent(IDispatch **ppid)
{
TRACE("(%p, %p)\n", this, ppid);
if (ppid)
*ppid = NULL;
return E_NOTIMPL;
}
@@ -240,40 +252,48 @@ HRESULT STDMETHODCALLTYPE CFolderItems::Item(VARIANT index, FolderItem **ppid)
if (!m_EnumIDList)
return E_FAIL;
if (V_VT(&index) != VT_I4 && V_VT(&index) != VT_UI4)
return E_INVALIDARG;
if (V_VT(&index) == VT_I2)
VariantChangeType(&index, &index, 0, VT_I4);
ULONG count = V_UI4(&index);
HRESULT hr = m_EnumIDList->Reset();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = m_EnumIDList->Skip(count);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
CComHeapPtr<ITEMIDLIST> spPidl;
hr = m_EnumIDList->Next(1, &spPidl, 0);
if (hr == S_OK)
if (V_VT(&index) == VT_I4)
{
CFolderItem* item = new CComObject<CFolderItem>();
item->AddRef();
item->Init(spPidl.Detach());
*ppid = item;
return S_OK;
ULONG count = V_UI4(&index);
HRESULT hr = m_EnumIDList->Reset();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = m_EnumIDList->Skip(count);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
CComHeapPtr<ITEMIDLIST> spPidl;
hr = m_EnumIDList->Next(1, &spPidl, 0);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = ShellObjectCreatorInit<CFolderItem>(m_Folder, static_cast<LPITEMIDLIST>(spPidl), IID_PPV_ARG(FolderItem, ppid));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return hr;
}
else if (V_VT(&index) == VT_BSTR)
{
if (!V_BSTR(&index))
return S_FALSE;
HRESULT hr = m_Folder->ParseName(V_BSTR(&index), ppid);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return hr;
}
return hr;
FIXME("Index type %d not handled.\n", V_VT(&index));
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CFolderItems::_NewEnum(IUnknown **ppunk)
{
CFolderItems* items = new CComObject<CFolderItems>();
items->AddRef();
items->Init(ILClone(m_idlist));
*ppunk = items;
return S_OK;
return ShellObjectCreatorInit<CFolderItems>(static_cast<LPITEMIDLIST>(m_idlist), m_Folder, IID_FolderItems, reinterpret_cast<void**>(ppunk));
}