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);
 +