You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
553 lines
12 KiB
553 lines
12 KiB
/**************************************************************************
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
PARTICULAR PURPOSE.
|
|
|
|
Copyright 1998 Microsoft Corporation. All Rights Reserved.
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
|
|
File: PidlMgr.cpp
|
|
|
|
Description: Implements CPidlMgr.
|
|
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
#include statements
|
|
**************************************************************************/
|
|
|
|
#include "PidlMgr.h"
|
|
#include "ShlFldr.h"
|
|
#include "Guid.h"
|
|
#include "resource.h"
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::CPidlMgr
|
|
|
|
**************************************************************************/
|
|
|
|
CPidlMgr::CPidlMgr()
|
|
{
|
|
g_DllRefCount++;
|
|
|
|
//get the shell's IMalloc pointer
|
|
//we'll keep this until we get destroyed
|
|
if(FAILED(SHGetMalloc(&m_pMalloc)))
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::~CPidlMgr
|
|
|
|
**************************************************************************/
|
|
|
|
CPidlMgr::~CPidlMgr()
|
|
{
|
|
if(m_pMalloc)
|
|
m_pMalloc->Release();
|
|
|
|
g_DllRefCount--;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::Create()
|
|
|
|
Creates a new PIDL
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::Create(VOID)
|
|
{
|
|
LPITEMIDLIST pidlOut;
|
|
USHORT uSize;
|
|
|
|
pidlOut = NULL;
|
|
|
|
/*
|
|
Calculate the size. This consists of the ITEMIDLIST plus the size of our
|
|
private PIDL structure.
|
|
*/
|
|
uSize = sizeof(ITEMIDLIST) + sizeof(PIDLDATA);
|
|
|
|
/*
|
|
Allocate the memory, adding an additional ITEMIDLIST for the NULL terminating
|
|
ID List.
|
|
*/
|
|
pidlOut = (LPITEMIDLIST)m_pMalloc->Alloc(uSize + sizeof(ITEMIDLIST));
|
|
|
|
if(pidlOut)
|
|
{
|
|
LPITEMIDLIST pidlTemp = pidlOut;
|
|
|
|
//set the size of this item
|
|
pidlTemp->mkid.cb = uSize;
|
|
|
|
//set the NULL terminator to 0
|
|
pidlTemp = GetNextItem(pidlTemp);
|
|
pidlTemp->mkid.cb = 0;
|
|
pidlTemp->mkid.abID[0] = 0;
|
|
}
|
|
|
|
return pidlOut;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::Delete()
|
|
|
|
Deletes a PIDL
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CPidlMgr::Delete(LPITEMIDLIST pidl)
|
|
{
|
|
m_pMalloc->Free(pidl);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetNextItem()
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::GetNextItem(LPCITEMIDLIST pidl)
|
|
{
|
|
if(pidl)
|
|
{
|
|
return (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetSize()
|
|
|
|
**************************************************************************/
|
|
|
|
UINT CPidlMgr::GetSize(LPCITEMIDLIST pidl)
|
|
{
|
|
UINT cbTotal = 0;
|
|
LPITEMIDLIST pidlTemp = (LPITEMIDLIST)pidl;
|
|
|
|
if(pidlTemp)
|
|
{
|
|
while(pidlTemp->mkid.cb)
|
|
{
|
|
cbTotal += pidlTemp->mkid.cb;
|
|
pidlTemp = GetNextItem(pidlTemp);
|
|
}
|
|
|
|
//add the size of the NULL terminating ITEMIDLIST
|
|
cbTotal += sizeof(ITEMIDLIST);
|
|
}
|
|
|
|
return cbTotal;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetLastItem()
|
|
|
|
Gets the last item in the list
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::GetLastItem(LPCITEMIDLIST pidl)
|
|
{
|
|
LPITEMIDLIST pidlLast = NULL;
|
|
|
|
//get the PIDL of the last item in the list
|
|
while(pidl && pidl->mkid.cb)
|
|
{
|
|
pidlLast = (LPITEMIDLIST)pidl;
|
|
pidl = GetNextItem(pidl);
|
|
}
|
|
|
|
return pidlLast;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::Copy()
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::Copy(LPCITEMIDLIST pidlSource)
|
|
{
|
|
LPITEMIDLIST pidlTarget = NULL;
|
|
UINT cbSource = 0;
|
|
|
|
if(NULL == pidlSource)
|
|
return NULL;
|
|
|
|
// Allocate the new pidl
|
|
cbSource = GetSize(pidlSource);
|
|
pidlTarget = (LPITEMIDLIST)m_pMalloc->Alloc(cbSource);
|
|
if(!pidlTarget)
|
|
return NULL;
|
|
|
|
// Copy the source to the target
|
|
CopyMemory(pidlTarget, pidlSource, cbSource);
|
|
|
|
return pidlTarget;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::CopySingleItem()
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::CopySingleItem(LPCITEMIDLIST pidlSource)
|
|
{
|
|
LPITEMIDLIST pidlTarget = NULL;
|
|
UINT cbSource = 0;
|
|
|
|
if(NULL == pidlSource)
|
|
return NULL;
|
|
|
|
// Allocate the new pidl
|
|
cbSource = pidlSource->mkid.cb;
|
|
pidlTarget = (LPITEMIDLIST)m_pMalloc->Alloc(cbSource + sizeof(ITEMIDLIST));
|
|
if(!pidlTarget)
|
|
return NULL;
|
|
|
|
// Copy the source to the target
|
|
ZeroMemory(pidlTarget, cbSource + sizeof(ITEMIDLIST));
|
|
CopyMemory(pidlTarget, pidlSource, cbSource);
|
|
|
|
return pidlTarget;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetDataPointer()
|
|
|
|
**************************************************************************/
|
|
|
|
inline LPPIDLDATA CPidlMgr::GetDataPointer(LPCITEMIDLIST pidl)
|
|
{
|
|
if(!pidl)
|
|
return NULL;
|
|
|
|
return (LPPIDLDATA)(pidl->mkid.abID);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::Concatenate()
|
|
|
|
Create a new PIDL by combining two existing PIDLs.
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::Concatenate(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
|
{
|
|
LPITEMIDLIST pidlNew;
|
|
UINT cb1 = 0,
|
|
cb2 = 0;
|
|
|
|
//are both of these NULL?
|
|
if(!pidl1 && !pidl2)
|
|
return NULL;
|
|
|
|
//if pidl1 is NULL, just return a copy of pidl2
|
|
if(!pidl1)
|
|
{
|
|
pidlNew = Copy(pidl2);
|
|
|
|
return pidlNew;
|
|
}
|
|
|
|
//if pidl2 is NULL, just return a copy of pidl1
|
|
if(!pidl2)
|
|
{
|
|
pidlNew = Copy(pidl1);
|
|
|
|
return pidlNew;
|
|
}
|
|
|
|
cb1 = GetSize(pidl1) - sizeof(ITEMIDLIST);
|
|
|
|
cb2 = GetSize(pidl2);
|
|
|
|
//create the new PIDL
|
|
pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(cb1 + cb2);
|
|
|
|
if(pidlNew)
|
|
{
|
|
//copy the first PIDL
|
|
CopyMemory(pidlNew, pidl1, cb1);
|
|
|
|
//copy the second PIDL
|
|
CopyMemory(((LPBYTE)pidlNew) + cb1, pidl2, cb2);
|
|
}
|
|
|
|
return pidlNew;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::CreateFolderPidl()
|
|
|
|
Create a new folder PIDL.
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::CreateFolderPidl(LPCTSTR pszName)
|
|
{
|
|
LPITEMIDLIST pidl = Create();
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
pData->fFolder = TRUE;
|
|
|
|
lstrcpyn(pData->szName, pszName, MAX_NAME);
|
|
|
|
pData->szData[0] = 0;
|
|
}
|
|
|
|
return pidl;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::CreateItemPidl()
|
|
|
|
Create a new item PIDL.
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::CreateItemPidl( LPCTSTR pszName,
|
|
LPCTSTR pszData)
|
|
{
|
|
LPITEMIDLIST pidl = Create();
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
pData->fFolder = FALSE;
|
|
|
|
lstrcpyn(pData->szName, pszName, MAX_NAME);
|
|
lstrcpyn(pData->szData, pszData, MAX_DATA);
|
|
}
|
|
|
|
return pidl;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::SetDataPidl()
|
|
|
|
Set a data in the PIDL.
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CPidlMgr::SetDataPidl(LPITEMIDLIST pidl, LPPIDLDATA pSourceData, PIDLDATATYPE pidldatatype)
|
|
{
|
|
if (!pidl)
|
|
pidl = Create();
|
|
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
if (pidldatatype & FOLDER)
|
|
pData->fFolder = pSourceData->fFolder;
|
|
if (pidldatatype & NAME)
|
|
lstrcpyn(pData->szName, pSourceData->szName, MAX_NAME);
|
|
if (pidldatatype & DATA)
|
|
lstrcpyn(pData->szData, pSourceData->szData, MAX_DATA);
|
|
if (pidldatatype & ICON)
|
|
pData->iIcon = pSourceData->iIcon;
|
|
if (pidldatatype & URL)
|
|
lstrcpyn(pData->szUrl, pSourceData->szUrl, MAX_DATA);
|
|
}
|
|
|
|
return pidl;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetName()
|
|
|
|
Gets the name for this item
|
|
|
|
**************************************************************************/
|
|
|
|
int CPidlMgr::GetName(LPCITEMIDLIST pidl, LPTSTR pszText, DWORD dwSize)
|
|
{
|
|
if(!IsBadWritePtr(pszText, dwSize))
|
|
{
|
|
*pszText = 0;
|
|
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
lstrcpyn(pszText, pData->szName, dwSize);
|
|
return lstrlen(pszText);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetRelativeName()
|
|
|
|
Gets the full name for this item
|
|
|
|
**************************************************************************/
|
|
|
|
int CPidlMgr::GetRelativeName(LPCITEMIDLIST pidl, LPTSTR pszText, DWORD dwSize)
|
|
{
|
|
if(!IsBadWritePtr(pszText, dwSize))
|
|
{
|
|
LPITEMIDLIST pidlTemp;
|
|
*pszText = 0;
|
|
|
|
//walk the list, getting the name for each item
|
|
pidlTemp = (LPITEMIDLIST)pidl;
|
|
while(pidlTemp && pidlTemp->mkid.cb)
|
|
{
|
|
LPTSTR pszCurrent = pszText + lstrlen(pszText);
|
|
dwSize -= GetName(pidlTemp, pszCurrent, dwSize);
|
|
pidlTemp = GetNextItem(pidlTemp);
|
|
|
|
//don't add a backslash to the last item
|
|
if(pidlTemp && pidlTemp->mkid.cb)
|
|
{
|
|
SmartAppendBackslash(pszCurrent);
|
|
}
|
|
}
|
|
return lstrlen(pszText);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetData()
|
|
|
|
Gets the data for this item
|
|
|
|
**************************************************************************/
|
|
|
|
int CPidlMgr::GetData(LPCITEMIDLIST pidl, LPTSTR pszText, DWORD dwSize)
|
|
{
|
|
if(!IsBadWritePtr(pszText, dwSize))
|
|
{
|
|
*pszText = 0;
|
|
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
lstrcpyn(pszText, pData->szData, dwSize);
|
|
return lstrlen(pszText);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::IsFolder()
|
|
|
|
Determines if the item is a folder
|
|
|
|
**************************************************************************/
|
|
|
|
BOOL CPidlMgr::IsFolder(LPCITEMIDLIST pidl)
|
|
{
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
return pData->fFolder;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::SetData()
|
|
|
|
**************************************************************************/
|
|
|
|
int CPidlMgr::SetData(LPCITEMIDLIST pidl, LPCTSTR pszData)
|
|
{
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
lstrcpyn(pData->szData, pszData, MAX_DATA);
|
|
|
|
return lstrlen(pData->szData);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetIcon()
|
|
|
|
Determines if the item is a folder
|
|
|
|
**************************************************************************/
|
|
|
|
int CPidlMgr::GetIcon(LPCITEMIDLIST pidl)
|
|
{
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
return pData->iIcon;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CPidlMgr::GetUrl()
|
|
|
|
Gets the data for this item
|
|
|
|
**************************************************************************/
|
|
|
|
int CPidlMgr::GetUrl(LPCITEMIDLIST pidl, LPTSTR pszText, DWORD dwSize)
|
|
{
|
|
if(!IsBadWritePtr(pszText, dwSize))
|
|
{
|
|
*pszText = 0;
|
|
|
|
LPPIDLDATA pData = GetDataPointer(pidl);
|
|
|
|
if(pData)
|
|
{
|
|
lstrcpyn(pszText, pData->szUrl, dwSize);
|
|
return lstrlen(pszText);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|