Пример #1
0
/**
Processes the core image file to produce a directory tree.

@return KErrNone for successful read or error number if failed 
*/
TInt CCoreImage::ProcessImage()
	{
	iRomFileName = iReader->Filename();
	int result = CreateRootDir();
	if (result == KErrNone)
		{
		if (iReader->Open())
			{
			RCoreImageReader::TImageType imageType = iReader->ReadImageType();
			if (imageType == RCoreImageReader::E_ROFS)
				{
				TRofsHeader header;
				result = iReader->ReadCoreHeader(header);
				if (result == KErrNone)
					{
					SaveDirInfo(header);
					result = ProcessDirectory(0);
					}
				}
			else
				result = KErrNotSupported;
			}
		else
			result = KErrGeneral;
		}
	return result;
	}
Пример #2
0
void ProcessDirectory(char *szPath)
{
    char szCurPath[MAX_PATH];
    intptr_t hFind;
    __finddata64_t fd;

    strcpy(szCurPath, szPath);
    strcat(szCurPath, "\\*.*");
    hFind = _findfirst64(szCurPath, &fd);
    if (hFind == -1)
        return;

    do
    {
        if (fd.attrib & _A_SUBDIR)
        {
            if (strcmp(fd.name, ".") && strcmp(fd.name, ".."))
            {
                sprintf(szCurPath, "%s\\%s", szPath, fd.name);
                ProcessDirectory(szCurPath);
            }
        }
        else
        {
            sprintf(szCurPath, "%s\\%s", szPath, fd.name);
            ProcessFile(szCurPath);
        }
    } while (_findnext64(hFind, &fd) != -1);

    _findclose(hFind);
}
Пример #3
0
void
InventoryEngine::ProcessDirectory(const char* name, int level)
{
	DIR* dir = opendir(name);
	if (dir == NULL)
		return;
	struct dirent* entry = readdir(dir);

	do {
		char cwpath[PATH_MAX];
		int len = snprintf(cwpath, sizeof(cwpath) - 1,
			"%s/%s", name, entry->d_name);
		cwpath[len] = 0;

		if (entry->d_type == DT_DIR) {
			if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
				continue;
			ProcessDirectory(cwpath, level + 1);
		} else {
			char hash[SHA_LENGTH_MAX];
			if (!GenerateSHA(cwpath, hash)) {
				continue;
			} else {
				fBaselineStore->Add(cwpath, hash);
			}
		}
	} while (entry = readdir(dir));
}
Пример #4
0
DWORD CDirWatcher::Run()
{
	int delay = 0;

	ReadIgnoreList();

	for(;;) {
		if(CNewzflow::Instance()->IsShuttingDown() || WaitForSingleObject(shutDown, 0) == WAIT_OBJECT_0)
			break;

		if(delay > 0) {
			WaitForSingleObject(shutDown, delay * 1000); // either waits until the delay ran out, or we need to shut down
			delay = 0;
			continue;
		}

		ProcessDirectory(CNewzflow::Instance()->settings->GetWatchDir());

		delay = 5;
	}

	WriteIgnoreList();

	return 0;
}
Пример #5
0
void DeleteRecursive(LPCTSTR target, wregex* ignorePattern)
{
	if (!Utilities::DirectoryExists(target))
	{
		CString message;
		message.Format(TEXT("Cannot delete directory %s because it does not exist. Proceeding anyway."),
			target);
		OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);
		return;
	}

	CDeleteAction deleteAction(target);
	ProcessDirectory(target, deleteAction, TEXT(""), true, ignorePattern);
}
Пример #6
0
/**
* Recursively processes directory structure, storing the relative path to each file found.
*/
void CDiskResource::ProcessDirectory(std::wstring path)
{
	// Determine the package-relative resource path.
	std::wstring findPath(m_path);
	if (path.length() > 0)
		findPath.append(std::wstring(_T("\\"))).append(path);

	std::wstring search(findPath);
	search.append(_T("\\*"));
	WIN32_FIND_DATA fd;	
	HANDLE ff = FindFirstFile(search.c_str(),&fd);

	if (ff != INVALID_HANDLE_VALUE)
	{
		do
		{
			if (_tcscmp(fd.cFileName,_T(".")) != 0 && _tcscmp(fd.cFileName,_T("..")) != 0 && _tcscmp(fd.cFileName,_T(".svn")) != 0)
			{
				std::wstring foundPath(path);
				if (foundPath.length() > 0)
					foundPath.append(_T("\\")).append(fd.cFileName);
				else
					foundPath = fd.cFileName;

				if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
				{
					// Recurse into this sub-directory.
					ProcessDirectory(foundPath);
				}
				else 
				{
					m_files.push_back(foundPath);
				}
			}
		}
		while (FindNextFile(ff,&fd) != 0);

		FindClose(ff);
	}
}
Пример #7
0
INT CommandDelete (LPTSTR param)
{
	/*cmd is the command that was given, in this case it will always be "del" or "delete"
	param is whatever is given after the command*/

	LPTSTR *arg = NULL;
	INT args;
	INT i;
	INT   nEvalArgs = 0; /* nunber of evaluated arguments */
	DWORD dwFlags = 0;
	DWORD dwAttrFlags = 0;
	DWORD dwFiles = 0;
	LONG ch;
	TCHAR szOrginalArg[MAX_PATH];

	/*checks the first two chars of param to see if it is /?
	this however allows the following command to not show help
	"del frog.txt /?" */

        if (!StringsLoaded)
        {
                LoadStrings();
        }

	if (!_tcsncmp (param, _T("/?"), 2))
	{
		ConOutResPaging(TRUE,STRING_DEL_HELP1);
		return 0;
	}

	nErrorLevel = 0;

	arg = split (param, &args, FALSE);

	if (args == 0)
	{
		/* only command given */
		error_req_param_missing ();
		freep (arg);
		return 1;
	}
	/* check for options anywhere in command line */
	for (i = 0; i < args; i++)
	{
		if (*arg[i] == _T('/'))
		{
			/*found a command, but check to make sure it has something after it*/
			if (_tcslen (arg[i]) >= 2)
			{
				ch = _totupper (arg[i][1]);
				if (ch == _T('N'))
				{
					dwFlags |= DEL_NOTHING;
				}
				else if (ch == _T('P'))
				{
					dwFlags |= DEL_PROMPT;
				}
				else if (ch == _T('Q'))
				{
					dwFlags |= DEL_QUIET;
				}
				else if (ch == _T('F'))
				{
					dwFlags |= DEL_FORCE;
				}
				else if (ch == _T('S'))
				{
					dwFlags |= DEL_SUBDIR;
				}
				else if (ch == _T('T'))
				{
					dwFlags |= DEL_TOTAL;
				}
				else if (ch == _T('W'))
				{
					dwFlags |= DEL_WIPE;
				}
				else if (ch == _T('Y'))
				{
					dwFlags |= DEL_YES;
				}
				else if (ch == _T('A'))
				{

					dwFlags |= DEL_ATTRIBUTES;
					/*the proper syntax for /A has a min of 4 chars
					i.e. /A:R or /A:-H */
					if (_tcslen (arg[i]) < 4)
					{
						error_invalid_parameter_format(arg[i]);
						return 0;
					}
					ch = _totupper (arg[i][3]);
					if (_tcslen (arg[i]) == 4)
					{
						if(ch == _T('A'))
						{
							dwAttrFlags |= ATTR_ARCHIVE;
						}
						if(ch == _T('H'))
						{
							dwAttrFlags |= ATTR_HIDDEN;
						}
						if(ch == _T('S'))
						{
							dwAttrFlags |= ATTR_SYSTEM;
						}
						if(ch == _T('R'))
						{
							dwAttrFlags |= ATTR_READ_ONLY;
						}
					}
					if (_tcslen (arg[i]) == 5)
					{
						if(ch == _T('-'))
						{
							ch = _totupper (arg[i][4]);
							if(ch == _T('A'))
							{
								dwAttrFlags |= ATTR_N_ARCHIVE;
							}
							if(ch == _T('H'))
							{
								dwAttrFlags |= ATTR_N_HIDDEN;
							}
							if(ch == _T('S'))
							{
								dwAttrFlags |= ATTR_N_SYSTEM;
							}
							if(ch == _T('R'))
							{
								dwAttrFlags |= ATTR_N_READ_ONLY;
							}
						}
					}
				}
			}

			nEvalArgs++;
		}
	}

	/* there are only options on the command line --> error!!!
	there is the same number of args as there is flags, so none of the args were filenames*/
	if (args == nEvalArgs)
	{
		error_req_param_missing ();
		freep (arg);
		return 1;
	}

	/* keep quiet within batch files */
	if (bc != NULL)
		dwFlags |= DEL_QUIET;

	/* check for filenames anywhere in command line */
	for (i = 0; i < args && !(dwFiles & 0x80000000); i++)
	{

                /*this checks to see if it isnt a flag, if it isnt, we assume it is a file name*/
		if((*arg[i] == _T('/')) || (*arg[i] == _T('-')))
			continue;

		/* We want to make a copies of the argument */
		if(_tcslen(arg[i]) == 2 && arg[i][1] == _T(':'))
		{
			/* Check for C: D: ... */
			GetRootPath(arg[i],szOrginalArg,MAX_PATH);
		}
		else
		{
			_tcscpy(szOrginalArg,arg[i]);
		}
                dwFiles += ProcessDirectory(szOrginalArg, &dwFlags, dwAttrFlags);

        }

	freep (arg);

	/*Based on MS cmd, we only tell what files are being deleted when /S is used */
	if (dwFlags & DEL_TOTAL)
	{
                dwFiles &= 0x7fffffff;
		if (dwFiles < 2)
		{
                        ConOutResPrintf(STRING_DEL_HELP3, dwFiles);
		}
		else
		{
			ConOutResPrintf(STRING_DEL_HELP4, dwFiles);
		}
	}

	return 0;
}
Пример #8
0
static DWORD
ProcessDirectory(LPTSTR FileName, DWORD* dwFlags, DWORD dwAttrFlags)
{
        TCHAR szFullPath[MAX_PATH];
        LPTSTR pFilePart;
        LPTSTR pSearchPart;
        HANDLE hFile;
        WIN32_FIND_DATA f;
        DWORD dwFiles = 0;

        GetFullPathName (FileName,
                         MAX_PATH,
                         szFullPath,
                         &pFilePart);

        dwFiles = DeleteFiles(szFullPath, dwFlags, dwAttrFlags);
        if (dwFiles & 0x80000000)
                return dwFiles;

        if (*dwFlags & DEL_SUBDIR)
        {
	        /* Get just the file name */
	        pSearchPart = _tcsrchr(FileName,_T('\\'));
	        if(pSearchPart != NULL)
		        pSearchPart++;
	        else
		        pSearchPart = FileName;

	        /* Get the full path to the file */
	        GetFullPathName (FileName,MAX_PATH,szFullPath,NULL);

	        /* strip the filename off of it */
                pFilePart = _tcsrchr(szFullPath, _T('\\'));
                if (pFilePart == NULL)
                {
                        pFilePart = szFullPath;
                }
                else
                {
                        pFilePart++;
                }

                _tcscpy(pFilePart, _T("*"));

                hFile = FindFirstFile(szFullPath, &f);
                if (hFile != INVALID_HANDLE_VALUE)
                {
                        do
                        {
       		                if (!(f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
                                    !_tcscmp(f.cFileName, _T(".")) ||
                                    !_tcscmp(f.cFileName, _T("..")))
		                        continue;

                                _tcscpy(pFilePart, f.cFileName);
                                _tcscat(pFilePart, _T("\\"));
                                _tcscat(pFilePart, pSearchPart);

                                dwFiles +=ProcessDirectory(szFullPath, dwFlags, dwAttrFlags);
                                if (dwFiles & 0x80000000)
                                {
                                    break;
                                }
                        }
                        while (FindNextFile (hFile, &f));
	                FindClose (hFile);
                }
        }
        return dwFiles;
}
Пример #9
0
//--------------------------------------------------------------------
//
// ProcessDirectory
// 
// Recursive routine that passes files to the delete function.
//
//--------------------------------------------------------------------
void ProcessDirectory( TCHAR *PathName, TCHAR *SearchPattern )
{
	TCHAR			subName[MAX_PATH], fileSearchName[MAX_PATH], searchName[MAX_PATH];
	HANDLE			dirHandle, patternHandle;
	static BOOLEAN	firstCall = TRUE;
	static BOOLEAN  deleteDirectories = FALSE;
	WIN32_FIND_DATA foundFile;

	//
	// Scan the files and/or directories if this is a directory
	//
	if( firstCall ) {

		if( _tcsrchr( PathName, '*' ) ) {
	
            if( _tcsrchr( PathName, '\\' ) ) {

                _stprintf( SearchPattern, _tcsrchr( PathName, '\\' )+1 );
                _tcscpy( searchName, PathName );
                _tcscpy( _tcsrchr( searchName, '\\')+1, _T("*.*") );
				if( !_tcscmp( SearchPattern, _T("*.*")) ||
					!_tcscmp( SearchPattern, _T("*"))) {

					deleteDirectories = TRUE;
				}

            } else {
                
                _stprintf( SearchPattern, PathName );
                _tcscpy( searchName, PathName );
            }
            _stprintf( fileSearchName, _T("%s"), PathName );

		} else {

			_stprintf( SearchPattern, _T("*.*") );
			_stprintf( searchName, _T("%s"), PathName );
            _stprintf( fileSearchName, _T("%s"), PathName );
			deleteDirectories = TRUE;
		}

	} else {

		_stprintf( searchName, _T("%s\\*.*"), PathName );
		_stprintf( fileSearchName, _T("%s\\%s"), PathName, SearchPattern );
	}

	//
	// Process all the files, according to the search pattern
	//
	if( (patternHandle = FindFirstFile( fileSearchName, &foundFile )) != 
		INVALID_HANDLE_VALUE  ) {

		do {

			if( _tcscmp( foundFile.cFileName, _T(".") ) &&
				_tcscmp( foundFile.cFileName, _T("..") )) {

				_tcscpy( subName, searchName );
				if( _tcsrchr( subName, '\\' ) ) 
					_tcscpy( _tcsrchr( subName, '\\')+1, foundFile.cFileName );
				else
					_tcscpy( subName, foundFile.cFileName );

				//
				// Do this file/directory
				//
				ProcessFile( &foundFile, subName );
			}
		} while( FindNextFile( patternHandle, &foundFile ));
		FindClose( patternHandle );
	}

	//
	// Now recurse if we're supposed to
	//
	if( Recurse ) {

        if( firstCall && !_tcsrchr( searchName, L'\\') ) {

            if( _tcsrchr( searchName, L'*' )) {

                if( (dirHandle = FindFirstFile( _T("*.*"), &foundFile )) == 
                    INVALID_HANDLE_VALUE  ) {

                    //
                    // Nothing to process
                    //
                    return;
                }
            } else {

                if( (dirHandle = FindFirstFile( searchName, &foundFile )) == 
                    INVALID_HANDLE_VALUE  ) {

                    //
                    // Nothing to process
                    //
                    return;
                }
            }
        } else {

            if( (dirHandle = FindFirstFile( searchName, &foundFile )) == 
                INVALID_HANDLE_VALUE  ) {

                //
                // Nothing to process
                //
                return;
            }
        }
        firstCall = FALSE;

		do {

			if( (foundFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
				_tcscmp( foundFile.cFileName, _T(".") ) &&
				_tcscmp( foundFile.cFileName, _T("..") )) {

				_tcscpy( subName, searchName );
				if( _tcsrchr( subName, '\\' ) ) 
					_tcscpy( _tcsrchr( subName, '\\')+1, foundFile.cFileName );
				else
					_tcscpy( subName, foundFile.cFileName );

				//
				// Go into this directory
				//
				ProcessDirectory( subName, SearchPattern );

				//
				// Delete the directory if we're supposed to
				//
				if( deleteDirectories ) {

					if( !RemoveDirectory( subName )) {

						_tprintf( _T("\nError deleting %s: "), subName );
						PrintWin32Error( GetLastError() );
					}
				}
			}

		} while( FindNextFile( dirHandle, &foundFile ));
		FindClose( dirHandle );
	}
}
Пример #10
0
//--------------------------------------------------------------------
//
// Main
//
// Runs the show. 
//
//--------------------------------------------------------------------
int _tmain( int argc, TCHAR *argv[] ) 
{
    TCHAR       searchPattern[MAX_PATH];
	TCHAR		searchPath[MAX_PATH];
	PTCHAR		filePart;
	BOOL		foundFileArg = FALSE;
	int			i;

    //
    // Print banner and perform parameter check
    //
    _tprintf(_T("\nSDelete - Secure Delete v1.51\n") );
    _tprintf(_T("Copyright (C) 1999-2005 Mark Russinovich\n"));
    _tprintf(_T("Sysinternals - www.sysinternals.com\n\n"));

    if( argc < 2 ) {

        return Usage( argv[0] );
    }

    for( i = 1; i < argc; i++ ) {

	    if( !_tcsicmp( argv[i], _T("/s") ) ||
			!_tcsicmp( argv[i], _T("-s") )) {

			Recurse = TRUE;

		} else if( !_tcsicmp( argv[i], _T("/q") ) ||
				   !_tcsicmp( argv[i], _T("-q") )) {

			Silent = TRUE;

		} else if( !_tcsicmp( argv[i], _T("/z") ) ||
				   !_tcsicmp( argv[i], _T("-z") )) {

			ZapFreeSpace = TRUE;

		} else if( !_tcsicmp( argv[i], _T("/c") ) ||
				   !_tcsicmp( argv[i], _T("-c") )) {

			ZapFreeSpace = TRUE;
			ZeroFreeSpace = TRUE;

		} else if( !_tcsicmp( argv[i], _T("/p") ) ||
				   !_tcsicmp( argv[i], _T("-p") )) {

			NumPasses = argc > i ? atoi( argv[i+1] ) : 1;
			if( !NumPasses ) return Usage( argv[0] );
			i++;

		} else if( !_tcsicmp( argv[i], _T("/?") ) ||
				   !_tcsicmp( argv[i], _T("-?") )) {
				   
			return Usage( argv[0] );

		} else {

			if( foundFileArg ) return Usage( argv[0] );
			foundFileArg = TRUE;
		}
    }

	//
	// Have to have file if not zapping free space
	//
	if( !ZapFreeSpace && !foundFileArg ) {

		return Usage( argv[0] );
	}

	//
	// Locate Native entry points we need
	//
	LocateNativeEntryPoints();

	if( foundFileArg ) {
		
		//
		// Get canonical path name
		//
		GetFullPathName( argv[argc-1], MAX_PATH, searchPath, &filePart );
	}
	printf("SDelete is set for %d pass%s.\n", NumPasses,
		NumPasses > 1 ? "es" : "");
	
	//
	// Do the deleting
	//
	if( !ZapFreeSpace ) {

		//
		// Now go and process directories
		//
		ProcessDirectory( searchPath, searchPattern );

		if( !FilesFound ) _tprintf(_T("No files found that match %s.\n"), argv[argc-1] );

	} else if( !foundFileArg ) {

		GetCurrentDirectory( MAX_PATH, searchPath );
	} 

	//
	// If we encountered a compressed file along the way, and we couldn't directly
	// zap its on-disk clusters then we have to clean all the free space.
	//
	if( CleanCompressedFiles || ZapFreeSpace ) {

		CleanFreeSpace( searchPath );
	}

	_tprintf(_T("\n"));
    return 0;
}
Пример #11
0
ForceInline void main2(int argc, char **argv)
{
    if (argc < 2)
        return;

    char *path;
    intptr_t hFind;
    __finddata64_t fd;

    iBufferSize = 0x3000;
    gpbBuffer = (uchar *)malloc(iBufferSize);

    for (int i = 1; i != argc; ++i)
    {
        hFind = _findfirst64(argv[i], &fd);
        if (hFind == -1)
            continue;

        do
        {
            path = findpath(argv[i]);
            if (path) *path = 0;

            if (fd.attrib & _A_SUBDIR)
            {
                if (strcmp(fd.name, ".") && strcmp(fd.name, ".."))
                {
                    int j;

                    if (path)
                    {
                        j = strlen(argv[i]);
                        strcpy(&fd.name[j + 1], fd.name);
                        strcpy(fd.name, argv[i]);
                        fd.name[j] = '\\';
                    }

                    ProcessDirectory(fd.name);

                    if (path) *path = '\\';
                }
            }
            else
            {
                int j;

                if (path)
                {
                    j = strlen(argv[i]);
                    strcpy(&fd.name[j + 1], fd.name);
                    strcpy(fd.name, argv[i]);
                    fd.name[j] = '\\';
                }

                ProcessFile(fd.name);

            }

            if (path) *path = '\\';
        } while (_findnext64(hFind, &fd) != -1);
    }

    _findclose(hFind);
    free(gpbBuffer);
}
Пример #12
0
void
InventoryEngine::Baseline()
{
	ProcessDirectory("/etc", 0);
}
Пример #13
0
CDiskResource::CDiskResource(std::wstring path) : CPackageResource(path)
{
	ProcessDirectory(_T(""));
}
//////////////////////////////////////////////////////////////////////
// feature_Factory::Create() //                    \author Logan Jones
//////////////////////////////                         \date 2/12/2002
//               
//====================================================================
// Parameters:
//  BYTE* pTntFileBuffer           - 
//  LPTSTR strWorld                - 
//  game_Main::LoadGameStruct Load - 
//
// Return: BOOL - 
//
BOOL feature_Factory::Create( BYTE* pTntFileBuffer, LPTSTR strWorld, game_LoadFacilitator Load )
{
	app_FileTree::HFIND				hList;
	app_FileTree::FindData_t		ListInfo;
	app_FileTree::HFIND				hFind;
	app_FileTree::FindData_t		FindInfo;
	BOOL							bWorkingFeatureFolders;
	BOOL							bWorkingFeatureFiles;
	char							SubDirectoryToSearch[128];
	LPTA_TNT_HEADER					pHeader;
	LPTA_TNT_EXT_HEADER				pMapHeader;
	DWORD							count;
	TA_TNT_FEATURE_ENTRY*			pFeatureToLoad;
	int								CurrentProgress;

	if( bFAILED( AddHardcodedFeatureTypes() ) )
	{
		return FALSE;
	}

	// Initialize some loading members
	m_LoadPass = -1;
	m_CurrentAnimFile = NULL;
	m_CurrentAnimFileName[0] = '\0';

	// TODO: Add unit feature stuff (corpses, etc...) to the list

	pHeader = (LPTA_TNT_HEADER)pTntFileBuffer;
	pMapHeader = (LPTA_TNT_EXT_HEADER)(pTntFileBuffer + sizeof(TA_TNT_HEADER));
	
	// Add the features from the map to the list
	pFeatureToLoad = (TA_TNT_FEATURE_ENTRY*)(pTntFileBuffer + pMapHeader->OffsetToFeatureEntryArray);
	for( count=pMapHeader->NumberOfFeatures; count>0; --count, ++pFeatureToLoad)
		AddToLoadList( pFeatureToLoad->Name, 0 );


	// Precheck features in the all worlds folder to speed loading
	theApp.Console.Comment( CT_LOAD, "Processing features/all worlds" );
	for( m_NewFeatureAdded=TRUE; m_NewFeatureAdded; )
	{
		m_NewFeatureAdded = FALSE;
		ProcessDirectory( "all worlds", Load );
	}
	Load.Progress( 10 );


	// Precheck features in the specific world folder to speed loading
	if( strWorld[0]!='\0' )
	{
		theApp.Console.Comment( CT_LOAD, "Processing features/%s", strWorld );
		for( m_NewFeatureAdded=TRUE; m_NewFeatureAdded; )
		{
			m_NewFeatureAdded = FALSE;
			ProcessDirectory( strWorld, Load );
		}
	}
	Load.Progress( 20 );


	// If there are any features left to load, look through all the other subdirectories
	for( m_LoadPass=0,CurrentProgress=20; !m_FeaturesToLoad.empty(); ++m_LoadPass )
	{
		// Check if we need to check for unfound features
		if( m_LoadPass>0 )
		{
			FeatureToLoadList_t::iterator		e,it = m_FeaturesToLoad.begin();
			FeatureToLoadList_t::const_iterator	end= m_FeaturesToLoad.end();
			for( ; it!=end; )
			{
				if( (*it).second.SearchAdded<m_LoadPass )
				{
					theApp.Console.Comment( CT_LOAD, "Could not find feature \"%s\"", (*it).second.Name );
					m_FeaturesToLoad.erase( e=it++ );
				}
				else ++it;
			}

			if( m_FeaturesToLoad.empty() )
				break;

		} // end if( m_LoadPass > 0 )

		// Search all subdirectories ind 'features'
		hList = theFileTree.Find( app_FileTree::DIRECTORIES, NULL, "features", &ListInfo );
		bWorkingFeatureFolders = hList!=NULL;
		while( bWorkingFeatureFolders )
		{
			// Make sure this is a directory
			if( ListInfo.bIsFile==FALSE )
			{
				theApp.Console.Comment( CT_LOAD, "Processing features/%s", ListInfo.Name );

				// Search all tdf files in this subdirectory
				sprintf( SubDirectoryToSearch, "features/%s", ListInfo.Name );
				hFind = theFileTree.Find( app_FileTree::FILES_WITH_EXTENSIONS, "tdf", SubDirectoryToSearch, &FindInfo );
				bWorkingFeatureFiles = hFind!=NULL;
				while( bWorkingFeatureFiles )
				{
					//theApp.Console.Comment( CT_LOAD, "Processing features/%s/%s", ListInfo.ItemName, FindInfo.Name );
					ProcessTDF( FindInfo.hFile, ListInfo.Name, FindInfo.Name, Load );

					// Check if there is anything else to load
					if( m_FeaturesToLoad.empty() )
						break;

					// Find next file
					bWorkingFeatureFiles = theFileTree.ContinueFind( hFind, &FindInfo );

				} // end while( tdf files )

				theFileTree.CloseFind( hFind );

			} // end if( IsDirectory )

			// Check if there is anything else to load
			if( m_FeaturesToLoad.empty() )
				break;

			// Find next subdirectory
			bWorkingFeatureFolders = theFileTree.ContinueFind( hList, &ListInfo );

		} // end while( subdirectories )

		theFileTree.CloseFind( hList );
	} // end while( there are still features to load )

	// Clean up some loading members
	SAFE_DELETE_ARRAY( m_CurrentAnimFile );

	theApp.Console.Comment( CT_LOAD, "Placing features on the terrain..." );
	Load.Progress( 90 );

	// Spawn all the features on the map
	pFeatureToLoad = (TA_TNT_FEATURE_ENTRY*)(pTntFileBuffer + pMapHeader->OffsetToFeatureEntryArray);
	LPTA_TNT_MAP_ENTRY pMapStuff = (LPTA_TNT_MAP_ENTRY)(pTntFileBuffer + pMapHeader->OffsetToMapInfoArray);
	for( DWORD y=0; y<pHeader->Height-1; ++y,pMapStuff+=pHeader->Width)
		for( DWORD x=0; x<pHeader->Width-1; ++x)
			if( pMapStuff[x].Special>=0 )
				SpawnFeature( pFeatureToLoad[pMapStuff[x].Special].Name, x * 16, y * 16, pMapStuff[x].Elevation );

	Load.Progress( 100 );
	return TRUE;
}
Пример #15
0
void ProcessDirectory(LPCTSTR srcbase, CDirectoryAction& action, LPCTSTR directory, bool recursive, wregex* ignorePattern)
{
	WIN32_FIND_DATA findData;
	HANDLE hFindHandle;

	CString srcdir;
	Utilities::CombinePath(srcbase, directory, srcdir);

	if (!ShouldProcess(ignorePattern, srcdir))
	{
		return;
	}

	action.VisitDirectoryInitial(directory);

	CString pattern;
	Utilities::CombinePath(srcdir, TEXT("*"), pattern);

	Utilities::FixLongFilenames(pattern);

	hFindHandle = ::FindFirstFile(pattern, &findData);
	if (hFindHandle != INVALID_HANDLE_VALUE)
	{
		BOOL done = false;
		while (!done)
		{
			if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
			{
				if (recursive)
				{
					if (Utilities::AreEqual(findData.cFileName, L".") || Utilities::AreEqual(findData.cFileName, L".."))
					{
						// Do nothing
					}
					else
					{
						CString subdirectory;
						Utilities::CombinePath(directory, findData.cFileName, subdirectory);
						if (!ShouldProcess(ignorePattern, srcbase, subdirectory))
						{
							continue;
						}
						ProcessDirectory(srcbase, action, subdirectory, recursive, ignorePattern);
					}
				}
			}
			else
			{
				CString file;
				Utilities::CombinePath(directory, findData.cFileName, file);
				if (!ShouldProcess(ignorePattern, srcbase, file)) continue;
				action.VisitFile(file);
			}

			BOOL worked = ::FindNextFile(hFindHandle, &findData);

			if (!worked)
			{
				int error = GetLastError();

				if (error == ERROR_NO_MORE_FILES)
				{
					done = true;
				}
				else
				{
					CString errorMessage;
					Utilities::FormatErrorMessage(error, errorMessage);
					CString message;
					message.AppendFormat(TEXT("There was an error calling FindNextFile. Path: %s Error: %s"),
						pattern, errorMessage);
					throw new CVSSCopyException(message.GetString());
				}
			}
		}
	}
	else
	{
		int error = GetLastError();

		if (error != ERROR_FILE_NOT_FOUND)
		{
			CString errorMessage;
			Utilities::FormatErrorMessage(error, errorMessage);
			CString message;
			message.AppendFormat(TEXT("There was an error calling FindFirstFile. Path: %s Error: %s"),
				pattern, errorMessage);
			throw new CVSSCopyException(message.GetString());
		}
	}
	::FindClose(hFindHandle);


	// Important to put this after FindClose, since otherwise there's still an 
	// open handle to the directory, and that can interfere with (e.g.) directory
	// deletion
	action.VisitDirectoryFinal(directory);

}
Пример #16
0
void startBackup(COptions options)
{
	GUID snapshotSetId = GUID_NULL;
	bool bSnapshotCreated = false;
	bool bAbnormalAbort = true;
	CComPtr<IVssBackupComponents> pBackupComponents;

	int fileCount = 0;
	LONGLONG byteCount = 0;
	int directoryCount = 0;
	int skipCount = 0;
	SYSTEMTIME startTime;
	
	try
	{
		OutputWriter::SetVerbosityLevel((VERBOSITY_LEVEL)options.get_VerbosityLevel());

		//for (int i = 0; i < argc; ++i)
		//{
		//	CString message;
		//	message.AppendFormat(TEXT("Argument %d: %s"), i, argv[i]);
		//	OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_IF_VERBOSE);
		//}

		OutputWriter::WriteLine(TEXT("Calling CoInitialize"));
		CHECK_HRESULT(::CoInitialize(NULL));
		CHECK_HRESULT(
			::CoInitializeSecurity(
			NULL,
			-1,
			NULL,
			NULL,
			RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
			RPC_C_IMP_LEVEL_IDENTIFY,
			NULL,
			EOAC_NONE,
			NULL));

		::GetSystemTime(&startTime);
		CString startTimeString;
		Utilities::FormatDateTime(&startTime, TEXT(" "), false, startTimeString);

		CString message;
		message.AppendFormat(TEXT("Starting a %s copy from %s to %s"),
			options.get_BackupType() == VSS_BT_FULL ? TEXT("full") : TEXT("incremental"),
			options.get_Source(),
			options.get_Destination());
		OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);

			if (options.get_ClearDestination())
			{
				if (!Utilities::DirectoryExists(options.get_Destination()))
				{
					CString message;
					message.AppendFormat(TEXT("Skipping recursive delete of destination directory %s because it appears not to exist."),
						options.get_Destination());
					OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);
				}
				else
				{
					CString message;
					message.AppendFormat(TEXT("Recursively deleting destination directory %s."),
						options.get_Destination());
					OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);

					bool doDelete = options.get_AcceptAll();

					if (!doDelete)
					{
						if (Confirm(message))
						{
							doDelete = true;
						}
						else
						{
							OutputWriter::WriteLine(TEXT("Aborting backup."), VERBOSITY_THRESHOLD_NORMAL);
							return;
						}
					}

					if (doDelete)
					{
						DeleteRecursive(options.get_Destination(), options.get_IgnorePattern());
					}
				}
			}

			CBackupState backupState;

			LPSYSTEMTIME lastBackupTime;

			if (options.get_BackupType() == VSS_BT_INCREMENTAL)
			{
				backupState.Load(options.get_StateFile());

				LPSYSTEMTIME lastFullBackupTime = backupState.get_LastFullBackupTime();
				LPSYSTEMTIME lastIncrementalBackupTime = backupState.get_LastIncrementalBackupTime();
				if (lastIncrementalBackupTime != NULL)
				{
					lastBackupTime = lastIncrementalBackupTime;
				}
				else
				{
					lastBackupTime = lastFullBackupTime;
				}
			}


			OutputWriter::WriteLine(TEXT("Calling CreateVssBackupComponents"));
			CHECK_HRESULT(::CreateVssBackupComponents(&pBackupComponents));

			OutputWriter::WriteLine(TEXT("Calling InitializeForBackup"));
			CHECK_HRESULT(pBackupComponents->InitializeForBackup());

			CComPtr<IVssAsync> pWriterMetadataStatus;

			OutputWriter::WriteLine(TEXT("Calling GatherWriterMetadata"));
			CHECK_HRESULT(pBackupComponents->GatherWriterMetadata(&pWriterMetadataStatus));

			OutputWriter::WriteLine(TEXT("Waiting for call to GatherWriterMetadata to finish..."));
			CHECK_HRESULT(pWriterMetadataStatus->Wait());

			HRESULT hrGatherStatus;
			OutputWriter::WriteLine(TEXT("Calling QueryStatus for GatherWriterMetadata"));
			CHECK_HRESULT(pWriterMetadataStatus->QueryStatus(&hrGatherStatus, NULL));

			if (hrGatherStatus == VSS_S_ASYNC_CANCELLED)
			{
				throw new CVSSCopyException(L"GatherWriterMetadata was cancelled.");
			}

			OutputWriter::WriteLine(TEXT("Call to GatherWriterMetadata finished."));


			OutputWriter::WriteLine(TEXT("Calling GetWriterMetadataCount"));

			vector<CWriter> writers;

			UINT cWriters;
			CHECK_HRESULT(pBackupComponents->GetWriterMetadataCount(&cWriters));

			for (UINT iWriter = 0; iWriter < cWriters; ++iWriter)
			{
				CWriter writer;
				CComPtr<IVssExamineWriterMetadata> pExamineWriterMetadata;
				GUID id;
				OutputWriter::WriteLine(TEXT("Calling GetWriterMetadata"));
				CHECK_HRESULT(pBackupComponents->GetWriterMetadata(iWriter, &id, &pExamineWriterMetadata));
				GUID idInstance;
				GUID idWriter;
				BSTR bstrWriterName;
				VSS_USAGE_TYPE usage;
				VSS_SOURCE_TYPE source;
				CHECK_HRESULT(pExamineWriterMetadata->GetIdentity(&idInstance, &idWriter, &bstrWriterName, &usage, &source));

				writer.set_InstanceId(idInstance);
				writer.set_Name(bstrWriterName);
				writer.set_WriterId(idWriter);

				CComBSTR writerName(bstrWriterName);
				CString message;
				message.AppendFormat(TEXT("Writer %d named %s"), iWriter, (LPCTSTR)writerName);
				OutputWriter::WriteLine(message);

				UINT cIncludeFiles;
				UINT cExcludeFiles;
				UINT cComponents;
				CHECK_HRESULT(pExamineWriterMetadata->GetFileCounts(&cIncludeFiles, &cExcludeFiles, &cComponents));

				message.Empty();
				message.AppendFormat(TEXT("Writer has %d components"), cComponents);
				OutputWriter::WriteLine(message);

				for (UINT iComponent = 0; iComponent < cComponents; ++iComponent)
				{
					CWriterComponent component;

					CComPtr<IVssWMComponent> pComponent;
					CHECK_HRESULT(pExamineWriterMetadata->GetComponent(iComponent, &pComponent));

					PVSSCOMPONENTINFO pComponentInfo;
					CHECK_HRESULT(pComponent->GetComponentInfo(&pComponentInfo));

					CString message;
					message.AppendFormat(TEXT("Component %d is named %s, has a path of %s, and is %sselectable for backup. %d files, %d databases, %d log files."),
						iComponent,
						pComponentInfo->bstrComponentName,
						pComponentInfo->bstrLogicalPath,
						pComponentInfo->bSelectable ? TEXT("") : TEXT("not "),
						pComponentInfo->cFileCount,
						pComponentInfo->cDatabases,
						pComponentInfo->cLogFiles);
					OutputWriter::WriteLine(message);

					component.set_LogicalPath(pComponentInfo->bstrLogicalPath);
					component.set_SelectableForBackup(pComponentInfo->bSelectable);
					component.set_Writer(iWriter);
					component.set_Name(pComponentInfo->bstrComponentName);
					component.set_Type(pComponentInfo->type);

					for (UINT iFile = 0; iFile < pComponentInfo->cFileCount; ++iFile)
					{
						CComPtr<IVssWMFiledesc> pFileDesc;
						CHECK_HRESULT(pComponent->GetFile(iFile, &pFileDesc));

						CComBSTR bstrPath;
						CHECK_HRESULT(pFileDesc->GetPath(&bstrPath));

						CComBSTR bstrFileSpec;
						CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec));

						CString message;
						message.AppendFormat(TEXT("File %d has path %s\\%s"), iFile, bstrPath, bstrFileSpec);
						OutputWriter::WriteLine(message);
					}

					for (UINT iDatabase = 0; iDatabase < pComponentInfo->cDatabases; ++iDatabase)
					{
						CComPtr<IVssWMFiledesc> pFileDesc;
						CHECK_HRESULT(pComponent->GetDatabaseFile(iDatabase, &pFileDesc));

						CComBSTR bstrPath;
						CHECK_HRESULT(pFileDesc->GetPath(&bstrPath));

						CComBSTR bstrFileSpec;
						CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec));

						CString message;
						message.AppendFormat(TEXT("Database file %d has path %s\\%s"), iDatabase, bstrPath, bstrFileSpec);
						OutputWriter::WriteLine(message);
					}

					for (UINT iDatabaseLogFile = 0; iDatabaseLogFile < pComponentInfo->cLogFiles; ++iDatabaseLogFile)
					{
						CComPtr<IVssWMFiledesc> pFileDesc;
						CHECK_HRESULT(pComponent->GetDatabaseLogFile(iDatabaseLogFile, &pFileDesc));

						CComBSTR bstrPath;
						CHECK_HRESULT(pFileDesc->GetPath(&bstrPath));

						CComBSTR bstrFileSpec;
						CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec));

						CString message;
						message.AppendFormat(TEXT("Database log file %d has path %s\\%s"), iDatabaseLogFile, bstrPath, bstrFileSpec);
						OutputWriter::WriteLine(message);
					}

					CHECK_HRESULT(pComponent->FreeComponentInfo(pComponentInfo));

					writer.get_Components().push_back(component);

				}

				writer.ComputeComponentTree();

				for (unsigned int iComponent = 0; iComponent < writer.get_Components().size(); ++iComponent)
				{
					CWriterComponent& component = writer.get_Components()[iComponent];
					CString message;
					message.AppendFormat(TEXT("Component %d has name %s, path %s, is %sselectable for backup, and has parent %s"),
						iComponent,
						component.get_Name(),
						component.get_LogicalPath(),
						component.get_SelectableForBackup() ? TEXT("") : TEXT("not "),
						component.get_Parent() == NULL ? TEXT("(no parent)") : component.get_Parent()->get_Name());
					OutputWriter::WriteLine(message);
				}

				writers.push_back(writer);
			}

			OutputWriter::WriteLine(TEXT("Calling StartSnapshotSet"));
			CHECK_HRESULT(pBackupComponents->StartSnapshotSet(&snapshotSetId));

			OutputWriter::WriteLine(TEXT("Calling GetVolumePathName"));
			WCHAR wszVolumePathName[MAX_PATH];
			BOOL bWorked = ::GetVolumePathName(options.get_Source(), wszVolumePathName, MAX_PATH);

			if (!bWorked)
			{
				DWORD error = ::GetLastError();
				CString errorMessage;
				Utilities::FormatErrorMessage(error, errorMessage);
				CString message;
				message.AppendFormat(TEXT("There was an error retrieving the volume name from the path. Path: %s Error: %s"),
					options.get_Source(), errorMessage);
				throw new CVSSCopyException(message.GetString());
			}

			OutputWriter::WriteLine(TEXT("Calling AddToSnapshotSet"));
			GUID snapshotId;
			CHECK_HRESULT(pBackupComponents->AddToSnapshotSet(wszVolumePathName, GUID_NULL, &snapshotId));

			for (unsigned int iWriter = 0; iWriter < writers.size(); ++iWriter)
			{
				CWriter writer = writers[iWriter];

				CString message;
				message.AppendFormat(TEXT("Adding components to snapshot set for writer %s"), writer.get_Name());
				OutputWriter::WriteLine(message);
				for (unsigned int iComponent = 0; iComponent < writer.get_Components().size(); ++iComponent)
				{
					CWriterComponent component = writer.get_Components()[iComponent];

					if (ShouldAddComponent(component))
					{
						CString message;
						message.AppendFormat(TEXT("Adding component %s (%s) from writer %s"),
							component.get_Name(),
							component.get_LogicalPath(),
							writer.get_Name());
						OutputWriter::WriteLine(message);
						CHECK_HRESULT(pBackupComponents->AddComponent(
							writer.get_InstanceId(),
							writer.get_WriterId(),
							component.get_Type(),
							component.get_LogicalPath(),
							component.get_Name()
							));
					}
					else
					{
						CString message;
						message.AppendFormat(TEXT("Not adding component %s from writer %s."),
							component.get_Name(), writer.get_Name());
						OutputWriter::WriteLine(message);
					}
				}
			}

			OutputWriter::WriteLine(TEXT("Calling SetBackupState"));
			// Issue #29: trying to figure out if using VSS_BT_INCREMENTAL causes a problem
			CHECK_HRESULT(pBackupComponents->SetBackupState(TRUE, FALSE, VSS_BT_FULL, FALSE));

			OutputWriter::WriteLine(TEXT("Calling PrepareForBackup"));
			CComPtr<IVssAsync> pPrepareForBackupResults;
			CHECK_HRESULT(pBackupComponents->PrepareForBackup(&pPrepareForBackupResults));

			OutputWriter::WriteLine(TEXT("Waiting for call to PrepareForBackup to finish..."));
			CHECK_HRESULT(pPrepareForBackupResults->Wait());

			HRESULT hrPrepareForBackupResults;
			CHECK_HRESULT(pPrepareForBackupResults->QueryStatus(&hrPrepareForBackupResults, NULL));

			if (hrPrepareForBackupResults != VSS_S_ASYNC_FINISHED)
			{
				throw new CVSSCopyException(TEXT("Prepare for backup failed."));
			}

			OutputWriter::WriteLine(TEXT("Call to PrepareForBackup finished."));

			SYSTEMTIME snapshotTime;
			::GetSystemTime(&snapshotTime);

			bWorked = ::SetConsoleCtrlHandler(CtrlHandler, TRUE);

			if (!bWorked)
			{
				OutputWriter::WriteLine(TEXT("Unable to set control handler. Ctrl-C and Ctrl-Break may have undesirable results."),
					VERBOSITY_THRESHOLD_NORMAL);
			}

			if (!options.get_Simulate())
			{
				OutputWriter::WriteLine(TEXT("Calling DoSnapshotSet"));
				CComPtr<IVssAsync> pDoSnapshotSetResults;
				CHECK_HRESULT(pBackupComponents->DoSnapshotSet(&pDoSnapshotSetResults));

				OutputWriter::WriteLine(TEXT("Waiting for call to DoSnapshotSet to finish..."));

				CHECK_HRESULT(pDoSnapshotSetResults->Wait());

				bSnapshotCreated = true;

				if (s_cancel)
				{
					throw new CVSSCopyException(TEXT("Processing was cancelled by control-c, control-break, or a shutdown event. Terminating."));
				}

				bWorked = ::SetConsoleCtrlHandler(CtrlHandler, FALSE);

				if (!bWorked)
				{
					OutputWriter::WriteLine(TEXT("Unable to reset control handler. Ctrl-C and Ctrl-Break may have undesirable results."), VERBOSITY_THRESHOLD_NORMAL);
				}

				HRESULT hrDoSnapshotSetResults;
				CHECK_HRESULT(pDoSnapshotSetResults->QueryStatus(&hrDoSnapshotSetResults, NULL));

				if (hrDoSnapshotSetResults != VSS_S_ASYNC_FINISHED)
				{
					throw new CVSSCopyException(L"DoSnapshotSet failed.");
				}

				OutputWriter::WriteLine(TEXT("Call to DoSnapshotSet finished."));

				OutputWriter::WriteLine(TEXT("Calling GetSnapshotProperties"));
				VSS_SNAPSHOT_PROP snapshotProperties;
				CHECK_HRESULT(pBackupComponents->GetSnapshotProperties(snapshotId, &snapshotProperties));

				OutputWriter::WriteLine(TEXT("Calling CalculateSourcePath"));
				// TODO: We'll eventually have to deal with mount points
				CString wszSource;
				CalculateSourcePath(
					snapshotProperties.m_pwszSnapshotDeviceObject,
					options.get_Source(),
					wszVolumePathName,
					wszSource
					);

				message.Empty();
				message.AppendFormat(TEXT("Recursively creating destination directory %s."),
					options.get_Destination());
				OutputWriter::WriteLine(message);

				Utilities::CreateDirectory(options.get_Destination());

				OutputWriter::WriteLine(TEXT("Calling CopyRecursive"));

				vector<CCopyFilter*> filters;

				if (options.get_BackupType() == VSS_BT_FULL)
				{
					filters.push_back(new CIncludeAllCopyFilter());
				}
				else if (options.get_BackupType() == VSS_BT_INCREMENTAL)
				{
					filters.push_back(new CModifiedSinceCopyFilter(lastBackupTime, options.get_SkipDenied()));
				}

				filters.push_back(new CFilespecCopyFilter(options.get_Filespecs()));

				CCopyAction copyAction(wszSource, options.get_Destination(), options.get_SkipDenied(), filters);
				ProcessDirectory(wszSource, copyAction, TEXT(""), options.get_Recursive(), options.get_IgnorePattern());

				for (unsigned int iFilter = 0; iFilter < filters.size(); ++iFilter)
				{
					delete filters[iFilter];
				}

				fileCount = copyAction.get_FileCount();
				directoryCount = copyAction.get_DirectoryCount();
				skipCount = copyAction.get_SkipCount();
				byteCount = copyAction.get_ByteCount();

				OutputWriter::WriteLine(TEXT("Calling BackupComplete"));
				CComPtr<IVssAsync> pBackupCompleteResults;
				CHECK_HRESULT(pBackupComponents->BackupComplete(&pBackupCompleteResults));

				OutputWriter::WriteLine(TEXT("Waiting for call to BackupComplete to finish..."));
				CHECK_HRESULT(pBackupCompleteResults->Wait());

				HRESULT hrBackupCompleteResults;
				CHECK_HRESULT(pBackupCompleteResults->QueryStatus(&hrBackupCompleteResults, NULL));

				if (hrBackupCompleteResults != VSS_S_ASYNC_FINISHED)
				{
					throw new CVSSCopyException(TEXT("Completion of backup failed."));
				}

				OutputWriter::WriteLine(TEXT("Call to BackupComplete finished."));

				bAbnormalAbort = false;

				if (options.get_StateFile() != NULL)
				{
					OutputWriter::WriteLine(TEXT("Calling SaveAsXML"));
					CComBSTR bstrBackupDocument;
					CHECK_HRESULT(pBackupComponents->SaveAsXML(&bstrBackupDocument));

					if (options.get_BackupType() == VSS_BT_FULL)
					{
						backupState.set_LastFullBackupTime(&snapshotTime);
					}
					else if (options.get_BackupType() == VSS_BT_INCREMENTAL)
					{
						backupState.set_LastIncrementalBackupTime(&snapshotTime);
					}
					else
					{
						throw new CVSSCopyException(TEXT("Unsupported backup type."));
					}

					backupState.Save(options.get_StateFile(), bstrBackupDocument);
				}
			}
		}
		catch (CComException* e)
		{
			Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId);
			CString message;
			CString file;
			e->get_File(file);
			message.Format(TEXT("There was a COM failure 0x%x - %s (%d)"),
				e->get_Hresult(), file, e->get_Line());
			OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_UNLESS_SILENT);
			return;
		}
		catch (CVSSCopyException* e)
		{
			Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId);
			OutputWriter::WriteLine(e->get_Message(), VERBOSITY_THRESHOLD_UNLESS_SILENT);
			return;
		}
		catch (CParseOptionsException* e)
		{
			Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId);
			CString message;
			message.AppendFormat(TEXT("Error: %s\n"), e->get_Message());
			OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_UNLESS_SILENT);
			OutputWriter::WriteLine(COptions::get_Usage(), VERBOSITY_THRESHOLD_UNLESS_SILENT);
			return;
		}

		Cleanup(false, bSnapshotCreated, pBackupComponents, snapshotSetId);
		OutputWriter::WriteLine(TEXT("Backup successfully completed."), VERBOSITY_THRESHOLD_UNLESS_SILENT);

		CString message;
		CString startTimeStringLocal;
		Utilities::FormatDateTime(&startTime, TEXT(" "), true, startTimeStringLocal);
		CString finishTimeString;
		SYSTEMTIME finishTime;
		::GetSystemTime(&finishTime);
		Utilities::FormatDateTime(&finishTime, TEXT(" "), true, finishTimeString);
		message.AppendFormat(TEXT("Backup started at %s, completed at %s."),
			startTimeStringLocal, finishTimeString);
		OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);
		message.Empty();

		float unitCount = (float)byteCount;
		LPCTSTR units = TEXT("bytes");

		if (unitCount > 1024)
		{
			unitCount = unitCount / 1024.0F;
			units = TEXT("KB");
		}

		if (unitCount > 1024)
		{
			unitCount = unitCount / 1024.0F;
			units = TEXT("MB");
		}

		if (unitCount > 1024)
		{
			unitCount = unitCount / 1024.0F;
			units = TEXT("GB");
		}

		message.AppendFormat(TEXT("%d files (%.2f %s, %d directories) copied, %d files skipped"),
			fileCount, unitCount, units, directoryCount, skipCount);
		OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);

		OutputWriter::SetVerbosityLevel((VERBOSITY_LEVEL)options.get_VerbosityLevel());

		//for (int i = 0; i < argc; ++i)
		//{
		//	CString message;
		//	message.AppendFormat(TEXT("Argument %d: %s"), i, argv[i]);
		//	OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_IF_VERBOSE);
		//}
}