1527 lines
37 KiB
C++
1527 lines
37 KiB
C++
|
#include "priv.h"
|
||
|
#include "sccls.h"
|
||
|
#include "iface.h"
|
||
|
#include "augisf.h"
|
||
|
#include "menuisf.h"
|
||
|
|
||
|
//=================================================================
|
||
|
// Implementation of an IShellFolder that wraps a collection of
|
||
|
// other IShellFolders. We call this an augmented IShellFolder
|
||
|
// object.
|
||
|
//
|
||
|
//=================================================================
|
||
|
|
||
|
// The CAugmentedISF wraps all the pidls so it can identify which pidl
|
||
|
// belongs to which IShellFolder object.
|
||
|
|
||
|
typedef struct tagIDWRAP
|
||
|
{
|
||
|
// Real pidl goes on the end
|
||
|
|
||
|
UINT nID; // Refers to a specific IShellFolder object
|
||
|
UINT cbOriginal; // the original size of the pidl. we need this because we dword align the pidl before wrapping it
|
||
|
} IDWRAP, * PIDWRAP;
|
||
|
|
||
|
#define IDWrap_GetWrap(pidl) ((PIDWRAP)(((LPBYTE)pidl) + (pidl)->mkid.cb - SIZEOF(IDWRAP)))
|
||
|
#define IDWrap_GetID(pidl) (IDWrap_GetWrap(pidl)->nID)
|
||
|
#define IDWrap_GetOriginalSize(pidl) (IDWrap_GetWrap(pidl)->cbOriginal)
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
The CAugmentedISF object holds an array of CISFElems, each of which
|
||
|
refers to an IShellFolder which will be enumerated.
|
||
|
*/
|
||
|
class CISFElem
|
||
|
{
|
||
|
public:
|
||
|
CISFElem * Clone(void);
|
||
|
HRESULT AcquireEnumerator(DWORD dwFlags);
|
||
|
IShellFolder * GetPSF() { return _psf; };
|
||
|
IEnumIDList * GetEnumerator() { return _pei; };
|
||
|
void GetNameSpaceID(GUID * rguid);
|
||
|
HRESULT SetPidl(LPCITEMIDLIST pidl);
|
||
|
LPCITEMIDLIST GetPidl() { return _pidl; };
|
||
|
DWORD GetFlags() { return _dwFlags; };
|
||
|
void SetRegister(UINT uReg) { _uRegister = uReg; };
|
||
|
UINT GetRegister() { return _uRegister; };
|
||
|
|
||
|
CISFElem(const GUID * pguid, IShellFolder * psf, DWORD dwFlags);
|
||
|
~CISFElem();
|
||
|
|
||
|
protected:
|
||
|
|
||
|
GUID _guid; // Unique ID
|
||
|
IShellFolder * _psf;
|
||
|
IEnumIDList * _pei; // Used by CAugSIFEnum only
|
||
|
LPITEMIDLIST _pidl;
|
||
|
DWORD _dwFlags;
|
||
|
UINT _uRegister;
|
||
|
|
||
|
friend BOOL IsValidPCISFElem(CISFElem * pel);
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// CAugmentedISF enumerator
|
||
|
//
|
||
|
class CAugISFEnum : public IEnumIDList
|
||
|
{
|
||
|
public:
|
||
|
// *** IUnknown methods ***
|
||
|
STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppvObj);
|
||
|
STDMETHOD_(ULONG,AddRef) () ;
|
||
|
STDMETHOD_(ULONG,Release) ();
|
||
|
|
||
|
// *** IEnumIDList methods ***
|
||
|
STDMETHOD(Next) (ULONG celt,
|
||
|
LPITEMIDLIST *rgelt,
|
||
|
ULONG *pceltFetched);
|
||
|
STDMETHOD(Skip) (ULONG celt);
|
||
|
STDMETHOD(Reset) ();
|
||
|
STDMETHOD(Clone) (IEnumIDList **ppenum);
|
||
|
|
||
|
// Other methods
|
||
|
HRESULT Init(HDPA hdpaISF, DWORD dwEnumFlags);
|
||
|
|
||
|
CAugISFEnum();
|
||
|
~CAugISFEnum();
|
||
|
|
||
|
protected:
|
||
|
IEnumIDList * _GetObjectEnumerator(int nID);
|
||
|
|
||
|
UINT _cRef;
|
||
|
int _iCurISF; // current item in _hdpaISF
|
||
|
HDPA _hdpaISF;
|
||
|
};
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Pidl wrapping routine
|
||
|
*/
|
||
|
LPITEMIDLIST AugISF_WrapPidl( LPCITEMIDLIST pidl, int nID )
|
||
|
{
|
||
|
LPITEMIDLIST pidlRet = NULL;
|
||
|
|
||
|
// get the size of the pidl
|
||
|
// round up to dword align.
|
||
|
UINT cbPidlSize = (pidl->mkid.cb + 3) & ~3;
|
||
|
|
||
|
ASSERT(cbPidlSize >= pidl->mkid.cb);
|
||
|
UINT cbSize = SIZEOF(IDWRAP) + cbPidlSize + SIZEOF(DWORD); // pidl plus terminator
|
||
|
LPBYTE p = (LPBYTE)SHAlloc(cbSize);
|
||
|
if (p)
|
||
|
{
|
||
|
ZeroMemory(p, cbSize);
|
||
|
memcpy(p, pidl, pidl->mkid.cb);
|
||
|
|
||
|
IDWRAP* pidw = (IDWRAP*) (p + cbPidlSize);
|
||
|
pidw->nID = nID;
|
||
|
pidw->cbOriginal = pidl->mkid.cb;
|
||
|
|
||
|
// now make the cb be the whole pidl (not including the final null)
|
||
|
pidlRet = (LPITEMIDLIST)p;
|
||
|
pidlRet->mkid.cb = (USHORT) (cbPidlSize + SIZEOF(IDWRAP));
|
||
|
}
|
||
|
return pidlRet;
|
||
|
}
|
||
|
|
||
|
// GetIDListWrapCount and GetNameSpaceCount are not used anywhere
|
||
|
#if 0
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IAugmentedShellFolder2::GetIDListWrapCount
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::GetNameSpaceCount( OUT LONG* pcNamespaces )
|
||
|
{
|
||
|
if( NULL == pcNamespaces )
|
||
|
return E_INVALIDARG ;
|
||
|
|
||
|
*pcNamespaces = (NULL != _hdpa) ? DPA_GetPtrCount( _hdpa ) : 0 ;
|
||
|
return S_OK ;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IAugmentedShellFolder2::GetIDListWrapCount
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::GetIDListWrapCount(
|
||
|
LPCITEMIDLIST pidlWrap,
|
||
|
OUT LONG * pcPidls )
|
||
|
{
|
||
|
if( NULL == pidlWrap || NULL == pcPidls )
|
||
|
return E_INVALIDARG ;
|
||
|
|
||
|
PIDWRAP pWrap = IDWrap_GetWrap(pidlWrap) ;
|
||
|
*pcPidls = 0 ;
|
||
|
|
||
|
if( NULL != _hdpa &&
|
||
|
DPA_GetPtrCount( _hdpa ) > (int)pWrap->nID &&
|
||
|
pWrap->cbOriginal < pidlWrap->mkid.cb + sizeof(IDWRAP) )
|
||
|
*pcPidls = 1 ;
|
||
|
|
||
|
return S_OK ;
|
||
|
}
|
||
|
#endif
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IAugmentedShellFolder2::UnWrapIDList
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::UnWrapIDList(
|
||
|
LPCITEMIDLIST pidl,
|
||
|
LONG cPidls,
|
||
|
IShellFolder ** ppsf,
|
||
|
LPITEMIDLIST * ppidlFolder,
|
||
|
LPITEMIDLIST * ppidl,
|
||
|
LONG * pcFetched )
|
||
|
{
|
||
|
HRESULT hres = E_INVALIDARG;
|
||
|
|
||
|
ASSERT(IS_VALID_PIDL(pidl));
|
||
|
|
||
|
if( pcFetched )
|
||
|
*pcFetched = 0 ;
|
||
|
|
||
|
if (pidl)
|
||
|
{
|
||
|
UINT nId = IDWrap_GetID(pidl);
|
||
|
CISFElem * pel = (CISFElem *)DPA_GetPtr(_hdpa, nId);
|
||
|
|
||
|
if (pel)
|
||
|
{
|
||
|
LPITEMIDLIST pidlNew = ILClone(GetNativePidl(pidl, nId));
|
||
|
LPITEMIDLIST pidlFolderNew = ILClone(pel->GetPidl());
|
||
|
|
||
|
if (pidlNew && pidlFolderNew)
|
||
|
{
|
||
|
if ( ppsf )
|
||
|
{
|
||
|
*ppsf = pel->GetPSF();
|
||
|
(*ppsf)->AddRef();
|
||
|
}
|
||
|
|
||
|
*ppidl = pidlNew;
|
||
|
*ppidlFolder = pidlFolderNew;
|
||
|
|
||
|
if( pcFetched )
|
||
|
*pcFetched = 1 ;
|
||
|
|
||
|
hres = (cPidls == 1) ? S_OK : S_FALSE ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ILFree(pidlNew);
|
||
|
ILFree(pidlFolderNew);
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hres = E_FAIL;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: CAugmentedISF::TranslatePidl
|
||
|
*/
|
||
|
LPITEMIDLIST CAugmentedISF::TranslatePidl( LPCITEMIDLIST pidlNS, LPCITEMIDLIST pidl, LPARAM nID )
|
||
|
{
|
||
|
LPITEMIDLIST pidlRet = NULL;
|
||
|
|
||
|
// Is this not empty and an immediate child?
|
||
|
if (ILIsParent(pidlNS, pidl, TRUE))
|
||
|
{
|
||
|
LPCITEMIDLIST pidlChild;
|
||
|
LPITEMIDLIST pidlNew;
|
||
|
TCHAR szFullName[MAX_PATH];
|
||
|
LPITEMIDLIST pidlFull = NULL;
|
||
|
|
||
|
// HACKHACK (lamadio): You cannot use SHGetRealIDL for augisf encapsulated
|
||
|
// IShellFolders. This routine QIs for INeedRealShellFolder, which IAugISF
|
||
|
// doesnot forward. The fstree code does not handle aggregation, so this
|
||
|
// cannot be forwarded anyway. This code can be cleaned up when we rewrite
|
||
|
// the fstree stuff... Sep.4.1997
|
||
|
|
||
|
if (SUCCEEDED(SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szFullName, SIZECHARS(szFullName), NULL))
|
||
|
&& (pidlFull = ILCreateFromPath(szFullName)) != NULL)
|
||
|
{
|
||
|
pidlChild = ILFindLastID(pidlFull);
|
||
|
pidlNew = ILClone(pidlFull);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pidlChild = ILFindLastID(pidl);
|
||
|
pidlNew = ILClone(pidl);
|
||
|
}
|
||
|
|
||
|
// Yes; create a new full pidl where the last element is wrapped
|
||
|
|
||
|
if (pidlNew)
|
||
|
{
|
||
|
ILRemoveLastID(pidlNew);
|
||
|
|
||
|
LPITEMIDLIST pidlWrap = AugISF_WrapPidl( pidlChild, (int)nID );
|
||
|
if (pidlWrap)
|
||
|
{
|
||
|
pidlRet = ILCombine(pidlNew, pidlWrap);
|
||
|
ILFree(pidlWrap);
|
||
|
}
|
||
|
ILFree(pidlNew);
|
||
|
}
|
||
|
|
||
|
ILFree(pidlFull); //Checks for a NULL pidl
|
||
|
}
|
||
|
else
|
||
|
pidlRet = (LPITEMIDLIST)pidl;
|
||
|
|
||
|
return pidlRet;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: CAugmentedISF::GetNativePidl
|
||
|
Clones and returns a copy of the native ('source') pidl
|
||
|
contained in the specified wrap.
|
||
|
*/
|
||
|
LPITEMIDLIST CAugmentedISF::GetNativePidl(LPCITEMIDLIST pidl, LPARAM lParam /*int nID*/ )
|
||
|
{
|
||
|
ASSERT(IS_VALID_PIDL(pidl));
|
||
|
UNREFERENCED_PARAMETER( lParam ) ; // only one source ID in the wrap!
|
||
|
|
||
|
LPITEMIDLIST pidlNew = ILClone(pidl);
|
||
|
|
||
|
if (pidlNew)
|
||
|
{
|
||
|
// Take off our trailing wrap signature
|
||
|
pidlNew->mkid.cb = IDWrap_GetOriginalSize(pidl);
|
||
|
|
||
|
ASSERT(sizeof(IDWRAP) >= sizeof(USHORT));
|
||
|
|
||
|
USHORT * pu = (USHORT *)_ILNext(pidlNew);
|
||
|
*pu = 0;
|
||
|
}
|
||
|
return pidlNew;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
CISFElem::CISFElem(const GUID * pguid, IShellFolder * psf, DWORD dwFlags) : _dwFlags(dwFlags)
|
||
|
{
|
||
|
ASSERT(IS_VALID_CODE_PTR(psf, IShellFolder));
|
||
|
ASSERT(NULL == pguid || IS_VALID_READ_PTR(pguid, GUID));
|
||
|
|
||
|
if (pguid)
|
||
|
CopyMemory(&_guid, pguid, sizeof(_guid));
|
||
|
|
||
|
_psf = psf;
|
||
|
_psf->AddRef();
|
||
|
}
|
||
|
|
||
|
CISFElem::~CISFElem()
|
||
|
{
|
||
|
ASSERT(IS_VALID_CODE_PTR(_psf, IShellFolder));
|
||
|
|
||
|
_psf->Release();
|
||
|
|
||
|
if (_pei)
|
||
|
_pei->Release();
|
||
|
|
||
|
Pidl_Set(&_pidl, NULL);
|
||
|
}
|
||
|
|
||
|
CISFElem * CISFElem::Clone(void)
|
||
|
{
|
||
|
CISFElem * pelem = new CISFElem(&_guid, _psf, _dwFlags);
|
||
|
|
||
|
if (pelem)
|
||
|
{
|
||
|
// If this fails, we're punting and going ahead anyway
|
||
|
pelem->SetPidl(_pidl);
|
||
|
}
|
||
|
|
||
|
return pelem;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CISFElem::GetNameSpaceID(GUID * pguid)
|
||
|
{
|
||
|
ASSERT(IS_VALID_WRITE_PTR(pguid, GUID));
|
||
|
CopyMemory(pguid, &_guid, sizeof(_guid));
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CISFElem::SetPidl(LPCITEMIDLIST pidl)
|
||
|
{
|
||
|
HRESULT hres = S_OK;
|
||
|
|
||
|
Pidl_Set(&_pidl, pidl);
|
||
|
|
||
|
if (pidl && NULL == _pidl)
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Gets an enumerator for the IShellFolder and caches it.
|
||
|
|
||
|
*/
|
||
|
HRESULT CISFElem::AcquireEnumerator(DWORD dwFlags)
|
||
|
{
|
||
|
return IShellFolder_EnumObjects(_psf, NULL, dwFlags, &_pei);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// CAugmentedISF object
|
||
|
//
|
||
|
|
||
|
|
||
|
#undef SUPERCLASS
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
|
||
|
BOOL IsValidPCISFElem(CISFElem * pel)
|
||
|
{
|
||
|
return (IS_VALID_WRITE_PTR(pel, CISFElem) &&
|
||
|
IS_VALID_CODE_PTR(pel->_psf, IShellFolder) &&
|
||
|
(NULL == pel->_pidl || IS_VALID_PIDL(pel->_pidl)));
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// Constructor
|
||
|
CAugmentedISF::CAugmentedISF() :
|
||
|
_cRef(1)
|
||
|
{
|
||
|
DllAddRef();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Callback to destroy each element
|
||
|
|
||
|
*/
|
||
|
int CISFElem_DestroyCB(LPVOID pv, LPVOID pvData)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)pv;
|
||
|
|
||
|
ASSERT(NULL == pel || IS_VALID_STRUCT_PTR(pel, CISFElem));
|
||
|
|
||
|
if (pel)
|
||
|
delete pel;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Callback to set the owner of each element
|
||
|
|
||
|
*/
|
||
|
int CISFElem_SetOwnerCB(LPVOID pv, LPVOID pvData)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)pv;
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(pel, CISFElem));
|
||
|
|
||
|
IShellFolder * psf = pel->GetPSF();
|
||
|
if (psf)
|
||
|
{
|
||
|
IUnknown_SetOwner(psf, (IUnknown *)pvData);
|
||
|
// don't need to release psf
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
HRESULT hres;
|
||
|
HWND hwnd;
|
||
|
const IID * piid;
|
||
|
void ** ppvObj;
|
||
|
} CVODATA;
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Callback to call CreateViewObject
|
||
|
|
||
|
*/
|
||
|
int CISFElem_CreateViewObjectCB(LPVOID pv, LPVOID pvData)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)pv;
|
||
|
CVODATA * pdata = (CVODATA *)pvData;
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(pel, CISFElem));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(pdata, CVODATA));
|
||
|
|
||
|
IShellFolder * psf = pel->GetPSF();
|
||
|
if (psf)
|
||
|
{
|
||
|
pdata->hres = psf->CreateViewObject(pdata->hwnd, *(pdata->piid), pdata->ppvObj);
|
||
|
if (SUCCEEDED(pdata->hres))
|
||
|
return FALSE; // stop on first success
|
||
|
|
||
|
// don't need to release psf
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Destructor
|
||
|
CAugmentedISF::~CAugmentedISF()
|
||
|
{
|
||
|
SetOwner(NULL);
|
||
|
|
||
|
DPA_DestroyCallback(_hdpa, CISFElem_DestroyCB, NULL);
|
||
|
_hdpa = NULL;
|
||
|
|
||
|
DllRelease();
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CAugmentedISF::AddRef()
|
||
|
{
|
||
|
_cRef++;
|
||
|
return _cRef;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CAugmentedISF::Release()
|
||
|
{
|
||
|
ASSERT(_cRef > 0);
|
||
|
_cRef--;
|
||
|
|
||
|
if (_cRef > 0)
|
||
|
return _cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAugmentedISF::QueryInterface(REFIID riid, void **ppvObj)
|
||
|
{
|
||
|
static const QITAB qit[] = {
|
||
|
QITABENT(CAugmentedISF, IShellFolder),
|
||
|
QITABENT(CAugmentedISF, IAugmentedShellFolder),
|
||
|
QITABENT(CAugmentedISF, IAugmentedShellFolder2),
|
||
|
QITABENT(CAugmentedISF, IShellService),
|
||
|
QITABENT(CAugmentedISF, ITranslateShellChangeNotify),
|
||
|
{ 0 },
|
||
|
};
|
||
|
return QISearch(this, qit, riid, ppvObj);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellService::SetOwner method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::SetOwner(IUnknown* punk)
|
||
|
{
|
||
|
HRESULT hres = S_OK;
|
||
|
|
||
|
ASSERT(NULL == punk || IS_VALID_CODE_PTR(punk, IUnknown));
|
||
|
|
||
|
if (_hdpa && _punkOwner)
|
||
|
DPA_EnumCallback(_hdpa, CISFElem_SetOwnerCB, NULL);
|
||
|
|
||
|
ATOMICRELEASE(_punkOwner);
|
||
|
|
||
|
if (punk)
|
||
|
{
|
||
|
hres = punk->QueryInterface(IID_IUnknown, (LPVOID *)&_punkOwner);
|
||
|
|
||
|
if (_hdpa)
|
||
|
DPA_EnumCallback(_hdpa, CISFElem_SetOwnerCB, (void *)_punkOwner);
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::EnumObjects method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::EnumObjects(HWND hwndOwner, DWORD grfFlags, LPENUMIDLIST * ppenumIDList)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
*ppenumIDList = new CAugISFEnum();
|
||
|
|
||
|
if (*ppenumIDList)
|
||
|
{
|
||
|
hres = ((CAugISFEnum *)(*ppenumIDList))->Init(_hdpa, grfFlags);
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
{
|
||
|
delete *ppenumIDList;
|
||
|
*ppenumIDList = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::BindToObject method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved,
|
||
|
REFIID riid, LPVOID * ppvOut)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
ASSERT(IS_VALID_PIDL(pidl));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(ppvOut, LPVOID));
|
||
|
|
||
|
*ppvOut = NULL;
|
||
|
|
||
|
UINT id = IDWrap_GetID(pidl);
|
||
|
IShellFolder * psf = _GetObjectPSF(id);
|
||
|
|
||
|
if (psf)
|
||
|
{
|
||
|
LPITEMIDLIST pidlReal = GetNativePidl(pidl, id);
|
||
|
|
||
|
if (pidlReal)
|
||
|
{
|
||
|
hres = psf->BindToObject(pidlReal, pbcReserved, riid, ppvOut);
|
||
|
ILFree(pidlReal);
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
psf->Release();
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::BindToStorage method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved,
|
||
|
REFIID riid, LPVOID * ppvObj)
|
||
|
{
|
||
|
TraceMsg(TF_WARNING, "Called unimplemented CAugmentedISF::BindToStorage");
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::CompareIDs method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
||
|
{
|
||
|
HRESULT hres = 0;
|
||
|
int nID1 = IDWrap_GetID(pidl1);
|
||
|
int nID2 = IDWrap_GetID(pidl2);
|
||
|
|
||
|
if (nID1 == nID2)
|
||
|
{
|
||
|
IShellFolder * psf = _GetObjectPSF(nID1);
|
||
|
if (psf)
|
||
|
{
|
||
|
LPITEMIDLIST pidlReal1 = GetNativePidl(pidl1, nID1);
|
||
|
|
||
|
if (pidlReal1)
|
||
|
{
|
||
|
LPITEMIDLIST pidlReal2 = GetNativePidl(pidl2, nID2);
|
||
|
if (pidlReal2)
|
||
|
{
|
||
|
hres = psf->CompareIDs(lParam, pidlReal1, pidlReal2);
|
||
|
ILFree(pidlReal2);
|
||
|
}
|
||
|
ILFree(pidlReal1);
|
||
|
}
|
||
|
psf->Release();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//In this situation, we want to see if one of these items wants to be sorted
|
||
|
// below the other.
|
||
|
CISFElem * pel1 = (CISFElem *)DPA_GetPtr(_hdpa, nID1);
|
||
|
CISFElem * pel2 = (CISFElem *)DPA_GetPtr(_hdpa, nID2);
|
||
|
DWORD dwel1 = 0;
|
||
|
DWORD dwel2 = 0;
|
||
|
|
||
|
if (pel1)
|
||
|
dwel1 = pel1->GetFlags();
|
||
|
|
||
|
if (pel2)
|
||
|
dwel2 = pel2->GetFlags();
|
||
|
|
||
|
// if both want their items sorted below the other, punt and do neither.
|
||
|
if ((dwel1 & ASFF_SORTDOWN) ^ (dwel2 & ASFF_SORTDOWN))
|
||
|
hres = ResultFromShort((dwel1 & ASFF_SORTDOWN)? 1 : -1);
|
||
|
else
|
||
|
hres = (nID1 - nID2);
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::CreateViewObject method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::CreateViewObject (HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
CVODATA cvodata;
|
||
|
|
||
|
cvodata.hres = E_FAIL;
|
||
|
cvodata.hwnd = hwndOwner;
|
||
|
cvodata.piid = &riid;
|
||
|
cvodata.ppvObj = ppvOut;
|
||
|
|
||
|
// Whoever responds first wins
|
||
|
DPA_EnumCallback(_hdpa, CISFElem_CreateViewObjectCB, (void *)&cvodata);
|
||
|
|
||
|
hres = cvodata.hres;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::GetAttributesOf method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl,
|
||
|
ULONG * pfInOut)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
ASSERT(IS_VALID_READ_PTR(apidl, LPCITEMIDLIST));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(pfInOut, ULONG));
|
||
|
|
||
|
ULONG fInOut = *pfInOut;
|
||
|
*pfInOut &= 0;
|
||
|
|
||
|
// We only handle one pidl
|
||
|
if (1 == cidl && apidl)
|
||
|
{
|
||
|
UINT id = IDWrap_GetID(*apidl);
|
||
|
IShellFolder * psf = _GetObjectPSF(id);
|
||
|
|
||
|
if (psf)
|
||
|
{
|
||
|
LPITEMIDLIST pidlReal = GetNativePidl(*apidl, id);
|
||
|
|
||
|
if (pidlReal)
|
||
|
{
|
||
|
hres = psf->GetAttributesOf(1, (LPCITEMIDLIST *)&pidlReal, &fInOut);
|
||
|
*pfInOut = fInOut;
|
||
|
ILFree(pidlReal);
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
psf->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::GetUIObjectOf method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl,
|
||
|
REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
ASSERT(IS_VALID_READ_PTR(apidl, LPCITEMIDLIST));
|
||
|
|
||
|
*ppvOut = NULL;
|
||
|
|
||
|
// We only handle one pidl
|
||
|
if (1 == cidl && apidl)
|
||
|
{
|
||
|
UINT id = IDWrap_GetID(*apidl);
|
||
|
IShellFolder * psf = _GetObjectPSF(id);
|
||
|
|
||
|
if (psf)
|
||
|
{
|
||
|
LPITEMIDLIST pidlReal = GetNativePidl(*apidl, id);
|
||
|
|
||
|
if (pidlReal)
|
||
|
{
|
||
|
hres = psf->GetUIObjectOf(hwndOwner, 1, (LPCITEMIDLIST *)&pidlReal, riid, prgfInOut, ppvOut);
|
||
|
ILFree(pidlReal);
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
psf->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::GetDisplayNameOf method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags,
|
||
|
LPSTRRET pstrret)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
ASSERT(NULL == pidl || IS_VALID_PIDL(pidl));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(pstrret, STRRET));
|
||
|
|
||
|
if (pidl)
|
||
|
{
|
||
|
UINT id = IDWrap_GetID(pidl);
|
||
|
IShellFolder * psf = _GetObjectPSF(id);
|
||
|
|
||
|
if (psf)
|
||
|
{
|
||
|
LPITEMIDLIST pidlReal = GetNativePidl(pidl, id);
|
||
|
|
||
|
if (pidlReal)
|
||
|
{
|
||
|
hres = psf->GetDisplayNameOf(pidlReal, uFlags, pstrret);
|
||
|
ILFree(pidlReal);
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
psf->Release();
|
||
|
}
|
||
|
else
|
||
|
hres = E_FAIL;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::SetNameOf method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,
|
||
|
LPCOLESTR lpszName, DWORD uFlags,
|
||
|
LPITEMIDLIST * ppidlOut)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
ASSERT(NULL == pidl || IS_VALID_PIDL(pidl));
|
||
|
if (pidl)
|
||
|
{
|
||
|
UINT id = IDWrap_GetID(pidl);
|
||
|
IShellFolder * psf = _GetObjectPSF(id);
|
||
|
|
||
|
if (psf)
|
||
|
{
|
||
|
LPITEMIDLIST pidlReal = GetNativePidl(pidl, id);
|
||
|
|
||
|
if (pidlReal)
|
||
|
{
|
||
|
LPITEMIDLIST pidlOut = NULL;
|
||
|
hres = psf->SetNameOf(hwndOwner, pidlReal,
|
||
|
lpszName, uFlags,
|
||
|
&pidlOut);
|
||
|
|
||
|
// Do they want a pidl back?
|
||
|
if (SUCCEEDED(hres) && ppidlOut)
|
||
|
{
|
||
|
*ppidlOut = AugISF_WrapPidl( pidlOut, id );
|
||
|
|
||
|
if (!*ppidlOut)
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
ILFree(pidlOut);
|
||
|
ILFree(pidlReal);
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
psf->Release();
|
||
|
}
|
||
|
else
|
||
|
hres = E_FAIL;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IShellFolder::ParseDisplayName method
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::ParseDisplayName(HWND hwndOwner,
|
||
|
LPBC pbcReserved, LPOLESTR lpszDisplayName,
|
||
|
ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG *pdwAttributes)
|
||
|
{
|
||
|
TraceMsg(TF_WARNING, "Called unimplemented CAugmentedISF::ParseDisplayNameOf");
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IAugmentedShellFolder::AddNameSpace
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::AddNameSpace(const GUID * pguid,
|
||
|
IShellFolder * psf, LPCITEMIDLIST pidl, DWORD dwFlags)
|
||
|
{
|
||
|
HRESULT hres = E_INVALIDARG;
|
||
|
|
||
|
ASSERT(IS_VALID_CODE_PTR(psf, IShellFolder));
|
||
|
ASSERT(NULL == pguid || IS_VALID_READ_PTR(pguid, GUID));
|
||
|
ASSERT(NULL == pidl || IS_VALID_PIDL(pidl));
|
||
|
|
||
|
if (NULL == _hdpa)
|
||
|
{
|
||
|
_hdpa = DPA_Create(4);
|
||
|
}
|
||
|
|
||
|
if (psf && _hdpa)
|
||
|
{
|
||
|
hres = S_OK; // Assume success
|
||
|
|
||
|
CISFElem * pel = new CISFElem(pguid, psf, dwFlags);
|
||
|
if (pel)
|
||
|
{
|
||
|
hres = pel->SetPidl(pidl);
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
if (DPA_ERR == DPA_AppendPtr(_hdpa, pel))
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
delete pel;
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IAugmentedShellFolder::GetNameSpaceID
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::GetNameSpaceID(LPCITEMIDLIST pidl, GUID * pguidOut)
|
||
|
{
|
||
|
HRESULT hres = E_INVALIDARG;
|
||
|
|
||
|
ASSERT(IS_VALID_PIDL(pidl));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(pguidOut, GUID));
|
||
|
|
||
|
if (pidl && pguidOut)
|
||
|
{
|
||
|
UINT id = IDWrap_GetID(pidl);
|
||
|
|
||
|
hres = E_FAIL;
|
||
|
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_GetPtr(_hdpa, id);
|
||
|
if (pel)
|
||
|
{
|
||
|
pel->GetNameSpaceID(pguidOut);
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IAugmentedShellFolder::QueryNameSpace
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::QueryNameSpace(DWORD dwID, GUID * pguidOut,
|
||
|
IShellFolder ** ppsf)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
ASSERT(NULL == pguidOut || IS_VALID_WRITE_PTR(pguidOut, GUID));
|
||
|
ASSERT(NULL == ppsf || IS_VALID_WRITE_PTR(ppsf, IShellFolder));
|
||
|
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_GetPtr(_hdpa, dwID);
|
||
|
if (pel)
|
||
|
{
|
||
|
if (ppsf)
|
||
|
{
|
||
|
IShellFolder * psf = pel->GetPSF();
|
||
|
psf->AddRef();
|
||
|
*ppsf = psf;
|
||
|
}
|
||
|
|
||
|
if (pguidOut)
|
||
|
pel->GetNameSpaceID(pguidOut);
|
||
|
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IAugmentedShellFolder::EnumNameSpace
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::EnumNameSpace(DWORD uNameSpace, DWORD * pdwID)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
DWORD celem = DPA_GetPtrCount(_hdpa);
|
||
|
|
||
|
if (-1 == uNameSpace)
|
||
|
hres = celem;
|
||
|
else
|
||
|
{
|
||
|
if (uNameSpace >= celem)
|
||
|
hres = E_FAIL;
|
||
|
else
|
||
|
{
|
||
|
// For now, simply use the index given
|
||
|
*pdwID = uNameSpace;
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: ITranslateShellChangeNotify::TranslateIDs
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::TranslateIDs(LONG *plEvent,
|
||
|
LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2,
|
||
|
LPITEMIDLIST * ppidlOut1, LPITEMIDLIST * ppidlOut2,
|
||
|
LONG *plEvent2, LPITEMIDLIST *ppidlOut1Event2,
|
||
|
LPITEMIDLIST *ppidlOut2Event2)
|
||
|
{
|
||
|
HRESULT hres = S_OK;
|
||
|
|
||
|
*plEvent2 = (LONG)-1;
|
||
|
|
||
|
*ppidlOut1Event2 = NULL;
|
||
|
*ppidlOut2Event2 = NULL;
|
||
|
|
||
|
|
||
|
*ppidlOut1 = (LPITEMIDLIST)pidl1;
|
||
|
*ppidlOut2 = (LPITEMIDLIST)pidl2;
|
||
|
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
int cElem = DPA_GetPtrCount(_hdpa);
|
||
|
int i;
|
||
|
|
||
|
// Go thru all the namespaces and find which one should
|
||
|
// translate this notification
|
||
|
for (i = 0; i < cElem; i++)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_FastGetPtr(_hdpa, i);
|
||
|
if (pel)
|
||
|
{
|
||
|
LPCITEMIDLIST pidlNS = pel->GetPidl();
|
||
|
|
||
|
if (pidlNS)
|
||
|
{
|
||
|
if (pidl1)
|
||
|
{
|
||
|
*ppidlOut1 = TranslatePidl(pidlNS, pidl1, i);
|
||
|
if (NULL == *ppidlOut1)
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hres) && pidl2)
|
||
|
{
|
||
|
*ppidlOut2 = TranslatePidl(pidlNS, pidl2, i);
|
||
|
if (NULL == *ppidlOut2)
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
{
|
||
|
if (*ppidlOut1 != pidl1)
|
||
|
Pidl_Set(ppidlOut1, NULL);
|
||
|
|
||
|
if (*ppidlOut2 != pidl2)
|
||
|
Pidl_Set(ppidlOut2, NULL);
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (*ppidlOut1 != pidl1 || *ppidlOut2 != pidl2)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: ITranslateShellChangeNotify::IsChildID
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::IsChildID(LPCITEMIDLIST pidlKid, BOOL fImmediate)
|
||
|
{
|
||
|
HRESULT hres = S_FALSE;
|
||
|
//At this point we should have a translated pidl
|
||
|
if (pidlKid)
|
||
|
{
|
||
|
// Weirdness: If fImmediate is TRUE, then this is a Wrapped pidl. If it's
|
||
|
// false, then it's not, and we need to check to see if it's a Real FS Child.
|
||
|
if (fImmediate)
|
||
|
{
|
||
|
LPCITEMIDLIST pidlRelKid = ILFindLastID(pidlKid);
|
||
|
if (pidlRelKid)
|
||
|
{
|
||
|
int nID = IDWrap_GetID(pidlRelKid);
|
||
|
CISFElem * pel = (CISFElem *)DPA_GetPtr(_hdpa, nID);
|
||
|
if (pel && pel->GetPidl())
|
||
|
{
|
||
|
|
||
|
if (ILIsParent(pel->GetPidl(), pidlKid, TRUE))
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int cElem = DPA_GetPtrCount(_hdpa);
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < cElem; i++)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_GetPtr(_hdpa, i);
|
||
|
if (pel && pel->GetPidl())
|
||
|
{
|
||
|
if (ILIsParent(pel->GetPidl(), pidlKid, FALSE))
|
||
|
{
|
||
|
hres = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: ITranslateShellChangeNotify::IsEqualID
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::IsEqualID(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
||
|
{
|
||
|
int cElem = DPA_GetPtrCount(_hdpa);
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < cElem; i++)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_FastGetPtr(_hdpa, i);
|
||
|
|
||
|
if (pel)
|
||
|
{
|
||
|
if (pidl1)
|
||
|
{
|
||
|
if (ILIsEqual(pel->GetPidl(),pidl1))
|
||
|
return S_OK;
|
||
|
}
|
||
|
else if (pidl2)
|
||
|
{
|
||
|
if (ILIsParent(pidl2, pel->GetPidl(), FALSE))
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: ITranslateShellChangeNotify::Register
|
||
|
Registers all pidls contained to the passed in window
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::Register(HWND hwnd, UINT uMsg, long lEvents)
|
||
|
{
|
||
|
HRESULT hres = NOERROR;
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
int cElem = DPA_GetPtrCount(_hdpa);
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < cElem; i++)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_FastGetPtr(_hdpa, i);
|
||
|
|
||
|
// Has this namespace been registered yet?
|
||
|
if (pel && 0 == pel->GetRegister())
|
||
|
{
|
||
|
// No; register it
|
||
|
LPCITEMIDLIST pidlNS = pel->GetPidl();
|
||
|
|
||
|
if (pidlNS)
|
||
|
{
|
||
|
pel->SetRegister(RegisterNotify(hwnd, uMsg, pidlNS, lEvents,
|
||
|
SHCNRF_ShellLevel | SHCNRF_InterruptLevel, TRUE));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hres = E_FAIL;
|
||
|
|
||
|
return hres;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: ITranslateShellChangeNotify::Unregister
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugmentedISF::Unregister()
|
||
|
{
|
||
|
HRESULT hres = NOERROR;
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
int cElem = DPA_GetPtrCount(_hdpa);
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < cElem; i++)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_FastGetPtr(_hdpa, i);
|
||
|
UINT uReg;
|
||
|
if (pel && (uReg = pel->GetRegister()) != 0)
|
||
|
{
|
||
|
// SHChangeNotifyDeregister will flush messages
|
||
|
// which will send a notify which will come back here...
|
||
|
pel->SetRegister(0);
|
||
|
SHChangeNotifyDeregister(uReg);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hres = E_FAIL;
|
||
|
|
||
|
return hres;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Returns the psf associated with the ID.
|
||
|
|
||
|
*/
|
||
|
IShellFolder * CAugmentedISF::_GetObjectPSF(int nID)
|
||
|
{
|
||
|
IShellFolder * psf = NULL;
|
||
|
|
||
|
if (_hdpa)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_GetPtr(_hdpa, nID);
|
||
|
if (pel)
|
||
|
{
|
||
|
psf = pel->GetPSF();
|
||
|
ASSERT(IS_VALID_CODE_PTR(psf, IShellFolder));
|
||
|
|
||
|
psf->AddRef();
|
||
|
}
|
||
|
}
|
||
|
return psf;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// CAugISF Enumerator object
|
||
|
//
|
||
|
|
||
|
#undef SUPERCLASS
|
||
|
|
||
|
|
||
|
// Constructor
|
||
|
CAugISFEnum::CAugISFEnum() :
|
||
|
_cRef(1)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
// Destructor
|
||
|
CAugISFEnum::~CAugISFEnum()
|
||
|
{
|
||
|
if (_hdpaISF)
|
||
|
{
|
||
|
DPA_DestroyCallback(_hdpaISF, CISFElem_DestroyCB, NULL);
|
||
|
_hdpaISF = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAugISFEnum::Init(HDPA hdpaISF, DWORD dwEnumFlags)
|
||
|
{
|
||
|
HRESULT hres = S_OK;
|
||
|
|
||
|
ASSERT(IS_VALID_HANDLE(hdpaISF, DPA));
|
||
|
|
||
|
// Clone the DPA
|
||
|
_hdpaISF = DPA_Clone(hdpaISF, NULL);
|
||
|
if (_hdpaISF)
|
||
|
{
|
||
|
// Clone the elements too
|
||
|
int cElem = DPA_GetPtrCount(_hdpaISF);
|
||
|
int i;
|
||
|
|
||
|
// If something fails in the loop, at least try to enumerate
|
||
|
// other namespaces.
|
||
|
for (i = 0; i < cElem; i++)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_FastGetPtr(_hdpaISF, i);
|
||
|
if (pel)
|
||
|
{
|
||
|
CISFElem * pelNew = pel->Clone();
|
||
|
if (pelNew)
|
||
|
{
|
||
|
// Get the enumerator
|
||
|
if (SUCCEEDED(pelNew->AcquireEnumerator(dwEnumFlags)))
|
||
|
DPA_SetPtr(_hdpaISF, i, pelNew);
|
||
|
else
|
||
|
{
|
||
|
TraceMsg(TF_WARNING, "CAugISFEnum::Init. Namespace %d has no enumerator.", i);
|
||
|
|
||
|
// Remove it from the list to enumerate, and continue
|
||
|
DPA_DeletePtr(_hdpaISF, i);
|
||
|
cElem--;
|
||
|
i--;
|
||
|
delete pelNew;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAugISFEnum::QueryInterface(REFIID riid, LPVOID * ppvObj)
|
||
|
{
|
||
|
static const QITAB qit[] = {
|
||
|
QITABENT(CAugISFEnum, IEnumIDList),
|
||
|
{ 0 },
|
||
|
};
|
||
|
return QISearch(this, qit, riid, ppvObj);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CAugISFEnum::AddRef()
|
||
|
{
|
||
|
return ++_cRef;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CAugISFEnum::Release()
|
||
|
{
|
||
|
if (--_cRef > 0) {
|
||
|
return _cRef;
|
||
|
}
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: IEnumIDList::Next method
|
||
|
|
||
|
This will call the current enumerator for the next
|
||
|
object. The object's pidl is wrapped in an IDWRAP
|
||
|
(which is stamped with the identifier of the specific
|
||
|
IShellFolder the object belongs to) and handed back.
|
||
|
|
||
|
If the current enumerator has no more items to return,
|
||
|
this function will call the next enumerator for its
|
||
|
first item, and returns that. The subsequent call
|
||
|
will pick up from there.
|
||
|
|
||
|
*/
|
||
|
STDMETHODIMP CAugISFEnum::Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
|
||
|
{
|
||
|
ULONG celtFetched = 0;
|
||
|
HRESULT hres = S_FALSE;
|
||
|
|
||
|
if (celt > 0)
|
||
|
{
|
||
|
IEnumIDList * pei = _GetObjectEnumerator(_iCurISF);
|
||
|
if (pei)
|
||
|
{
|
||
|
LPITEMIDLIST pidl;
|
||
|
|
||
|
hres = pei->Next(1, &pidl, &celtFetched);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
// End of enumeration for this object?
|
||
|
if (S_FALSE == hres)
|
||
|
{
|
||
|
// Yes; go to next ISF object
|
||
|
_iCurISF++;
|
||
|
hres = Next(celt, rgelt, &celtFetched);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No; now wrap the pidl.
|
||
|
rgelt[0] = AugISF_WrapPidl( pidl, _iCurISF );
|
||
|
if (rgelt[0])
|
||
|
{
|
||
|
celtFetched = 1;
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pei->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pceltFetched)
|
||
|
*pceltFetched = celtFetched;
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAugISFEnum::Skip(ULONG celt)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAugISFEnum::Reset()
|
||
|
{
|
||
|
if (_hdpaISF)
|
||
|
{
|
||
|
// Reset all the enumerators
|
||
|
int cel = DPA_GetPtrCount(_hdpaISF);
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < cel; i++)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_FastGetPtr(_hdpaISF, i);
|
||
|
if (pel)
|
||
|
{
|
||
|
IEnumIDList * pei = pel->GetEnumerator();
|
||
|
if (pei)
|
||
|
{
|
||
|
pei->Reset();
|
||
|
// Don't Release b/c GetEnumerator doesn't AddRef
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_iCurISF = 0;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAugISFEnum::Clone(IEnumIDList **ppenum)
|
||
|
{
|
||
|
*ppenum = NULL;
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Returns the enumerator associated with the ID.
|
||
|
|
||
|
*/
|
||
|
IEnumIDList * CAugISFEnum::_GetObjectEnumerator(int nID)
|
||
|
{
|
||
|
IEnumIDList * pei = NULL;
|
||
|
|
||
|
if (_hdpaISF)
|
||
|
{
|
||
|
CISFElem * pel = (CISFElem *)DPA_GetPtr(_hdpaISF, nID);
|
||
|
if (pel)
|
||
|
{
|
||
|
pei = pel->GetEnumerator();
|
||
|
ASSERT(IS_VALID_CODE_PTR(pei, IEnumIDList));
|
||
|
|
||
|
pei->AddRef();
|
||
|
}
|
||
|
}
|
||
|
return pei;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Create-instance function for class factory
|
||
|
|
||
|
*/
|
||
|
STDAPI CAugmentedISF_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
|
||
|
{
|
||
|
// aggregation checking is handled in class factory
|
||
|
|
||
|
HRESULT hres;
|
||
|
CAugmentedISF* pObj;
|
||
|
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
pObj = new CAugmentedISF();
|
||
|
if (pObj)
|
||
|
{
|
||
|
*ppunk = SAFECAST(pObj, IShellFolder *);
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|