257 lines
6.3 KiB
C++
257 lines
6.3 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (C) Silicon Prairie Software, 1996
|
||
|
//
|
||
|
// File: pidl.cpp
|
||
|
//
|
||
|
// Contents: CIDList
|
||
|
//
|
||
|
// History: 9-26-95 Davepl Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
#include "shtl.h"
|
||
|
#include "cidl.h"
|
||
|
#include "shellapi.h"
|
||
|
|
||
|
|
||
|
//
|
||
|
// CombineWith - Adds another pidl with this one, puts the result at
|
||
|
// a new pidl ptr passed in
|
||
|
//
|
||
|
|
||
|
__DATL_INLINE HRESULT CIDList::CombineWith(const CIDList * pidlwith, CIDList ** ppidlto)
|
||
|
{
|
||
|
UINT cb1 = this->GetSize() - CB_IDLIST_TERMINATOR;
|
||
|
UINT cb2 = pidlwith->GetSize();
|
||
|
|
||
|
*ppidlto = (CIDList *) g_SHAlloc.Alloc(cb1 + cb2);
|
||
|
if (NULL == *ppidlto)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
CopyMemory(*ppidlto, this, cb1);
|
||
|
CopyMemory((((LPBYTE)*ppidlto) + cb1), pidlwith, cb2);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDList::IsParent
|
||
|
//
|
||
|
// Synopsis: Tests whether or not _this_ pidl is a parent of some
|
||
|
// other pidl
|
||
|
//
|
||
|
// Returns: BOOL - TRUE if we are a child of the other pidl
|
||
|
//
|
||
|
// History: 5-15-95 DavePl Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
__DATL_INLINE BOOL CIDList::IsParentOf(const CIDList * pidlother, BOOL fImmediate) const
|
||
|
{
|
||
|
ptrdiff_t cb;
|
||
|
|
||
|
if (NULL == pidlother)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
const CIDList * pidlthisT = this;
|
||
|
const CIDList * pidlotherT = pidlother;
|
||
|
|
||
|
//
|
||
|
// Walk to the end of _this_ pidl. If we run out of hops on the other
|
||
|
// pidl, its shorter than us so we can't be its parent
|
||
|
|
||
|
while(FALSE == pidlthisT->IsEmpty())
|
||
|
{
|
||
|
if (pidlotherT->IsEmpty())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
pidlthisT = pidlthisT->Next();
|
||
|
pidlotherT = pidlotherT->Next();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If caller wants to know if we're the _immediate_ parent, we should
|
||
|
// be empty at this point and the other pidl should have exactly
|
||
|
// one entry left
|
||
|
//
|
||
|
|
||
|
if (fImmediate)
|
||
|
{
|
||
|
if (pidlotherT->IsEmpty() || FALSE == pidlotherT->Next()->IsEmpty())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create a new IDList from a portion of pidl2, which contains the
|
||
|
// same number of IDs as pidl1.
|
||
|
//
|
||
|
|
||
|
cb = pidlotherT - pidlother;
|
||
|
|
||
|
//
|
||
|
// BUGBUG It's probably not valid to binary compare the pidls up to this point,
|
||
|
// but since the shell doesn't expose a better mechanism for us to use...
|
||
|
//
|
||
|
|
||
|
if (0 == memcmp(pidlother, this, cb))
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDList::FindChild
|
||
|
//
|
||
|
// Synopsis: Given _this_ as a parent pidl, and some pidlchild which is
|
||
|
// a child of it, returns the portion of the child not found
|
||
|
// in the parent.
|
||
|
//
|
||
|
// ie: this == c:\foo\bar
|
||
|
// child == c:\foo\bar\etc
|
||
|
// return == \etc
|
||
|
//
|
||
|
// Returns: Uncommon child portion. NULL if child is not really our child.
|
||
|
//
|
||
|
// History: 5-15-95 DavePl Created
|
||
|
//
|
||
|
// Notes: Does _not_ allocate a new pidl, just returns a ptr into the
|
||
|
// child.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
__DATL_INLINE const CIDList * CIDList::FindChild(const CIDList * pidlchild) const
|
||
|
{
|
||
|
const CIDList * pidlparent = this;
|
||
|
|
||
|
if (IsParentOf(pidlchild, FALSE))
|
||
|
{
|
||
|
while (FALSE == pidlparent->IsEmpty())
|
||
|
{
|
||
|
pidlchild = pidlchild->Next();
|
||
|
pidlparent = pidlparent->Next();
|
||
|
}
|
||
|
return pidlchild;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// CIDList::GetIShellFolder
|
||
|
//
|
||
|
// Returns the IShellFolder implementation for this idlist
|
||
|
|
||
|
__DATL_INLINE HRESULT CIDList::GetIShellFolder(IShellFolder ** ppFolder)
|
||
|
{
|
||
|
IShellFolder * pDesktop = NULL;
|
||
|
HRESULT hr = SHGetDesktopFolder(&pDesktop);
|
||
|
if (SUCCEEDED(hr))
|
||
|
hr = pDesktop->BindToObject(this, NULL, IID_IShellFolder, (void **)ppFolder);
|
||
|
|
||
|
if (pDesktop)
|
||
|
pDesktop->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// CIDList::AppendPath
|
||
|
//
|
||
|
// Given an idlist, which must be a folder, adds a text path to it
|
||
|
|
||
|
__DATL_INLINE HRESULT CIDList::AppendPath(LPCTSTR pszPath, CIDList ** ppidlResult)
|
||
|
{
|
||
|
IShellFolder * pFolder = NULL;
|
||
|
HRESULT hr = GetIShellFolder(&pFolder);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
CIDList * pidlNew = NULL;
|
||
|
|
||
|
#if defined(UNICODE) || defined(_UNICODE)
|
||
|
LPCWSTR pwszPath = pszPath;
|
||
|
#else
|
||
|
WCHAR pwszPath[MAX_PATH];
|
||
|
VERIFY( MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszPath, -1, pwszPath, MAX_PATH) );
|
||
|
#endif
|
||
|
|
||
|
ULONG chEaten;
|
||
|
hr = pFolder->ParseDisplayName(NULL, NULL, const_cast<LPWSTR>(pwszPath), &chEaten, (LPITEMIDLIST *)&pidlNew, NULL);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
CIDList * pidlResult = NULL;
|
||
|
hr = CombineWith(pidlNew, ppidlResult);
|
||
|
}
|
||
|
g_SHAlloc.Free(pidlNew);
|
||
|
}
|
||
|
if (pFolder)
|
||
|
pFolder->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// StrRetToTString - Gets a TString from a strret structure
|
||
|
//
|
||
|
// PrintStrRet - prints the contents of a STRRET structure.
|
||
|
// pidl - PIDL containing the display name if STRRET_OFFSET
|
||
|
// lpStr - address of the STRRET structure
|
||
|
//
|
||
|
|
||
|
/*
|
||
|
__DATL_INLINE void StrRetToCString(CIDList * pCidl, LPSTRRET lpStr, tstring &str)
|
||
|
{
|
||
|
LPSTR lpsz;
|
||
|
int cch;
|
||
|
|
||
|
switch (lpStr->uType)
|
||
|
{
|
||
|
|
||
|
case STRRET_WSTR:
|
||
|
|
||
|
cch = WideCharToMultiByte(CP_ACP, 0,
|
||
|
lpStr->pOleStr, -1, NULL, 0, NULL, NULL);
|
||
|
|
||
|
lpsz = new char[cch];
|
||
|
if (lpsz != NULL) {
|
||
|
WideCharToMultiByte(CP_ACP, 0,
|
||
|
lpStr->pOleStr, -1, lpsz, cch, NULL, NULL);
|
||
|
str = lpsz;
|
||
|
delete [] lpsz;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case STRRET_OFFSET:
|
||
|
str = (((char *) pCidl) + lpStr->uOffset);
|
||
|
break;
|
||
|
|
||
|
case STRRET_CSTR:
|
||
|
str = lpStr->cStr;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
__DATL_INLINE tstring CIDList::GetPath() const
|
||
|
{
|
||
|
tstring strPath;
|
||
|
|
||
|
if (FALSE == SHGetPathFromIDList(this, strPath.GetBuffer(MAX_PATH)))
|
||
|
throw new dexception(E_OUTOFMEMORY);
|
||
|
|
||
|
strPath.ReleaseBuffer(-1);
|
||
|
|
||
|
return strPath;
|
||
|
}
|