BOOL CDiskObject::CopyFiles( const CString& sourceDirectory,const CString& destDirectory ) /* ============================================================ Function : CDiskObject::CopyFiles Description : The member copies all files from "sourceDirectory" to "destDirectory". Subdirectories will not be copied. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will return errors. Parameters : CString sourceDirectory - Copy from. If empty, current. CString destDirectory - Copy to. If empty, current. Usage : Call to copy the files from one directory to another. ============================================================*/ { ClearError( ); CString source( sourceDirectory ); CString dest( destDirectory ); QualifyPath( source ); QualifyPath( dest ); // First, we enumerate all files CStringArray files; BOOL result = EnumFilesInDirectory( source, files ); if( result ) { // Create the destination directory, if necessary if( ( result = CreateDirectory( dest ) ) ) { INT_PTR max = files.GetSize( ); for( INT_PTR t = 0 ; t < max ; t++ ) { // Copy the files CString file; file = files[ t ]; Trigger( file ); if( !( result = ::CopyFile( source + file, dest + file, FALSE ) ) ) { // Set error message SetSystemErrorMessage( ::GetLastError( ), source + file + _T( " -> " ) + dest + file ); t = max; } } } } return result; }
BOOL CDiskObject::CopyDirectories( const CString& sourceDirectory,const CString& destDirectory ) /* ============================================================ Function : CDiskObject::CopyDirectories Description : Copies all the files and subdirectories from "sourceDirectory" to "destDirectory", keeping the directory structure. Existing files will be overwritten. "destDirectory" and subdirectories will be created if necessary. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will get an error string if "FALSE" Parameters : CString sourceDirectory - copy from. CString destDirectory - copy to. Usage : Call to copy a directory tree to a new directory tree. ============================================================*/ { ClearError( ); CString source( sourceDirectory ); CString dest( destDirectory ); QualifyPath( source ); QualifyPath( dest ); // Enumerate all directories and files below sourceDirectory CStringArray directories; directories.Add( source ); BOOL result = EnumAllDirectories( source, directories ); if( result ) { // Create and copy directories INT_PTR max = directories.GetSize( ); for( INT_PTR t = 0 ; t < max ; t++ ) { // Create names and copy CString from = directories[ t ]; CString part = from.Right( from.GetLength( ) - source.GetLength( ) ); CString to = dest + part; if( !( result = CopyFiles( from, to ) ) ) t = max; } } return result; }
BOOL CDiskObject::RemoveDirectories( const CString& directory ) /* ============================================================ Function : CDiskObject::RemoveDirectories Description : Will remove the directory "directory", even if not empty. Will remove subdirectories. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will get an error string if "FALSE" Parameters : CString directory - root directory to remove. Usage : Call to remove a directory tree. ============================================================*/ { ClearError( ); BOOL result = TRUE; CString indir( directory ); if( indir.GetLength( ) ) { QualifyPath( indir ); CStringArray directories; // Get all directories ; if( ( result = EnumAllDirectories( indir, directories ) ) ) { // Loop and remove INT_PTR max = directories.GetSize( ); for( INT_PTR t = max - 1; t >= 0 ; t-- ) if( !( result = RemoveDirectory( directories[ t ] ) ) ) t = -1; if( result ) result = RemoveDirectory( indir ); } } else { // Small sanity check, we can't // delete the current directory. SetInternalErrorMessage( ); result = FALSE; } return result; }
BOOL CDiskObject::CopyFile( const CString& sourceFile,const CString& destDirectory, const CString& destFile ) /* ============================================================ Function : CDiskObject::CopyFile Description : Will copy "sourceFile" to "destDirectory" with the new name "destFile". An existing file will be overwritten. The directory will be created if it doesn't exist. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will contain errors Parameters : CString sourceFile - file to copy CString destDirectory - destination CString destFile - destination file name (in "destDirectory") Usage : Call to copy a file to a directory. ============================================================*/ { ClearError( ); CString source( sourceFile ); CString destDir( destDirectory ); CString dest( destFile ); BOOL result = TRUE; if( sourceFile.GetLength( ) ) { QualifyFile( source ); QualifyFile( dest ); QualifyPath( destDir ); // Creating destDirectory if necessary. if( ( result = CreateDirectory( destDir ) ) ) { // Copy the file Trigger( dest ); if( !( result = ::CopyFile( source, dest, FALSE ) ) ) SetSystemErrorMessage( ::GetLastError( ), source ); } } else { SetInternalErrorMessage( ); result = FALSE; } return result; }
BOOL CDiskObject::CopyDirectory( const CString& sourceDirectory,const CString& destDirectory ) /* ============================================================ Function : CDiskObject::CopyDirectory Description : Copies all the files from "sourceDirectory" to "destDirectory". Existing files will be overwritten. "destDirectory" will be created if necessary. Subdirectories will not be copied. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will get an error string if "FALSE" Parameters : CString sourceDirectory - copy from. CString destDirectory - copy to. Usage : Call to copy a directory to another directory. ============================================================*/ { ClearError( ); CString source( sourceDirectory ); CString dest( destDirectory ); QualifyPath( source ); QualifyPath( dest ); Trigger( dest ); // We don't care if this fails - CopyFiles will // return an error in that case. ::CreateDirectory( dest, NULL ); return CopyFiles( source, dest ); }
BOOL CDiskObject::EnumAllFilesWithFilter( const CString& filter,const CString& sourceDirectory, CStringArray& files ) /* ============================================================ Function : CDiskObject::EnumAllFiles Description : Returns, recursively, the fully qualified names of all files matching the filter found under "sourceDirectory". Access : Public Return : BOOL - "TRUE" if OK. Parameters : CString filter - Filter for files to find CString sourceDirectory - Root dir CStringArray& files - output list of all files found Usage : Call to get a filtered list of all files in a directory tree. ============================================================*/ { CStringArray dirs; BOOL result = EnumAllDirectories( sourceDirectory, dirs ); dirs.Add(sourceDirectory); if( result ) { INT_PTR max1 = dirs.GetSize( ); for( int t = 0 ; t < max1 ; t++ ) { CString dir = dirs[ t ]; QualifyPath( dir ); CStringArray dirfiles; if( EnumFilesInDirectoryWithFilter( filter, dir, dirfiles, EF_FULLY_QUALIFIED ) ) { INT_PTR max2 = dirfiles.GetSize( ); for( int i = 0 ; i < max2 ; i++ ) { CString file = dirfiles[ i ]; Trigger( file ); files.Add( file ); } } // Sleep(100); } } return result; }
BOOL CDiskObject::RemoveDirectory( const CString& directory ) /* ============================================================ Function : CDiskObject::RemoveDirectory Description : Will remove the directory "directory", even if not empty. Will not remove subdirectories. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will get an error string if "FALSE" Parameters : CString directory - directory to remove. Usage : Call to remove a directory. ============================================================*/ { ClearError( ); BOOL result = TRUE; CString indir( directory ); if( indir.GetLength( ) ) { QualifyPath( indir ); // Wipe and remove directory if( ( result = EmptyDirectory( indir ) ) ) { Trigger( indir ); if( !( result = ::RemoveDirectory( indir ) ) ) SetSystemErrorMessage( ::GetLastError( ), indir ); } } else { // Small sanity check, we can't // delete the current directory. SetInternalErrorMessage( ); result = FALSE; } return result; }
BOOL CDiskObject::EmptyDirectory( const CString& directory ) /* ============================================================ Function : CDiskObject::EmptyDirectory Description : Will delete all files in directory. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will get an error string if "FALSE" Parameters : CString directory - the directory to empty. Usage : Call to empty a directory. ============================================================*/ { ClearError( ); CString indir( directory ); QualifyPath( indir ); // Enumerate all files CStringArray files; BOOL result = EnumFilesInDirectory( indir, files ); if( result ) { INT_PTR max = files.GetSize( ); for( INT_PTR t = 0 ; t < max ; t++ ) { // Loop and delete CString file = files[ t ]; Trigger( file ); if( !( result = ::DeleteFile( indir + file ) ) ) { SetSystemErrorMessage( ::GetLastError( ), indir + file ); t = max; } } } return result; }
BOOL CDiskObject::EmptyDirectories( const CString& directory ) /* ============================================================ Function : CDiskObject::EmptyDirectories Description : Will delete all files in "directory". Will also empty subdirectories. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will get an error string if "FALSE" Parameters : CString directory - the root directory to empty. Usage : Call to empty a directory tree. ============================================================*/ { ClearError( ); CString indir( directory ); QualifyPath( indir ); CStringArray directories; // Get all directories BOOL result = EnumAllDirectories( indir, directories ); if( result ) { INT_PTR max = directories.GetSize( ); // Loop and empty for( INT_PTR t = max - 1 ; t >= 0 ; t-- ) if( !( result = EmptyDirectory( directories[ t ] ) ) ) t = -1; if( result ) result = EmptyDirectory( indir ); } return result; }
BOOL CDiskObject::DirectoryExists( const CString& directory ) /* ============================================================ Function : CDiskObject::DirectoryExists Description : Returns "TRUE" if the directory "directory" exists Access : Public Return : BOOL - "TRUE" if found Parameters : CString directory - directory to check Usage : Call to check for directory existence. ============================================================*/ { ClearError( ); BOOL result = FALSE; if( directory.GetLength( ) ) { CString indir( directory ); QualifyPath( indir ); TCHAR buff[ _MAX_PATH ]; ::GetCurrentDirectory(_MAX_PATH, buff ); if( ::SetCurrentDirectory( indir ) ) result = TRUE; ::SetCurrentDirectory( buff ); } else { SetInternalErrorMessage( ); } return result; }
/*---------------------------------------------------------------------*/ BOOL ValidatePath(CHAR * path, H_ARCHIVE harchive) { _archive[harchive].last_error = ARC_NO_ERROR; _archive_error = ARC_NO_ERROR; /* Check out the path */ if (path == NULL) _archive_error = ARC_BAD_PATH; if (strlen(path) > MAX_PATH_LEN - ARC_PATH_LEN) _archive_error = ARC_BAD_PATH; if (!IsDirectory(path)) _archive_error = ARC_BAD_PATH; if (_archive_error != ARC_NO_ERROR) return (FALSE); /* Fully qualify the path */ QualifyPath(_archive[harchive].path, path); return (TRUE); }
BOOL CDiskObject::CreateDirectory( const CString& directory ) /* ============================================================ Function : CDiskObject::CreateDirectory Description : Will recursively create the directory "directory". Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will get an error string if "FALSE" Parameters : CString directory - directory to create Usage : Call to create a directory chain. ============================================================*/ { ClearError( ); BOOL result = TRUE; CString indir( directory ); if( indir.GetLength( ) ) { QualifyPath( indir ); _TCHAR drive[ _MAX_PATH ]; _TCHAR dir[ _MAX_DIR ]; _TCHAR fname[ _MAX_FNAME ]; _TCHAR ext[ _MAX_EXT ]; // Split directory into parts _tsplitpath( indir, drive, dir, fname, ext ); TCHAR currentDirectory[ _MAX_PATH ]; ::GetCurrentDirectory( _MAX_PATH, currentDirectory ); CStringArray directories; CString parts = dir; if( parts.GetLength( ) > 2 ) { if( parts.Left( 2 ) == _T( "\\\\" ) ) { // We have an UNC name CString strComputer; parts = parts.Right( parts.GetLength( ) - 2 ); int findDir = parts.Find( _TCHAR( '\\' ) ); if( findDir!=-1) { strComputer = _T( "\\\\" ) + parts.Left( findDir ); parts = parts.Right( parts.GetLength( ) - ( findDir + 1 ) ); } _tcscpy( drive, strComputer ); } } CString strRoot( drive ); // Strip leading \'s while( parts.GetLength( ) && parts[0] == _TCHAR( '\\' ) ) parts = parts.Right( parts.GetLength( ) - 1 ); // Cut into separate directories int find = parts.Find( _TCHAR( '\\' ) ); while( find != -1 ) { directories.Add( parts.Left( find ) ); parts = parts.Right( parts.GetLength( ) - ( find + 1 ) ); find = parts.Find( _TCHAR( '\\' ) ); } if( parts.GetLength( ) ) directories.Add( parts ); if( fname ) directories.Add( fname ); // Loop directories one-by-one, creating as necessary INT_PTR max = directories.GetSize( ); CString strCurrentDirectory( strRoot ); for( INT_PTR t = 0 ; t < max ; t++ ) { strCurrentDirectory += _TCHAR( '\\' ) + directories[ t ]; Trigger( strCurrentDirectory ); if( !( result = ::SetCurrentDirectory( strCurrentDirectory ) ) ) { if( !( result = ::CreateDirectory( strCurrentDirectory, NULL ) ) ) { SetSystemErrorMessage( ::GetLastError( ), strCurrentDirectory ); t = max; } } } ::SetCurrentDirectory( currentDirectory ); } else { SetInternalErrorMessage( ); result = FALSE; } return result; }
BOOL CDiskObject::CopyFiles( CStringArray& files,const CString& destDirectory ) /* ============================================================ Function : CDiskObject::CopyFiles Description : The function copies the files in the "CStringArray" "files" to the directory "destDirectory". Existing files will be overwritten. The destination will be created if it doesn't already exist. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will return errors. Parameters : CStringArray& files - a string array with the files to copy CString destDirectory - destination Usage : Copy a list of files to a directory. ============================================================*/ { ClearError( ); CString dest( destDirectory ); BOOL result = TRUE; if( files.GetSize( ) ) { QualifyPath( dest ); // Create destination, if necessary if( ( result = CreateDirectory( dest ) ) ) { INT_PTR max = files.GetSize( ); for( INT_PTR t = 0 ; t < max ; t++ ) { // Loop and copy the files CString file; file = files[ t ]; if( file.GetLength( ) ) { Trigger( file ); QualifyFile( file ); // Create destination filename CString to = dest + GetFileName( file ); if( !( result = ::CopyFile( file, to, FALSE ) ) ) { // Set error message SetSystemErrorMessage( ::GetLastError( ), file + _T( " -> " ) + dest + file ); t = max; } } } } } else { SetInternalErrorMessage( ); result = FALSE; } return result; }
BOOL CDiskObject::EnumDirectories( const CString& sourceDirectory, CStringArray& directories ) /* ============================================================ Function : CDiskObject::EnumDirectories Description : Enumerates all directories in directory "sourceDirectory", and adds them to the "CStringArray" "directories". Each entry will be a fully qualified name Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will contain errors Parameters : CString sourceDirectory - start directory CStringArray& directories - "CStringArray" to be filled with the directory names. Usage : Call to get a list of directories in a directory tree. ============================================================*/ { ClearError( ); CString source( sourceDirectory ); QualifyPath( source ); CString sourceFiles( source + _T( "*.*" ) ); BOOL result = TRUE; WIN32_FIND_DATA ff; HANDLE findhandle = FindFirstFile( sourceFiles, &ff ); if( findhandle != INVALID_HANDLE_VALUE) { BOOL res = TRUE; while( res) { // We only want directories if( ( ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) && _tcscmp( ff.cFileName, _T( "." ) ) && _tcscmp( ff.cFileName, _T( ".." ) ) ) { directories.Add( ff.cFileName ); Trigger( ff.cFileName ); } if( res ) res = FindNextFile( findhandle, &ff ); else result = FALSE; } FindClose( findhandle ); } else { // Set error message SetSystemErrorMessage( ::GetLastError( ), sourceFiles ); result = FALSE; } return result; }
BOOL CDiskObject::EnumFilesInDirectoryWithFilter( const CString& strFilter,const CString& sourceDirectory, CStringArray& files, int mode ) /* ============================================================ Function : CDiskObject::EnumFilesInDirectoryWithFilter Description : Enumerates all files matching "strFilter" in the directory "sourceDirectory", and adds them to the "CStringArray" "files". Will not add subdirectories. Access : Public Return : BOOL - "TRUE" if OK. "GetErrorMessage" will contain errors Parameters : CString strFilter - the file name filter CString sourceDirectory - source directory CStringArray& files - output array Usage : Call to get a filtered list of files from a directory. ============================================================*/ { ClearError( ); CString source( sourceDirectory ); QualifyPath( source ); CString sourceFiles( source + strFilter ); BOOL result = TRUE; WIN32_FIND_DATA ff; HANDLE findhandle = FindFirstFile( sourceFiles, &ff ); if( findhandle != INVALID_HANDLE_VALUE ) { BOOL res = TRUE; while( res ) { // We only want files if( !( ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ) { BOOL added = FALSE; CString file; file = ff.cFileName; if( mode == EF_FULLY_QUALIFIED ) file = sourceDirectory + file; if ( !added ) { files.Add( file ); } Trigger( file ); } res = FindNextFile( findhandle, &ff ); } FindClose( findhandle ); } else { // Set error message SetSystemErrorMessage( ::GetLastError( ), sourceFiles ); result = FALSE; } return result; }
int main( int argc, char *argv[]) { char msg[300]; DWORD dwWritten; int chars; /* * Make sure children (cl.exe and link.exe) are kept quiet. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); /* * Make sure the compiler and linker aren't effected by the outside world. */ SetEnvironmentVariable("CL", ""); SetEnvironmentVariable("LINK", ""); if (argc > 1 && *argv[1] == '-') { switch (*(argv[1]+1)) { case 'c': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -c <compiler option>\n" "Tests for whether cl.exe supports an option\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return CheckForCompilerFeature(argv[2]); case 'l': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -l <linker option>\n" "Tests for whether link.exe supports an option\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return CheckForLinkerFeature(argv[2]); case 'f': if (argc == 2) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -f <string> <substring>\n" "Find a substring within another\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } else if (argc == 3) { /* * If the string is blank, there is no match. */ return 0; } else { return IsIn(argv[2], argv[3]); } case 's': if (argc == 2) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -s <substitutions file> <file>\n" "Perform a set of string map type substutitions on a file\n" "exitcodes: 0\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return SubstituteFile(argv[2], argv[3]); case 'V': if (argc != 4) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -V filename matchstring\n" "Extract a version from a file:\n" "eg: pkgIndex.tcl \"package ifneeded http\"", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 0; } printf("%s\n", GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0')); return 0; case 'Q': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -Q path\n" "Emit the fully qualified path\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return QualifyPath(argv[2]); } } chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -c|-f|-l|-Q|-s|-V ...\n" "This is a little helper app to equalize shell differences between WinNT and\n" "Win9x and get nmake.exe to accomplish its job.\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; }
// Main entry point int _tmain(int argc, _TCHAR* argv[]) { // Add command line alias' cl.AddAlias(L"h", L"?"); cl.AddAlias(L"help", L"?"); cl.AddAlias(L"x", L"extract"); cl.AddAlias(L"o", L"out"); // Parse command line cl.Parse(GetCommandLine(), true); // Display logo... if (!cl.GetSwitch(L"nologo")) { wprintf(L"Structured Ini File Compiler v1.1\nCopyright (C) 2007 Topten Software. All Rights Reserved\n\n"); } // Display help if (cl.GetSwitch(L"?")) { cl.BuildHelp(L"nologo", L"Suppress display of copyright and version info", NULL, clOptional); cl.BuildHelp(L"?|h|help", L"Display help information", NULL, clOptional); cl.BuildHelp(L"i", L"Include path", L"path", clMulti|clValue|clOptional); cl.BuildHelp(L"x|extract", L"Extract (decompile)", NULL, clOptional); cl.BuildHelp(L"unicode", L"Decompile to unicode", NULL, clOptional); cl.BuildHelp(L"flat", L"Decompile to flat", NULL, clOptional); cl.BuildHelp(L"o|out", L"Output File", NULL, clOptional); cl.BuildHelp(L"InputFile", L"File to be processed", NULL, clPlaced); cl.BuildHelp(L"crcstamp", L"CRC Stamp Module", NULL, clOptional); cl.BuildHelp(L"crcverify", L"Check Module CRC Stamp", NULL, clOptional); wprintf(cl.GetHelp(L"Sinic")); return 7; } // Get input value CUniString strInputFile; cl.GetPlacedValue(0, L"InputFile", strInputFile); strInputFile=QualifyPath(strInputFile); if (cl.GetSwitch(L"crcverify")) { if (!DoesFileExist(strInputFile)) { wprintf(L"Verifying %s... file doesn't exist, ignoring\n", strInputFile); return 0; } else { if (!CheckModuleCRC(strInputFile)) { CheckModuleCRCWithErrors(strInputFile); wprintf(L"************************************************************\n"); wprintf(L" Verifying %s... FAILED\n", strInputFile); wprintf(L"************************************************************\n"); return 7; } else { wprintf(L"Verifying %s... OK\n", strInputFile); return 0; } } } // Module CRC Stamp? if (cl.GetSwitch(L"crcstamp")) { // Work out output file CUniString strOutputFile; cl.GetValue(L"out", strOutputFile); if (strOutputFile.IsEmpty()) strOutputFile=strInputFile; // Error handling... cl.CheckNoUnknownArgs(); if (cl.HasError()) { wprintf(cl.GetErrorMessage()); wprintf(L"\n\n"); return 7; } // Open file for read/write FILE* pFile; if (_wfopen_s(&pFile, strInputFile, L"rb")!=0) { wprintf(L"Error: Can't open file '%s'\n", strInputFile); return 7; } // Get file size fseek(pFile, 0, SEEK_END); DWORD dwLength=ftell(pFile); fseek(pFile, 0, SEEK_SET); // Check has length if (dwLength==0) { fclose(pFile); wprintf(L"Error: Zero length file\n"); return 7; } // Load file into memory LPBYTE pFileData=(LPBYTE)malloc(dwLength); // Read data if (fread(pFileData, dwLength, 1, pFile)!=1) { free(pFileData); fclose(pFile); wprintf(L"Error: Error reading file\n"); return 7; } // Close the file fclose(pFile); if (CountCRCControlBlocks(pFileData, dwLength)>1) { free(pFileData); fclose(pFile); wprintf(L"Error: File contains multiple CRC Control blocks!\n"); return 7; } // Locate CRC Control block CRCCONTROLBLOCK* pCRCBlock=LocateCRCControlBlock(pFileData, dwLength); if (!pCRCBlock) { free(pFileData); fclose(pFile); wprintf(L"Error: File doesn't contain CRC Control block!\n"); return 7; } wprintf(L"CRC Control Block located at offset: 0x%.8x\n", reinterpret_cast<LPBYTE>(pCRCBlock)-pFileData); // Calculate the CRC upto start of control block pCRCBlock->dwCRC=CalculateModuleCRC(pFileData, dwLength, pCRCBlock); pCRCBlock->dwModuleLength=dwLength; wprintf(L"Module length: 0x%.8x\n", dwLength); wprintf(L"CRC: 0x%.8x\n", pCRCBlock->dwCRC); pFile=NULL; if (_wfopen_s(&pFile, strOutputFile, L"wb")!=0) { wprintf(L"Error: Can't open output file '%s'\n", strOutputFile); return 7; } if (!CheckModuleCRC(pFileData, dwLength)) { wprintf(L"Error: double check failed\n"); return 7; } // Write CRC stamped fwrite(pFileData, dwLength, 1, pFile); // Clean up free(pFileData); fclose(pFile); if (!CheckModuleCRC(strOutputFile)) { CheckModuleCRCWithErrors(strOutputFile); return 7; } wprintf(L"CRC Stamped %s - OK\n\n", strOutputFile); return 0; } // Compile or decompile bool bDecompile=cl.GetSwitch(L"extract"); bool bUnicode=cl.GetSwitch(L"unicode"); bool bFlat=cl.GetSwitch(L"flat"); // Get output file CUniString strOutputFile; cl.GetValue(L"out", strOutputFile); if (strOutputFile.IsEmpty()) { strOutputFile=ChangeFileExtension(strInputFile.IsEmpty() ? L"" : strInputFile, bDecompile ? L"sini" : L"bini"); } strOutputFile=QualifyPath(strOutputFile); // Setup file content provider with include paths CFileContentProvider fp; CVector<CUniString> vecIncludePaths; cl.GetMultiValue(L"i", vecIncludePaths); for (int i=0; i<vecIncludePaths.GetSize(); i++) { CUniString str=QualifyPath(vecIncludePaths[i]); fp.AddIncludePath(str); } // Get defines CVector<CUniString> vecDefines; cl.GetMultiValue(L"d", vecDefines); // Error handling... cl.CheckNoUnknownArgs(); if (cl.HasError()) { wprintf(cl.GetErrorMessage()); wprintf(L"\n\n"); return 7; } if (!bDecompile) { // Load the input file CProfileFile file; for (int i=0; i<vecDefines.GetSize(); i++) { CUniString strName, strValue; SplitString(vecDefines[i], L"=", strName, strValue); wprintf(L"#define %s %s\n", strName, strValue); file.Define(strName, strValue); } if (!file.Load(strInputFile, &fp)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(file.GetParseError()); return 7; } // Extract encryption key DWORD dwEncryptionKey=0; CProfileSection* pSection=file.FindSection(L"Sinic"); if (pSection) { // Save the key dwEncryptionKey=pSection->GetIntValue(L"EncryptionKey", 0); // Remove the "sinic" section file.Remove(pSection); } // Create output file CFileStream OutStream; if (!OutStream.Create(strOutputFile)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(L"Failed to create '%s' - %s (0x%.8x)\n\n", strOutputFile, FormatError(hr), hr); return 7; } // Save as binary file HRESULT hr; if (dwEncryptionKey) { CAutoPtr<IStream, SRefCounted> spEncStream; CreateCryptorStream(&OutStream, CCryptorKey(dwEncryptionKey), &spEncStream); hr=SaveBinaryProfile(file, spEncStream); } else { hr=SaveBinaryProfile(file, &OutStream); } OutStream.Close(); if (FAILED(hr)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(L"Failed to save '%s' - %s (0x%.8x)\n\n", strOutputFile, FormatError(hr), hr); DeleteFile(strOutputFile); return 7; } } else { // Open stream CFileStream InStream; if (!InStream.Open(strInputFile)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(L"Failed to open '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr); return 7; } // Load profile CProfileFile file; HRESULT hr=LoadBinaryProfile(file, &InStream); if (FAILED(hr)) { if (hr!=E_UNEXPECTED) { wprintf(L"Failed to load '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr); return 7; } else { wprintf(L"Failed to load '%s' - not a binary profile file\n\n", strInputFile); return 7; } } // Save as heirarchial if (!file.Save(strOutputFile, bUnicode, !bFlat)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(L"Failed to save '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr); return 7; } } wprintf(L"%s - OK\n\n", strOutputFile); return 0; }