Index: dll/win32/shell32/shell32.spec =================================================================== --- dll/win32/shell32/shell32.spec (revision 58787) +++ dll/win32/shell32/shell32.spec (working copy) @@ -505,3 +505,10 @@ @ stdcall SHRegQueryValueW (long long long long) @ stdcall SHRegQueryValueExW (long wstr ptr ptr ptr ptr) @ stdcall SHRegDeleteKeyW(long wstr) + +@ stdcall SHCreateItemFromParsingName(ptr ptr ptr ptr) +@ stdcall SHCreateItemFromIDList(ptr ptr ptr) +@ stdcall SHCreateShellItemArray(ptr ptr long ptr ptr) +@ stdcall SHCreateShellItemArrayFromShellItem(ptr ptr ptr) +@ stdcall SHGetIDListFromObject(ptr ptr) +@ stdcall SHGetItemFromDataObject(ptr long ptr ptr) Index: dll/win32/shell32/shell32_main.cpp =================================================================== --- dll/win32/shell32/shell32_main.cpp (revision 58787) +++ dll/win32/shell32/shell32_main.cpp (working copy) @@ -1278,24 +1278,25 @@ BEGIN_OBJECT_MAP(ObjectMap) -OBJECT_ENTRY(CLSID_ShellFSFolder, CFSFolder) -OBJECT_ENTRY(CLSID_MyComputer, CDrivesFolder) -OBJECT_ENTRY(CLSID_ShellDesktop, CDesktopFolder) -OBJECT_ENTRY(CLSID_ShellItem, CShellItem) -OBJECT_ENTRY(CLSID_ShellLink, CShellLink) -OBJECT_ENTRY(CLSID_DragDropHelper, CDropTargetHelper) -OBJECT_ENTRY(CLSID_ControlPanel, CControlPanelFolder) -OBJECT_ENTRY(CLSID_AutoComplete, CAutoComplete) -OBJECT_ENTRY(CLSID_MyDocuments, CMyDocsFolder) -OBJECT_ENTRY(CLSID_NetworkPlaces, CNetFolder) -OBJECT_ENTRY(CLSID_FontsFolderShortcut, CFontsFolder) -OBJECT_ENTRY(CLSID_Printers, CPrinterFolder) -OBJECT_ENTRY(CLSID_AdminFolderShortcut, CAdminToolsFolder) -OBJECT_ENTRY(CLSID_RecycleBin, CRecycleBin) -OBJECT_ENTRY(CLSID_OpenWithMenu, COpenWithMenu) -OBJECT_ENTRY(CLSID_NewMenu, CNewMenu) -OBJECT_ENTRY(CLSID_StartMenu, CStartMenu) -OBJECT_ENTRY(CLSID_MenuBandSite, CMenuBandSite) + OBJECT_ENTRY(CLSID_ShellFSFolder, CFSFolder) + OBJECT_ENTRY(CLSID_MyComputer, CDrivesFolder) + OBJECT_ENTRY(CLSID_ShellDesktop, CDesktopFolder) + OBJECT_ENTRY(CLSID_ShellItem, CShellItem) + OBJECT_ENTRY(CLSID_ShellItemArray, CShellItemArray) + OBJECT_ENTRY(CLSID_ShellLink, CShellLink) + OBJECT_ENTRY(CLSID_DragDropHelper, CDropTargetHelper) + OBJECT_ENTRY(CLSID_ControlPanel, CControlPanelFolder) + OBJECT_ENTRY(CLSID_AutoComplete, CAutoComplete) + OBJECT_ENTRY(CLSID_MyDocuments, CMyDocsFolder) + OBJECT_ENTRY(CLSID_NetworkPlaces, CNetFolder) + OBJECT_ENTRY(CLSID_FontsFolderShortcut, CFontsFolder) + OBJECT_ENTRY(CLSID_Printers, CPrinterFolder) + OBJECT_ENTRY(CLSID_AdminFolderShortcut, CAdminToolsFolder) + OBJECT_ENTRY(CLSID_RecycleBin, CRecycleBin) + OBJECT_ENTRY(CLSID_OpenWithMenu, COpenWithMenu) + OBJECT_ENTRY(CLSID_NewMenu, CNewMenu) + OBJECT_ENTRY(CLSID_StartMenu, CStartMenu) + OBJECT_ENTRY(CLSID_MenuBandSite, CMenuBandSite) END_OBJECT_MAP() CShell32Module gModule; Index: dll/win32/shell32/shellitem.cpp =================================================================== --- dll/win32/shell32/shellitem.cpp (revision 58787) +++ dll/win32/shell32/shellitem.cpp (working copy) @@ -27,9 +27,11 @@ EXTERN_C HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent, IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi); -CShellItem::CShellItem() +////////////////////////////////////// +// CShellItem + +CShellItem::CShellItem() : m_pidl(NULL) { - m_pidl = NULL; } CShellItem::~CShellItem() @@ -60,23 +62,25 @@ HRESULT CShellItem::get_parent_shellfolder(IShellFolder **ppsf) { + HRESULT hr; LPITEMIDLIST parent_pidl; CComPtr desktop; - HRESULT hr; - + hr = get_parent_pidl(&parent_pidl); if (SUCCEEDED(hr)) { hr = SHGetDesktopFolder(&desktop); if (SUCCEEDED(hr)) - hr = desktop->BindToObject(parent_pidl, NULL, IID_IShellFolder, (void**)ppsf); + hr = desktop->BindToObject( + parent_pidl, NULL, IID_IShellFolder, reinterpret_cast(ppsf)); ILFree(parent_pidl); } return hr; } -HRESULT WINAPI CShellItem::BindToHandler(IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppvOut) +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); @@ -87,8 +91,8 @@ HRESULT WINAPI CShellItem::GetParent(IShellItem **ppsi) { + HRESULT hr; LPITEMIDLIST parent_pidl; - HRESULT hr; TRACE("(%p,%p)\n", this, ppsi); @@ -104,8 +108,8 @@ HRESULT WINAPI CShellItem::GetDisplayName(SIGDN sigdnName, LPWSTR *ppszName) { + HRESULT hr; CComPtr parent_folder; - HRESULT hr; STRRET name; DWORD uFlags; @@ -114,7 +118,7 @@ if (sigdnName & SIGDN_URL) return E_NOTIMPL; - if (ppszName == NULL) + if (!ppszName) return E_POINTER; *ppszName = NULL; @@ -161,7 +165,8 @@ { child_pidl = ILFindLastID(m_pidl); *psfgaoAttribs = sfgaoMask; - hr = parent_folder->GetAttributesOf(1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs); + hr = parent_folder->GetAttributesOf( + 1, const_cast(&child_pidl), psfgaoAttribs); } return hr; @@ -169,17 +174,17 @@ HRESULT WINAPI CShellItem::Compare(IShellItem *oth, SICHINTF hint, int *piOrder) { + HRESULT hr; + CComPtr pIDList; CComPtr parent_folder; - CComPtr pIDList; - HRESULT hr; LPITEMIDLIST pidl; TRACE("(%p,%p,%x,%p)\n", this, oth, hint, piOrder); - if (piOrder == NULL || oth == NULL) + if (!piOrder || !oth) return E_POINTER; - hr = oth->QueryInterface(IID_IPersistIDList, (void **)&pIDList); + hr = oth->QueryInterface(IID_IPersistIDList, reinterpret_cast(&pIDList)); if (SUCCEEDED(hr)) { hr = pIDList->GetIDList(&pidl); @@ -189,21 +194,22 @@ if (SUCCEEDED(hr)) { hr = parent_folder->CompareIDs(hint, m_pidl, pidl); - *piOrder = (int)SCODE_CODE(hr); + *piOrder = static_cast(SCODE_CODE(hr)); } ILFree(pidl); } } - if (SUCCEEDED(hr)) - return S_OK; - return hr; + return SUCCEEDED(hr) ? S_OK : hr; } HRESULT WINAPI CShellItem::GetClassID(CLSID *pClassID) { TRACE("(%p,%p)\n", this, pClassID); + if (pClassID == NULL) + return E_POINTER; + *pClassID = CLSID_ShellItem; return S_OK; } @@ -214,6 +220,9 @@ TRACE("(%p,%p)\n", this, pidlx); + if (!pidlx) + return E_POINTER; + new_pidl = ILClone(pidlx); if (new_pidl) { @@ -229,6 +238,9 @@ { TRACE("(%p,%p)\n", this, ppidl); + if (!ppidl) + return E_POINTER; + *ppidl = ILClone(m_pidl); if (*ppidl) return S_OK; @@ -236,28 +248,31 @@ return E_OUTOFMEMORY; } +////////////////////////////////////// +// SHCreateShellItem [SHELL32.@] + +EXTERN_C HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent, IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi) { - IShellItem *newShellItem; + HRESULT hr; LPITEMIDLIST new_pidl; - CComPtr newPersistIDList; - HRESULT hr; + CComPtr pItem; + CComPtr pPersistIDList; + CComPtr ppf2Parent; TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi); if (!pidl) - { return E_INVALIDARG; - } - else if (pidlParent || psfParent) + + if (pidlParent || psfParent) { - LPITEMIDLIST temp_parent=NULL; + LPITEMIDLIST temp_parent = NULL; if (!pidlParent) { - CComPtr ppf2Parent; - - if (FAILED(psfParent->QueryInterface(IID_IPersistFolder2, (void**)&ppf2Parent))) + if (FAILED(psfParent->QueryInterface( + IID_IPersistFolder2, reinterpret_cast(&ppf2Parent)))) { FIXME("couldn't get IPersistFolder2 interface of parent\n"); return E_NOINTERFACE; @@ -285,26 +300,548 @@ return E_OUTOFMEMORY; } - hr = CShellItem::_CreatorClass::CreateInstance(NULL, IID_IShellItem, (void**)&newShellItem); - if (FAILED(hr)) + hr = CShellItem::_CreatorClass::CreateInstance( + NULL, IID_IShellItem, reinterpret_cast(&pItem)); + if (SUCCEEDED(hr)) { - *ppsi = NULL; - ILFree(new_pidl); - return hr; + hr = pItem->QueryInterface( + IID_IPersistIDList, reinterpret_cast(&pPersistIDList)); + if (SUCCEEDED(hr)) + { + hr = pPersistIDList->SetIDList(new_pidl); + if (SUCCEEDED(hr)) + { + *ppsi = static_cast(pItem.Detach()); + return hr; + } + } } - hr = newShellItem->QueryInterface(IID_IPersistIDList, (void **)&newPersistIDList); - if (FAILED(hr)) + + *ppsi = NULL; + ILFree(new_pidl); + return hr; +} + +////////////////////////////////////// +// SHCreateItemFromParsingName [SHELL32.@] + +EXTERN_C +HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath, + IBindCtx *pbc, REFIID riid, void **ppv) +{ + HRESULT ret; + LPITEMIDLIST pidl; + CComPtr pItem; + CComPtr pPersistIDList; + + if (!ppv) + return E_POINTER; + + *ppv = NULL; + + ret = SHParseDisplayName(pszPath, pbc, &pidl, 0, NULL); + if (SUCCEEDED(ret)) { - ILFree(new_pidl); - return hr; + ret = CShellItem::_CreatorClass::CreateInstance( + NULL, IID_IShellItem, reinterpret_cast(&pItem)); + if (SUCCEEDED(ret)) + { + ret = pItem->QueryInterface( + IID_IPersistIDList, reinterpret_cast(&pPersistIDList)); + if (SUCCEEDED(ret)) + { + ret = pPersistIDList->SetIDList(pidl); + if (SUCCEEDED(ret)) + { + *ppv = static_cast(pItem.Detach()); + } + } + } + ILFree(pidl); } - hr = newPersistIDList->SetIDList(new_pidl); - if (FAILED(hr)) + + return ret; +} + +////////////////////////////////////// +// SHCreateItemFromIDList [SHELL32.@] + +EXTERN_C +HRESULT WINAPI +SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv) +{ + HRESULT ret; + CComPtr pItem; + CComPtr pPersistIDList; + + if (!pidl) + return E_POINTER; + + *ppv = NULL; + + ret = CShellItem::_CreatorClass::CreateInstance( + NULL, IID_IShellItem, reinterpret_cast(&pItem)); + if (SUCCEEDED(ret)) { - ILFree(new_pidl); - return hr; + ret = pItem->QueryInterface( + IID_IPersistIDList, reinterpret_cast(&pPersistIDList)); + if (SUCCEEDED(ret)) + { + ret = pPersistIDList->SetIDList(pidl); + if (SUCCEEDED(ret)) + { + *ppv = static_cast(pItem.Detach()); + } + } } - ILFree(new_pidl); - *ppsi = newShellItem; - return hr; + + return ret; } + +////////////////////////////////////// +// SHGetItemFromDataObject [SHELL32.@] + +EXTERN_C +HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj, + DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv) +{ + HRESULT ret; + FORMATETC fmt; + STGMEDIUM medium; + LPITEMIDLIST pidl; + + TRACE("%p, %x, %s, %p\n", pdtobj, dwFlags, debugstr_guid(&riid), ppv); + + if (!pdtobj) + return E_POINTER; + + fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW); + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_HGLOBAL; + + ret = pdtobj->GetData(&fmt, &medium); + if (SUCCEEDED(ret)) + { + LPIDA pida = reinterpret_cast(GlobalLock(medium.hGlobal)); + + if ((pida->cidl > 1 && !(dwFlags & DOGIF_ONLY_IF_ONE)) || + pida->cidl == 1) + { + // Get the first pidl (parent + child1) + pidl = ILCombine( + reinterpret_cast( + reinterpret_cast(pida) + pida->aoffset[0]), + reinterpret_cast( + reinterpret_cast(pida) + pida->aoffset[1])); + + ret = SHCreateItemFromIDList(pidl, riid, ppv); + ILFree(pidl); + } + else + { + ret = E_FAIL; + } + + GlobalUnlock(medium.hGlobal); + GlobalFree(medium.hGlobal); + } + + if (FAILED(ret) && !(dwFlags & DOGIF_NO_HDROP)) + { + TRACE("Attempting to fall back on CF_HDROP.\n"); + + fmt.cfFormat = CF_HDROP; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_HGLOBAL; + + ret = pdtobj->GetData(&fmt, &medium); + if (SUCCEEDED(ret)) + { + DROPFILES *df = reinterpret_cast(GlobalLock(medium.hGlobal)); + LPBYTE files = reinterpret_cast(df) + df->pFiles; + BOOL multiple_files = FALSE; + + ret = E_FAIL; + if (!df->fWide) + { + WCHAR filename[MAX_PATH]; + PCSTR first_file = reinterpret_cast(files); + if (*(files + lstrlenA(first_file) + 1) != 0) + multiple_files = TRUE; + + if (!(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE))) + { + MultiByteToWideChar(CP_ACP, 0, first_file, -1, filename, MAX_PATH); + ret = SHCreateItemFromParsingName(filename, NULL, riid, ppv); + } + } + else + { + PCWSTR first_file = reinterpret_cast(files); + if (*(reinterpret_cast(files) + lstrlenW(first_file) + 1) != 0) + multiple_files = TRUE; + + if (!(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE))) + ret = SHCreateItemFromParsingName(first_file, NULL, riid, ppv); + } + + GlobalUnlock(medium.hGlobal); + GlobalFree(medium.hGlobal); + } + } + + if (FAILED(ret) && !(dwFlags & DOGIF_NO_URL)) + { + FIXME("Failed to create item, should try CF_URL.\n"); + } + + return ret; +} + +////////////////////////////////////// +// SHGetIDListFromObject [SHELL32.@] + +EXTERN_C +HRESULT WINAPI SHGetIDListFromObject(IUnknown *punk, PIDLIST_ABSOLUTE *ppidl) +{ + HRESULT ret; + CComPtr ppersidl; + CComPtr ppf2; + CComPtr pdo; + CComPtr pfv; + CComPtr psi; + CComPtr psf; + + if (!punk) + return E_NOINTERFACE; + + *ppidl = NULL; + + // Try IPersistIDList + ret = punk->QueryInterface(IID_IPersistIDList, reinterpret_cast(&ppersidl)); + if (SUCCEEDED(ret)) + { + TRACE("IPersistIDList (%p)\n", &ppersidl); + ret = ppersidl->GetIDList(ppidl); + if (SUCCEEDED(ret)) + return ret; + } + + // Try IPersistFolder2 + ret = punk->QueryInterface(IID_IPersistFolder2, reinterpret_cast(&ppf2)); + if (SUCCEEDED(ret)) + { + TRACE("IPersistFolder2 (%p)\n", &ppf2); + ret = ppf2->GetCurFolder(ppidl); + if (SUCCEEDED(ret)) + return ret; + } + + // Try IDataObject + ret = punk->QueryInterface(IID_IDataObject, reinterpret_cast(&pdo)); + if (SUCCEEDED(ret)) + { + TRACE("IDataObject (%p)\n", &pdo); + ret = SHGetItemFromDataObject( + pdo, DOGIF_ONLY_IF_ONE, IID_IShellItem, reinterpret_cast(&psi)); + if (SUCCEEDED(ret)) + ret = SHGetIDListFromObject(static_cast(psi), ppidl); + if (SUCCEEDED(ret)) + return ret; + } + + // Try IFolderView + ret = punk->QueryInterface(IID_IFolderView, reinterpret_cast(&pfv)); + if (SUCCEEDED(ret)) + { + TRACE("IFolderView (%p)\n", &pfv); + ret = pfv->GetFolder(IID_IShellFolder, reinterpret_cast(&psf)); + if (SUCCEEDED(ret)) + { + // We might be able to get IPersistFolder2 from a shellfolder. + ret = SHGetIDListFromObject(static_cast(psf), ppidl); + } + return ret; + } + + return ret; +} + +////////////////////////////////////// +// SHGetItemFromObject [SHELL32.@] + +EXTERN_C +HRESULT WINAPI SHGetItemFromObject(IUnknown *punk, REFIID riid, void **ppv) +{ + LPITEMIDLIST pidl; + HRESULT ret; + + ret = SHGetIDListFromObject(punk, &pidl); + if (SUCCEEDED(ret)) + { + ret = SHCreateItemFromIDList(pidl, riid, ppv); + ILFree(pidl); + } + + return ret; +} + +////////////////////////////////////// +// CShellItemArray + +const CLSID CLSID_ShellItemArray = + { 0xB63EA76D, 0x1F85, 0x456F, {0xA1, 0x9C, 0x48, 0x15, 0x9E, 0xFA, 0x85, 0x8B} }; + +CShellItemArray::CShellItemArray() : m_array(NULL), m_count(0) +{ +} + +CShellItemArray::~CShellItemArray() +{ + for (DWORD i = 0; i < m_count; i++) + { + if (m_array[i]) + m_array[i]->Release(); + } + CoTaskMemFree(m_array); +} + +HRESULT STDMETHODCALLTYPE CShellItemArray::BindToHandler( + IBindCtx *pbc, + REFGUID bhid, + REFIID riid, + void **ppvOut) +{ + FIXME("Stub: %p (%p, %s, %s, %p)\n", + this, pbc, shdebugstr_guid(&bhid), shdebugstr_guid(&riid), ppvOut); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CShellItemArray::GetPropertyStore( + GETPROPERTYSTOREFLAGS flags, + REFIID riid, + void **ppv) +{ + FIXME("Stub: %p (%x, %s, %p)\n", this, flags, shdebugstr_guid(&riid), ppv); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CShellItemArray::GetPropertyDescriptionList( + REFPROPERTYKEY keyType, + REFIID riid, + void **ppv) +{ + FIXME("Stub: %p (%p, %s, %p)\n", + this, keyType, shdebugstr_guid(&riid), ppv); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CShellItemArray::GetAttributes( + SIATTRIBFLAGS AttribFlags, + SFGAOF sfgaoMask, + SFGAOF *psfgaoAttribs) +{ + FIXME("Stub: %p (%x, %x, %p)\n", this, AttribFlags, sfgaoMask, psfgaoAttribs); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CShellItemArray::GetCount( + DWORD *pdwNumItems) +{ + TRACE("%p (%p)\n", this, pdwNumItems); + + if (!pdwNumItems) + return E_POINTER; + + *pdwNumItems = m_count; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CShellItemArray::GetItemAt( + DWORD dwIndex, + IShellItem **ppsi) +{ + TRACE("%p (%x, %p)\n", this, dwIndex, ppsi); + + if (!ppsi) + return E_POINTER; + + if (dwIndex >= m_count) + return E_FAIL; + + m_array[dwIndex]->AddRef(); + *ppsi = m_array[dwIndex]; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CShellItemArray::EnumItems( + IEnumShellItems **ppenumShellItems) +{ + FIXME("Stub: %p (%p)\n", this, ppenumShellItems); + return E_NOTIMPL; +} + +////////////////////////////////////// +// SHCreateShellItemArray [SHELL32.@] + +EXTERN_C +HRESULT WINAPI +SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent, + IShellFolder *psf, + UINT cidl, + PCUITEMID_CHILD_ARRAY ppidl, + IShellItemArray **ppsiItemArray) +{ + HRESULT ret = E_FAIL; + CComPtr pArray; + IShellItem **array; + UINT i; + + TRACE("%p, %p, %d, %p, %p\n", pidlParent, psf, cidl, ppidl, ppsiItemArray); + + if (!pidlParent && !psf) + return E_POINTER; + + if (!ppsiItemArray) + return E_POINTER; + + if (!ppidl) + return E_INVALIDARG; + + array = reinterpret_cast(CoTaskMemAlloc(cidl * sizeof(IShellItem *))); + if (!array) + return E_OUTOFMEMORY; + + for (i = 0; i < cidl; i++) + { + ret = SHCreateShellItem(pidlParent, psf, ppidl[i], &array[i]); + if (FAILED(ret)) + break; + } + + if (SUCCEEDED(ret)) + { + ret = CShellItemArray::_CreatorClass::CreateInstance( + NULL, IID_IShellItemArray, reinterpret_cast(&pArray)); + if (SUCCEEDED(ret)) + { + pArray->m_array = array; + pArray->m_count = cidl; + *ppsiItemArray = static_cast(pArray.Detach()); + return ret; + } + } + + // failed. clean up + for (i = 0; i < cidl; i++) + if (array[i]) array[i]->Release(); + CoTaskMemFree(array); + *ppsiItemArray = NULL; + return ret; +} + +////////////////////////////////////// +// SHCreateShellItemArrayFromShellItem [SHELL32.@] + +EXTERN_C +HRESULT WINAPI +SHCreateShellItemArrayFromShellItem(IShellItem *psi, REFIID riid, void **ppv) +{ + HRESULT ret; + CComPtr pArray; + IShellItem **array; + + TRACE("%p, %s, %p\n", psi, shdebugstr_guid(&riid), ppv); + + *ppv = NULL; + + array = reinterpret_cast(CoTaskMemAlloc(sizeof(IShellItem *))); + if (!array) + return E_OUTOFMEMORY; + + ret = CShellItemArray::_CreatorClass::CreateInstance( + NULL, riid, reinterpret_cast(&pArray)); + if (SUCCEEDED(ret)) + { + array[0] = psi; + psi->AddRef(); + pArray->m_array = array; + pArray->m_count = 1; + *ppv = static_cast(pArray.Detach()); + } + else + { + CoTaskMemFree(array); + } + + return ret; +} + +////////////////////////////////////// +// SHCreateShellItemArrayFromDataObject [SHELL32.@] + +EXTERN_C +HRESULT WINAPI SHCreateShellItemArrayFromDataObject(IDataObject *pdo, + REFIID riid, void **ppv) +{ + HRESULT ret; + CComPtr pArray; + FORMATETC fmt; + STGMEDIUM medium; + UINT i; + LPCITEMIDLIST parent_pidl, *children; + + TRACE("%p, %s, %p\n", pdo, shdebugstr_guid(&riid), ppv); + + *ppv = NULL; + + if (!pdo) + return E_INVALIDARG; + + fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW); + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_HGLOBAL; + + ret = pdo->GetData(&fmt, &medium); + if (SUCCEEDED(ret)) + { + LPIDA pida = reinterpret_cast(GlobalLock(medium.hGlobal)); + + TRACE("Converting %d objects.\n", pida->cidl); + + parent_pidl = reinterpret_cast( + reinterpret_cast(pida) + pida->aoffset[0]); + + children = reinterpret_cast( + CoTaskMemAlloc(sizeof(LPCITEMIDLIST) * pida->cidl)); + + for (i = 0; i < pida->cidl; i++) + { + children[i] = + reinterpret_cast( + reinterpret_cast(pida) + pida->aoffset[i+1]); + } + + ret = SHCreateShellItemArray( + parent_pidl, NULL, pida->cidl, children, &pArray); + + CoTaskMemFree(children); + + GlobalUnlock(medium.hGlobal); + GlobalFree(medium.hGlobal); + + if (SUCCEEDED(ret)) + { + ret = pArray->QueryInterface(riid, ppv); + } + } + + return ret; +} Index: dll/win32/shell32/shellitem.h =================================================================== --- dll/win32/shell32/shellitem.h (revision 58787) +++ dll/win32/shell32/shellitem.h (working copy) @@ -1,8 +1,9 @@ /* - * IShellItem implementation + * IShellItem and IShellItemArray 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 @@ -22,41 +23,122 @@ #ifndef _SHELLITEM_H_ #define _SHELLITEM_H_ +////////////////////////////////////// +// CShellItem + class CShellItem : - public CComCoClass, - public CComObjectRootEx, - public IShellItem, - public IPersistIDList + public CComCoClass, + public CComObjectRootEx, + public IShellItem, + public IPersistIDList { private: - LPITEMIDLIST m_pidl; + LPITEMIDLIST m_pidl; + public: - CShellItem(); - ~CShellItem(); - HRESULT get_parent_pidl(LPITEMIDLIST *parent_pidl); - HRESULT get_parent_shellfolder(IShellFolder **ppsf); + CShellItem(); + HRESULT get_parent_pidl(LPITEMIDLIST *parent_pidl); + HRESULT get_parent_shellfolder(IShellFolder **ppsf); - // IShellItem - virtual HRESULT WINAPI BindToHandler(IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppvOut); - virtual HRESULT WINAPI GetParent(IShellItem **ppsi); - virtual HRESULT WINAPI GetDisplayName(SIGDN sigdnName, LPWSTR *ppszName); - virtual HRESULT WINAPI GetAttributes(SFGAOF sfgaoMask, SFGAOF *psfgaoAttribs); - virtual HRESULT WINAPI Compare(IShellItem *oth, SICHINTF hint, int *piOrder); +protected: + ~CShellItem(); - // IPersistIDList - virtual HRESULT WINAPI GetClassID(CLSID *pClassID); - virtual HRESULT WINAPI SetIDList(LPCITEMIDLIST pidl); - virtual HRESULT WINAPI GetIDList(LPITEMIDLIST *ppidl); +public: + // IShellItem + virtual HRESULT WINAPI BindToHandler(IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppvOut); + virtual HRESULT WINAPI GetParent(IShellItem **ppsi); + virtual HRESULT WINAPI GetDisplayName(SIGDN sigdnName, LPWSTR *ppszName); + virtual HRESULT WINAPI GetAttributes(SFGAOF sfgaoMask, SFGAOF *psfgaoAttribs); + virtual HRESULT WINAPI Compare(IShellItem *oth, SICHINTF hint, int *piOrder); -DECLARE_NO_REGISTRY() -DECLARE_NOT_AGGREGATABLE(CShellItem) + // IPersistIDList + virtual HRESULT WINAPI GetClassID(CLSID *pClassID); + virtual HRESULT WINAPI SetIDList(LPCITEMIDLIST pidl); + virtual HRESULT WINAPI GetIDList(LPITEMIDLIST *ppidl); -DECLARE_PROTECT_FINAL_CONSTRUCT() + DECLARE_NO_REGISTRY() + DECLARE_NOT_AGGREGATABLE(CShellItem) -BEGIN_COM_MAP(CShellItem) - COM_INTERFACE_ENTRY_IID(IID_IShellItem, IShellItem) - COM_INTERFACE_ENTRY_IID(IID_IPersistIDList, IPersistIDList) -END_COM_MAP() + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CShellItem) + COM_INTERFACE_ENTRY_IID(IID_IShellItem, IShellItem) + COM_INTERFACE_ENTRY_IID(IID_IPersistIDList, IPersistIDList) + END_COM_MAP() }; +////////////////////////////////////// +// CShellItemArray + +extern const CLSID CLSID_ShellItemArray; + +class CShellItemArray : + public CComCoClass, + public CComObjectRootEx, + public IShellItemArray +{ +private: + IShellItem **m_array; // allocated by CoTaskMemAlloc + DWORD m_count; + + friend HRESULT WINAPI + SHCreateShellItemArray(PCIDLIST_ABSOLUTE, + IShellFolder *, + UINT, + PCUITEMID_CHILD_ARRAY, + IShellItemArray **); + + friend HRESULT WINAPI + SHCreateShellItemArrayFromShellItem(IShellItem *, REFIID, void **); + +public: + CShellItemArray(); + +protected: + virtual ~CShellItemArray(); + +public: + // IShellItemArray + virtual HRESULT STDMETHODCALLTYPE BindToHandler( + IBindCtx *pbc, + REFGUID bhid, + REFIID riid, + void **ppvOut); + + virtual HRESULT STDMETHODCALLTYPE GetPropertyStore( + GETPROPERTYSTOREFLAGS flags, + REFIID riid, + void **ppv); + + virtual HRESULT STDMETHODCALLTYPE GetPropertyDescriptionList( + REFPROPERTYKEY keyType, + REFIID riid, + void **ppv); + + virtual HRESULT STDMETHODCALLTYPE GetAttributes( + SIATTRIBFLAGS AttribFlags, + SFGAOF sfgaoMask, + SFGAOF *psfgaoAttribs); + + virtual HRESULT STDMETHODCALLTYPE GetCount( + DWORD *pdwNumItems); + + virtual HRESULT STDMETHODCALLTYPE GetItemAt( + DWORD dwIndex, + IShellItem **ppsi); + + virtual HRESULT STDMETHODCALLTYPE EnumItems( + IEnumShellItems **ppenumShellItems); + +public: + DECLARE_NO_REGISTRY() + DECLARE_NOT_AGGREGATABLE(CShellItemArray) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CShellItemArray) + COM_INTERFACE_ENTRY_IID(IID_IShellItemArray, IShellItemArray) + END_COM_MAP() +}; + #endif // _SHELLITEM_H_ Index: lib/atl/atlcom.h =================================================================== --- lib/atl/atlcom.h (revision 58787) +++ lib/atl/atlcom.h (working copy) @@ -2,6 +2,7 @@ * ReactOS ATL * * 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 @@ -134,39 +135,26 @@ virtual ~CComObject() { - CComObject *pThis; - - pThis = reinterpret_cast *>(this); - pThis->FinalRelease(); + this->FinalRelease(); _pAtlModule->Unlock(); } STDMETHOD_(ULONG, AddRef)() { - CComObject *pThis; - - pThis = reinterpret_cast *>(this); - return pThis->InternalAddRef(); + return this->InternalAddRef(); } STDMETHOD_(ULONG, Release)() { - CComObject *pThis; - ULONG l; - - pThis = reinterpret_cast *>(this); - l = pThis->InternalRelease(); - if (l == 0) + ULONG ul = this->InternalRelease(); + if (ul == 0) delete this; - return l; + return ul; } STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) { - CComObject *pThis; - - pThis = reinterpret_cast *>(this); - return pThis->_InternalQueryInterface(iid, ppvObject); + return this->_InternalQueryInterface(iid, ppvObject); } static HRESULT WINAPI CreateInstance(CComObject **pp) @@ -283,36 +271,25 @@ STDMETHOD_(ULONG, AddRef)() { - CComObjectCached *pThis; - ULONG newRefCount; - - pThis = reinterpret_cast*>(this); - newRefCount = pThis->InternalAddRef(); - if (newRefCount == 2) + ULONG ul = this->InternalAddRef(); + if (ul == 2) _pAtlModule->Lock(); - return newRefCount; + return ul; } STDMETHOD_(ULONG, Release)() { - CComObjectCached *pThis; - ULONG newRefCount; - - pThis = reinterpret_cast*>(this); - newRefCount = pThis->InternalRelease(); - if (newRefCount == 0) + ULONG ul = this->InternalRelease(); + if (ul == 0) delete this; - else if (newRefCount == 1) + else if (ul == 1) _pAtlModule->Unlock(); - return newRefCount; + return ul; } STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) { - CComObjectCached *pThis; - - pThis = reinterpret_cast*>(this); - return pThis->_InternalQueryInterface(iid, ppvObject); + return this->_InternalQueryInterface(iid, ppvObject); } }; @@ -436,6 +413,11 @@ { public: _ATL_CREATORFUNC *m_pfnCreateInstance; + + virtual ~CComClassFactory() + { + } + public: STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj) { Index: lib/atl/statreg.h =================================================================== --- lib/atl/statreg.h (revision 58787) +++ lib/atl/statreg.h (working copy) @@ -60,9 +60,9 @@ ~CRegObject() { HRESULT hResult; - hResult = ClearReplacements(); ATLASSERT(SUCCEEDED(hResult)); + hResult = hResult; } HRESULT STDMETHODCALLTYPE QueryInterface(const IID & /* riid */, void ** /* ppvObject */ )