Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.3 KiB

  1. #include "shellprv.h"
  2. #include "treewkcb.h"
  3. #include "propsht.h"
  4. CBaseTreeWalkerCB::CBaseTreeWalkerCB(): _cRef(1)
  5. {
  6. }
  7. CBaseTreeWalkerCB::~CBaseTreeWalkerCB()
  8. {
  9. }
  10. HRESULT CBaseTreeWalkerCB::QueryInterface(REFIID riid, void **ppv)
  11. {
  12. static const QITAB qit[] = {
  13. QITABENT(CBaseTreeWalkerCB, IShellTreeWalkerCallBack),
  14. { 0 },
  15. };
  16. return QISearch(this, qit, riid, ppv);
  17. }
  18. ULONG CBaseTreeWalkerCB::AddRef()
  19. {
  20. return InterlockedIncrement(&_cRef);
  21. }
  22. ULONG CBaseTreeWalkerCB::Release()
  23. {
  24. if (InterlockedDecrement(&_cRef))
  25. return _cRef;
  26. delete this;
  27. return 0;
  28. }
  29. HRESULT CBaseTreeWalkerCB::FoundFile(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd)
  30. {
  31. return E_NOTIMPL;
  32. }
  33. HRESULT CBaseTreeWalkerCB::EnterFolder(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd)
  34. {
  35. return E_NOTIMPL;
  36. }
  37. HRESULT CBaseTreeWalkerCB::LeaveFolder(LPCWSTR pwszPath, TREEWALKERSTATS *ptws)
  38. {
  39. return E_NOTIMPL;
  40. }
  41. HRESULT CBaseTreeWalkerCB::HandleError(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, HRESULT ErrorCode)
  42. {
  43. return E_NOTIMPL;
  44. }
  45. //
  46. // Folder size computation tree walker callback class
  47. //
  48. class CFolderSizeTreeWalkerCB : public CBaseTreeWalkerCB
  49. {
  50. public:
  51. CFolderSizeTreeWalkerCB(FOLDERCONTENTSINFO * pfci);
  52. // IShellTreeWalkerCallBack
  53. STDMETHODIMP FoundFile(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd);
  54. STDMETHODIMP EnterFolder(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd);
  55. protected:
  56. FOLDERCONTENTSINFO * _pfci;
  57. TREEWALKERSTATS _twsInitial;
  58. };
  59. CFolderSizeTreeWalkerCB::CFolderSizeTreeWalkerCB(FOLDERCONTENTSINFO * pfci): _pfci(pfci)
  60. {
  61. // set the starting values for the twsInitial so we can have cumulative results
  62. _twsInitial.nFiles = _pfci->cFiles;
  63. _twsInitial.nFolders = _pfci->cFolders;
  64. _twsInitial.ulTotalSize = _pfci->cbSize;
  65. _twsInitial.ulActualSize = _pfci->cbActualSize;
  66. }
  67. HRESULT CFolderSizeTreeWalkerCB::FoundFile(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd)
  68. {
  69. if (_pfci->bContinue)
  70. {
  71. _pfci->cbSize = _twsInitial.ulTotalSize + ptws->ulTotalSize;
  72. _pfci->cbActualSize = _twsInitial.ulActualSize + ptws->ulActualSize;
  73. _pfci->cFiles = _twsInitial.nFiles + ptws->nFiles;
  74. }
  75. return _pfci->bContinue ? S_OK : E_FAIL;
  76. }
  77. HRESULT CFolderSizeTreeWalkerCB::EnterFolder(LPCWSTR pwszPath, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd)
  78. {
  79. if (_pfci->bContinue)
  80. {
  81. _pfci->cFolders = _twsInitial.nFolders + ptws->nFolders;
  82. }
  83. return _pfci->bContinue ? S_OK : E_FAIL;
  84. }
  85. //
  86. // Main function for folder size computation
  87. //
  88. STDAPI FolderSize(LPCTSTR pszDir, FOLDERCONTENTSINFO *pfci)
  89. {
  90. HRESULT hrInit = SHCoInitialize(); // in case our caller did not do this
  91. HRESULT hr = E_FAIL;
  92. CFolderSizeTreeWalkerCB *pfstwcb = new CFolderSizeTreeWalkerCB(pfci);
  93. if (pfstwcb)
  94. {
  95. IShellTreeWalker *pstw;
  96. hr = CoCreateInstance(CLSID_CShellTreeWalker, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellTreeWalker, &pstw));
  97. if (SUCCEEDED(hr))
  98. {
  99. hr = pstw->WalkTree(WT_NOTIFYFOLDERENTER, pszDir, NULL, 0, SAFECAST(pfstwcb, IShellTreeWalkerCallBack *));
  100. pstw->Release();
  101. }
  102. pfstwcb->Release();
  103. }
  104. SHCoUninitialize(hrInit);
  105. return hr;
  106. }