|
|
#include "shellprv.h"
#include "treewkcb.h"
#include "propsht.h"
CBaseTreeWalkerCB::CBaseTreeWalkerCB(): _cRef(1) { }
CBaseTreeWalkerCB::~CBaseTreeWalkerCB() { }
HRESULT CBaseTreeWalkerCB::QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CBaseTreeWalkerCB, IShellTreeWalkerCallBack), { 0 }, }; return QISearch(this, qit, riid, ppv); }
ULONG CBaseTreeWalkerCB::AddRef() { return InterlockedIncrement(&_cRef); }
ULONG CBaseTreeWalkerCB::Release() { if (InterlockedDecrement(&_cRef)) return _cRef;
delete this; return 0; }
HRESULT CBaseTreeWalkerCB::FoundFile(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd) { return E_NOTIMPL; }
HRESULT CBaseTreeWalkerCB::EnterFolder(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd) { return E_NOTIMPL; }
HRESULT CBaseTreeWalkerCB::LeaveFolder(LPCWSTR pwszPath, TREEWALKERSTATS *ptws) { return E_NOTIMPL; }
HRESULT CBaseTreeWalkerCB::HandleError(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, HRESULT ErrorCode) { return E_NOTIMPL; }
//
// Folder size computation tree walker callback class
//
class CFolderSizeTreeWalkerCB : public CBaseTreeWalkerCB { public: CFolderSizeTreeWalkerCB(FOLDERCONTENTSINFO * pfci);
// IShellTreeWalkerCallBack
STDMETHODIMP FoundFile(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd); STDMETHODIMP EnterFolder(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd);
protected: FOLDERCONTENTSINFO * _pfci; TREEWALKERSTATS _twsInitial; };
CFolderSizeTreeWalkerCB::CFolderSizeTreeWalkerCB(FOLDERCONTENTSINFO * pfci): _pfci(pfci) { // set the starting values for the twsInitial so we can have cumulative results
_twsInitial.nFiles = _pfci->cFiles; _twsInitial.nFolders = _pfci->cFolders; _twsInitial.ulTotalSize = _pfci->cbSize; _twsInitial.ulActualSize = _pfci->cbActualSize; }
HRESULT CFolderSizeTreeWalkerCB::FoundFile(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd) { if (_pfci->bContinue) { _pfci->cbSize = _twsInitial.ulTotalSize + ptws->ulTotalSize; _pfci->cbActualSize = _twsInitial.ulActualSize + ptws->ulActualSize; _pfci->cFiles = _twsInitial.nFiles + ptws->nFiles; } return _pfci->bContinue ? S_OK : E_FAIL; }
HRESULT CFolderSizeTreeWalkerCB::EnterFolder(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd) { if (_pfci->bContinue) { _pfci->cFolders = _twsInitial.nFolders + ptws->nFolders; } return _pfci->bContinue ? S_OK : E_FAIL; }
//
// Main function for folder size computation
//
STDAPI FolderSize(LPCTSTR pszDir, FOLDERCONTENTSINFO *pfci) { HRESULT hrInit = SHCoInitialize(); // in case our caller did not do this
HRESULT hr = E_FAIL; CFolderSizeTreeWalkerCB *pfstwcb = new CFolderSizeTreeWalkerCB(pfci); if (pfstwcb) { IShellTreeWalker *pstw; hr = CoCreateInstance(CLSID_CShellTreeWalker, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellTreeWalker, &pstw)); if (SUCCEEDED(hr)) { hr = pstw->WalkTree(WT_NOTIFYFOLDERENTER, pszDir, NULL, 0, SAFECAST(pfstwcb, IShellTreeWalkerCallBack *)); pstw->Release(); } pfstwcb->Release(); }
SHCoUninitialize(hrInit); return hr; }
|