/**************************************************************************
THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Author: S.Nandagopal 16 March 2003
**************************************************************************/
//---------------------------------------------------------------------------
// Description: Defines CWalker template class.
#include <windows.h>
#include <string>
#include <iostream.h>
#import "msxml3.dll"
enum
{
fail = 0,
success = 1,
stopped = 2
};
class CFolderContext
{
public:
// Required types
//
typedef std::string ContextIdentifierType;
typedef std::string ContentFilterType;
CFolderContext()
{}
CFolderContext(const CFolderContext& o)
{
*this = o;
}
CFolderContext& operator = (const CFolderContext& o)
{
}
// Required interface
//
class CItem
{
public:
// Required function
//
bool IsAContext() const
{
return fileInfo.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY;
}
WIN32_FIND_DATA& GetInfo()
{
return fileInfo;
}
const WIN32_FIND_DATA& GetInfo() const
{
return fileInfo;
}
private:
WIN32_FIND_DATA fileInfo;
};
// Required interface
// All the public methods are required
//
class COpenContext
{
public:
COpenContext(const ContextIdentifierType& context,const ContentFilterType& filter)
{
m_context = context;
std::string szToSearchFor = context;
if(!filter.empty())
szToSearchFor += "\\" + filter;
m_hFind = ::FindFirstFile(szToSearchFor.data(),&m_folderItem.GetInfo());
}
~COpenContext()
{
if(m_hFind!=INVALID_HANDLE_VALUE) ::FindClose(m_hFind);
}
const CItem* GetNext()
{
if(m_hFind==INVALID_HANDLE_VALUE) return 0;
if(!::FindNextFile(m_hFind,&m_folderItem.GetInfo()))
return 0;
return &m_folderItem;
}
const CItem* Get() const
{
if(m_hFind==INVALID_HANDLE_VALUE) return 0;
return &m_folderItem;
}
bool GetNewContextId(ContextIdentifierType& newId) const
{
if(m_folderItem.IsAContext())
{
newId = m_context + "\\" + m_folderItem.GetInfo().cFileName;
return true;
}
return false;
}
private:
CItem m_folderItem;
HANDLE m_hFind;
ContextIdentifierType m_context;
COpenContext(const COpenContext&);
COpenContext& operator = (const COpenContext&);
};
// Required method
//
static bool IsReserved(const CItem& item)
{
if(std::string(".")==item.GetInfo().cFileName || std::string("..")==item.GetInfo().cFileName) return true;
return false;
}
};
//************************** CWalker template *************************************
//
// Description: Takes two template arguments, UserDataTypeT, on which there are no
// restrictions, and ContextTypeT which, will have to comply to an interface.
//
template <class UserDataTypeT,class ContextTypeT>
class CWalker
{
public:
typedef ContextTypeT ContextType;
typedef UserDataTypeT UserDataType;
typedef CWalker<UserDataType,ContextType> MyType;
CWalker():m_bStopped(false)
{}
int Walk(UserDataType userData,
const ContextType::ContextIdentifierType& iContext
)
{
ContextType::ContentFilterType filter = m_filter;
int nRet = WalkI(userData,iContext,filter,m_bStopped);
m_bStopped = false;
return nRet;
}
void SetContentFilter(const ContextType::ContentFilterType& filter)
{
m_filter = filter;
}
void StopWalking()
{
m_bStopped = true;
}
private:
int WalkI(UserDataType userData,
const ContextType::ContextIdentifierType& iContext,
const ContextType::ContentFilterType& filter,
bool& bStopped
)
{
if(bStopped) return stopped;
ContextType::COpenContext openContext(iContext,filter);
const ContextType::CItem *item = openContext.Get();
if(!item) return fail;
if(!item->IsAContext())
{
this->OnItemFound(userData,*item,iContext);
}
else
{
if(!ContextType::IsReserved(*item))
{
ContextType::ContextIdentifierType newContext;
openContext.GetNewContextId(newContext);
if(this->OnContextChange(&userData,*item,newContext,true))
{
WalkI(userData,newContext,filter,bStopped);
if(bStopped) return stopped;
this->OnContextChange(&userData,*item,iContext,false);
}
}
else this->OnItemFound(userData,*item,iContext);
}
while(true)
{
if(bStopped) return stopped;
const ContextType::CItem *item = openContext.GetNext();
if(!item)
break;
if(!item->IsAContext())
{
this->OnItemFound(userData,*item,iContext);
}
else
{
if(!ContextType::IsReserved(*item))
{
ContextType::ContextIdentifierType newContext;
openContext.GetNewContextId(newContext);
if(this->OnContextChange(&userData,*item,newContext,true))
{
WalkI(userData,newContext,filter,bStopped);
if(bStopped) return stopped;
this->OnContextChange(&userData,*item,iContext,false);
}
}
else this->OnItemFound(userData,*item,iContext);
}
}
return success;
}
ContextType::ContentFilterType m_filter;
virtual bool OnContextChange(UserDataType*,const ContextType::CItem&,const ContextType::ContextIdentifierType&,bool bMovedToNewOrBackToOld)
{
return false;
}
virtual void OnItemFound(UserDataType,const ContextType::CItem&,const ContextType::ContextIdentifierType&)
{
}
bool m_bStopped;
};
class CMyFolderWalker:public CWalker<void*,CFolderContext>
{
public:
CMyFolderWalker(bool bSurfaceWalk):m_bSurfaceWalk(bSurfaceWalk)
{}
void SetFileToFind(const std::string& szFileToFind)
{
m_szFileToBeFound = szFileToFind;
}
private:
bool OnContextChange(void**,const CFolderContext::CItem& item,const CFolderContext::ContextIdentifierType& szFolderPathAndName,bool bMovedToNewOrBackToOld)
{
if(bMovedToNewOrBackToOld)
{
cout << szTabs.data() << "****** folder " << szFolderPathAndName.data() << "******\n";
szTabs += "\t";
return !m_bSurfaceWalk;
}
else
{
szTabs.erase(szTabs.length()-1);
cout << szTabs.data() << "************************************************\n";
}
return false;
}
void OnItemFound(void*,const CFolderContext::CItem& item,const CFolderContext::ContextIdentifierType& szPath)
{
std::string szTabsToUse = szTabs;
if(!szTabsToUse.empty()) szTabsToUse.erase(szTabs.length()-1);
cout << szTabsToUse.data() << "#### file #### " << item.GetInfo().cFileName << "\n";
if(m_szFileToBeFound==item.GetInfo().cFileName)
{
cout << "$$$$$ File Found $$$$$\n";
this->StopWalking();
}
}
bool m_bSurfaceWalk;
std::string szTabs;
std::string m_szFileToBeFound;
};
int main(int argc, char* argv[])
{
CMyFolderWalker folderWalker(false);
folderWalker.SetContentFilter("*.*");
folderWalker.SetFileToFind("gsdll32.dll");
folderWalker.Walk(0,"D:\\gs");
return 0;
}