00001 /* Manage the creation and manipulation of PIDLs 00002 00003 Copyright (C) 2007 Alexander Lamaison <awl03@doc.ic.ac.uk> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License along 00016 with this program; if not, write to the Free Software Foundation, Inc., 00017 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 00020 #include "stdafx.h" 00021 #include "PidlManager.h" 00022 00023 CPidlManager::CPidlManager() 00024 { 00025 } 00026 00027 CPidlManager::~CPidlManager() 00028 { 00029 } 00030 00031 /*------------------------------------------------------------------------------ 00032 * CPidlManager::Delete 00033 * Free the PIDL using the Shell PIDL allocator. 00034 * Apparently, this function Validates that the memory being freed is 00035 * a PIDL when in a Debug build. 00036 *----------------------------------------------------------------------------*/ 00037 void CPidlManager::Delete( LPITEMIDLIST pidl ) 00038 { 00039 ILFree(pidl); 00040 } 00041 00042 /*------------------------------------------------------------------------------ 00043 * CPidlManager::GetNextItem 00044 * Returns a pointer to the next item ID in the list passed as pidl. 00045 * If pidl points to the last *non-terminator* SHITEMID the terminator is 00046 * returned. If pidl points to the terminator already or is NULL the function 00047 * returns NULL. This is not made clear in the MSDN ILGetNext documentation. 00048 *----------------------------------------------------------------------------*/ 00049 LPITEMIDLIST CPidlManager::GetNextItem( LPCITEMIDLIST pidl ) 00050 { 00051 return ILGetNext(pidl); 00052 } 00053 00054 /*------------------------------------------------------------------------------ 00055 * CPidlManager::GetLastItem 00056 * Returns a pointer to the last *non-terminator* item ID in the list pidl. 00057 * This is not made clear in the MSDN ILGetNext documentation. It is also 00058 * unclear what happens of the pidl were to be the terminator or NULL. 00059 *----------------------------------------------------------------------------*/ 00060 LPITEMIDLIST CPidlManager::GetLastItem( LPCITEMIDLIST pidl ) 00061 { 00062 ATLENSURE(pidl); 00063 ATLENSURE(pidl->mkid.cb); // pidl is not the terminator 00064 00065 return ILFindLastID(pidl); 00066 } 00067 00068 /*------------------------------------------------------------------------------ 00069 * CPidlManager::GetSize 00070 * The total size of the passed in pidl in bytes including the zero terminator. 00071 *----------------------------------------------------------------------------*/ 00072 UINT CPidlManager::GetSize( LPCITEMIDLIST pidl ) 00073 { 00074 return ILGetSize(pidl); 00075 } 00076 00077 /*------------------------------------------------------------------------------ 00078 * CPidlManager::CopyWSZString 00079 * Copies a WString into provided buffer and performs checking. 00080 * Length in BYTEs of return buffer is given as cchDest. 00081 *----------------------------------------------------------------------------*/ 00082 HRESULT CPidlManager::CopyWSZString( __out_ecount(cchDest) PWSTR pwszDest, 00083 __in USHORT cchDest, 00084 __in PCWSTR pwszSrc) 00085 { 00086 // Neither source nor destination of StringCbCopyW can be NULL 00087 ATLASSERT(pwszSrc != NULL && pwszDest != NULL); 00088 00089 HRESULT hr = StringCchCopyW(pwszDest, cchDest, pwszSrc); 00090 00091 ATLASSERT(SUCCEEDED(hr)); 00092 return hr; 00093 } 00094 00095 /*------------------------------------------------------------------------------ 00096 * CPidlManager::GetDataSegment 00097 * Walk to last item in PIDL (if multilevel) and returns item as a HOSTPIDL. 00098 *----------------------------------------------------------------------------*/ 00099 PITEMID_CHILD CPidlManager::GetDataSegment( LPCITEMIDLIST pidl ) 00100 { 00101 // Get the last item of the PIDL to make sure we get the right value 00102 // in case of multiple nesting levels 00103 return (PITEMID_CHILD)GetLastItem( pidl ); 00104 } 00105 00106 /*------------------------------------------------------------------------------ 00107 * CPidlManager::Copy 00108 * Duplicate a PIDL. 00109 *----------------------------------------------------------------------------*/ 00110 LPITEMIDLIST CPidlManager::Copy( LPCITEMIDLIST pidlSrc ) 00111 { 00112 LPITEMIDLIST pidlTarget = ILClone( pidlSrc ); 00113 00114 ATLASSERT(GetSize(pidlSrc) == GetSize(pidlTarget)); 00115 ATLASSERT(!memcmp(pidlSrc, pidlTarget, GetSize(pidlSrc))); 00116 00117 return pidlTarget; 00118 }