|
|
//+-------------------------------------------------------------------------
//
// 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; }
|