Sync with trunk r63935.
authorDavid Quintana <gigaherz@gmail.com>
Sun, 24 Aug 2014 15:10:11 +0000 (15:10 +0000)
committerDavid Quintana <gigaherz@gmail.com>
Sun, 24 Aug 2014 15:10:11 +0000 (15:10 +0000)
svn path=/branches/shell-experiments/; revision=63939

87 files changed:
1  2 
base/applications/mscutils/eventvwr/eventvwr.c
base/applications/mscutils/eventvwr/lang/bg-BG.rc
base/applications/mscutils/eventvwr/lang/cs-CZ.rc
base/applications/mscutils/eventvwr/lang/de-DE.rc
base/applications/mscutils/eventvwr/lang/el-GR.rc
base/applications/mscutils/eventvwr/lang/en-US.rc
base/applications/mscutils/eventvwr/lang/es-ES.rc
base/applications/mscutils/eventvwr/lang/fr-FR.rc
base/applications/mscutils/eventvwr/lang/he-IL.rc
base/applications/mscutils/eventvwr/lang/it-IT.rc
base/applications/mscutils/eventvwr/lang/ja-JP.rc
base/applications/mscutils/eventvwr/lang/ko-KR.rc
base/applications/mscutils/eventvwr/lang/no-NO.rc
base/applications/mscutils/eventvwr/lang/pl-PL.rc
base/applications/mscutils/eventvwr/lang/pt-BR.rc
base/applications/mscutils/eventvwr/lang/ro-RO.rc
base/applications/mscutils/eventvwr/lang/ru-RU.rc
base/applications/mscutils/eventvwr/lang/sk-SK.rc
base/applications/mscutils/eventvwr/lang/sq-AL.rc
base/applications/mscutils/eventvwr/lang/sv-SE.rc
base/applications/mscutils/eventvwr/lang/tr-TR.rc
base/applications/mscutils/eventvwr/lang/uk-UA.rc
base/applications/mscutils/eventvwr/lang/zh-CN.rc
base/applications/mscutils/eventvwr/resource.h
base/applications/rapps/misc.c
base/shell/explorer/shell/shellfs.cpp
base/shell/explorer/shell/winfs.cpp
base/shell/explorer/shell/winfs.h
boot/bootdata/packages/CMakeLists.txt
cmake/CMakeMacros.cmake
cmake/gcc.cmake
dll/cpl/appwiz/addons.c
dll/cpl/desk/general.c
dll/win32/devmgr/lang/fr-FR.rc
dll/win32/shell32/defcontextmenu.cpp
dll/win32/shell32/folders/admintools.cpp
dll/win32/shell32/folders/admintools.h
dll/win32/shell32/folders/cpanel.cpp
dll/win32/shell32/folders/cpanel.h
dll/win32/shell32/folders/desktop.cpp
dll/win32/shell32/folders/desktop.h
dll/win32/shell32/folders/fonts.cpp
dll/win32/shell32/folders/fonts.h
dll/win32/shell32/folders/fs.cpp
dll/win32/shell32/folders/fs.h
dll/win32/shell32/folders/mycomp.cpp
dll/win32/shell32/folders/mycomp.h
dll/win32/shell32/folders/mydocuments.cpp
dll/win32/shell32/folders/mydocuments.h
dll/win32/shell32/folders/netplaces.cpp
dll/win32/shell32/folders/netplaces.h
dll/win32/shell32/folders/printers.cpp
dll/win32/shell32/folders/printers.h
dll/win32/shell32/folders/recyclebin.cpp
dll/win32/shell32/folders/recyclebin.h
drivers/filesystems/fastfat/CMakeLists.txt
drivers/filesystems/fastfat/fcb.c
drivers/filesystems/fastfat/fsctl.c
drivers/filesystems/fastfat/rw.c
drivers/filesystems/fastfat/vfat.h
drivers/filesystems/npfs/seinfo.c
drivers/network/ndisuio/main.c
drivers/network/ndisuio/ndisuio.h
drivers/network/ndisuio/protocol.c
drivers/network/tcpip/tcpip/fileobjs.c
hal/halx86/generic/dma.c
include/crt/ivec.h
include/psdk/bthdef.h
include/psdk/driverspecs.h
include/psdk/shobjidl.idl
include/psdk/shtypes.idl
include/psdk/stralign.h
lib/drivers/ip/transport/rawip/rawip.c
lib/drivers/ip/transport/udp/udp.c
media/fonts/UniVGA16.ttf
ntoskrnl/cc/copy.c
ntoskrnl/cc/fs.c
ntoskrnl/cc/view.c
ntoskrnl/config/cmsysini.c
ntoskrnl/include/internal/cc.h
ntoskrnl/io/iomgr/device.c
ntoskrnl/io/pnpmgr/pnpmgr.c
toolchain-gcc.cmake
win32ss/gdi/gdi32/objects/bitmap.c
win32ss/gdi/gdi32/objects/utils.c
win32ss/gdi/ntgdi/dibobj.c
win32ss/gdi/ntgdi/freetype.c

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc cmake/gcc.cmake
Simple merge
Simple merge
Simple merge
Simple merge
index 8b59ca6,0000000..b02f9d0
mode 100644,000000..100644
--- /dev/null
@@@ -1,1680 -1,0 +1,1681 @@@
-     CComPtr<IDataObject> pDataObj;
 +/*
 + * PROJECT:     shell32
 + * LICENSE:     GPL - See COPYING in the top level directory
 + * FILE:        dll/win32/shell32/shv_item_new.c
 + * PURPOSE:     provides default context menu implementation
 + * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
 + */
 +
 +/*
 +TODO:
 +    The code in NotifyShellViewWindow to deliver commands to the view is broken. It is an excellent
 +    example of the wrong way to do it.
 +*/
 +
 +#include "precomp.h"
 +
 +WINE_DEFAULT_DEBUG_CHANNEL(dmenu);
 +
 +typedef struct _DynamicShellEntry_
 +{
 +    UINT iIdCmdFirst;
 +    UINT NumIds;
 +    CLSID ClassID;
 +    IContextMenu *pCM;
 +    struct _DynamicShellEntry_ *pNext;
 +} DynamicShellEntry, *PDynamicShellEntry;
 +
 +typedef struct _StaticShellEntry_
 +{
 +    LPWSTR szVerb;
 +    LPWSTR szClass;
 +    struct _StaticShellEntry_ *pNext;
 +} StaticShellEntry, *PStaticShellEntry;
 +
 +class CDefaultContextMenu :
 +    public CComObjectRootEx<CComMultiThreadModelNoCS>,
 +    public IContextMenu2
 +{
 +    private:
 +        CComPtr<IShellFolder> m_psf;
 +        UINT m_cidl;
 +        PCUITEMID_CHILD_ARRAY m_apidl;
 +        CComPtr<IDataObject> m_pDataObj;
 +        PIDLIST_ABSOLUTE m_pidlFolder;
 +        DWORD m_bGroupPolicyActive;
 +        PDynamicShellEntry m_pDynamicEntries; /* first dynamic shell extension entry */
 +        UINT m_iIdSHEFirst; /* first used id */
 +        UINT m_iIdSHELast; /* last used id */
 +        PStaticShellEntry m_pStaticEntries; /* first static shell extension entry */
 +        UINT m_iIdSCMFirst; /* first static used id */
 +        UINT m_iIdSCMLast; /* last static used id */
 +
 +        void AddStaticEntry(LPCWSTR pwszVerb, LPCWSTR pwszClass);
 +        void AddStaticEntryForKey(HKEY hKey, LPCWSTR pwszClass);
 +        void AddStaticEntryForFileClass(LPCWSTR pwszExt);
 +        BOOL IsShellExtensionAlreadyLoaded(const CLSID *pclsid);
 +        HRESULT LoadDynamicContextMenuHandler(HKEY hKey, const CLSID *pclsid);
 +        BOOL EnumerateDynamicContextHandlerForKey(HKEY hRootKey);
 +        UINT InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, UINT IndexMenu, UINT idCmdFirst, UINT idCmdLast);
 +        UINT BuildBackgroundContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
 +        UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu);
 +        UINT BuildShellItemContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
 +        HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink);
 +        HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi);
 +        HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi);
 +        HRESULT DoRefresh(LPCMINVOKECOMMANDINFO lpcmi);
 +        HRESULT DoDelete(LPCMINVOKECOMMANDINFO lpcmi);
 +        HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy);
 +        HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi);
 +        HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi);
 +        HRESULT DoFormat(LPCMINVOKECOMMANDINFO lpcmi);
 +        HRESULT DoDynamicShellExtensions(LPCMINVOKECOMMANDINFO lpcmi);
 +        HRESULT DoStaticShellExtensions(LPCMINVOKECOMMANDINFO lpcmi);
 +        DWORD BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry);
 +        HRESULT TryToBrowse(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags);
 +        HRESULT InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry);
 +
 +    public:
 +        CDefaultContextMenu();
 +        ~CDefaultContextMenu();
 +        HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm);
 +
 +        // IContextMenu
 +        virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
 +        virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
 +        virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen);
 +
 +        // IContextMenu2
 +        virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
 +
 +        BEGIN_COM_MAP(CDefaultContextMenu)
 +        COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
 +        COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
 +        END_COM_MAP()
 +};
 +
 +CDefaultContextMenu::CDefaultContextMenu() :
 +    m_psf(NULL),
 +    m_cidl(0),
 +    m_apidl(NULL),
 +    m_pDataObj(NULL),
 +    m_pidlFolder(NULL),
 +    m_bGroupPolicyActive(0),
 +    m_pDynamicEntries(NULL),
 +    m_iIdSHEFirst(0),
 +    m_iIdSHELast(0),
 +    m_pStaticEntries(NULL),
 +    m_iIdSCMFirst(0),
 +    m_iIdSCMLast(0)
 +{
 +}
 +
 +CDefaultContextMenu::~CDefaultContextMenu()
 +{
 +    /* Free dynamic shell extension entries */
 +    PDynamicShellEntry pDynamicEntry = m_pDynamicEntries, pNextDynamic;
 +    while (pDynamicEntry)
 +    {
 +        pNextDynamic = pDynamicEntry->pNext;
 +        pDynamicEntry->pCM->Release();
 +        HeapFree(GetProcessHeap(), 0, pDynamicEntry);
 +        pDynamicEntry = pNextDynamic;
 +    }
 +
 +    /* Free static shell extension entries */
 +    PStaticShellEntry pStaticEntry = m_pStaticEntries, pNextStatic;
 +    while (pStaticEntry)
 +    {
 +        pNextStatic = pStaticEntry->pNext;
 +        HeapFree(GetProcessHeap(), 0, pStaticEntry->szClass);
 +        HeapFree(GetProcessHeap(), 0, pStaticEntry->szVerb);
 +        HeapFree(GetProcessHeap(), 0, pStaticEntry);
 +        pStaticEntry = pNextStatic;
 +    }
 +
 +    if (m_pidlFolder)
 +        CoTaskMemFree(m_pidlFolder);
 +    _ILFreeaPidl(const_cast<PITEMID_CHILD *>(m_apidl), m_cidl);
 +}
 +
 +HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm)
 +{
 +    CComPtr<IDataObject> pDataObj;
 +
 +    TRACE("cidl %u\n", pdcm->cidl);
 +
 +    m_cidl = pdcm->cidl;
 +    m_apidl = const_cast<PCUITEMID_CHILD_ARRAY>(_ILCopyaPidl(pdcm->apidl, m_cidl));
 +    if (m_cidl && !m_apidl)
 +        return E_OUTOFMEMORY;
 +    m_psf = pdcm->psf;
 +
 +    if (SUCCEEDED(SHCreateDataObject(pdcm->pidlFolder, pdcm->cidl, pdcm->apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
 +        m_pDataObj = pDataObj;
 +
 +    if (pdcm->pidlFolder)
 +    {
 +        m_pidlFolder = ILClone(pdcm->pidlFolder);
 +    }
 +    else
 +    {
 +        CComPtr<IPersistFolder2> pf = NULL;
 +        if (SUCCEEDED(m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf))))
 +        {
 +            if (FAILED(pf->GetCurFolder(reinterpret_cast<LPITEMIDLIST*>(&m_pidlFolder))))
 +                ERR("GetCurFolder failed\n");
 +        }
 +        TRACE("pidlFolder %p\n", m_pidlFolder);
 +    }
 +
 +    return S_OK;
 +}
 +
 +void
 +CDefaultContextMenu::AddStaticEntry(const WCHAR *szVerb, const WCHAR *szClass)
 +{
 +    PStaticShellEntry pEntry = m_pStaticEntries, pLastEntry = NULL;
 +    while(pEntry)
 +    {
 +        if (!wcsicmp(pEntry->szVerb, szVerb))
 +        {
 +            /* entry already exists */
 +            return;
 +        }
 +        pLastEntry = pEntry;
 +        pEntry = pEntry->pNext;
 +    }
 +
 +    TRACE("adding verb %s szClass %s\n", debugstr_w(szVerb), debugstr_w(szClass));
 +
 +    pEntry = (StaticShellEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(StaticShellEntry));
 +    if (pEntry)
 +    {
 +        pEntry->pNext = NULL;
 +        pEntry->szVerb = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(szVerb) + 1) * sizeof(WCHAR));
 +        if (pEntry->szVerb)
 +            wcscpy(pEntry->szVerb, szVerb);
 +        pEntry->szClass = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(szClass) + 1) * sizeof(WCHAR));
 +        if (pEntry->szClass)
 +            wcscpy(pEntry->szClass, szClass);
 +    }
 +
 +    if (!wcsicmp(szVerb, L"open"))
 +    {
 +        /* open verb is always inserted in front */
 +        pEntry->pNext = m_pStaticEntries;
 +        m_pStaticEntries = pEntry;
 +    }
 +    else if (pLastEntry)
 +        pLastEntry->pNext = pEntry;
 +    else
 +        m_pStaticEntries = pEntry;
 +}
 +
 +void
 +CDefaultContextMenu::AddStaticEntryForKey(HKEY hKey, const WCHAR *pwszClass)
 +{
 +    WCHAR wszName[40];
 +    DWORD cchName, dwIndex = 0;
 +
 +    TRACE("AddStaticEntryForKey %x %ls\n", hKey, pwszClass);
 +
 +    while(TRUE)
 +    {
 +        cchName = _countof(wszName);
 +        if (RegEnumKeyExW(hKey, dwIndex++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
 +            break;
 +
 +        AddStaticEntry(wszName, pwszClass);
 +    }
 +}
 +
 +void
 +CDefaultContextMenu::AddStaticEntryForFileClass(const WCHAR * szExt)
 +{
 +    WCHAR szBuffer[100];
 +    HKEY hKey;
 +    LONG result;
 +    DWORD dwBuffer;
 +    UINT Length;
 +    static WCHAR szShell[] = L"\\shell";
 +    static WCHAR szShellAssoc[] = L"SystemFileAssociations\\";
 +
 +    TRACE("AddStaticEntryForFileClass entered with %s\n", debugstr_w(szExt));
 +
 +    Length = wcslen(szExt);
 +    if (Length + (sizeof(szShell) / sizeof(WCHAR)) + 1 < sizeof(szBuffer) / sizeof(WCHAR))
 +    {
 +        wcscpy(szBuffer, szExt);
 +        wcscpy(&szBuffer[Length], szShell);
 +        result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
 +        if (result == ERROR_SUCCESS)
 +        {
 +            szBuffer[Length] = 0;
 +            AddStaticEntryForKey(hKey, szExt);
 +            RegCloseKey(hKey);
 +        }
 +    }
 +
 +    dwBuffer = sizeof(szBuffer);
 +    result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, NULL, RRF_RT_REG_SZ, NULL, (LPBYTE)szBuffer, &dwBuffer);
 +    if (result == ERROR_SUCCESS)
 +    {
 +        Length = wcslen(szBuffer);
 +        if (Length + (sizeof(szShell) / sizeof(WCHAR)) + 1 < sizeof(szBuffer) / sizeof(WCHAR))
 +        {
 +            wcscpy(&szBuffer[Length], szShell);
 +            TRACE("szBuffer %s\n", debugstr_w(szBuffer));
 +
 +            result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
 +            if (result == ERROR_SUCCESS)
 +            {
 +                szBuffer[Length] = 0;
 +                AddStaticEntryForKey(hKey, szBuffer);
 +                RegCloseKey(hKey);
 +            }
 +        }
 +    }
 +
 +    wcscpy(szBuffer, szShellAssoc);
 +    dwBuffer = sizeof(szBuffer) - sizeof(szShellAssoc) - sizeof(WCHAR);
 +    result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, L"PerceivedType", RRF_RT_REG_SZ, NULL, (LPBYTE)&szBuffer[_countof(szShellAssoc) - 1], &dwBuffer);
 +    if (result == ERROR_SUCCESS)
 +    {
 +        Length = wcslen(&szBuffer[_countof(szShellAssoc)]) + _countof(szShellAssoc);
 +        wcscat(szBuffer, L"\\shell");
 +        TRACE("szBuffer %s\n", debugstr_w(szBuffer));
 +
 +        result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
 +        if (result == ERROR_SUCCESS)
 +        {
 +            szBuffer[Length] = 0;
 +            AddStaticEntryForKey(hKey, szBuffer);
 +            RegCloseKey(hKey);
 +        }
 +    }
 +}
 +
 +static
 +BOOL
 +HasClipboardData()
 +{
 +    BOOL bRet = FALSE;
 +    CComPtr<IDataObject> pDataObj;
 +
 +    if(SUCCEEDED(OleGetClipboard(&pDataObj)))
 +    {
 +        STGMEDIUM medium;
 +        FORMATETC formatetc;
 +
 +        TRACE("pDataObj=%p\n", pDataObj.p);
 +
 +        /* Set the FORMATETC structure*/
 +        InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
 +        if(SUCCEEDED(pDataObj->GetData(&formatetc, &medium)))
 +        {
 +            bRet = TRUE;
 +            ReleaseStgMedium(&medium);
 +        }
 +    }
 +
 +    return bRet;
 +}
 +
 +static
 +VOID
 +DisablePasteOptions(HMENU hMenu)
 +{
 +    MENUITEMINFOW mii;
 +
 +    mii.cbSize = sizeof(mii);
 +    mii.fMask = MIIM_STATE;
 +    mii.fState = MFS_DISABLED;
 +
 +    TRACE("result %d\n", SetMenuItemInfoW(hMenu, FCIDM_SHVIEW_INSERT, FALSE, &mii));
 +    TRACE("result %d\n", SetMenuItemInfoW(hMenu, FCIDM_SHVIEW_INSERTLINK, FALSE, &mii));
 +}
 +
 +BOOL
 +CDefaultContextMenu::IsShellExtensionAlreadyLoaded(const CLSID *pclsid)
 +{
 +    PDynamicShellEntry pEntry = m_pDynamicEntries;
 +
 +    while (pEntry)
 +    {
 +        if (!memcmp(&pEntry->ClassID, pclsid, sizeof(CLSID)))
 +            return TRUE;
 +        pEntry = pEntry->pNext;
 +    }
 +
 +    return FALSE;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::LoadDynamicContextMenuHandler(HKEY hKey, const CLSID *pclsid)
 +{
 +    HRESULT hr;
 +
 +    TRACE("LoadDynamicContextMenuHandler entered with This %p hKey %p pclsid %s\n", this, hKey, wine_dbgstr_guid(pclsid));
 +
 +    if (IsShellExtensionAlreadyLoaded(pclsid))
 +        return S_OK;
 +
 +    CComPtr<IContextMenu> pcm;
 +    hr = SHCoCreateInstance(NULL, pclsid, NULL, IID_PPV_ARG(IContextMenu, &pcm));
 +    if (hr != S_OK)
 +    {
 +        ERR("SHCoCreateInstance failed %x\n", GetLastError());
 +        return hr;
 +    }
 +
 +    CComPtr<IShellExtInit> pExtInit;
 +    hr = pcm->QueryInterface(IID_PPV_ARG(IShellExtInit, &pExtInit));
 +    if (hr != S_OK)
 +    {
 +        ERR("Failed to query for interface IID_IShellExtInit hr %x pclsid %s\n", hr, wine_dbgstr_guid(pclsid));
 +        return hr;
 +    }
 +
 +    hr = pExtInit->Initialize(m_pidlFolder, m_pDataObj, hKey);
 +    if (hr != S_OK)
 +    {
 +        TRACE("Failed to initialize shell extension error %x pclsid %s\n", hr, wine_dbgstr_guid(pclsid));
 +        return hr;
 +    }
 +
 +    PDynamicShellEntry pEntry = (DynamicShellEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(DynamicShellEntry));
 +    if (!pEntry)
 +    {
 +        return E_OUTOFMEMORY;
 +    }
 +
 +    pEntry->iIdCmdFirst = 0;
 +    pEntry->pNext = NULL;
 +    pEntry->NumIds = 0;
 +    pEntry->pCM = pcm.Detach();
 +    memcpy(&pEntry->ClassID, pclsid, sizeof(CLSID));
 +
 +    if (m_pDynamicEntries)
 +    {
 +        PDynamicShellEntry pLastEntry = m_pDynamicEntries;
 +
 +        while (pLastEntry->pNext)
 +            pLastEntry = pLastEntry->pNext;
 +
 +        pLastEntry->pNext = pEntry;
 +    }
 +    else
 +        m_pDynamicEntries = pEntry;
 +
 +    return S_OK;
 +}
 +
 +BOOL
 +CDefaultContextMenu::EnumerateDynamicContextHandlerForKey(HKEY hRootKey)
 +{
 +
 +    WCHAR wszName[MAX_PATH], wszBuf[MAX_PATH], *pwszClsid;
 +    DWORD cchName;
 +    HRESULT hr;
 +    HKEY hKey;
 +
 +    if (RegOpenKeyExW(hRootKey, L"shellex\\ContextMenuHandlers", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
 +    {
 +        TRACE("RegOpenKeyExW failed\n");
 +        return FALSE;
 +    }
 +
 +    DWORD dwIndex = 0;
 +    while (TRUE)
 +    {
 +        cchName = _countof(wszName);
 +        if (RegEnumKeyExW(hKey, dwIndex++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
 +            break;
 +
 +        /* Key name or key value is CLSID */
 +        CLSID clsid;
 +        hr = CLSIDFromString(wszName, &clsid);
 +        if (hr == S_OK)
 +            pwszClsid = wszName;
 +        else
 +        {
 +            DWORD cchBuf = _countof(wszBuf);
 +            if (RegGetValueW(hKey, wszName, NULL, RRF_RT_REG_SZ, NULL, wszBuf, &cchBuf) == ERROR_SUCCESS)
 +                hr = CLSIDFromString(wszBuf, &clsid);
 +            pwszClsid = wszBuf;
 +        }
 +        if (SUCCEEDED(hr))
 +        {
 +            if (m_bGroupPolicyActive)
 +            {
 +                if (RegGetValueW(HKEY_LOCAL_MACHINE,
 +                                L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
 +                                pwszClsid,
 +                                RRF_RT_REG_SZ,
 +                                NULL,
 +                                NULL,
 +                                NULL) == ERROR_SUCCESS)
 +                {
 +                    LoadDynamicContextMenuHandler(hKey, &clsid);
 +                }
 +            }
 +            else
 +                LoadDynamicContextMenuHandler(hKey, &clsid);
 +        }
 +    }
 +
 +    RegCloseKey(hKey);
 +    return TRUE;
 +}
 +
 +UINT
 +CDefaultContextMenu::InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, UINT IndexMenu, UINT idCmdFirst, UINT idCmdLast)
 +{
 +    if (!m_pDynamicEntries)
 +    {
 +        m_iIdSHEFirst = 0;
 +        m_iIdSHELast = 0;
 +        return IndexMenu;
 +    }
 +
 +    PDynamicShellEntry pEntry = m_pDynamicEntries;
 +    idCmdFirst = 0x5000;
 +    idCmdLast =  0x6000;
 +    m_iIdSHEFirst = idCmdFirst;
 +    do
 +    {
 +        HRESULT hr = pEntry->pCM->QueryContextMenu(hMenu, IndexMenu++, idCmdFirst, idCmdLast, CMF_NORMAL);
 +        if (SUCCEEDED(hr))
 +        {
 +            pEntry->iIdCmdFirst = idCmdFirst;
 +            pEntry->NumIds = LOWORD(hr);
 +            IndexMenu += pEntry->NumIds;
 +            idCmdFirst += pEntry->NumIds + 0x10;
 +        }
 +        TRACE("pEntry %p hr %x contextmenu %p cmdfirst %x num ids %x\n", pEntry, hr, pEntry->pCM, pEntry->iIdCmdFirst, pEntry->NumIds);
 +        pEntry = pEntry->pNext;
 +    } while (pEntry);
 +
 +    m_iIdSHELast = idCmdFirst;
 +    TRACE("SH_LoadContextMenuHandlers first %x last %x\n", m_iIdSHEFirst, m_iIdSHELast);
 +    return IndexMenu;
 +}
 +
 +UINT
 +CDefaultContextMenu::BuildBackgroundContextMenu(
 +    HMENU hMenu,
 +    UINT iIdCmdFirst,
 +    UINT iIdCmdLast,
 +    UINT uFlags)
 +{
 +    UINT IndexMenu = 0;
 +    HMENU hSubMenu;
 +
 +    TRACE("BuildBackgroundContextMenu entered\n");
 +
 +    if (!_ILIsDesktop(m_pidlFolder))
 +    {
 +        WCHAR wszBuf[MAX_PATH];
 +
 +        /* view option is only available in browsing mode */
 +        hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_001");
 +        if (hSubMenu && LoadStringW(shell32_hInstance, FCIDM_SHVIEW_VIEW, wszBuf, _countof(wszBuf)))
 +        {
 +            TRACE("wszBuf %s\n", debugstr_w(wszBuf));
 +
 +            MENUITEMINFOW mii;
 +            ZeroMemory(&mii, sizeof(mii));
 +            mii.cbSize = sizeof(mii);
 +            mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_ID;
 +            mii.fType = MFT_STRING;
 +            mii.wID = iIdCmdFirst++;
 +            mii.dwTypeData = wszBuf;
 +            mii.cch = wcslen(mii.dwTypeData);
 +            mii.fState = MFS_ENABLED;
 +            mii.hSubMenu = hSubMenu;
 +            InsertMenuItemW(hMenu, IndexMenu++, TRUE, &mii);
 +            DestroyMenu(hSubMenu);
 +        }
 +    }
 +
 +    hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_002");
 +    if (hSubMenu)
 +    {
 +        /* merge general background context menu in */
 +        iIdCmdFirst = Shell_MergeMenus(hMenu, GetSubMenu(hSubMenu, 0), IndexMenu, 0, 0xFFFF, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS) + 1;
 +        DestroyMenu(hSubMenu);
 +    }
 +
 +    if (!HasClipboardData())
 +    {
 +        TRACE("disabling paste options\n");
 +        DisablePasteOptions(hMenu);
 +    }
 +
 +    /* Directory is progid of filesystem folders only */
 +    LPITEMIDLIST pidlFolderLast = ILFindLastID(m_pidlFolder);
 +    if (_ILIsDesktop(pidlFolderLast) || _ILIsDrive(pidlFolderLast) || _ILIsFolder(pidlFolderLast))
 +    {
 +        /* Load context menu handlers */
 +        TRACE("Add background handlers: %p\n", m_pidlFolder);
 +        HKEY hKey;
 +        if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Directory\\Background", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +        {
 +            EnumerateDynamicContextHandlerForKey(hKey);
 +            RegCloseKey(hKey);
 +        }
 +
 +        if (InsertMenuItemsOfDynamicContextMenuExtension(hMenu, GetMenuItemCount(hMenu) - 1, iIdCmdFirst, iIdCmdLast))
 +        {
 +            /* seperate dynamic context menu items */
 +            _InsertMenuItemW(hMenu, GetMenuItemCount(hMenu) - 1, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
 +        }
 +    }
 +
 +    return iIdCmdLast;
 +}
 +
 +UINT
 +CDefaultContextMenu::AddStaticContextMenusToMenu(
 +    HMENU hMenu,
 +    UINT IndexMenu)
 +{
 +    MENUITEMINFOW mii;
 +    UINT idResource;
 +    WCHAR wszVerb[40];
 +    UINT fState;
 +
 +    mii.cbSize = sizeof(mii);
 +    mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
 +    mii.fType = MFT_STRING;
 +    mii.wID = 0x4000;
 +    mii.dwTypeData = NULL;
 +    m_iIdSCMFirst = mii.wID;
 +
 +    PStaticShellEntry pEntry = m_pStaticEntries;
 +
 +    while (pEntry)
 +    {
 +        fState = MFS_ENABLED;
 +        mii.dwTypeData = NULL;
 +
 +        /* set first entry as default */
 +        if (pEntry == m_pStaticEntries)
 +            fState |= MFS_DEFAULT;
 +
 +        if (!wcsicmp(pEntry->szVerb, L"open"))
 +        {
 +            /* override default when open verb is found */
 +            fState |= MFS_DEFAULT;
 +            idResource = IDS_OPEN_VERB;
 +        }
 +        else if (!wcsicmp(pEntry->szVerb, L"explore"))
 +            idResource = IDS_EXPLORE_VERB;
 +        else if (!wcsicmp(pEntry->szVerb, L"runas"))
 +            idResource = IDS_RUNAS_VERB;
 +        else if (!wcsicmp(pEntry->szVerb, L"edit"))
 +            idResource = IDS_EDIT_VERB;
 +        else if (!wcsicmp(pEntry->szVerb, L"find"))
 +            idResource = IDS_FIND_VERB;
 +        else if (!wcsicmp(pEntry->szVerb, L"print"))
 +            idResource = IDS_PRINT_VERB;
 +        else if (!wcsicmp(pEntry->szVerb, L"printto"))
 +        {
 +            pEntry = pEntry->pNext;
 +            continue;
 +        }
 +        else
 +            idResource = 0;
 +
 +        /* By default use verb for menu item name */
 +        mii.dwTypeData = pEntry->szVerb;
 +
 +        if (idResource > 0)
 +        {
 +            if (LoadStringW(shell32_hInstance, idResource, wszVerb, _countof(wszVerb)))
 +                mii.dwTypeData = wszVerb; /* use translated verb */
 +            else
 +                ERR("Failed to load string\n");
 +        }
 +        else
 +        {
 +            WCHAR wszKey[256];
 +            HRESULT hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"%s\\shell\\%s", pEntry->szClass, pEntry->szVerb);
 +
 +            if (SUCCEEDED(hr))
 +            {
 +                DWORD cbVerb = sizeof(wszVerb);
 +
 +                if (RegGetValueW(HKEY_CLASSES_ROOT, wszKey, NULL, RRF_RT_REG_SZ, NULL, wszVerb, &cbVerb) == ERROR_SUCCESS)
 +                    mii.dwTypeData = wszVerb; /* use description for the menu entry */
 +            }
 +        }
 +
 +        mii.cch = wcslen(mii.dwTypeData);
 +        mii.fState = fState;
 +        InsertMenuItemW(hMenu, IndexMenu++, TRUE, &mii);
 +
 +        mii.wID++;
 +        pEntry = pEntry->pNext;
 +    }
 +
 +    m_iIdSCMLast = mii.wID - 1;
 +    return IndexMenu;
 +}
 +
 +void WINAPI _InsertMenuItemW(
 +    HMENU hMenu,
 +    UINT indexMenu,
 +    BOOL fByPosition,
 +    UINT wID,
 +    UINT fType,
 +    LPCWSTR dwTypeData,
 +    UINT fState)
 +{
 +    MENUITEMINFOW mii;
 +    WCHAR wszText[100];
 +
 +    ZeroMemory(&mii, sizeof(mii));
 +    mii.cbSize = sizeof(mii);
 +    if (fType == MFT_SEPARATOR)
 +        mii.fMask = MIIM_ID | MIIM_TYPE;
 +    else if (fType == MFT_STRING)
 +    {
 +        mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
 +        if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0)
 +        {
 +            if (LoadStringW(shell32_hInstance, LOWORD((ULONG_PTR)dwTypeData), wszText, _countof(wszText)))
 +                mii.dwTypeData = wszText;
 +            else
 +            {
 +                ERR("failed to load string %p\n", dwTypeData);
 +                return;
 +            }
 +        }
 +        else
 +            mii.dwTypeData = (LPWSTR)dwTypeData;
 +        mii.fState = fState;
 +    }
 +
 +    mii.wID = wID;
 +    mii.fType = fType;
 +    InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
 +}
 +
 +UINT
 +CDefaultContextMenu::BuildShellItemContextMenu(
 +    HMENU hMenu,
 +    UINT iIdCmdFirst,
 +    UINT iIdCmdLast,
 +    UINT uFlags)
 +{
 +    HKEY hKey;
 +    HRESULT hr;
 +
 +    TRACE("BuildShellItemContextMenu entered\n");
 +    ASSERT(m_cidl >= 1);
 +
 +    STRRET strFile;
 +    hr = m_psf->GetDisplayNameOf(m_apidl[0], SHGDN_FORPARSING, &strFile);
 +    if (hr == S_OK)
 +    {
 +        WCHAR wszPath[MAX_PATH];
 +        hr = StrRetToBufW(&strFile, m_apidl[0], wszPath, _countof(wszPath));
 +        if (hr == S_OK)
 +        {
 +            LPCWSTR pwszExt = PathFindExtensionW(wszPath);
 +            if (pwszExt[0])
 +            {
 +                /* enumerate dynamic/static for a given file class */
 +                if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +                {
 +                    /* add static verbs */
 +                    AddStaticEntryForFileClass(pwszExt);
 +
 +                    /* load dynamic extensions from file extension key */
 +                    EnumerateDynamicContextHandlerForKey(hKey);
 +                    RegCloseKey(hKey);
 +                }
 +
 +                WCHAR wszTemp[40];
 +                DWORD dwSize = sizeof(wszTemp);
 +                if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, NULL, RRF_RT_REG_SZ, NULL, wszTemp, &dwSize) == ERROR_SUCCESS)
 +                {
 +                    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszTemp, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +                    {
 +                        /* add static verbs from progid key */
 +                        AddStaticEntryForFileClass(wszTemp);
 +
 +                        /* load dynamic extensions from progid key */
 +                        EnumerateDynamicContextHandlerForKey(hKey);
 +                        RegCloseKey(hKey);
 +                    }
 +                }
 +            }
 +
 +            if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"*", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +            {
 +                /* load default extensions */
 +                EnumerateDynamicContextHandlerForKey(hKey);
 +                RegCloseKey(hKey);
 +            }
 +        }
 +    }
 +    else
 +        ERR("GetDisplayNameOf failed: %x\n", hr);
 +
 +    GUID *pGuid = _ILGetGUIDPointer(m_apidl[0]);
 +    if (pGuid)
 +    {
 +        LPOLESTR pwszCLSID;
 +        WCHAR buffer[60];
 +
 +        wcscpy(buffer, L"CLSID\\");
 +        hr = StringFromCLSID(*pGuid, &pwszCLSID);
 +        if (hr == S_OK)
 +        {
 +            wcscpy(&buffer[6], pwszCLSID);
 +            TRACE("buffer %s\n", debugstr_w(buffer));
 +            if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +            {
 +                EnumerateDynamicContextHandlerForKey(hKey);
 +                AddStaticEntryForFileClass(buffer);
 +                RegCloseKey(hKey);
 +            }
 +            CoTaskMemFree(pwszCLSID);
 +        }
 +    }
 +
 +    if (_ILIsDrive(m_apidl[0]))
 +    {
 +        AddStaticEntryForFileClass(L"Drive");
 +        if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Drive", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +        {
 +            EnumerateDynamicContextHandlerForKey(hKey);
 +            RegCloseKey(hKey);
 +        }
 +
 +    }
 +
 +    /* add static actions */
 +    SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER;
 +    hr = m_psf->GetAttributesOf(m_cidl, m_apidl, &rfg);
 +    if (FAILED(hr))
 +    {
 +        ERR("GetAttributesOf failed: %x\n", hr);
 +        rfg = 0;
 +    }
 +
 +    if (rfg & SFGAO_FOLDER)
 +    {
 +        /* add the default verbs open / explore */
 +        AddStaticEntryForFileClass(L"Folder");
 +        if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Folder", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +        {
 +            EnumerateDynamicContextHandlerForKey(hKey);
 +            RegCloseKey(hKey);
 +        }
 +
 +        /* Directory is only loaded for real filesystem directories */
 +        if (_ILIsFolder(m_apidl[0]))
 +        {
 +            AddStaticEntryForFileClass(L"Directory");
 +            if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Directory", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +            {
 +                EnumerateDynamicContextHandlerForKey(hKey);
 +                RegCloseKey(hKey);
 +            }
 +        }
 +    }
 +
 +    /* AllFilesystemObjects class is loaded only for files and directories */
 +    if (_ILIsFolder(m_apidl[0]) || _ILIsValue(m_apidl[0]))
 +    {
 +        if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"AllFilesystemObjects", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +        {
 +            /* sendto service is registered here */
 +            EnumerateDynamicContextHandlerForKey(hKey);
 +            RegCloseKey(hKey);
 +        }
 +    }
 +
 +    /* add static context menu handlers */
 +    UINT IndexMenu = AddStaticContextMenusToMenu(hMenu, 0);
 +
 +    /* now process dynamic context menu handlers */
 +    BOOL bAddSep = FALSE;
 +    IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, iIdCmdFirst, iIdCmdLast);
 +    TRACE("IndexMenu %d\n", IndexMenu);
 +
 +    if (_ILIsDrive(m_apidl[0]))
 +    {
 +        /* The 'Format' option must be always available,
 +         * thus it is not registered as a static shell extension */
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED);
 +        bAddSep = TRUE;
 +    }
 +
 +    BOOL bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM));
 +    if (rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE) || bClipboardData)
 +    {
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
 +        if (rfg & SFGAO_CANMOVE)
 +            _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, MAKEINTRESOURCEW(IDS_CUT), MFS_ENABLED);
 +        if (rfg & SFGAO_CANCOPY)
 +            _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, MAKEINTRESOURCEW(IDS_COPY), MFS_ENABLED);
 +        if (bClipboardData)
 +            _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_INSERT, MFT_STRING, MAKEINTRESOURCEW(IDS_INSERT), MFS_ENABLED);
 +
 +        bAddSep = TRUE;
 +    }
 +
 +    if (rfg & SFGAO_CANLINK)
 +    {
 +        bAddSep = FALSE;
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_CREATELINK, MFT_STRING, MAKEINTRESOURCEW(IDS_CREATELINK), MFS_ENABLED);
 +    }
 +
 +    if (rfg & SFGAO_CANDELETE)
 +    {
 +        if (bAddSep)
 +        {
 +            bAddSep = FALSE;
 +            _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
 +        }
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_DELETE), MFS_ENABLED);
 +    }
 +
 +    if (rfg & SFGAO_CANRENAME)
 +    {
 +        if (bAddSep)
 +        {
 +            _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
 +        }
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_RENAME), MFS_ENABLED);
 +        bAddSep = TRUE;
 +    }
 +
 +    if (rfg & SFGAO_HASPROPSHEET)
 +    {
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
 +        _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
 +    }
 +
 +    return iIdCmdLast;
 +}
 +
 +HRESULT
 +WINAPI
 +CDefaultContextMenu::QueryContextMenu(
 +    HMENU hMenu,
 +    UINT IndexMenu,
 +    UINT idCmdFirst,
 +    UINT idCmdLast,
 +    UINT uFlags)
 +{
 +    if (m_cidl)
 +        idCmdFirst = BuildShellItemContextMenu(hMenu, idCmdFirst, idCmdLast, uFlags);
 +    else
 +        idCmdFirst = BuildBackgroundContextMenu(hMenu, idCmdFirst, idCmdLast, uFlags);
 +
 +    return S_OK;
 +}
 +
 +static
 +HRESULT
 +NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi, BOOL bRefresh)
 +{
 +    /* Note: CWM_GETISHELLBROWSER returns not referenced object */
 +    LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
 +    if (!lpSB)
 +        return E_FAIL;
 +
 +    CComPtr<IShellView> lpSV;
 +    if (FAILED(lpSB->QueryActiveShellView(&lpSV)))
 +        return E_FAIL;
 +
 +    HWND hwndSV = NULL;
 +    if (SUCCEEDED(lpSV->GetWindow(&hwndSV)))
 +        SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
 +    return S_OK;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoRefresh(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    CComPtr<IPersistFolder2> ppf2 = NULL;
 +    LPITEMIDLIST pidl;
 +    HRESULT hr = m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
 +    if (SUCCEEDED(hr))
 +    {
 +        hr = ppf2->GetCurFolder(&pidl);
 +        if (SUCCEEDED(hr))
 +        {
 +            SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, NULL);
 +            ILFree(pidl);
 +        }
 +    }
 +    return hr;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoPaste(
 +    LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink)
 +{
 +    HRESULT hr;
 +
 +    CComPtr<IDataObject> pda;
 +    hr = OleGetClipboard(&pda);
 +    if (FAILED(hr))
 +        return hr;
 +
 +    CComPtr<IShellFolder> psfDesktop;
 +    CComPtr<IShellFolder> psfTarget = NULL;
 +
 +    hr = SHGetDesktopFolder(&psfDesktop);
 +    if (FAILED(hr))
 +        return hr;
 +
 +    /* Find target folder */
 +    if (m_cidl)
 +    {
 +        hr = m_psf->BindToObject(m_apidl[0], NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
 +    }
 +    else
 +    {
 +        CComPtr<IPersistFolder2> ppf2 = NULL;
 +        LPITEMIDLIST pidl;
 +
 +        /* cidl is zero due to explorer view */
 +        hr = m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
 +        if (SUCCEEDED(hr))
 +        {
 +            hr = ppf2->GetCurFolder(&pidl);
 +            if (SUCCEEDED(hr))
 +            {
 +                if (_ILIsDesktop(pidl))
 +                {
 +                    /* use desktop shellfolder */
 +                    psfTarget = psfDesktop;
 +                }
 +                else
 +                {
 +                    /* retrieve target desktop folder */
 +                    hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
 +                }
 +                TRACE("psfTarget %x %p, Desktop %u\n", hr, psfTarget.p, _ILIsDesktop(pidl));
 +                ILFree(pidl);
 +            }
 +        }
 +    }
 +
 +    if (FAILED(hr))
 +    {
 +        ERR("no IShellFolder\n");
 +        return hr;
 +    }
 +
 +    FORMATETC formatetc2;
 +    STGMEDIUM medium2;
 +    InitFormatEtc(formatetc2, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL);
 +
 +    DWORD dwKey= 0;
 +
 +    if (SUCCEEDED(pda->GetData(&formatetc2, &medium2)))
 +    {
 +        DWORD * pdwFlag = (DWORD*)GlobalLock(medium2.hGlobal);
 +        if (pdwFlag)
 +        {
 +            if (*pdwFlag == DROPEFFECT_COPY)
 +                dwKey = MK_CONTROL;
 +            else
 +                dwKey = MK_SHIFT;
 +        }
 +        else {
 +            ERR("No drop effect obtained");
 +        }
 +        GlobalUnlock(medium2.hGlobal);
 +    }
 +
 +    if (bLink)
 +    {
 +        dwKey = MK_CONTROL|MK_SHIFT;
 +    }
 +
 +    CComPtr<IDropTarget> pdrop;
 +    hr = psfTarget->QueryInterface(IID_PPV_ARG(IDropTarget, &pdrop));
 +    if (FAILED(hr))
 +    {
 +        ERR("Error getting IDropTarget interface\n");
 +        return hr;
 +    }
 +
 +    SHSimulateDrop(pdrop, pda, dwKey, NULL, NULL);
 +
 +    TRACE("CP result %x\n", hr);
 +    return S_OK;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoOpenOrExplore(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    UNIMPLEMENTED;
 +    return E_FAIL;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoCreateLink(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    CComPtr<IDataObject> pDataObj;
 +    CComPtr<IDropTarget> pDT;
 +    HRESULT hr;
 +    CComPtr<IPersistFolder2> ppf2 = NULL;
 +    LPITEMIDLIST pidl;
 +    CComPtr<IShellFolder> psfDesktop;
 +    CComPtr<IShellFolder> psfTarget = NULL;
 +
 +    hr = SHGetDesktopFolder(&psfDesktop);
 +    if (FAILED(hr))
 +        return hr;
 +
 +    if (SUCCEEDED(hr = SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
 +    {
 +        hr = m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
 +        if (SUCCEEDED(hr))
 +        {
 +            hr = ppf2->GetCurFolder(&pidl);
 +            if (SUCCEEDED(hr))
 +            {
 +                if (_ILIsDesktop(pidl))
 +                {
 +                    /* use desktop shellfolder */
 +                    psfTarget = psfDesktop;
 +                }
 +                else
 +                {
 +                    /* retrieve target desktop folder */
 +                    hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
 +                }
 +                TRACE("psfTarget %x %p, Desktop %u\n", hr, psfTarget.p, _ILIsDesktop(pidl));
 +                ILFree(pidl);
 +            }
 +        }
 +
 +    }
 +
 +    if (FAILED(hr))
 +    {
 +        ERR("no IShellFolder\n");
 +        return hr;
 +    }
 +
 +    psfTarget->QueryInterface(IID_PPV_ARG(IDropTarget, &pDT));
 +    if (FAILED(hr))
 +    {
 +        ERR("no IDropTarget Interface\n");
 +        return hr;
 +    }
 +    SHSimulateDrop(pDT, pDataObj, MK_CONTROL|MK_SHIFT, NULL, NULL);
 +
 +    return S_OK;
 +}
 +
 +HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi) {
 +    TRACE("(%p) Deleting\n", this);
 +
-     if (SUCCEEDED(SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
++    CComPtr<IDataObject> pDataObject;
 +
-         SHCreateThread(DoDeleteThreadProc, pDataObj, NULL, NULL);
++    if (SUCCEEDED(SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObject))))
 +    {
++        IStream *s;
++        CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &s);
++        SHCreateThread(DoDeleteThreadProc, s, NULL, NULL);
 +    }
 +    else
 +        return E_FAIL;
 +    return S_OK;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoCopyOrCut(
 +    LPCMINVOKECOMMANDINFO lpcmi,
 +    BOOL bCopy)
 +{
 +    CComPtr<IDataObject> pDataObj;
 +    HRESULT hr;
 +
 +    if (SUCCEEDED(SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
 +    {
 +        if (!bCopy)
 +        {
 +            FORMATETC formatetc;
 +            STGMEDIUM medium;
 +            InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL);
 +            pDataObj->GetData(&formatetc, &medium);
 +            DWORD * pdwFlag = (DWORD*)GlobalLock(medium.hGlobal);
 +            if (pdwFlag)
 +                *pdwFlag = DROPEFFECT_MOVE;
 +            GlobalUnlock(medium.hGlobal);
 +            pDataObj->SetData(&formatetc, &medium, TRUE);
 +        }
 +
 +        hr = OleSetClipboard(pDataObj);
 +        return hr;
 +    }
 +
 +    /* Note: CWM_GETISHELLBROWSER returns not referenced object */
 +    LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
 +    if (!lpSB)
 +    {
 +        ERR("failed to get shellbrowser\n");
 +        return E_FAIL;
 +    }
 +
 +    CComPtr<IShellView> lpSV;
 +    hr = lpSB->QueryActiveShellView(&lpSV);
 +    if (FAILED(hr))
 +    {
 +        ERR("failed to query the active shellview\n");
 +        return hr;
 +    }
 +
 +    hr = lpSV->GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IDataObject, &pDataObj));
 +    if (SUCCEEDED(hr))
 +    {
 +        hr = OleSetClipboard(pDataObj);
 +        if (FAILED(hr))
 +            ERR("OleSetClipboard failed");
 +        pDataObj->Release();
 +    } else
 +        ERR("failed to get item object\n");
 +
 +    return hr;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoRename(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    /* get the active IShellView. Note: CWM_GETISHELLBROWSER returns not referenced object */
 +    LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
 +    if (!lpSB)
 +    {
 +        ERR("CWM_GETISHELLBROWSER failed\n");
 +        return E_FAIL;
 +    }
 +
 +    /* is the treeview focused */
 +    HWND hwnd;
 +    if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwnd)))
 +    {
 +        HTREEITEM hItem = TreeView_GetSelection(hwnd);
 +        if (hItem)
 +            (void)TreeView_EditLabel(hwnd, hItem);
 +    }
 +
 +    CComPtr<IShellView> lpSV;
 +    HRESULT hr = lpSB->QueryActiveShellView(&lpSV);
 +    if (FAILED(hr))
 +    {
 +        ERR("CWM_GETISHELLBROWSER failed\n");
 +        return hr;
 +    }
 +
 +    SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
 +    lpSV->SelectItem(m_apidl[0], selFlags);
 +    return S_OK;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoProperties(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    HRESULT hr = S_OK;
 +    const ITEMIDLIST *pidlParent = m_pidlFolder, *pidlChild;
 +
 +    if (!pidlParent)
 +    {
 +        CComPtr<IPersistFolder2> pf;
 +
 +        /* pidlFolder is optional */
 +        if (SUCCEEDED(m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf))))
 +        {
 +            pf->GetCurFolder((_ITEMIDLIST**)&pidlParent);
 +        }
 +    }
 +
 +    if (m_cidl > 0)
 +        pidlChild = m_apidl[0];
 +    else
 +    {
 +        /* Set pidlChild to last pidl of current folder */
 +        if (pidlParent == m_pidlFolder)
 +            pidlParent = (ITEMIDLIST*)ILClone(pidlParent);
 +
 +        pidlChild = (ITEMIDLIST*)ILClone(ILFindLastID(pidlParent));
 +        ILRemoveLastID((ITEMIDLIST*)pidlParent);
 +    }
 +
 +    if (_ILIsMyComputer(pidlChild))
 +    {
 +        if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL))
 +            hr = E_FAIL;
 +    }
 +    else if (_ILIsDesktop(pidlChild))
 +    {
 +        if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL))
 +            hr = E_FAIL;
 +    }
 +    else if (_ILIsDrive(pidlChild))
 +    {
 +        WCHAR wszBuf[MAX_PATH];
 +        ILGetDisplayName(pidlChild, wszBuf);
 +        if (!SH_ShowDriveProperties(wszBuf, pidlParent, &pidlChild))
 +            hr = E_FAIL;
 +    }
 +    else if (_ILIsNetHood(pidlChild))
 +    {
 +        // FIXME path!
 +        if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe",
 +                                      L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
 +                                      NULL, SW_SHOWDEFAULT))
 +            hr = E_FAIL;
 +    }
 +    else if (_ILIsBitBucket(pidlChild))
 +    {
 +        /* FIXME: detect the drive path of bitbucket if appropiate */
 +        if(!SH_ShowRecycleBinProperties(L'C'))
 +            hr = E_FAIL;
 +    }
 +    else
 +    {
 +        if (m_cidl > 1)
 +            WARN("SHMultiFileProperties is not yet implemented\n");
 +
 +        STRRET strFile;
 +        hr = m_psf->GetDisplayNameOf(pidlChild, SHGDN_FORPARSING, &strFile);
 +        if (SUCCEEDED(hr))
 +        {
 +            WCHAR wszBuf[MAX_PATH];
 +            hr = StrRetToBufW(&strFile, pidlChild, wszBuf, _countof(wszBuf));
 +            if (SUCCEEDED(hr))
 +                hr = SH_ShowPropertiesDialog(wszBuf, pidlParent, &pidlChild);
 +            else
 +                ERR("StrRetToBufW failed\n");
 +        }
 +        else
 +            ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
 +    }
 +
 +    /* Free allocated PIDLs */
 +    if (pidlParent != m_pidlFolder)
 +        ILFree((ITEMIDLIST*)pidlParent);
 +    if (m_cidl < 1 || pidlChild != m_apidl[0])
 +        ILFree((ITEMIDLIST*)pidlChild);
 +
 +    return hr;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoFormat(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    char szDrive[8] = {0};
 +
 +    if (!_ILGetDrive(m_apidl[0], szDrive, sizeof(szDrive)))
 +    {
 +        ERR("pidl is not a drive\n");
 +        return E_FAIL;
 +    }
 +
 +    SHFormatDrive(lpcmi->hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
 +    return S_OK;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoDynamicShellExtensions(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    UINT idCmd = LOWORD(lpcmi->lpVerb);
 +    PDynamicShellEntry pEntry = m_pDynamicEntries;
 +
 +    TRACE("verb %p first %x last %x", lpcmi->lpVerb, m_iIdSHEFirst, m_iIdSHELast);
 +
 +    while(pEntry && idCmd > pEntry->iIdCmdFirst + pEntry->NumIds)
 +        pEntry = pEntry->pNext;
 +
 +    if (!pEntry)
 +        return E_FAIL;
 +
 +    if (idCmd >= pEntry->iIdCmdFirst && idCmd <= pEntry->iIdCmdFirst + pEntry->NumIds)
 +    {
 +        /* invoke the dynamic context menu */
 +        lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd - pEntry->iIdCmdFirst);
 +        return pEntry->pCM->InvokeCommand(lpcmi);
 +    }
 +
 +    return E_FAIL;
 +}
 +
 +DWORD
 +CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry)
 +{
 +    LPSHELLBROWSER lpSB;
 +    HWND hwndTree;
 +    LPCWSTR FlagsName;
 +    WCHAR wszKey[256];
 +    HRESULT hr;
 +    DWORD wFlags;
 +    DWORD cbVerb;
 +
 +    /* Get a pointer to the shell browser */
 +    lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
 +    if (lpSB == NULL)
 +        return 0;
 +
 +    /* See if we are in Explore or Browse mode. If the browser's tree is present, we are in Explore mode.*/
 +    if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree)
 +        FlagsName = L"ExplorerFlags";
 +    else
 +        FlagsName = L"BrowserFlags";
 +
 +    /* Try to get the flag from the verb */
 +    hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"%s\\shell\\%s", pEntry->szClass, pEntry->szVerb);
 +    if (!SUCCEEDED(hr))
 +        return 0;
 +
 +    cbVerb = sizeof(wFlags);
 +    if (RegGetValueW(HKEY_CLASSES_ROOT, wszKey, FlagsName, RRF_RT_REG_DWORD, NULL, &wFlags, &cbVerb) == ERROR_SUCCESS)
 +    {
 +        return wFlags;
 +    }
 +
 +    return 0;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::TryToBrowse(
 +    LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags)
 +{
 +    LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageW(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
 +    HRESULT hr;
 +
 +    if (lpSB == NULL)
 +        return E_FAIL;
 +
 +    hr = lpSB->BrowseObject(ILCombine(m_pidlFolder, pidl), wFlags);
 +
 +    return hr;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry)
 +{
 +    LPITEMIDLIST pidlFull = ILCombine(m_pidlFolder, pidl);
 +    if (pidlFull == NULL)
 +    {
 +        return E_FAIL;
 +    }
 +
 +    WCHAR wszPath[MAX_PATH];
 +    BOOL bHasPath = SHGetPathFromIDListW(pidlFull, wszPath);
 +
 +    WCHAR wszDir[MAX_PATH];
 +    if(bHasPath)
 +    {
 +        wcscpy(wszDir, wszPath);
 +        PathRemoveFileSpec(wszDir);
 +    }
 +    else
 +    {
 +        SHGetPathFromIDListW(m_pidlFolder, wszDir);
 +    }
 +
 +    HKEY hkeyClass;
 +    RegOpenKeyExW(HKEY_CLASSES_ROOT, pEntry->szClass, 0, KEY_READ, &hkeyClass);
 +
 +    SHELLEXECUTEINFOW sei;
 +    ZeroMemory(&sei, sizeof(sei));
 +    sei.cbSize = sizeof(sei);
 +    sei.hwnd = lpcmi->hwnd;
 +    sei.nShow = SW_SHOWNORMAL;
 +    sei.lpVerb = pEntry->szVerb;
 +    sei.lpDirectory = wszDir;
 +    sei.lpIDList = pidlFull;
 +    sei.hkeyClass = hkeyClass;
 +    sei.fMask = SEE_MASK_CLASSKEY | SEE_MASK_IDLIST;
 +    if (bHasPath)
 +    {
 +        sei.lpFile = wszPath;
 +    }
 +
 +    ShellExecuteExW(&sei);
 +
 +    RegCloseKey(hkeyClass);
 +
 +    ILFree(pidlFull);
 +
 +    return S_OK;
 +}
 +
 +HRESULT
 +CDefaultContextMenu::DoStaticShellExtensions(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    PStaticShellEntry pEntry = m_pStaticEntries;
 +    INT iCmd = LOWORD(lpcmi->lpVerb) - m_iIdSCMFirst;
 +    HRESULT hr;
 +    UINT i;
 +
 +    while (pEntry && (iCmd--) > 0)
 +        pEntry = pEntry->pNext;
 +
 +    if (iCmd > 0)
 +        return E_FAIL;
 +
 +    /* Get the browse flags to see if we need to browse */
 +    DWORD wFlags = BrowserFlagsFromVerb(lpcmi, pEntry);
 +    BOOL bBrowsed = FALSE;
 +
 +    for (i=0; i < m_cidl; i++)
 +    {
 +        /* Check if we need to browse */
 +        if (wFlags > 0)
 +        {
 +            /* In xp if we have browsed, we don't open any more folders .
 +             * In win7 we browse to the first folder we find and
 +             * open new windows fo for each of the rest of the folders */
 +            if (bBrowsed)
 +                continue;
 +
 +            hr = TryToBrowse(lpcmi, m_apidl[i], wFlags);
 +            if (SUCCEEDED(hr))
 +            {
 +                bBrowsed = TRUE;
 +                continue;
 +            }
 +        }
 +
 +        InvokePidl(lpcmi, m_apidl[i], pEntry);
 +    }
 +
 +    return S_OK;
 +}
 +
 +HRESULT
 +WINAPI
 +CDefaultContextMenu::InvokeCommand(
 +    LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    switch(LOWORD(lpcmi->lpVerb))
 +    {
 +        case FCIDM_SHVIEW_BIGICON:
 +        case FCIDM_SHVIEW_SMALLICON:
 +        case FCIDM_SHVIEW_LISTVIEW:
 +        case FCIDM_SHVIEW_REPORTVIEW:
 +        case 0x30: /* FIX IDS in resource files */
 +        case 0x31:
 +        case 0x32:
 +        case 0x33:
 +        case FCIDM_SHVIEW_AUTOARRANGE:
 +        case FCIDM_SHVIEW_SNAPTOGRID:
 +            return NotifyShellViewWindow(lpcmi, FALSE);
 +        case FCIDM_SHVIEW_REFRESH:
 +            return DoRefresh(lpcmi);
 +        case FCIDM_SHVIEW_INSERT:
 +            return DoPaste(lpcmi, FALSE);
 +        case FCIDM_SHVIEW_INSERTLINK:
 +            return DoPaste(lpcmi, TRUE);
 +        case FCIDM_SHVIEW_OPEN:
 +        case FCIDM_SHVIEW_EXPLORE:
 +            return DoOpenOrExplore(lpcmi);
 +        case FCIDM_SHVIEW_COPY:
 +        case FCIDM_SHVIEW_CUT:
 +            return DoCopyOrCut(lpcmi, LOWORD(lpcmi->lpVerb) == FCIDM_SHVIEW_COPY);
 +        case FCIDM_SHVIEW_CREATELINK:
 +            return DoCreateLink(lpcmi);
 +        case FCIDM_SHVIEW_DELETE:
 +            return DoDelete(lpcmi);
 +        case FCIDM_SHVIEW_RENAME:
 +            return DoRename(lpcmi);
 +        case FCIDM_SHVIEW_PROPERTIES:
 +            return DoProperties(lpcmi);
 +        case 0x7ABC:
 +            return DoFormat(lpcmi);
 +    }
 +
 +    if (m_iIdSHEFirst && m_iIdSHELast)
 +    {
 +        if (LOWORD(lpcmi->lpVerb) >= m_iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSHELast)
 +            return DoDynamicShellExtensions(lpcmi);
 +    }
 +
 +    if (m_iIdSCMFirst && m_iIdSCMLast)
 +    {
 +        if (LOWORD(lpcmi->lpVerb) >= m_iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSCMLast)
 +            return DoStaticShellExtensions(lpcmi);
 +    }
 +
 +    FIXME("Unhandled Verb %xl\n", LOWORD(lpcmi->lpVerb));
 +    return E_UNEXPECTED;
 +}
 +
 +HRESULT
 +WINAPI
 +CDefaultContextMenu::GetCommandString(
 +    UINT_PTR idCommand,
 +    UINT uFlags,
 +    UINT* lpReserved,
 +    LPSTR lpszName,
 +    UINT uMaxNameLen)
 +{
 +    return S_OK;
 +}
 +
 +HRESULT
 +WINAPI
 +CDefaultContextMenu::HandleMenuMsg(
 +    UINT uMsg,
 +    WPARAM wParam,
 +    LPARAM lParam)
 +{
 +    return S_OK;
 +}
 +
 +static
 +HRESULT
 +IDefaultContextMenu_Constructor(
 +    const DEFCONTEXTMENU *pdcm,
 +    REFIID riid,
 +    void **ppv)
 +{
 +    if (ppv == NULL)
 +        return E_POINTER;
 +    *ppv = NULL;
 +
 +    CComObject<CDefaultContextMenu> *pCM;
 +    HRESULT hr = CComObject<CDefaultContextMenu>::CreateInstance(&pCM);
 +    if (FAILED(hr))
 +        return hr;
 +    pCM->AddRef(); // CreateInstance returns object with 0 ref count */
 +
 +    CComPtr<IUnknown> pResult;
 +    hr = pCM->QueryInterface(riid, (void **)&pResult);
 +    if (FAILED(hr))
 +    {
 +        pCM->Release();
 +        return hr;
 +    }
 +
 +    hr = pCM->Initialize(pdcm);
 +    if (FAILED(hr))
 +    {
 +        pCM->Release();
 +        return hr;
 +    }
 +
 +    *ppv = pResult.Detach();
 +    pCM->Release();
 +    TRACE("This(%p) cidl %u\n", *ppv, pdcm->cidl);
 +    return S_OK;
 +}
 +
 +/*************************************************************************
 + * SHCreateDefaultContextMenu            [SHELL32.325] Vista API
 + *
 + */
 +
 +HRESULT
 +WINAPI
 +SHCreateDefaultContextMenu(
 +    const DEFCONTEXTMENU *pdcm,
 +    REFIID riid,
 +    void **ppv)
 +{
 +    *ppv = NULL;
 +    HRESULT hr = IDefaultContextMenu_Constructor(pdcm, riid, ppv);
 +    if (FAILED(hr))
 +        ERR("IDefaultContextMenu_Constructor failed: %x\n", hr);
 +    TRACE("pcm %p hr %x\n", pdcm, hr);
 +    return hr;
 +}
 +
 +/*************************************************************************
 + * CDefFolderMenu_Create2            [SHELL32.701]
 + *
 + */
 +
 +HRESULT
 +WINAPI
 +CDefFolderMenu_Create2(
 +    LPCITEMIDLIST pidlFolder,
 +    HWND hwnd,
 +    UINT cidl,
 +    LPCITEMIDLIST *apidl,
 +    IShellFolder *psf,
 +    LPFNDFMCALLBACK lpfn,
 +    UINT nKeys,
 +    const HKEY *ahkeyClsKeys,
 +    IContextMenu **ppcm)
 +{
 +    DEFCONTEXTMENU pdcm;
 +    pdcm.hwnd = hwnd;
 +    pdcm.pcmcb = NULL;
 +    pdcm.pidlFolder = pidlFolder;
 +    pdcm.psf = psf;
 +    pdcm.cidl = cidl;
 +    pdcm.apidl = apidl;
 +    pdcm.punkAssociationInfo = NULL;
 +    pdcm.cKeys = nKeys;
 +    pdcm.aKeys = ahkeyClsKeys;
 +
 +    HRESULT hr = SHCreateDefaultContextMenu(&pdcm, IID_PPV_ARG(IContextMenu, ppcm));
 +    return hr;
 +}
 +
index 35cf97f,0000000..b742d99
mode 100644,000000..100644
--- /dev/null
@@@ -1,589 -1,0 +1,589 @@@
-         DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
 +/*
 + *    Virtual Admin Tools Folder
 + *
 + *    Copyright 2008                Johannes Anderwald
 + *    Copyright 2009                Andrew Hill
 + *
 + * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 + */
 +
 +#include <precomp.h>
 +
 +WINE_DEFAULT_DEBUG_CHANNEL (shell);
 +
 +/*
 +This folder should not exist. It is just a file system folder...
 +*/
 +
 +/* List shortcuts of
 + * CSIDL_COMMON_ADMINTOOLS
 + * Note: CSIDL_ADMINTOOLS is ignored, tested with Window XP SP3+
 + */
 +
 +/***********************************************************************
 + *     AdminTools folder implementation
 + */
 +
 +class CDesktopFolderEnumY :
 +    public IEnumIDListImpl
 +{
 +    private:
 +    public:
 +        CDesktopFolderEnumY();
 +        ~CDesktopFolderEnumY();
 +        HRESULT WINAPI Initialize(LPWSTR szTarget, DWORD dwFlags);
 +
 +        BEGIN_COM_MAP(CDesktopFolderEnumY)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +static const shvheader AdminToolsSFHeader[] = {
 +    {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12}
 +};
 +
 +#define COLUMN_NAME                0
 +#define COLUMN_SIZE                1
 +#define COLUMN_TYPE                2
 +#define COLUMN_DATE                3
 +
 +#define AdminToolsHELLVIEWCOLUMNS (4)
 +
 +CDesktopFolderEnumY::CDesktopFolderEnumY()
 +{
 +}
 +
 +CDesktopFolderEnumY::~CDesktopFolderEnumY()
 +{
 +}
 +
 +HRESULT WINAPI CDesktopFolderEnumY::Initialize(LPWSTR szTarget, DWORD dwFlags)
 +{
 +    TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
 +    /* enumerate the elements in %windir%\desktop */
 +    return CreateFolderEnumList(szTarget, dwFlags);
 +}
 +
 +CAdminToolsFolder::CAdminToolsFolder()
 +{
 +    pclsid = NULL;
 +
 +    pidlRoot = NULL;  /* absolute pidl */
 +    szTarget = NULL;
 +
 +    dwAttributes = 0;        /* attributes returned by GetAttributesOf FIXME: use it */
 +}
 +
 +CAdminToolsFolder::~CAdminToolsFolder()
 +{
 +    TRACE ("-- destroying IShellFolder(%p)\n", this);
 +    if (pidlRoot)
 +        SHFree(pidlRoot);
 +    HeapFree(GetProcessHeap(), 0, szTarget);
 +}
 +
 +HRESULT WINAPI CAdminToolsFolder::FinalConstruct()
 +{
 +    szTarget = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
 +    if (szTarget == NULL)
 +        return E_OUTOFMEMORY;
 +    if (!SHGetSpecialFolderPathW(NULL, szTarget, CSIDL_COMMON_ADMINTOOLS, FALSE))
 +        return E_FAIL;
 +
 +    pidlRoot = _ILCreateAdminTools();    /* my qualified pidl */
 +    if (pidlRoot == NULL)
 +        return E_OUTOFMEMORY;
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *    CAdminToolsFolder::ParseDisplayName
 + *
 + */
 +HRESULT WINAPI CAdminToolsFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
- HRESULT WINAPI CAdminToolsFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++        DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
 +{
 +    TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
 +          this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
 +          pchEaten, ppidl, pdwAttributes);
 +
 +    *ppidl = 0;
 +    if (pchEaten)
 +        *pchEaten = 0;
 +
 +    MessageBoxW(NULL, lpszDisplayName, L"ParseDisplayName", MB_OK);
 +
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 + *        CAdminToolsFolder::EnumObjects
 + */
 +HRESULT WINAPI CAdminToolsFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
 +{
 +    CComObject<CDesktopFolderEnumY>        *theEnumerator;
 +    CComPtr<IEnumIDList>                    result;
 +    HRESULT                                 hResult;
 +
 +    TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +    *ppEnumIDList = NULL;
 +    ATLTRY (theEnumerator = new CComObject<CDesktopFolderEnumY>);
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
 +    if (FAILED (hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +    hResult = theEnumerator->Initialize (szTarget, dwFlags);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach ();
 +
 +    TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *        CAdminToolsFolder::BindToObject
 + */
- HRESULT WINAPI CAdminToolsFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++HRESULT WINAPI CAdminToolsFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this,
 +           pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
 +}
 +
 +/**************************************************************************
 + *    CAdminToolsFolder::BindToStorage
 + */
- HRESULT WINAPI CAdminToolsFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++HRESULT WINAPI CAdminToolsFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
 +           this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 + *     CAdminToolsFolder::CompareIDs
 + */
- HRESULT WINAPI CAdminToolsFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl, DWORD *rgfInOut)
++HRESULT WINAPI CAdminToolsFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs (this, lParam, pidl1, pidl2);
 +    TRACE ("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 + *    CAdminToolsFolder::CreateViewObject
 + */
 +HRESULT WINAPI CAdminToolsFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
 +{
 +    CComPtr<IShellView>                    pShellView;
 +    HRESULT                                hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(hwnd=%p,%s,%p)\n", this,
 +           hwndOwner, shdebugstr_guid (&riid), ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IDropTarget))
 +    {
 +        WARN ("IDropTarget not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID (riid, IID_IShellView))
 +    {
 +        hr = IShellView_Constructor ((IShellFolder *)this, &pShellView);
 +        if (pShellView)
 +            hr = pShellView->QueryInterface(riid, ppvOut);
 +    }
 +    TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *  ISF_AdminTools_fnGetAttributesOf
 + */
- HRESULT WINAPI CAdminToolsFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl,
++HRESULT WINAPI CAdminToolsFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
 +{
 +    HRESULT hr = S_OK;
 +    static const DWORD dwAdminToolsAttributes =
 +        SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
 +        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM;
 +
 +    TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
 +           this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
 +
 +    if (!rgfInOut)
 +        return E_INVALIDARG;
 +    if (cidl && !apidl)
 +        return E_INVALIDARG;
 +
 +    if (*rgfInOut == 0)
 +        *rgfInOut = ~0;
 +
 +    if(cidl == 0) {
 +        *rgfInOut &= dwAdminToolsAttributes;
 +    } else {
 +        while (cidl > 0 && *apidl) {
 +            pdump (*apidl);
 +            if (_ILIsAdminTools(*apidl)) {
 +                *rgfInOut &= dwAdminToolsAttributes;
 +            } else {
 +                SHELL32_GetItemAttributes (this, *apidl, rgfInOut);
 +            }
 +            apidl++;
 +            cidl--;
 +        }
 +    }
 +    /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE ("-- result=0x%08x\n", *rgfInOut);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *    CAdminToolsFolder::GetUIObjectOf
 + *
 + * PARAMETERS
 + *  HWND           hwndOwner, //[in ] Parent window for any output
 + *  UINT           cidl,      //[in ] array size
 + *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
 + *  REFIID         riid,      //[in ] Requested Interface
 + *  UINT*          prgfInOut, //[   ] reserved
 + *  LPVOID*        ppvObject) //[out] Resulting Interface
 + *
 + */
- HRESULT WINAPI CAdminToolsFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
++HRESULT WINAPI CAdminToolsFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
 +        REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
 +{
 +    LPITEMIDLIST pidl;
 +    CComPtr<IUnknown>                    pObj;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
 +           this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IContextMenu))
 +    {
 +        IContextMenu  * pCm = NULL;
 +        hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, 0, NULL, &pCm);
 +        pObj = pCm;
 +    }
 +    else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
 +    {
 +        IDataObject * pDo = NULL;
 +        hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, &pDo);
 +        pObj = pDo;
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconA_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconW_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
 +    {
 +        IDropTarget * pDt = NULL;
 +        hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
 +        pObj = pDt;
 +    }
 +    else if ((IsEqualIID(riid, IID_IShellLinkW) ||
 +              IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        hr = IShellLink_ConstructFromFile(NULL, riid, pidl, reinterpret_cast<LPVOID*>(&pObj));
 +        SHFree (pidl);
 +    }
 +    else
 +        hr = E_NOINTERFACE;
 +
 +    if (SUCCEEDED(hr) && !pObj)
 +        hr = E_OUTOFMEMORY;
 +
 +    *ppvOut = pObj.Detach();
 +    TRACE ("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *    CAdminToolsFolder::GetDisplayNameOf
 + *
 + */
- HRESULT WINAPI CAdminToolsFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,    /* simple pidl */
-         LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
++HRESULT WINAPI CAdminToolsFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 +{
 +    HRESULT hr = S_OK;
 +    LPWSTR pszPath, pOffset;
 +
 +    TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump (pidl);
 +
 +    if (!strRet)
 +        return E_INVALIDARG;
 +
 +    pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
 +    if (!pszPath)
 +        return E_OUTOFMEMORY;
 +
 +    ZeroMemory(pszPath, (MAX_PATH + 1) * sizeof(WCHAR));
 +
 +    if (!pidl->mkid.cb)
 +    {
 +        if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
 +                (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING))
 +            wcscpy(pszPath, szTarget);
 +        else if (!HCR_GetClassNameW(CLSID_AdminFolderShortcut, pszPath, MAX_PATH))
 +            hr = E_FAIL;
 +    }
 +    else if (_ILIsPidlSimple(pidl))
 +    {
 +        if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
 +                (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) &&
 +                szTarget)
 +        {
 +            wcscpy(pszPath, szTarget);
 +            pOffset = PathAddBackslashW(pszPath);
 +            if (pOffset)
 +            {
 +                if (!_ILSimpleGetTextW(pidl, pOffset, MAX_PATH + 1 - (pOffset - pszPath)))
 +                    hr = E_FAIL;
 +            }
 +            else
 +                hr = E_FAIL;
 +        }
 +        else
 +        {
 +            if (_ILSimpleGetTextW(pidl, pszPath, MAX_PATH + 1))
 +            {
 +                if (SHELL_FS_HideExtension(pszPath))
 +                    PathRemoveExtensionW(pszPath);
 +            }
 +            else
 +                hr = E_FAIL;
 +        }
 +    }
 +    else if (_ILIsSpecialFolder(pidl))
 +    {
 +        BOOL bSimplePidl = _ILIsPidlSimple(pidl);
 +
 +        if (bSimplePidl)
 +        {
 +            if (!_ILSimpleGetTextW(pidl, pszPath, MAX_PATH))
 +                hr = E_FAIL;
 +        }
 +        else if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl)
 +        {
 +            int len = 0;
 +
 +            wcscpy(pszPath, szTarget);
 +            PathAddBackslashW(pszPath);
 +            len = wcslen(pszPath);
 +
 +            if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags | SHGDN_INFOLDER, pszPath + len, MAX_PATH + 1 - len)))
 +            {
 +                CoTaskMemFree(pszPath);
 +                return E_OUTOFMEMORY;
 +            }
 +
 +        }
 +    }
 +
 +    if (SUCCEEDED(hr))
 +    {
 +        strRet->uType = STRRET_WSTR;
 +        strRet->pOleStr = pszPath;
 +        TRACE ("-- (%p)->(%s,0x%08x)\n", this, debugstr_w(strRet->pOleStr), hr);
 +    }
 +    else
 +        CoTaskMemFree(pszPath);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *  CAdminToolsFolder::SetNameOf
 + *  Changes the name of a file object or subfolder, possibly changing its item
 + *  identifier in the process.
 + *
 + * PARAMETERS
 + *  HWND          hwndOwner,  //[in ] Owner window for output
 + *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
 + *  LPCOLESTR     lpszName,   //[in ] the items new display name
 + *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
 + *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
 + */
- HRESULT WINAPI CAdminToolsFolder::GetDetailsEx (LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
++HRESULT WINAPI CAdminToolsFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,    /* simple pidl */
++        LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
 +{
 +    FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner, pidl,
 +           debugstr_w (lpName), dwFlags, pPidlOut);
 +
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CAdminToolsFolder::GetDefaultSearchGUID(GUID *pguid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CAdminToolsFolder::EnumSearches(IEnumExtraSearch ** ppenum)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CAdminToolsFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
 +{
 +    if (pSort)
 +        *pSort = 0;
 +    if (pDisplay)
 +        *pDisplay = 0;
 +
 +    return S_OK;
 +}
 +HRESULT WINAPI CAdminToolsFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
 +{
 +    if (!pcsFlags || iColumn >= AdminToolsHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +    *pcsFlags = AdminToolsSFHeader[iColumn].pcsFlags;
 +    return S_OK;
 +
 +}
 +
- HRESULT WINAPI CAdminToolsFolder::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
++HRESULT WINAPI CAdminToolsFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
 +{
 +    FIXME ("(%p): stub\n", this);
 +
 +    return E_NOTIMPL;
 +}
 +
++HRESULT WINAPI CAdminToolsFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
 +{
 +    WCHAR buffer[MAX_PATH] = {0};
 +    HRESULT hr = E_FAIL;
 +
 +    TRACE("(%p)->(%p %i %p): stub\n", this, pidl, iColumn, psd);
 +
 +    if (iColumn >= AdminToolsHELLVIEWCOLUMNS)
 +        return E_FAIL;
 +
 +    psd->fmt = AdminToolsSFHeader[iColumn].fmt;
 +    psd->cxChar = AdminToolsSFHeader[iColumn].cxChar;
 +    if (pidl == NULL)
 +    {
 +        psd->str.uType = STRRET_WSTR;
 +        if (LoadStringW(shell32_hInstance, AdminToolsSFHeader[iColumn].colnameid, buffer, MAX_PATH))
 +            hr = SHStrDupW(buffer, &psd->str.pOleStr);
 +
 +        return hr;
 +    }
 +
 +    psd->str.uType = STRRET_CSTR;
 +    switch (iColumn)
 +    {
 +        case COLUMN_NAME:
 +            psd->str.uType = STRRET_WSTR;
 +            hr = GetDisplayNameOf(pidl,
 +                                  SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
 +            break;
 +        case COLUMN_SIZE:
 +            _ILGetFileSize (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +        case COLUMN_TYPE:
 +            _ILGetFileType (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +        case COLUMN_DATE:
 +            _ILGetFileDate (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +    }
 +
 +    return hr;
 +}
 +
 +HRESULT WINAPI CAdminToolsFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
 +{
 +    FIXME ("(%p): stub\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +/************************************************************************
 + *    CAdminToolsFolder::GetClassID
 + */
 +HRESULT WINAPI CAdminToolsFolder::GetClassID(CLSID *lpClassId)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    memcpy(lpClassId, &CLSID_AdminFolderShortcut, sizeof(CLSID));
 +
 +    return S_OK;
 +}
 +
 +/************************************************************************
 + *    CAdminToolsFolder::Initialize
 + *
 + */
 +HRESULT WINAPI CAdminToolsFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    if (pidlRoot)
 +        SHFree((LPVOID)pidlRoot);
 +
 +    pidlRoot = ILClone(pidl);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *    CAdminToolsFolder::GetCurFolder
 + */
 +HRESULT WINAPI CAdminToolsFolder::GetCurFolder(LPITEMIDLIST *pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    *pidl = ILClone (pidlRoot);
 +    return S_OK;
 +}
index 306786a,0000000..01aaf99
mode 100644,000000..100644
--- /dev/null
@@@ -1,1072 -1,0 +1,1072 @@@
-     LPITEMIDLIST *ppidl,
 +/*
 + * Control panel folder
 + *
 + * Copyright 2003 Martin Fuchs
 + * Copyright 2009 Andrew Hill
 + *
 + * 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
 + */
 +
 +/*
 +TODO:
 +1. The selected items list should not be stored in CControlPanelFolder, it should
 +    be a result returned by an internal method.
 +*/
 +
 +#include <precomp.h>
 +
 +WINE_DEFAULT_DEBUG_CHANNEL(shell);
 +
 +/***********************************************************************
 +*   control panel implementation in shell namespace
 +*/
 +
 +class CControlPanelEnum :
 +    public IEnumIDListImpl
 +{
 +    public:
 +        CControlPanelEnum();
 +        ~CControlPanelEnum();
 +        HRESULT WINAPI Initialize(DWORD dwFlags);
 +        BOOL RegisterCPanelApp(LPCSTR path);
 +        int RegisterRegistryCPanelApps(HKEY hkey_root, LPCSTR szRepPath);
 +        int RegisterCPanelFolders(HKEY hkey_root, LPCSTR szRepPath);
 +        BOOL CreateCPanelEnumList(DWORD dwFlags);
 +
 +        BEGIN_COM_MAP(CControlPanelEnum)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +/***********************************************************************
 +*   IShellFolder [ControlPanel] implementation
 +*/
 +
 +static const shvheader ControlPanelSFHeader[] = {
 +    {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},/*FIXME*/
 +    {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 200},/*FIXME*/
 +};
 +
 +#define CONROLPANELSHELLVIEWCOLUMNS 2
 +
 +CControlPanelEnum::CControlPanelEnum()
 +{
 +}
 +
 +CControlPanelEnum::~CControlPanelEnum()
 +{
 +}
 +
 +HRESULT WINAPI CControlPanelEnum::Initialize(DWORD dwFlags)
 +{
 +    if (CreateCPanelEnumList(dwFlags) == FALSE)
 +        return E_FAIL;
 +    return S_OK;
 +}
 +
 +static LPITEMIDLIST _ILCreateCPanelApplet(LPCSTR pszName, LPCSTR pszDisplayName, LPCSTR pszComment, int iIconIdx)
 +{
 +    PIDLCPanelStruct *pCP;
 +    LPITEMIDLIST pidl;
 +    LPPIDLDATA pData;
 +    int cchName, cchDisplayName, cchComment, cbData;
 +
 +    /* Calculate lengths of given strings */
 +    cchName = strlen(pszName);
 +    cchDisplayName = strlen(pszDisplayName);
 +    cchComment = strlen(pszComment);
 +
 +    /* Allocate PIDL */
 +    cbData = sizeof(pidl->mkid.cb) + sizeof(pData->type) + sizeof(pData->u.cpanel) - sizeof(pData->u.cpanel.szName)
 +             + cchName + cchDisplayName + cchComment + 3;
 +    pidl = (LPITEMIDLIST)SHAlloc(cbData + sizeof(WORD));
 +    if (!pidl)
 +        return NULL;
 +
 +    /* Copy data to allocated memory */
 +    pidl->mkid.cb = cbData;
 +    pData = (PIDLDATA *)pidl->mkid.abID;
 +    pData->type = PT_CPLAPPLET;
 +
 +    pCP = &pData->u.cpanel;
 +    pCP->dummy = 0;
 +    pCP->iconIdx = iIconIdx;
 +    strcpy(pCP->szName, pszName);
 +    pCP->offsDispName = cchName + 1;
 +    strcpy(pCP->szName + pCP->offsDispName, pszDisplayName);
 +    pCP->offsComment = pCP->offsDispName + cchDisplayName + 1;
 +    strcpy(pCP->szName + pCP->offsComment, pszComment);
 +
 +    /* Add PIDL NULL terminator */
 +    *(WORD*)(pCP->szName + pCP->offsComment + cchComment + 1) = 0;
 +
 +    pcheck(pidl);
 +
 +    return pidl;
 +}
 +
 +/**************************************************************************
 + *  _ILGetCPanelPointer()
 + * gets a pointer to the control panel struct stored in the pidl
 + */
 +static PIDLCPanelStruct *_ILGetCPanelPointer(LPCITEMIDLIST pidl)
 +{
 +    LPPIDLDATA pdata = _ILGetDataPointer(pidl);
 +
 +    if (pdata && pdata->type == PT_CPLAPPLET)
 +        return (PIDLCPanelStruct *) & (pdata->u.cpanel);
 +
 +    return NULL;
 +}
 +
 +BOOL CControlPanelEnum::RegisterCPanelApp(LPCSTR path)
 +{
 +    LPITEMIDLIST pidl;
 +    CPlApplet* applet;
 +    CPanel panel;
 +    CPLINFO info;
 +    unsigned i;
 +    int iconIdx;
 +
 +    char displayName[MAX_PATH];
 +    char comment[MAX_PATH];
 +
 +    WCHAR wpath[MAX_PATH];
 +
 +    MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH);
 +
 +    panel.first = NULL;
 +    applet = Control_LoadApplet(0, wpath, &panel);
 +
 +    if (applet)
 +    {
 +        for (i = 0; i < applet->count; ++i)
 +        {
 +            WideCharToMultiByte(CP_ACP, 0, applet->info[i].szName, -1, displayName, MAX_PATH, 0, 0);
 +            WideCharToMultiByte(CP_ACP, 0, applet->info[i].szInfo, -1, comment, MAX_PATH, 0, 0);
 +
 +            applet->proc(0, CPL_INQUIRE, i, (LPARAM)&info);
 +
 +            if (info.idIcon > 0)
 +                iconIdx = -info.idIcon; /* negative icon index instead of icon number */
 +            else
 +                iconIdx = 0;
 +
 +            pidl = _ILCreateCPanelApplet(path, displayName, comment, iconIdx);
 +
 +            if (pidl)
 +                AddToEnumList(pidl);
 +        }
 +        Control_UnloadApplet(applet);
 +    }
 +    return TRUE;
 +}
 +
 +int CControlPanelEnum::RegisterRegistryCPanelApps(HKEY hkey_root, LPCSTR szRepPath)
 +{
 +    char name[MAX_PATH];
 +    char value[MAX_PATH];
 +    HKEY hkey;
 +
 +    int cnt = 0;
 +
 +    if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
 +    {
 +        int idx = 0;
 +
 +        for(; ; idx++)
 +        {
 +            DWORD nameLen = MAX_PATH;
 +            DWORD valueLen = MAX_PATH;
 +
 +            if (RegEnumValueA(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS)
 +                break;
 +
 +            if (RegisterCPanelApp(value))
 +                ++cnt;
 +        }
 +        RegCloseKey(hkey);
 +    }
 +
 +    return cnt;
 +}
 +
 +int CControlPanelEnum::RegisterCPanelFolders(HKEY hkey_root, LPCSTR szRepPath)
 +{
 +    char name[MAX_PATH];
 +    HKEY hkey;
 +
 +    int cnt = 0;
 +
 +    if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
 +    {
 +        int idx = 0;
 +        for (; ; idx++)
 +        {
 +            if (RegEnumKeyA(hkey, idx, name, MAX_PATH) != ERROR_SUCCESS)
 +                break;
 +
 +            if (*name == '{')
 +            {
 +                LPITEMIDLIST pidl = _ILCreateGuidFromStrA(name);
 +
 +                if (pidl && AddToEnumList(pidl))
 +                    ++cnt;
 +            }
 +        }
 +
 +        RegCloseKey(hkey);
 +    }
 +
 +    return cnt;
 +}
 +
 +/**************************************************************************
 + *  CControlPanelEnum::CreateCPanelEnumList()
 + */
 +BOOL CControlPanelEnum::CreateCPanelEnumList(DWORD dwFlags)
 +{
 +    CHAR szPath[MAX_PATH];
 +    WIN32_FIND_DATAA wfd;
 +    HANDLE hFile;
 +
 +    TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
 +
 +    /* enumerate control panel folders */
 +    if (dwFlags & SHCONTF_FOLDERS)
 +        RegisterCPanelFolders(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
 +
 +    /* enumerate the control panel applets */
 +    if (dwFlags & SHCONTF_NONFOLDERS)
 +    {
 +        LPSTR p;
 +
 +        GetSystemDirectoryA(szPath, MAX_PATH);
 +        p = PathAddBackslashA(szPath);
 +        strcpy(p, "*.cpl");
 +
 +        TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n", this, debugstr_a(szPath));
 +        hFile = FindFirstFileA(szPath, &wfd);
 +
 +        if (hFile != INVALID_HANDLE_VALUE)
 +        {
 +            do
 +            {
 +                if (!(dwFlags & SHCONTF_INCLUDEHIDDEN) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
 +                    continue;
 +
 +                if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
 +                    strcpy(p, wfd.cFileName);
 +                    if (strcmp(wfd.cFileName, "ncpa.cpl"))
 +                        RegisterCPanelApp(szPath);
 +                }
 +            } while(FindNextFileA(hFile, &wfd));
 +            FindClose(hFile);
 +        }
 +
 +        RegisterRegistryCPanelApps(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
 +        RegisterRegistryCPanelApps(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
 +    }
 +    return TRUE;
 +}
 +
 +CControlPanelFolder::CControlPanelFolder()
 +{
 +    pidlRoot = NULL;    /* absolute pidl */
 +    dwAttributes = 0;        /* attributes returned by GetAttributesOf FIXME: use it */
 +    apidl = NULL;
 +    cidl = 0;
 +}
 +
 +CControlPanelFolder::~CControlPanelFolder()
 +{
 +    TRACE("-- destroying IShellFolder(%p)\n", this);
 +    SHFree(pidlRoot);
 +}
 +
 +HRESULT WINAPI CControlPanelFolder::FinalConstruct()
 +{
 +    pidlRoot = _ILCreateControlPanel();    /* my qualified pidl */
 +    if (pidlRoot == NULL)
 +        return E_OUTOFMEMORY;
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*    CControlPanelFolder::ParseDisplayName
 +*/
 +HRESULT WINAPI CControlPanelFolder::ParseDisplayName(
 +    HWND hwndOwner,
 +    LPBC pbc,
 +    LPOLESTR lpszDisplayName,
 +    DWORD *pchEaten,
-     LPCITEMIDLIST pidl,
++    PIDLIST_RELATIVE *ppidl,
 +    DWORD *pdwAttributes)
 +{
 +    WCHAR szElement[MAX_PATH];
 +    LPCWSTR szNext = NULL;
 +    LPITEMIDLIST pidlTemp = NULL;
 +    HRESULT hr = S_OK;
 +    CLSID clsid;
 +
 +    TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
 +           this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
 +           pchEaten, ppidl, pdwAttributes);
 +
 +    if (!lpszDisplayName || !ppidl)
 +        return E_INVALIDARG;
 +
 +    *ppidl = 0;
 +
 +    if (pchEaten)
 +        *pchEaten = 0;        /* strange but like the original */
 +
 +    if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
 +    {
 +        szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
 +        TRACE ("-- element: %s\n", debugstr_w (szElement));
 +        CLSIDFromString (szElement + 2, &clsid);
 +        pidlTemp = _ILCreateGuid (PT_GUID, clsid);
 +    }
 +    else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) )
 +    {
 +        *ppidl = pidlTemp;
 +        return S_OK;
 +    }
 +
 +    if (SUCCEEDED(hr) && pidlTemp)
 +    {
 +        if (szNext && *szNext)
 +        {
 +            hr = SHELL32_ParseNextElement(this, hwndOwner, pbc,
 +                                          &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
 +        }
 +        else
 +        {
 +            if (pdwAttributes && *pdwAttributes)
 +                hr = SHELL32_GetItemAttributes(this,
 +                                               pidlTemp, pdwAttributes);
 +        }
 +    }
 +
 +    *ppidl = pidlTemp;
 +
 +    TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*        CControlPanelFolder::EnumObjects
 +*/
 +HRESULT WINAPI CControlPanelFolder::EnumObjects(
 +    HWND hwndOwner,
 +    DWORD dwFlags,
 +    LPENUMIDLIST *ppEnumIDList)
 +{
 +    CComObject<CControlPanelEnum>            *theEnumerator;
 +    CComPtr<IEnumIDList>                    result;
 +    HRESULT                                    hResult;
 +
 +    TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +    *ppEnumIDList = NULL;
 +    ATLTRY (theEnumerator = new CComObject<CControlPanelEnum>);
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
 +    if (FAILED (hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +    hResult = theEnumerator->Initialize (dwFlags);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach ();
 +
 +    TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*        CControlPanelFolder::BindToObject
 +*/
 +HRESULT WINAPI CControlPanelFolder::BindToObject(
-     LPCITEMIDLIST pidl,
++    PCUIDLIST_RELATIVE pidl,
 +    LPBC pbcReserved,
 +    REFIID riid,
 +    LPVOID *ppvOut)
 +{
 +    TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
 +
 +    return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
 +}
 +
 +/**************************************************************************
 +*    CControlPanelFolder::BindToStorage
 +*/
 +HRESULT WINAPI CControlPanelFolder::BindToStorage(
- HRESULT WINAPI CControlPanelFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++    PCUIDLIST_RELATIVE pidl,
 +    LPBC pbcReserved,
 +    REFIID riid,
 +    LPVOID *ppvOut)
 +{
 +    FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 +*     CControlPanelFolder::CompareIDs
 +*/
 +
- HRESULT WINAPI CControlPanelFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
++HRESULT WINAPI CControlPanelFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs(this, lParam, pidl1, pidl2);
 +    TRACE("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 +*    CControlPanelFolder::CreateViewObject
 +*/
 +HRESULT WINAPI CControlPanelFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
 +{
 +    CComPtr<IShellView>                    pShellView;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner, shdebugstr_guid(&riid), ppvOut);
 +
 +    if (ppvOut) {
 +        *ppvOut = NULL;
 +
 +        if (IsEqualIID(riid, IID_IDropTarget)) {
 +            WARN("IDropTarget not implemented\n");
 +            hr = E_NOTIMPL;
 +        } else if (IsEqualIID(riid, IID_IContextMenu)) {
 +            WARN("IContextMenu not implemented\n");
 +            hr = E_NOTIMPL;
 +        } else if (IsEqualIID(riid, IID_IShellView)) {
 +            hr = IShellView_Constructor((IShellFolder *)this, &pShellView);
 +            if (pShellView) {
 +                hr = pShellView->QueryInterface(riid, ppvOut);
 +            }
 +        }
 +    }
 +    TRACE("--(%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*  CControlPanelFolder::GetAttributesOf
 +*/
-         UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
++HRESULT WINAPI CControlPanelFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
 +{
 +    HRESULT hr = S_OK;
 +
 +    TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
 +          this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
 +
 +    if (!rgfInOut)
 +        return E_INVALIDARG;
 +    if (cidl && !apidl)
 +        return E_INVALIDARG;
 +
 +    if (*rgfInOut == 0)
 +        *rgfInOut = ~0;
 +
 +    while(cidl > 0 && *apidl)
 +    {
 +        pdump(*apidl);
 +        SHELL32_GetItemAttributes(this, *apidl, rgfInOut);
 +        apidl++;
 +        cidl--;
 +    }
 +    /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE("-- result=0x%08x\n", *rgfInOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*    CControlPanelFolder::GetUIObjectOf
 +*
 +* PARAMETERS
 +*  HWND           hwndOwner, //[in ] Parent window for any output
 +*  UINT           cidl,      //[in ] array size
 +*  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
 +*  REFIID         riid,      //[in ] Requested Interface
 +*  UINT*          prgfInOut, //[   ] reserved
 +*  LPVOID*        ppvObject) //[out] Resulting Interface
 +*
 +*/
 +HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner,
- HRESULT WINAPI CControlPanelFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
++        UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
 +{
 +    LPITEMIDLIST pidl;
 +    IUnknown *pObj = NULL;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
 +          this, hwndOwner, cidl, apidl, shdebugstr_guid(&riid), prgfInOut, ppvOut);
 +
 +    if (ppvOut) {
 +        *ppvOut = NULL;
 +
 +        if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) {
 +            // TODO
 +            // create a seperate item struct
 +            //
 +            pObj = (IContextMenu *)this;
 +            this->apidl = apidl;
 +            this->cidl = cidl;
 +            pObj->AddRef();
 +            hr = S_OK;
 +        } else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1)) {
 +            hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj);
 +        } else if (IsEqualIID(riid, IID_IExtractIconA) && (cidl == 1)) {
 +            pidl = ILCombine(pidlRoot, apidl[0]);
 +            pObj = IExtractIconA_Constructor(pidl);
 +            SHFree(pidl);
 +            hr = S_OK;
 +        } else if (IsEqualIID(riid, IID_IExtractIconW) && (cidl == 1)) {
 +            pidl = ILCombine(pidlRoot, apidl[0]);
 +            pObj = IExtractIconW_Constructor(pidl);
 +            SHFree(pidl);
 +            hr = S_OK;
 +        } else if ((IsEqualIID(riid, IID_IShellLinkW) || IsEqualIID(riid, IID_IShellLinkA))
 +                   && (cidl == 1)) {
 +            pidl = ILCombine(pidlRoot, apidl[0]);
 +            hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
 +            SHFree(pidl);
 +        } else {
 +            hr = E_NOINTERFACE;
 +        }
 +
 +        if (SUCCEEDED(hr) && !pObj)
 +            hr = E_OUTOFMEMORY;
 +
 +        *ppvOut = pObj;
 +    }
 +    TRACE("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*    CControlPanelFolder::GetDisplayNameOf
 +*/
- HRESULT WINAPI CControlPanelFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,    /*simple pidl */
-         LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
++HRESULT WINAPI CControlPanelFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 +{
 +    CHAR szName[MAX_PATH];
 +    WCHAR wszName[MAX_PATH+1]; /* +1 for potential backslash */
 +    PIDLCPanelStruct *pCPanel;
 +    HRESULT hr;
 +
 +    *szName = '\0';
 +
 +    TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump(pidl);
 +
 +    if (!pidl)
 +        return S_FALSE;
 +
 +    pCPanel = _ILGetCPanelPointer(pidl);
 +
 +    if (pCPanel)
 +    {
 +        /* copy display name from pidl - it was retrived from applet before;
 +           SHGDN_FORPARSING does not need special handling */
 +        lstrcpyA(szName, pCPanel->szName + pCPanel->offsDispName);
 +    }
 +    /* take names of special folders only if it's only this folder */
 +    else if (_ILIsSpecialFolder(pidl))
 +    {
 +        BOOL bSimplePidl = _ILIsPidlSimple(pidl);
 +        SFGAOF Attr = SFGAO_FILESYSTEM;
 +
 +        SHELL32_GetItemAttributes(this, pidl, &Attr);
 +        if (Attr & SFGAO_FILESYSTEM)
 +        {
 +            hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, wszName, sizeof(wszName));
 +            if (FAILED(hr))
 +                return hr;
 +        }
 +        else if (bSimplePidl)
 +        {
 +            _ILSimpleGetTextW(pidl, wszName, MAX_PATH);    /* append my own path */
 +        }
 +        else
 +        {
 +            FIXME("special pidl\n");
 +            if (dwFlags & SHGDN_FORPARSING)
 +            {
 +                /* go deeper if needed */
 +                int cchName;
 +
 +                PathAddBackslashW(wszName);
 +                cchName = wcslen(wszName);
 +
 +                hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, wszName + cchName, MAX_PATH + 1 - cchName);
 +                if (FAILED(hr))
 +                    return hr;
 +            }
 +        }
 +
 +        if (!WideCharToMultiByte(CP_ACP, 0, wszName, -1, szName, MAX_PATH, NULL, NULL))
 +            szName[0] = '\0';
 +    }
 +
 +    strRet->uType = STRRET_CSTR;
 +    lstrcpynA(strRet->cStr, szName, MAX_PATH);
 +
 +    TRACE("--(%p)->(%s)\n", this, szName);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*  CControlPanelFolder::SetNameOf
 +*  Changes the name of a file object or subfolder, possibly changing its item
 +*  identifier in the process.
 +*
 +* PARAMETERS
 +*  HWND          hwndOwner,  //[in ] Owner window for output
 +*  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
 +*  LPCOLESTR     lpszName,   //[in ] the items new display name
 +*  DWORD         dwFlags,    //[in ] SHGNO formatting flags
 +*  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
 +*/
- HRESULT WINAPI CControlPanelFolder::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
++HRESULT WINAPI CControlPanelFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,    /*simple pidl */
++        LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
 +{
 +    FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl, debugstr_w(lpName), dwFlags, pPidlOut);
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CControlPanelFolder::GetDefaultSearchGUID(GUID *pguid)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CControlPanelFolder::EnumSearches(IEnumExtraSearch **ppenum)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CControlPanelFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (pSort) *pSort = 0;
 +    if (pDisplay) *pDisplay = 0;
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CControlPanelFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (!pcsFlags || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) return E_INVALIDARG;
 +    *pcsFlags = ControlPanelSFHeader[iColumn].pcsFlags;
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CControlPanelFolder::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
++HRESULT WINAPI CControlPanelFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
++HRESULT WINAPI CControlPanelFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
 +{
 +    HRESULT hr;
 +
 +    TRACE("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
 +
 +    if (!psd || iColumn >= CONROLPANELSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +
 +    if (!pidl) {
 +        psd->fmt = ControlPanelSFHeader[iColumn].fmt;
 +        psd->cxChar = ControlPanelSFHeader[iColumn].cxChar;
 +        psd->str.uType = STRRET_CSTR;
 +        LoadStringA(shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid, psd->str.cStr, MAX_PATH);
 +        return S_OK;
 +    } else {
 +        psd->str.cStr[0] = 0x00;
 +        psd->str.uType = STRRET_CSTR;
 +        switch(iColumn) {
 +            case 0:        /* name */
 +                hr = GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
 +                break;
 +            case 1:        /* comment */
 +                _ILGetFileType(pidl, psd->str.cStr, MAX_PATH);
 +                break;
 +        }
 +        hr = S_OK;
 +    }
 +
 +    return hr;
 +}
 +
 +HRESULT WINAPI CControlPanelFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +/************************************************************************
 + *    CControlPanelFolder::GetClassID
 + */
 +HRESULT WINAPI CControlPanelFolder::GetClassID(CLSID *lpClassId)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (!lpClassId)
 +        return E_POINTER;
 +    *lpClassId = CLSID_ControlPanel;
 +
 +    return S_OK;
 +}
 +
 +/************************************************************************
 + *    CControlPanelFolder::Initialize
 + *
 + * NOTES: it makes no sense to change the pidl
 + */
 +HRESULT WINAPI CControlPanelFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    if (pidlRoot)
 +        SHFree((LPVOID)pidlRoot);
 +
 +    pidlRoot = ILClone(pidl);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *    CControlPanelFolder::GetCurFolder
 + */
 +HRESULT WINAPI CControlPanelFolder::GetCurFolder(LPITEMIDLIST * pidl)
 +{
 +    TRACE("(%p)->(%p)\n", this, pidl);
 +
 +    if (!pidl)
 +        return E_POINTER;
 +    *pidl = ILClone(pidlRoot);
 +    return S_OK;
 +}
 +
 +HRESULT CPanel_GetIconLocationW(LPCITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex)
 +{
 +    PIDLCPanelStruct* pcpanel = _ILGetCPanelPointer(pidl);
 +
 +    if (!pcpanel)
 +        return E_INVALIDARG;
 +
 +    MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, szIconFile, cchMax);
 +    *piIndex = (int)pcpanel->iconIdx != -1 ? pcpanel->iconIdx : 0;
 +
 +    return S_OK;
 +}
 +
 +
 +/**************************************************************************
 +* IShellExecuteHookW Implementation
 +*/
 +
 +static HRESULT
 +ExecuteAppletFromCLSID(LPOLESTR pOleStr)
 +{
 +    WCHAR wszBuf[128], wszCmd[MAX_PATH];
 +    DWORD cbCmd = sizeof(wszCmd);
 +
 +    StringCbPrintfW(wszBuf, sizeof(wszBuf), L"CLSID\\%s\\shell\\open\\command", pOleStr);
 +
 +    if (RegGetValueW(HKEY_CLASSES_ROOT, wszBuf, NULL, RRF_RT_REG_SZ, NULL, (PVOID)wszCmd, &cbCmd) != ERROR_SUCCESS)
 +    {
 +        ERR("RegGetValueW(%ls) failed with %u\n", wszBuf, GetLastError());
 +        return E_FAIL;
 +    }
 +
 +    if (!ExpandEnvironmentStringsW(wszCmd, wszBuf, _countof(wszBuf)))
 +        return E_FAIL;
 +
 +    PROCESS_INFORMATION pi;
 +    STARTUPINFOW si;
 +    ZeroMemory(&si, sizeof(si));
 +    si.cb = sizeof(si);
 +    if (!CreateProcessW(NULL, wszBuf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
 +        return E_FAIL;
 +
 +    CloseHandle(pi.hProcess);
 +    CloseHandle(pi.hThread);
 +    return S_OK;
 +}
 +
 +EXTERN_C void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
 +
 +HRESULT WINAPI CControlPanelFolder::ExecuteFromIdList(LPCITEMIDLIST pidl)
 +{
 +    PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(ILFindLastID(pidl));
 +
 +    if (!pCPanel)
 +    {
 +        /* Is it GUID to control panel applet? */
 +        IID *piid = _ILGetGUIDPointer(ILFindLastID(pidl));
 +        if (!piid)
 +            return E_INVALIDARG;
 +
 +        /* Start it */
 +        LPOLESTR pOleStr;
 +        if (StringFromCLSID(*piid, &pOleStr) == S_OK)
 +        {
 +            HRESULT hr = ExecuteAppletFromCLSID(pOleStr);
 +            CoTaskMemFree(pOleStr);
 +            return hr;
 +        }
 +
 +        ERR("Cannot open cpanel applet\n");
 +        return E_INVALIDARG;
 +    }
 +
 +    /* Build control panel applet cmd
 +       Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */
 +    WCHAR wszCmd[2*MAX_PATH];
 +    WCHAR wszAppletName[MAX_PATH];
 +
 +    if(!MultiByteToWideChar(CP_ACP, 0, pCPanel->szName + pCPanel->offsDispName, -1, wszAppletName, MAX_PATH))
 +        return E_FAIL;
 +
 +    StringCbPrintfW(wszCmd, sizeof(wszCmd), L"rundll32 shell32.dll,Control_RunDLL \"%hs\",\"%ls\"", pCPanel->szName, wszAppletName);
 +
 +    /* Start the applet */
 +    TRACE("Run cpl %ls\n", wszCmd);
 +    STARTUPINFO si;
 +    PROCESS_INFORMATION pi;
 +    ZeroMemory(&si, sizeof(si));
 +    si.cb = sizeof(si);
 +    if (!CreateProcessW(NULL, wszCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
 +        return E_FAIL;
 +
 +    CloseHandle(pi.hProcess);
 +    CloseHandle(pi.hThread);
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CControlPanelFolder::Execute(LPSHELLEXECUTEINFOW psei)
 +{
 +    TRACE("(%p)->execute(%p)\n", this, psei);
 +
 +    if (!psei)
 +        return E_INVALIDARG;
 +
 +    if (!(psei->fMask & SEE_MASK_IDLIST))
 +    {
 +        FIXME("no idlist given!\n");
 +        return E_FAIL;
 +    }
 +
 +    return ExecuteFromIdList((LPCITEMIDLIST)psei->lpIDList);
 +}
 +
 +/**************************************************************************
 +* IShellExecuteHookA Implementation
 +*/
 +
 +HRESULT WINAPI CControlPanelFolder::Execute(LPSHELLEXECUTEINFOA psei)
 +{
 +    TRACE("(%p)->execute(%p)\n", this, psei);
 +
 +    if (!psei)
 +        return E_INVALIDARG;
 +
 +    if (!(psei->fMask & SEE_MASK_IDLIST))
 +    {
 +        FIXME("no idlist given!\n");
 +        return E_FAIL;
 +    }
 +
 +    return ExecuteFromIdList((LPCITEMIDLIST)psei->lpIDList);
 +}
 +
 +/**************************************************************************
 +* IContextMenu2 Implementation
 +*/
 +
 +/**************************************************************************
 +* ICPanel_IContextMenu_QueryContextMenu()
 +*/
 +HRESULT WINAPI CControlPanelFolder::QueryContextMenu(
 +    HMENU hMenu,
 +    UINT indexMenu,
 +    UINT idCmdFirst,
 +    UINT idCmdLast,
 +    UINT uFlags)
 +{
 +    WCHAR szBuffer[30] = {0};
 +    ULONG Count = 1;
 +
 +    TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
 +          this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
 +
 +    if (LoadStringW(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_OPEN, MFT_STRING, szBuffer, MFS_DEFAULT); //FIXME identifier
 +        Count++;
 +    }
 +
 +    if (LoadStringW(shell32_hInstance, IDS_CREATELINK, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        if (Count)
 +        {
 +            _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_SEPARATOR, NULL, MFS_ENABLED);
 +        }
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_CREATELINK, MFT_STRING, szBuffer, MFS_ENABLED); //FIXME identifier
 +        Count++;
 +    }
 +    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count);
 +}
 +
 +/**************************************************************************
 +* ICPanel_IContextMenu_InvokeCommand()
 +*/
 +HRESULT WINAPI CControlPanelFolder::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    SHELLEXECUTEINFOW sei;
 +    WCHAR szPath[MAX_PATH];
 +    char szTarget[MAX_PATH];
 +    STRRET strret;
 +    WCHAR* pszPath;
 +    INT Length, cLength;
 +    PIDLCPanelStruct *pcpanel;
 +    CComPtr<IPersistFile>                ppf;
 +    CComPtr<IShellLinkA>                isl;
 +    HRESULT hResult;
 +
 +    TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
 +
 +    if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_OPEN)) //FIXME
 +    {
 +        ZeroMemory(&sei, sizeof(sei));
 +        sei.cbSize = sizeof(sei);
 +        sei.fMask = SEE_MASK_INVOKEIDLIST;
 +        sei.lpIDList = ILCombine(pidlRoot, apidl[0]);
 +        sei.hwnd = lpcmi->hwnd;
 +        sei.nShow = SW_SHOWNORMAL;
 +        sei.lpVerb = L"open";
 +ERR("here\n");
 +        return Execute(&sei);
 +    }
 +    else if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_CREATELINK)) //FIXME
 +    {
 +        if (!SHGetSpecialFolderPathW(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE))
 +            return E_FAIL;
 +
 +        pszPath = PathAddBackslashW(szPath);
 +        if (!pszPath)
 +            return E_FAIL;
 +
 +        if (GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strret) != S_OK)
 +            return E_FAIL;
 +
 +        Length =  MAX_PATH - (pszPath - szPath);
 +        cLength = strlen(strret.cStr);
 +        if (Length < cLength + 5)
 +        {
 +            FIXME("\n");
 +            return E_FAIL;
 +        }
 +
 +        if (MultiByteToWideChar(CP_ACP, 0, strret.cStr, cLength + 1, pszPath, Length))
 +        {
 +            pszPath += cLength;
 +            Length -= cLength;
 +        }
 +
 +        if (Length > 10)
 +        {
 +            wcscpy(pszPath, L" - ");
 +            cLength = LoadStringW(shell32_hInstance, IDS_LNK_FILE, &pszPath[3], Length - 4) + 3;
 +            if (cLength + 5 > Length)
 +                cLength = Length - 5;
 +            Length -= cLength;
 +            pszPath += cLength;
 +        }
 +        wcscpy(pszPath, L".lnk");
 +
 +        pcpanel = _ILGetCPanelPointer(ILFindLastID(apidl[0]));
 +        if (pcpanel)
 +        {
 +            strncpy(szTarget, pcpanel->szName, MAX_PATH);
 +        }
 +        else
 +        {
 +            FIXME("Couldn't retrieve pointer to cpl structure\n");
 +            return E_FAIL;
 +        }
 +        hResult = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkA, &isl));
 +        if (SUCCEEDED(hResult))
 +        {
 +            isl->SetPath(szTarget);
 +            if (SUCCEEDED(isl->QueryInterface(IID_PPV_ARG(IPersistFile,&ppf))))
 +                ppf->Save(szPath, TRUE);
 +        }
 +        return NOERROR;
 +    }
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *  ICPanel_IContextMenu_GetCommandString()
 + *
 + */
 +HRESULT WINAPI CControlPanelFolder::GetCommandString(
 +    UINT_PTR idCommand,
 +    UINT uFlags,
 +    UINT* lpReserved,
 +    LPSTR lpszName,
 +    UINT uMaxNameLen)
 +{
 +    TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
 +
 +    FIXME("unknown command string\n");
 +    return E_FAIL;
 +}
 +
 +/**************************************************************************
 +* ICPanel_IContextMenu_HandleMenuMsg()
 +*/
 +HRESULT WINAPI CControlPanelFolder::HandleMenuMsg(
 +    UINT uMsg,
 +    WPARAM wParam,
 +    LPARAM lParam)
 +{
 +    TRACE("ICPanel_IContextMenu_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
 +
 +    return E_NOTIMPL;
 +}
Simple merge
index 6fb5c35,0000000..5ed78a2
mode 100644,000000..100644
--- /dev/null
@@@ -1,1542 -1,0 +1,1542 @@@
-     LPITEMIDLIST *ppidl,
 +/*
 + *    Virtual Desktop Folder
 + *
 + *    Copyright 1997                Marcus Meissner
 + *    Copyright 1998, 1999, 2002    Juergen Schmied
 + *    Copyright 2009                Andrew Hill
 + *
 + * 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);
 +
 +/*
 +CDesktopFolder should create two file system folders internally, one representing the
 +user's desktop folder, and the other representing the common desktop folder. It should
 +also create a CRegFolder to represent the virtual items that exist only in the registry.
 +The CRegFolder is aggregated by the CDesktopFolder, and queries for the CLSID_IShellFolder,
 +CLSID_IShellFolder2, or CLSID_IShellIconOverlay interfaces prefer the CRegFolder
 +implementation.
 +The CDesktopFolderEnum class should create two enumerators, one for each of the file
 +system folders, and enumerate the contents of each folder. Since the CRegFolder
 +implementation of IShellFolder::EnumObjects enumerates the virtual items, the
 +CDesktopFolderEnum is only responsible for returning the physical items.
 +CDesktopFolderEnum is incorrect where it filters My Computer from the enumeration
 +if the new start menu is used. The CDesktopViewCallback is responsible for filtering
 +it from the view by handling the IncludeObject query to return S_FALSE. The enumerator
 +always shows My Computer.
 +*/
 +
 +/* Undocumented functions from shdocvw */
 +extern "C" HRESULT WINAPI IEParseDisplayNameWithBCW(DWORD codepage, LPCWSTR lpszDisplayName, LPBC pbc, LPITEMIDLIST *ppidl);
 +
 +/***********************************************************************
 +*     Desktopfolder implementation
 +*/
 +
 +class CDesktopFolder;
 +
 +class CDesktopFolderEnum :
 +    public IEnumIDListImpl
 +{
 +    private:
 +//    CComPtr                                fDesktopEnumerator;
 +//    CComPtr                                fCommonDesktopEnumerator;
 +    public:
 +        CDesktopFolderEnum();
 +        ~CDesktopFolderEnum();
 +        HRESULT WINAPI Initialize(CDesktopFolder *desktopFolder, HWND hwndOwner, DWORD dwFlags);
 +
 +        BEGIN_COM_MAP(CDesktopFolderEnum)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +int SHELL_ConfirmMsgBox(HWND hWnd, LPWSTR lpszText, LPWSTR lpszCaption, HICON hIcon, BOOL bYesToAll);
 +
 +static const shvheader DesktopSFHeader[] = {
 +    {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
 +    {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
 +};
 +
 +#define DESKTOPSHELLVIEWCOLUMNS 5
 +
 +CDesktopFolderEnum::CDesktopFolderEnum()
 +{
 +}
 +
 +CDesktopFolderEnum::~CDesktopFolderEnum()
 +{
 +}
 +
 +static const WCHAR ClassicStartMenuW[] = L"SOFTWARE\\Microsoft\\Windows\\"
 +    L"CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu";
 +
 +static INT
 +IsNamespaceExtensionHidden(const WCHAR *iid)
 +{
 +    DWORD Result, dwResult;
 +    dwResult = sizeof(DWORD);
 +
 +    if (RegGetValueW(HKEY_CURRENT_USER, /* FIXME use NewStartPanel when activated */
 +                     ClassicStartMenuW,
 +                     iid,
 +                     RRF_RT_DWORD,
 +                     NULL,
 +                     &Result,
 +                     &dwResult) != ERROR_SUCCESS)
 +    {
 +        return -1;
 +    }
 +
 +    return Result;
 +}
 +
 +static VOID
 +SetNamespaceExtensionVisibleStatus(const WCHAR * iid, DWORD dwStatus)
 +{
 +    HKEY hKey;
 +
 +    if (RegOpenKeyExW(HKEY_CURRENT_USER, ClassicStartMenuW, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
 +    {
 +        RegSetValueExW(hKey, iid, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(DWORD));
 +        RegCloseKey(hKey);
 +    }
 +}
 +
 +/**************************************************************************
 + *  CreateDesktopEnumList()
 + */
 +
 +HRESULT WINAPI CDesktopFolderEnum::Initialize(CDesktopFolder *desktopFolder, HWND hwndOwner, DWORD dwFlags)
 +{
 +    BOOL ret = TRUE;
 +    WCHAR szPath[MAX_PATH];
 +
 +    static const WCHAR MyDocumentsClassString[] = L"{450D8FBA-AD25-11D0-98A8-0800361B1103}";
 +    static const WCHAR Desktop_NameSpaceW[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\Namespace";
 +
 +    TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
 +
 +    /* enumerate the root folders */
 +    if (dwFlags & SHCONTF_FOLDERS)
 +    {
 +        HKEY hkey;
 +        UINT i;
 +        DWORD dwResult;
 +
 +        /* create the pidl for This item */
 +        if (IsNamespaceExtensionHidden(MyDocumentsClassString) < 1)
 +        {
 +            ret = AddToEnumList(_ILCreateMyDocuments());
 +        }
 +        ret = AddToEnumList(_ILCreateMyComputer());
 +
 +        for (i = 0; i < 2; i++)
 +        {
 +            if (i == 0)
 +                dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, Desktop_NameSpaceW, 0, KEY_READ, &hkey);
 +            else
 +                dwResult = RegOpenKeyExW(HKEY_CURRENT_USER, Desktop_NameSpaceW, 0, KEY_READ, &hkey);
 +
 +            if (dwResult == ERROR_SUCCESS)
 +            {
 +                WCHAR iid[50];
 +                LPITEMIDLIST pidl;
 +                int i = 0;
 +
 +                while (ret)
 +                {
 +                    DWORD size;
 +                    LONG r;
 +
 +                    size = sizeof (iid) / sizeof (iid[0]);
 +                    r = RegEnumKeyExW(hkey, i, iid, &size, 0, NULL, NULL, NULL);
 +                    if (ERROR_SUCCESS == r)
 +                    {
 +                        if (IsNamespaceExtensionHidden(iid) < 1)
 +                        {
 +                            pidl = _ILCreateGuidFromStrW(iid);
 +                            if (pidl != NULL)
 +                            {
 +                                if (!HasItemWithCLSID(pidl))
 +                                {
 +                                    ret = AddToEnumList(pidl);
 +                                }
 +                                else
 +                                {
 +                                    SHFree(pidl);
 +                                }
 +                            }
 +                        }
 +                    }
 +                    else if (ERROR_NO_MORE_ITEMS == r)
 +                        break;
 +                    else
 +                        ret = FALSE;
 +                    i++;
 +                }
 +                RegCloseKey(hkey);
 +            }
 +        }
 +        for (i = 0; i < 2; i++)
 +        {
 +            if (i == 0)
 +                dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, ClassicStartMenuW, 0, KEY_READ, &hkey);
 +            else
 +                dwResult = RegOpenKeyExW(HKEY_CURRENT_USER, ClassicStartMenuW, 0, KEY_READ, &hkey);
 +
 +            if (dwResult == ERROR_SUCCESS)
 +            {
 +                DWORD j = 0, dwVal, Val, dwType, dwIID;
 +                LONG r;
 +                WCHAR iid[50];
 +
 +                while(ret)
 +                {
 +                    dwVal = sizeof(Val);
 +                    dwIID = sizeof(iid) / sizeof(WCHAR);
 +
 +                    r = RegEnumValueW(hkey, j++, iid, &dwIID, NULL, &dwType, (LPBYTE)&Val, &dwVal);
 +                    if (r == ERROR_SUCCESS)
 +                    {
 +                        if (Val == 0 && dwType == REG_DWORD)
 +                        {
 +                            LPITEMIDLIST pidl = _ILCreateGuidFromStrW(iid);
 +                            if (pidl != NULL)
 +                            {
 +                                if (!HasItemWithCLSID(pidl))
 +                                {
 +                                    AddToEnumList(pidl);
 +                                }
 +                                else
 +                                {
 +                                    SHFree(pidl);
 +                                }
 +                            }
 +                        }
 +                    }
 +                    else if (ERROR_NO_MORE_ITEMS == r)
 +                        break;
 +                    else
 +                        ret = FALSE;
 +                }
 +                RegCloseKey(hkey);
 +            }
 +
 +        }
 +    }
 +
 +    /* enumerate the elements in %windir%\desktop */
 +    ret = ret && SHGetSpecialFolderPathW(0, szPath, CSIDL_DESKTOPDIRECTORY, FALSE);
 +    ret = ret && CreateFolderEnumList(szPath, dwFlags);
 +
 +    ret = ret && SHGetSpecialFolderPathW(0, szPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE);
 +    ret = ret && CreateFolderEnumList(szPath, dwFlags);
 +
 +    return ret ? S_OK : E_FAIL;
 +}
 +
 +void CDesktopFolder::SF_RegisterClipFmt()
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!cfShellIDList)
 +        cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
 +}
 +
 +CDesktopFolder::CDesktopFolder()
 +{
 +    pidlRoot = NULL;
 +    sPathTarget = NULL;
 +    cfShellIDList = 0;
 +    SF_RegisterClipFmt();
 +    fAcceptFmt = FALSE;
 +}
 +
 +CDesktopFolder::~CDesktopFolder()
 +{
 +}
 +
 +HRESULT WINAPI CDesktopFolder::FinalConstruct()
 +{
 +    WCHAR                                szMyPath[MAX_PATH];
 +
 +    if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE ))
 +        return E_UNEXPECTED;
 +
 +    pidlRoot = _ILCreateDesktop();    /* my qualified pidl */
 +    sPathTarget = (LPWSTR)SHAlloc((wcslen(szMyPath) + 1) * sizeof(WCHAR));
 +    wcscpy(sPathTarget, szMyPath);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *    CDesktopFolder::ParseDisplayName
 + *
 + * NOTES
 + *    "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
 + *    to MyComputer
 + */
 +HRESULT WINAPI CDesktopFolder::ParseDisplayName(
 +    HWND hwndOwner,
 +    LPBC pbc,
 +    LPOLESTR lpszDisplayName,
 +    DWORD *pchEaten,
-     LPCITEMIDLIST pidl,
++    PIDLIST_RELATIVE *ppidl,
 +    DWORD *pdwAttributes)
 +{
 +    WCHAR szElement[MAX_PATH];
 +    LPCWSTR szNext = NULL;
 +    LPITEMIDLIST pidlTemp = NULL;
 +    PARSEDURLW urldata;
 +    HRESULT hr = S_OK;
 +    CLSID clsid;
 +
 +    TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
 +           this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
 +           pchEaten, ppidl, pdwAttributes);
 +
 +    if (!ppidl)
 +        return E_INVALIDARG;
 +
 +    if (!lpszDisplayName)
 +    {
 +        *ppidl = NULL;
 +        return E_INVALIDARG;
 +    }
 +
 +    *ppidl = NULL;
 +
 +    if (pchEaten)
 +        *pchEaten = 0;        /* strange but like the original */
 +
 +    urldata.cbSize = sizeof(urldata);
 +
 +    if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
 +    {
 +        szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
 +        TRACE ("-- element: %s\n", debugstr_w (szElement));
 +        CLSIDFromString (szElement + 2, &clsid);
 +        pidlTemp = _ILCreateGuid (PT_GUID, clsid);
 +    }
 +    else if (PathGetDriveNumberW (lpszDisplayName) >= 0)
 +    {
 +        /* it's a filesystem path with a drive. Let MyComputer/UnixDosFolder parse it */
 +        pidlTemp = _ILCreateMyComputer ();
 +        szNext = lpszDisplayName;
 +    }
 +    else if (PathIsUNCW(lpszDisplayName))
 +    {
 +        pidlTemp = _ILCreateNetwork();
 +        szNext = lpszDisplayName;
 +    }
 +    else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) )
 +    {
 +        *ppidl = pidlTemp;
 +        return S_OK;
 +    }
 +    else if (SUCCEEDED(ParseURLW(lpszDisplayName, &urldata)))
 +    {
 +        if (urldata.nScheme == URL_SCHEME_SHELL) /* handle shell: urls */
 +        {
 +            TRACE ("-- shell url: %s\n", debugstr_w(urldata.pszSuffix));
 +            SHCLSIDFromStringW (urldata.pszSuffix + 2, &clsid);
 +            pidlTemp = _ILCreateGuid (PT_GUID, clsid);
 +        }
 +        else
 +            return IEParseDisplayNameWithBCW(CP_ACP, lpszDisplayName, pbc, ppidl);
 +    }
 +    else
 +    {
 +        /* it's a filesystem path on the desktop. Let a FSFolder parse it */
 +
 +        if (*lpszDisplayName)
 +        {
 +            WCHAR szPath[MAX_PATH];
 +            LPWSTR pathPtr;
 +
 +            /* build a complete path to create a simple pidl */
 +            lstrcpynW(szPath, sPathTarget, MAX_PATH);
 +            pathPtr = PathAddBackslashW(szPath);
 +            if (pathPtr)
 +            {
 +                lstrcpynW(pathPtr, lpszDisplayName, MAX_PATH - (pathPtr - szPath));
 +                hr = _ILCreateFromPathW(szPath, &pidlTemp);
 +            }
 +            else
 +            {
 +                /* should never reach here, but for completeness */
 +                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
 +            }
 +        }
 +        else
 +            pidlTemp = _ILCreateMyComputer();
 +
 +        szNext = NULL;
 +    }
 +
 +    if (SUCCEEDED(hr) && pidlTemp)
 +    {
 +        if (szNext && *szNext)
 +        {
 +            hr = SHELL32_ParseNextElement(this, hwndOwner, pbc,
 +                                          &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
 +        }
 +        else
 +        {
 +            if (pdwAttributes && *pdwAttributes)
 +                hr = SHELL32_GetItemAttributes((IShellFolder *)this,
 +                                               pidlTemp, pdwAttributes);
 +        }
 +    }
 +
 +    if (SUCCEEDED(hr))
 +        *ppidl = pidlTemp;
 +    else
 +        *ppidl = NULL;
 +
 +    TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *        CDesktopFolder::EnumObjects
 + */
 +HRESULT WINAPI CDesktopFolder::EnumObjects(
 +    HWND hwndOwner,
 +    DWORD dwFlags,
 +    LPENUMIDLIST *ppEnumIDList)
 +{
 +    CComObject<CDesktopFolderEnum>            *theEnumerator;
 +    CComPtr<IEnumIDList>                    result;
 +    HRESULT                                    hResult;
 +
 +    TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +    *ppEnumIDList = NULL;
 +
 +    ATLTRY (theEnumerator = new CComObject<CDesktopFolderEnum>);
 +
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +
 +    hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
 +    if (FAILED (hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +
 +    hResult = theEnumerator->Initialize (this, hwndOwner, dwFlags);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach ();
 +
 +    TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *        CDesktopFolder::BindToObject
 + */
 +HRESULT WINAPI CDesktopFolder::BindToObject(
-     LPCITEMIDLIST pidl,
++    PCUIDLIST_RELATIVE pidl,
 +    LPBC pbcReserved,
 +    REFIID riid,
 +    LPVOID *ppvOut)
 +{
 +    TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n",
 +           this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    return SHELL32_BindToChild( pidlRoot, sPathTarget, pidl, riid, ppvOut );
 +}
 +
 +/**************************************************************************
 + *    CDesktopFolder::BindToStorage
 + */
 +HRESULT WINAPI CDesktopFolder::BindToStorage(
- HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++    PCUIDLIST_RELATIVE pidl,
 +    LPBC pbcReserved,
 +    REFIID riid,
 +    LPVOID *ppvOut)
 +{
 +    FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
 +           this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 + *     CDesktopFolder::CompareIDs
 + */
-     LPCITEMIDLIST *apidl,
++HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs ((IShellFolder *)this, lParam, pidl1, pidl2);
 +    TRACE ("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 + *    CDesktopFolder::CreateViewObject
 + */
 +HRESULT WINAPI CDesktopFolder::CreateViewObject(
 +    HWND hwndOwner,
 +    REFIID riid,
 +    LPVOID *ppvOut)
 +{
 +    CComPtr<IShellView> pShellView;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
 +           this, hwndOwner, shdebugstr_guid (&riid), ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IDropTarget))
 +    {
 +        hr = this->QueryInterface (IID_IDropTarget, ppvOut);
 +    }
 +    else if (IsEqualIID (riid, IID_IContextMenu))
 +    {
 +        WARN ("IContextMenu not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID (riid, IID_IShellView))
 +    {
 +        hr = IShellView_Constructor((IShellFolder *)this, &pShellView);
 +        if (pShellView)
 +            hr = pShellView->QueryInterface(riid, ppvOut);
 +    }
 +    TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *  CDesktopFolder::GetAttributesOf
 + */
 +HRESULT WINAPI CDesktopFolder::GetAttributesOf(
 +    UINT cidl,
-     LPCITEMIDLIST *apidl,
++    PCUITEMID_CHILD_ARRAY apidl,
 +    DWORD *rgfInOut)
 +{
 +    HRESULT hr = S_OK;
 +    static const DWORD dwDesktopAttributes =
 +        SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
 +        SFGAO_STORAGEANCESTOR | SFGAO_HASPROPSHEET | SFGAO_STORAGE | SFGAO_CANLINK;
 +    static const DWORD dwMyComputerAttributes =
 +        SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
 +        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
 +    static DWORD dwMyNetPlacesAttributes =
 +        SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
 +        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
 +
 +    TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
 +          this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
 +
 +    if (cidl && !apidl)
 +        return E_INVALIDARG;
 +
 +    if (*rgfInOut == 0)
 +        *rgfInOut = ~0;
 +
 +    if(cidl == 0)
 +        *rgfInOut &= dwDesktopAttributes;
 +    else
 +    {
 +        /* TODO: always add SFGAO_CANLINK */
 +        for (UINT i = 0; i < cidl; ++i)
 +        {
 +            pdump(*apidl);
 +            if (_ILIsDesktop(*apidl))
 +                *rgfInOut &= dwDesktopAttributes;
 +            else if (_ILIsMyComputer(apidl[i]))
 +                *rgfInOut &= dwMyComputerAttributes;
 +            else if (_ILIsNetHood(apidl[i]))
 +                *rgfInOut &= dwMyNetPlacesAttributes;
 +            else
 +                SHELL32_GetItemAttributes((IShellFolder *)this, apidl[i], rgfInOut);
 +        }
 +    }
 +    /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE("-- result=0x%08x\n", *rgfInOut);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *    CDesktopFolder::GetUIObjectOf
 + *
 + * PARAMETERS
 + *  HWND           hwndOwner, //[in ] Parent window for any output
 + *  UINT           cidl,      //[in ] array size
 + *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
 + *  REFIID         riid,      //[in ] Requested Interface
 + *  UINT*          prgfInOut, //[   ] reserved
 + *  LPVOID*        ppvObject) //[out] Resulting Interface
 + *
 + */
 +HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
 +    HWND hwndOwner,
 +    UINT cidl,
- HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
++    PCUITEMID_CHILD_ARRAY apidl,
 +    REFIID riid,
 +    UINT *prgfInOut,
 +    LPVOID *ppvOut)
 +{
 +    LPITEMIDLIST pidl;
 +    IUnknown *pObj = NULL;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
 +           this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IContextMenu))
 +    {
 +        hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder *)this, NULL, 0, NULL, (IContextMenu **)&pObj);
 +    }
 +    else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
 +    {
 +        hr = IDataObject_Constructor( hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj);
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconA_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconW_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IDropTarget))
 +    {
 +        /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
 +        if (cidl != 1 || FAILED(hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj)))
 +        {
 +            IDropTarget * pDt = NULL;
 +            hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
 +            pObj = pDt;
 +        }
 +    }
 +    else if ((IsEqualIID(riid, IID_IShellLinkW) ||
 +              IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
 +        SHFree (pidl);
 +    }
 +    else
 +        hr = E_NOINTERFACE;
 +
 +    if (SUCCEEDED(hr) && !pObj)
 +        hr = E_OUTOFMEMORY;
 +
 +    *ppvOut = pObj;
 +    TRACE ("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *    CDesktopFolder::GetDisplayNameOf
 + *
 + * NOTES
 + *    special case: pidl = null gives desktop-name back
 + */
-     LPCITEMIDLIST pidl,    /* simple pidl */
++HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 +{
 +    HRESULT hr = S_OK;
 +    LPWSTR pszPath;
 +
 +    TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump (pidl);
 +
 +    if (!strRet)
 +        return E_INVALIDARG;
 +
 +    pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
 +    if (!pszPath)
 +        return E_OUTOFMEMORY;
 +
 +    if (_ILIsDesktop (pidl))
 +    {
 +        if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
 +                (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING))
 +            wcscpy(pszPath, sPathTarget);
 +        else
 +            HCR_GetClassNameW(CLSID_ShellDesktop, pszPath, MAX_PATH);
 +    }
 +    else if (_ILIsPidlSimple (pidl))
 +    {
 +        GUID const *clsid;
 +
 +        if ((clsid = _ILGetGUIDPointer (pidl)))
 +        {
 +            if (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING)
 +            {
 +                int bWantsForParsing;
 +
 +                /*
 +                 * We can only get a filesystem path from a shellfolder if the
 +                 *  value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
 +                 *
 +                 * Exception: The MyComputer folder doesn't have this key,
 +                 *   but any other filesystem backed folder it needs it.
 +                 */
 +                if (IsEqualIID (*clsid, CLSID_MyComputer))
 +                {
 +                    bWantsForParsing = TRUE;
 +                }
 +                else
 +                {
 +                    /* get the "WantsFORPARSING" flag from the registry */
 +                    static const WCHAR clsidW[] =
 +                    { 'C', 'L', 'S', 'I', 'D', '\\', 0 };
 +                    static const WCHAR shellfolderW[] =
 +                    { '\\', 's', 'h', 'e', 'l', 'l', 'f', 'o', 'l', 'd', 'e', 'r', 0 };
 +                    static const WCHAR wantsForParsingW[] =
 +                    {   'W', 'a', 'n', 't', 's', 'F', 'o', 'r', 'P', 'a', 'r', 's', 'i', 'n',
 +                        'g', 0
 +                    };
 +                    WCHAR szRegPath[100];
 +                    LONG r;
 +
 +                    wcscpy (szRegPath, clsidW);
 +                    SHELL32_GUIDToStringW (*clsid, &szRegPath[6]);
 +                    wcscat (szRegPath, shellfolderW);
 +                    r = SHGetValueW(HKEY_CLASSES_ROOT, szRegPath,
 +                                    wantsForParsingW, NULL, NULL, NULL);
 +                    if (r == ERROR_SUCCESS)
 +                        bWantsForParsing = TRUE;
 +                    else
 +                        bWantsForParsing = FALSE;
 +                }
 +
 +                if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
 +                        bWantsForParsing)
 +                {
 +                    /*
 +                     * we need the filesystem path to the destination folder.
 +                     * Only the folder itself can know it
 +                     */
 +                    hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags,
 +                                                        pszPath,
 +                                                        MAX_PATH);
 +                }
 +                else
 +                {
 +                    /* parsing name like ::{...} */
 +                    pszPath[0] = ':';
 +                    pszPath[1] = ':';
 +                    SHELL32_GUIDToStringW (*clsid, &pszPath[2]);
 +                }
 +            }
 +            else
 +            {
 +                /* user friendly name */
 +                HCR_GetClassNameW (*clsid, pszPath, MAX_PATH);
 +            }
 +        }
 +        else
 +        {
 +            int cLen = 0;
 +
 +            /* file system folder or file rooted at the desktop */
 +            if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) &&
 +                    (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
 +            {
 +                lstrcpynW(pszPath, sPathTarget, MAX_PATH - 1);
 +                PathAddBackslashW(pszPath);
 +                cLen = wcslen(pszPath);
 +            }
 +
 +            _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen);
 +            if (!_ILIsFolder(pidl))
 +                SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
 +
 +            if (GetFileAttributes(pszPath) == INVALID_FILE_ATTRIBUTES)
 +            {
 +                /* file system folder or file rooted at the AllUsers desktop */
 +                if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) &&
 +                        (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
 +                {
 +                    SHGetSpecialFolderPathW(0, pszPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE);
 +                    PathAddBackslashW(pszPath);
 +                    cLen = wcslen(pszPath);
 +                }
 +
 +                _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen);
 +                if (!_ILIsFolder(pidl))
 +                    SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
 +            }
 +        }
 +    }
 +    else
 +    {
 +        /* a complex pidl, let the subfolder do the work */
 +        hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags,
 +                                            pszPath, MAX_PATH);
 +    }
 +
 +    if (SUCCEEDED(hr))
 +    {
 +        /* Win9x always returns ANSI strings, NT always returns Unicode strings */
 +        if (GetVersion() & 0x80000000)
 +        {
 +            strRet->uType = STRRET_CSTR;
 +            if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->cStr, MAX_PATH,
 +                                     NULL, NULL))
 +                strRet->cStr[0] = '\0';
 +            CoTaskMemFree(pszPath);
 +        }
 +        else
 +        {
 +            strRet->uType = STRRET_WSTR;
 +            strRet->pOleStr = pszPath;
 +        }
 +    }
 +    else
 +        CoTaskMemFree(pszPath);
 +
 +    TRACE ("-- (%p)->(%s,0x%08x)\n", this,
 +           strRet->uType == STRRET_CSTR ? strRet->cStr :
 +           debugstr_w(strRet->pOleStr), hr);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *  CDesktopFolder::SetNameOf
 + *  Changes the name of a file object or subfolder, possibly changing its item
 + *  identifier in the process.
 + *
 + * PARAMETERS
 + *  HWND          hwndOwner,  //[in ] Owner window for output
 + *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
 + *  LPCOLESTR     lpszName,   //[in ] the items new display name
 + *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
 + *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
 + */
 +HRESULT WINAPI CDesktopFolder::SetNameOf(
 +    HWND hwndOwner,
-     LPITEMIDLIST *pPidlOut)
++    PCUITEMID_CHILD pidl,    /* simple pidl */
 +    LPCOLESTR lpName,
 +    DWORD dwFlags,
-     LPCITEMIDLIST pidl,
++    PITEMID_CHILD *pPidlOut)
 +{
 +    CComPtr<IShellFolder2>                psf;
 +    HRESULT hr;
 +    WCHAR szSrc[MAX_PATH + 1], szDest[MAX_PATH + 1];
 +    LPWSTR ptr;
 +    BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl));
 +
 +    TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl,
 +           debugstr_w (lpName), dwFlags, pPidlOut);
 +
 +    if (_ILGetGUIDPointer(pidl))
 +    {
 +        if (SUCCEEDED(BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder2, &psf))))
 +        {
 +            hr = psf->SetNameOf(hwndOwner, pidl, lpName, dwFlags, pPidlOut);
 +            return hr;
 +        }
 +    }
 +
 +    /* build source path */
 +    lstrcpynW(szSrc, sPathTarget, MAX_PATH);
 +    ptr = PathAddBackslashW (szSrc);
 +    if (ptr)
 +        _ILSimpleGetTextW (pidl, ptr, MAX_PATH + 1 - (ptr - szSrc));
 +
 +    /* build destination path */
 +    if (dwFlags == SHGDN_NORMAL || dwFlags & SHGDN_INFOLDER) {
 +        lstrcpynW(szDest, sPathTarget, MAX_PATH);
 +        ptr = PathAddBackslashW (szDest);
 +        if (ptr)
 +            lstrcpynW(ptr, lpName, MAX_PATH + 1 - (ptr - szDest));
 +    } else
 +        lstrcpynW(szDest, lpName, MAX_PATH);
 +
 +    if(!(dwFlags & SHGDN_FORPARSING) && SHELL_FS_HideExtension(szSrc)) {
 +        WCHAR *ext = PathFindExtensionW(szSrc);
 +        if(*ext != '\0') {
 +            INT len = wcslen(szDest);
 +            lstrcpynW(szDest + len, ext, MAX_PATH - len);
 +        }
 +    }
 +
 +    if (!memcmp(szSrc, szDest, (wcslen(szDest) + 1) * sizeof(WCHAR)))
 +    {
 +        /* src and destination is the same */
 +        hr = S_OK;
 +        if (pPidlOut)
 +            hr = _ILCreateFromPathW(szDest, pPidlOut);
 +
 +        return hr;
 +    }
 +
 +    TRACE ("src=%s dest=%s\n", debugstr_w(szSrc), debugstr_w(szDest));
 +    if (MoveFileW (szSrc, szDest))
 +    {
 +        hr = S_OK;
 +
 +        if (pPidlOut)
 +            hr = _ILCreateFromPathW(szDest, pPidlOut);
 +
 +        SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM,
 +                        SHCNF_PATHW, szSrc, szDest);
 +
 +        return hr;
 +    }
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::GetDefaultSearchGUID(GUID *pguid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::EnumSearches(IEnumExtraSearch **ppenum)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (pSort)
 +        *pSort = 0;
 +    if (pDisplay)
 +        *pDisplay = 0;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +
 +    *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::GetDetailsEx(
-     LPCITEMIDLIST pidl,
++    PCUITEMID_CHILD pidl,
 +    const SHCOLUMNID *pscid,
 +    VARIANT *pv)
 +{
 +    FIXME ("(%p)\n", this);
 +
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::GetDetailsOf(
++    PCUITEMID_CHILD pidl,
 +    UINT iColumn,
 +    SHELLDETAILS *psd)
 +{
 +    HRESULT hr = S_OK;
 +
 +    TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
 +
 +    if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +
 +    if (!pidl)
 +    {
 +        psd->fmt = DesktopSFHeader[iColumn].fmt;
 +        psd->cxChar = DesktopSFHeader[iColumn].cxChar;
 +        psd->str.uType = STRRET_CSTR;
 +        LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid,
 +                     psd->str.cStr, MAX_PATH);
 +        return S_OK;
 +    }
 +
 +    /* the data from the pidl */
 +    psd->str.uType = STRRET_CSTR;
 +    switch (iColumn)
 +    {
 +        case 0:        /* name */
 +            hr = GetDisplayNameOf(pidl,
 +                                  SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
 +            break;
 +        case 1:        /* size */
 +            _ILGetFileSize (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +        case 2:        /* type */
 +            _ILGetFileType (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +        case 3:        /* date */
 +            _ILGetFileDate (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +        case 4:        /* attributes */
 +            _ILGetFileAttributes (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +    }
 +
 +    return hr;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::GetClassID(CLSID *lpClassId)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!lpClassId)
 +        return E_POINTER;
 +
 +    *lpClassId = CLSID_ShellDesktop;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::GetCurFolder(LPITEMIDLIST * pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    if (!pidl) return E_POINTER;
 +    *pidl = ILClone (pidlRoot);
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::GetUniqueName(LPWSTR pwszName, UINT uLen)
 +{
 +    CComPtr<IEnumIDList>                penum;
 +    HRESULT hr;
 +    WCHAR wszText[MAX_PATH];
 +    WCHAR wszNewFolder[25];
 +    const WCHAR wszFormat[] = {'%', 's', ' ', '%', 'd', 0 };
 +
 +    LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder,  sizeof(wszNewFolder) / sizeof(WCHAR));
 +
 +    TRACE ("(%p)(%p %u)\n", this, pwszName, uLen);
 +
 +    if (uLen < sizeof(wszNewFolder) / sizeof(WCHAR) + 3)
 +        return E_POINTER;
 +
 +    lstrcpynW (pwszName, wszNewFolder, uLen);
 +
 +    hr = EnumObjects(0,
 +                     SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
 +    if (penum) {
 +        LPITEMIDLIST pidl;
 +        DWORD dwFetched;
 +        int i = 1;
 +
 +next:
 +        penum->Reset ();
 +        while (S_OK == penum->Next(1, &pidl, &dwFetched) &&
 +                dwFetched) {
 +            _ILSimpleGetTextW (pidl, wszText, MAX_PATH);
 +            if (0 == lstrcmpiW (wszText, pwszName)) {
 +                _snwprintf (pwszName, uLen, wszFormat, wszNewFolder, i++);
 +                if (i > 99) {
 +                    hr = E_FAIL;
 +                    break;
 +                }
 +                goto next;
 +            }
 +        }
 +
 +    }
 +    return hr;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::AddFolder(HWND hwnd, LPCWSTR pwszName, LPITEMIDLIST *ppidlOut)
 +{
 +    WCHAR wszNewDir[MAX_PATH];
 +    DWORD bRes;
 +    HRESULT hres = E_FAIL;
 +
 +    TRACE ("(%p)(%s %p)\n", this, debugstr_w(pwszName), ppidlOut);
 +
 +    wszNewDir[0] = 0;
 +    if (sPathTarget)
 +        lstrcpynW(wszNewDir, sPathTarget, MAX_PATH);
 +    PathAppendW(wszNewDir, pwszName);
 +    bRes = CreateDirectoryW (wszNewDir, NULL);
 +    if (bRes)
 +    {
 +        SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHW, wszNewDir, NULL);
 +        hres = S_OK;
 +        if (ppidlOut)
 +            hres = _ILCreateFromPathW(wszNewDir, ppidlOut);
 +    }
 +
 +    return hres;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::DeleteItems(UINT cidl, LPCITEMIDLIST *apidl)
 +{
 +    UINT i;
 +    SHFILEOPSTRUCTW op;
 +    WCHAR wszPath[MAX_PATH];
 +    WCHAR wszCaption[50];
 +    WCHAR *wszPathsList;
 +    HRESULT ret;
 +    WCHAR *wszCurrentPath;
 +    UINT bRestoreWithDeskCpl = FALSE;
 +    int res;
 +
 +    TRACE ("(%p)(%u %p)\n", this, cidl, apidl);
 +    if (cidl == 0) return S_OK;
 +
 +    for(i = 0; i < cidl; i++)
 +    {
 +        if (_ILIsMyComputer(apidl[i]))
 +            bRestoreWithDeskCpl++;
 +        else if (_ILIsNetHood(apidl[i]))
 +            bRestoreWithDeskCpl++;
 +        else if (_ILIsMyDocuments(apidl[i]))
 +            bRestoreWithDeskCpl++;
 +    }
 +
 +    if (bRestoreWithDeskCpl)
 +    {
 +        /* FIXME use FormatMessage
 +         * use a similar message resource as in windows
 +         */
 +        LoadStringW(shell32_hInstance, IDS_DELETEMULTIPLE_TEXT, wszPath, sizeof(wszPath) / sizeof(WCHAR));
 +        wszPath[(sizeof(wszPath)/sizeof(WCHAR))-1] = 0;
 +
 +        LoadStringW(shell32_hInstance, IDS_DELETEITEM_CAPTION, wszCaption, sizeof(wszCaption) / sizeof(WCHAR));
 +        wszCaption[(sizeof(wszCaption)/sizeof(WCHAR))-1] = 0;
 +
 +        res = SHELL_ConfirmMsgBox(GetActiveWindow(), wszPath, wszCaption, NULL, cidl > 1);
 +        if (res == IDC_YESTOALL || res == IDYES)
 +        {
 +            for(i = 0; i < cidl; i++)
 +            {
 +                if (_ILIsMyComputer(apidl[i]))
 +                    SetNamespaceExtensionVisibleStatus(L"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0x1);
 +                else if (_ILIsNetHood(apidl[i]))
 +                    SetNamespaceExtensionVisibleStatus(L"{208D2C60-3AEA-1069-A2D7-08002B30309D}", 0x1);
 +                else if (_ILIsMyDocuments(apidl[i]))
 +                    SetNamespaceExtensionVisibleStatus(L"{450D8FBA-AD25-11D0-98A8-0800361B1103}", 0x1);
 +            }
 +        }
 +    }
 +    if (sPathTarget)
 +        lstrcpynW(wszPath, sPathTarget, MAX_PATH);
 +    else
 +        wszPath[0] = '\0';
 +
 +    PathAddBackslashW(wszPath);
 +    wszPathsList = BuildPathsList(wszPath, cidl, apidl);
 +
 +    ZeroMemory(&op, sizeof(op));
 +    op.hwnd = GetActiveWindow();
 +    op.wFunc = FO_DELETE;
 +    op.pFrom = wszPathsList;
 +    op.fFlags = FOF_ALLOWUNDO;
 +    if (SHFileOperationW(&op))
 +    {
 +        WARN("SHFileOperation failed\n");
 +        ret = E_FAIL;
 +    }
 +    else
 +        ret = S_OK;
 +
 +    /* we currently need to manually send the notifies */
 +    wszCurrentPath = wszPathsList;
 +    for (i = 0; i < cidl; i++)
 +    {
 +        LONG wEventId;
 +
 +        if (_ILIsFolder(apidl[i]))
 +            wEventId = SHCNE_RMDIR;
 +        else if (_ILIsValue(apidl[i]))
 +            wEventId = SHCNE_DELETE;
 +        else
 +            continue;
 +
 +        /* check if file exists */
 +        if (GetFileAttributesW(wszCurrentPath) == INVALID_FILE_ATTRIBUTES)
 +        {
 +            LPITEMIDLIST pidl = ILCombine(pidlRoot, apidl[i]);
 +            SHChangeNotify(wEventId, SHCNF_IDLIST, pidl, NULL);
 +            SHFree(pidl);
 +        }
 +
 +        wszCurrentPath += wcslen(wszCurrentPath) + 1;
 +    }
 +    HeapFree(GetProcessHeap(), 0, wszPathsList);
 +    return ret;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, bool bCopy)
 +{
 +    CComPtr<IPersistFolder2> ppf2;
 +    WCHAR szSrcPath[MAX_PATH];
 +    WCHAR szTargetPath[MAX_PATH];
 +    SHFILEOPSTRUCTW op;
 +    LPITEMIDLIST pidl;
 +    LPWSTR pszSrc, pszTarget, pszSrcList, pszTargetList, pszFileName;
 +    int res, length;
 +    STRRET strRet;
 +
 +    TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom, cidl, apidl);
 +
 +    pSFFrom->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
 +    if (ppf2)
 +    {
 +        if (FAILED(ppf2->GetCurFolder(&pidl)))
 +            return E_FAIL;
 +
 +        if (FAILED(pSFFrom->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strRet)))
 +        {
 +            SHFree (pidl);
 +            return E_FAIL;
 +        }
 +
 +        if (FAILED(StrRetToBufW(&strRet, pidl, szSrcPath, MAX_PATH)))
 +        {
 +            SHFree (pidl);
 +            return E_FAIL;
 +        }
 +        SHFree (pidl);
 +
 +        pszSrc = PathAddBackslashW (szSrcPath);
 +
 +        wcscpy(szTargetPath, sPathTarget);
 +        pszTarget = PathAddBackslashW (szTargetPath);
 +
 +        pszSrcList = BuildPathsList(szSrcPath, cidl, apidl);
 +        pszTargetList = BuildPathsList(szTargetPath, cidl, apidl);
 +
 +        if (!pszSrcList || !pszTargetList)
 +        {
 +            if (pszSrcList)
 +                HeapFree(GetProcessHeap(), 0, pszSrcList);
 +
 +            if (pszTargetList)
 +                HeapFree(GetProcessHeap(), 0, pszTargetList);
 +
 +            SHFree (pidl);
 +            return E_OUTOFMEMORY;
 +        }
 +        ZeroMemory(&op, sizeof(op));
 +        if (!pszSrcList[0])
 +        {
 +            /* remove trailing backslash */
 +            pszSrc--;
 +            pszSrc[0] = L'\0';
 +            op.pFrom = szSrcPath;
 +        }
 +        else
 +        {
 +            op.pFrom = pszSrcList;
 +        }
 +
 +        if (!pszTargetList[0])
 +        {
 +            /* remove trailing backslash */
 +            if (pszTarget - szTargetPath > 3)
 +            {
 +                pszTarget--;
 +                pszTarget[0] = L'\0';
 +            }
 +            else
 +            {
 +                pszTarget[1] = L'\0';
 +            }
 +
 +            op.pTo = szTargetPath;
 +            op.fFlags = 0;
 +        }
 +        else
 +        {
 +            op.pTo = pszTargetList;
 +            op.fFlags = FOF_MULTIDESTFILES;
 +        }
 +        op.hwnd = GetActiveWindow();
 +        op.wFunc = bCopy ? FO_COPY : FO_MOVE;
 +        op.fFlags |= FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
 +
 +        res = SHFileOperationW(&op);
 +
 +        if (res == DE_SAMEFILE)
 +        {
 +            length = wcslen(szTargetPath);
 +
 +
 +            pszFileName = wcsrchr(pszSrcList, '\\');
 +            pszFileName++;
 +
 +            if (LoadStringW(shell32_hInstance, IDS_COPY_OF, pszTarget, MAX_PATH - length))
 +            {
 +                wcscat(szTargetPath, L" ");
 +            }
 +
 +            wcscat(szTargetPath, pszFileName);
 +            op.pTo = szTargetPath;
 +
 +            res = SHFileOperationW(&op);
 +        }
 +
 +
 +        HeapFree(GetProcessHeap(), 0, pszSrcList);
 +        HeapFree(GetProcessHeap(), 0, pszTargetList);
 +
 +        if (res)
 +            return E_FAIL;
 +        else
 +            return S_OK;
 +    }
 +    return E_FAIL;
 +}
 +
 +/****************************************************************************
 + * IDropTarget implementation
 + *
 + * This should allow two somewhat separate things, copying files to the users directory,
 + * as well as allowing icons to be moved anywhere and updating the registry to save.
 + *
 + * The first thing I think is best done using fs.cpp to prevent WET code. So we'll simulate
 + * a drop to the user's home directory. The second will look at the pointer location and
 + * set sensible places for the icons to live.
 + *
 + */
 +BOOL CDesktopFolder::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
 +{
 +    /* TODO Windows does different drop effects if dragging across drives.
 +    i.e., it will copy instead of move if the directories are on different disks. */
 +
 +    DWORD dwEffect = DROPEFFECT_MOVE;
 +
 +    *pdwEffect = DROPEFFECT_NONE;
 +
 +    if (fAcceptFmt) { /* Does our interpretation of the keystate ... */
 +        *pdwEffect = KeyStateToDropEffect (dwKeyState);
 +
 +        if (*pdwEffect == DROPEFFECT_NONE)
 +            *pdwEffect = dwEffect;
 +
 +        /* ... matches the desired effect ? */
 +        if (dwEffect & *pdwEffect) {
 +            return TRUE;
 +        }
 +    }
 +    return FALSE;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::DragEnter(IDataObject *pDataObject,
 +                                    DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
 +    FORMATETC fmt;
 +    FORMATETC fmt2;
 +    fAcceptFmt = FALSE;
 +
 +    InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
 +    InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
 +
 +    if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
 +        fAcceptFmt = TRUE;
 +    else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
 +        fAcceptFmt = TRUE;
 +
 +    QueryDrop(dwKeyState, pdwEffect);
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::DragOver(DWORD dwKeyState, POINTL pt,
 +                                   DWORD *pdwEffect)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (!pdwEffect)
 +        return E_INVALIDARG;
 +
 +    QueryDrop(dwKeyState, pdwEffect);
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::DragLeave()
 +{
 +    TRACE("(%p)\n", this);
 +    fAcceptFmt = FALSE;
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::Drop(IDataObject *pDataObject,
 +                               DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    TRACE("(%p) object dropped desktop\n", this);
 +
 +    STGMEDIUM medium;
 +    bool passthroughtofs = FALSE;
 +    FORMATETC formatetc;
 +    InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
 +    
 +    HRESULT hr = pDataObject->GetData(&formatetc, &medium);
 +    if (SUCCEEDED(hr))
 +    {
 +        /* lock the handle */
 +        LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
 +        if (!lpcida)
 +        {
 +            ReleaseStgMedium(&medium);
 +            return E_FAIL;
 +        }
 +
 +        /* convert the clipboard data into pidl (pointer to id list) */
 +        LPITEMIDLIST pidl;
 +        LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
 +        if (!apidl)
 +        {
 +            ReleaseStgMedium(&medium);
 +            return E_FAIL;
 +        }
 +        passthroughtofs = !_ILIsDesktop(pidl) || (dwKeyState & MK_CONTROL);
 +        SHFree(pidl);
 +        _ILFreeaPidl(apidl, lpcida->cidl);
 +        ReleaseStgMedium(&medium);
 +    }
 +    else
 +    {
 +        InitFormatEtc (formatetc, CF_HDROP, TYMED_HGLOBAL);
 +        if (SUCCEEDED(pDataObject->QueryGetData(&formatetc)))
 +        {
 +            passthroughtofs = TRUE;
 +        }
 +    }
 +    /* We only want to really move files around if they don't already
 +       come from the desktop, or we're linking or copying */
 +    if (passthroughtofs)
 +    {
 +        LPITEMIDLIST pidl = NULL;
 +
 +        WCHAR szPath[MAX_PATH];
 +        //LPWSTR pathPtr;
 +
 +        /* build a complete path to create a simple pidl */
 +        lstrcpynW(szPath, sPathTarget, MAX_PATH);
 +        /*pathPtr = */PathAddBackslashW(szPath);
 +        //hr = _ILCreateFromPathW(szPath, &pidl);
 +        hr = this->ParseDisplayName(NULL, NULL, szPath, NULL, &pidl, NULL);
 +
 +        if (SUCCEEDED(hr))
 +        {
 +            CComPtr<IDropTarget> pDT;
 +            hr = this->BindToObject(pidl, NULL, IID_PPV_ARG(IDropTarget, &pDT));
 +            CoTaskMemFree(pidl);
 +            if (SUCCEEDED(hr))
 +                SHSimulateDrop(pDT, pDataObject, dwKeyState, NULL, pdwEffect);
 +            else
 +                ERR("Error Binding");
 +        }
 +        else
 +            ERR("Error creating from %s\n", debugstr_w(szPath));
 +    }
 +
 +    /* Todo, rewrite the registry such that the icons are well placed.
 +    Blocked by no bags implementation. */
 +    return hr;
 +}
 +
 +HRESULT WINAPI CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut) {
 +    HRESULT hr;
 +
 +    TRACE("CFSFolder::_GetDropTarget entered\n");
 +
 +    if (_ILGetGUIDPointer (pidl) || _ILIsFolder (pidl))
 +        return this->BindToObject(pidl, NULL, IID_IDropTarget, ppvOut);
 +
 +    LPITEMIDLIST pidlNext = NULL;
 +
 +    STRRET strFile;
 +    hr = this->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strFile);
 +    if (SUCCEEDED(hr))
 +    {
 +        WCHAR wszPath[MAX_PATH];
 +        hr = StrRetToBufW(&strFile, pidl, wszPath, _countof(wszPath));
 +
 +        if (SUCCEEDED(hr))
 +        {
 +            PathRemoveFileSpecW (wszPath);
 +            hr = this->ParseDisplayName(NULL, NULL, wszPath, NULL, &pidlNext, NULL);
 +
 +            if (SUCCEEDED(hr))
 +            {
 +                CComPtr<IShellFolder> psf;
 +                hr = this->BindToObject(pidlNext, NULL, IID_PPV_ARG(IShellFolder, &psf));
 +                CoTaskMemFree(pidlNext);
 +                if (SUCCEEDED(hr))
 +                {
 +                    hr = psf->GetUIObjectOf(NULL, 1, &pidl, IID_IDropTarget, NULL, ppvOut);
 +                    if (FAILED(hr))
 +                        ERR("FS GetUIObjectOf failed: %x\n", hr);
 +                }
 +                else 
 +                    ERR("BindToObject failed: %x\n", hr);
 +            }
 +            else
 +                ERR("ParseDisplayName failed: %x\n", hr);
 +        }
 +        else
 +            ERR("StrRetToBufW failed: %x\n", hr);
 +    }    
 +    else
 +        ERR("GetDisplayNameOf failed: %x\n", hr);
 +
 +    return hr;
 +}
Simple merge
index c337e42,0000000..9ed181b
mode 100644,000000..100644
--- /dev/null
@@@ -1,817 -1,0 +1,817 @@@
-     LPITEMIDLIST *ppidl,
 +/*
 + * Fonts folder
 + *
 + * Copyright 2008       Johannes Anderwald <johannes.anderwald@reactos.org>
 + * Copyright 2009       Andrew Hill
 + *
 + * 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);
 +
 +/*
 +This folder should not exist. It is just a file system folder... The \windows\fonts
 +directory contains a hidden desktop.ini with a UIHandler entry that specifies a class
 +that lives in fontext.dll. The UI handler creates a custom view for the folder, which
 +is what we normally see. However, the folder is a perfectly normal CFSFolder.
 +*/
 +
 +/***********************************************************************
 +*   IShellFolder implementation
 +*/
 +
 +class CDesktopFolderEnumZ: public IEnumIDListImpl
 +{
 +    public:
 +        CDesktopFolderEnumZ();
 +        ~CDesktopFolderEnumZ();
 +        HRESULT WINAPI Initialize(DWORD dwFlags);
 +        BOOL CreateFontsEnumList(DWORD dwFlags);
 +
 +        BEGIN_COM_MAP(CDesktopFolderEnumZ)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +static shvheader FontsSFHeader[] = {
 +    {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN_FONTTYPE , SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN12, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}
 +};
 +
 +#define COLUMN_NAME     0
 +#define COLUMN_TYPE     1
 +#define COLUMN_SIZE     2
 +#define COLUMN_FILENAME 3
 +
 +#define FontsSHELLVIEWCOLUMNS (4)
 +
 +CDesktopFolderEnumZ::CDesktopFolderEnumZ()
 +{
 +}
 +
 +CDesktopFolderEnumZ::~CDesktopFolderEnumZ()
 +{
 +}
 +
 +HRESULT WINAPI CDesktopFolderEnumZ::Initialize(DWORD dwFlags)
 +{
 +    if (CreateFontsEnumList(dwFlags) == FALSE)
 +        return E_FAIL;
 +    return S_OK;
 +}
 +
 +static LPITEMIDLIST _ILCreateFontItem(LPWSTR pszFont, LPWSTR pszFile)
 +{
 +    PIDLDATA tmp;
 +    LPITEMIDLIST pidl;
 +    PIDLFontStruct * p;
 +    int size0 = (char*)&tmp.u.cfont.szName - (char*)&tmp.u.cfont;
 +    int size = size0;
 +
 +    tmp.type = 0x00;
 +    tmp.u.cfont.dummy = 0xFF;
 +    tmp.u.cfont.offsFile = wcslen(pszFont) + 1;
 +
 +    size += (tmp.u.cfont.offsFile + wcslen(pszFile) + 1) * sizeof(WCHAR);
 +
 +    pidl = (LPITEMIDLIST)SHAlloc(size + 4);
 +    if (!pidl)
 +        return pidl;
 +
 +    pidl->mkid.cb = size + 2;
 +    memcpy(pidl->mkid.abID, &tmp, 2 + size0);
 +
 +    p = &((PIDLDATA*)pidl->mkid.abID)->u.cfont;
 +    wcscpy(p->szName, pszFont);
 +    wcscpy(p->szName + tmp.u.cfont.offsFile, pszFile);
 +
 +    *(WORD*)((char*)pidl + (size + 2)) = 0;
 +    return pidl;
 +}
 +
 +static PIDLFontStruct * _ILGetFontStruct(LPCITEMIDLIST pidl)
 +{
 +    LPPIDLDATA pdata = _ILGetDataPointer(pidl);
 +
 +    if (pdata && pdata->type == 0x00)
 +        return (PIDLFontStruct*) & (pdata->u.cfont);
 +
 +    return NULL;
 +}
 +
 +/**************************************************************************
 + *  CDesktopFolderEnumZ::CreateFontsEnumList()
 + */
 +BOOL CDesktopFolderEnumZ::CreateFontsEnumList(DWORD dwFlags)
 +{
 +    WCHAR szPath[MAX_PATH];
 +    WCHAR szName[LF_FACESIZE+20];
 +    WCHAR szFile[MAX_PATH];
 +    LPWSTR pszPath;
 +    UINT Length;
 +    LONG ret;
 +    DWORD dwType, dwName, dwFile, dwIndex;
 +    LPITEMIDLIST pidl;
 +    HKEY hKey;
 +
 +    if (dwFlags & SHCONTF_NONFOLDERS)
 +    {
 +        if (!SHGetSpecialFolderPathW(NULL, szPath, CSIDL_FONTS, FALSE))
 +            return FALSE;
 +
 +        pszPath = PathAddBackslashW(szPath);
 +        if (!pszPath)
 +            return FALSE;
 +        if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
 +            return FALSE;
 +
 +        Length = pszPath - szPath;
 +        dwIndex = 0;
 +        do
 +        {
 +            dwName = sizeof(szName) / sizeof(WCHAR);
 +            dwFile = sizeof(szFile) / sizeof(WCHAR);
 +            ret = RegEnumValueW(hKey, dwIndex++, szName, &dwName, NULL, &dwType, (LPBYTE)szFile, &dwFile);
 +            if (ret == ERROR_SUCCESS)
 +            {
 +                szFile[(sizeof(szFile)/sizeof(WCHAR))-1] = L'\0';
 +                if (dwType == REG_SZ && wcslen(szFile) + Length + 1 < (sizeof(szPath) / sizeof(WCHAR)))
 +                {
 +                    wcscpy(&szPath[Length], szFile);
 +                    pidl = _ILCreateFontItem(szName, szPath);
 +                    TRACE("pidl %p name %s path %s\n", pidl, debugstr_w(szName), debugstr_w(szPath));
 +                    if (pidl)
 +                    {
 +                        if (!AddToEnumList(pidl))
 +                            SHFree(pidl);
 +                    }
 +                }
 +            }
 +        } while(ret != ERROR_NO_MORE_ITEMS);
 +        RegCloseKey(hKey);
 +
 +    }
 +    return TRUE;
 +}
 +
 +CFontsFolder::CFontsFolder()
 +{
 +    pidlRoot = NULL;
 +    apidl = NULL;
 +}
 +
 +CFontsFolder::~CFontsFolder()
 +{
 +    TRACE("-- destroying IShellFolder(%p)\n", this);
 +    SHFree(pidlRoot);
 +}
 +
 +HRESULT WINAPI CFontsFolder::FinalConstruct()
 +{
 +    pidlRoot = _ILCreateFont();    /* my qualified pidl */
 +    if (pidlRoot == NULL)
 +        return E_OUTOFMEMORY;
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*    CFontsFolder::ParseDisplayName
 +*/
 +HRESULT WINAPI CFontsFolder::ParseDisplayName(
 +    HWND hwndOwner,
 +    LPBC pbcReserved,
 +    LPOLESTR lpszDisplayName,
 +    DWORD *pchEaten,
- HRESULT WINAPI CFontsFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++    PIDLIST_RELATIVE *ppidl,
 +    DWORD * pdwAttributes)
 +{
 +    HRESULT hr = E_UNEXPECTED;
 +
 +    TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
 +           hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName),
 +           pchEaten, ppidl, pdwAttributes);
 +
 +    *ppidl = 0;
 +    if (pchEaten)
 +        *pchEaten = 0;        /* strange but like the original */
 +
 +    TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*        CFontsFolder::EnumObjects
 +*/
 +HRESULT WINAPI CFontsFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
 +{
 +    CComObject<CDesktopFolderEnumZ>            *theEnumerator;
 +    CComPtr<IEnumIDList>                    result;
 +    HRESULT                                    hResult;
 +
 +    TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +    *ppEnumIDList = NULL;
 +    ATLTRY (theEnumerator = new CComObject<CDesktopFolderEnumZ>);
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
 +    if (FAILED (hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +    hResult = theEnumerator->Initialize (dwFlags);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach ();
 +
 +    TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*        CFontsFolder::BindToObject
 +*/
- HRESULT WINAPI CFontsFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++HRESULT WINAPI CFontsFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this,
 +           pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    return SHELL32_BindToChild (pidlRoot, NULL, pidl, riid, ppvOut);
 +}
 +
 +/**************************************************************************
 +*    CFontsFolder::BindToStorage
 +*/
- HRESULT WINAPI CFontsFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++HRESULT WINAPI CFontsFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
 +           pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 +*     CFontsFolder::CompareIDs
 +*/
 +
- HRESULT WINAPI CFontsFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl, DWORD *rgfInOut)
++HRESULT WINAPI CFontsFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs (this, lParam, pidl1, pidl2);
 +    TRACE ("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 +*    CFontsFolder::CreateViewObject
 +*/
 +HRESULT WINAPI CFontsFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
 +{
 +    CComPtr<IShellView>                    pShellView;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(hwnd=%p,%s,%p)\n", this,
 +           hwndOwner, shdebugstr_guid (&riid), ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IDropTarget))
 +    {
 +        WARN ("IDropTarget not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID (riid, IID_IContextMenu))
 +    {
 +        WARN ("IContextMenu not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID (riid, IID_IShellView))
 +    {
 +        hr = IShellView_Constructor (this, &pShellView);
 +        if (pShellView)
 +            hr = pShellView->QueryInterface(riid, ppvOut);
 +    }
 +    TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*  CFontsFolder::GetAttributesOf
 +*/
-     UINT cidl, LPCITEMIDLIST *apidl,
++HRESULT WINAPI CFontsFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
 +{
 +    HRESULT hr = S_OK;
 +
 +    TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", this,
 +           cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
 +
 +    if (!rgfInOut)
 +        return E_INVALIDARG;
 +    if (cidl && !apidl)
 +        return E_INVALIDARG;
 +
 +    if (*rgfInOut == 0)
 +        *rgfInOut = ~0;
 +
 +    if (cidl == 0)
 +    {
 +        CComPtr<IShellFolder>            psfParent;
 +        LPCITEMIDLIST rpidl = NULL;
 +
 +        hr = SHBindToParent(pidlRoot, IID_PPV_ARG(IShellFolder, &psfParent), (LPCITEMIDLIST *)&rpidl);
 +        if (SUCCEEDED(hr))
 +            SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut);
 +    }
 +    else
 +    {
 +        while (cidl > 0 && *apidl)
 +        {
 +            pdump (*apidl);
 +            SHELL32_GetItemAttributes (this, *apidl, rgfInOut);
 +            apidl++;
 +            cidl--;
 +        }
 +    }
 +
 +    /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE ("-- result=0x%08x\n", *rgfInOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*    CFontsFolder::GetUIObjectOf
 +*
 +* PARAMETERS
 +*  hwndOwner [in]  Parent window for any output
 +*  cidl      [in]  array size
 +*  apidl     [in]  simple pidl array
 +*  riid      [in]  Requested Interface
 +*  prgfInOut [   ] reserved
 +*  ppvObject [out] Resulting Interface
 +*
 +*/
 +HRESULT WINAPI CFontsFolder::GetUIObjectOf(
 +    HWND hwndOwner,
- HRESULT WINAPI CFontsFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
++    UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
 +    REFIID riid, UINT *prgfInOut, LPVOID *ppvOut)
 +{
 +    LPITEMIDLIST pidl;
 +    CComPtr<IUnknown>                    pObj;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
 +           hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
 +    {
 +        pObj = (IContextMenu *)this;
 +        this->apidl = apidl[0];
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
 +    {
 +        hr = IDataObject_Constructor (hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj);
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconA_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconW_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
 +    {
 +        IDropTarget * pDt = NULL;
 +        hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
 +        pObj = pDt;
 +    }
 +    else
 +        hr = E_NOINTERFACE;
 +
 +    if (SUCCEEDED(hr) && !pObj)
 +        hr = E_OUTOFMEMORY;
 +
 +    *ppvOut = pObj.Detach();
 +    TRACE ("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*    CFontsFolder::GetDisplayNameOf
 +*
 +*/
- HRESULT WINAPI CFontsFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,    /*simple pidl */
-                                        LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
++HRESULT WINAPI CFontsFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 +{
 +    PIDLFontStruct *pFont;
 +
 +    TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump (pidl);
 +
 +    if (!strRet)
 +        return E_INVALIDARG;
 +
 +    pFont = _ILGetFontStruct(pidl);
 +    if (pFont)
 +    {
 +        strRet->pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(pFont->szName) + 1) * sizeof(WCHAR));
 +        if (!strRet->pOleStr)
 +            return E_OUTOFMEMORY;
 +
 +        wcscpy(strRet->pOleStr, pFont->szName);
 +        strRet->uType = STRRET_WSTR;
 +    }
 +    else if (!pidl->mkid.cb)
 +    {
 +        WCHAR wszPath[MAX_PATH];
 +
 +        if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
 +                (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING))
 +        {
 +            if (!SHGetSpecialFolderPathW(NULL, wszPath, CSIDL_FONTS, FALSE))
 +                return E_FAIL;
 +        }
 +        else if (!HCR_GetClassNameW(CLSID_FontsFolderShortcut, wszPath, MAX_PATH))
 +            return E_FAIL;
 +
 +        strRet->pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(wszPath) + 1) * sizeof(WCHAR));
 +        if (!strRet->pOleStr)
 +            return E_OUTOFMEMORY;
 +
 +        wcscpy(strRet->pOleStr, wszPath);
 +        strRet->uType = STRRET_WSTR;
 +    }
 +    else
 +        return E_INVALIDARG;
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*  CFontsFolder::SetNameOf
 +*  Changes the name of a file object or subfolder, possibly changing its item
 +*  identifier in the process.
 +*
 +* PARAMETERS
 +*  hwndOwner [in]  Owner window for output
 +*  pidl      [in]  simple pidl of item to change
 +*  lpszName  [in]  the items new display name
 +*  dwFlags   [in]  SHGNO formatting flags
 +*  ppidlOut  [out] simple pidl returned
 +*/
- HRESULT WINAPI CFontsFolder::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
++HRESULT WINAPI CFontsFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,    /*simple pidl */
++                                       LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
 +{
 +    FIXME ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this,
 +           hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CFontsFolder::GetDefaultSearchGUID(GUID *pguid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CFontsFolder::EnumSearches(IEnumExtraSearch **ppenum)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CFontsFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (pSort)
 +        *pSort = 0;
 +    if (pDisplay)
 +        *pDisplay = 0;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CFontsFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!pcsFlags || iColumn >= FontsSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +    *pcsFlags = FontsSFHeader[iColumn].pcsFlags;
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CFontsFolder::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
++HRESULT WINAPI CFontsFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
++HRESULT WINAPI CFontsFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
 +{
 +    WCHAR buffer[MAX_PATH] = {0};
 +    HRESULT hr = E_FAIL;
 +    PIDLFontStruct * pfont;
 +    HANDLE hFile;
 +    LARGE_INTEGER FileSize;
 +    SHFILEINFOW fi;
 +
 +    TRACE("(%p, %p, %d, %p)\n", this, pidl, iColumn, psd);
 +
 +    if (iColumn >= FontsSHELLVIEWCOLUMNS)
 +        return E_FAIL;
 +
 +    psd->fmt = FontsSFHeader[iColumn].fmt;
 +    psd->cxChar = FontsSFHeader[iColumn].cxChar;
 +    if (pidl == NULL)
 +    {
 +        psd->str.uType = STRRET_WSTR;
 +        if (LoadStringW(shell32_hInstance, FontsSFHeader[iColumn].colnameid, buffer, MAX_PATH))
 +            hr = SHStrDupW(buffer, &psd->str.pOleStr);
 +
 +        return hr;
 +    }
 +
 +    if (iColumn == COLUMN_NAME)
 +    {
 +        psd->str.uType = STRRET_WSTR;
 +        return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
 +    }
 +
 +    psd->str.uType = STRRET_CSTR;
 +    psd->str.cStr[0] = '\0';
 +
 +    switch(iColumn)
 +    {
 +        case COLUMN_TYPE:
 +            pfont = _ILGetFontStruct(pidl);
 +            if (pfont)
 +            {
 +                if (SHGetFileInfoW(pfont->szName + pfont->offsFile, 0, &fi, sizeof(fi), SHGFI_TYPENAME))
 +                {
 +                    psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(fi.szTypeName) + 1) * sizeof(WCHAR));
 +                    if (!psd->str.pOleStr)
 +                        return E_OUTOFMEMORY;
 +                    wcscpy(psd->str.pOleStr, fi.szTypeName);
 +                    psd->str.uType = STRRET_WSTR;
 +                    return S_OK;
 +                }
 +            }
 +            break;
 +        case COLUMN_SIZE:
 +            pfont = _ILGetFontStruct(pidl);
 +            if (pfont)
 +            {
 +                hFile = CreateFileW(pfont->szName + pfont->offsFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 +                if (hFile != INVALID_HANDLE_VALUE)
 +                {
 +                    if (GetFileSizeEx(hFile, &FileSize))
 +                    {
 +                        if (StrFormatByteSizeW(FileSize.QuadPart, buffer, sizeof(buffer) / sizeof(WCHAR)))
 +                        {
 +                            psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc(wcslen(buffer) + 1);
 +                            if (!psd->str.pOleStr)
 +                            {
 +                                CloseHandle(hFile);
 +                                return E_OUTOFMEMORY;
 +                            }
 +                            wcscpy(psd->str.pOleStr, buffer);
 +                            psd->str.uType = STRRET_WSTR;
 +                            CloseHandle(hFile);
 +                            return S_OK;
 +                        }
 +                    }
 +                    CloseHandle(hFile);
 +                }
 +            }
 +            break;
 +        case COLUMN_FILENAME:
 +            pfont = _ILGetFontStruct(pidl);
 +            if (pfont)
 +            {
 +                psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(pfont->szName + pfont->offsFile) + 1) * sizeof(WCHAR));
 +                if (psd->str.pOleStr)
 +                {
 +                    psd->str.uType = STRRET_WSTR;
 +                    wcscpy(psd->str.pOleStr, pfont->szName + pfont->offsFile);
 +                    return S_OK;
 +                }
 +                else
 +                    return E_OUTOFMEMORY;
 +            }
 +            break;
 +    }
 +
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CFontsFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
 +{
 +    FIXME ("(%p)\n", this);
 +
 +    return E_NOTIMPL;
 +}
 +
 +/************************************************************************
 + *    CFontsFolder::GetClassID
 + */
 +HRESULT WINAPI CFontsFolder::GetClassID(CLSID *lpClassId)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!lpClassId)
 +        return E_POINTER;
 +
 +    *lpClassId = CLSID_FontsFolderShortcut;
 +
 +    return S_OK;
 +}
 +
 +/************************************************************************
 + *    CFontsFolder::Initialize
 + *
 + * NOTES: it makes no sense to change the pidl
 + */
 +HRESULT WINAPI CFontsFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 + *    CFontsFolder::GetCurFolder
 + */
 +HRESULT WINAPI CFontsFolder::GetCurFolder(LPITEMIDLIST *pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    if (!pidl)
 +        return E_POINTER;
 +
 +    *pidl = ILClone(pidlRoot);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +* IContextMenu2 Implementation
 +*/
 +
 +/**************************************************************************
 +* CFontsFolder::QueryContextMenu()
 +*/
 +HRESULT WINAPI CFontsFolder::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
 +{
 +    WCHAR szBuffer[30] = {0};
 +    ULONG Count = 1;
 +
 +    TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
 +          this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
 +
 +    if (LoadStringW(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT);
 +        Count++;
 +    }
 +
 +    if (LoadStringW(shell32_hInstance, IDS_PRINT_VERB, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
 +    }
 +
 +    if (LoadStringW(shell32_hInstance, IDS_COPY, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
 +    }
 +
 +    if (LoadStringW(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED);
 +    }
 +
 +    if (LoadStringW(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED);
 +    }
 +
 +    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count);
 +}
 +
 +/**************************************************************************
 +* CFontsFolder::InvokeCommand()
 +*/
 +HRESULT WINAPI CFontsFolder::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    SHELLEXECUTEINFOW sei;
 +    PIDLFontStruct * pfont;
 +    SHFILEOPSTRUCTW op;
 +
 +    TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
 +
 +    if (lpcmi->lpVerb == MAKEINTRESOURCEA(1) || lpcmi->lpVerb == MAKEINTRESOURCEA(2) || lpcmi->lpVerb == MAKEINTRESOURCEA(7))
 +    {
 +        ZeroMemory(&sei, sizeof(sei));
 +        sei.cbSize = sizeof(sei);
 +        sei.hwnd = lpcmi->hwnd;
 +        sei.nShow = SW_SHOWNORMAL;
 +        if (lpcmi->lpVerb == MAKEINTRESOURCEA(1))
 +            sei.lpVerb = L"open";
 +        else if (lpcmi->lpVerb == MAKEINTRESOURCEA(2))
 +            sei.lpVerb = L"print";
 +        else if (lpcmi->lpVerb == MAKEINTRESOURCEA(7))
 +            sei.lpVerb = L"properties";
 +
 +        pfont = _ILGetFontStruct(apidl);
 +        sei.lpFile = pfont->szName + pfont->offsFile;
 +
 +        if (ShellExecuteExW(&sei) == FALSE)
 +            return E_FAIL;
 +    }
 +    else if (lpcmi->lpVerb == MAKEINTRESOURCEA(4))
 +    {
 +        FIXME("implement font copying\n");
 +        return E_NOTIMPL;
 +    }
 +    else if (lpcmi->lpVerb == MAKEINTRESOURCEA(6))
 +    {
 +        ZeroMemory(&op, sizeof(op));
 +        op.hwnd = lpcmi->hwnd;
 +        op.wFunc = FO_DELETE;
 +        op.fFlags = FOF_ALLOWUNDO;
 +        pfont = _ILGetFontStruct(apidl);
 +        op.pFrom = pfont->szName + pfont->offsFile;
 +        SHFileOperationW(&op);
 +    }
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *  CFontsFolder::GetCommandString()
 + *
 + */
 +HRESULT WINAPI CFontsFolder::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
 +{
 +    TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
 +
 +    return E_FAIL;
 +}
 +
 +/**************************************************************************
 +* CFontsFolder::HandleMenuMsg()
 +*/
 +HRESULT WINAPI CFontsFolder::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
 +{
 +    TRACE("(%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
 +
 +    return E_NOTIMPL;
 +}
Simple merge
index 9ffd0b9,0000000..fd75611
mode 100644,000000..100644
--- /dev/null
@@@ -1,1875 -1,0 +1,1878 @@@
-         DWORD *pchEaten, LPITEMIDLIST *ppidl,
 +
 +/*
 + * file system folder
 + *
 + * Copyright 1997             Marcus Meissner
 + * Copyright 1998, 1999, 2002 Juergen Schmied
 + *
 + * 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);
 +
 +/*
 +CFileSysEnum should do an initial FindFirstFile and do a FindNextFile as each file is
 +returned by Next. When the enumerator is created, it can do numerous additional operations
 +including formatting a drive, reconnecting a network share drive, and requesting a disk
 +be inserted in a removable drive.
 +*/
 +
 +/***********************************************************************
 +*   IShellFolder implementation
 +*/
 +
 +class CFileSysEnum :
 +    public IEnumIDListImpl
 +{
 +    private:
 +    public:
 +        CFileSysEnum();
 +        ~CFileSysEnum();
 +        HRESULT WINAPI Initialize(LPWSTR sPathTarget, DWORD dwFlags);
 +
 +        BEGIN_COM_MAP(CFileSysEnum)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +CFileSysEnum::CFileSysEnum()
 +{
 +}
 +
 +CFileSysEnum::~CFileSysEnum()
 +{
 +}
 +
 +HRESULT WINAPI CFileSysEnum::Initialize(LPWSTR sPathTarget, DWORD dwFlags)
 +{
 +    return CreateFolderEnumList(sPathTarget, dwFlags);
 +}
 +
 +/**************************************************************************
 +* registers clipboardformat once
 +*/
 +void CFSFolder::SF_RegisterClipFmt()
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!cfShellIDList)
 +        cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
 +}
 +
 +CFSFolder::CFSFolder()
 +{
 +    pclsid = (CLSID *)&CLSID_ShellFSFolder;
 +    sPathTarget = NULL;
 +    pidlRoot = NULL;
 +    cfShellIDList = 0;
 +    SF_RegisterClipFmt();
 +    fAcceptFmt = FALSE;
 +    m_bGroupPolicyActive = 0;
 +}
 +
 +CFSFolder::~CFSFolder()
 +{
 +    TRACE("-- destroying IShellFolder(%p)\n", this);
 +
 +    SHFree(pidlRoot);
 +    SHFree(sPathTarget);
 +}
 +
 +
 +static const shvheader GenericSFHeader[] = {
 +    {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
 +    {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
 +};
 +
 +#define GENERICSHELLVIEWCOLUMNS 5
 +
 +/**************************************************************************
 + *  SHELL32_CreatePidlFromBindCtx  [internal]
 + *
 + *  If the caller bound File System Bind Data, assume it is the
 + *   find data for the path.
 + *  This allows binding of paths that don't exist.
 + */
 +LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path)
 +{
 +    IFileSystemBindData *fsbd = NULL;
 +    LPITEMIDLIST pidl = NULL;
 +    IUnknown *param = NULL;
 +    WIN32_FIND_DATAW wfd;
 +    HRESULT r;
 +
 +    TRACE("%p %s\n", pbc, debugstr_w(path));
 +
 +    if (!pbc)
 +        return NULL;
 +
 +    /* see if the caller bound File System Bind Data */
 +    r = pbc->GetObjectParam((LPOLESTR)STR_FILE_SYS_BIND_DATA, &param);
 +    if (FAILED(r))
 +        return NULL;
 +
 +    r = param->QueryInterface(IID_PPV_ARG(IFileSystemBindData,&fsbd));
 +    if (SUCCEEDED(r))
 +    {
 +        r = fsbd->GetFindData(&wfd);
 +        if (SUCCEEDED(r))
 +        {
 +            lstrcpynW(&wfd.cFileName[0], path, MAX_PATH);
 +            pidl = _ILCreateFromFindDataW(&wfd);
 +        }
 +        fsbd->Release();
 +    }
 +
 +    return pidl;
 +}
 +
 +/**************************************************************************
 +* CFSFolder::ParseDisplayName {SHELL32}
 +*
 +* Parse a display name.
 +*
 +* PARAMS
 +*  hwndOwner       [in]  Parent window for any message's
 +*  pbc             [in]  optional FileSystemBindData context
 +*  lpszDisplayName [in]  Unicode displayname.
 +*  pchEaten        [out] (unicode) characters processed
 +*  ppidl           [out] complex pidl to item
 +*  pdwAttributes   [out] items attributes
 +*
 +* NOTES
 +*  Every folder tries to parse only its own (the leftmost) pidl and creates a
 +*  subfolder to evaluate the remaining parts.
 +*  Now we can parse into namespaces implemented by shell extensions
 +*
 +*  Behaviour on win98: lpszDisplayName=NULL -> crash
 +*                      lpszDisplayName="" -> returns mycoputer-pidl
 +*
 +* FIXME
 +*    pdwAttributes is not set
 +*    pchEaten is not set like in windows
 +*/
 +HRESULT WINAPI CFSFolder::ParseDisplayName(HWND hwndOwner,
 +        LPBC pbc,
 +        LPOLESTR lpszDisplayName,
-     LPCITEMIDLIST pidl,
++        DWORD *pchEaten, PIDLIST_RELATIVE *ppidl,
 +        DWORD *pdwAttributes)
 +{
 +    HRESULT hr = E_INVALIDARG;
 +    LPCWSTR szNext = NULL;
 +    WCHAR szElement[MAX_PATH];
 +    WCHAR szPath[MAX_PATH];
 +    LPITEMIDLIST pidlTemp = NULL;
 +    DWORD len;
 +
 +    TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
 +           this, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
 +           pchEaten, ppidl, pdwAttributes);
 +
 +    if (!ppidl)
 +        return E_INVALIDARG;
 +
 +    if (!lpszDisplayName)
 +    {
 +        *ppidl = NULL;
 +        return E_INVALIDARG;
 +    }
 +
 +    *ppidl = NULL;
 +
 +    if (pchEaten)
 +        *pchEaten = 0; /* strange but like the original */
 +
 +    if (*lpszDisplayName)
 +    {
 +        /* get the next element */
 +        szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
 +
 +        pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, szElement);
 +        if (pidlTemp != NULL)
 +        {
 +            hr = S_OK;
 +        }
 +        else
 +        {
 +            /* build the full pathname to the element */
 +            lstrcpynW(szPath, sPathTarget, MAX_PATH - 1);
 +            PathAddBackslashW(szPath);
 +            len = wcslen(szPath);
 +            lstrcpynW(szPath + len, szElement, MAX_PATH - len);
 +
 +            /* get the pidl */
 +            hr = _ILCreateFromPathW(szPath, &pidlTemp);
 +        }
 +
 +        if (SUCCEEDED(hr))
 +        {
 +            if (szNext && *szNext)
 +            {
 +                /* try to analyse the next element */
 +                hr = SHELL32_ParseNextElement(this, hwndOwner, pbc,
 +                                              &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
 +            }
 +            else
 +            {
 +                /* it's the last element */
 +                if (pdwAttributes && *pdwAttributes)
 +                    hr = SHELL32_GetItemAttributes(this, pidlTemp, pdwAttributes);
 +            }
 +        }
 +    }
 +
 +    if (SUCCEEDED(hr))
 +        *ppidl = pidlTemp;
 +    else
 +        *ppidl = NULL;
 +
 +    TRACE("(%p)->(-- pidl=%p ret=0x%08x)\n", this, ppidl ? *ppidl : 0, hr);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 +* CFSFolder::EnumObjects
 +* PARAMETERS
 +*  HWND          hwndOwner,    //[in ] Parent Window
 +*  DWORD         grfFlags,     //[in ] SHCONTF enumeration mask
 +*  LPENUMIDLIST* ppenumIDList  //[out] IEnumIDList interface
 +*/
 +HRESULT WINAPI CFSFolder::EnumObjects(
 +    HWND hwndOwner,
 +    DWORD dwFlags,
 +    LPENUMIDLIST *ppEnumIDList)
 +{
 +    CComObject<CFileSysEnum> *theEnumerator;
 +    CComPtr<IEnumIDList>      result;
 +    HRESULT                   hResult;
 +
 +    TRACE("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +    *ppEnumIDList = NULL;
 +    ATLTRY (theEnumerator = new CComObject<CFileSysEnum>);
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
 +    if (FAILED(hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +    hResult = theEnumerator->Initialize (sPathTarget, dwFlags);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach();
 +
 +    TRACE("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +* CFSFolder::BindToObject
 +* PARAMETERS
 +*  LPCITEMIDLIST pidl,       //[in ] relative pidl to open
 +*  LPBC          pbc,        //[in ] optional FileSystemBindData context
 +*  REFIID        riid,       //[in ] Initial Interface
 +*  LPVOID*       ppvObject   //[out] Interface*
 +*/
 +HRESULT WINAPI CFSFolder::BindToObject(
-     LPCITEMIDLIST pidl,
++    PCUIDLIST_RELATIVE pidl,
 +    LPBC pbc,
 +    REFIID riid,
 +    LPVOID * ppvOut)
 +{
 +    TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl, pbc,
 +          shdebugstr_guid(&riid), ppvOut);
 +
 +    return SHELL32_BindToChild(pidlRoot, sPathTarget, pidl, riid, ppvOut);
 +}
 +
 +/**************************************************************************
 +*  CFSFolder::BindToStorage
 +* PARAMETERS
 +*  LPCITEMIDLIST pidl,       //[in ] complex pidl to store
 +*  LPBC          pbc,        //[in ] reserved
 +*  REFIID        riid,       //[in ] Initial storage interface
 +*  LPVOID*       ppvObject   //[out] Interface* returned
 +*/
 +HRESULT WINAPI CFSFolder::BindToStorage(
-                                      LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++    PCUIDLIST_RELATIVE pidl,
 +    LPBC pbcReserved,
 +    REFIID riid,
 +    LPVOID *ppvOut)
 +{
 +    FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl, pbcReserved,
 +          shdebugstr_guid (&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 +*  CFSFolder::CompareIDs
 +*/
 +
 +HRESULT WINAPI CFSFolder::CompareIDs(LPARAM lParam,
-         LPCITEMIDLIST * apidl, DWORD * rgfInOut)
++                                     PCUIDLIST_RELATIVE pidl1,
++                                     PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs(this, lParam, pidl1, pidl2);
 +    TRACE("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 +* CFSFolder::CreateViewObject
 +*/
 +HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner,
 +        REFIID riid, LPVOID * ppvOut)
 +{
 +    CComPtr<IShellView> pShellView;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner, shdebugstr_guid (&riid),
 +           ppvOut);
 +
 +    if (ppvOut)
 +    {
 +        *ppvOut = NULL;
 +
 +        if (IsEqualIID (riid, IID_IDropTarget))
 +            hr = this->QueryInterface (IID_IDropTarget, ppvOut);
 +        else if (IsEqualIID (riid, IID_IContextMenu))
 +        {
 +            FIXME ("IContextMenu not implemented\n");
 +            hr = E_NOTIMPL;
 +        }
 +        else if (IsEqualIID (riid, IID_IShellView))
 +        {
 +            hr = IShellView_Constructor ((IShellFolder *)this, &pShellView);
 +            if (pShellView)
 +            {
 +                hr = pShellView->QueryInterface(riid, ppvOut);
 +            }
 +        }
 +    }
 +    TRACE("-- (%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*  CFSFolder::GetAttributesOf
 +*
 +* PARAMETERS
 +*  UINT            cidl,     //[in ] num elements in pidl array
 +*  LPCITEMIDLIST*  apidl,    //[in ] simple pidl array
 +*  ULONG*          rgfInOut) //[out] result array
 +*
 +*/
 +HRESULT WINAPI CFSFolder::GetAttributesOf(UINT cidl,
-                                         UINT cidl, LPCITEMIDLIST * apidl, REFIID riid,
-                                         UINT * prgfInOut, LPVOID * ppvOut)
++        PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
 +{
 +    HRESULT hr = S_OK;
 +
 +    TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", this, cidl, apidl,
 +          rgfInOut, rgfInOut ? *rgfInOut : 0);
 +
 +    if (!rgfInOut)
 +        return E_INVALIDARG;
 +    if (cidl && !apidl)
 +        return E_INVALIDARG;
 +
 +    if (*rgfInOut == 0)
 +        *rgfInOut = ~0;
 +
 +    if(cidl == 0)
 +    {
 +        IShellFolder *psfParent = NULL;
 +        LPCITEMIDLIST rpidl = NULL;
 +
 +        hr = SHBindToParent(pidlRoot, IID_PPV_ARG(IShellFolder, &psfParent), &rpidl);
 +        if(SUCCEEDED(hr))
 +        {
 +            SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut);
 +            psfParent->Release();
 +        }
 +    }
 +    else
 +    {
 +        while (cidl > 0 && *apidl)
 +        {
 +            pdump(*apidl);
 +            SHELL32_GetItemAttributes(this, *apidl, rgfInOut);
 +            apidl++;
 +            cidl--;
 +        }
 +    }
 +    /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE("-- result=0x%08x\n", *rgfInOut);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*  CFSFolder::GetUIObjectOf
 +*
 +* PARAMETERS
 +*  HWND           hwndOwner, //[in ] Parent window for any output
 +*  UINT           cidl,      //[in ] array size
 +*  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
 +*  REFIID         riid,      //[in ] Requested Interface
 +*  UINT*          prgfInOut, //[   ] reserved
 +*  LPVOID*        ppvObject) //[out] Resulting Interface
 +*
 +* NOTES
 +*  This function gets asked to return "view objects" for one or more (multiple
 +*  select) items:
 +*  The viewobject typically is an COM object with one of the following
 +*  interfaces:
 +*  IExtractIcon,IDataObject,IContextMenu
 +*  In order to support icon positions in the default Listview your DataObject
 +*  must implement the SetData method (in addition to GetData :) - the shell
 +*  passes a barely documented "Icon positions" structure to SetData when the
 +*  drag starts, and GetData's it if the drop is in another explorer window that
 +*  needs the positions.
 +*/
 +HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner,
- HRESULT WINAPI CFSFolder::GetDisplayNameOf(LPCITEMIDLIST pidl,
++                                        UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
++                                        REFIID riid, UINT * prgfInOut,
++                                        LPVOID * ppvOut)
 +{
 +    LPITEMIDLIST pidl;
 +    IUnknown *pObj = NULL;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
 +           this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
 +
 +    if (ppvOut)
 +    {
 +        *ppvOut = NULL;
 +
 +        if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1))
 +        {
 +            IContextMenu  * pCm = NULL;
 +            hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, 0, NULL, &pCm);
 +            pObj = pCm;
 +        }
 +        else if (IsEqualIID (riid, IID_IDataObject))
 +        {
 +            if (cidl >= 1) 
 +            {
 +                hr = IDataObject_Constructor (hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj);
 +            }
 +            else
 +            {
 +                hr = IDataObject_Constructor (hwndOwner, pidlRoot, (LPCITEMIDLIST*)&pidlRoot, 1, (IDataObject **)&pObj);
 +            }
 +        }
 +        else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
 +        {
 +            pidl = ILCombine (pidlRoot, apidl[0]);
 +            pObj = IExtractIconA_Constructor (pidl);
 +            SHFree (pidl);
 +            hr = S_OK;
 +        }
 +        else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
 +        {
 +            pidl = ILCombine (pidlRoot, apidl[0]);
 +            pObj = IExtractIconW_Constructor (pidl);
 +            SHFree (pidl);
 +            hr = S_OK;
 +        }
 +        else if (IsEqualIID (riid, IID_IDropTarget))
 +        {
 +            /* only interested in attempting to bind to shell folders, not files (except exe), so if we fail, rebind to root */
 +            if (cidl != 1 || FAILED(hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj)))
 +            {
 +                IDropTarget * pDt = NULL;
 +                hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
 +                pObj = pDt;
 +            }
 +        }
 +        else if ((IsEqualIID(riid, IID_IShellLinkW) ||
 +            IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
 +        {
 +            pidl = ILCombine (pidlRoot, apidl[0]);
 +            hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
 +            SHFree (pidl);
 +        }
 +        else
 +            hr = E_NOINTERFACE;
 +
 +        if (SUCCEEDED(hr) && !pObj)
 +            hr = E_OUTOFMEMORY;
 +
 +        *ppvOut = pObj;
 +    }
 +    TRACE("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
 +static const WCHAR AdvancedW[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
 +static const WCHAR HideFileExtW[] = L"HideFileExt";
 +static const WCHAR NeverShowExtW[] = L"NeverShowExt";
 +
 +/******************************************************************************
 + * SHELL_FS_HideExtension [Internal]
 + *
 + * Query the registry if the filename extension of a given path should be
 + * hidden.
 + *
 + * PARAMS
 + *  szPath [I] Relative or absolute path of a file
 + *
 + * RETURNS
 + *  TRUE, if the filename's extension should be hidden
 + *  FALSE, otherwise.
 + */
 +BOOL SHELL_FS_HideExtension(LPWSTR szPath)
 +{
 +    HKEY hKey;
 +    DWORD dwData;
 +    DWORD dwDataSize = sizeof (DWORD);
 +    BOOL doHide = FALSE; /* The default value is FALSE (win98 at least) */
 +
 +    if (!RegCreateKeyExW(HKEY_CURRENT_USER, AdvancedW, 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) {
 +        if (!RegQueryValueExW(hKey, HideFileExtW, 0, 0, (LPBYTE) &dwData, &dwDataSize))
 +            doHide = dwData;
 +        RegCloseKey (hKey);
 +    }
 +
 +    if (!doHide) {
 +        LPWSTR ext = PathFindExtensionW(szPath);
 +
 +        if (*ext != '\0') {
 +            WCHAR classname[MAX_PATH];
 +            LONG classlen = sizeof(classname);
 +
 +            if (!RegQueryValueW(HKEY_CLASSES_ROOT, ext, classname, &classlen))
 +                if (!RegOpenKeyW(HKEY_CLASSES_ROOT, classname, &hKey)) {
 +                    if (!RegQueryValueExW(hKey, NeverShowExtW, 0, NULL, NULL, NULL))
 +                        doHide = TRUE;
 +                    RegCloseKey(hKey);
 +                }
 +        }
 +    }
 +    return doHide;
 +}
 +
 +void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags)
 +{
 +    /*FIXME: MSDN also mentions SHGDN_FOREDITING which is not yet handled. */
 +    if (!(dwFlags & SHGDN_FORPARSING) &&
 +        ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL))) {
 +            if (SHELL_FS_HideExtension(szPath) && szPath[0] != '.')
 +                PathRemoveExtensionW(szPath);
 +    }
 +}
 +
 +/**************************************************************************
 +*  CFSFolder::GetDisplayNameOf
 +*  Retrieves the display name for the specified file object or subfolder
 +*
 +* PARAMETERS
 +*  LPCITEMIDLIST pidl,    //[in ] complex pidl to item
 +*  DWORD         dwFlags, //[in ] SHGNO formatting flags
 +*  LPSTRRET      lpName)  //[out] Returned display name
 +*
 +* FIXME
 +*  if the name is in the pidl the ret value should be a STRRET_OFFSET
 +*/
 +
-     LPCITEMIDLIST pidl,
++HRESULT WINAPI CFSFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl,
 +        DWORD dwFlags, LPSTRRET strRet)
 +{
 +    LPWSTR pszPath;
 +
 +    HRESULT hr = S_OK;
 +    int len = 0;
 +
 +    TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump(pidl);
 +
 +    if (!pidl || !strRet)
 +        return E_INVALIDARG;
 +
 +    pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
 +    if (!pszPath)
 +        return E_OUTOFMEMORY;
 +
 +    if (_ILIsDesktop(pidl)) /* empty pidl */
 +    {
 +        if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
 +                (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
 +        {
 +            if (sPathTarget)
 +                lstrcpynW(pszPath, sPathTarget, MAX_PATH);
 +        }
 +        else
 +            hr = E_INVALIDARG; /* pidl has to contain exactly one non null SHITEMID */
 +    }
 +    else if (_ILIsPidlSimple(pidl))
 +    {
 +        if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
 +                (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) &&
 +                sPathTarget)
 +        {
 +            lstrcpynW(pszPath, sPathTarget, MAX_PATH);
 +            PathAddBackslashW(pszPath);
 +            len = wcslen(pszPath);
 +        }
 +        _ILSimpleGetTextW(pidl, pszPath + len, MAX_PATH + 1 - len);
 +        if (!_ILIsFolder(pidl)) SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
 +    } else
 +        hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, pszPath, MAX_PATH);
 +
 +    if (SUCCEEDED(hr)) {
 +        /* Win9x always returns ANSI strings, NT always returns Unicode strings */
 +        if (GetVersion() & 0x80000000)
 +        {
 +            strRet->uType = STRRET_CSTR;
 +            if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->cStr, MAX_PATH,
 +                                     NULL, NULL))
 +                strRet->cStr[0] = '\0';
 +            CoTaskMemFree(pszPath);
 +        }
 +        else
 +        {
 +            strRet->uType = STRRET_WSTR;
 +            strRet->pOleStr = pszPath;
 +        }
 +    } else
 +        CoTaskMemFree(pszPath);
 +
 +    TRACE ("-- (%p)->(%s)\n", this, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr));
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*  CFSFolder::SetNameOf
 +*  Changes the name of a file object or subfolder, possibly changing its item
 +*  identifier in the process.
 +*
 +* PARAMETERS
 +*  HWND          hwndOwner,  //[in ] Owner window for output
 +*  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
 +*  LPCOLESTR     lpszName,   //[in ] the items new display name
 +*  DWORD         dwFlags,    //[in ] SHGNO formatting flags
 +*  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
 +*/
 +HRESULT WINAPI CFSFolder::SetNameOf(
 +    HWND hwndOwner,
-     LPITEMIDLIST * pPidlOut)
++    PCUITEMID_CHILD pidl,
 +    LPCOLESTR lpName,
 +    DWORD dwFlags,
- HRESULT WINAPI CFSFolder::GetDetailsEx(LPCITEMIDLIST pidl,
++    PITEMID_CHILD *pPidlOut)
 +{
 +    WCHAR szSrc[MAX_PATH + 1], szDest[MAX_PATH + 1];
 +    LPWSTR ptr;
 +    BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl));
 +
 +    TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl,
 +           debugstr_w (lpName), dwFlags, pPidlOut);
 +
 +    /* build source path */
 +    lstrcpynW(szSrc, sPathTarget, MAX_PATH);
 +    ptr = PathAddBackslashW (szSrc);
 +    if (ptr)
 +        _ILSimpleGetTextW (pidl, ptr, MAX_PATH + 1 - (ptr - szSrc));
 +
 +    /* build destination path */
 +    if (dwFlags == SHGDN_NORMAL || dwFlags & SHGDN_INFOLDER) {
 +        lstrcpynW(szDest, sPathTarget, MAX_PATH);
 +        ptr = PathAddBackslashW (szDest);
 +        if (ptr)
 +            lstrcpynW(ptr, lpName, MAX_PATH + 1 - (ptr - szDest));
 +    } else
 +        lstrcpynW(szDest, lpName, MAX_PATH);
 +
 +    if(!(dwFlags & SHGDN_FORPARSING) && SHELL_FS_HideExtension(szSrc)) {
 +        WCHAR *ext = PathFindExtensionW(szSrc);
 +        if(*ext != '\0') {
 +            INT len = wcslen(szDest);
 +            lstrcpynW(szDest + len, ext, MAX_PATH - len);
 +        }
 +    }
 +
 +    TRACE ("src=%s dest=%s\n", debugstr_w(szSrc), debugstr_w(szDest));
 +    if (!memcmp(szSrc, szDest, (wcslen(szDest) + 1) * sizeof(WCHAR)))
 +    {
 +        /* src and destination is the same */
 +        HRESULT hr = S_OK;
 +        if (pPidlOut)
 +            hr = _ILCreateFromPathW(szDest, pPidlOut);
 +
 +        return hr;
 +    }
 +
 +
 +    if (MoveFileW (szSrc, szDest))
 +    {
 +        HRESULT hr = S_OK;
 +
 +        if (pPidlOut)
 +            hr = _ILCreateFromPathW(szDest, pPidlOut);
 +
 +        SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM,
 +                        SHCNF_PATHW, szSrc, szDest);
 +
 +        return hr;
 +    }
 +
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CFSFolder::GetDefaultSearchGUID(GUID * pguid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CFSFolder::EnumSearches(IEnumExtraSearch ** ppenum)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CFSFolder::GetDefaultColumn(DWORD dwRes,
 +        ULONG * pSort, ULONG * pDisplay)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (pSort)
 +        *pSort = 0;
 +    if (pDisplay)
 +        *pDisplay = 0;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CFSFolder::GetDefaultColumnState(UINT iColumn,
 +        DWORD * pcsFlags)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +
 +    *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
 +
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CFSFolder::GetDetailsOf(LPCITEMIDLIST pidl,
++HRESULT WINAPI CFSFolder::GetDetailsEx(PCUITEMID_CHILD pidl,
 +                                       const SHCOLUMNID * pscid, VARIANT * pv)
 +{
 +    FIXME ("(%p)\n", this);
 +
 +    return E_NOTIMPL;
 +}
 +
++HRESULT WINAPI CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl,
 +                                       UINT iColumn, SHELLDETAILS * psd)
 +{
 +    HRESULT hr = E_FAIL;
 +
 +    TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
 +
 +    if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +
 +    if (!pidl)
 +    {
 +        /* the header titles */
 +        psd->fmt = GenericSFHeader[iColumn].fmt;
 +        psd->cxChar = GenericSFHeader[iColumn].cxChar;
 +        psd->str.uType = STRRET_CSTR;
 +        LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid,
 +                    psd->str.cStr, MAX_PATH);
 +        return S_OK;
 +    }
 +    else
 +    {
 +        hr = S_OK;
 +        psd->str.uType = STRRET_CSTR;
 +        /* the data from the pidl */
 +        switch (iColumn)
 +        {
 +            case 0:                /* name */
 +                hr = GetDisplayNameOf (pidl,
 +                    SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
 +                break;
 +            case 1:                /* size */
 +                _ILGetFileSize(pidl, psd->str.cStr, MAX_PATH);
 +                break;
 +            case 2:                /* type */
 +                _ILGetFileType(pidl, psd->str.cStr, MAX_PATH);
 +                break;
 +            case 3:                /* date */
 +                _ILGetFileDate(pidl, psd->str.cStr, MAX_PATH);
 +                break;
 +            case 4:                /* attributes */
 +                _ILGetFileAttributes(pidl, psd->str.cStr, MAX_PATH);
 +                break;
 +        }
 +    }
 +
 +    return hr;
 +}
 +
 +HRESULT WINAPI CFSFolder::MapColumnToSCID (UINT column,
 +        SHCOLUMNID * pscid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +/****************************************************************************
 + * ISFHelper for IShellFolder implementation
 + */
 +
 +/****************************************************************************
 + * CFSFolder::GetUniqueName
 + *
 + * creates a unique folder name
 + */
 +
 +HRESULT WINAPI CFSFolder::GetUniqueName(LPWSTR pwszName, UINT uLen)
 +{
 +    CComPtr<IEnumIDList> penum;
 +    HRESULT hr;
 +    WCHAR wszText[MAX_PATH];
 +    WCHAR wszNewFolder[25];
 +    const WCHAR wszFormat[] = L"%s %d";
 +
 +    LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, _countof(wszNewFolder));
 +
 +    TRACE ("(%p)(%p %u)\n", this, pwszName, uLen);
 +
 +    if (uLen < _countof(wszNewFolder) + 3)
 +        return E_POINTER;
 +
 +    lstrcpynW (pwszName, wszNewFolder, uLen);
 +
 +    hr = EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
 +    if (penum)
 +    {
 +        LPITEMIDLIST pidl;
 +        DWORD dwFetched;
 +        int i = 1;
 +
 +next:
 +        penum->Reset ();
 +        while (S_OK == penum->Next(1, &pidl, &dwFetched) && dwFetched)
 +        {
 +            _ILSimpleGetTextW(pidl, wszText, MAX_PATH);
 +            if (0 == lstrcmpiW(wszText, pwszName))
 +            {
 +                _snwprintf(pwszName, uLen, wszFormat, wszNewFolder, i++);
 +                if (i > 99)
 +                {
 +                    hr = E_FAIL;
 +                    break;
 +                }
 +                goto next;
 +            }
 +        }
 +    }
 +    return hr;
 +}
 +
 +/****************************************************************************
 + * CFSFolder::AddFolder
 + *
 + * adds a new folder.
 + */
 +
 +HRESULT WINAPI CFSFolder::AddFolder(HWND hwnd, LPCWSTR pwszName,
 +                                    LPITEMIDLIST * ppidlOut)
 +{
 +    WCHAR wszNewDir[MAX_PATH];
 +    DWORD bRes;
 +    HRESULT hres = E_FAIL;
 +
 +    TRACE ("(%p)(%s %p)\n", this, debugstr_w(pwszName), ppidlOut);
 +
 +    wszNewDir[0] = 0;
 +    if (sPathTarget)
 +        lstrcpynW(wszNewDir, sPathTarget, MAX_PATH);
 +    PathAppendW(wszNewDir, pwszName);
 +
 +    bRes = CreateDirectoryW(wszNewDir, NULL);
 +    if (bRes)
 +    {
 +        SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, wszNewDir, NULL);
 +
 +        hres = S_OK;
 +
 +        if (ppidlOut)
 +            hres = _ILCreateFromPathW(wszNewDir, ppidlOut);
 +    }
 +    else
 +    {
 +        WCHAR wszText[128 + MAX_PATH];
 +        WCHAR wszTempText[128];
 +        WCHAR wszCaption[256];
 +
 +        /* Cannot Create folder because of permissions */
 +        LoadStringW(shell32_hInstance, IDS_CREATEFOLDER_DENIED, wszTempText,
 +                    _countof(wszTempText));
 +        LoadStringW(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, wszCaption,
 +                    _countof(wszCaption));
 +        swprintf(wszText, wszTempText, wszNewDir);
 +        MessageBoxW(hwnd, wszText, wszCaption, MB_OK | MB_ICONEXCLAMATION);
 +    }
 +
 +    return hres;
 +}
 +
 +/****************************************************************************
 + * BuildPathsList
 + *
 + * Builds a list of paths like the one used in SHFileOperation from a table of
 + * PIDLs relative to the given base folder
 + */
 +WCHAR *
 +BuildPathsList(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls)
 +{
 +    WCHAR *pwszPathsList;
 +    WCHAR *pwszListPos;
 +    int iPathLen, i;
 +
 +    iPathLen = wcslen(wszBasePath);
 +    pwszPathsList = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) * cidl + 1);
 +    pwszListPos = pwszPathsList;
 +
 +    for (i = 0; i < cidl; i++)
 +    {
 +        if (!_ILIsFolder(pidls[i]) && !_ILIsValue(pidls[i]))
 +            continue;
 +
 +        wcscpy(pwszListPos, wszBasePath);
 +        pwszListPos += iPathLen;
 +        /* FIXME: abort if path too long */
 +        _ILSimpleGetTextW(pidls[i], pwszListPos, MAX_PATH - iPathLen);
 +        pwszListPos += wcslen(pwszListPos) + 1;
 +    }
 +    *pwszListPos = 0;
 +    return pwszPathsList;
 +}
 +
 +/****************************************************************************
 + * CFSFolder::DeleteItems
 + *
 + * deletes items in folder
 + */
 +HRESULT WINAPI CFSFolder::DeleteItems(UINT cidl, LPCITEMIDLIST *apidl)
 +{
 +    UINT i;
 +    SHFILEOPSTRUCTW op;
 +    WCHAR wszPath[MAX_PATH];
 +    WCHAR *wszPathsList;
 +    HRESULT ret;
 +    WCHAR *wszCurrentPath;
 +
 +    TRACE ("(%p)(%u %p)\n", this, cidl, apidl);
 +    if (cidl == 0) return S_OK;
 +
 +    if (sPathTarget)
 +        lstrcpynW(wszPath, sPathTarget, MAX_PATH);
 +    else
 +        wszPath[0] = '\0';
 +    PathAddBackslashW(wszPath);
 +    wszPathsList = BuildPathsList(wszPath, cidl, apidl);
 +
 +    ZeroMemory(&op, sizeof(op));
 +    op.hwnd = GetActiveWindow();
 +    op.wFunc = FO_DELETE;
 +    op.pFrom = wszPathsList;
 +    op.fFlags = FOF_ALLOWUNDO;
 +    if (SHFileOperationW(&op))
 +    {
 +        WARN("SHFileOperation failed\n");
 +        ret = E_FAIL;
 +    }
 +    else
 +        ret = S_OK;
 +
 +    /* we currently need to manually send the notifies */
 +    wszCurrentPath = wszPathsList;
 +    for (i = 0; i < cidl; i++)
 +    {
 +        LONG wEventId;
 +
 +        if (_ILIsFolder(apidl[i]))
 +            wEventId = SHCNE_RMDIR;
 +        else if (_ILIsValue(apidl[i]))
 +            wEventId = SHCNE_DELETE;
 +        else
 +            continue;
 +
 +        /* check if file exists */
 +        if (GetFileAttributesW(wszCurrentPath) == INVALID_FILE_ATTRIBUTES)
 +        {
 +            LPITEMIDLIST pidl = ILCombine(pidlRoot, apidl[i]);
 +            SHChangeNotify(wEventId, SHCNF_IDLIST, pidl, NULL);
 +            SHFree(pidl);
 +        }
 +
 +        wszCurrentPath += wcslen(wszCurrentPath) + 1;
 +    }
 +    HeapFree(GetProcessHeap(), 0, wszPathsList);
 +    return ret;
 +}
 +
 +/****************************************************************************
 + * CFSFolder::CopyItems
 + *
 + * copies items to this folder
 + */
 +HRESULT WINAPI CFSFolder::CopyItems(IShellFolder * pSFFrom, UINT cidl,
 +                                    LPCITEMIDLIST * apidl, bool bCopy)
 +{
 +    CComPtr<IPersistFolder2> ppf2 = NULL;
 +    WCHAR szSrcPath[MAX_PATH];
 +    WCHAR szTargetPath[MAX_PATH];
 +    SHFILEOPSTRUCTW op;
 +    LPITEMIDLIST pidl;
 +    LPWSTR pszSrc, pszTarget, pszSrcList, pszTargetList, pszFileName;
 +    int res, length;
 +    HRESULT hr;
 +    STRRET strRet;
 +
 +    TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom, cidl, apidl);
 +
 +    hr = pSFFrom->QueryInterface (IID_PPV_ARG(IPersistFolder2, &ppf2));
 +    if (SUCCEEDED(hr))
 +    {
 +        hr = ppf2->GetCurFolder(&pidl);
 +        if (FAILED(hr))
 +        {
 +            return hr;
 +        }
 +
 +        hr = pSFFrom->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strRet);
 +        if (FAILED(hr))
 +        {
 +            SHFree(pidl);
 +            return hr;
 +        }
 +
 +        hr = StrRetToBufW(&strRet, pidl, szSrcPath, MAX_PATH);
 +        if (FAILED(hr))
 +        {
 +            SHFree(pidl);
 +            return hr;
 +        }
 +        SHFree(pidl);
 +
 +        pszSrc = PathAddBackslashW(szSrcPath);
 +
 +        wcscpy(szTargetPath, sPathTarget);
 +        pszTarget = PathAddBackslashW(szTargetPath);
 +
 +        pszSrcList = BuildPathsList(szSrcPath, cidl, apidl);
 +        pszTargetList = BuildPathsList(szTargetPath, cidl, apidl);
 +
 +        if (!pszSrcList || !pszTargetList)
 +        {
 +            if (pszSrcList)
 +                HeapFree(GetProcessHeap(), 0, pszSrcList);
 +
 +            if (pszTargetList)
 +                HeapFree(GetProcessHeap(), 0, pszTargetList);
 +
 +            SHFree(pidl);
 +            return E_OUTOFMEMORY;
 +        }
 +
 +        ZeroMemory(&op, sizeof(op));
 +        if (!pszSrcList[0])
 +        {
 +            /* remove trailing backslash */
 +            pszSrc--;
 +            pszSrc[0] = L'\0';
 +            op.pFrom = szSrcPath;
 +        }
 +        else
 +        {
 +            op.pFrom = pszSrcList;
 +        }
 +
 +        if (!pszTargetList[0])
 +        {
 +            /* remove trailing backslash */
 +            if (pszTarget - szTargetPath > 3)
 +            {
 +                pszTarget--;
 +                pszTarget[0] = L'\0';
 +            }
 +            else
 +            {
 +                pszTarget[1] = L'\0';
 +            }
 +
 +            op.pTo = szTargetPath;
 +            op.fFlags = 0;
 +        }
 +        else
 +        {
 +            op.pTo = pszTargetList;
 +            op.fFlags = FOF_MULTIDESTFILES;
 +        }
 +        op.hwnd = GetActiveWindow();
 +        op.wFunc = bCopy ? FO_COPY : FO_MOVE;
 +        op.fFlags |= FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
 +
 +        res = SHFileOperationW(&op);
 +
 +        if (res == DE_SAMEFILE)
 +        {
 +            length = wcslen(szTargetPath);
 +
 +            pszFileName = wcsrchr(pszSrcList, '\\');
 +            pszFileName++;
 +
 +            if (LoadStringW(shell32_hInstance, IDS_COPY_OF, pszTarget, MAX_PATH - length))
 +            {
 +                wcscat(szTargetPath, L" ");
 +            }
 +
 +            wcscat(szTargetPath, pszFileName);
 +            op.pTo = szTargetPath;
 +
 +            res = SHFileOperationW(&op);
 +        }
 +
 +        HeapFree(GetProcessHeap(), 0, pszSrcList);
 +        HeapFree(GetProcessHeap(), 0, pszTargetList);
 +
 +        if (res)
 +            return E_FAIL;
 +        else
 +            return S_OK;
 +    }
 +    return E_FAIL;
 +}
 +
 +/************************************************************************
 + * CFSFolder::GetClassID
 + */
 +HRESULT WINAPI CFSFolder::GetClassID(CLSID * lpClassId)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!lpClassId)
 +        return E_POINTER;
 +
 +    *lpClassId = *pclsid;
 +
 +    return S_OK;
 +}
 +
 +/************************************************************************
 + * CFSFolder::Initialize
 + *
 + * NOTES
 + *  sPathTarget is not set. Don't know how to handle in a non rooted environment.
 + */
 +HRESULT WINAPI CFSFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    WCHAR wszTemp[MAX_PATH];
 +
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    SHFree (pidlRoot);     /* free the old pidl */
 +    pidlRoot = ILClone (pidl); /* set my pidl */
 +
 +    SHFree (sPathTarget);
 +    sPathTarget = NULL;
 +
 +    /* set my path */
 +    if (SHGetPathFromIDListW (pidl, wszTemp))
 +    {
 +        int len = wcslen(wszTemp);
 +        sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR));
 +        if (!sPathTarget)
 +            return E_OUTOFMEMORY;
 +        memcpy(sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
 +    }
 +
 +    TRACE ("--(%p)->(%s)\n", this, debugstr_w(sPathTarget));
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + * CFSFolder::GetCurFolder
 + */
 +HRESULT WINAPI CFSFolder::GetCurFolder(LPITEMIDLIST * pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    if (!pidl)
 +        return E_POINTER;
 +
 +    *pidl = ILClone(pidlRoot);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + * CFSFolder::InitializeEx
 + *
 + * FIXME: error handling
 + */
 +HRESULT WINAPI CFSFolder::InitializeEx(IBindCtx * pbc, LPCITEMIDLIST pidlRootx,
 +                                       const PERSIST_FOLDER_TARGET_INFO * ppfti)
 +{
 +    WCHAR wszTemp[MAX_PATH];
 +
 +    TRACE("(%p)->(%p,%p,%p)\n", this, pbc, pidlRootx, ppfti);
 +    if (ppfti)
 +        TRACE("--%p %s %s 0x%08x 0x%08x\n",
 +              ppfti->pidlTargetFolder, debugstr_w (ppfti->szTargetParsingName),
 +              debugstr_w (ppfti->szNetworkProvider), ppfti->dwAttributes,
 +              ppfti->csidl);
 +
 +    pdump (pidlRootx);
 +    if (ppfti && ppfti->pidlTargetFolder)
 +        pdump(ppfti->pidlTargetFolder);
 +
 +    if (pidlRoot)
 +        __SHFreeAndNil(&pidlRoot);    /* free the old */
 +    if (sPathTarget)
 +        __SHFreeAndNil(&sPathTarget);
 +
 +    /*
 +     * Root path and pidl
 +     */
 +    pidlRoot = ILClone(pidlRootx);
 +
 +    /*
 +     *  the target folder is spezified in csidl OR pidlTargetFolder OR
 +     *  szTargetParsingName
 +     */
 +    if (ppfti)
 +    {
 +        if (ppfti->csidl != -1)
 +        {
 +            if (SHGetSpecialFolderPathW(0, wszTemp, ppfti->csidl,
 +                                        ppfti->csidl & CSIDL_FLAG_CREATE)) {
 +                int len = wcslen(wszTemp);
 +                sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR));
 +                if (!sPathTarget)
 +                    return E_OUTOFMEMORY;
 +                memcpy(sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
 +            }
 +        }
 +        else if (ppfti->szTargetParsingName[0])
 +        {
 +            int len = wcslen(ppfti->szTargetParsingName);
 +            sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR));
 +            if (!sPathTarget)
 +                return E_OUTOFMEMORY;
 +            memcpy(sPathTarget, ppfti->szTargetParsingName,
 +                   (len + 1) * sizeof(WCHAR));
 +        }
 +        else if (ppfti->pidlTargetFolder)
 +        {
 +            if (SHGetPathFromIDListW(ppfti->pidlTargetFolder, wszTemp))
 +            {
 +                int len = wcslen(wszTemp);
 +                sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR));
 +                if (!sPathTarget)
 +                    return E_OUTOFMEMORY;
 +                memcpy(sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
 +            }
 +        }
 +    }
 +
 +    TRACE("--(%p)->(target=%s)\n", this, debugstr_w(sPathTarget));
 +    pdump(pidlRoot);
 +    return (sPathTarget) ? S_OK : E_FAIL;
 +}
 +
 +HRESULT WINAPI CFSFolder::GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO * ppfti)
 +{
 +    FIXME("(%p)->(%p)\n", this, ppfti);
 +    ZeroMemory(ppfti, sizeof (*ppfti));
 +    return E_NOTIMPL;
 +}
 +
 +BOOL
 +CFSFolder::GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
 +{
 +    WCHAR wszLink[40];
 +
 +    if (!bShortcut)
 +    {
 +        if (!LoadStringW(shell32_hInstance, IDS_LNK_FILE, wszLink, _countof(wszLink)))
 +            wszLink[0] = L'\0';
 +    }
 +
 +    if (!bShortcut)
 +        swprintf(pwszTarget, L"%s%s%s", wszLink, pwszBasePath, pwszExt);
 +    else
 +        swprintf(pwszTarget, L"%s%s", pwszBasePath, pwszExt);
 +
 +    for (UINT i = 2; PathFileExistsW(pwszTarget); ++i)
 +    {
 +        if (!bShortcut)
 +            swprintf(pwszTarget, L"%s%s (%u)%s", wszLink, pwszBasePath, i, pwszExt);
 +        else
 +            swprintf(pwszTarget, L"%s (%u)%s", pwszBasePath, i, pwszExt);
 +    }
 +
 +    return TRUE;
 +}
 +
 +/****************************************************************************
 + * IDropTarget implementation
 + */
 +BOOL CFSFolder::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
 +{
 +    /* TODO Windows does different drop effects if dragging across drives. 
 +    i.e., it will copy instead of move if the directories are on different disks. */
 +
 +    DWORD dwEffect = DROPEFFECT_MOVE;
 +
 +    *pdwEffect = DROPEFFECT_NONE;
 +
 +    if (fAcceptFmt) { /* Does our interpretation of the keystate ... */
 +        *pdwEffect = KeyStateToDropEffect (dwKeyState);
 +
 +        if (*pdwEffect == DROPEFFECT_NONE)
 +            *pdwEffect = dwEffect;
 +
 +        /* ... matches the desired effect ? */
 +        if (dwEffect & *pdwEffect) {
 +            return TRUE;
 +        }
 +    }
 +    return FALSE;
 +}
 +
 +HRESULT WINAPI CFSFolder::DragEnter(IDataObject *pDataObject,
 +                                    DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
 +    FORMATETC fmt;
 +    FORMATETC fmt2;
 +    fAcceptFmt = FALSE;
 +
 +    InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
 +    InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
 +
 +    if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
 +        fAcceptFmt = TRUE;
 +    else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
 +        fAcceptFmt = TRUE;
 +
 +    QueryDrop(dwKeyState, pdwEffect);
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CFSFolder::DragOver(DWORD dwKeyState, POINTL pt,
 +                                   DWORD *pdwEffect)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (!pdwEffect)
 +        return E_INVALIDARG;
 +
 +    QueryDrop(dwKeyState, pdwEffect);
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CFSFolder::DragLeave()
 +{
 +    TRACE("(%p)\n", this);
 +
 +    fAcceptFmt = FALSE;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CFSFolder::Drop(IDataObject *pDataObject,
 +                               DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect);
 +    
 +    BOOL fIsOpAsync = FALSE;
 +    CComPtr<IAsyncOperation> pAsyncOperation;
 +
 +    if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
 +    {
 +        if (SUCCEEDED(pAsyncOperation->GetAsyncMode(&fIsOpAsync)) && fIsOpAsync)
 +        {
 +            _DoDropData *data = static_cast<_DoDropData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(_DoDropData)));
 +            data->This = this;
 +            // Need to maintain this class in case the window is closed or the class exists temporarily (when dropping onto a folder).
 +            pDataObject->AddRef();
 +            pAsyncOperation->StartOperation(NULL);
 +            CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &data->pStream);
 +            this->AddRef();
 +            data->dwKeyState = dwKeyState;
 +            data->pt = pt;
 +            // Need to dereference as pdweffect gets freed.
 +            data->pdwEffect = *pdwEffect;
 +            SHCreateThread(CFSFolder::_DoDropThreadProc, data, NULL, NULL);
 +            return S_OK;
 +        }
 +    }
 +    return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect);
 +}
 +
 +HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject,
 +                               DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    TRACE("(%p) performing drop, effect %u\n", this, *pdwEffect);
 +    FORMATETC fmt;
 +    FORMATETC fmt2;
 +    STGMEDIUM medium;
 +
 +    InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
 +    InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
 +
 +    HRESULT hr;
 +    bool bCopy = TRUE;
 +    bool bLinking = FALSE;
 +
 +    /* Figure out what drop operation we're doing */
 +    if (pdwEffect)
 +    {
 +        TRACE("Current drop effect flag %i\n", *pdwEffect);
 +        if ((*pdwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
 +            bCopy = FALSE;
 +        if ((*pdwEffect & DROPEFFECT_LINK) == DROPEFFECT_LINK)
 +            bLinking = TRUE;
 +    }
 +
 +    if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
 +    {
 +        hr = pDataObject->GetData(&fmt, &medium);
 +        TRACE("CFSTR_SHELLIDLIST.\n");
 +
 +        /* lock the handle */
 +        LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
 +        if (!lpcida)
 +        {
 +            ReleaseStgMedium(&medium);
 +            return E_FAIL;
 +        }
 +
 +        /* convert the data into pidl */
 +        LPITEMIDLIST pidl;
 +        LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
 +        if (!apidl)
 +        {
 +            ReleaseStgMedium(&medium);
 +            return E_FAIL;
 +        }
 +
 +        CComPtr<IShellFolder> psfDesktop;
 +        CComPtr<IShellFolder> psfFrom = NULL;
 +        CComPtr<IShellFolder> psfTarget = NULL;
 +
 +        hr = this->QueryInterface(IID_PPV_ARG(IShellFolder, &psfTarget));
 +        if (FAILED(hr))
 +        {
 +            ERR("psfTarget setting failed\n");
 +            SHFree(pidl);
 +            _ILFreeaPidl(apidl, lpcida->cidl);
 +            ReleaseStgMedium(&medium);
 +            return E_FAIL;
 +        }
 +
 +        /* Grab the desktop shell folder */
 +        hr = SHGetDesktopFolder(&psfDesktop);
 +        if (FAILED(hr))
 +        {
 +            ERR("SHGetDesktopFolder failed\n");
 +            SHFree(pidl);
 +            _ILFreeaPidl(apidl, lpcida->cidl);
 +            ReleaseStgMedium(&medium);
 +            return E_FAIL;
 +        }
 +
 +        /* Find source folder, this is where the clipboard data was copied from */
 +        if (_ILIsDesktop(pidl))
 +        {
 +            /* use desktop shell folder */
 +            psfFrom = psfDesktop;
 +        }
 +        else 
 +        {
 +            hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom));
 +            if (FAILED(hr))
 +            {
 +                ERR("no IShellFolder\n");
 +                SHFree(pidl);
 +                _ILFreeaPidl(apidl, lpcida->cidl);
 +                ReleaseStgMedium(&medium);
 +                return E_FAIL;
 +            }
 +        }
 +
 +        if (bLinking)
 +        {
 +            CComPtr<IPersistFolder2> ppf2 = NULL;
 +            STRRET strFile;
 +            WCHAR wszTargetPath[MAX_PATH];
 +            LPITEMIDLIST targetpidl;
 +            WCHAR wszPath[MAX_PATH];
 +            WCHAR wszTarget[MAX_PATH];
 +
 +            hr = this->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
 +            if (SUCCEEDED(hr))
 +            {
 +                hr = ppf2->GetCurFolder(&targetpidl);
 +                if (SUCCEEDED(hr))
 +                {
 +                    hr = psfDesktop->GetDisplayNameOf(targetpidl, SHGDN_FORPARSING, &strFile);
 +                    ILFree(targetpidl);
 +                    if (SUCCEEDED(hr)) 
 +                    {
 +                        hr = StrRetToBufW(&strFile, NULL, wszTargetPath, _countof(wszTargetPath));
 +                    }
 +                }
 +            }
 +
 +            if (FAILED(hr)) 
 +            {
 +                ERR("Error obtaining target path");
 +            }
 +
 +            TRACE("target path = %s", debugstr_w(wszTargetPath));
 +
 +            /* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */
 +            for (UINT i = 0; i < lpcida->cidl; i++)
 +            {
 +                //Find out which file we're copying
 +                STRRET strFile;
 +                hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strFile);
 +                if (FAILED(hr)) 
 +                {
 +                    ERR("Error source obtaining path");
 +                    break;
 +                }
 +
 +                hr = StrRetToBufW(&strFile, apidl[i], wszPath, _countof(wszPath));
 +                if (FAILED(hr)) 
 +                {
 +                    ERR("Error putting source path into buffer");
 +                    break;
 +                }
 +                TRACE("source path = %s", debugstr_w(wszPath));
 +
 +                // Creating a buffer to hold the combined path
 +                WCHAR buffer_1[MAX_PATH] = L"";
 +                WCHAR *lpStr1;
 +                lpStr1 = buffer_1;
 +
 +                LPWSTR pwszFileName = PathFindFileNameW(wszPath);
 +                LPWSTR pwszExt = PathFindExtensionW(wszPath);
 +                LPWSTR placementPath = PathCombineW(lpStr1, wszTargetPath, pwszFileName);
 +                CComPtr<IPersistFile> ppf;
 +
 +                //Check to see if it's already a link. 
 +                if (!wcsicmp(pwszExt, L".lnk"))
 +                {
 +                    //It's a link so, we create a new one which copies the old.
 +                    if(!GetUniqueFileName(placementPath, pwszExt, wszTarget, TRUE)) 
 +                    {
 +                        ERR("Error getting unique file name");
 +                        hr = E_FAIL;
 +                        break;
 +                    }
 +                    hr = IShellLink_ConstructFromFile(NULL, IID_IPersistFile, ILCombine(pidl, apidl[i]), (LPVOID*)&ppf);
 +                    if (FAILED(hr)) {
 +                        ERR("Error constructing link from file");
 +                        break;
 +                    }
 +
 +                    hr = ppf->Save(wszTarget, FALSE);
 +                                      if (FAILED(hr))
 +                                              break;
 +                                      SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL);
 +                }
 +                else
 +                {
 +                    //It's not a link, so build a new link using the creator class and fill it in.
 +                    //Create a file name for the link
 +                    if (!GetUniqueFileName(placementPath, L".lnk", wszTarget, TRUE))
 +                    {
 +                        ERR("Error creating unique file name");
 +                        hr = E_FAIL;
 +                        break;
 +                    }
 +
 +                    CComPtr<IShellLinkW> pLink;
 +                    hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink));
 +                    if (FAILED(hr)) {
 +                        ERR("Error instantiating IShellLinkW");
 +                        break;
 +                    }
 +
 +                    WCHAR szDirPath[MAX_PATH], *pwszFile;
 +                    GetFullPathName(wszPath, MAX_PATH, szDirPath, &pwszFile);
 +                    if (pwszFile) pwszFile[0] = 0;
 +
 +                    hr = pLink->SetPath(wszPath);
 +                    if(FAILED(hr))
 +                        break;
 +
 +                    hr = pLink->SetWorkingDirectory(szDirPath);
 +                    if(FAILED(hr))
 +                        break;
 +
 +                    hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
 +                    if(FAILED(hr))
 +                        break;
 +
 +                    hr = ppf->Save(wszTarget, TRUE);
 +                                      if (FAILED(hr))
 +                                              break;
 +                                      SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL);
 +                }
 +            }
 +        }
 +        else 
 +        {
 +            hr = this->CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy);
 +        }
 +
 +        SHFree(pidl);
 +        _ILFreeaPidl(apidl, lpcida->cidl);
 +        ReleaseStgMedium(&medium);
 +    }
 +    else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
 +    {
 +        FORMATETC fmt2;
 +        InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
 +        if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/)
 +        {
 +            CComPtr<IPersistFolder2> ppf2 = NULL;
 +            STRRET strFile;
 +            WCHAR wszTargetPath[MAX_PATH + 1];
 +            LPWSTR pszSrcList;
 +            LPITEMIDLIST targetpidl;
 +            CComPtr<IShellFolder> psfDesktop = NULL;
 +            hr = SHGetDesktopFolder(&psfDesktop);
 +            if (FAILED(hr))
 +            {
 +                ERR("SHGetDesktopFolder failed\n");
 +                return E_FAIL;
 +            }
 +
 +            hr = this->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
 +            if (SUCCEEDED(hr))
 +            {
 +                hr = ppf2->GetCurFolder(&targetpidl);
 +                if (SUCCEEDED(hr))
 +                {
 +                    hr = psfDesktop->GetDisplayNameOf(targetpidl, SHGDN_FORPARSING, &strFile);
 +                    ILFree(targetpidl);
 +                    if (SUCCEEDED(hr)) 
 +                    {
 +                        hr = StrRetToBufW(&strFile, NULL, wszTargetPath, _countof(wszTargetPath));
 +                        //Double NULL terminate.
 +                        wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
 +                    }
 +                }
 +            }
 +            if (FAILED(hr)) 
 +            {
 +                ERR("Error obtaining target path");
 +                return E_FAIL;
 +            }
 +
 +            LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal);
 +            if (!lpdf)
 +            {
 +                ERR("Error locking global\n");
 +                return E_FAIL;
 +            }
 +            pszSrcList = (LPWSTR) (((byte*) lpdf) + lpdf->pFiles);
 +            TRACE("Source file (just the first) = %s\n", debugstr_w(pszSrcList));
 +            TRACE("Target path = %s\n", debugstr_w(wszTargetPath));
 +
 +            SHFILEOPSTRUCTW op;
 +            ZeroMemory(&op, sizeof(op));
 +            op.pFrom = pszSrcList;
 +            op.pTo = wszTargetPath;
 +            op.hwnd = GetActiveWindow();
 +            op.wFunc = bCopy ? FO_COPY : FO_MOVE;
 +            op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
 +            hr = SHFileOperationW(&op);
 +            return hr;
 +        }
 +        ERR("Error calling GetData\n");
 +        hr = E_FAIL;
 +    }
 +    else 
 +    {
 +        ERR("No viable drop format.\n");
 +        hr = E_FAIL;
 +    }    
 +    return hr;
 +}
 +
 +DWORD WINAPI CFSFolder::_DoDropThreadProc(LPVOID lpParameter) {
 +    CoInitialize(NULL);
 +    _DoDropData *data = static_cast<_DoDropData*>(lpParameter);
 +    CComPtr<IDataObject> pDataObject;
 +    HRESULT hr = CoGetInterfaceAndReleaseStream (data->pStream, IID_PPV_ARG(IDataObject, &pDataObject));
 +
 +    if (SUCCEEDED(hr))
 +    {
 +        CComPtr<IAsyncOperation> pAsyncOperation;
 +        hr = data->This->_DoDrop(pDataObject, data->dwKeyState, data->pt, &data->pdwEffect);
 +        if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
 +        {
 +            pAsyncOperation->EndOperation(hr, NULL, data->pdwEffect);
 +        }
 +    }
 +    //Release the CFSFolder and data object holds in the copying thread.
 +    data->This->Release();
 +    //Release the parameter from the heap.
 +    HeapFree(GetProcessHeap(), 0, data);
++    CoUninitialize();
 +    return 0;
 +}
 +
 +HRESULT WINAPI CFSFolder::_GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut) {
 +    HKEY hKey;
 +    HRESULT hr;
 +
 +    TRACE("CFSFolder::_GetDropTarget entered\n");
 +
 +    if (_ILGetGUIDPointer (pidl) || _ILIsFolder (pidl))
 +        return this->BindToObject(pidl, NULL, IID_IDropTarget, ppvOut);
 +
 +    STRRET strFile;
 +    hr = this->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strFile);
 +    if (hr == S_OK)
 +    {
 +        WCHAR wszPath[MAX_PATH];
 +        hr = StrRetToBufW(&strFile, pidl, wszPath, _countof(wszPath));
 +
 +        if (hr == S_OK)
 +        {
 +            LPCWSTR pwszExt = PathFindExtensionW(wszPath);
 +            if (pwszExt[0])
 +            {
 +                /* enumerate dynamic/static for a given file class */
 +                if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +                {
 +                    /* load dynamic extensions from file extension key, for example .jpg */
 +                    _LoadDynamicDropTargetHandlerForKey(hKey, wszPath, ppvOut);
 +                    RegCloseKey(hKey);
 +                }
 +
 +                WCHAR wszTemp[40];
 +                DWORD dwSize = sizeof(wszTemp);
 +                if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, NULL, RRF_RT_REG_SZ, NULL, wszTemp, &dwSize) == ERROR_SUCCESS)
 +                {
 +                    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszTemp, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
 +                    {
 +                        /* load dynamic extensions from progid key, for example jpegfile */
 +                        _LoadDynamicDropTargetHandlerForKey(hKey, wszPath, ppvOut);
 +                        RegCloseKey(hKey);
 +                    }
 +                }
 +            }
 +        }
 +    }
 +    else
 +        ERR("GetDisplayNameOf failed: %x\n", hr);
 +
 +    return hr;
 +}
 +
 +HRESULT WINAPI CFSFolder::_LoadDynamicDropTargetHandlerForKey(HKEY hRootKey, LPCWSTR pwcsname, LPVOID *ppvOut) 
 +{
 +    TRACE("CFSFolder::_LoadDynamicDropTargetHandlerForKey entered\n");
 +
 +    WCHAR wszName[MAX_PATH], *pwszClsid;
 +    DWORD dwSize = sizeof(wszName);
 +    HRESULT hr;
 +
 +    if (RegGetValueW(hRootKey, L"shellex\\DropHandler", NULL, RRF_RT_REG_SZ, NULL, wszName, &dwSize) == ERROR_SUCCESS)
 +    {
 +        CLSID clsid;
 +        hr = CLSIDFromString(wszName, &clsid);
 +        if (hr == S_OK)
 +            pwszClsid = wszName;
 +
 +        if (m_bGroupPolicyActive)
 +        {
 +            if (RegGetValueW(HKEY_LOCAL_MACHINE,
 +                L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
 +                pwszClsid,
 +                RRF_RT_REG_SZ,
 +                NULL,
 +                NULL,
 +                NULL) == ERROR_SUCCESS)
 +            {
 +                hr = _LoadDynamicDropTargetHandler(&clsid, pwcsname, ppvOut);
 +            }
 +        }
 +        else
 +        {
 +            hr = _LoadDynamicDropTargetHandler(&clsid, pwcsname, ppvOut);
 +        }
 +    }
 +    else
 +        return E_FAIL;
 +    return hr;
 +}
 +
 +HRESULT WINAPI CFSFolder::_LoadDynamicDropTargetHandler(const CLSID *pclsid, LPCWSTR pwcsname, LPVOID *ppvOut)
 +{
 +    TRACE("CFSFolder::_LoadDynamicDropTargetHandler entered\n");
 +    HRESULT hr;
 +
 +    CComPtr<IPersistFile> pp;
 +    hr = SHCoCreateInstance(NULL, pclsid, NULL, IID_PPV_ARG(IPersistFile, &pp));
 +    if (hr != S_OK)
 +    {
 +        ERR("SHCoCreateInstance failed %x\n", GetLastError());
 +    }
 +    pp->Load(pwcsname, 0);
 +
 +    hr = pp->QueryInterface(IID_PPV_ARG(IDropTarget, (IDropTarget**) ppvOut));
 +    if (hr != S_OK)
 +    {
 +        ERR("Failed to query for interface IID_IShellExtInit hr %x pclsid %s\n", hr, wine_dbgstr_guid(pclsid));
 +        return hr;
 +    }
 +    return hr;
 +}
Simple merge
index 4b93fef,0000000..9239977
mode 100644,000000..100644
--- /dev/null
@@@ -1,881 -1,0 +1,881 @@@
-         DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
 +/*
 + *    Virtual Workplace folder
 + *
 + *    Copyright 1997                Marcus Meissner
 + *    Copyright 1998, 1999, 2002    Juergen Schmied
 + *    Copyright 2009                Andrew Hill
 + *
 + * 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);
 +
 +/*
 +CDrivesFolder should create a CRegFolder to represent the virtual items that exist only in
 +the registry. The CRegFolder is aggregated by the CDrivesFolder.
 +The CDrivesFolderEnum class should enumerate only drives on the system. Since the CRegFolder
 +implementation of IShellFolder::EnumObjects enumerates the virtual items, the
 +CDrivesFolderEnum is only responsible for returning the physical items.
 +
 +2. At least on my XP system, the drive pidls returned are of type PT_DRIVE1, not PT_DRIVE
 +3. The parsing name returned for my computer is incorrect. It should be "My Computer"
 +*/
 +
 +/***********************************************************************
 +*   IShellFolder implementation
 +*/
 +
 +class CDrivesFolderEnum :
 +    public IEnumIDListImpl
 +{
 +    public:
 +        CDrivesFolderEnum();
 +        ~CDrivesFolderEnum();
 +        HRESULT WINAPI Initialize(HWND hwndOwner, DWORD dwFlags);
 +        BOOL CreateMyCompEnumList(DWORD dwFlags);
 +
 +        BEGIN_COM_MAP(CDrivesFolderEnum)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +/***********************************************************************
 +*   IShellFolder [MyComputer] implementation
 +*/
 +
 +static const shvheader MyComputerSFHeader[] = {
 +    {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +};
 +
 +#define MYCOMPUTERSHELLVIEWCOLUMNS 4
 +
 +CDrivesFolderEnum::CDrivesFolderEnum()
 +{
 +}
 +
 +CDrivesFolderEnum::~CDrivesFolderEnum()
 +{
 +}
 +
 +HRESULT WINAPI CDrivesFolderEnum::Initialize(HWND hwndOwner, DWORD dwFlags)
 +{
 +    if (CreateMyCompEnumList(dwFlags) == FALSE)
 +        return E_FAIL;
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *  CDrivesFolderEnum::CreateMyCompEnumList()
 + */
 +
 +BOOL CDrivesFolderEnum::CreateMyCompEnumList(DWORD dwFlags)
 +{
 +    BOOL bRet = TRUE;
 +    static const WCHAR MyComputer_NameSpaceW[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\Namespace";
 +
 +    TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
 +
 +    /* enumerate the folders */
 +    if (dwFlags & SHCONTF_FOLDERS)
 +    {
 +        WCHAR wszDriveName[] = {'A', ':', '\\', '\0'};
 +        DWORD dwDrivemap = GetLogicalDrives();
 +        HKEY hKey;
 +        UINT i;
 +
 +        while (bRet && wszDriveName[0] <= 'Z')
 +        {
 +            if(dwDrivemap & 0x00000001L)
 +                bRet = AddToEnumList(_ILCreateDrive(wszDriveName));
 +            wszDriveName[0]++;
 +            dwDrivemap = dwDrivemap >> 1;
 +        }
 +
 +        TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n", this);
 +        for (i = 0; i < 2; i++)
 +        {
 +            if (bRet && ERROR_SUCCESS == RegOpenKeyExW(i == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
 +                    MyComputer_NameSpaceW, 0, KEY_READ, &hKey))
 +            {
 +                WCHAR wszBuf[50];
 +                DWORD dwSize, j = 0;
 +                LONG ErrorCode;
 +                LPITEMIDLIST pidl;
 +
 +                while (bRet)
 +                {
 +                    dwSize = sizeof(wszBuf) / sizeof(wszBuf[0]);
 +                    ErrorCode = RegEnumKeyExW(hKey, j, wszBuf, &dwSize, 0, NULL, NULL, NULL);
 +                    if (ERROR_SUCCESS == ErrorCode)
 +                    {
 +                        if (wszBuf[0] != L'{')
 +                        {
 +                            dwSize = sizeof(wszBuf);
 +                            RegGetValueW(hKey, wszBuf, NULL, RRF_RT_REG_SZ, NULL, wszBuf, &dwSize);
 +                        }
 +
 +                        /* FIXME: shell extensions - the type should be PT_SHELLEXT (tested) */
 +                        pidl = _ILCreateGuidFromStrW(wszBuf);
 +                        if (pidl != NULL)
 +                            bRet = AddToEnumList(pidl);
 +                        else
 +                            ERR("Invalid MyComputer namespace extesion: %s\n", wszBuf);
 +                        j++;
 +                    }
 +                    else if (ERROR_NO_MORE_ITEMS == ErrorCode)
 +                        break;
 +                    else
 +                        bRet = FALSE;
 +                }
 +                RegCloseKey(hKey);
 +            }
 +        }
 +    }
 +    return bRet;
 +}
 +
 +CDrivesFolder::CDrivesFolder()
 +{
 +    pidlRoot = NULL;
 +    sName = NULL;
 +}
 +
 +CDrivesFolder::~CDrivesFolder()
 +{
 +    TRACE ("-- destroying IShellFolder(%p)\n", this);
 +    SHFree(pidlRoot);
 +}
 +
 +HRESULT WINAPI CDrivesFolder::FinalConstruct()
 +{
 +    DWORD dwSize;
 +    WCHAR szName[MAX_PATH];
 +    WCHAR wszMyCompKey[256];
 +    INT i;
 +
 +    pidlRoot = _ILCreateMyComputer();    /* my qualified pidl */
 +    if (pidlRoot == NULL)
 +        return E_OUTOFMEMORY;
 +
 +    i = swprintf(wszMyCompKey, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\");
 +    StringFromGUID2(CLSID_MyComputer, wszMyCompKey + i, sizeof(wszMyCompKey) / sizeof(wszMyCompKey[0]) - i);
 +    dwSize = sizeof(szName);
 +    if (RegGetValueW(HKEY_CURRENT_USER, wszMyCompKey,
 +                     NULL, RRF_RT_REG_SZ, NULL, szName, &dwSize) == ERROR_SUCCESS)
 +    {
 +        sName = (LPWSTR)SHAlloc((wcslen(szName) + 1) * sizeof(WCHAR));
 +        if (sName)
 +            wcscpy(sName, szName);
 +        TRACE("sName %s\n", debugstr_w(sName));
 +    }
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*    CDrivesFolder::ParseDisplayName
 +*/
 +HRESULT WINAPI CDrivesFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
- HRESULT WINAPI CDrivesFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++        DWORD * pchEaten, PIDLIST_RELATIVE * ppidl, DWORD * pdwAttributes)
 +{
 +    HRESULT hr = E_INVALIDARG;
 +    LPCWSTR szNext = NULL;
 +    WCHAR szElement[MAX_PATH];
 +    LPITEMIDLIST pidlTemp = NULL;
 +    CLSID clsid;
 +
 +    TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
 +          hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
 +          pchEaten, ppidl, pdwAttributes);
 +
 +    *ppidl = 0;
 +    if (pchEaten)
 +        *pchEaten = 0;        /* strange but like the original */
 +
 +    /* handle CLSID paths */
 +    if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
 +    {
 +        szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
 +        TRACE ("-- element: %s\n", debugstr_w (szElement));
 +        CLSIDFromString (szElement + 2, &clsid);
 +        pidlTemp = _ILCreateGuid (PT_GUID, clsid);
 +    }
 +    /* do we have an absolute path name ? */
 +    else if (PathGetDriveNumberW (lpszDisplayName) >= 0 &&
 +             lpszDisplayName[2] == (WCHAR) '\\')
 +    {
 +        szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
 +        /* make drive letter uppercase to enable PIDL comparison */
 +        szElement[0] = toupper(szElement[0]);
 +        pidlTemp = _ILCreateDrive (szElement);
 +    }
 +
 +    if (szNext && *szNext)
 +    {
 +        hr = SHELL32_ParseNextElement (this, hwndOwner, pbc, &pidlTemp,
 +                                       (LPOLESTR) szNext, pchEaten, pdwAttributes);
 +    }
 +    else
 +    {
 +        if (pdwAttributes && *pdwAttributes)
 +            SHELL32_GetItemAttributes (this,
 +                                       pidlTemp, pdwAttributes);
 +        hr = S_OK;
 +    }
 +
 +    *ppidl = pidlTemp;
 +
 +    TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*        CDrivesFolder::EnumObjects
 +*/
 +HRESULT WINAPI CDrivesFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
 +{
 +    CComObject<CDrivesFolderEnum> *theEnumerator;
 +    CComPtr<IEnumIDList>          result;
 +    HRESULT                       hResult;
 +
 +    TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +
 +    *ppEnumIDList = NULL;
 +    ATLTRY(theEnumerator = new CComObject<CDrivesFolderEnum>);
 +
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +
 +    hResult = theEnumerator->QueryInterface(IID_IEnumIDList, (void **)&result);
 +    if (FAILED(hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +
 +    hResult = theEnumerator->Initialize(hwndOwner, dwFlags);
 +    if (FAILED(hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach();
 +
 +    TRACE("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*        CDrivesFolder::BindToObject
 +*/
- HRESULT WINAPI CDrivesFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++HRESULT WINAPI CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this,
 +          pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
 +
 +    return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
 +}
 +
 +/**************************************************************************
 +*    CDrivesFolder::BindToStorage
 +*/
- HRESULT WINAPI CDrivesFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++HRESULT WINAPI CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
 +          pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 +*     CDrivesFolder::CompareIDs
 +*/
 +
- HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
++HRESULT WINAPI CDrivesFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs (this, lParam, pidl1, pidl2);
 +    TRACE("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 +*    CDrivesFolder::CreateViewObject
 +*/
 +HRESULT WINAPI CDrivesFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
 +{
 +    CComPtr<IShellView> pShellView;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
 +          hwndOwner, shdebugstr_guid (&riid), ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID(riid, IID_IDropTarget))
 +    {
 +        WARN("IDropTarget not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID(riid, IID_IContextMenu))
 +    {
 +        WARN("IContextMenu not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID(riid, IID_IShellView))
 +    {
 +        hr = IShellView_Constructor ((IShellFolder *)this, &pShellView);
 +        if (pShellView)
 +        {
 +            hr = pShellView->QueryInterface(riid, ppvOut);
 +        }
 +    }
 +    TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*  CDrivesFolder::GetAttributesOf
 +*/
-     UINT cidl, LPCITEMIDLIST *apidl,
++HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
 +{
 +    static const DWORD dwComputerAttributes =
 +        SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
 +        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
 +    static const DWORD dwControlPanelAttributes =
 +        SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CANLINK;
 +    static const DWORD dwDriveAttributes =
 +        SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
 +        SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANRENAME | SFGAO_CANLINK;
 +
 +    TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
 +           this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
 +
 +    if (cidl && !apidl)
 +        return E_INVALIDARG;
 +
 +    if (*rgfInOut == 0)
 +        *rgfInOut = ~0;
 +
 +    /* FIXME: always add SFGAO_CANLINK */
 +    if(cidl == 0)
 +        *rgfInOut &= dwComputerAttributes;
 +    else
 +    {
 +        for (UINT i = 0; i < cidl; ++i)
 +        {
 +            if (_ILIsDrive(apidl[i]))
 +                *rgfInOut &= dwDriveAttributes;
 +            else if (_ILIsControlPanel(apidl[i]))
 +                *rgfInOut &= dwControlPanelAttributes;
 +            else
 +            {
 +                pdump(apidl[i]);
 +                SHELL32_GetItemAttributes(this, apidl[i], rgfInOut);
 +            }
 +        }
 +    }
 +
 +    /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE ("-- result=0x%08x\n", *rgfInOut);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*    CDrivesFolder::GetUIObjectOf
 +*
 +* PARAMETERS
 +*  hwndOwner [in]  Parent window for any output
 +*  cidl      [in]  array size
 +*  apidl     [in]  simple pidl array
 +*  riid      [in]  Requested Interface
 +*  prgfInOut [   ] reserved
 +*  ppvObject [out] Resulting Interface
 +*
 +*/
 +HRESULT WINAPI CDrivesFolder::GetUIObjectOf(HWND hwndOwner,
- HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
++    UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
 +    REFIID riid, UINT *prgfInOut, LPVOID *ppvOut)
 +{
 +    LPITEMIDLIST pidl;
 +    IUnknown *pObj = NULL;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
 +          hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
 +    {
 +        hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)this, NULL, 0, NULL, (IContextMenu**)&pObj);
 +    }
 +    else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
 +    {
 +        hr = IDataObject_Constructor (hwndOwner,
 +                                      pidlRoot, apidl, cidl, (IDataObject **)&pObj);
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconA_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconW_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
 +    {
 +        IDropTarget * pDt = NULL;
 +        hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
 +        pObj = pDt;
 +    }
 +    else if ((IsEqualIID(riid, IID_IShellLinkW) ||
 +              IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*) &pObj);
 +        SHFree (pidl);
 +    }
 +    else
 +        hr = E_NOINTERFACE;
 +
 +    if (SUCCEEDED(hr) && !pObj)
 +        hr = E_OUTOFMEMORY;
 +
 +    *ppvOut = pObj;
 +    TRACE ("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*    CDrivesFolder::GetDisplayNameOf
 +*/
- HRESULT WINAPI CDrivesFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,
-                                         LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST *pPidlOut)
++HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 +{
 +    LPWSTR pszPath;
 +    HRESULT hr = S_OK;
 +
 +    TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump (pidl);
 +
 +    if (!strRet)
 +        return E_INVALIDARG;
 +
 +    pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
 +    if (!pszPath)
 +        return E_OUTOFMEMORY;
 +
 +    pszPath[0] = 0;
 +
 +    if (!pidl->mkid.cb)
 +    {
 +        /* parsing name like ::{...} */
 +        pszPath[0] = ':';
 +        pszPath[1] = ':';
 +        SHELL32_GUIDToStringW(CLSID_MyComputer, &pszPath[2]);
 +    }
 +    else if (_ILIsPidlSimple(pidl))
 +    {
 +        /* take names of special folders only if its only this folder */
 +        if (_ILIsSpecialFolder(pidl))
 +        {
 +            GUID const *clsid;
 +
 +            clsid = _ILGetGUIDPointer (pidl);
 +            if (clsid)
 +            {
 +                if (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING)
 +                {
 +                    static const WCHAR clsidW[] = L"CLSID\\";
 +                    static const WCHAR shellfolderW[] = L"\\shellfolder";
 +                    static const WCHAR wantsForParsingW[] = L"WantsForParsing";
 +                    BOOL bWantsForParsing = FALSE;
 +                    WCHAR szRegPath[100];
 +                    LONG r;
 +
 +                    /*
 +                     * We can only get a filesystem path from a shellfolder
 +                     * if the value WantsFORPARSING exists in
 +                     *      CLSID\\{...}\\shellfolder
 +                     * exception: the MyComputer folder has this keys not
 +                     *            but like any filesystem backed
 +                     *            folder it needs these behaviour
 +                     *
 +                     * Get the "WantsFORPARSING" flag from the registry
 +                     */
 +
 +                    wcscpy(szRegPath, clsidW);
 +                    SHELL32_GUIDToStringW(*clsid, &szRegPath[6]);
 +                    wcscat(szRegPath, shellfolderW);
 +                    r = SHGetValueW(HKEY_CLASSES_ROOT, szRegPath,
 +                                    wantsForParsingW, NULL, NULL, NULL);
 +                    if (r == ERROR_SUCCESS)
 +                        bWantsForParsing = TRUE;
 +
 +                    if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
 +                            bWantsForParsing)
 +                    {
 +                        /*
 +                         * We need the filesystem path to the destination folder
 +                         * Only the folder itself can know it
 +                         */
 +                        hr = SHELL32_GetDisplayNameOfChild (this, pidl,
 +                                                            dwFlags, pszPath, MAX_PATH);
 +                    }
 +                    else
 +                    {
 +                        LPWSTR p = pszPath;
 +
 +                        /* parsing name like ::{...} */
 +                        p[0] = ':';
 +                        p[1] = ':';
 +                        p += 2;
 +                        p += SHELL32_GUIDToStringW(CLSID_MyComputer, p);
 +
 +                        /* \:: */
 +                        p[0] = '\\';
 +                        p[1] = ':';
 +                        p[2] = ':';
 +                        p += 3;
 +                        SHELL32_GUIDToStringW(*clsid, p);
 +                    }
 +                }
 +                else
 +                {
 +                    /* user friendly name */
 +
 +                    if (_ILIsMyComputer(pidl) && sName)
 +                        wcscpy(pszPath, sName);
 +                    else
 +                        HCR_GetClassNameW (*clsid, pszPath, MAX_PATH);
 +
 +                    TRACE("pszPath %s\n", debugstr_w(pszPath));
 +                }
 +            }
 +            else
 +            {
 +                /* append my own path */
 +                _ILSimpleGetTextW(pidl, pszPath, MAX_PATH);
 +            }
 +        }
 +        else if (_ILIsDrive(pidl))
 +        {
 +
 +            _ILSimpleGetTextW(pidl, pszPath, MAX_PATH);    /* append my own path */
 +            /* long view "lw_name (C:)" */
 +            if (!(dwFlags & SHGDN_FORPARSING))
 +            {
 +                WCHAR wszDrive[18] = {0};
 +                DWORD dwVolumeSerialNumber, dwMaximumComponentLength, dwFileSystemFlags;
 +                static const WCHAR wszOpenBracket[] = {' ', '(', 0};
 +                static const WCHAR wszCloseBracket[] = {')', 0};
 +
 +                lstrcpynW(wszDrive, pszPath, 4);
 +                pszPath[0] = L'\0';
 +                GetVolumeInformationW(wszDrive, pszPath,
 +                                      MAX_PATH - 7,
 +                                      &dwVolumeSerialNumber,
 +                                      &dwMaximumComponentLength, &dwFileSystemFlags, NULL, 0);
 +                pszPath[MAX_PATH-1] = L'\0';
 +                if (!wcslen(pszPath))
 +                {
 +                    UINT DriveType, ResourceId;
 +                    DriveType = GetDriveTypeW(wszDrive);
 +                    switch(DriveType)
 +                    {
 +                        case DRIVE_FIXED:
 +                            ResourceId = IDS_DRIVE_FIXED;
 +                            break;
 +                        case DRIVE_REMOTE:
 +                            ResourceId = IDS_DRIVE_NETWORK;
 +                            break;
 +                        case DRIVE_CDROM:
 +                            ResourceId = IDS_DRIVE_CDROM;
 +                            break;
 +                        default:
 +                            ResourceId = 0;
 +                    }
 +                    if (ResourceId)
 +                    {
 +                        dwFileSystemFlags = LoadStringW(shell32_hInstance, ResourceId, pszPath, MAX_PATH);
 +                        if (dwFileSystemFlags > MAX_PATH - 7)
 +                            pszPath[MAX_PATH-7] = L'\0';
 +                    }
 +                }
 +                wcscat (pszPath, wszOpenBracket);
 +                wszDrive[2] = L'\0';
 +                wcscat (pszPath, wszDrive);
 +                wcscat (pszPath, wszCloseBracket);
 +            }
 +        }
 +        else
 +        {
 +            /* Neither a shell namespace extension nor a drive letter. */
 +            ERR("Wrong pidl type\n");
 +            CoTaskMemFree(pszPath);
 +            return E_INVALIDARG;
 +        }
 +    }
 +    else
 +    {
 +        /* Complex pidl. Let the child folder do the work */
 +        hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, pszPath, MAX_PATH);
 +    }
 +
 +    if (SUCCEEDED(hr))
 +    {
 +        strRet->uType = STRRET_WSTR;
 +        strRet->pOleStr = pszPath;
 +    }
 +    else
 +        CoTaskMemFree(pszPath);
 +
 +    TRACE("-- (%p)->(%s)\n", this, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr));
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*  CDrivesFolder::SetNameOf
 +*  Changes the name of a file object or subfolder, possibly changing its item
 +*  identifier in the process.
 +*
 +* PARAMETERS
 +*  hwndOwner  [in]   Owner window for output
 +*  pidl       [in]   simple pidl of item to change
 +*  lpszName   [in]   the items new display name
 +*  dwFlags    [in]   SHGNO formatting flags
 +*  ppidlOut   [out]  simple pidl returned
 +*/
- HRESULT WINAPI CDrivesFolder::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
++HRESULT WINAPI CDrivesFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,
++                                        LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
 +{
 +    LPWSTR sName;
 +    HKEY hKey;
 +    UINT length;
 +    WCHAR szName[30];
 +
 +    TRACE("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this,
 +          hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
 +
 +    if (_ILIsDrive(pidl))
 +    {
 +        if (_ILSimpleGetTextW(pidl, szName, _countof(szName)))
 +            SetVolumeLabelW(szName, lpName);
 +        if (pPidlOut)
 +            *pPidlOut = _ILCreateDrive(szName);
 +        return S_OK;
 +    }
 +
 +
 +    if (pPidlOut != NULL)
 +        *pPidlOut = _ILCreateMyComputer();
 +
 +    length = (wcslen(lpName) + 1) * sizeof(WCHAR);
 +    sName = (LPWSTR)SHAlloc(length);
 +
 +    if (!sName)
 +        return E_OUTOFMEMORY;
 +
 +    if (RegOpenKeyExW(HKEY_CURRENT_USER,
 +                      L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
 +                      0,
 +                      KEY_WRITE,
 +                      &hKey) != ERROR_SUCCESS)
 +    {
 +        WARN("Error: failed to open registry key\n");
 +    }
 +    else
 +    {
 +        RegSetValueExW(hKey, NULL, 0, REG_SZ, (const LPBYTE)lpName, length);
 +        RegCloseKey(hKey);
 +    }
 +
 +    wcscpy(sName, lpName);
 +    SHFree(this->sName);
 +    this->sName = sName;
 +    TRACE("result %s\n", debugstr_w(sName));
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDrivesFolder::GetDefaultSearchGUID(GUID * pguid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CDrivesFolder::EnumSearches(IEnumExtraSearch ** ppenum)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CDrivesFolder::GetDefaultColumn (DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (pSort)
 +        *pSort = 0;
 +    if (pDisplay)
 +        *pDisplay = 0;
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CDrivesFolder::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +    *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CDrivesFolder::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
++HRESULT WINAPI CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +/* FIXME: drive size >4GB is rolling over */
++HRESULT WINAPI CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
 +{
 +    HRESULT hr;
 +
 +    TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
 +
 +    if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +
 +    if (!pidl)
 +    {
 +        psd->fmt = MyComputerSFHeader[iColumn].fmt;
 +        psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
 +        psd->str.uType = STRRET_CSTR;
 +        LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid,
 +                    psd->str.cStr, MAX_PATH);
 +        return S_OK;
 +    }
 +    else
 +    {
 +        char szPath[MAX_PATH];
 +        ULARGE_INTEGER ulBytes;
 +
 +        psd->str.cStr[0] = 0x00;
 +        psd->str.uType = STRRET_CSTR;
 +        switch (iColumn)
 +        {
 +            case 0:        /* name */
 +                hr = GetDisplayNameOf(pidl,
 +                                      SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
 +                break;
 +            case 1:        /* type */
 +                _ILGetFileType(pidl, psd->str.cStr, MAX_PATH);
 +                break;
 +            case 2:        /* total size */
 +                if (_ILIsDrive(pidl))
 +                {
 +                    _ILSimpleGetText (pidl, szPath, MAX_PATH);
 +                    GetDiskFreeSpaceExA (szPath, NULL, &ulBytes, NULL);
 +                    StrFormatByteSizeA (ulBytes.LowPart, psd->str.cStr, MAX_PATH);
 +                }
 +                break;
 +            case 3:        /* free size */
 +                if (_ILIsDrive(pidl))
 +                {
 +                    _ILSimpleGetText (pidl, szPath, MAX_PATH);
 +                    GetDiskFreeSpaceExA (szPath, &ulBytes, NULL, NULL);
 +                    StrFormatByteSizeA (ulBytes.LowPart, psd->str.cStr, MAX_PATH);
 +                }
 +                break;
 +        }
 +        hr = S_OK;
 +    }
 +
 +    return hr;
 +}
 +
 +HRESULT WINAPI CDrivesFolder::MapColumnToSCID(UINT column, SHCOLUMNID * pscid)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +/************************************************************************
 + *    CDrivesFolder::GetClassID
 + */
 +HRESULT WINAPI CDrivesFolder::GetClassID(CLSID *lpClassId)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!lpClassId)
 +        return E_POINTER;
 +
 +    *lpClassId = CLSID_MyComputer;
 +    return S_OK;
 +}
 +
 +/************************************************************************
 + *    CDrivesFolder::Initialize
 + *
 + * NOTES: it makes no sense to change the pidl
 + */
 +HRESULT WINAPI CDrivesFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    if (pidlRoot)
 +        SHFree((LPVOID)pidlRoot);
 +
 +    pidlRoot = ILClone(pidl);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *    CDrivesFolder::GetCurFolder
 + */
 +HRESULT WINAPI CDrivesFolder::GetCurFolder(LPITEMIDLIST *pidl)
 +{
 +    TRACE("(%p)->(%p)\n", this, pidl);
 +
 +    if (!pidl)
 +        return E_POINTER;
 +
 +    *pidl = ILClone(pidlRoot);
 +    return S_OK;
 +}
Simple merge
index 20b4642,0000000..b610f4c
mode 100644,000000..100644
--- /dev/null
@@@ -1,732 -1,0 +1,732 @@@
- HRESULT WINAPI CMyDocsFolder::ParseDisplayName (HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
-         DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
 +/*
 + *    Virtual MyDocuments Folder
 + *
 + *    Copyright 2007    Johannes Anderwald
 + *    Copyright 2009    Andrew Hill
 + *
 + * 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 (mydocs);
 +
 +/*
 +CFileSysEnumX should not exist. CMyDocsFolder should aggregate a CFSFolder which always
 +maps the contents of CSIDL_PERSONAL. Therefore, CMyDocsFolder::EnumObjects simply calls
 +CFSFolder::EnumObjects.
 +*/
 +
 +/***********************************************************************
 +*     MyDocumentsfolder implementation
 +*/
 +
 +class CFileSysEnumX :
 +    public IEnumIDListImpl
 +{
 +    private:
 +    public:
 +        CFileSysEnumX();
 +        ~CFileSysEnumX();
 +        HRESULT WINAPI Initialize(DWORD dwFlags);
 +
 +        BEGIN_COM_MAP(CFileSysEnumX)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +static const shvheader MyDocumentsSFHeader[] = {
 +    {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
 +    {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
 +};
 +
 +#define MYDOCUMENTSSHELLVIEWCOLUMNS 5
 +
 +CFileSysEnumX::CFileSysEnumX()
 +{
 +}
 +
 +CFileSysEnumX::~CFileSysEnumX()
 +{
 +}
 +
 +HRESULT WINAPI CFileSysEnumX::Initialize(DWORD dwFlags)
 +{
 +    WCHAR                                szPath[MAX_PATH];
 +
 +    if (SHGetSpecialFolderPathW(0, szPath, CSIDL_PERSONAL, FALSE) == FALSE)
 +        return E_FAIL;
 +    return CreateFolderEnumList(szPath, dwFlags);
 +}
 +
 +CMyDocsFolder::CMyDocsFolder()
 +{
 +    pidlRoot = NULL;
 +    sPathTarget = NULL;
 +    mFSDropTarget = NULL;
 +}
 +
 +CMyDocsFolder::~CMyDocsFolder()
 +{
 +    TRACE ("-- destroying IShellFolder(%p)\n", this);
 +    SHFree(pidlRoot);
 +    HeapFree(GetProcessHeap(), 0, sPathTarget);
 +    mFSDropTarget->Release();
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::FinalConstruct()
 +{
 +    WCHAR                                szMyPath[MAX_PATH];
 +
 +    if (!SHGetSpecialFolderPathW(0, szMyPath, CSIDL_PERSONAL, TRUE))
 +        return E_UNEXPECTED;
 +
 +    pidlRoot = _ILCreateMyDocuments();    /* my qualified pidl */
 +    sPathTarget = (LPWSTR)SHAlloc((wcslen(szMyPath) + 1) * sizeof(WCHAR));
 +    wcscpy(sPathTarget, szMyPath);
 +
 +    LPITEMIDLIST pidl = NULL;
 +
 +    WCHAR szPath[MAX_PATH];
 +    lstrcpynW(szPath, sPathTarget, MAX_PATH);
 +    PathAddBackslashW(szPath);
 +    CComPtr<IShellFolder> psfDesktop = NULL;
 +    
 +    HRESULT hr = SHGetDesktopFolder(&psfDesktop);
 +    if (SUCCEEDED(hr))
 +        hr = psfDesktop->ParseDisplayName(NULL, NULL, szPath, NULL, &pidl, NULL);
 +    else
 +        ERR("Error getting desktop folder\n");
 +
 +    if (SUCCEEDED(hr))
 +    {
 +        hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IDropTarget, &mFSDropTarget));
 +        CoTaskMemFree(pidl);
 +        if (FAILED(hr))
 +            ERR("Error Binding");
 +    }
 +    else
 +        ERR("Error creating from %s\n", debugstr_w(szPath));
 +
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CMyDocsFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++HRESULT WINAPI CMyDocsFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
++        DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
 +{
 +    WCHAR szElement[MAX_PATH];
 +    LPCWSTR szNext = NULL;
 +    LPITEMIDLIST pidlTemp = NULL;
 +    HRESULT hr = S_OK;
 +    CLSID clsid;
 +
 +    TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
 +           this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
 +           pchEaten, ppidl, pdwAttributes);
 +
 +    if (!lpszDisplayName || !ppidl)
 +        return E_INVALIDARG;
 +
 +    *ppidl = 0;
 +
 +    if (pchEaten)
 +        *pchEaten = 0;        /* strange but like the original */
 +
 +    if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
 +    {
 +        szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
 +        TRACE("-- element: %s\n", debugstr_w (szElement));
 +        CLSIDFromString(szElement + 2, &clsid);
 +        pidlTemp = _ILCreateGuid (PT_GUID, clsid);
 +    }
 +    else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) )
 +    {
 +        *ppidl = pidlTemp;
 +        return S_OK;
 +    }
 +    else
 +    {
 +        /* it's a filesystem path on the desktop. Let a FSFolder parse it */
 +
 +        if (*lpszDisplayName)
 +        {
 +            WCHAR szPath[MAX_PATH];
 +            LPWSTR pathPtr;
 +
 +            /* build a complete path to create a simple pidl */
 +            lstrcpynW(szPath, sPathTarget, MAX_PATH);
 +            pathPtr = PathAddBackslashW(szPath);
 +            if (pathPtr)
 +            {
 +                lstrcpynW(pathPtr, lpszDisplayName, MAX_PATH - (pathPtr - szPath));
 +                hr = _ILCreateFromPathW(szPath, &pidlTemp);
 +            }
 +            else
 +            {
 +                /* should never reach here, but for completeness */
 +                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
 +            }
 +        }
 +        else
 +            pidlTemp = _ILCreateMyDocuments();
 +
 +        szNext = NULL;
 +    }
 +
 +    if (SUCCEEDED(hr) && pidlTemp)
 +    {
 +        if (szNext && *szNext)
 +        {
 +            hr = SHELL32_ParseNextElement(this, hwndOwner, pbc,
 +                                          &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
 +        }
 +        else
 +        {
 +            if (pdwAttributes && *pdwAttributes)
 +                hr = SHELL32_GetItemAttributes(this, pidlTemp, pdwAttributes);
 +        }
 +    }
 +
 +    *ppidl = pidlTemp;
 +
 +    TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *        ISF_MyDocuments_fnEnumObjects
 + */
 +HRESULT WINAPI CMyDocsFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
 +{
 +    CComObject<CFileSysEnumX>                *theEnumerator;
 +    CComPtr<IEnumIDList>                    result;
 +    HRESULT                                    hResult;
 +
 +    TRACE("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +    *ppEnumIDList = NULL;
 +    ATLTRY (theEnumerator = new CComObject<CFileSysEnumX>);
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theEnumerator->QueryInterface(IID_IEnumIDList, (void **)&result);
 +    if (FAILED (hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +    hResult = theEnumerator->Initialize(dwFlags);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach();
 +
 +    TRACE("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *        CMyDocsFolder::BindToObject
 + */
- HRESULT WINAPI CMyDocsFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++HRESULT WINAPI CMyDocsFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    TRACE("(%p)->(pidl=%p,%p,%s,%p)\n",
 +           this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    return SHELL32_BindToChild( pidlRoot, sPathTarget, pidl, riid, ppvOut );
 +}
 +
 +/**************************************************************************
 + *    CMyDocsFolder::BindToStorage
 + */
- HRESULT WINAPI CMyDocsFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++HRESULT WINAPI CMyDocsFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n",
 +           this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 + *     CMyDocsFolder::CompareIDs
 + */
- HRESULT WINAPI CMyDocsFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl, DWORD *rgfInOut)
++HRESULT WINAPI CMyDocsFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs (this, lParam, pidl1, pidl2);
 +    TRACE ("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 + *    CMyDocsFolder::CreateViewObject
 + */
 +HRESULT WINAPI CMyDocsFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
 +{
 +    CComPtr<IShellView> pShellView;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
 +           this, hwndOwner, shdebugstr_guid (&riid), ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IDropTarget))
 +    {
 +        hr = this->QueryInterface (IID_IDropTarget, ppvOut);
 +    }
 +    else if (IsEqualIID (riid, IID_IContextMenu))
 +    {
 +        WARN ("IContextMenu not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID (riid, IID_IShellView))
 +    {
 +        hr = IShellView_Constructor ((IShellFolder *)this, &pShellView);
 +        if (pShellView)
 +        {
 +            hr = pShellView->QueryInterface(riid, ppvOut);
 +        }
 +    }
 +    TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *  CMyDocsFolder::GetAttributesOf
 + */
- HRESULT WINAPI CMyDocsFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl,
++HRESULT WINAPI CMyDocsFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
 +{
 +    HRESULT hr = S_OK;
 +    static const DWORD dwMyDocumentsAttributes =
 +        SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_CANCOPY |
 +        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
 +
 +    TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
 +           this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
 +
 +    if (!rgfInOut)
 +        return E_INVALIDARG;
 +    if (cidl && !apidl)
 +        return E_INVALIDARG;
 +
 +    if (*rgfInOut == 0)
 +        *rgfInOut = ~0;
 +
 +    if(cidl == 0) {
 +        *rgfInOut &= dwMyDocumentsAttributes;
 +    } else {
 +        while (cidl > 0 && *apidl) {
 +            pdump (*apidl);
 +            if (_ILIsMyDocuments(*apidl)) {
 +                *rgfInOut &= dwMyDocumentsAttributes;
 +            } else {
 +                SHELL32_GetItemAttributes (this, *apidl, rgfInOut);
 +            }
 +            apidl++;
 +            cidl--;
 +        }
 +    }
 +    /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE ("-- result=0x%08x\n", *rgfInOut);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *    CMyDocsFolder::GetUIObjectOf
 + *
 + * PARAMETERS
 + *  HWND           hwndOwner, //[in ] Parent window for any output
 + *  UINT           cidl,      //[in ] array size
 + *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
 + *  REFIID         riid,      //[in ] Requested Interface
 + *  UINT*          prgfInOut, //[   ] reserved
 + *  LPVOID*        ppvObject) //[out] Resulting Interface
 + *
 + */
- HRESULT WINAPI CMyDocsFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
++HRESULT WINAPI CMyDocsFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
 +        REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
 +{
 +    LPITEMIDLIST pidl;
 +    IUnknown *pObj = NULL;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
 +           this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID (riid, IID_IContextMenu))
 +    {
 +        IContextMenu  * pCm = NULL;
 +        hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, 0, NULL, &pCm);
 +        pObj = pCm;
 +    }
 +    else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
 +    {
 +        IDataObject * pDo = NULL;
 +        hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, &pDo);
 +        pObj = pDo;
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconA_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconW_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
 +    {
 +        IDropTarget * pDt = NULL;
 +        hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
 +        pObj = pDt;
 +    }
 +    else if ((IsEqualIID(riid, IID_IShellLinkW) ||
 +              IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
 +        SHFree (pidl);
 +    }
 +    else
 +        hr = E_NOINTERFACE;
 +
 +    if (SUCCEEDED(hr) && !pObj)
 +        hr = E_OUTOFMEMORY;
 +
 +    *ppvOut = pObj;
 +    TRACE ("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
- HRESULT WINAPI CMyDocsFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,    /* simple pidl */
-                                         LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
++HRESULT WINAPI CMyDocsFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 +{
 +    HRESULT hr = S_OK;
 +    LPWSTR pszPath;
 +
 +    TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump (pidl);
 +
 +    if (!strRet)
 +        return E_INVALIDARG;
 +
 +    pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
 +    if (!pszPath)
 +        return E_OUTOFMEMORY;
 +
 +    ZeroMemory(pszPath, (MAX_PATH + 1) * sizeof(WCHAR));
 +
 +    if (_ILIsMyDocuments (pidl))
 +    {
 +        if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
 +                (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING))
 +            wcscpy(pszPath, sPathTarget);
 +        else
 +            HCR_GetClassNameW(CLSID_MyDocuments, pszPath, MAX_PATH);
 +        TRACE("CP\n");
 +    }
 +    else if (_ILIsPidlSimple (pidl))
 +    {
 +        GUID const *clsid;
 +
 +        if ((clsid = _ILGetGUIDPointer (pidl)))
 +        {
 +            if (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING)
 +            {
 +                int bWantsForParsing;
 +
 +                /*
 +                 * We can only get a filesystem path from a shellfolder if the
 +                 *  value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
 +                 *
 +                 * Exception: The MyComputer folder doesn't have this key,
 +                 *   but any other filesystem backed folder it needs it.
 +                 */
 +                if (IsEqualIID (*clsid, CLSID_MyDocuments))
 +                {
 +                    bWantsForParsing = TRUE;
 +                }
 +                else
 +                {
 +                    /* get the "WantsFORPARSING" flag from the registry */
 +                    static const WCHAR clsidW[] = L"CLSID\\";
 +                    static const WCHAR shellfolderW[] = L"shellfolder";
 +                    static const WCHAR wantsForParsingW[] = L"WantsForParsing";
 +                    WCHAR szRegPath[100];
 +                    LONG r;
 +
 +                    wcscpy (szRegPath, clsidW);
 +                    SHELL32_GUIDToStringW (*clsid, &szRegPath[6]);
 +                    wcscat (szRegPath, shellfolderW);
 +                    r = SHGetValueW(HKEY_CLASSES_ROOT, szRegPath,
 +                                    wantsForParsingW, NULL, NULL, NULL);
 +                    if (r == ERROR_SUCCESS)
 +                        bWantsForParsing = TRUE;
 +                    else
 +                        bWantsForParsing = FALSE;
 +                }
 +
 +                if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
 +                        bWantsForParsing)
 +                {
 +                    /*
 +                     * we need the filesystem path to the destination folder.
 +                     * Only the folder itself can know it
 +                     */
 +                    hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags,
 +                                                        pszPath,
 +                                                        MAX_PATH);
 +                    TRACE("CP\n");
 +                }
 +                else
 +                {
 +                    /* parsing name like ::{...} */
 +                    pszPath[0] = ':';
 +                    pszPath[1] = ':';
 +                    SHELL32_GUIDToStringW (*clsid, &pszPath[2]);
 +                    TRACE("CP\n");
 +                }
 +            }
 +            else
 +            {
 +                /* user friendly name */
 +                HCR_GetClassNameW (*clsid, pszPath, MAX_PATH);
 +                TRACE("CP\n");
 +            }
 +        }
 +        else
 +        {
 +            int cLen = 0;
 +
 +            /* file system folder or file rooted at the desktop */
 +            if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) &&
 +                    (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
 +            {
 +                lstrcpynW(pszPath, sPathTarget, MAX_PATH - 1);
 +                TRACE("CP %s\n", debugstr_w(pszPath));
 +            }
 +
 +            if (!_ILIsDesktop(pidl))
 +            {
 +                PathAddBackslashW(pszPath);
 +                cLen = wcslen(pszPath);
 +                _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen);
 +                if (!_ILIsFolder(pidl))
 +                {
 +                    SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
 +                    TRACE("CP\n");
 +                }
 +            }
 +        }
 +    }
 +    else
 +    {
 +        /* a complex pidl, let the subfolder do the work */
 +        hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags,
 +                                            pszPath, MAX_PATH);
 +        TRACE("CP\n");
 +    }
 +
 +    if (SUCCEEDED(hr))
 +    {
 +        strRet->uType = STRRET_WSTR;
 +        strRet->pOleStr = pszPath;
 +    }
 +    else
 +        CoTaskMemFree(pszPath);
 +
 +    TRACE ("-- (%p)->(%s,0x%08x)\n", this, debugstr_w(strRet->pOleStr), hr);
 +    return hr;
 +}
 +
- HRESULT WINAPI CMyDocsFolder::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
++HRESULT WINAPI CMyDocsFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,    /* simple pidl */
++                                        LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
 +{
 +    FIXME ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl,
 +           debugstr_w (lpName), dwFlags, pPidlOut);
 +
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::GetDefaultSearchGUID(GUID *pguid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::EnumSearches(IEnumExtraSearch **ppenum)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (pSort)
 +        *pSort = 0;
 +    if (pDisplay)
 +        *pDisplay = 0;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!pcsFlags || iColumn >= MYDOCUMENTSSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +
 +    *pcsFlags = MyDocumentsSFHeader[iColumn].pcsFlags;
 +
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CMyDocsFolder::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
++HRESULT WINAPI CMyDocsFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
 +{
 +    FIXME ("(%p)\n", this);
 +
 +    return E_NOTIMPL;
 +}
 +
++HRESULT WINAPI CMyDocsFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
 +{
 +    HRESULT hr = S_OK;
 +
 +    TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
 +
 +    if (!psd || iColumn >= MYDOCUMENTSSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +
 +    if (!pidl)
 +    {
 +        psd->fmt = MyDocumentsSFHeader[iColumn].fmt;
 +        psd->cxChar = MyDocumentsSFHeader[iColumn].cxChar;
 +        psd->str.uType = STRRET_CSTR;
 +        LoadStringA (shell32_hInstance, MyDocumentsSFHeader[iColumn].colnameid,
 +                     psd->str.cStr, MAX_PATH);
 +        return S_OK;
 +    }
 +
 +    /* the data from the pidl */
 +    psd->str.uType = STRRET_CSTR;
 +    switch (iColumn)
 +    {
 +        case 0:        /* name */
 +            hr = GetDisplayNameOf(pidl,
 +                                  SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
 +            break;
 +        case 1:        /* size */
 +            _ILGetFileSize (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +        case 2:        /* type */
 +            _ILGetFileType (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +        case 3:        /* date */
 +            _ILGetFileDate (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +        case 4:        /* attributes */
 +            _ILGetFileAttributes (pidl, psd->str.cStr, MAX_PATH);
 +            break;
 +    }
 +
 +    return hr;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::MapColumnToSCID (UINT column, SHCOLUMNID *pscid)
 +{
 +    FIXME ("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::GetClassID(CLSID *lpClassId)
 +{
 +    static GUID const CLSID_MyDocuments =
 +    { 0x450d8fba, 0xad25, 0x11d0, {0x98, 0xa8, 0x08, 0x00, 0x36, 0x1b, 0x11, 0x03} };
 +
 +    TRACE ("(%p)\n", this);
 +
 +    if (!lpClassId)
 +        return E_POINTER;
 +
 +    memcpy(lpClassId, &CLSID_MyDocuments, sizeof(GUID));
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::GetCurFolder(LPITEMIDLIST *pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    if (!pidl) return E_POINTER;
 +    *pidl = ILClone (pidlRoot);
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::DragEnter(IDataObject *pDataObject,
 +                                    DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    return mFSDropTarget->DragEnter(pDataObject, dwKeyState, pt, pdwEffect);
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::DragOver(DWORD dwKeyState, POINTL pt,
 +                                   DWORD *pdwEffect)
 +{
 +    return mFSDropTarget->DragOver(dwKeyState, pt, pdwEffect);
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::DragLeave()
 +{
 +    return mFSDropTarget->DragLeave();
 +}
 +
 +HRESULT WINAPI CMyDocsFolder::Drop(IDataObject *pDataObject,
 +                               DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    return mFSDropTarget->Drop(pDataObject, dwKeyState, pt, pdwEffect);
 +}
index 198dde0,0000000..3630394
mode 100644,000000..100644
--- /dev/null
@@@ -1,436 -1,0 +1,436 @@@
-         DWORD *pchEaten, LPITEMIDLIST *ppidl, DWORD *pdwAttributes)
 +/*
 + *    Network Places (Neighbourhood) folder
 + *
 + *    Copyright 1997                Marcus Meissner
 + *    Copyright 1998, 1999, 2002    Juergen Schmied
 + *    Copyright 2003              Mike McCormack for Codeweavers
 + *    Copyright 2009              Andrew Hill
 + *
 + * 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);
 +
 +/***********************************************************************
 +*   IShellFolder implementation
 +*/
 +
 +static shvheader NetworkPlacesSFHeader[] = {
 +    {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN13, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
 +    {IDS_SHV_COLUMN_WORKGROUP, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_NETWORKLOCATION, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}
 +};
 +
 +#define COLUMN_NAME          0
 +#define COLUMN_CATEGORY      1
 +#define COLUMN_WORKGROUP     2
 +#define COLUMN_NETLOCATION   3
 +
 +#define NETWORKPLACESSHELLVIEWCOLUMNS 4
 +
 +CNetFolder::CNetFolder()
 +{
 +    pidlRoot = NULL;
 +}
 +
 +CNetFolder::~CNetFolder()
 +{
 +    TRACE("-- destroying IShellFolder(%p)\n", this);
 +    SHFree(pidlRoot);
 +}
 +
 +HRESULT WINAPI CNetFolder::FinalConstruct()
 +{
 +    pidlRoot = _ILCreateNetHood();    /* my qualified pidl */
 +    if (pidlRoot == NULL)
 +        return E_OUTOFMEMORY;
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +*    CNetFolder::ParseDisplayName
 +*/
 +HRESULT WINAPI CNetFolder::ParseDisplayName(HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName,
- HRESULT WINAPI CNetFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++        DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
 +{
 +    HRESULT hr = E_UNEXPECTED;
 +
 +    TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
 +          hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName),
 +          pchEaten, ppidl, pdwAttributes);
 +
 +    *ppidl = 0;
 +    if (pchEaten)
 +        *pchEaten = 0;        /* strange but like the original */
 +
 +    TRACE("(%p)->(-- ret=0x%08x)\n", this, hr);
 +
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*        CNetFolder::EnumObjects
 +*/
 +HRESULT WINAPI CNetFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
 +{
 +    TRACE("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this,
 +          hwndOwner, dwFlags, ppEnumIDList);
 +
 +    *ppEnumIDList = NULL; //IEnumIDList_Constructor();
 +
 +    TRACE("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +    return S_FALSE;
 +    // return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
 +}
 +
 +/**************************************************************************
 +*        CNetFolder::BindToObject
 +*/
- HRESULT WINAPI CNetFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
++HRESULT WINAPI CNetFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this,
 +           pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
 +}
 +
 +/**************************************************************************
 +*    CNetFolder::BindToStorage
 +*/
- HRESULT WINAPI CNetFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++HRESULT WINAPI CNetFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
 +{
 +    FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
 +          pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 +*     CNetFolder::CompareIDs
 +*/
 +
- HRESULT WINAPI CNetFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl, DWORD *rgfInOut)
++HRESULT WINAPI CNetFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs(this, lParam, pidl1, pidl2);
 +    TRACE("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 +*    CNetFolder::CreateViewObject
 +*/
 +HRESULT WINAPI CNetFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
 +{
 +    CComPtr<IShellView> pShellView;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
 +          hwndOwner, shdebugstr_guid (&riid), ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID(riid, IID_IDropTarget))
 +    {
 +        WARN("IDropTarget not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID(riid, IID_IContextMenu))
 +    {
 +        WARN("IContextMenu not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if (IsEqualIID(riid, IID_IShellView))
 +    {
 +        hr = IShellView_Constructor((IShellFolder *)this, &pShellView);
 +        if (pShellView)
 +        {
 +            hr = pShellView->QueryInterface(riid, ppvOut);
 +        }
 +    }
 +    TRACE("-- (%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*  CNetFolder::GetAttributesOf
 +*/
- HRESULT WINAPI CNetFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl, REFIID riid,
++HRESULT WINAPI CNetFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
 +{
 +    static const DWORD dwNethoodAttributes =
 +        SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
 +        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
 +    HRESULT hr = S_OK;
 +
 +    TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", this,
 +          cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
 +
 +    if (!rgfInOut)
 +        return E_INVALIDARG;
 +    if (cidl && !apidl)
 +        return E_INVALIDARG;
 +
 +    if (*rgfInOut == 0)
 +        *rgfInOut = ~0;
 +
 +    if(cidl == 0)
 +        *rgfInOut = dwNethoodAttributes;
 +    else
 +    {
 +        while (cidl > 0 && *apidl)
 +        {
 +            pdump(*apidl);
 +            SHELL32_GetItemAttributes(this, *apidl, rgfInOut);
 +            apidl++;
 +            cidl--;
 +        }
 +    }
 +
 +    /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE("-- result=0x%08x\n", *rgfInOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*    CNetFolder::GetUIObjectOf
 +*
 +* PARAMETERS
 +*  hwndOwner [in]  Parent window for any output
 +*  cidl      [in]  array size
 +*  apidl     [in]  simple pidl array
 +*  riid      [in]  Requested Interface
 +*  prgfInOut [   ] reserved
 +*  ppvObject [out] Resulting Interface
 +*
 +*/
- HRESULT WINAPI CNetFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
++HRESULT WINAPI CNetFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
 +        UINT * prgfInOut, LPVOID * ppvOut)
 +{
 +    LPITEMIDLIST pidl;
 +    IUnknown *pObj = NULL;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
 +          hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1))
 +    {
 +        IContextMenu  * pCm = NULL;
 +        hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, 0, NULL, &pCm);
 +        pObj = pCm;
 +    }
 +    else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1))
 +    {
 +        IDataObject * pDo = NULL;
 +        hr = IDataObject_Constructor (hwndOwner, pidlRoot, apidl, cidl, &pDo);
 +        pObj = pDo;
 +    }
 +    else if (IsEqualIID(riid, IID_IExtractIconA) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconA_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID(riid, IID_IExtractIconW) && (cidl == 1))
 +    {
 +        pidl = ILCombine (pidlRoot, apidl[0]);
 +        pObj = IExtractIconW_Constructor (pidl);
 +        SHFree (pidl);
 +        hr = S_OK;
 +    }
 +    else if (IsEqualIID(riid, IID_IDropTarget) && (cidl >= 1))
 +    {
 +        IDropTarget * pDt = NULL;
 +        hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
 +        pObj = pDt;
 +    }
 +    else
 +        hr = E_NOINTERFACE;
 +
 +    if (SUCCEEDED(hr) && !pObj)
 +        hr = E_OUTOFMEMORY;
 +
 +    *ppvOut = pObj;
 +    TRACE("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
 +/**************************************************************************
 +*    CNetFolder::GetDisplayNameOf
 +*
 +*/
- HRESULT WINAPI CNetFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,    /*simple pidl */
-                                      LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
++HRESULT WINAPI CNetFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 +{
 +    FIXME("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump(pidl);
 +
 +    if (!strRet)
 +        return E_INVALIDARG;
 +
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 +*  CNetFolder::SetNameOf
 +*  Changes the name of a file object or subfolder, possibly changing its item
 +*  identifier in the process.
 +*
 +* PARAMETERS
 +*  hwndOwner [in]  Owner window for output
 +*  pidl      [in]  simple pidl of item to change
 +*  lpszName  [in]  the items new display name
 +*  dwFlags   [in]  SHGNO formatting flags
 +*  ppidlOut  [out] simple pidl returned
 +*/
- HRESULT WINAPI CNetFolder::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
++HRESULT WINAPI CNetFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,    /*simple pidl */
++                                     LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
 +{
 +    FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this,
 +          hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CNetFolder::GetDefaultSearchGUID(GUID *pguid)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CNetFolder::EnumSearches(IEnumExtraSearch ** ppenum)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CNetFolder::GetDefaultColumn (DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (pSort)
 +        *pSort = 0;
 +    if (pDisplay)
 +        *pDisplay = 0;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CNetFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (!pcsFlags || iColumn >= NETWORKPLACESSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +    *pcsFlags = NetworkPlacesSFHeader[iColumn].pcsFlags;
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CNetFolder::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
++HRESULT WINAPI CNetFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
++HRESULT WINAPI CNetFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
 +{
 +    WCHAR buffer[MAX_PATH] = {0};
 +    HRESULT hr = E_FAIL;
 +
 +    if (iColumn >= NETWORKPLACESSHELLVIEWCOLUMNS)
 +        return E_FAIL;
 +
 +    psd->fmt = NetworkPlacesSFHeader[iColumn].fmt;
 +    psd->cxChar = NetworkPlacesSFHeader[iColumn].cxChar;
 +    if (pidl == NULL)
 +    {
 +        psd->str.uType = STRRET_WSTR;
 +        if (LoadStringW(shell32_hInstance, NetworkPlacesSFHeader[iColumn].colnameid, buffer, _countof(buffer)))
 +            hr = SHStrDupW(buffer, &psd->str.pOleStr);
 +
 +        return hr;
 +    }
 +
 +    if (iColumn == COLUMN_NAME)
 +        return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
 +
 +    FIXME("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
 +
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CNetFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
 +{
 +    FIXME("(%p)\n", this);
 +
 +    return E_NOTIMPL;
 +}
 +
 +/************************************************************************
 + *    CNetFolder::GetClassID
 + */
 +HRESULT WINAPI CNetFolder::GetClassID(CLSID *lpClassId)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (!lpClassId)
 +        return E_POINTER;
 +
 +    *lpClassId = CLSID_NetworkPlaces;
 +
 +    return S_OK;
 +}
 +
 +/************************************************************************
 + *    CNetFolder::Initialize
 + *
 + * NOTES: it makes no sense to change the pidl
 + */
 +HRESULT WINAPI CNetFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    TRACE("(%p)->(%p)\n", this, pidl);
 +
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 + *    CNetFolder::GetCurFolder
 + */
 +HRESULT WINAPI CNetFolder::GetCurFolder(LPITEMIDLIST *pidl)
 +{
 +    TRACE("(%p)->(%p)\n", this, pidl);
 +
 +    if (!pidl)
 +        return E_POINTER;
 +
 +    *pidl = ILClone(pidlRoot);
 +
 +    return S_OK;
 +}
Simple merge
index 10c17a5,0000000..2e794af
mode 100644,000000..100644
--- /dev/null
@@@ -1,726 -1,0 +1,726 @@@
-         DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
 +/*
 + *    Virtual Printers Folder
 + *
 + *    Copyright 1997                Marcus Meissner
 + *    Copyright 1998, 1999, 2002    Juergen Schmied
 + *    Copyright 2005                Huw Davies
 + *    Copyright 2009                Andrew Hill
 + *
 + * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 + */
 +
 +#include <precomp.h>
 +
 +#include <winspool.h>
 +
 +WINE_DEFAULT_DEBUG_CHANNEL (shell);
 +
 +/***********************************************************************
 + *   Printers_IExtractIconW implementation
 + */
 +class CPrintersExtractIconW :
 +    public CComObjectRootEx<CComMultiThreadModelNoCS>,
 +    public IExtractIconW,
 +    public IExtractIconA
 +{
 +    private:
 +        LPITEMIDLIST                        pidl;
 +    public:
 +        CPrintersExtractIconW();
 +        ~CPrintersExtractIconW();
 +        HRESULT WINAPI Initialize(LPCITEMIDLIST pidl);
 +
 +        // IExtractIconW
 +        virtual HRESULT STDMETHODCALLTYPE GetIconLocation(UINT uFlags, LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags);
 +        virtual HRESULT STDMETHODCALLTYPE Extract(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
 +
 +        // IExtractIconA
 +        virtual HRESULT STDMETHODCALLTYPE GetIconLocation(UINT uFlags, LPSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags);
 +        virtual HRESULT STDMETHODCALLTYPE Extract(LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
 +
 +        BEGIN_COM_MAP(CPrintersExtractIconW)
 +        COM_INTERFACE_ENTRY_IID(IID_IExtractIconW, IExtractIconW)
 +        COM_INTERFACE_ENTRY_IID(IID_IExtractIconA, IExtractIconA)
 +        END_COM_MAP()
 +};
 +
 +static shvheader PrinterSFHeader[] = {
 +    {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN_DOCUMENTS , SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN_STATUS, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN_COMMENTS, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN_LOCATION, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
 +    {IDS_SHV_COLUMN_MODEL, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}
 +};
 +
 +#define COLUMN_NAME          0
 +#define COLUMN_DOCUMENTS     1
 +#define COLUMN_STATUS        2
 +#define COLUMN_COMMENTS      3
 +#define COLUMN_LOCATION      4
 +#define COLUMN_MODEL         5
 +
 +
 +#define PrinterSHELLVIEWCOLUMNS (6)
 +
 +CPrintersExtractIconW::CPrintersExtractIconW()
 +{
 +    pidl = NULL;
 +}
 +
 +CPrintersExtractIconW::~CPrintersExtractIconW()
 +{
 +    TRACE(" destroying IExtractIcon(%p)\n", this);
 +    SHFree(pidl);
 +}
 +
 +HRESULT WINAPI CPrintersExtractIconW::Initialize(LPCITEMIDLIST pidl)
 +{
 +    pidl = ILClone(pidl);
 +
 +    pdump(pidl);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *  CPrintersExtractIconW::GetIconLocation
 + *
 + * mapping filetype to icon
 + */
 +HRESULT WINAPI CPrintersExtractIconW::GetIconLocation(UINT uFlags,        /* GIL_ flags */
 +        LPWSTR szIconFile,
 +        UINT cchMax,
 +        int *piIndex,
 +        UINT *pwFlags)        /* returned GIL_ flags */
 +{
 +    TRACE("(%p) (flags=%u %p %u %p %p)\n", this, uFlags, szIconFile, cchMax, piIndex, pwFlags);
 +
 +    if (pwFlags)
 +        *pwFlags = 0;
 +
 +    lstrcpynW(szIconFile, swShell32Name, cchMax);
 +    *piIndex = -IDI_SHELL_PRINTERS_FOLDER; /* FIXME: other icons for default, network, print to file */
 +
 +    TRACE("-- %s %x\n", debugstr_w(szIconFile), *piIndex);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *  CPrintersExtractIconW::Extract
 + */
 +HRESULT WINAPI CPrintersExtractIconW::Extract(LPCWSTR pszFile,
 +        UINT nIconIndex, HICON *phiconLarge,
 +        HICON *phiconSmall, UINT nIconSize)
 +{
 +    int index;
 +
 +    FIXME("(%p) (file=%p index=%d %p %p size=%x) semi-stub\n", this, debugstr_w(pszFile),
 +          (signed)nIconIndex, phiconLarge, phiconSmall, nIconSize);
 +
 +    index = SIC_GetIconIndex(pszFile, nIconIndex, 0);
 +
 +    if (phiconLarge)
 +        *phiconLarge = ImageList_GetIcon(ShellBigIconList, index, ILD_TRANSPARENT);
 +
 +    if (phiconSmall)
 +        *phiconSmall = ImageList_GetIcon(ShellSmallIconList, index, ILD_TRANSPARENT);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *  CPrintersExtractIconW::GetIconLocation
 + */
 +HRESULT WINAPI CPrintersExtractIconW::GetIconLocation(UINT uFlags,
 +        LPSTR szIconFile,
 +        UINT cchMax,
 +        int * piIndex,
 +        UINT * pwFlags)
 +{
 +    HRESULT ret;
 +    LPWSTR lpwstrFile = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cchMax * sizeof(WCHAR));
 +
 +    TRACE("(%p) (flags=%u %p %u %p %p)\n", this, uFlags, szIconFile, cchMax, piIndex, pwFlags);
 +
 +    ret = GetIconLocation(uFlags, lpwstrFile, cchMax, piIndex, pwFlags);
 +    WideCharToMultiByte(CP_ACP, 0, lpwstrFile, -1, szIconFile, cchMax, NULL, NULL);
 +    HeapFree(GetProcessHeap(), 0, lpwstrFile);
 +
 +    TRACE("-- %s %x\n", szIconFile, *piIndex);
 +    return ret;
 +}
 +/**************************************************************************
 + *  CPrintersExtractIconW::Extract
 + */
 +HRESULT WINAPI CPrintersExtractIconW::Extract(LPCSTR pszFile,
 +        UINT nIconIndex, HICON *phiconLarge,
 +        HICON *phiconSmall, UINT nIconSize)
 +{
 +    HRESULT ret;
 +    INT len = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0);
 +    LPWSTR lpwstrFile = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +
 +    TRACE("(%p) (file=%p index=%u %p %p size=%u)\n", this, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
 +
 +    MultiByteToWideChar(CP_ACP, 0, pszFile, -1, lpwstrFile, len);
 +    ret = Extract(lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
 +    HeapFree(GetProcessHeap(), 0, lpwstrFile);
 +    return ret;
 +}
 +
 +/**************************************************************************
 + *  IExtractIcon_Constructor
 + */
 +static HRESULT WINAPI IEI_Printers_Constructor(LPCITEMIDLIST pidl, REFIID riid, IUnknown **ppv)
 +{
 +    CComObject<CPrintersExtractIconW> *theExtractor;
 +    CComPtr<IUnknown>                 result;
 +    HRESULT                           hResult;
 +
 +    if (ppv == NULL)
 +        return E_POINTER;
 +    *ppv = NULL;
 +    ATLTRY (theExtractor = new CComObject<CPrintersExtractIconW>);
 +    if (theExtractor == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theExtractor->QueryInterface(riid, (void **)&result);
 +    if (FAILED (hResult))
 +    {
 +        delete theExtractor;
 +        return hResult;
 +    }
 +    hResult = theExtractor->Initialize(pidl);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppv = result.Detach();
 +    return S_OK;
 +}
 +
 +/***********************************************************************
 + *     Printers folder implementation
 + */
 +
 +class CPrintersEnum: public IEnumIDListImpl
 +{
 +    public:
 +        CPrintersEnum();
 +        ~CPrintersEnum();
 +        HRESULT WINAPI Initialize(HWND hwndOwner, DWORD dwFlags);
 +        BOOL CreatePrintersEnumList(DWORD dwFlags);
 +
 +        BEGIN_COM_MAP(CPrintersEnum)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +CPrintersEnum::CPrintersEnum()
 +{
 +}
 +
 +CPrintersEnum::~CPrintersEnum()
 +{
 +}
 +
 +HRESULT WINAPI CPrintersEnum::Initialize(HWND hwndOwner, DWORD dwFlags)
 +{
 +    if (CreatePrintersEnumList(dwFlags) == FALSE)
 +        return E_FAIL;
 +    return S_OK;
 +}
 +
 +static LPITEMIDLIST _ILCreatePrinterItem(PRINTER_INFO_4W *pi)
 +{
 +    PIDLDATA tmp;
 +    LPITEMIDLIST pidl;
 +    PIDLPrinterStruct * p;
 +    int size0 = (char*)&tmp.u.cprinter.szName - (char*)&tmp.u.cprinter;
 +    int size = size0;
 +
 +    tmp.type = 0x00;
 +    tmp.u.cprinter.dummy = 0xFF;
 +    if (pi->pPrinterName)
 +        tmp.u.cprinter.offsServer = wcslen(pi->pPrinterName) + 1;
 +    else
 +        tmp.u.cprinter.offsServer = 1;
 +
 +    size += tmp.u.cprinter.offsServer * sizeof(WCHAR);
 +    if (pi->pServerName)
 +        size += (wcslen(pi->pServerName) + 1) * sizeof(WCHAR);
 +    else
 +        size += sizeof(WCHAR);
 +
 +    pidl = (LPITEMIDLIST)SHAlloc(size + 4);
 +    if (!pidl)
 +        return pidl;
 +
 +    pidl->mkid.cb = size + 2;
 +    memcpy(pidl->mkid.abID, &tmp, 2 + size0);
 +
 +    p = &((PIDLDATA*)pidl->mkid.abID)->u.cprinter;
 +
 +    p->Attributes = pi->Attributes;
 +    if (pi->pPrinterName)
 +        wcscpy(p->szName, pi->pPrinterName);
 +    else
 +        p->szName[0] = L'\0';
 +
 +    if (pi->pServerName)
 +        wcscpy(p->szName + p->offsServer, pi->pServerName);
 +    else
 +        p->szName[p->offsServer] = L'\0';
 +
 +    *(WORD*)((char*)pidl + (size + 2)) = 0;
 +    return pidl;
 +}
 +
 +/**************************************************************************
 + *  CPrintersEnum::CreatePrintersEnumList()
 + */
 +BOOL CPrintersEnum::CreatePrintersEnumList(DWORD dwFlags)
 +{
 +    BOOL ret = TRUE;
 +
 +    TRACE("(%p)->(flags=0x%08lx) \n", this, dwFlags);
 +
 +    /* enumerate the folders */
 +    if (dwFlags & SHCONTF_NONFOLDERS)
 +    {
 +        DWORD needed = 0, num = 0, i;
 +        PRINTER_INFO_4W *pi;
 +
 +        EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &needed, &num);
 +        if (!needed)
 +            return ret;
 +
 +        pi = (PRINTER_INFO_4W *)HeapAlloc(GetProcessHeap(), 0, needed);
 +        if(!EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 4, (LPBYTE)pi, needed, &needed, &num)) {
 +            HeapFree(GetProcessHeap(), 0, pi);
 +            return FALSE;
 +        }
 +
 +        for(i = 0; i < num; i++) {
 +            LPITEMIDLIST pidl = _ILCreatePrinterItem(&pi[i]);
 +            if (pidl)
 +            {
 +                if (!AddToEnumList(pidl))
 +                    SHFree(pidl);
 +            }
 +        }
 +        HeapFree(GetProcessHeap(), 0, pi);
 +    }
 +    return ret;
 +}
 +
 +CPrinterFolder::CPrinterFolder()
 +{
 +    pidlRoot = NULL;
 +    dwAttributes = 0;
 +    pclsid = NULL;
 +}
 +
 +CPrinterFolder::~CPrinterFolder()
 +{
 +    TRACE("-- destroying IShellFolder(%p)\n", this);
 +    if (pidlRoot)
 +        SHFree(pidlRoot);
 +}
 +
 +HRESULT WINAPI CPrinterFolder::FinalConstruct()
 +{
 +    pidlRoot = _ILCreatePrinters();    /* my qualified pidl */
 +    if (pidlRoot == NULL)
 +        return E_OUTOFMEMORY;
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *    CPrinterFolder::ParseDisplayName
 + *
 + * This is E_NOTIMPL in Windows too.
 + */
 +HRESULT WINAPI CPrinterFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
- HRESULT WINAPI CPrinterFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
++        DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
 +{
 +    TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
 +          this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
 +          pchEaten, ppidl, pdwAttributes);
 +
 +    *ppidl = 0;
 +    if (pchEaten)
 +        *pchEaten = 0;
 +
 +    return E_NOTIMPL;
 +}
 +
 +static PIDLPrinterStruct * _ILGetPrinterStruct(LPCITEMIDLIST pidl)
 +{
 +    LPPIDLDATA pdata = _ILGetDataPointer(pidl);
 +
 +    if (pdata && pdata->type == 0x00)
 +        return (PIDLPrinterStruct*) & (pdata->u.cfont);
 +
 +    return NULL;
 +}
 +
 +/**************************************************************************
 + *        CPrinterFolder::EnumObjects
 + */
 +HRESULT WINAPI CPrinterFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
 +{
 +    CComObject<CPrintersEnum> *theEnumerator;
 +    CComPtr<IEnumIDList>      result;
 +    HRESULT                   hResult;
 +
 +    TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +    *ppEnumIDList = NULL;
 +    ATLTRY (theEnumerator = new CComObject<CPrintersEnum>);
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
 +    if (FAILED (hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +    hResult = theEnumerator->Initialize(hwndOwner, dwFlags);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach();
 +
 +    TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *        CPrinterFolder::BindToObject
 + */
- HRESULT WINAPI CPrinterFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
++HRESULT WINAPI CPrinterFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
 +{
 +    TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this,
 +           pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
 +}
 +
 +/**************************************************************************
 + *    ISF_Printers_fnBindToStorage
 + */
- HRESULT WINAPI CPrinterFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++HRESULT WINAPI CPrinterFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
 +{
 +    FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
 +           this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
 +
 +    *ppvOut = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +/**************************************************************************
 + *     CPrinterFolder::CompareIDs
 + */
- HRESULT WINAPI CPrinterFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl, DWORD *rgfInOut)
++HRESULT WINAPI CPrinterFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    int nReturn;
 +
 +    TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
 +    nReturn = SHELL32_CompareIDs (this, lParam, pidl1, pidl2);
 +    TRACE ("-- %i\n", nReturn);
 +    return nReturn;
 +}
 +
 +/**************************************************************************
 + *    CPrinterFolder::CreateViewObject
 + */
 +HRESULT WINAPI CPrinterFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
 +{
 +    CComPtr<IShellView> pShellView;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
 +          hwndOwner, shdebugstr_guid (&riid), ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if (IsEqualIID(riid, IID_IDropTarget))
 +    {
 +        WARN("IDropTarget not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if(IsEqualIID(riid, IID_IContextMenu))
 +    {
 +        WARN("IContextMenu not implemented\n");
 +        hr = E_NOTIMPL;
 +    }
 +    else if(IsEqualIID(riid, IID_IShellView))
 +    {
 +        hr = IShellView_Constructor((IShellFolder *)this, &pShellView);
 +        if (pShellView)
 +        {
 +            hr = pShellView->QueryInterface(riid, ppvOut);
 +            pShellView->Release();
 +        }
 +    }
 +    TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *  CPrinterFolder::GetAttributesOf
 + */
- HRESULT WINAPI CPrinterFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl,
++HRESULT WINAPI CPrinterFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
 +{
 +    static const DWORD dwPrintersAttributes =
 +        SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
 +    HRESULT hr = S_OK;
 +
 +    FIXME ("(%p)->(cidl=%d apidl=%p mask=0x%08lx): stub\n",
 +           this, cidl, apidl, *rgfInOut);
 +
 +    *rgfInOut &= dwPrintersAttributes;
 +
 +    *rgfInOut &= ~SFGAO_VALIDATE;
 +
 +    TRACE ("-- result=0x%08x\n", *rgfInOut);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *    CPrinterFolder::GetUIObjectOf
 + *
 + * PARAMETERS
 + *  HWND           hwndOwner, //[in ] Parent window for any output
 + *  UINT           cidl,      //[in ] array size
 + *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
 + *  REFIID         riid,      //[in ] Requested Interface
 + *  UINT*          prgfInOut, //[   ] reserved
 + *  LPVOID*        ppvObject) //[out] Resulting Interface
 + *
 + */
- HRESULT WINAPI CPrinterFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
++HRESULT WINAPI CPrinterFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
 +        REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
 +{
 +    IUnknown *pObj = NULL;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
 +           this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
 +
 +    if (!ppvOut)
 +        return hr;
 +
 +    *ppvOut = NULL;
 +
 +    if ((IsEqualIID (riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && cidl == 1)
 +        hr = IEI_Printers_Constructor(apidl[0], riid, &pObj);
 +    else
 +        hr = E_NOINTERFACE;
 +
 +    if (SUCCEEDED(hr) && !pObj)
 +        hr = E_OUTOFMEMORY;
 +
 +    *ppvOut = pObj;
 +    TRACE ("(%p)->hr=0x%08lx\n", this, hr);
 +    return hr;
 +}
 +
 +/**************************************************************************
 + *    CPrinterFolder::GetDisplayNameOf
 + *
 + */
- HRESULT WINAPI CPrinterFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,    /* simple pidl */
-         LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
++HRESULT WINAPI CPrinterFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 +{
 +    LPWSTR pszName;
 +    PIDLPrinterStruct * p;
 +
 +    TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl, dwFlags, strRet);
 +    pdump (pidl);
 +
 +    if (!strRet)
 +    {
 +        WARN("no strRet\n");
 +        return E_INVALIDARG;
 +    }
 +
 +    if (!pidl->mkid.cb)
 +    {
 +        pszName = (LPWSTR)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
 +        if (!pszName)
 +            return E_OUTOFMEMORY;
 +
 +        if (LoadStringW(shell32_hInstance, IDS_PRINTERS, pszName, MAX_PATH))
 +        {
 +            pszName[MAX_PATH-1] = L'\0';
 +            strRet->uType = STRRET_WSTR;
 +            strRet->pOleStr = pszName;
 +            return S_OK;
 +        }
 +        CoTaskMemFree(pszName);
 +        return E_FAIL;
 +    }
 +
 +    p = _ILGetPrinterStruct(pidl);
 +    if (!p)
 +    {
 +        WARN("no printer struct\n");
 +        return E_INVALIDARG;
 +    }
 +    strRet->pOleStr = (LPWSTR)SHAlloc(p->offsServer * sizeof(WCHAR));
 +    if (!strRet->pOleStr)
 +        return E_OUTOFMEMORY;
 +
 +    memcpy((LPVOID)strRet->pOleStr, (LPVOID)p->szName, p->offsServer * sizeof(WCHAR));
 +    TRACE("ret %s\n", debugstr_w(strRet->pOleStr));
 +
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *  CPrinterFolder::SetNameOf
 + *  Changes the name of a file object or subfolder, possibly changing its item
 + *  identifier in the process.
 + *
 + * PARAMETERS
 + *  HWND          hwndOwner,  //[in ] Owner window for output
 + *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
 + *  LPCOLESTR     lpszName,   //[in ] the items new display name
 + *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
 + *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
 + */
- HRESULT WINAPI CPrinterFolder::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
++HRESULT WINAPI CPrinterFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,    /* simple pidl */
++        LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
 +{
 +    FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner, pidl,
 +          debugstr_w (lpName), dwFlags, pPidlOut);
 +
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CPrinterFolder::GetDefaultSearchGUID(GUID *pguid)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CPrinterFolder::EnumSearches(IEnumExtraSearch **ppenum)
 +{
 +    FIXME("(%p)\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CPrinterFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
 +{
 +    if (pSort)
 +        *pSort = 0;
 +    if (pDisplay)
 +        *pDisplay = 0;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CPrinterFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
 +{
 +    if (!pcsFlags || iColumn >= PrinterSHELLVIEWCOLUMNS)
 +        return E_INVALIDARG;
 +    *pcsFlags = PrinterSFHeader[iColumn].pcsFlags;
 +    return S_OK;
 +
 +}
 +
- HRESULT WINAPI CPrinterFolder::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
++HRESULT WINAPI CPrinterFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
 +{
 +    FIXME("(%p): stub\n", this);
 +
 +    return E_NOTIMPL;
 +}
 +
++HRESULT WINAPI CPrinterFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
 +{
 +    WCHAR buffer[MAX_PATH] = {0};
 +    HRESULT hr = E_FAIL;
 +
 +    TRACE("(%p)->(%p %i %p): stub\n", this, pidl, iColumn, psd);
 +
 +    if (iColumn >= PrinterSHELLVIEWCOLUMNS)
 +        return E_FAIL;
 +
 +    psd->fmt = PrinterSFHeader[iColumn].fmt;
 +    psd->cxChar = PrinterSFHeader[iColumn].cxChar;
 +    if (pidl == NULL)
 +    {
 +        psd->str.uType = STRRET_WSTR;
 +        if (LoadStringW(shell32_hInstance, PrinterSFHeader[iColumn].colnameid, buffer, MAX_PATH))
 +            hr = SHStrDupW(buffer, &psd->str.pOleStr);
 +
 +        return hr;
 +    }
 +
 +    if (iColumn == COLUMN_NAME)
 +    {
 +        psd->str.uType = STRRET_WSTR;
 +        return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
 +    }
 +
 +    psd->str.uType = STRRET_CSTR;
 +    psd->str.cStr[0] = '\0';
 +
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CPrinterFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
 +{
 +    FIXME ("(%p): stub\n", this);
 +    return E_NOTIMPL;
 +}
 +
 +/************************************************************************
 + *    CPrinterFolder::GetClassID
 + */
 +HRESULT WINAPI CPrinterFolder::GetClassID(CLSID *lpClassId)
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    *lpClassId = CLSID_Printers;
 +
 +    return S_OK;
 +}
 +
 +/************************************************************************
 + *    CPrinterFolder::Initialize
 + */
 +HRESULT WINAPI CPrinterFolder::Initialize(LPCITEMIDLIST pidl)
 +{
 +    if (pidlRoot)
 +        SHFree((LPVOID)pidlRoot);
 +
 +    pidlRoot = ILClone(pidl);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 + *    CPrinterFolder::GetCurFolder
 + */
 +HRESULT WINAPI CPrinterFolder::GetCurFolder(LPITEMIDLIST * pidl)
 +{
 +    TRACE ("(%p)->(%p)\n", this, pidl);
 +
 +    *pidl = ILClone (pidlRoot);
 +    return S_OK;
 +}
Simple merge
index 94417f5,0000000..19f9bbd
mode 100644,000000..100644
--- /dev/null
@@@ -1,1601 -1,0 +1,1606 @@@
-         LPOLESTR pszDisplayName, ULONG *pchEaten, LPITEMIDLIST *ppidl,
 +/*
 + * Trash virtual folder support. The trashing engine is implemented in trash.c
 + *
 + * Copyright (C) 2006 Mikolaj Zalewski
 + * Copyright (C) 2009 Andrew Hill
 + *
 + * 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>
 +
 +#include <ntquery.h>
 +
 +#define MAX_PROPERTY_SHEET_PAGE 32
 +
 +WINE_DEFAULT_DEBUG_CHANNEL(CRecycleBin);
 +
 +typedef struct
 +{
 +    int column_name_id;
 +    const GUID *fmtId;
 +    DWORD pid;
 +    int pcsFlags;
 +    int fmt;
 +    int cxChars;
 +} columninfo;
 +
 +static const columninfo RecycleBinColumns[] =
 +{
 +    {IDS_SHV_COLUMN1,        &FMTID_Storage,   PID_STG_NAME,       SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT,  LVCFMT_LEFT,  30},
 +    {IDS_SHV_COLUMN_DELFROM, &FMTID_Displaced, PID_DISPLACED_FROM, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT,  LVCFMT_LEFT,  30},
 +    {IDS_SHV_COLUMN_DELDATE, &FMTID_Displaced, PID_DISPLACED_DATE, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT,  20},
 +    {IDS_SHV_COLUMN2,        &FMTID_Storage,   PID_STG_SIZE,       SHCOLSTATE_TYPE_INT | SHCOLSTATE_ONBYDEFAULT,  LVCFMT_RIGHT, 20},
 +    {IDS_SHV_COLUMN3,        &FMTID_Storage,   PID_STG_STORAGETYPE, SHCOLSTATE_TYPE_INT | SHCOLSTATE_ONBYDEFAULT,  LVCFMT_LEFT,  20},
 +    {IDS_SHV_COLUMN4,        &FMTID_Storage,   PID_STG_WRITETIME,  SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT,  20},
 +    /*    {"creation time",  &FMTID_Storage,   PID_STG_CREATETIME, SHCOLSTATE_TYPE_DATE,                        LVCFMT_LEFT,  20}, */
 +    /*    {"attribs",        &FMTID_Storage,   PID_STG_ATTRIBUTES, SHCOLSTATE_TYPE_STR,                         LVCFMT_LEFT,  20},       */
 +};
 +
 +#define COLUMN_NAME    0
 +#define COLUMN_DELFROM 1
 +#define COLUMN_DATEDEL 2
 +#define COLUMN_SIZE    3
 +#define COLUMN_TYPE    4
 +#define COLUMN_MTIME   5
 +
 +#define COLUMNS_COUNT  6
 +
 +/*
 + * Recycle Bin folder
 + */
 +
 +class CRecycleBinEnum :
 +    public IEnumIDListImpl
 +{
 +    private:
 +    public:
 +        CRecycleBinEnum();
 +        ~CRecycleBinEnum();
 +        HRESULT WINAPI Initialize(DWORD dwFlags);
 +        static BOOL WINAPI CBEnumRecycleBin(IN PVOID Context, IN HANDLE hDeletedFile);
 +        BOOL WINAPI CBEnumRecycleBin(IN HANDLE hDeletedFile);
 +
 +        BEGIN_COM_MAP(CRecycleBinEnum)
 +        COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
 +        END_COM_MAP()
 +};
 +
 +class CRecycleBinItemContextMenu :
 +    public CComObjectRootEx<CComMultiThreadModelNoCS>,
 +    public IContextMenu2
 +{
 +    private:
 +        LPITEMIDLIST                        apidl;
 +    public:
 +        CRecycleBinItemContextMenu();
 +        ~CRecycleBinItemContextMenu();
 +        HRESULT WINAPI Initialize(LPCITEMIDLIST pidl);
 +
 +        // IContextMenu
 +        virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
 +        virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
 +        virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen);
 +
 +        // IContextMenu2
 +        virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
 +
 +        BEGIN_COM_MAP(CRecycleBinItemContextMenu)
 +        COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
 +        COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
 +        END_COM_MAP()
 +};
 +
 +typedef struct
 +{
 +    PIDLRecycleStruct *pFileDetails;
 +    HANDLE hDeletedFile;
 +    BOOL bFound;
 +} SEARCH_CONTEXT, *PSEARCH_CONTEXT;
 +
 +typedef struct
 +{
 +    DWORD dwNukeOnDelete;
 +    DWORD dwSerial;
 +    DWORD dwMaxCapacity;
 +} DRIVE_ITEM_CONTEXT, *PDRIVE_ITEM_CONTEXT;
 +
 +BOOL WINAPI CBSearchRecycleBin(IN PVOID Context, IN HANDLE hDeletedFile)
 +{
 +    PSEARCH_CONTEXT pContext = (PSEARCH_CONTEXT)Context;
 +
 +    PDELETED_FILE_DETAILS_W pFileDetails;
 +    DWORD dwSize;
 +    BOOL ret;
 +
 +    if (!GetDeletedFileDetailsW(hDeletedFile,
 +                                0,
 +                                NULL,
 +                                &dwSize) &&
 +            GetLastError() != ERROR_INSUFFICIENT_BUFFER)
 +    {
 +        ERR("GetDeletedFileDetailsW failed\n");
 +        return FALSE;
 +    }
 +
 +    pFileDetails = (DELETED_FILE_DETAILS_W *)SHAlloc(dwSize);
 +    if (!pFileDetails)
 +    {
 +        ERR("No memory\n");
 +        return FALSE;
 +    }
 +
 +    if (!GetDeletedFileDetailsW(hDeletedFile,
 +                                dwSize,
 +                                pFileDetails,
 +                                NULL))
 +    {
 +        ERR("GetDeletedFileDetailsW failed\n");
 +        SHFree(pFileDetails);
 +        return FALSE;
 +    }
 +
 +    ret = memcmp(pFileDetails, pContext->pFileDetails, dwSize);
 +    if (!ret)
 +    {
 +        pContext->hDeletedFile = hDeletedFile;
 +        pContext->bFound = TRUE;
 +    }
 +    else
 +        CloseRecycleBinHandle(hDeletedFile);
 +
 +    SHFree(pFileDetails);
 +    return ret;
 +}
 +
 +static PIDLRecycleStruct * _ILGetRecycleStruct(LPCITEMIDLIST pidl)
 +{
 +    LPPIDLDATA pdata = _ILGetDataPointer(pidl);
 +
 +    if (pdata && pdata->type == 0x00)
 +        return (PIDLRecycleStruct*) & (pdata->u.crecycle);
 +
 +    return NULL;
 +}
 +
 +CRecycleBinEnum::CRecycleBinEnum()
 +{
 +}
 +
 +CRecycleBinEnum::~CRecycleBinEnum()
 +{
 +}
 +
 +HRESULT WINAPI CRecycleBinEnum::Initialize(DWORD dwFlags)
 +{
 +    static LPCWSTR szDrive = L"C:\\";
 +
 +    if (dwFlags & SHCONTF_NONFOLDERS)
 +    {
 +        TRACE("Starting Enumeration\n");
 +
 +        if (!EnumerateRecycleBinW(szDrive /* FIXME */ , CBEnumRecycleBin, (PVOID)this))
 +        {
 +            WARN("Error: EnumerateCRecycleBinW failed\n");
 +            return E_FAIL;
 +        }
 +    }
 +    else
 +    {
 +        // do nothing
 +    }
 +    return S_OK;
 +}
 +
 +static LPITEMIDLIST _ILCreateRecycleItem(PDELETED_FILE_DETAILS_W pFileDetails)
 +{
 +    PIDLDATA tmp;
 +    LPITEMIDLIST pidl;
 +    PIDLRecycleStruct * p;
 +    int size0 = (char*)&tmp.u.crecycle.szName - (char*)&tmp.u.crecycle;
 +    int size = size0;
 +
 +    tmp.type = 0x00;
 +    size += (wcslen(pFileDetails->FileName) + 1) * sizeof(WCHAR);
 +
 +    pidl = (LPITEMIDLIST)SHAlloc(size + 4);
 +    if (!pidl)
 +        return pidl;
 +
 +    pidl->mkid.cb = size + 2;
 +    memcpy(pidl->mkid.abID, &tmp, 2 + size0);
 +
 +    p = &((PIDLDATA*)pidl->mkid.abID)->u.crecycle;
 +    RtlCopyMemory(p, pFileDetails, sizeof(DELETED_FILE_DETAILS_W));
 +    wcscpy(p->szName, pFileDetails->FileName);
 +    *(WORD*)((char*)pidl + (size + 2)) = 0;
 +    return pidl;
 +}
 +
 +BOOL WINAPI CRecycleBinEnum::CBEnumRecycleBin(IN PVOID Context, IN HANDLE hDeletedFile)
 +{
 +    return static_cast<CRecycleBinEnum *>(Context)->CBEnumRecycleBin(hDeletedFile);
 +}
 +
 +BOOL WINAPI CRecycleBinEnum::CBEnumRecycleBin(IN HANDLE hDeletedFile)
 +{
 +    PDELETED_FILE_DETAILS_W pFileDetails;
 +    DWORD dwSize;
 +    LPITEMIDLIST pidl = NULL;
 +    BOOL ret;
 +
 +    if (!GetDeletedFileDetailsW(hDeletedFile,
 +                                0,
 +                                NULL,
 +                                &dwSize) &&
 +            GetLastError() != ERROR_INSUFFICIENT_BUFFER)
 +    {
 +        ERR("GetDeletedFileDetailsW failed\n");
 +        return FALSE;
 +    }
 +
 +    pFileDetails = (DELETED_FILE_DETAILS_W *)SHAlloc(dwSize);
 +    if (!pFileDetails)
 +    {
 +        ERR("No memory\n");
 +        return FALSE;
 +    }
 +
 +    if (!GetDeletedFileDetailsW(hDeletedFile,
 +                                dwSize,
 +                                pFileDetails,
 +                                NULL))
 +    {
 +        ERR("GetDeletedFileDetailsW failed\n");
 +        SHFree(pFileDetails);
 +        return FALSE;
 +    }
 +
 +    pidl = _ILCreateRecycleItem(pFileDetails);
 +    if (!pidl)
 +    {
 +        SHFree(pFileDetails);
 +        return FALSE;
 +    }
 +
 +    ret = AddToEnumList(pidl);
 +
 +    if (!ret)
 +        SHFree(pidl);
 +    SHFree(pFileDetails);
 +    TRACE("Returning %d\n", ret);
 +    CloseRecycleBinHandle(hDeletedFile);
 +    return ret;
 +}
 +
 +/**************************************************************************
 +* IContextMenu2 Bitbucket Item Implementation
 +*/
 +
 +CRecycleBinItemContextMenu::CRecycleBinItemContextMenu()
 +{
 +    apidl = NULL;
 +}
 +
 +CRecycleBinItemContextMenu::~CRecycleBinItemContextMenu()
 +{
 +    ILFree(apidl);
 +}
 +
 +HRESULT WINAPI CRecycleBinItemContextMenu::Initialize(LPCITEMIDLIST pidl)
 +{
 +    apidl = ILClone(pidl);
 +    if (apidl == NULL)
 +        return E_OUTOFMEMORY;
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBinItemContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
 +{
 +    WCHAR szBuffer[30] = {0};
 +    ULONG Count = 1;
 +
 +    TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
 +
 +    if (LoadStringW(shell32_hInstance, IDS_RESTORE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED);
 +        Count++;
 +    }
 +
 +    if (LoadStringW(shell32_hInstance, IDS_CUT, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
 +    }
 +
 +    if (LoadStringW(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
 +    }
 +
 +    if (LoadStringW(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
 +    {
 +        szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
 +        _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT);
 +    }
 +
 +    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count);
 +}
 +
 +HRESULT WINAPI CRecycleBinItemContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    SEARCH_CONTEXT Context;
 +    static LPCWSTR szDrive = L"C:\\";
 +
 +    TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
 +
 +    if (lpcmi->lpVerb == MAKEINTRESOURCEA(1) || lpcmi->lpVerb == MAKEINTRESOURCEA(5))
 +    {
 +        Context.pFileDetails = _ILGetRecycleStruct(apidl);
 +        Context.bFound = FALSE;
 +
 +        EnumerateRecycleBinW(szDrive, CBSearchRecycleBin, (PVOID)&Context);
 +        if (!Context.bFound)
 +            return E_FAIL;
 +
 +        if (lpcmi->lpVerb == MAKEINTRESOURCEA(1))
 +        {
 +            /* restore file */
 +            if (RestoreFile(Context.hDeletedFile))
 +                return S_OK;
 +            else
 +                return E_FAIL;
 +        }
 +        else
 +        {
 +            DeleteFileHandleToRecycleBin(Context.hDeletedFile);
 +            return E_NOTIMPL;
 +        }
 +    }
 +    else if (lpcmi->lpVerb == MAKEINTRESOURCEA(3))
 +    {
 +        FIXME("implement cut\n");
 +        return E_NOTIMPL;
 +    }
 +    else if (lpcmi->lpVerb == MAKEINTRESOURCEA(7))
 +    {
 +        FIXME("implement properties\n");
 +        return E_NOTIMPL;
 +    }
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBinItemContextMenu::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
 +{
 +    TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
 +
 +    return E_FAIL;
 +}
 +
 +HRESULT WINAPI CRecycleBinItemContextMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
 +{
 +    TRACE("CRecycleBin_IContextMenu2Item_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
 +
 +    return E_NOTIMPL;
 +}
 +
 +static HRESULT WINAPI CRecycleBinItemContextMenuConstructor(REFIID riid, LPCITEMIDLIST pidl, LPVOID *ppv)
 +{
 +    CComObject<CRecycleBinItemContextMenu>    *theMenu;
 +    CComPtr<IUnknown>                        result;
 +    HRESULT                                    hResult;
 +
 +    TRACE("%s\n", shdebugstr_guid(&riid));
 +
 +    if (ppv == NULL)
 +        return E_POINTER;
 +    *ppv = NULL;
 +    ATLTRY(theMenu = new CComObject<CRecycleBinItemContextMenu>);
 +    if (theMenu == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theMenu->QueryInterface(riid, (void **)&result);
 +    if (FAILED(hResult))
 +    {
 +        delete theMenu;
 +        return hResult;
 +    }
 +    hResult = theMenu->Initialize(pidl);
 +    if (FAILED(hResult))
 +        return hResult;
 +    *ppv = result.Detach();
 +    TRACE ("--(%p)\n", *ppv);
 +    return S_OK;
 +}
 +
 +/**************************************************************************
 +* registers clipboardformat once
 +*/
 +void CRecycleBin::SF_RegisterClipFmt()
 +{
 +    TRACE ("(%p)\n", this);
 +
 +    if (!cfShellIDList)
 +        cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
 +}
 +
 +CRecycleBin::CRecycleBin()
 +{
 +    pidl = NULL;
 +    iIdEmpty = 0;
 +    cfShellIDList = 0;
 +    SF_RegisterClipFmt();
 +    fAcceptFmt = FALSE;
 +}
 +
 +CRecycleBin::~CRecycleBin()
 +{
 +    /*    InterlockedDecrement(&objCount);*/
 +    SHFree(pidl);
 +}
 +
 +/*************************************************************************
 + * RecycleBin IPersistFolder2 interface
 + */
 +
 +HRESULT WINAPI CRecycleBin::GetClassID(CLSID *pClassID)
 +{
 +    TRACE("(%p, %p)\n", this, pClassID);
 +    if (pClassID == NULL)
 +        return E_INVALIDARG;
 +    memcpy(pClassID, &CLSID_RecycleBin, sizeof(CLSID));
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBin::Initialize(LPCITEMIDLIST pidl)
 +{
 +    TRACE("(%p, %p)\n", this, pidl);
 +
 +    SHFree((LPVOID)this->pidl);
 +    this->pidl = ILClone(pidl);
 +    if (this->pidl == NULL)
 +        return E_OUTOFMEMORY;
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBin::GetCurFolder(LPITEMIDLIST *ppidl)
 +{
 +    TRACE("\n");
 +    *ppidl = ILClone(pidl);
 +    return S_OK;
 +}
 +
 +/*************************************************************************
 + * RecycleBin IShellFolder2 interface
 + */
 +
 +HRESULT WINAPI CRecycleBin::ParseDisplayName(HWND hwnd, LPBC pbc,
- HRESULT WINAPI CRecycleBin::BindToObject(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppv)
++        LPOLESTR pszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl,
 +        ULONG *pdwAttributes)
 +{
 +    FIXME("stub\n");
 +    return E_NOTIMPL;
 +}
 +
 +
 +PDELETED_FILE_DETAILS_W
 +UnpackDetailsFromPidl(LPCITEMIDLIST pidl)
 +{
 +    return (PDELETED_FILE_DETAILS_W)&pidl->mkid.abID;
 +}
 +
 +HRESULT WINAPI CRecycleBin::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
 +{
 +    CComObject<CRecycleBinEnum>                *theEnumerator;
 +    CComPtr<IEnumIDList>                    result;
 +    HRESULT                                    hResult;
 +
 +    TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
 +
 +    if (ppEnumIDList == NULL)
 +        return E_POINTER;
 +    *ppEnumIDList = NULL;
 +    ATLTRY (theEnumerator = new CComObject<CRecycleBinEnum>);
 +    if (theEnumerator == NULL)
 +        return E_OUTOFMEMORY;
 +    hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
 +    if (FAILED (hResult))
 +    {
 +        delete theEnumerator;
 +        return hResult;
 +    }
 +    hResult = theEnumerator->Initialize(dwFlags);
 +    if (FAILED (hResult))
 +        return hResult;
 +    *ppEnumIDList = result.Detach();
 +
 +    TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
 +
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CRecycleBin::BindToStorage(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppv)
++HRESULT WINAPI CRecycleBin::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbc, REFIID riid, void **ppv)
 +{
 +    FIXME("(%p, %p, %p, %s, %p) - stub\n", this, pidl, pbc, debugstr_guid(&riid), ppv);
 +    return E_NOTIMPL;
 +}
 +
- HRESULT WINAPI CRecycleBin::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
++HRESULT WINAPI CRecycleBin::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbc, REFIID riid, void **ppv)
 +{
 +    FIXME("(%p, %p, %p, %s, %p) - stub\n", this, pidl, pbc, debugstr_guid(&riid), ppv);
 +    return E_NOTIMPL;
 +}
 +
- HRESULT WINAPI CRecycleBin::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl,
++HRESULT WINAPI CRecycleBin::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 +{
 +    /* TODO */
 +    TRACE("(%p, %p, %p, %p)\n", this, (void *)lParam, pidl1, pidl2);
 +    if (pidl1->mkid.cb != pidl2->mkid.cb)
 +        return MAKE_HRESULT(SEVERITY_SUCCESS, 0, pidl1->mkid.cb - pidl2->mkid.cb);
 +    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (unsigned short)memcmp(pidl1->mkid.abID, pidl2->mkid.abID, pidl1->mkid.cb));
 +}
 +
 +HRESULT WINAPI CRecycleBin::CreateViewObject(HWND hwndOwner, REFIID riid, void **ppv)
 +{
 +    CComPtr<IShellView> pShellView;
 +    HRESULT hr = E_NOINTERFACE;
 +
 +    TRACE("(%p, %p, %s, %p)\n", this, hwndOwner, debugstr_guid(&riid), ppv);
 +
 +    if (!ppv)
 +        return hr;
 +
 +    *ppv = NULL;
 +
 +    if (IsEqualIID (riid, IID_IDropTarget))
 +    {
 +        hr = this->QueryInterface (IID_IDropTarget, ppv);
 +    }
 +    else if (IsEqualIID (riid, IID_IContextMenu) || IsEqualIID (riid, IID_IContextMenu2))
 +    {
 +        hr = this->QueryInterface(riid, ppv);
 +    }
 +    else if (IsEqualIID (riid, IID_IShellView))
 +    {
 +        hr = IShellView_Constructor ((IShellFolder *)this, &pShellView);
 +        if (pShellView)
 +        {
 +            hr = pShellView->QueryInterface(riid, ppv);
 +        }
 +    }
 +    else
 +        return hr;
 +    TRACE ("-- (%p)->(interface=%p)\n", this, ppv);
 +    return hr;
 +
 +}
 +
- HRESULT WINAPI CRecycleBin::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl,
++HRESULT WINAPI CRecycleBin::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
 +        SFGAOF *rgfInOut)
 +{
 +    TRACE("(%p, %d, {%p, ...}, {%x})\n", this, cidl, apidl ? apidl[0] : NULL, (unsigned int)*rgfInOut);
 +    *rgfInOut &= SFGAO_FOLDER|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANLINK;
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CRecycleBin::GetDisplayNameOf(LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET *pName)
++HRESULT WINAPI CRecycleBin::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
 +        REFIID riid, UINT *prgfInOut, void **ppv)
 +{
 +    IUnknown *pObj = NULL;
 +    HRESULT hr = E_INVALIDARG;
 +
 +    TRACE ("(%p)->(%p,%u,apidl=%p, %p %p)\n", this,
 +           hwndOwner, cidl, apidl, prgfInOut, ppv);
 +
 +    if (!ppv)
 +        return hr;
 +
 +    *ppv = NULL;
 +
 +    if ((IsEqualIID (riid, IID_IContextMenu) || IsEqualIID(riid, IID_IContextMenu2)) && (cidl >= 1))
 +    {
 +        hr = CRecycleBinItemContextMenuConstructor(riid, apidl[0], (void **)&pObj);
 +    }
 +    else if (IsEqualIID (riid, IID_IDropTarget) && (cidl == 1))
 +    {
 +        IDropTarget * pDt = NULL;
 +        hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
 +        pObj = pDt;
 +    }
 +    else
 +        hr = E_NOINTERFACE;
 +
 +    if (SUCCEEDED(hr) && !pObj)
 +        hr = E_OUTOFMEMORY;
 +
 +    *ppv = pObj;
 +    TRACE ("(%p)->hr=0x%08x\n", this, hr);
 +    return hr;
 +}
 +
- HRESULT WINAPI CRecycleBin::SetNameOf(HWND hwnd, LPCITEMIDLIST pidl, LPCOLESTR pszName,
-                                       SHGDNF uFlags, LPITEMIDLIST *ppidlOut)
++HRESULT WINAPI CRecycleBin::GetDisplayNameOf(PCUITEMID_CHILD pidl, SHGDNF uFlags, STRRET *pName)
 +{
 +    PIDLRecycleStruct *pFileDetails;
 +    LPWSTR pFileName;
 +
 +    TRACE("(%p, %p, %x, %p)\n", this, pidl, (unsigned int)uFlags, pName);
 +
 +
 +    if (_ILIsBitBucket (pidl))
 +    {
 +        WCHAR pszPath[100];
 +
 +        if (HCR_GetClassNameW(CLSID_RecycleBin, pszPath, MAX_PATH))
 +        {
 +            pName->uType = STRRET_WSTR;
 +            pName->pOleStr = StrDupW(pszPath);
 +            return S_OK;
 +        }
 +    }
 +
 +    pFileDetails = _ILGetRecycleStruct(pidl);
 +    if (!pFileDetails)
 +    {
 +        pName->cStr[0] = 0;
 +        pName->uType = STRRET_CSTR;
 +        return E_INVALIDARG;
 +    }
 +
 +    pFileName = wcsrchr(pFileDetails->szName, L'\\');
 +    if (!pFileName)
 +    {
 +        pName->cStr[0] = 0;
 +        pName->uType = STRRET_CSTR;
 +        return E_UNEXPECTED;
 +    }
 +
 +    pName->pOleStr = StrDupW(pFileName + 1);
 +    if (pName->pOleStr == NULL)
 +        return E_OUTOFMEMORY;
 +
 +    pName->uType = STRRET_WSTR;
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CRecycleBin::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
++HRESULT WINAPI CRecycleBin::SetNameOf(HWND hwnd, PCUITEMID_CHILD pidl, LPCOLESTR pszName,
++                                      SHGDNF uFlags, PITEMID_CHILD *ppidlOut)
 +{
 +    TRACE("\n");
 +    return E_FAIL; /* not supported */
 +}
 +
 +HRESULT WINAPI CRecycleBin::GetDefaultSearchGUID(GUID *pguid)
 +{
 +    FIXME("stub\n");
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CRecycleBin::EnumSearches(IEnumExtraSearch **ppEnum)
 +{
 +    FIXME("stub\n");
 +    *ppEnum = NULL;
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CRecycleBin::GetDefaultColumn(DWORD dwReserved, ULONG *pSort, ULONG *pDisplay)
 +{
 +    TRACE("(%p, %x, %p, %p)\n", this, (unsigned int)dwReserved, pSort, pDisplay);
 +    *pSort = 0;
 +    *pDisplay = 0;
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBin::GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags)
 +{
 +    TRACE("(%p, %d, %p)\n", this, iColumn, pcsFlags);
 +    if (iColumn >= COLUMNS_COUNT)
 +        return E_INVALIDARG;
 +    *pcsFlags = RecycleBinColumns[iColumn].pcsFlags;
 +    return S_OK;
 +}
 +
- HRESULT WINAPI CRecycleBin::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, LPSHELLDETAILS pDetails)
++HRESULT WINAPI CRecycleBin::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
 +{
 +    FIXME("stub\n");
 +    return E_NOTIMPL;
 +}
 +
 +static HRESULT FormatDateTime(LPWSTR buffer, int size, FILETIME * ft)
 +{
 +    FILETIME lft;
 +    SYSTEMTIME time;
 +    int ret;
 +
 +    FileTimeToLocalFileTime(ft, &lft);
 +    FileTimeToSystemTime(&lft, &time);
 +
 +    ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, buffer, size);
 +    if (ret > 0 && ret < size)
 +    {
 +        /* Append space + time without seconds */
 +        buffer[ret-1] = ' ';
 +        GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &buffer[ret], size - ret);
 +    }
 +
 +    return (ret != 0 ? E_FAIL : S_OK);
 +}
 +
-         pDataObject->AddRef();
-         SHCreateThread(DoDeleteThreadProc, pDataObject, NULL, NULL);
++HRESULT WINAPI CRecycleBin::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, LPSHELLDETAILS pDetails)
 +{
 +    PIDLRecycleStruct * pFileDetails;
 +    WCHAR buffer[MAX_PATH];
 +    WCHAR szTypeName[100];
 +    LPWSTR pszBackslash;
 +    UINT Length;
 +
 +    TRACE("(%p, %p, %d, %p)\n", this, pidl, iColumn, pDetails);
 +    if (iColumn >= COLUMNS_COUNT)
 +        return E_FAIL;
 +    pDetails->fmt = RecycleBinColumns[iColumn].fmt;
 +    pDetails->cxChar = RecycleBinColumns[iColumn].cxChars;
 +    if (pidl == NULL)
 +    {
 +        pDetails->str.uType = STRRET_WSTR;
 +        LoadStringW(shell32_hInstance, RecycleBinColumns[iColumn].column_name_id, buffer, MAX_PATH);
 +        return SHStrDupW(buffer, &pDetails->str.pOleStr);
 +    }
 +
 +    if (iColumn == COLUMN_NAME)
 +        return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str);
 +
 +    pFileDetails = _ILGetRecycleStruct(pidl);
 +    switch (iColumn)
 +    {
 +        case COLUMN_DATEDEL:
 +            FormatDateTime(buffer, MAX_PATH, &pFileDetails->DeletionTime);
 +            break;
 +        case COLUMN_DELFROM:
 +            pszBackslash = wcsrchr(pFileDetails->szName, L'\\');
 +            Length = (pszBackslash - pFileDetails->szName);
 +            memcpy((LPVOID)buffer, pFileDetails->szName, Length * sizeof(WCHAR));
 +            buffer[Length] = L'\0';
 +            break;
 +        case COLUMN_SIZE:
 +            StrFormatKBSizeW(pFileDetails->FileSize.QuadPart, buffer, MAX_PATH);
 +            break;
 +        case COLUMN_MTIME:
 +            FormatDateTime(buffer, MAX_PATH, &pFileDetails->LastModification);
 +            break;
 +        case COLUMN_TYPE:
 +            szTypeName[0] = L'\0';
 +            wcscpy(buffer, PathFindExtensionW(pFileDetails->szName));
 +            if (!( HCR_MapTypeToValueW(buffer, buffer, sizeof(buffer) / sizeof(WCHAR), TRUE) &&
 +                    HCR_MapTypeToValueW(buffer, szTypeName, sizeof(szTypeName) / sizeof(WCHAR), FALSE )))
 +            {
 +                wcscpy (szTypeName, PathFindExtensionW(pFileDetails->szName));
 +                wcscat(szTypeName, L"-");
 +                Length = wcslen(szTypeName);
 +                if (LoadStringW(shell32_hInstance, IDS_SHV_COLUMN1, &szTypeName[Length], (sizeof(szTypeName) / sizeof(WCHAR)) - Length))
 +                    szTypeName[(sizeof(szTypeName)/sizeof(WCHAR))-1] = L'\0';
 +            }
 +            pDetails->str.uType = STRRET_WSTR;
 +            return SHStrDupW(szTypeName, &pDetails->str.pOleStr);
 +            break;
 +        default:
 +            return E_FAIL;
 +    }
 +
 +    pDetails->str.uType = STRRET_WSTR;
 +    return SHStrDupW(buffer, &pDetails->str.pOleStr);
 +}
 +
 +HRESULT WINAPI CRecycleBin::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
 +{
 +    TRACE("(%p, %d, %p)\n", this, iColumn, pscid);
 +    if (iColumn >= COLUMNS_COUNT)
 +        return E_INVALIDARG;
 +    pscid->fmtid = *RecycleBinColumns[iColumn].fmtId;
 +    pscid->pid = RecycleBinColumns[iColumn].pid;
 +    return S_OK;
 +}
 +
 +/*************************************************************************
 + * RecycleBin IContextMenu interface
 + */
 +
 +HRESULT WINAPI CRecycleBin::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
 +{
 +    WCHAR szBuffer[100];
 +    MENUITEMINFOW mii;
 +    int id = 1;
 +
 +    TRACE("QueryContextMenu %p %p %u %u %u %u\n", this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags );
 +
 +    if (!hMenu)
 +        return E_INVALIDARG;
 +
 +    memset(&mii, 0, sizeof(mii));
 +    mii.cbSize = sizeof(mii);
 +    mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
 +    mii.fState = MFS_ENABLED;
 +    szBuffer[0] = L'\0';
 +    LoadStringW(shell32_hInstance, IDS_EMPTY_BITBUCKET, szBuffer, sizeof(szBuffer) / sizeof(WCHAR));
 +    mii.dwTypeData = szBuffer;
 +    mii.cch = wcslen(mii.dwTypeData);
 +    mii.wID = idCmdFirst + id++;
 +    mii.fType = MFT_STRING;
 +    iIdEmpty = 1;
 +
 +    if (!InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
 +        return E_FAIL;
 +
 +    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, id);
 +}
 +
 +HRESULT WINAPI CRecycleBin::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
 +{
 +    HRESULT hr;
 +    LPSHELLBROWSER lpSB;
 +    IShellView * lpSV = NULL;
 +
 +    TRACE("%p %p verb %p\n", this, lpcmi, lpcmi->lpVerb);
 +
 +    if (LOWORD(lpcmi->lpVerb) == iIdEmpty)
 +    {
 +        // FIXME
 +        // path & flags
 +        hr = SHEmptyRecycleBinW(lpcmi->hwnd, L"C:\\", 0);
 +        TRACE("result %x\n", hr);
 +        if (hr != S_OK)
 +            return hr;
 +
 +        lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
 +        if (lpSB && SUCCEEDED(lpSB->QueryActiveShellView(&lpSV)))
 +            lpSV->Refresh();
 +    }
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBin::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
 +{
 +    FIXME("%p %lu %u %p %p %u\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
 +
 +    return E_NOTIMPL;
 +}
 +
 +/*************************************************************************
 + * RecycleBin IShellPropSheetExt interface
 + */
 +
 +HRESULT WINAPI CRecycleBin::AddPages(LPFNSVADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
 +{
 +    FIXME("%p %p %lu\n", this, pfnAddPage, lParam);
 +
 +    return E_NOTIMPL;
 +}
 +
 +HRESULT WINAPI CRecycleBin::ReplacePage(EXPPS uPageID, LPFNSVADDPROPSHEETPAGE pfnReplaceWith, LPARAM lParam)
 +{
 +    FIXME("%p %lu %p %lu\n", this, uPageID, pfnReplaceWith, lParam);
 +
 +    return E_NOTIMPL;
 +}
 +
 +/*************************************************************************
 + * RecycleBin IShellExtInit interface
 + */
 +
 +HRESULT WINAPI CRecycleBin::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
 +{
 +    TRACE("%p %p %p %p\n", this, pidlFolder, pdtobj, hkeyProgID );
 +    return S_OK;
 +}
 +
 +void toggleNukeOnDeleteOption(HWND hwndDlg, BOOL bEnable)
 +{
 +    if (bEnable)
 +    {
 +        SendDlgItemMessage(hwndDlg, 14001, BM_SETCHECK, BST_UNCHECKED, 0);
 +        EnableWindow(GetDlgItem(hwndDlg, 14002), FALSE);
 +        SendDlgItemMessage(hwndDlg, 14003, BM_SETCHECK, BST_CHECKED, 0);
 +    }
 +    else
 +    {
 +        SendDlgItemMessage(hwndDlg, 14001, BM_SETCHECK, BST_CHECKED, 0);
 +        EnableWindow(GetDlgItem(hwndDlg, 14002), TRUE);
 +        SendDlgItemMessage(hwndDlg, 14003, BM_SETCHECK, BST_UNCHECKED, 0);
 +    }
 +}
 +
 +
 +static VOID
 +InitializeRecycleBinDlg(HWND hwndDlg, WCHAR DefaultDrive)
 +{
 +    WCHAR CurDrive = L'A';
 +    WCHAR szDrive[] = L"A:\\";
 +    DWORD dwDrives;
 +    WCHAR szName[100];
 +    WCHAR szVolume[100];
 +    DWORD MaxComponent, Flags;
 +    DWORD dwSerial;
 +    LVCOLUMNW lc;
 +    HWND hDlgCtrl;
 +    LVITEMW li;
 +    INT itemCount;
 +    ULARGE_INTEGER TotalNumberOfFreeBytes, TotalNumberOfBytes, FreeBytesAvailable;
 +    RECT rect;
 +    int columnSize;
 +    int defIndex = 0;
 +    DWORD dwSize;
 +    PDRIVE_ITEM_CONTEXT pItem = NULL, pDefault = NULL, pFirst = NULL;
 +
 +    hDlgCtrl = GetDlgItem(hwndDlg, 14000);
 +
 +    if (!LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_LOCATION, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
 +        szVolume[0] = 0;
 +
 +    GetClientRect(hDlgCtrl, &rect);
 +
 +    memset(&lc, 0, sizeof(LV_COLUMN) );
 +    lc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
 +
 +    columnSize = 140; //FIXME
 +    lc.iSubItem   = 0;
 +    lc.fmt = LVCFMT_FIXED_WIDTH;
 +    lc.cx         = columnSize;
 +    lc.cchTextMax = wcslen(szVolume);
 +    lc.pszText    = szVolume;
 +    (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&lc);
 +
 +    if (!LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_DISKSPACE, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
 +        szVolume[0] = 0;
 +
 +    lc.iSubItem   = 1;
 +    lc.cx         = rect.right - rect.left - columnSize;
 +    lc.cchTextMax = wcslen(szVolume);
 +    lc.pszText    = szVolume;
 +    (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM)&lc);
 +
 +    dwDrives = GetLogicalDrives();
 +    itemCount = 0;
 +    do
 +    {
 +        if ((dwDrives & 0x1))
 +        {
 +            UINT Type = GetDriveTypeW(szDrive);
 +            if (Type == DRIVE_FIXED) //FIXME
 +            {
 +                if (!GetVolumeInformationW(szDrive, szName, sizeof(szName) / sizeof(WCHAR), &dwSerial, &MaxComponent, &Flags, NULL, 0))
 +                {
 +                    szName[0] = 0;
 +                    dwSerial = -1;
 +                }
 +
 +                swprintf(szVolume, L"%s (%c)", szName, szDrive[0]);
 +                memset(&li, 0x0, sizeof(LVITEMW));
 +                li.mask = LVIF_TEXT | LVIF_PARAM;
 +                li.iSubItem = 0;
 +                li.pszText = szVolume;
 +                li.iItem = itemCount;
 +                SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
 +                if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable , &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
 +                {
 +                    if (StrFormatByteSizeW(TotalNumberOfFreeBytes.QuadPart, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
 +                    {
 +
 +                        pItem = (DRIVE_ITEM_CONTEXT *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DRIVE_ITEM_CONTEXT));
 +                        if (pItem)
 +                        {
 +                            swprintf(szName, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\%04X-%04X", LOWORD(dwSerial), HIWORD(dwSerial));
 +                            dwSize = sizeof(DWORD);
 +                            RegGetValueW(HKEY_CURRENT_USER, szName, L"MaxCapacity", RRF_RT_DWORD, NULL, &pItem->dwMaxCapacity, &dwSize);
 +                            dwSize = sizeof(DWORD);
 +                            RegGetValueW(HKEY_CURRENT_USER, szName, L"NukeOnDelete", RRF_RT_DWORD, NULL, &pItem->dwNukeOnDelete, &dwSize);
 +                            pItem->dwSerial = dwSerial;
 +                            li.mask = LVIF_PARAM;
 +                            li.lParam = (LPARAM)pItem;
 +                            (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
 +                            if (CurDrive == DefaultDrive)
 +                            {
 +                                defIndex = itemCount;
 +                                pDefault = pItem;
 +                            }
 +                        }
 +                        if (!pFirst)
 +                            pFirst = pItem;
 +
 +                        li.mask = LVIF_TEXT;
 +                        li.iSubItem = 1;
 +                        li.pszText = szVolume;
 +                        li.iItem = itemCount;
 +                        (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
 +                    }
 +                }
 +                itemCount++;
 +            }
 +        }
 +        CurDrive++;
 +        szDrive[0] = CurDrive;
 +        dwDrives = (dwDrives >> 1);
 +    } while(dwDrives);
 +
 +    if (!pDefault)
 +        pDefault = pFirst;
 +    if (pDefault)
 +    {
 +        toggleNukeOnDeleteOption(hwndDlg, pDefault->dwNukeOnDelete);
 +        SetDlgItemInt(hwndDlg, 14002, pDefault->dwMaxCapacity, FALSE);
 +    }
 +    ZeroMemory(&li, sizeof(li));
 +    li.mask = LVIF_STATE;
 +    li.stateMask = (UINT) - 1;
 +    li.state = LVIS_FOCUSED | LVIS_SELECTED;
 +    li.iItem = defIndex;
 +    (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
 +
 +}
 +
 +static BOOL StoreDriveSettings(HWND hwndDlg)
 +{
 +    int iCount, iIndex;
 +    HWND hDlgCtrl = GetDlgItem(hwndDlg, 14000);
 +    LVITEMW li;
 +    PDRIVE_ITEM_CONTEXT pItem;
 +    HKEY hKey, hSubKey;
 +    WCHAR szSerial[20];
 +    DWORD dwSize;
 +
 +
 +    if (RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume", 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
 +        return FALSE;
 +
 +    iCount = ListView_GetItemCount(hDlgCtrl);
 +
 +    ZeroMemory(&li, sizeof(li));
 +    li.mask = LVIF_PARAM;
 +
 +    for(iIndex = 0; iIndex < iCount; iIndex++)
 +    {
 +        li.iItem = iIndex;
 +        if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&li))
 +        {
 +            pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
 +            swprintf(szSerial, L"%04X-%04X", LOWORD(pItem->dwSerial), HIWORD(pItem->dwSerial));
 +            if (RegCreateKeyExW(hKey, szSerial, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
 +            {
 +                dwSize = sizeof(DWORD);
 +                RegSetValueExW(hSubKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&pItem->dwNukeOnDelete, dwSize);
 +                dwSize = sizeof(DWORD);
 +                RegSetValueExW(hSubKey, L"MaxCapacity", 0, REG_DWORD, (LPBYTE)&pItem->dwMaxCapacity, dwSize);
 +                RegCloseKey(hSubKey);
 +            }
 +        }
 +    }
 +    RegCloseKey(hKey);
 +    return TRUE;
 +
 +}
 +
 +static VOID FreeDriveItemContext(HWND hwndDlg)
 +{
 +    int iCount, iIndex;
 +    HWND hDlgCtrl = GetDlgItem(hwndDlg, 14000);
 +    LVITEMW li;
 +
 +    iCount = ListView_GetItemCount(hDlgCtrl);
 +
 +    ZeroMemory(&li, sizeof(li));
 +    li.mask = LVIF_PARAM;
 +
 +    for(iIndex = 0; iIndex < iCount; iIndex++)
 +    {
 +        li.iItem = iIndex;
 +        if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&li))
 +        {
 +            HeapFree(GetProcessHeap(), 0, (LPVOID)li.lParam);
 +        }
 +    }
 +}
 +
 +static INT
 +GetDefaultItem(HWND hwndDlg, LVITEMW * li)
 +{
 +    HWND hDlgCtrl;
 +    UINT iItemCount, iIndex;
 +
 +    hDlgCtrl = GetDlgItem(hwndDlg, 14000);
 +    if (!hDlgCtrl)
 +        return -1;
 +
 +    iItemCount = ListView_GetItemCount(hDlgCtrl);
 +    if (!iItemCount)
 +        return -1;
 +
 +    ZeroMemory(li, sizeof(LVITEMW));
 +    li->mask = LVIF_PARAM | LVIF_STATE;
 +    li->stateMask = (UINT) - 1;
 +    for (iIndex = 0; iIndex < iItemCount; iIndex++)
 +    {
 +        li->iItem = iIndex;
 +        if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)li))
 +        {
 +            if (li->state & LVIS_SELECTED)
 +                return iIndex;
 +        }
 +    }
 +    return -1;
 +
 +}
 +
 +static INT_PTR CALLBACK
 +RecycleBinDlg(
 +    HWND hwndDlg,
 +    UINT uMsg,
 +    WPARAM wParam,
 +    LPARAM lParam
 +)
 +{
 +    LPPSHNOTIFY lppsn;
 +    LPNMLISTVIEW lppl;
 +    LVITEMW li;
 +    PDRIVE_ITEM_CONTEXT pItem;
 +    BOOL bSuccess;
 +    UINT uResult;
 +    PROPSHEETPAGE * page;
 +    DWORD dwStyle;
 +
 +    switch(uMsg)
 +    {
 +        case WM_INITDIALOG:
 +            page = (PROPSHEETPAGE*)lParam;
 +            InitializeRecycleBinDlg(hwndDlg, (WCHAR)page->lParam);
 +            dwStyle = (DWORD) SendDlgItemMessage(hwndDlg, 14000, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
 +            dwStyle = dwStyle | LVS_EX_FULLROWSELECT;
 +            SendDlgItemMessage(hwndDlg, 14000, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
 +            if (GetDlgCtrlID((HWND)wParam) != 14000)
 +            {
 +                SetFocus(GetDlgItem(hwndDlg, 14000));
 +                return FALSE;
 +            }
 +            return TRUE;
 +        case WM_COMMAND:
 +            switch(LOWORD(wParam))
 +            {
 +                case 14001:
 +                    toggleNukeOnDeleteOption(hwndDlg, FALSE);
 +                    PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
 +                    break;
 +                case 14003:
 +                    toggleNukeOnDeleteOption(hwndDlg, TRUE);
 +                    PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
 +                    break;
 +                case 14004:
 +                    PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
 +                    break;
 +            }
 +            break;
 +        case WM_NOTIFY:
 +            lppsn = (LPPSHNOTIFY) lParam;
 +            lppl = (LPNMLISTVIEW) lParam;
 +            if (lppsn->hdr.code == PSN_APPLY)
 +            {
 +                if (GetDefaultItem(hwndDlg, &li) > -1)
 +                {
 +                    pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
 +                    if (pItem)
 +                    {
 +                        uResult = GetDlgItemInt(hwndDlg, 14002, &bSuccess, FALSE);
 +                        if (bSuccess)
 +                            pItem->dwMaxCapacity = uResult;
 +                        if (SendDlgItemMessageW(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED)
 +                            pItem->dwNukeOnDelete = TRUE;
 +                        else
 +                            pItem->dwNukeOnDelete = FALSE;
 +                    }
 +                }
 +                if (StoreDriveSettings(hwndDlg))
 +                {
 +                    SetWindowLongPtr( hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR );
 +                    return TRUE;
 +                }
 +            }
 +            else if (lppl->hdr.code == LVN_ITEMCHANGING)
 +            {
 +                ZeroMemory(&li, sizeof(li));
 +                li.mask = LVIF_PARAM;
 +                li.iItem = lppl->iItem;
 +                if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&li))
 +                    return TRUE;
 +
 +                pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
 +                if (!pItem)
 +                    return TRUE;
 +
 +                if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED))
 +                {
 +                    /* new focused item */
 +                    toggleNukeOnDeleteOption(lppl->hdr.hwndFrom, pItem->dwNukeOnDelete);
 +                    SetDlgItemInt(hwndDlg, 14002, pItem->dwMaxCapacity, FALSE);
 +                }
 +                else if ((lppl->uOldState & LVIS_FOCUSED) && !(lppl->uNewState & LVIS_FOCUSED))
 +                {
 +                    /* kill focus */
 +                    uResult = GetDlgItemInt(hwndDlg, 14002, &bSuccess, FALSE);
 +                    if (bSuccess)
 +                        pItem->dwMaxCapacity = uResult;
 +                    if (SendDlgItemMessageW(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED)
 +                        pItem->dwNukeOnDelete = TRUE;
 +                    else
 +                        pItem->dwNukeOnDelete = FALSE;
 +                }
 +                return TRUE;
 +
 +            }
 +            break;
 +        case WM_DESTROY:
 +            FreeDriveItemContext(hwndDlg);
 +            break;
 +    }
 +    return FALSE;
 +}
 +
 +BOOL SH_ShowRecycleBinProperties(WCHAR sDrive)
 +{
 +    HPROPSHEETPAGE hpsp[1];
 +    PROPSHEETHEADERW psh;
 +    HPROPSHEETPAGE hprop;
 +
 +    BOOL ret;
 +
 +
 +    ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
 +    psh.dwSize = sizeof(PROPSHEETHEADERW);
 +    psh.dwFlags = PSP_DEFAULT | PSH_PROPTITLE;
 +    psh.pszCaption = MAKEINTRESOURCEW(IDS_RECYCLEBIN_FOLDER_NAME);
 +    psh.hwndParent = NULL;
 +    psh.phpage = hpsp;
 +    psh.hInstance = shell32_hInstance;
 +
 +    hprop = SH_CreatePropertySheetPage(IDD_RECYCLE_BIN_PROPERTIES, RecycleBinDlg, (LPARAM)sDrive, NULL);
 +    if (!hprop)
 +    {
 +        ERR("Failed to create property sheet\n");
 +        return FALSE;
 +    }
 +    hpsp[psh.nPages] = hprop;
 +    psh.nPages++;
 +
 +
 +    ret = PropertySheetW(&psh);
 +    if (ret < 0)
 +        return FALSE;
 +    else
 +        return TRUE;
 +}
 +
 +BOOL
 +TRASH_CanTrashFile(LPCWSTR wszPath)
 +{
 +    LONG ret;
 +    DWORD dwNukeOnDelete, dwType, VolSerialNumber, MaxComponentLength;
 +    DWORD FileSystemFlags, dwSize, dwDisposition;
 +    HKEY hKey;
 +    WCHAR szBuffer[10];
 +    WCHAR szKey[150] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\";
 +
 +    if (wszPath[1] != L':')
 +    {
 +        /* path is UNC */
 +        return FALSE;
 +    }
 +
 +    if (GetDriveTypeW(wszPath) != DRIVE_FIXED)
 +    {
 +        /* no bitbucket on removable media */
 +        return FALSE;
 +    }
 +
 +    if (!GetVolumeInformationW(wszPath, NULL, 0, &VolSerialNumber, &MaxComponentLength, &FileSystemFlags, NULL, 0))
 +    {
 +        ERR("GetVolumeInformationW failed with %u\n", GetLastError());
 +        return FALSE;
 +    }
 +
 +    swprintf(szBuffer, L"%04X-%04X", LOWORD(VolSerialNumber), HIWORD(VolSerialNumber));
 +    wcscat(szKey, szBuffer);
 +
 +    if (RegCreateKeyExW(HKEY_CURRENT_USER, szKey, 0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS)
 +    {
 +        ERR("RegCreateKeyExW failed\n");
 +        return FALSE;
 +    }
 +
 +    if (dwDisposition  & REG_CREATED_NEW_KEY)
 +    {
 +        /* per default move to bitbucket */
 +        dwNukeOnDelete = 0;
 +        RegSetValueExW(hKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&dwNukeOnDelete, sizeof(DWORD));
 +        /* per default unlimited size */
 +        dwSize = -1;
 +        RegSetValueExW(hKey, L"MaxCapacity", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD));
 +        RegCloseKey(hKey);
 +        return TRUE;
 +    }
 +    else
 +    {
 +        dwSize = sizeof(dwNukeOnDelete);
 +        ret = RegQueryValueExW(hKey, L"NukeOnDelete", NULL, &dwType, (LPBYTE)&dwNukeOnDelete, &dwSize);
 +        if (ret != ERROR_SUCCESS)
 +        {
 +            if (ret ==  ERROR_FILE_NOT_FOUND)
 +            {
 +                /* restore key and enable bitbucket */
 +                dwNukeOnDelete = 0;
 +                RegSetValueExW(hKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&dwNukeOnDelete, sizeof(DWORD));
 +            }
 +            RegCloseKey(hKey);
 +            return TRUE;
 +        }
 +        else if (dwNukeOnDelete)
 +        {
 +            /* do not delete to bitbucket */
 +            RegCloseKey(hKey);
 +            return FALSE;
 +        }
 +        /* FIXME
 +         * check if bitbucket is full
 +         */
 +        RegCloseKey(hKey);
 +        return TRUE;
 +    }
 +}
 +
 +BOOL
 +TRASH_TrashFile(LPCWSTR wszPath)
 +{
 +    TRACE("(%s)\n", debugstr_w(wszPath));
 +    return DeleteFileToRecycleBin(wszPath);
 +}
 +
 +/*************************************************************************
 + * SHUpdateCRecycleBinIcon                                [SHELL32.@]
 + *
 + * Undocumented
 + */
 +EXTERN_C HRESULT WINAPI SHUpdateRecycleBinIcon(void)
 +{
 +    FIXME("stub\n");
 +
 +
 +
 +    return S_OK;
 +}
 +
 +/****************************************************************************
 + * IDropTarget implementation
 + */
 +BOOL CRecycleBin::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
 +{
 +    /* TODO on shift we should delete, we should update the cursor manager to show this. */
 +
 +    DWORD dwEffect = DROPEFFECT_COPY;
 +
 +    *pdwEffect = DROPEFFECT_NONE;
 +
 +    if (fAcceptFmt) { /* Does our interpretation of the keystate ... */
 +        *pdwEffect = KeyStateToDropEffect (dwKeyState);
 +
 +        if (*pdwEffect == DROPEFFECT_NONE)
 +            *pdwEffect = dwEffect;
 +
 +        /* ... matches the desired effect ? */
 +        if (dwEffect & *pdwEffect) {
 +            return TRUE;
 +        }
 +    }
 +    return FALSE;
 +}
 +
 +HRESULT WINAPI CRecycleBin::DragEnter(IDataObject *pDataObject,
 +                                    DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    TRACE("Recycle bin drag over (%p)\n", this);
 +    /* The recycle bin accepts pretty much everything, and sets a CSIDL flag. */
 +    fAcceptFmt = TRUE;
 +
 +    QueryDrop(dwKeyState, pdwEffect);
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBin::DragOver(DWORD dwKeyState, POINTL pt,
 +                                   DWORD *pdwEffect)
 +{
 +    TRACE("(%p)\n", this);
 +
 +    if (!pdwEffect)
 +        return E_INVALIDARG;
 +
 +    QueryDrop(dwKeyState, pdwEffect);
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBin::DragLeave()
 +{
 +    TRACE("(%p)\n", this);
 +
 +    fAcceptFmt = FALSE;
 +
 +    return S_OK;
 +}
 +
 +HRESULT WINAPI CRecycleBin::Drop(IDataObject *pDataObject,
 +                               DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 +{
 +    TRACE("(%p) object dropped on recycle bin, effect %u\n", this, *pdwEffect);
 +    
 +    /* TODO: pdwEffect should be read and make the drop object be permanently deleted in the move case (shift held) */
 +
 +    FORMATETC fmt;
 +    TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
 +    InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
 +
 +    /* Handle cfShellIDList Drop objects here, otherwise send the approriate message to other software */
 +    if (SUCCEEDED(pDataObject->QueryGetData(&fmt))) {
-     IDataObject *pda = (IDataObject*) lpParameter;
-     DoDeleteDataObject(pda);
-     //Release the data object
-     pda->Release();
++        IStream *s;
++        CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &s);
++        SHCreateThread(DoDeleteThreadProc, s, NULL, NULL);
 +    }
 +    else
 +    {
 +        /* 
 +         * TODO call SetData on the data object with format CFSTR_TARGETCLSID
 +         * set to the Recycle Bin's class identifier CLSID_RecycleBin.
 +         */
 +    }
 +    return S_OK;
 +}
 +
 +DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter) 
 +{
++    CoInitialize(NULL);
++    CComPtr<IDataObject> pDataObject;
++    HRESULT hr = CoGetInterfaceAndReleaseStream (static_cast<IStream*>(lpParameter), IID_PPV_ARG(IDataObject, &pDataObject));
++    if (SUCCEEDED(hr))
++    {
++        DoDeleteDataObject(pDataObject);
++    }
++    CoUninitialize();
 +    return 0;
 +}
 +
 +HRESULT WINAPI DoDeleteDataObject(IDataObject *pda) 
 +{
 +    TRACE("performing delete");
 +    HRESULT hr;
 +
 +    STGMEDIUM medium;
 +    FORMATETC formatetc;
 +    InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
 +    hr = pda->GetData(&formatetc, &medium);
 +    if (FAILED(hr))
 +        return hr;
 +
 +    /* lock the handle */
 +    LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
 +    if (!lpcida)
 +    {
 +        ReleaseStgMedium(&medium);
 +        return E_FAIL;
 +    }
 +
 +    /* convert the data into pidl */
 +    LPITEMIDLIST pidl;
 +    LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
 +    if (!apidl)
 +    {
 +        ReleaseStgMedium(&medium);
 +        return E_FAIL;
 +    }
 +
 +    CComPtr<IShellFolder> psfDesktop;
 +    CComPtr<IShellFolder> psfFrom = NULL;
 +
 +    /* Grab the desktop shell folder */
 +    hr = SHGetDesktopFolder(&psfDesktop);
 +    if (FAILED(hr))
 +    {
 +        ERR("SHGetDesktopFolder failed\n");
 +        SHFree(pidl);
 +        _ILFreeaPidl(apidl, lpcida->cidl);
 +        ReleaseStgMedium(&medium);
 +        return E_FAIL;
 +    }
 +
 +    /* Find source folder, this is where the clipboard data was copied from */
 +    if (_ILIsDesktop(pidl))
 +    {
 +        psfFrom = psfDesktop;
 +    }
 +    else 
 +    {
 +        hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom));
 +        if (FAILED(hr))
 +        {
 +            ERR("no IShellFolder\n");
 +            SHFree(pidl);
 +            _ILFreeaPidl(apidl, lpcida->cidl);
 +            ReleaseStgMedium(&medium);
 +            return E_FAIL;
 +        }
 +    }
 +
 +    STRRET strTemp;
 +    hr = psfFrom->GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strTemp);
 +    if (FAILED(hr))
 +    {
 +        ERR("IShellFolder_GetDisplayNameOf failed with %x\n", hr);
 +        SHFree(pidl);
 +        _ILFreeaPidl(apidl, lpcida->cidl);
 +        ReleaseStgMedium(&medium);
 +        return hr;
 +    }
 +
 +    WCHAR wszPath[MAX_PATH];
 +    hr = StrRetToBufW(&strTemp, apidl[0], wszPath, _countof(wszPath));
 +    if (FAILED(hr))
 +    {
 +        ERR("StrRetToBufW failed with %x\n", hr);
 +        SHFree(pidl);
 +        _ILFreeaPidl(apidl, lpcida->cidl);
 +        ReleaseStgMedium(&medium);
 +        return hr;
 +    }
 +
 +    /* Only keep the base path */
 +    LPWSTR pwszFilename = PathFindFileNameW(wszPath);
 +    *pwszFilename = L'\0';
 +
 +    /* Build paths list */
 +    LPWSTR pwszPaths = BuildPathsList(wszPath, lpcida->cidl, (LPCITEMIDLIST*) apidl);
 +    if (!pwszPaths)
 +    {
 +        SHFree(pidl);
 +        _ILFreeaPidl(apidl, lpcida->cidl);
 +        ReleaseStgMedium(&medium);
 +        return E_FAIL;
 +    }
 +
 +    /* Delete them */
 +    SHFILEOPSTRUCTW FileOp;
 +    ZeroMemory(&FileOp, sizeof(FileOp));
 +    FileOp.wFunc = FO_DELETE;
 +    FileOp.pFrom = pwszPaths;
 +    FileOp.fFlags = FOF_ALLOWUNDO;
 +
 +    if (SHFileOperationW(&FileOp) != 0)
 +    {
 +        ERR("SHFileOperation failed with 0x%x for %s\n", GetLastError(), debugstr_w(pwszPaths));
 +        hr = E_FAIL;
 +    }
 +
 +    HeapFree(GetProcessHeap(), 0, pwszPaths);
 +    SHFree(pidl);
 +    _ILFreeaPidl(apidl, lpcida->cidl);
 +    ReleaseStgMedium(&medium);
 +
 +    return hr;
 +}
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,7d10e03..7d10e03
mode 000000,100644..100644
--- /dev/null
index 0000000,d49a60a..d49a60a
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
index 0000000,9b5637d..9b5637d
mode 000000,100644..100644
--- /dev/null
Simple merge
index a7b6f2e,48c0d0e..48c0d0e
Binary files differ
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge