#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
}