PIDL操作用APIのエミュレーション

(2003.02.11)
#define ILHELPER_USE_EMULATE
 
    // ShlwapiHelper.hからコピー
    // shell32.dll version 5.0 or later 互換
    static LPVOID Emulate_SHAlloc(SIZE_T cb)
    {
#ifdef ILHELPER_USE_EMULATE
        HRESULT hr = S_OK;
 
        IMallocPtr spMalloc;
        hr = ::SHGetMalloc(&spMalloc);
        if (FAILED(hr))
        {
            return NULL;
        }
 
        return spMalloc->Alloc(cb);
#else
        return ::Emulate_SHAlloc(cb);
#endif
    }
    // ShlwapiHelper.hからコピー
    // shell32.dll version 5.0 or later 互換
    static void Emulate_SHFree(void* pv)
    {
#ifdef ILHELPER_USE_EMULATE
        HRESULT hr = S_OK;
 
        IMallocPtr spMalloc;
        hr = ::SHGetMalloc(&spMalloc);
        if (FAILED(hr))
        {
            return;
        }
 
        spMalloc->Free(pv);
#else
        return ::Emulate_SHFree(pv);
#endif
    }
    // ShlwapiHelper.hからコピー
    // shell32.dll version 5.0 or later 互換
    static void Emulate_ILFree(LPITEMIDLIST pidl)
    {
#ifdef ILHELPER_USE_EMULATE
        Emulate_SHFree(pidl);
#else
        return ::Emulate_ILFree(pidl);
#endif
    }
 
    // shell32.dll version 5.0 or later 互換
    static UINT Emulate_ILGetSize(LPCITEMIDLIST pidl)
    {
#ifdef ILHELPER_USE_EMULATE
        if (pidl == NULL)
        {
            return 0;
        }
 
        UINT cbTotal = sizeof(pidl->mkid.cb);    // Null terminator
        while (pidl)
        {
            cbTotal += pidl->mkid.cb;
            pidl = Emulate_ILGetNext(pidl);
        }
 
        return cbTotal;
#else
        return ::ILGetSize(pidl);
#endif
    }
    // shell32.dll version 5.0 or later 互換
    static LPITEMIDLIST Emulate_ILGetNext(LPCITEMIDLIST pidl)
    { 
#ifdef ILHELPER_USE_EMULATE
        if (pidl == NULL)
        {
            ATLASSERT(0);
            return NULL;
        }
 
        // Get the size of the specified item identifier. 
        int cb = pidl->mkid.cb; 
        if (cb == 0) 
        {
            return NULL; 
        }
 
        // Add cb to pidl (casting to increment by bytes). 
        pidl = (LPITEMIDLIST)(((LPBYTE)pidl) + cb); 
 
        // Return NULL if it is null-terminating, or a pidl otherwise. 
//        return (pidl->mkid.cb == 0) ? NULL : (LPITEMIDLIST)pidl; 
        return (LPITEMIDLIST)pidl;            // ILGetNext()の仕様にあわせた
#else
        return ::ILGetNext(pidl);
#endif
    }
 
    // shell32.dll version 5.0 or later 互換
    static LPITEMIDLIST Emulate_ILClone(LPCITEMIDLIST pidl)
    {
#ifdef ILHELPER_USE_EMULATE
        if (pidl == NULL)
        {
//            ATLASSERT(0);
            return NULL;
        }
 
        // Calculate size of list.
        UINT cb = Emulate_ILGetSize(pidl);
 
        LPITEMIDLIST pidlClone = (LPITEMIDLIST)Emulate_SHAlloc(cb);
        if (pidlClone == NULL)
        {
            ATLASSERT(0);
            return NULL;
        }
 
        ::CopyMemory(pidlClone, pidl, cb);
 
        return pidlClone;
#else
        return ::ILClone(pidl);
#endif
    }
    // shell32.dll version 5.0 or later 互換
    static LPITEMIDLIST Emulate_ILCloneFirst(LPCITEMIDLIST pidl)
    {
#ifdef ILHELPER_USE_EMULATE
        if (pidl == NULL)
        {
            ATLASSERT(0);
            return NULL;
        }
 
        // Calculate size and allocate space.
        UINT cb = pidl->mkid.cb + sizeof(pidl->mkid.cb);
 
        LPITEMIDLIST pidlRet = (LPITEMIDLIST)Emulate_SHAlloc(cb);
 
        // Copy first item and append terminating zero.
        if (pidlRet)
        {
            ::CopyMemory(pidlRet, pidl, cb);
            Emulate_ILGetNext(pidlRet)->mkid.cb = 0;
        }
 
        return pidlRet;
#else
        return ::ILCloneFirst(pidl);
#endif
    }
    // shell32.dll version 5.0 or later 互換
    static LPITEMIDLIST Emulate_ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
    {
#ifdef ILHELPER_USE_EMULATE
        if (pidl1 == NULL)
        {
            return NULL;
        }
 
        if (pidl2 == NULL)
        {
            return Emulate_ILClone(pidl1);
        }
 
        UINT cb1 = Emulate_ILGetSize(pidl1) - sizeof(pidl1->mkid.cb);
        UINT cb2 = Emulate_ILGetSize(pidl2);
 
        LPITEMIDLIST pidlNew = (LPITEMIDLIST)Emulate_SHAlloc(cb1 + cb2);
        if (pidlNew == NULL)
        {
            return NULL;
        }
 
        ::CopyMemory(pidlNew, pidl1, cb1);
        ::CopyMemory(((LPSTR)pidlNew) + cb1, pidl2, cb2);
 
        return pidlNew;
#else
        return ::ILCombine(pidl1, pidl2);
#endif
    }
 
public:
    // shell32.dll version 5.0 or later 互換
    static LPITEMIDLIST Emulate_ILCreateFromPath(LPCTSTR pszPath)
    {
        USES_CONVERSION;
        return Emulate_ILCreateFromPathW(T2W(pszPath));
    }
    // shell32.dll version 5.0 or later 互換
    static LPITEMIDLIST Emulate_ILCreateFromPathW(LPCWSTR pwszPath)
    {
#ifdef ILHELPER_USE_EMULATE
        HRESULT hr = S_OK;
 
        IShellFolderPtr spDesktop;
        hr = ::SHGetDesktopFolder(&spDesktop);
        if (FAILED(hr))
        {
            ATLASSERT(0);
            return NULL;
        }
 
        ULONG chEaten = 0;
        LPITEMIDLIST pidl = NULL;
        ULONG dwAttributes = 0;
        hr = spDesktop->ParseDisplayName(NULL, NULL, (LPOLESTR)pwszPath, &chEaten, &pidl, &dwAttributes);
        if (FAILED(hr))
        {
            return NULL;
        }
 
        return pidl;
#else
        return ::ILCreateFromPathW(pwszPath);
#endif
    }
    // shell32.dll version 5.0 or later 互換
    static BOOL Emulate_ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
    {
#ifdef ILHELPER_USE_EMULATE
        if (pidl1 == pidl2)
        {
            return TRUE;
        }
 
        int nSize1 = Emulate_ILGetSize(pidl1);
        int nSize2 = Emulate_ILGetSize(pidl2);
        if (nSize1 != nSize2)
        {
            return FALSE;
        }
 
        return (memcmp(pidl1, pidl2, nSize1) == 0) ? TRUE : FALSE;
#else
        return ::ILIsEqual(pidl1, pidl2);
#endif
    }
一覧に戻る
© 2003 WAC.com All Right Reserved.