232 lines
5.3 KiB
C++
232 lines
5.3 KiB
C++
// ShellPidl.cpp: implementation of the CShellPidl class.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2000-2001 by Paolo Messina
|
|
// (http://www.geocities.com/ppescher - ppescher@yahoo.com)
|
|
//
|
|
// The contents of this file are subject to the Artistic License (the "License").
|
|
// You may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at:
|
|
// http://www.opensource.org/licenses/artistic-license.html
|
|
//
|
|
// If you find this code useful, credits would be nice!
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include <afxpriv.h>
|
|
#include "ShellPidl.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Static Functions
|
|
|
|
// does not include terminating zero
|
|
// NULL objects get a zero length
|
|
UINT CShellPidl::ILGetLength(LPCITEMIDLIST pidl)
|
|
{
|
|
if (pidl == NULL)
|
|
return 0;
|
|
|
|
UINT length = 0, cb;
|
|
do
|
|
{
|
|
cb = pidl->mkid.cb;
|
|
pidl = (LPCITEMIDLIST)((LPBYTE)pidl + cb);
|
|
length += cb;
|
|
}
|
|
while (cb != 0);
|
|
|
|
return length;
|
|
}
|
|
|
|
LPCITEMIDLIST CShellPidl::ILGetNext(LPCITEMIDLIST pidl)
|
|
{
|
|
if (pidl == NULL)
|
|
return NULL;
|
|
|
|
// Get the size of the specified item identifier.
|
|
int cb = pidl->mkid.cb;
|
|
|
|
// If the size is zero, it is the end of the list.
|
|
if (cb == 0)
|
|
return NULL;
|
|
|
|
// Add cb to pidl (casting to increment by bytes).
|
|
pidl = (LPCITEMIDLIST)((LPBYTE)pidl + cb);
|
|
|
|
// Return NULL if we reached the terminator, or a pidl otherwise.
|
|
return (pidl->mkid.cb == 0) ? NULL : pidl;
|
|
}
|
|
|
|
LPCITEMIDLIST CShellPidl::ILGetLast(LPCITEMIDLIST pidl)
|
|
{
|
|
LPCITEMIDLIST pidlLast = pidl, tmp = ILGetNext(pidl);
|
|
while (tmp != NULL)
|
|
{
|
|
pidlLast = tmp;
|
|
tmp = ILGetNext(tmp);
|
|
}
|
|
|
|
return pidlLast;
|
|
}
|
|
|
|
LPITEMIDLIST CShellPidl::ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
|
{
|
|
// check arguments
|
|
if (pidl1 == NULL && pidl2 == NULL)
|
|
return NULL;
|
|
|
|
// Get the size of the resulting item identifier list
|
|
UINT cb1 = ILGetLength(pidl1);
|
|
UINT cb2 = ILGetLength(pidl2);
|
|
|
|
// Allocate a new item identifier list
|
|
SMallocPtr pMalloc;
|
|
LPITEMIDLIST pidlNew = (LPITEMIDLIST)pMalloc->Alloc(cb1 + cb2 + sizeof(USHORT));
|
|
LPITEMIDLIST pidlEnd = pidlNew;
|
|
if (pidlNew != NULL)
|
|
{
|
|
// Copy the first item identifier list and terminating 0
|
|
if (cb1 > 0)
|
|
{
|
|
CopyMemory(pidlEnd, pidl1, cb1);
|
|
pidlEnd = (LPITEMIDLIST)((LPBYTE)pidlEnd + cb1);
|
|
}
|
|
|
|
// Copy the second item identifier list and terminating 0
|
|
if (cb2 > 0)
|
|
{
|
|
CopyMemory(pidlEnd, pidl2, cb2);
|
|
pidlEnd = (LPITEMIDLIST)((LPBYTE)pidlEnd + cb2);
|
|
}
|
|
|
|
// Append a terminating zero.
|
|
pidlEnd->mkid.cb = 0;
|
|
}
|
|
return pidlNew;
|
|
}
|
|
|
|
LPITEMIDLIST CShellPidl::ILCloneFirst(LPCITEMIDLIST pidl)
|
|
{
|
|
LPITEMIDLIST pidlNew = NULL;
|
|
|
|
if (pidl != NULL)
|
|
{
|
|
// Get the size of the first item identifier.
|
|
int cb = pidl->mkid.cb;
|
|
|
|
// Allocate a new item identifier list.
|
|
SMallocPtr pMalloc;
|
|
pidlNew = (LPITEMIDLIST)pMalloc->Alloc(cb + sizeof(USHORT));
|
|
|
|
if (pidlNew != NULL)
|
|
{
|
|
// Copy the specified item identifier.
|
|
CopyMemory(pidlNew, pidl, cb);
|
|
|
|
// Append a terminating zero.
|
|
((LPITEMIDLIST)((LPBYTE)pidlNew + cb))->mkid.cb = 0;
|
|
}
|
|
}
|
|
return pidlNew;
|
|
}
|
|
|
|
LPITEMIDLIST CShellPidl::ILCloneParent(LPCITEMIDLIST pidl)
|
|
{
|
|
// Get the size of the parent item identifier.
|
|
UINT cb = (UINT)ILGetLast(pidl) - (UINT)pidl;
|
|
|
|
SMallocPtr pMalloc;
|
|
LPITEMIDLIST pidlNew = (LPITEMIDLIST)pMalloc->Alloc(cb + sizeof(USHORT));
|
|
|
|
if (pidlNew != NULL)
|
|
{
|
|
// Copy the specified item identifier.
|
|
CopyMemory(pidlNew, pidl, cb);
|
|
|
|
// Append a terminating zero.
|
|
((LPITEMIDLIST)((LPBYTE)pidlNew + cb))->mkid.cb = 0;
|
|
}
|
|
return pidlNew;
|
|
}
|
|
|
|
LPITEMIDLIST CShellPidl::ILFromPath(LPCTSTR pszPath, HWND hOwner)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
ULONG count = 0;
|
|
LPITEMIDLIST pidlNew = NULL;
|
|
|
|
SDesktopFolderPtr pDesktopFolder;
|
|
pDesktopFolder->ParseDisplayName(hOwner, NULL,
|
|
T2OLE(pszPath), &count, &pidlNew, NULL);
|
|
|
|
return pidlNew;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Member Functions
|
|
|
|
// debug
|
|
|
|
#ifdef _DEBUG
|
|
void CShellPidl::Dump(CDumpContext& dc) const
|
|
{
|
|
dc << "addr = " << (void*)m_pObj << "\n";
|
|
if (m_pObj == NULL)
|
|
return;
|
|
|
|
dc << "[structure]\n";
|
|
|
|
LPCITEMIDLIST pidl = m_pObj;
|
|
while (pidl != NULL)
|
|
{
|
|
dc << " " << pidl->mkid.cb;
|
|
pidl = ILGetNext(pidl);
|
|
}
|
|
dc << "\n";
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
int CShellPidl::CompareItemID(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
|
|
{
|
|
if(pidl1 == pidl2)
|
|
return 0;
|
|
if(!pidl1 || !pidl2)
|
|
return -1;
|
|
if(GetItemIDSize(pidl1) != GetItemIDSize(pidl2))
|
|
return -1;
|
|
return memcmp(pidl1,pidl2,GetItemIDSize(pidl1));
|
|
}
|
|
|
|
|
|
int CShellPidl::GetItemIDSize(LPCITEMIDLIST pidl)
|
|
{
|
|
if(!pidl)
|
|
return 0;
|
|
int nSize = 0;
|
|
while(pidl -> mkid.cb)
|
|
{
|
|
nSize += pidl -> mkid.cb;
|
|
pidl = (LPCITEMIDLIST)(((LPBYTE)pidl) + pidl -> mkid.cb);
|
|
}
|
|
return nSize;
|
|
}
|
|
|
|
LPITEMIDLIST CShellPidl::GetObject()
|
|
{
|
|
return this -> m_pObj;
|
|
}
|
|
|
|
int CShellPidl::CompareItemID(int nSpecialFolder)
|
|
{
|
|
CShellPidl compareID(nSpecialFolder);
|
|
return CompareItemID(m_pObj, compareID);
|
|
}
|
|
|
|
int CShellPidl::CompareItemID(LPITEMIDLIST cmpid)
|
|
{
|
|
return CompareItemID(m_pObj, cmpid);
|
|
}
|