Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
delfldr.cpp
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 39k
Category:
Windows Kernel
Development Platform:
Visual C++
- #include "shellprv.h"
- #include "clsobj.h"
- #include "caggunk.h"
- #pragma hdrstop
- // Delegated IShellFolder object. Takes an ISF inner and adds the list of
- // delegated shell folders to its namespace, wrapping the IDLISTs as required.
- class CDelegateFolder : public CAggregatedUnknown, IDelegateShellFolder, IShellFolder2, IPersistFreeThreadedObject
- {
- public:
- // *** IUnknown ***
- STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
- { return CAggregatedUnknown::QueryInterface(riid, ppv); };
- STDMETHODIMP_(ULONG) AddRef(void)
- { return CAggregatedUnknown::AddRef(); };
- STDMETHODIMP_(ULONG) Release(void)
- { return CAggregatedUnknown::Release(); };
- // IPersistFreeThreadedObject
- STDMETHODIMP GetClassID(CLSID *pCLSID);
- // *** IShellFolder methods ***
- STDMETHODIMP ParseDisplayName(HWND hwnd, LPBC pbc, LPOLESTR pszDisplayName,
- ULONG *pchEaten, LPITEMIDLIST *ppidl, ULONG *pdwAttributes);
- STDMETHODIMP EnumObjects(HWND hwnd, DWORD grfFlags, IEnumIDList **ppenumIDList);
- STDMETHODIMP BindToObject(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppvOut);
- STDMETHODIMP BindToStorage(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppv);
- STDMETHODIMP CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
- STDMETHODIMP CreateViewObject (HWND hwnd, REFIID riid, void **ppvOut);
- STDMETHODIMP GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl, ULONG *rgfInOut);
- STDMETHODIMP GetUIObjectOf(HWND hwnd, UINT cidl, LPCITEMIDLIST * apidl,
- REFIID riid, UINT * prgfInOut, void **ppvOut);
- STDMETHODIMP GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, STRRET *pName);
- STDMETHODIMP SetNameOf(HWND hwnd, LPCITEMIDLIST pidl, LPCOLESTR pszName,
- DWORD uFlags, LPITEMIDLIST *ppidlOut);
- // *** IShellFolder2 methods ***
- STDMETHODIMP GetDefaultSearchGUID(LPGUID lpGuid);
- STDMETHODIMP EnumSearches(LPENUMEXTRASEARCH *ppenum);
- STDMETHODIMP GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay);
- STDMETHODIMP GetDefaultColumnState(UINT iColumn, DWORD *pbState);
- STDMETHODIMP GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv);
- STDMETHODIMP GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *pDetails);
- STDMETHODIMP MapNameToSCID(LPCWSTR pwszName, SHCOLUMNID *pscid);
- // *** IDelegateShellFolder ***
- STDMETHODIMP Initialize(WORD id, IShellFolder2* psf);
- STDMETHODIMP AddFolders(CLSID* aCLISD, INT count);
- protected:
- CDelegateFolder(IUnknown *punkOuter);
- ~CDelegateFolder();
- // used by the CAggregatedUnknown stuff
- HRESULT v_InternalQueryInterface(REFIID riid,void **ppv);
- LPCITEMIDLIST _GetFolderIDList();
- PDELEGATEITEMID _IsDelegateObject(LPCITEMIDLIST pidl, LPCLSID pclsid);
- HRESULT _InitFolder(IUnknown *punk);
- HRESULT _GetDelegateFolder(LPCITEMIDLIST pidl, REFIID riid, void **ppv);
- HRESULT _GetItemFolder(LPCITEMIDLIST pidl, IShellFolder **ppsf);
- HRESULT _GetItemFolder2(LPCITEMIDLIST pidl, IShellFolder2 **ppsf);
- private:
- HDCA _dcaDelegates; // array of CLSIDs we are using
- IShellFolder2 *_psfOuter; // IShellFolder2 of the inner object
- WORD _id; // ID used for marking our IDLISTs
- BOOL _fFreeThread:1; // supports the IPersistFreeThreadedObject iface
- LPITEMIDLIST _pidl; // IDLIST passed to our ::Initialize method
- friend HRESULT CDelegateFolder_CreateInstance(IUnknown* punkOuter, REFIID riid, void **ppvOut);
- };
- //-----------------------------------------------------------------------------
- // Stuff
- //-----------------------------------------------------------------------------
- // flow control helpers
- #define ExitGracefully(_hr, _r)
- { _hr = (_r); goto exit; }
- #define FailGracefully(_hr)
- { if (FAILED(hr)) goto exit; }
- STDAPI CDelegateMalloc_Create(void *pv, UINT cbSize, WORD wOuter, IMalloc **ppmalloc);
- class CDelegateFolderEnum : public IEnumIDList
- {
- public:
- CDelegateFolderEnum(HWND hwnd, DWORD grfFlags, HDPA dpaFolders);
- ~CDelegateFolderEnum();
- // *** IUnknown methods ***
- STDMETHOD(QueryInterface) (REFIID riid, void **ppv);
- STDMETHOD_(ULONG,AddRef) (THIS);
- STDMETHOD_(ULONG,Release) (THIS);
- // *** IEnumIDList methods ***
- STDMETHOD(Next) (ULONG celt,
- LPITEMIDLIST *rgelt,
- ULONG *pceltFetched);
- STDMETHOD(Skip) (ULONG celt);
- STDMETHOD(Reset) (THIS);
- STDMETHOD(Clone) (IEnumIDList **ppenum);
- private:
- LONG _cRef;
- HWND _hwnd;
- DWORD _grfFlags;
- HDPA _dpaFolders;
- INT _index;
- IEnumIDList* _pCurrentEnum;
- };
- //
- // get the clsid of the delegate from the pidl.
- //
- #define _GetDelegateCLSID(pdi)
- (*(UNALIGNED CLSID*)&(((PDELEGATEITEMID)(pdi))->rgb[((PDELEGATEITEMID)(pdi))->cbInner]))
- //
- // callback used to comapre two delegate item idlists CLSID
- //
- INT _CompareDelegateItem(void *pv1, void *pv2, LPARAM lParam)
- {
- PDELEGATEITEMID pdi1 = (PDELEGATEITEMID)pv1;
- PDELEGATEITEMID pdi2 = (PDELEGATEITEMID)pv2;
- return memcmp((UNALIGNED CLSID*)&(pdi1->rgb[pdi1->cbInner]),
- (UNALIGNED CLSID*)&(pdi2->rgb[pdi2->cbInner]),
- SIZEOF(CLSID));
- }
- //
- // callback used to destroy the IUnkown DPA.
- //
- static INT _ReleaseCB(void *pItem, void *pData)
- {
- IUnknown *pUnknown = (IUnknown *)pItem;
- pUnknown->Release();
- return 1;
- }
- //-----------------------------------------------------------------------------
- // Constructors etc
- //-----------------------------------------------------------------------------
- // Constructor
- CDelegateFolder::CDelegateFolder(IUnknown *punkOuter) :
- CAggregatedUnknown(punkOuter),
- _dcaDelegates(NULL),
- _psfOuter(NULL),
- _id(0),
- _fFreeThread(FALSE),
- _pidl(NULL)
- {
- DllAddRef();
- }
- CDelegateFolder::~CDelegateFolder()
- {
- if ( _dcaDelegates )
- DCA_Destroy(_dcaDelegates);
- ILFree(_pidl);
- DllRelease();
- }
- //
- // get the pidl used to initialize this namespace
- //
- LPCITEMIDLIST CDelegateFolder::_GetFolderIDList()
- {
- if (!_pidl)
- SHGetIDListFromUnk(_psfOuter, &_pidl);
- return _pidl;
- }
- //
- // aggregated unknown handling
- //
- HRESULT CDelegateFolder::v_InternalQueryInterface(REFIID riid, void **ppv)
- {
- static const QITAB qit[] = {
- QITABENT(CDelegateFolder, IDelegateShellFolder), // IID_IDelegateShellFolder
- QITABENTMULTI(CDelegateFolder, IShellFolder, IShellFolder2), // IID_IShellFolder
- QITABENT(CDelegateFolder, IShellFolder2), // IID_IShellFolder2
- QITABENT(CDelegateFolder, IPersistFreeThreadedObject), // IID_IPersistFreeThreadedObject
- { 0 },
- };
- if ( IsEqualIID(riid, IID_IPersistFreeThreadedObject) && !_fFreeThread )
- return E_NOINTERFACE;
- return QISearch(this, qit, riid, ppv);
- }
- //-----------------------------------------------------------------------------
- // IDelegateShellFolder
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::Initialize(WORD id, IShellFolder2* psf)
- {
- // ensure we have the DCA for storing the delegate folders into, then lets grav the ISF
- // we have been given.
- if ( !_dcaDelegates )
- {
- _dcaDelegates = DCA_Create();
- if ( !_dcaDelegates )
- return E_OUTOFMEMORY;
- }
- ASSERT(NULL != psf);
- // NOTE: AddRef() is not called because psf is required to be an interface on the
- // same aggregated object
- _psfOuter = psf;
- _id = id;
- // use the CLSID (from our delegate) as the location in the registry
- // where we look for the delegates to load
- CLSID clsid;
- if (SUCCEEDED(GetClassID(&clsid)))
- {
- HKEY hKey;
- if (SUCCEEDED(SHRegGetCLSIDKey(clsid, NULL, FALSE, FALSE, &hKey)))
- {
- DCA_AddItemsFromKey(_dcaDelegates, hKey, TEXT("shellex\DelegateShellFolders"));
- RegCloseKey(hKey);
- }
- }
- // is the inner object free threaded? if so we must honor this IID as the regitems
- // code uses it to cache us.
- IPersistFreeThreadedObject* ppfto;
- if ( SUCCEEDED(_psfOuter->QueryInterface(IID_IPersistFreeThreadedObject, (void **)&ppfto)))
- {
- _fFreeThread = TRUE;
- ppfto->Release();
- }
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- // given an array of CLISDs add them to the delegate object list
- STDMETHODIMP CDelegateFolder::AddFolders(CLSID* aCLISD, INT count)
- {
- INT i;
- // fail if either we don't have a delegate list to ad items to or, we have
- // no array of CLSIDs to add.
- if ( !aCLISD || !_dcaDelegates )
- return E_INVALIDARG;
- for ( i = 0 ; i < count ; i++ )
- {
- if ( !DCA_AddItem(_dcaDelegates, aCLISD[i]) )
- return E_FAIL;
- }
- return S_OK;
- }
- /*-----------------------------------------------------------------------------
- / Crack the pidl and see if it looks like a delegate object, we return S_OK
- / if it is, otherwise we hand back S_FALSE.
- /
- / In:
- / pidl -> pidl to be cracked
- / pclsid -> receives the CLSID for the object (if non-zero)
- /
- / Out:
- / HRESULT
- /----------------------------------------------------------------------------*/
- PDELEGATEITEMID CDelegateFolder::_IsDelegateObject(LPCITEMIDLIST pidl, LPCLSID pclsid)
- {
- PDELEGATEITEMID pdi = (PDELEGATEITEMID)pidl;
- if ( pdi && (pdi->cbSize > SIZEOF(DELEGATEITEMID)-1) && (pdi->wOuter == _id) )
- {
- if ( pclsid )
- *pclsid = *((UNALIGNED CLSID*)&(pdi->rgb[pdi->cbInner]));
- return pdi;
- }
- return NULL;
- }
- HRESULT CDelegateFolder::_InitFolder(IUnknown *punk)
- {
- HRESULT hr = S_OK;
- IPersistFolder* ppf;
- if ( SUCCEEDED(punk->QueryInterface(IID_IPersistFolder, (void **)&ppf)) )
- {
- hr = ppf->Initialize(_GetFolderIDList());
- ppf->Release();
- }
- return hr;
- }
- /*-----------------------------------------------------------------------------
- / Extract the delegate CLSID from the pidl we see, if the type is not a delegate
- / item then return failure. if ppv is non-NULL then create an object from that
- / CLSID that maps to the thing we want.
- /
- / In:
- / pidl = pidl to look into
- / pCLSID = receives the clisd
- / riid, ppv -> if you want an instance then pass the IID and a ppv
- /
- / Out:
- / HRESULT
- /----------------------------------------------------------------------------*/
- HRESULT CDelegateFolder::_GetDelegateFolder(LPCITEMIDLIST pidl, REFIID riid, void **ppv)
- {
- HRESULT hr;
- CLSID clsid;
- PDELEGATEITEMID pdi = _IsDelegateObject(pidl, &clsid);
- if (!pdi)
- return E_FAIL;
- // the caller wants an instance of this delegate folder, so lets co-create it and set
- // its allocator as required.
- IDelegateFolder* pDelegateFolder;
- hr = SHCoCreateInstance(NULL, &clsid, NULL, IID_IDelegateFolder, (void **)&pDelegateFolder);
- FailGracefully(hr);
- IMalloc* pAlloc;
- if ( SUCCEEDED(CDelegateMalloc_Create(&clsid, SIZEOF(CLSID), _id, &pAlloc)) )
- {
- pDelegateFolder->SetItemAlloc(pAlloc);
- pAlloc->Release();
- }
- hr = pDelegateFolder->QueryInterface(riid, ppv);
- pDelegateFolder->Release();
- // the caller is requesting IShellFolder for this object, therefore we need to bind
- // and ensure that its parent is correctly initialized (by calling IPersistFolder),
- // note that at this point just calling Initialize with our cached PIDL should be
- // sufficent.
- if ( SUCCEEDED(hr) && _GetFolderIDList() &&
- (IsEqualIID(riid, IID_IShellFolder) || IsEqualIID(riid, IID_IShellFolder2)) )
- {
- _InitFolder((IUnknown *)*ppv);
- }
- hr = S_OK; // success
- exit:
- return hr;
- }
- HRESULT CDelegateFolder::_GetItemFolder(LPCITEMIDLIST pidl, IShellFolder **ppsf)
- {
- HRESULT hr;
- if (_IsDelegateObject(pidl, NULL))
- {
- hr = _GetDelegateFolder(pidl, IID_IShellFolder, (void **)ppsf);
- }
- else
- {
- *ppsf = _psfOuter;
- _psfOuter->AddRef();
- hr = S_OK;
- }
- return hr;
- }
- HRESULT CDelegateFolder::_GetItemFolder2(LPCITEMIDLIST pidl, IShellFolder2 **ppsf)
- {
- HRESULT hr;
- if (_IsDelegateObject(pidl, NULL))
- {
- hr = _GetDelegateFolder(pidl, IID_IShellFolder2, (void **)ppsf);
- }
- else
- {
- *ppsf = _psfOuter;
- _psfOuter->AddRef();
- hr = S_OK;
- }
- return hr;
- }
- // IPersist method
- STDMETHODIMP CDelegateFolder::GetClassID(CLSID *pCLSID)
- {
- IPersist* pps;
- HRESULT hr = _psfOuter->QueryInterface(IID_IPersist, (void **)&pps);
- if ( SUCCEEDED(hr) )
- {
- hr = pps->GetClassID(pCLSID);
- pps->Release();
- }
- return hr;
- }
- //-----------------------------------------------------------------------------
- // IShellFolder methods
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::ParseDisplayName(HWND hwnd, LPBC pbc, LPOLESTR pszDisplayName,
- ULONG *pchEaten, LPITEMIDLIST *ppidl, ULONG *pdwAttributes)
- {
- // round robbin the delegate namespaces, seeing if any want to parse the string,
- // if they don't they will return E_NOTIMPL or E_INVALIDARG. If they return anything
- // other than that then we return their result, otherwise we continue.
- for (int i = 0 ; i < DCA_GetItemCount(_dcaDelegates) ; i++)
- {
- IShellFolder* psf;
- if ( SUCCEEDED(DCA_CreateInstance(_dcaDelegates, i, IID_IShellFolder, (void**)&psf)) )
- {
- IDelegateFolder* pdf;
- if ( SUCCEEDED(psf->QueryInterface(IID_IDelegateFolder, (void**)&pdf)) )
- {
- IMalloc* pAlloc;
- if ( SUCCEEDED(CDelegateMalloc_Create((LPVOID)DCA_GetItem(_dcaDelegates, i), SIZEOF(CLSID), _id, &pAlloc)) )
- {
- pdf->SetItemAlloc(pAlloc);
- pAlloc->Release();
- }
- pdf->Release();
- }
- HRESULT hr = psf->ParseDisplayName(hwnd, pbc, pszDisplayName, pchEaten, ppidl, pdwAttributes);
- psf->Release();
- if ( (hr != E_INVALIDARG) && (hr != E_NOTIMPL) )
- {
- return hr;
- }
- }
- }
- // None of the delegates were interested so lets call the _psfOuter and let them have a crack at it!
- return _psfOuter->ParseDisplayName(hwnd, pbc, pszDisplayName,
- pchEaten, ppidl, pdwAttributes);
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::EnumObjects(HWND hwnd, DWORD grfFlags, IEnumIDList **ppenumIDList)
- {
- CDelegateFolderEnum* pEnum;
- IDelegateFolder* pDelegateFolder;
- IMalloc* pAlloc;
- HDPA dpaFolders = NULL;
- INT i;
- *ppenumIDList = NULL; // in case of failure
- // to construct the enumerator we are going to give out to the oustside world we
- // must fill a DPA with the IShellFolder iface's we want to use. Therefore lets
- // walk the list of delegate folders add those to the DPA (having both set their
- // malloc and then initialized them).
- dpaFolders = DPA_Create(4);
- if ( !dpaFolders )
- return E_OUTOFMEMORY;
- for ( i = 0 ; i < DCA_GetItemCount(_dcaDelegates) ; i++ )
- {
- if ( SUCCEEDED(DCA_CreateInstance(_dcaDelegates, i, IID_IDelegateFolder, (void **)&pDelegateFolder)) )
- {
- if ( SUCCEEDED(CDelegateMalloc_Create((LPVOID)DCA_GetItem(_dcaDelegates, i), SIZEOF(CLSID), _id, &pAlloc)) )
- {
- pDelegateFolder->SetItemAlloc(pAlloc);
- pAlloc->Release();
- _InitFolder((IUnknown *)pDelegateFolder);
- IShellFolder* psf;
- if ( SUCCEEDED(pDelegateFolder->QueryInterface(IID_IShellFolder, (void **)&psf)) )
- {
- if ( -1 == DPA_AppendPtr(dpaFolders, psf) )
- {
- psf->Release(); // failed to place into the DPA.
- }
- }
- }
- pDelegateFolder->Release();
- }
- }
- _psfOuter->AddRef();
- DPA_AppendPtr(dpaFolders, _psfOuter); // BUGBUG: what about failure
- pEnum = new CDelegateFolderEnum(hwnd, grfFlags, dpaFolders);
- if ( !pEnum )
- {
- DPA_DestroyCallback(dpaFolders, _ReleaseCB, NULL);
- return E_OUTOFMEMORY;
- }
- *ppenumIDList = SAFECAST(pEnum, IEnumIDList*); // pass out the enumerator
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbc,
- REFIID riid, void **ppvOut)
- {
- IShellFolder* psfItem;
- HRESULT hr = _GetItemFolder(pidl, &psfItem);
- if (SUCCEEDED(hr))
- {
- hr = psfItem->BindToObject(pidl, pbc, riid, ppvOut);
- psfItem->Release();
- }
- return hr;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbc,
- REFIID riid, void **ppv)
- {
- IShellFolder* psfItem;
- HRESULT hr = _GetItemFolder(pidl, &psfItem);
- if (SUCCEEDED(hr))
- {
- hr = psfItem->BindToStorage(pidl, pbc, riid, ppv);
- psfItem->Release();
- }
- return hr;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
- {
- HRESULT hr;
- LPCITEMIDLIST pidlNext1 = _ILNext(pidl1);
- LPCITEMIDLIST pidlNext2 = _ILNext(pidl2);
- PDELEGATEITEMID pdi1 = _IsDelegateObject(pidl1, NULL);
- PDELEGATEITEMID pdi2 = _IsDelegateObject(pidl2, NULL);
- IShellFolder* psfItem1 = NULL;
- IShellFolder* psfItem2 = NULL;
- // if we have two delegate objects then attempt to compare, if we have a single then
- // the delegate comes first. if neither of the items are delegates then lets pass
- // them onto the innerISF.
- if ( pdi1 )
- {
- INT iResult = 0;
- if ( pdi2 )
- {
- STRRET StrRet1, StrRet2;
- TCHAR szItemName1[MAX_PATH];
- TCHAR szItemName2[MAX_PATH];
- hr = _GetDelegateFolder(pidl1, IID_IShellFolder, (void **)&psfItem1);
- FailGracefully(hr);
- hr = _GetDelegateFolder(pidl2, IID_IShellFolder, (void **)&psfItem2);
- FailGracefully(hr);
- if ( FAILED(psfItem1->GetDisplayNameOf(pidl1, SHGDN_NORMAL, &StrRet1)) ||
- FAILED(psfItem2->GetDisplayNameOf(pidl2, SHGDN_NORMAL, &StrRet2)) )
- {
- ExitGracefully(hr, E_FAIL);
- }
- StrRetToStrN(szItemName1, ARRAYSIZE(szItemName1), &StrRet1, pidl1);
- StrRetToStrN(szItemName2, ARRAYSIZE(szItemName2), &StrRet2, pidl2);
- iResult = lstrcmp(szItemName1,szItemName2);
- }
- else
- {
- iResult = 1;
- }
- // their names match so lets check out the rest of the data, starting with the CLSIDs,
- // if they match then we must continue the binding process and let them be compared.
- if ( !iResult )
- iResult = memcmp(&pdi1->rgb[pdi1->cbInner], &pdi2->rgb[pdi2->cbInner], SIZEOF(CLSID));
- if ( iResult )
- ExitGracefully(hr, ResultFromShort(iResult));
- if ( ILIsEmpty(pidlNext1) )
- {
- if ( ILIsEmpty(pidlNext2) )
- ExitGracefully(hr, ResultFromShort(0)); // they are the same size
- ExitGracefully(hr, ResultFromShort(-1)); // pidl1 is shorter
- }
- else if ( ILIsEmpty(pidlNext2) )
- ExitGracefully(hr, ResultFromShort(1)); // pidl2 is shorter
- // call into the delegate namespace that owns these IDLISTs and let it compare
- if ( psfItem1 )
- {
- hr = _GetDelegateFolder(pidl1, IID_IShellFolder, (void **)&psfItem1);
- FailGracefully(hr);
- }
- hr = psfItem1->CompareIDs(lParam, pidl1, pidl2); // done
- }
- else if ( pdi2 )
- {
- hr = ResultFromShort(-1); // only pidl2 was a delegate
- }
- else
- {
- // both items belong to the inner ISF, so lets pass them to that so they can be compared,
- // having done that we can just return the result from there.
- hr = _psfOuter->CompareIDs(lParam, pidl1, pidl2);
- }
- exit:
- if ( psfItem1 )
- psfItem1->Release();
- if ( psfItem2 )
- psfItem2->Release();
- return hr;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::CreateViewObject(HWND hwnd, REFIID riid, void **ppvOut)
- {
- return _psfOuter->CreateViewObject(hwnd, riid, ppvOut);
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl, ULONG * rgfInOut)
- {
- HRESULT hr = E_FAIL;
- IShellFolder* psfItem;
- LPCITEMIDLIST* apidl2 = NULL;
- HDPA dpa = NULL;
- CLSID clsid;
- ULONG i, cidl2;
- if ( cidl == 1 )
- {
- // pass real IDLs through, otherwise get the delegate folder that
- // this idlist maps to and get attributes from it.
- IShellFolder* psfItem;
- hr = _GetItemFolder(*apidl, &psfItem);
- if (SUCCEEDED(hr))
- {
- hr = psfItem->GetAttributesOf(cidl, apidl, rgfInOut);
- psfItem->Release();
- }
- }
- else if ( cidl > 1 )
- {
- // the selection is large, so we build two lists, the first contains the items that
- // relate to the inner ISF, the second is a list of the delegate items. the items
- // destined for the inner ISF are stored in a LocalAlloc, the delegates are in a
- // DPA.
- dpa = DPA_Create(4);
- apidl2 = (LPCITEMIDLIST*)LocalAlloc(LPTR, SIZEOF(LPCITEMIDLIST)*cidl);
- if ( !apidl2 || !dpa )
- ExitGracefully(hr, E_OUTOFMEMORY);
- for ( cidl2 = 0, i = 0 ; i != cidl ; i++ )
- {
- if ( !_IsDelegateObject(apidl[i], NULL) )
- {
- apidl2[cidl2++] = apidl[i];
- }
- else
- {
- if ( -1 == DPA_AppendPtr(dpa, (LPVOID)apidl[i]) )
- ExitGracefully(hr, E_OUTOFMEMORY);
- }
- }
- // call the innerISF with the items it is interested in.
- if ( cidl2 )
- {
- hr = _psfOuter->GetAttributesOf(cidl2, apidl2, rgfInOut);
- FailGracefully(hr);
- }
- // if we have any destined for the delegate namespace then lets
- // first sort that list (basedon the CLSID) and bind to the
- // namespace as required. the initial sort avoids us having
- // to CoCreate the delegate object multiple times.
- if ( DPA_GetPtrCount(dpa) )
- {
- DPA_Sort(dpa, _CompareDelegateItem, NULL);
- for ( cidl2 = 0, i = 0 ; i != (ULONG)DPA_GetPtrCount(dpa) ; i++ )
- {
- // if we are no longer in the same CLSID and the list
- // is long we pass them onto the namespace
- if ( cidl2 &&
- !IsEqualCLSID(clsid, _GetDelegateCLSID((PDELEGATEITEMID)DPA_GetPtr(dpa, i))) )
- {
- hr = _GetDelegateFolder(apidl2[0], IID_IShellFolder, (void **)&psfItem);
- FailGracefully(hr);
- hr = psfItem->GetAttributesOf(cidl2, apidl2, rgfInOut);
- psfItem->Release();
- cidl2 = 0; // no new items in the dpa copy yet!
- }
- // add this item to the list, if we have none
- // then take a snapshot of the GUID
- if ( !cidl2 )
- clsid = _GetDelegateCLSID((PDELEGATEITEMID)DPA_GetPtr(dpa, i));
- apidl2[cidl2++] = (LPCITEMIDLIST)DPA_GetPtr(dpa, i);
- }
- if ( cidl2 )
- {
- // on exit ensure that we have passed out the remainng items.
- hr = _GetDelegateFolder(apidl2[0], IID_IShellFolder, (void **)&psfItem);
- FailGracefully(hr);
- hr = psfItem->GetAttributesOf(cidl2, apidl2, rgfInOut);
- psfItem->Release();
- }
- }
- }
- exit:
- if ( dpa )
- DPA_Destroy(dpa);
- if ( apidl2 )
- LocalFree((HLOCAL)apidl2);
- return hr;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, STRRET *pName)
- {
- IShellFolder* psfItem;
- HRESULT hr = _GetItemFolder(pidl, &psfItem);
- if (SUCCEEDED(hr))
- {
- hr = psfItem->GetDisplayNameOf(pidl, uFlags, pName);
- psfItem->Release();
- }
- return hr;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::SetNameOf(HWND hwnd, LPCITEMIDLIST pidl,
- LPCOLESTR pszName, DWORD uFlags, LPITEMIDLIST *ppidlOut)
- {
- IShellFolder* psfItem;
- HRESULT hr = _GetItemFolder(pidl, &psfItem);
- if (SUCCEEDED(hr))
- {
- hr = psfItem->SetNameOf(hwnd, pidl, pszName, uFlags, ppidlOut);
- psfItem->Release();
- }
- return hr;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::GetUIObjectOf(HWND hwnd, UINT cidl, LPCITEMIDLIST *apidl,
- REFIID riid, UINT *prgfInOut, void **ppvOut)
- {
- HRESULT hr = E_FAIL;
- IShellFolder* psfItem;
- BOOL fDelegate = FALSE;
- UINT i, cidl2;
- LPCITEMIDLIST* apidl2 = NULL;
- if ( cidl == 1 )
- {
- // single selection is simple, we must just pass that down to the
- // correct owner.
- fDelegate = (_IsDelegateObject(*apidl, NULL) != NULL);
- if ( fDelegate )
- {
- hr = _GetDelegateFolder(*apidl, IID_IShellFolder, (void **)&psfItem);
- FailGracefully(hr);
- hr = psfItem->GetUIObjectOf(hwnd, cidl, apidl, riid, prgfInOut, ppvOut);
- psfItem->Release();
- }
- }
- else if ( cidl > 1 )
- {
- // walk the list of IDLISTs and see what items we have, if there are any delegate
- // items then this complicates things, if not then we can just pass to the
- // inner ISF to get the information from that.
- for ( i = 0 ; (i != cidl) && !fDelegate ; i++ )
- fDelegate = (_IsDelegateObject(apidl[i], NULL) != NULL);
- if ( fDelegate )
- {
- if ( IsEqualIID(riid, IID_IDataObject) )
- {
- hr = CIDLData_CreateFromIDArray(_GetFolderIDList(), cidl, apidl, (IDataObject **)ppvOut);
- }
- else if ( IsEqualIID(riid, IID_IContextMenu) )
- {
- // the selection is large, there is at least one delegate item in it
- // so lets build an alternate list where all the items match the
- // first (clsid and delegate-ness).
- apidl2 = (LPCITEMIDLIST*)LocalAlloc(LPTR, SIZEOF(LPCITEMIDLIST)*cidl);
- if ( !apidl2 )
- ExitGracefully(hr, E_OUTOFMEMORY);
- for ( cidl2 = 0, i = 0 ; i != cidl ; i++ )
- {
- if ( (_IsDelegateObject(apidl[0], NULL) == _IsDelegateObject(apidl[i], NULL)) &&
- ( !_IsDelegateObject(apidl[0], NULL) ||
- IsEqualCLSID(_GetDelegateCLSID(apidl[0]), _GetDelegateCLSID(apidl[i]))) )
- {
- apidl2[cidl2++] = apidl[i];
- }
- }
- // if there is a delegate in the first the bind to it and call it, otherwise
- // just call the innerISF.
- if ( !_IsDelegateObject(apidl2[0], NULL) )
- {
- hr = _psfOuter->GetUIObjectOf(hwnd, cidl2, apidl2, riid, prgfInOut, ppvOut);
- }
- else
- {
- hr = _GetDelegateFolder(apidl2[0], IID_IShellFolder, (void **)&psfItem);
- FailGracefully(hr);
- hr = psfItem->GetUIObjectOf(hwnd, cidl2, apidl2, riid, prgfInOut, ppvOut);
- psfItem->Release();
- }
- fDelegate = TRUE; // already handled
- }
- else
- {
- ExitGracefully(hr, E_NOTIMPL); // BUGBUG: we must expand on this guy!
- }
- }
- }
- // handled yet? if not then pass onto the inner ISF
- if ( !fDelegate )
- hr = _psfOuter->GetUIObjectOf(hwnd, cidl, apidl, riid, prgfInOut, ppvOut);
- exit:
- if ( apidl2 )
- LocalFree(apidl2);
- return hr;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolder::GetDefaultSearchGUID(LPGUID lpGUID)
- {
- return _psfOuter->GetDefaultSearchGUID(lpGUID);
- }
- STDMETHODIMP CDelegateFolder::EnumSearches(LPENUMEXTRASEARCH *ppenum)
- {
- return _psfOuter->EnumSearches(ppenum);
- }
- STDMETHODIMP CDelegateFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
- {
- return _psfOuter->GetDefaultColumn(dwRes, pSort, pDisplay);
- }
- STDMETHODIMP CDelegateFolder::GetDefaultColumnState(UINT iColumn, DWORD *pbState)
- {
- return _psfOuter->GetDefaultColumnState(iColumn, pbState);
- }
- STDMETHODIMP CDelegateFolder::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
- {
- IShellFolder2* psfItem;
- HRESULT hr = _GetItemFolder2(pidl, &psfItem);
- if (SUCCEEDED(hr))
- {
- hr = psfItem->GetDetailsEx(pidl, pscid, pv);
- psfItem->Release();
- }
- return hr;
- }
- STDMETHODIMP CDelegateFolder::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *pDetails)
- {
- IShellFolder2* psfItem;
- HRESULT hr = _GetItemFolder2(pidl, &psfItem);
- if (SUCCEEDED(hr))
- {
- hr = psfItem->GetDetailsOf(pidl, iColumn, pDetails);
- psfItem->Release();
- }
- return hr;
- }
- STDMETHODIMP CDelegateFolder::MapNameToSCID(LPCWSTR pwszName, SHCOLUMNID *pscid)
- {
- return _psfOuter->MapNameToSCID(pwszName, pscid);
- }
- /*-----------------------------------------------------------------------------
- / Instance creation
- /----------------------------------------------------------------------------*/
- STDAPI CDelegateFolder_CreateInstance(IUnknown* punkOuter, REFIID riid, void **ppvOut)
- {
- // we only suport being created as an agregate
- if ( !punkOuter || !IsEqualIID(riid, IID_IUnknown))
- {
- ASSERT(0);
- return E_FAIL;
- }
- CDelegateFolder *pdelisf = new CDelegateFolder(punkOuter);
- if ( !pdelisf )
- return E_OUTOFMEMORY;
- *ppvOut = pdelisf->_GetInner();
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- // Enumerator, this handles enumerating the IF and bringing in the delegate
- // folder objects.
- //-----------------------------------------------------------------------------
- CDelegateFolderEnum::CDelegateFolderEnum(HWND hwnd, DWORD grfFlags, HDPA dpaFolders) :
- _cRef(1),
- _hwnd(hwnd),
- _grfFlags(grfFlags),
- _dpaFolders(dpaFolders),
- _index(0),
- _pCurrentEnum(NULL)
- {
- DllAddRef();
- }
- CDelegateFolderEnum::~CDelegateFolderEnum()
- {
- if ( _dpaFolders )
- DPA_DestroyCallback(_dpaFolders, _ReleaseCB, NULL);
- if ( _pCurrentEnum )
- _pCurrentEnum->Release();
- DllRelease();
- }
- // IUnknown goop
- STDMETHODIMP CDelegateFolderEnum::QueryInterface(REFIID riid, void **ppv)
- {
- static const QITAB qit[] = {
- QITABENT(CDelegateFolderEnum, IEnumIDList),
- { 0 },
- };
- return QISearch(this, qit, riid, ppv);
- }
- STDMETHODIMP_(ULONG) CDelegateFolderEnum::AddRef()
- {
- return InterlockedIncrement(&_cRef);
- }
- STDMETHODIMP_(ULONG) CDelegateFolderEnum::Release()
- {
- if (InterlockedDecrement(&_cRef))
- return _cRef;
- delete this;
- return 0;
- }
- //-----------------------------------------------------------------------------
- // IEnumIDList
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolderEnum::Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
- {
- HRESULT hr = S_FALSE;
- ULONG ulDummy;
- if (pceltFetched == NULL)
- pceltFetched = &ulDummy;
- *pceltFetched = 0; // nothing has been returned yet
- // whilst we have an enumerator and there have been no items returned
- // lets go around to see how many objects we should be removing.
- while ( !*pceltFetched )
- {
- // no enumerator, lets see if we can get an instance of the next
- // one to enumerate from.
- if ( !_pCurrentEnum )
- {
- while ( _index < DPA_GetPtrCount(_dpaFolders) )
- {
- IShellFolder* pShellFolder = (IShellFolder*)DPA_GetPtr(_dpaFolders, _index++);
- ASSERT(pShellFolder);
- if ( SUCCEEDED(pShellFolder->EnumObjects(_hwnd, _grfFlags, &_pCurrentEnum)) )
- break;
- }
- if ( !_pCurrentEnum )
- break;
- }
- // do we have an enumerator now? if so then lets call it and return the items back
- // to the caller.
- if ( _pCurrentEnum )
- {
- hr = _pCurrentEnum->Next(celt, rgelt, pceltFetched);
- if ( hr == S_FALSE )
- {
- _pCurrentEnum->Release();
- _pCurrentEnum = NULL;
- if ( !*pceltFetched )
- continue;
- }
- break;
- }
- }
- return hr;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolderEnum::Skip(ULONG celt)
- {
- return E_NOTIMPL;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolderEnum::Reset(THIS)
- {
- // lets start the enumeration process again, so set the index back to the head
- // and release the enumerator we are currently using.
- _index = 0;
- ATOMICRELEASE(_pCurrentEnum);
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- STDMETHODIMP CDelegateFolderEnum::Clone(IEnumIDList **ppenum)
- {
- return E_NOTIMPL;
- }
- //-----------------------------------------------------------------------------
- // This code used to be in shdocvw, it is the implementation of a IMalloc for handling
- // delegate folder items
- //-----------------------------------------------------------------------------
- class CDelagateMalloc : public IMalloc
- {
- public:
- // IUnknown
- virtual STDMETHODIMP QueryInterface(REFIID,void **);
- virtual STDMETHODIMP_(ULONG) AddRef(void);
- virtual STDMETHODIMP_(ULONG) Release(void);
- // IMalloc
- virtual STDMETHODIMP_(LPVOID) Alloc(ULONG cb);
- virtual STDMETHODIMP_(LPVOID) Realloc(void *pv, ULONG cb);
- virtual STDMETHODIMP_(void) Free(void *pv);
- virtual STDMETHODIMP_(ULONG) GetSize(void *pv);
- virtual STDMETHODIMP_(int) DidAlloc(void *pv);
- virtual STDMETHODIMP_(void) HeapMinimize();
- private:
- CDelagateMalloc(void *pv, UINT cbSize, WORD wOuter);
- ~CDelagateMalloc();
- void* operator new(size_t cbClass, UINT cbSize);
- friend HRESULT CDelegateMalloc_Create(void *pv, UINT cbSize, WORD wOuter, IMalloc **ppmalloc);
- protected:
- LONG _cRef;
- WORD _wOuter; // delegate item outer signature
- WORD _wUnused; // to allign
- #ifdef DEBUG
- UINT _cAllocs;
- #endif
- UINT _cb;
- BYTE _data[];
- };
- void* CDelagateMalloc::operator new(size_t cbClass, UINT cbSize)
- {
- return ::operator new(cbClass + cbSize);
- }
- CDelagateMalloc::CDelagateMalloc(void *pv, UINT cbSize, WORD wOuter)
- {
- _cRef = 1;
- _wOuter = wOuter;
- _cb = cbSize;
- memcpy(_data, pv, _cb);
- }
- CDelagateMalloc::~CDelagateMalloc()
- {
- DEBUG_CODE( TraceMsg(DM_TRACE, "DelegateMalloc destroyed with %d allocs performed", _cAllocs); )
- }
- HRESULT CDelagateMalloc::QueryInterface(REFIID riid, void **ppv)
- {
- static const QITAB qit[] = {
- QITABENT(CDelagateMalloc, IMalloc), // IID_IMalloc
- { 0 },
- };
- return QISearch(this, qit, riid, ppv);
- }
- ULONG CDelagateMalloc::AddRef()
- {
- return InterlockedIncrement(&_cRef);
- }
- ULONG CDelagateMalloc::Release()
- {
- if (InterlockedDecrement(&_cRef))
- return _cRef;
- delete this;
- return 0;
- }
- void *CDelagateMalloc::Alloc(ULONG cb)
- {
- WORD cbActualSize = (WORD)(
- SIZEOF(DELEGATEITEMID) - 1 + // header (-1 sizeof(rgb[0])
- cb + // inner
- _cb); // outer data
- PDELEGATEITEMID pidl = (PDELEGATEITEMID)SHAlloc(cbActualSize + 2); // +2 for pidl term
- if (pidl)
- {
- pidl->cbSize = cbActualSize;
- pidl->wOuter = _wOuter;
- pidl->cbInner = (WORD)cb;
- memcpy(&pidl->rgb[cb], _data, _cb);
- *(WORD *)&(((BYTE *)pidl)[cbActualSize]) = 0;
- #ifdef DEBUG
- _cAllocs++;
- #endif
- }
- return pidl;
- }
- void *CDelagateMalloc::Realloc(void *pv, ULONG cb)
- {
- return NULL;
- }
- void CDelagateMalloc::Free(void *pv)
- {
- SHFree(pv);
- }
- ULONG CDelagateMalloc::GetSize(void *pv)
- {
- return (ULONG)-1;
- }
- int CDelagateMalloc::DidAlloc(void *pv)
- {
- return -1;
- }
- void CDelagateMalloc::HeapMinimize()
- {
- }
- STDAPI CDelegateMalloc_Create(void *pv, UINT cbSize, WORD wOuter, IMalloc **ppmalloc)
- {
- CDelagateMalloc *pdm = new(cbSize) CDelagateMalloc(pv, cbSize, wOuter);
- if (pdm)
- {
- HRESULT hres = pdm->QueryInterface(IID_IMalloc, (void **)ppmalloc);
- pdm->Release();
- return hres;
- }
- return E_OUTOFMEMORY;
- }