Files
source/Standard Gaming Platform/FileMan.cpp
T
Kriplo 37bd981181 Brief: //dnl ch81
- Fix several problems with summary windows and improve map loading to any map for mapeditor.
Details:
- Add option from CTRL+L list box to load any map from any listed profiles.
- Fix incorrect loading of items option in summary window for non vanilla maps.
- Fix improper popup of radio boxes for when items is selected in summary window and summary file or map not exist.
- Summary items information is now show for non sector custom map files too.
- Fix glitches when switching from overhead map to sector summary windows.
- Fix improper opening of exit screen text box during exit from overhead map.
- Change size to fixed macro of all temporary buffers for map filename.


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6687 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2013-12-06 21:14:09 +00:00

2555 lines
63 KiB
C++

//**************************************************************************
//
// Filename : FileMan.c
//
// Purpose : function definitions for the memory manager
//
// Modification history :
//
// 24sep96:HJH ->creation
// 08Apr97:ARM ->Assign return value from Push() calls back to HStack
// handle, because it may possibly do a MemRealloc()
// 29Dec97:Kris Morness
// ->Added functionality for setting file attributes which
// allows for read-only attribute overriding
// ->Also added a simple function that clears all file attributes
// to normal.
//
// 5 Feb 98:Dave French->extensive modification to support libraries
//
//**************************************************************************
//**************************************************************************
//
// Includes
//
//**************************************************************************
#ifdef JA2_PRECOMPILED_HEADERS
#include "JA2 SGP ALL.H"
#elif defined( WIZ8_PRECOMPILED_HEADERS )
#include "WIZ8 SGP ALL.H"
#else
#include "Types.h"
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <direct.h>
#include "windows.h"
#include "FileMan.h"
#include "MemMan.h"
#include "DbMan.h"
#include "Debug.h"
#include "RegInst.h"
#include "Container.h"
#include "LibraryDataBase.h"
#include "io.h"
#include "sgp_logger.h"
#endif
using namespace std;
#include <vfs/Core/vfs.h>
#include <vfs/Core/vfs_os_functions.h>
#include <vfs/Aspects/vfs_settings.h>
#ifdef USE_VFS
#include <vfs/Core/vfs_file_raii.h>
#include <map>
struct SOperation
{
enum EOperation
{
UNKNOWN, READ, WRITE,
};
EOperation op;
SOperation() : op(UNKNOWN) {};
};
typedef std::map<vfs::IBaseFile*, SOperation> tFILEMAP;
static tFILEMAP s_mapFiles;
#endif
//**************************************************************************
//
// Defines
//
//**************************************************************************
#define FILENAME_LENGTH 600
#define CHECKF(exp) if (!(exp)) { return(FALSE); }
#define CHECKV(exp) if (!(exp)) { return; }
#define CHECKN(exp) if (!(exp)) { return(NULL); }
#define CHECKBI(exp) if (!(exp)) { return(-1); }
#define PRINT_DEBUG_INFO FileDebugPrint();
//**************************************************************************
//
// Typedefs
//
//**************************************************************************
typedef struct FMFileInfoTag
{
CHAR strFilename[FILENAME_LENGTH];
UINT8 uiFileAccess;
UINT32 uiFilePosition;
HANDLE hFileHandle;
HDBFILE hDBFile;
} FMFileInfo; // for 'File Manager File Information'
typedef struct FileSystemTag
{
FMFileInfo *pFileInfo;
UINT32 uiNumHandles;
BOOLEAN fDebug;
BOOLEAN fDBInitialized;
CHAR *pcFileNames;
UINT32 uiNumFilesInDirectory;
} FileSystem;
//**************************************************************************
//
// Variables
//
//**************************************************************************
//The FileDatabaseHeader
DatabaseManagerHeaderStruct gFileDataBase;
//FileSystem gfs;
WIN32_FIND_DATA Win32FindInfo[20];
BOOLEAN fFindInfoInUse[20] = {FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE };
HANDLE hFindInfoHandle[20] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
// Snap: At program launch we build two directory catalogues:
// one for the default Data directory, the other for the custom Data directory.
TFileCat gDefaultDataCat; // Init in InitializeStandardGamingPlatform (sgp.cpp)
TFileCat gCustomDataCat; // Init in InitializeStandardGamingPlatform (sgp.cpp)
//**************************************************************************
//
// Function Prototypes
//
//**************************************************************************
void W32toSGPFileFind( GETFILESTRUCT *pGFStruct, WIN32_FIND_DATA *pW32Struct );
void FileDebugPrint( void );
HANDLE GetHandleToRealFile( HWFILE hFile, BOOLEAN *pfDatabaseFile );
HWFILE CreateFileHandle( HANDLE hRealFile, BOOLEAN fDatabaseFile );
void DestroyFileHandle( HWFILE hFile );
void BuildFileDirectory( void );
INT32 GetFilesInDirectory( HCONTAINER hStack, CHAR *, HANDLE hFile, WIN32_FIND_DATA *pFind );
//**************************************************************************
//
// Functions
//
//**************************************************************************
//**************************************************************************
//
// FileSystemInit
//
// Starts up the file system.
//
// Parameter List :
// Return Value :
// Modification history :
//
// 24sep96:HJH ->creation
//
//**************************************************************************
BOOLEAN InitializeFileManager( STR strIndexFilename )
{
RegisterDebugTopic( TOPIC_FILE_MANAGER, "File Manager" );
return( TRUE );
}
//**************************************************************************
//
// FileSystemShutdown
//
// Shuts down the file system.
//
// Parameter List :
// Return Value :
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
void ShutdownFileManager( void )
{
UnRegisterDebugTopic( TOPIC_FILE_MANAGER, "File Manager" );
}
//**************************************************************************
//
// FileDebug
//
// To set whether or not we should print debug info.
//
// Parameter List :
// Return Value :
// Modification history :
//
// 24sep96:HJH ->creation
//
//**************************************************************************
void FileDebug( BOOLEAN f )
{
// gfs.fDebug = f;
}
//**************************************************************************
//
// FileExists
//
// Checks if a file exists.
//
// Parameter List :
//
// STR ->name of file to check existence of
//
// Return Value :
//
// BOOLEAN ->TRUE if it exists
// ->FALSE if not
//
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
// Oct 2005: Snap - Rewrote, made to check data catalogues
//
//**************************************************************************
BOOLEAN FileExists( STR strFilename )
{
#ifdef USE_VFS
return getVFS()->fileExists(vfs::Path(strFilename));
#else
// First check to see if it's in a library (most files should be there)
if ( gFileDataBase.fInitialized &&
CheckIfFileExistInLibrary( strFilename ) ) return TRUE;
// ... then check if it's in the custom Data directory
if ( gCustomDataCat.FindFile(strFilename) ) return TRUE;
// ... then check if it's in the default Data directory
if ( gDefaultDataCat.FindFile(strFilename) ) return TRUE;
// ... lastly, try to locate it in the file system
DWORD attribs = GetFileAttributes(strFilename);
if ( attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY) )
return TRUE;
return FALSE;
#endif
}
//**************************************************************************
//
// FileExistsNoDB
//
// Checks if a file exists, but doesn't check the database files.
//
// Parameter List :
//
// STR ->name of file to check existence of
//
// Return Value :
//
// BOOLEAN ->TRUE if it exists
// ->FALSE if not
//
// Modification history :
//
// 24sep96:HJH ->creation
//
// Oct 2005: Snap - Rewrote, made to check data catalogues
//
//**************************************************************************
extern BOOLEAN FileExistsNoDB( STR strFilename )
{
#ifdef USE_VFS
return getVFS()->fileExists(vfs::Path(strFilename));
#else
// First check if it's in the custom Data directory
if ( gCustomDataCat.FindFile(strFilename) ) return TRUE;
// ... then check if it's in the default Data directory
if ( gDefaultDataCat.FindFile(strFilename) ) return TRUE;
// ... lastly, try to locate it in the file system
DWORD attribs = GetFileAttributes(strFilename);
if ( attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY) )
return TRUE;
return FALSE;
#endif
}
//**************************************************************************
//
// FileDelete
//
// Deletes a file.
//
// Parameter List :
//
// STR ->name of file to delete
//
// Return Value :
//
// BOOLEAN ->TRUE if successful
// ->FALSE if not
//
// Modification history :
//
// 24sep96:HJH ->creation
//
//**************************************************************************
BOOLEAN FileDelete( STR strFilename )
{
#ifdef USE_VFS
return getVFS()->removeFileFromFS(vfs::Path(strFilename));
#else
// Snap: delete the file from the default Data catalogue (if it is there)
// Since the path can be either relative or absolute, try both methods
gDefaultDataCat.RemoveFile(strFilename, true);
gDefaultDataCat.RemoveFile(strFilename, false);
return( DeleteFile( (LPCSTR) strFilename ) );
#endif
}
//**************************************************************************
//
// FileOpen
//
// Opens a file.
//
// Parameter List :
//
// STR ->filename
// UIN32 ->access - read or write, or both
// BOOLEAN ->delete on close
//
// Return Value :
//
// HWFILE ->handle of opened file
//
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
// Oct 2005: Snap - modified to work with the custom Data directory
//
//**************************************************************************
HWFILE FileOpen( STR strFilename, UINT32 uiOptions, BOOLEAN fDeleteOnClose, STR strProfilename )//dnl ch81 021213
{
#ifdef USE_VFS
vfs::Path path(strFilename);
vfs::IBaseFile *pFile = NULL;
try
{
if(uiOptions & FILE_ACCESS_WRITE)
{
// 'vfs::CVirtualFile::SF_TOP' should be enough, but if for some strange reason
// file creation fails, we will stop at a writable profile
// and won't unintentionally mess up a file from another profile
vfs::COpenWriteFile open_w( path, true, false, vfs::CVirtualFile::SF_STOP_ON_WRITABLE_PROFILE);
pFile = &open_w.file();
open_w.release();
s_mapFiles[pFile].op = SOperation::WRITE;
return (HWFILE)pFile;
}
else if(uiOptions & FILE_ACCESS_READ)
{
if(strProfilename && strProfilename[0])
{
vfs::COpenReadFile open_r(vfs::tReadableFile::cast(getVFS()->getFile(path, strProfilename)));
pFile = &open_r.file();
open_r.release();
}
else
{
vfs::COpenReadFile open_r(path, vfs::CVirtualFile::SF_TOP);
pFile = &open_r.file();
open_r.release();
}
s_mapFiles[pFile].op = SOperation::READ;
return (HWFILE)pFile;
}
}
// sometimes a file is supposed to opened that does not exist (not tested with FileExists())
// this operation can fail with an exception that the calling code doesn't catch
// instead we catch it (any exception, not just CBasicException) here and return 0
catch(vfs::Exception& ex) { SGP_ERROR(ex.what()); }
catch(...)
{
SGP_ERROR( "Caught undefined exception" );
}
return 0;
#else
HWFILE hFile;
HANDLE hRealFile;
DWORD dwAccess;
DWORD dwFlagsAndAttributes;
BOOLEAN fExists;
HDBFILE hDBFile;
DWORD dwCreationFlags;
HWFILE hLibFile;
hFile = 0;
hDBFile = 0;
dwCreationFlags = 0;
dwAccess = 0;
if ( uiOptions & FILE_ACCESS_READ )
dwAccess |= GENERIC_READ;
if ( uiOptions & FILE_ACCESS_WRITE )
dwAccess |= GENERIC_WRITE;
dwFlagsAndAttributes = FILE_FLAG_RANDOM_ACCESS;
if ( fDeleteOnClose )
dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
// Snap: This seems like an unnecessary check, but I don't feel like
// rewriting the function to eliminate it...
// check if the file exists - note that we use the function FileExistsNoDB
// because it doesn't check the databases, and we don't want to do that here
fExists = FileExistsNoDB( strFilename );
// Snap: First see if the file is in the custom Data catalogue:
std::string filePath;
if ( gCustomDataCat.FindFile(strFilename) ) {
filePath = gCustomDataCat.GetRootDir() + '\\';
}
filePath += strFilename;
// Bad cast! strFilename should have been const. Oh well...
strFilename = const_cast<STR>( filePath.c_str() );
// Now strFilename points either to the original file name,
// or to the full file path in the custom Data directory.
// Except for this substitution, the rest of the function is unchanged.
//if the file is on the disk
if ( fExists )
{
hRealFile = CreateFile( (LPCSTR) strFilename, dwAccess, 0, NULL, OPEN_ALWAYS,
dwFlagsAndAttributes, NULL );
if ( hRealFile == INVALID_HANDLE_VALUE )
{
return(0);
}
//create a file handle for the 'real file'
hFile = CreateRealFileHandle( hRealFile );
}
// if the file did not exist, try to open it from the database
else if ( gFileDataBase.fInitialized )
{
//if the file is to be opened for writing, return an error cause you cant write a file that is in the database library
if( fDeleteOnClose )
{
return( 0 );
}
//if the file doesnt exist on the harddrive, but it is to be created, dont try to load it from the file database
if( uiOptions & FILE_ACCESS_WRITE )
{
//if the files is to be written to
if( ( uiOptions & FILE_CREATE_NEW ) || ( uiOptions & FILE_OPEN_ALWAYS ) || ( uiOptions & FILE_CREATE_ALWAYS ) || ( uiOptions & FILE_TRUNCATE_EXISTING ) )
{
hFile = 0;
}
}
//else if the file is to be opened using FILE_OPEN_EXISTING, and the file doesnt exists, fail out of the function)
// else if( uiOptions & FILE_OPEN_EXISTING )
// {
//fail out of the function
// return( 0 );
// }
else
{
//If the file is in the library, get a handle to it.
hLibFile = OpenFileFromLibrary( strFilename );
//tried to open a file that wasnt in the database
if( !hLibFile )
return( 0 );
else
return( hLibFile ); //return the file handle
}
}
if ( !hFile )
{
if ( uiOptions & FILE_CREATE_NEW )
{
dwCreationFlags = CREATE_NEW;
}
else if ( uiOptions & FILE_CREATE_ALWAYS )
{
dwCreationFlags = CREATE_ALWAYS;
}
else if ( uiOptions & FILE_OPEN_EXISTING || uiOptions & FILE_ACCESS_READ )
{
dwCreationFlags = OPEN_EXISTING;
}
else if ( uiOptions & FILE_OPEN_ALWAYS )
{
dwCreationFlags = OPEN_ALWAYS;
}
else if ( uiOptions & FILE_TRUNCATE_EXISTING )
{
dwCreationFlags = TRUNCATE_EXISTING;
}
else
{
dwCreationFlags = OPEN_ALWAYS;
}
hRealFile = CreateFile( (LPCSTR) strFilename, dwAccess, 0, NULL, dwCreationFlags,
dwFlagsAndAttributes, NULL );
if ( hRealFile == INVALID_HANDLE_VALUE )
{
UINT32 uiLastError = GetLastError();
char zString[1024];
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, uiLastError, 0, zString, 1024, NULL);
return(0);
}
hFile = CreateRealFileHandle( hRealFile );
}
if ( !hFile )
return(0);
return(hFile);
#endif
}
//**************************************************************************
//
// FileClose
//
//
// Parameter List :
//
// HWFILE hFile ->handle to file to close
//
// Return Value :
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
void FileClose( HWFILE hFile )
{
#ifdef USE_VFS
vfs::IBaseFile *pFile = (vfs::IBaseFile*)hFile;
if(pFile)
{
pFile->close();
s_mapFiles.erase(pFile);
}
#else
INT16 sLibraryID;
UINT32 uiFileNum;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its the 'real file' library
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//if its not already closed
if( gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].uiFileID != 0 )
{
CloseHandle( gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle );
gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].uiFileID = 0;
gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle= 0;
gFileDataBase.RealFiles.iNumFilesOpen--;
if( gFileDataBase.RealFiles.iNumFilesOpen < 0 )
{
//if for some reason we are below 0, report an error ( should never be )
Assert( 0 );
}
}
}
else
{
//if the database is initialized
if( gFileDataBase.fInitialized )
CloseLibraryFile( sLibraryID, uiFileNum );
}
#endif
}
//**************************************************************************
//
// FileRead
//
// To read a file.
//
// Parameter List :
//
// HWFILE ->handle to file to read from
// void * ->source buffer
// UINT32 ->num bytes to read
// UINT32 ->num bytes read
//
// Return Value :
//
// BOOLEAN ->TRUE if successful
// ->FALSE if not
//
// Modification history :
//
// 24sep96:HJH ->creation
// 08Dec97:ARM ->return FALSE if bytes to read != bytes read
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
#ifdef JA2TESTVERSION
extern UINT32 uiTotalFileReadTime;
extern UINT32 uiTotalFileReadCalls;
#include "Timer Control.h"
class TimeCounter
{
public:
TimeCounter() : start_time(GetJA2Clock()) {}
~TimeCounter()
{
uiTotalFileReadTime += GetJA2Clock() - start_time;
uiTotalFileReadCalls++;
}
private:
UINT32 start_time;
};
#endif
BOOLEAN FileRead( HWFILE hFile, PTR pDest, UINT32 uiBytesToRead, UINT32 *puiBytesRead )
{
#ifdef USE_VFS
#ifdef JA2TESTVERSION
TimeCounter timer;
#endif
vfs::IBaseFile *pFile = (vfs::IBaseFile*)hFile;
if(pFile && (s_mapFiles[pFile].op == SOperation::READ))
{
vfs::tReadableFile *pRF = vfs::tReadableFile::cast(pFile);
if(pRF)
{
UINT32 uiBytesRead = 0;
try
{
uiBytesRead = pRF->read((vfs::Byte*)pDest, uiBytesToRead);
}
catch(std::exception& ex)
{
pRF->close();
SGP_RETHROW(L"", ex);
}
if(puiBytesRead)
{
*puiBytesRead = uiBytesRead;
}
if(uiBytesToRead != uiBytesRead)
{
return FALSE;
}
return TRUE;
}
}
return FALSE;
#else
HANDLE hRealFile;
DWORD dwNumBytesToRead, dwNumBytesRead;
BOOLEAN fRet = FALSE;
INT16 sLibraryID;
UINT32 uiFileNum;
#ifdef JA2TESTVERSION
UINT32 uiStartTime = GetJA2Clock();
#endif
//init the variables
dwNumBytesToRead = dwNumBytesRead = 0;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
dwNumBytesToRead = (DWORD)uiBytesToRead;
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//if the file is opened
if( uiFileNum != 0 )
{
hRealFile = gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle;
fRet = ReadFile( hRealFile, pDest, dwNumBytesToRead, &dwNumBytesRead, NULL );
if ( dwNumBytesToRead != dwNumBytesRead )
{
UINT32 uiLastError = GetLastError();
char zString[1024];
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, uiLastError, 0, zString, 1024, NULL);
fRet = FALSE;
}
if ( puiBytesRead )
*puiBytesRead = (UINT32)dwNumBytesRead;
}
}
else
{
//if the database is initialized
if( gFileDataBase.fInitialized )
{
//if the library is open
if( IsLibraryOpened( sLibraryID ) )
{
//if the file is opened
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFileID != 0 )
{
//read the data from the library
fRet = LoadDataFromLibrary( sLibraryID, uiFileNum, pDest, dwNumBytesToRead, (UINT32 *) &dwNumBytesRead );
if ( puiBytesRead )
{
*puiBytesRead = (UINT32)dwNumBytesRead;
}
}
}
}
}
#ifdef JA2TESTVERSION
//Add the time that we spent in this function to the total.
uiTotalFileReadTime += GetJA2Clock() - uiStartTime;
uiTotalFileReadCalls++;
#endif
return(fRet);
#endif
}
//**************************************************************************
//
// FileWrite
//
// To write a file.
//
// Parameter List :
//
// HWFILE ->handle to file to write to
// void * ->destination buffer
// UINT32 ->num bytes to write
// UINT32 ->num bytes written
//
// Return Value :
//
// BOOLEAN ->TRUE if successful
// ->FALSE if not
//
// Modification history :
//
// 24sep96:HJH ->creation
// 08Dec97:ARM ->return FALSE if dwNumBytesToWrite != dwNumBytesWritten
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
BOOLEAN FileWrite( HWFILE hFile, PTR pDest, UINT32 uiBytesToWrite, UINT32 *puiBytesWritten )
{
#ifdef USE_VFS
if(uiBytesToWrite == 0)//dnl ch38 110909
{
*puiBytesWritten = 0;
return(TRUE);
}
vfs::IBaseFile *pFile = (vfs::IBaseFile*)hFile;
if(pFile && (s_mapFiles[pFile].op == SOperation::WRITE))
{
vfs::tWritableFile *pWF = vfs::tWritableFile::cast(pFile);
if(pWF)
{
UINT32 uiBytesWritten;
try
{
uiBytesWritten = pWF->write((vfs::Byte*)pDest, uiBytesToWrite);
}
catch(std::exception& ex)
{
pWF->close();
SGP_RETHROW(L"", ex);
}
if (uiBytesToWrite != uiBytesWritten)
{
return FALSE;
}
if ( puiBytesWritten )
{
*puiBytesWritten = uiBytesWritten;
}
return TRUE;
}
}
return FALSE;
#else
HANDLE hRealFile;
DWORD dwNumBytesToWrite, dwNumBytesWritten;
BOOLEAN fRet;
INT16 sLibraryID;
UINT32 uiFileNum;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
dwNumBytesToWrite = (DWORD)uiBytesToWrite;
//get the real file handle to the file
hRealFile = gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle;
fRet = WriteFile( hRealFile, pDest, dwNumBytesToWrite, &dwNumBytesWritten, NULL );
if (dwNumBytesToWrite != dwNumBytesWritten)
fRet = FALSE;
if ( puiBytesWritten )
*puiBytesWritten = (UINT32)dwNumBytesWritten;
}
else
{
//we cannot write to a library file
if ( puiBytesWritten )
*puiBytesWritten = 0;
return(FALSE);
}
return(fRet);
#endif
}
//**************************************************************************
//
// FileLoad
//
// To open, read, and close a file.
//
// Parameter List :
//
//
// Return Value :
//
// BOOLEAN ->TRUE if successful
// ->FALSE if not
//
// Modification history :
//
// 24sep96:HJH ->creation
// 08Dec97:ARM ->return FALSE if bytes to read != bytes read (CHECKF is inappropriate?)
//
//**************************************************************************
BOOLEAN FileLoad( STR strFilename, PTR pDest, UINT32 uiBytesToRead, UINT32 *puiBytesRead )
{
#ifdef USE_VFS
vfs::tReadableFile *pFile = getVFS()->getReadFile(vfs::Path(strFilename));
vfs::COpenReadFile rfile(pFile);
if(pFile)
{
UINT32 uiNumBytesRead;
SGP_TRYCATCH_RETHROW(uiNumBytesRead = pFile->read((vfs::Byte*)pDest,uiBytesToRead), L"");
if (uiBytesToRead != uiNumBytesRead)
{
return FALSE;
}
if ( puiBytesRead )
{
*puiBytesRead = uiNumBytesRead;
}
CHECKF( uiNumBytesRead == uiBytesToRead );
return TRUE;
}
return FALSE;
#else
HWFILE hFile;
UINT32 uiNumBytesRead;
BOOLEAN fRet;
hFile = FileOpen( strFilename, FILE_ACCESS_READ, FALSE );
if ( hFile )
{
fRet = FileRead( hFile, pDest, uiBytesToRead, &uiNumBytesRead );
FileClose( hFile );
if (uiBytesToRead != uiNumBytesRead)
fRet = FALSE;
if ( puiBytesRead )
*puiBytesRead = uiNumBytesRead;
CHECKF( uiNumBytesRead == uiBytesToRead );
}
else
fRet = FALSE;
return(fRet);
#endif
}
//**************************************************************************
//
// FilePrintf
//
// To printf to a file.
//
// Parameter List :
//
// HWFILE ->handle to file to seek in
// ... ->arguments, 1st of which should be a string
//
// Return Value :
//
// BOOLEAN ->TRUE if successful
// ->FALSE if not
//
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
#ifndef DIM
# define DIM(x) (sizeof(x)/sizeof(x[0])) /* made StringLen Save, Sergeant_Kolja, 2007-06-10 */
#endif
BOOLEAN _cdecl FilePrintf( HWFILE hFile, STR8 strFormatted, ... )
{
#ifdef USE_VFS
CHAR8 strToSend[160]; /* itemdescription of item 0 will NOT fit if only 80 Chars per Line!, Sergeant_Kolja, 2007-06-10 */
va_list argptr;
BOOLEAN fRetVal = FALSE;
va_start(argptr, strFormatted);
_vsnprintf( strToSend, DIM(strToSend), strFormatted, argptr ); /* made StringLen Save, Sergeant_Kolja, 2007-06-10 */
strToSend[ DIM(strToSend)-1 ] = 0;
va_end(argptr);
fRetVal = FileWrite( hFile, strToSend, strlen(strToSend), NULL );
return( fRetVal );
#else
CHAR8 strToSend[160]; /* itemdescription of item 0 will NOT fit if only 80 Chars per Line!, Sergeant_Kolja, 2007-06-10 */
va_list argptr;
BOOLEAN fRetVal = FALSE;
INT16 sLibraryID;
UINT32 uiFileNum;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
va_start(argptr, strFormatted);
_vsnprintf( strToSend, DIM(strToSend), strFormatted, argptr ); /* made StringLen Save, Sergeant_Kolja, 2007-06-10 */
strToSend[ DIM(strToSend)-1 ] = 0;
va_end(argptr);
fRetVal = FileWrite( hFile, strToSend, strlen(strToSend), NULL );
}
else
{
//its a library file, cant write to it so return an error
fRetVal = FALSE;
}
return( fRetVal );
#endif
}
//**************************************************************************
//
// FileSeek
//
// To seek to a position in a file.
//
// Parameter List :
//
// HWFILE ->handle to file to seek in
// UINT32 ->distance to seek
// UINT8 ->how to seek
//
// Return Value :
//
// BOOLEAN ->TRUE if successful
// ->FALSE if not
//
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
BOOLEAN FileSeek( HWFILE hFile, UINT32 uiDistance, UINT8 uiHow )
{
#ifdef USE_VFS
INT32 iDistance = (INT32)uiDistance;
vfs::IBaseFile *pFile = (vfs::IBaseFile*)hFile;
if(pFile)
{
vfs::IBaseFile::ESeekDir eSD;
if ( uiHow == FILE_SEEK_FROM_START )
{
eSD = vfs::IBaseFile::SD_BEGIN;
}
else if ( uiHow == FILE_SEEK_FROM_END )
{
eSD = vfs::IBaseFile::SD_END;
if( iDistance > 0 )
{
iDistance = -(iDistance);
}
}
else
{
eSD = vfs::IBaseFile::SD_CURRENT;
}
if(s_mapFiles[pFile].op == SOperation::WRITE)
{
vfs::tWritableFile *pWF = vfs::tWritableFile::cast(pFile);
if(pWF)
{
SGP_TRYCATCH_RETHROW(pWF->setWritePosition(iDistance, eSD), L"");
return TRUE;
}
}
else if(s_mapFiles[pFile].op == SOperation::READ)
{
vfs::tReadableFile *pRF = vfs::tReadableFile::cast(pFile);
if(pRF)
{
SGP_TRYCATCH_RETHROW(pRF->setReadPosition(iDistance, eSD), L"");
return TRUE;
}
}
else
{
SGP_THROW(L"unknown operation");
}
}
return FALSE;
#else
HANDLE hRealFile;
LONG lDistanceToMove;
DWORD dwMoveMethod;
INT32 iDistance=0;
INT16 sLibraryID;
UINT32 uiFileNum;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//Get the handle to the real file
hRealFile = gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle;
iDistance = (INT32) uiDistance;
if ( uiHow == FILE_SEEK_FROM_START )
dwMoveMethod = FILE_BEGIN;
else if ( uiHow == FILE_SEEK_FROM_END )
{
dwMoveMethod = FILE_END;
if( iDistance > 0 )
iDistance = -(iDistance);
}
else
dwMoveMethod = FILE_CURRENT;
lDistanceToMove = (LONG)uiDistance;
if ( SetFilePointer( hRealFile, iDistance, NULL, dwMoveMethod ) == 0xFFFFFFFF )
return(FALSE);
}
else
{
//if the database is initialized
if( gFileDataBase.fInitialized )
LibraryFileSeek( sLibraryID, uiFileNum, uiDistance, uiHow );
}
return(TRUE);
#endif
}
//**************************************************************************
//
// FileGetPos
//
// To get the current position in a file.
//
// Parameter List :
//
// HWFILE ->handle to file
//
// Return Value :
//
// INT32 ->current offset in file if successful
// ->-1 if not
//
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
INT32 FileGetPos( HWFILE hFile )
{
#ifdef USE_VFS
vfs::IBaseFile *pFile = (vfs::IBaseFile*)hFile;
if(pFile && (s_mapFiles[pFile].op == SOperation::WRITE))
{
vfs::tWritableFile *pWF = vfs::tWritableFile::cast(pFile);
if(pWF)
{
return pWF->getWritePosition();
}
}
else if(pFile && (s_mapFiles[pFile].op == SOperation::READ))
{
vfs::tReadableFile *pRF = vfs::tReadableFile::cast(pFile);
if(pRF)
{
return pRF->getReadPosition();
}
}
return BAD_INDEX;
#else
HANDLE hRealFile;
UINT32 uiPositionInFile=0;
INT16 sLibraryID;
UINT32 uiFileNum;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//Get the handle to the real file
hRealFile = gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle;
uiPositionInFile = SetFilePointer( hRealFile, 0, NULL, FILE_CURRENT);
if( uiPositionInFile == 0xFFFFFFFF )
{
uiPositionInFile = 0;
}
return( uiPositionInFile );
}
else
{
//if the library is open
if( IsLibraryOpened( sLibraryID ) )
{
//check if the file is open
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFileID != 0 )
{
uiPositionInFile = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFilePosInFile;
return( uiPositionInFile );
}
}
}
return(BAD_INDEX);
#endif
}
//**************************************************************************
//
// FileGetSize
//
// To get the current file size.
//
// Parameter List :
//
// HWFILE ->handle to file
//
// Return Value :
//
// INT32 ->file size in file if successful
// ->0 if not
//
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
UINT32 FileGetSize( HWFILE hFile )
{
#ifdef USE_VFS
vfs::IBaseFile *pFile = (vfs::IBaseFile*)hFile;
if(pFile)
{
return pFile->getSize();
}
return 0;
#else
HANDLE hRealHandle;
UINT32 uiFileSize = 0xFFFFFFFF;
INT16 sLibraryID;
UINT32 uiFileNum;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//Get the handle to a real file
hRealHandle = gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle;
uiFileSize = GetFileSize( hRealHandle, NULL );
}
else
{
//if the library is open
if( IsLibraryOpened( sLibraryID ) )
uiFileSize = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].pFileHeader->uiFileLength;
}
if ( uiFileSize == 0xFFFFFFFF )
return(0);
else
return( uiFileSize );
#endif
}
//**************************************************************************
//
// FileDebugPrint
//
// To print the state of memory to output.
//
// Parameter List :
// Return Value :
// Modification history :
//
// 24sep96:HJH ->creation
//
//**************************************************************************
void FileDebugPrint( void )
{
}
//**************************************************************************
//
// GetHandleToRealFile
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// 24sep96:HJH ->creation
//
// 9 Feb 98 DEF - modified to work with the library system
//
//**************************************************************************
HANDLE GetHandleToRealFile( HWFILE hFile, BOOLEAN *pfDatabaseFile )
{
HANDLE hRealFile;
INT16 sLibraryID;
UINT32 uiFileNum;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//Get the handle to the real file
hRealFile = gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle;
*pfDatabaseFile = FALSE;
}
else
{
*pfDatabaseFile = TRUE;
hRealFile = (HANDLE) hFile;
}
return(hRealFile);
}
//**************************************************************************
//
// CreateFileHandle
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// 24sep96:HJH ->creation
//
//**************************************************************************
/*
not needed anymore
HWFILE CreateFileHandle( HANDLE hRealFile, BOOLEAN fDatabaseFile )
{
UINT32 i, uiOldNumHandles;
FMFileInfo *pNewFileInfo;
Assert( !fDatabaseFile || (fDatabaseFile && gfs.fDBInitialized) );
// don't use 1st position - it'll confuse the users
for ( i=1 ; i<gfs.uiNumHandles ; i++ )
{
if ( gfs.pFileInfo[i].hFileHandle == 0 && gfs.pFileInfo[i].hDBFile == 0 )
{
if ( fDatabaseFile )
gfs.pFileInfo[i].hDBFile = (HDBFILE)hRealFile;
else
gfs.pFileInfo[i].hFileHandle = hRealFile;
return( i );
}
}
uiOldNumHandles = gfs.uiNumHandles;
pNewFileInfo = (FMFileInfo *)MemRealloc( gfs.pFileInfo, gfs.uiNumHandles + NUM_FILES_TO_ADD_AT_A_TIME );
if ( !pNewFileInfo )
{
// TBD: error error error
return(0);
}
gfs.pFileInfo = (FMFileInfo *)pNewFileInfo;
gfs.uiNumHandles = gfs.uiNumHandles + NUM_FILES_TO_ADD_AT_A_TIME;
for ( i=uiOldNumHandles ; i<gfs.uiNumHandles ; i++ )
{
gfs.pFileInfo[i].hFileHandle = 0;
gfs.pFileInfo[i].hDBFile = 0;
}
if ( fDatabaseFile )
gfs.pFileInfo[uiOldNumHandles].hDBFile = (HDBFILE)hRealFile;
else
gfs.pFileInfo[uiOldNumHandles].hFileHandle = hRealFile;
return(uiOldNumHandles);
}
*/
//**************************************************************************
//
// DestroyFileHandle
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// 24sep96:HJH ->creation
//
//**************************************************************************
/*
void DestroyFileHandle( HWFILE hFile )
{
if ( hFile < gfs.uiNumHandles && hFile )
{
gfs.pFileInfo[hFile].hFileHandle = 0;
gfs.pFileInfo[hFile].hDBFile = 0;
}
}
*/
//**************************************************************************
//
// BuildFileDirectory
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// ??nov96:HJH ->creation
//
//**************************************************************************
void BuildFileDirectory( void )
{
return; // temporary until container stuff is fixed
/*
INT32 i, iNumFiles = 0;
HANDLE hFile, hFileIn;
WIN32_FIND_DATA find, inFind;
BOOLEAN fMore = TRUE;
CHAR cName[FILENAME_LENGTH], cDir[FILENAME_LENGTH], cSubDir[FILENAME_LENGTH];
HCONTAINER hStack;
//
// First, push all the file names in the directory (and subdirectories)
// onto the stack.
//
GetProfileChar( "Startup", "InstPath", "", cDir );
if ( strlen( cDir ) == 0 )
return;
hStack = CreateStack( 100, FILENAME_LENGTH );
if (hStack == NULL)
{
FastDebugMsg(String("BuildFileDirectory: CreateStack Failed for the filename stack"));
return;
}
find.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY;
strcpy( &(cDir[strlen(cDir)]), "\\*.*\0" );
hFile = FindFirstFile( cDir, &find );
while ( fMore )
{
if ( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if ( strcmp( find.cFileName, "." ) != 0 && strcmp( find.cFileName, ".." ) != 0 )
{
// a valid directory
inFind.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY;
strcpy( cSubDir, cDir );
strcpy( &(cSubDir[strlen(cDir)-3]), find.cFileName );
strcpy( &(cSubDir[strlen(cSubDir)]), "\\*.*\0" );
hFileIn = FindFirstFile( cSubDir, &inFind );
iNumFiles += GetFilesInDirectory( hStack, cSubDir, hFileIn, &inFind );
FindClose( hFileIn );
}
}
else
{
iNumFiles++;
strcpy( cName, cDir );
strcpy( &(cName[strlen(cName)-3]), find.cFileName );
CharLower( cName );
hStack = Push( hStack, cName );
}
find.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY;
fMore = FindNextFile( hFile, &find );
}
FindClose( hFile );
//
// Okay, we have all the files in the stack, now put them in place.
//
gfs.uiNumFilesInDirectory = iNumFiles;
gfs.pcFileNames = (STR8)MemAlloc( iNumFiles * FILENAME_LENGTH );
if ( gfs.pcFileNames )
{
for ( i=0 ; i<iNumFiles ; i++ )
{
Pop( hStack, (void *)(&gfs.pcFileNames[i*FILENAME_LENGTH]) );
}
}
//
// Clean up.
//
DeleteStack( hStack );
*/
}
//**************************************************************************
//
// GetFilesInDirectory
//
// Gets the files in a directory and the subdirectories.
//
// Parameter List :
// Return Value :
// Modification history :
//
// ??nov96:HJH ->creation
//
//**************************************************************************
INT32 GetFilesInDirectory( HCONTAINER hStack, CHAR *pcDir, HANDLE hFile, WIN32_FIND_DATA *pFind )
{
INT32 iNumFiles;
WIN32_FIND_DATA inFind;
BOOLEAN fMore;
CHAR cName[FILENAME_LENGTH], cDir[FILENAME_LENGTH];
HANDLE hFileIn;
fMore = TRUE;
iNumFiles = 0;
while ( fMore )
{
if ( pFind->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if ( strcmp( pFind->cFileName, "." ) != 0 && strcmp( pFind->cFileName, ".." ) != 0 )
{
// a valid directory - recurse and find the files in that directory
inFind.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY;
strcpy( cDir, pcDir );
strcpy( &(cDir[strlen(cDir)-3]), pFind->cFileName );
strcpy( &(cDir[strlen(cDir)]), "\\*.*\0" );
hFileIn = FindFirstFile( cDir, &inFind );
iNumFiles += GetFilesInDirectory( hStack, cDir, hFileIn, &inFind );
FindClose( hFileIn );
}
}
else
{
iNumFiles++;
strcpy( cName, pcDir );
strcpy( &(cName[strlen(cName)-3]), pFind->cFileName );
CharLower( cName );
hStack = Push( hStack, cName );
}
pFind->dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY;
fMore = FindNextFile( hFile, pFind );
}
return(iNumFiles);
}
BOOLEAN SetFileManCurrentDirectory( STR pcDirectory )
{
#ifndef USE_VFS
return( SetCurrentDirectory( pcDirectory ) );
#else
try
{
vfs::OS::setCurrectDirectory(pcDirectory);
}
catch(vfs::Exception& ex)
{
SGP_ERROR(ex.what());
return FALSE;
}
return TRUE;
#endif
}
BOOLEAN GetFileManCurrentDirectory( STRING512 pcDirectory )
{
#ifndef USE_VFS
if (GetCurrentDirectory( 512, pcDirectory ) == 0)
{
return( FALSE );
}
return( TRUE );
#else
try
{
vfs::Path sDir;
vfs::OS::getCurrentDirectory(sDir);
strncpy(pcDirectory, sDir.to_string().c_str(), 512);
}
catch(vfs::Exception& ex)
{
SGP_ERROR(ex.what());
return FALSE;
}
return TRUE;
#endif
}
BOOLEAN DirectoryExists( STRING512 pcDirectory )
{
UINT32 uiAttribs;
DWORD uiLastError;
uiAttribs = GetFileAttributes( pcDirectory );
if ( uiAttribs == 0xFFFFFFFF )
{
// an error, make sure it's the right error
uiLastError = GetLastError();
if (uiLastError != ERROR_FILE_NOT_FOUND)
{
FastDebugMsg(String("DirectoryExists: ERROR - GetFileAttributes failed, error #%d on file %s", uiLastError, pcDirectory));
}
}
else
{
// something's there, make sure it's a directory
if ( uiAttribs & FILE_ATTRIBUTE_DIRECTORY )
{
return TRUE;
}
}
// this could also mean that the name given is that of a file, or that an error occurred
return FALSE;
}
BOOLEAN MakeFileManDirectory( STRING512 pcDirectory )
{
#ifndef USE_VFS
return CreateDirectory( pcDirectory, NULL );
#else
return FALSE;
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Removes ALL FILES in the specified directory (and all subdirectories with their files if fRecursive is TRUE)
// Use EraseDirectory() to simply delete directory contents without deleting the directory itself
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOLEAN RemoveFileManDirectory( STRING512 pcDirectory, BOOLEAN fRecursive )
{
#ifdef USE_VFS
// ignore 'recursive' flag, just delete every file in that subtree (but leave the directories)
return getVFS()->removeDirectoryFromFS(pcDirectory);
#else
WIN32_FIND_DATA sFindData;
HANDLE SearchHandle;
const CHAR8 *pFileSpec = "*.*";
BOOLEAN fDone = FALSE;
BOOLEAN fRetval=FALSE;
CHAR8 zOldDir[512];
CHAR8 zSubdirectory[512];
GetFileManCurrentDirectory( zOldDir );
if( !SetFileManCurrentDirectory( pcDirectory ) )
{
FastDebugMsg(String("RemoveFileManDirectory: ERROR - SetFileManCurrentDirectory on %s failed, error %d", pcDirectory, GetLastError()));
return( FALSE ); //Error going into directory
}
//If there are files in the directory, DELETE THEM
SearchHandle = FindFirstFile( pFileSpec, &sFindData);
if( SearchHandle != INVALID_HANDLE_VALUE )
{
fDone = FALSE;
do
{
// if the object is a directory
if( GetFileAttributes( sFindData.cFileName ) == FILE_ATTRIBUTE_DIRECTORY )
{
// only go in if the fRecursive flag is TRUE (like Deltree)
if (fRecursive)
{
sprintf(zSubdirectory, "%s\\%s", pcDirectory, sFindData.cFileName);
if ((strcmp(sFindData.cFileName, ".") != 0) && (strcmp(sFindData.cFileName, "..") != 0))
{
if (!RemoveFileManDirectory(zSubdirectory, TRUE))
{
FastDebugMsg(String("RemoveFileManDirectory: ERROR - Recursive call on %s failed", zSubdirectory));
break;
}
}
}
// otherwise, all the individual files will be deleted, but the subdirectories remain, causing
// RemoveDirectory() at the end to fail, thus this function will return FALSE in that event (failure)
}
else
{
FileDelete( sFindData.cFileName );
}
//find the next file in the directory
fRetval = FindNextFile( SearchHandle, &sFindData );
if( fRetval == 0 )
{
fDone = TRUE;
}
} while(!fDone);
// very important: close the find handle, or subsequent RemoveDirectory() calls will fail
FindClose( SearchHandle );
}
if( !SetFileManCurrentDirectory( zOldDir ) )
{
FastDebugMsg(String("RemoveFileManDirectory: ERROR - SetFileManCurrentDirectory on %s failed, error %d", zOldDir, GetLastError()));
return( FALSE ); //Error returning from subdirectory
}
// The directory MUST be empty
fRetval = RemoveDirectory( pcDirectory );
if (!fRetval)
{
FastDebugMsg(String("RemoveFileManDirectory: ERROR - RemoveDirectory on %s failed, error %d", pcDirectory, GetLastError()));
}
return fRetval;
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Removes ALL FILES in the specified directory but leaves the directory alone. Does not affect any subdirectories!
// Use RemoveFilemanDirectory() to also delete the directory itself, or to recursively delete subdirectories.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOLEAN EraseDirectory( STRING512 pcDirectory)
{
#ifdef USE_VFS
// ignore 'recursive' flag, just delete every file in that subtree (but leave the directories)
return getVFS()->removeDirectoryFromFS(pcDirectory);
#else
WIN32_FIND_DATA sFindData;
HANDLE SearchHandle;
const CHAR8 *pFileSpec = "*.*";
BOOLEAN fDone = FALSE;
CHAR8 zOldDir[512];
GetFileManCurrentDirectory( zOldDir );
if( !SetFileManCurrentDirectory( pcDirectory ) )
{
FastDebugMsg(String("EraseDirectory: ERROR - SetFileManCurrentDirectory on %s failed, error %d", pcDirectory, GetLastError()));
return( FALSE ); //Error going into directory
}
//If there are files in the directory, DELETE THEM
SearchHandle = FindFirstFile( pFileSpec, &sFindData);
if( SearchHandle != INVALID_HANDLE_VALUE )
{
fDone = FALSE;
do
{
// if it's a file, not a directory
if( GetFileAttributes( sFindData.cFileName ) != FILE_ATTRIBUTES_DIRECTORY )
{
FileDelete( sFindData.cFileName );
}
//find the next file in the directory
if ( !FindNextFile( SearchHandle, &sFindData ))
{
fDone = TRUE;
}
} while(!fDone);
// very important: close the find handle, or subsequent RemoveDirectory() calls will fail
FindClose( SearchHandle );
}
// Snap: Delete the directory from the default Data catalogue (if it is there)
// Since the path can be either relative or absolute, try both methods
gDefaultDataCat.RemoveDir(pcDirectory, true);
gDefaultDataCat.RemoveDir(pcDirectory, false);
if( !SetFileManCurrentDirectory( zOldDir ) )
{
FastDebugMsg(String("EraseDirectory: ERROR - SetFileManCurrentDirectory on %s failed, error %d", zOldDir, GetLastError()));
return( FALSE ); //Error returning from directory
}
return( TRUE );
#endif
}
BOOLEAN GetExecutableDirectory( STRING512 pcDirectory )
{
#ifdef USE_VFS
vfs::Path exe_dir, exe_file;
vfs::OS::getExecutablePath(exe_dir, exe_file);
strncpy(pcDirectory, exe_dir.to_string().c_str(), 512);
return true;
#else
SGPFILENAME ModuleFilename;
UINT32 cnt;
if ( GetModuleFileName( NULL, ModuleFilename, sizeof( ModuleFilename ) ) == 0 )
{
return( FALSE );
}
// Now get directory
strcpy( pcDirectory, ModuleFilename );
for ( cnt = strlen( pcDirectory ) - 1; cnt >= 0; cnt -- )
{
if ( pcDirectory[ cnt ] == '\\' )
{
pcDirectory[ cnt ] = '\0';
break;
}
}
#endif
return( TRUE );
}
#ifdef USE_VFS
static vfs::CVirtualFileSystem::Iterator file_iter;
#endif
BOOLEAN GetFileFirst( CHAR8 * pSpec, GETFILESTRUCT *pGFStruct )
{
#ifdef USE_VFS
CHECKF( pSpec != NULL );
CHECKF( pGFStruct != NULL );
file_iter = getVFS()->begin(pSpec);
if(!file_iter.end())
{
vfs::Path const& path = file_iter.value()->getName();
std::string s = path.to_string();
::size_t size = s.length();
size = std::min< ::size_t>(size,260-1);
sprintf( pGFStruct->zFileName, s.c_str());
pGFStruct->zFileName[size] = 0;
pGFStruct->iFindHandle = 0;
pGFStruct->uiFileSize = file_iter.value()->getSize();
pGFStruct->uiFileAttribs = ( file_iter.value()->implementsWritable() ? FILE_IS_NORMAL : FILE_IS_READONLY );
return TRUE;
}
return FALSE;
#else
INT32 x,iWhich=0;
BOOLEAN fFound;
CHECKF( pSpec != NULL );
CHECKF( pGFStruct != NULL );
fFound = FALSE;
for( x = 0; x < 20 && !fFound; x++)
{
if( !fFindInfoInUse[x] )
{
iWhich = x;
fFound = TRUE;
}
}
if ( !fFound )
return(FALSE);
pGFStruct->iFindHandle = iWhich;
hFindInfoHandle[iWhich] = FindFirstFile( pSpec, &Win32FindInfo[iWhich] );
if ( hFindInfoHandle[iWhich] == INVALID_HANDLE_VALUE )
return(FALSE);
fFindInfoInUse[iWhich] = TRUE;
W32toSGPFileFind( pGFStruct, &Win32FindInfo[iWhich] );
return(TRUE);
#endif
}
BOOLEAN GetFileNext( GETFILESTRUCT *pGFStruct )
{
#ifdef USE_VFS
if(!file_iter.end())
{
file_iter.next();
}
if(!file_iter.end())
{
vfs::Path const& path = file_iter.value()->getName();
std::string s = path.to_string();
::size_t size = s.length();
size = std::min< ::size_t>(size,260-1);
sprintf( pGFStruct->zFileName, s.c_str());
pGFStruct->zFileName[size] = 0;
pGFStruct->iFindHandle = 0;
pGFStruct->uiFileSize = file_iter.value()->getSize();
pGFStruct->uiFileAttribs = ( file_iter.value()->implementsWritable() ? FILE_IS_NORMAL : FILE_IS_READONLY );
return TRUE;
}
return FALSE;
#else
CHECKF( pGFStruct != NULL );
if ( FindNextFile(hFindInfoHandle[pGFStruct->iFindHandle], &Win32FindInfo[pGFStruct->iFindHandle]) )
{
W32toSGPFileFind( pGFStruct, &Win32FindInfo[pGFStruct->iFindHandle] );
return(TRUE);
}
return(FALSE);
#endif
}
void GetFileClose( GETFILESTRUCT *pGFStruct )
{
#ifdef USE_VFS
file_iter = vfs::CVirtualFileSystem::Iterator();
#else
if ( pGFStruct == NULL )
return;
FindClose( hFindInfoHandle[pGFStruct->iFindHandle] );
hFindInfoHandle[pGFStruct->iFindHandle] = INVALID_HANDLE_VALUE;
fFindInfoInUse[pGFStruct->iFindHandle] = FALSE;
return;
#endif
}
void W32toSGPFileFind( GETFILESTRUCT *pGFStruct, WIN32_FIND_DATA *pW32Struct )
{
UINT32 uiAttribMask;
// Copy the filename
strcpy(pGFStruct->zFileName, pW32Struct->cFileName);
// Get file size
if ( pW32Struct->nFileSizeHigh != 0 )
pGFStruct->uiFileSize = 0xffffffff;
else
pGFStruct->uiFileSize = pW32Struct->nFileSizeLow;
// Copy the file attributes
pGFStruct->uiFileAttribs = 0;
for( uiAttribMask = 0x80000000; uiAttribMask > 0; uiAttribMask >>= 1)
{
switch( pW32Struct->dwFileAttributes & uiAttribMask )
{
case FILE_ATTRIBUTE_ARCHIVE:
pGFStruct->uiFileAttribs |= FILE_IS_ARCHIVE;
break;
case FILE_ATTRIBUTE_DIRECTORY:
pGFStruct->uiFileAttribs |= FILE_IS_DIRECTORY;
break;
case FILE_ATTRIBUTE_HIDDEN:
pGFStruct->uiFileAttribs |= FILE_IS_HIDDEN;
break;
case FILE_ATTRIBUTE_NORMAL:
pGFStruct->uiFileAttribs |= FILE_IS_NORMAL;
break;
case FILE_ATTRIBUTE_READONLY:
pGFStruct->uiFileAttribs |= FILE_IS_READONLY;
break;
case FILE_ATTRIBUTE_SYSTEM:
pGFStruct->uiFileAttribs |= FILE_IS_SYSTEM;
break;
case FILE_ATTRIBUTE_TEMPORARY:
pGFStruct->uiFileAttribs |= FILE_IS_TEMPORARY;
break;
case FILE_ATTRIBUTE_COMPRESSED:
pGFStruct->uiFileAttribs |= FILE_IS_COMPRESSED;
break;
case FILE_ATTRIBUTE_OFFLINE:
pGFStruct->uiFileAttribs |= FILE_IS_OFFLINE;
break;
}
}
}
BOOLEAN FileCopy(STR strSrcFile, STR strDstFile, BOOLEAN fFailIfExists)
{
return(CopyFile(strSrcFile, strDstFile, fFailIfExists));
// Not needed, use Windows CopyFile
/*
HWFILE hFile;
UINT32 uiSize;
CHAR *pBuffer;
UINT32 uiBytesRead, uiBytesWritten;
// open source file
hFile = FileOpen(strSrcFile, FILE_ACCESS_READ, FALSE);
if (hFile == 0)
{
FastDebugMsg(String("FileCopy: FileOpen failed on Src file %s", strSrcFile));
return(FALSE);
}
// get its size
uiSize = FileGetSize(hFile);
if (uiSize == 0)
{
FastDebugMsg(String("FileCopy: size is 0, Src file %s", strSrcFile));
FileClose(hFile);
return(FALSE);
}
// allocate a buffer big enough to hold the entire file
pBuffer = MemAlloc(uiSize);
if (pBuffer == NULL)
{
FastDebugMsg(String("FileCopy: ERROR - MemAlloc pBuffer failed, size %d", uiSize));
FileClose(hFile);
return(FALSE);
}
// read the file into memory
if (!FileRead(hFile, pBuffer, uiSize, &uiBytesRead))
{
FastDebugMsg(String("FileCopy: FileRead failed, file %s", strSrcFile));
FileClose(hFile);
return(FALSE);
}
// close source file
FileClose(hFile);
// open destination file
hFile = FileOpen(strDstFile, FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE);
if (hFile == 0)
{
FastDebugMsg(String("FileCopy: FileOpen failed on Dst file %s", strDstFile));
return(FALSE);
}
// write buffer to the destination file
if (!FileWrite(hFile, pBuffer, uiSize, &uiBytesWritten))
{
FastDebugMsg(String("FileCopy: FileWrite failed, file %s", strDstFile));
FileClose(hFile);
return(FALSE);
}
// close destination file
FileClose(hFile);
MemFree(pBuffer);
pBuffer = NULL;
return(TRUE);
*/
}
BOOLEAN FileMove(STR strOldName, STR strNewName)
{
// rename
return(MoveFile(strOldName, strNewName));
}
//Additions by Kris Morness
BOOLEAN FileSetAttributes( STR strFilename, UINT32 uiNewAttribs )
{
UINT32 uiFileAttrib = 0;
if( uiNewAttribs & FILE_ATTRIBUTES_ARCHIVE )
uiFileAttrib |= FILE_ATTRIBUTE_ARCHIVE;
if( uiNewAttribs & FILE_ATTRIBUTES_HIDDEN )
uiFileAttrib |= FILE_ATTRIBUTE_HIDDEN;
if( uiNewAttribs & FILE_ATTRIBUTES_NORMAL )
uiFileAttrib |= FILE_ATTRIBUTE_NORMAL;
if( uiNewAttribs & FILE_ATTRIBUTES_OFFLINE )
uiFileAttrib |= FILE_ATTRIBUTE_OFFLINE;
if( uiNewAttribs & FILE_ATTRIBUTES_READONLY )
uiFileAttrib |= FILE_ATTRIBUTE_READONLY;
if( uiNewAttribs & FILE_ATTRIBUTES_SYSTEM )
uiFileAttrib |= FILE_ATTRIBUTE_SYSTEM;
if( uiNewAttribs & FILE_ATTRIBUTES_TEMPORARY )
uiFileAttrib |= FILE_ATTRIBUTE_TEMPORARY;
return SetFileAttributes( strFilename, uiFileAttrib );
}
UINT32 FileGetAttributes( STR strFilename )
{
UINT32 uiAttribs = 0;
UINT32 uiFileAttrib = 0;
uiAttribs = GetFileAttributes( strFilename );
if( uiAttribs == 0xFFFFFFFF )
return( uiAttribs );
if( uiAttribs & FILE_ATTRIBUTE_ARCHIVE )
uiFileAttrib |= FILE_ATTRIBUTES_ARCHIVE;
if( uiAttribs & FILE_ATTRIBUTE_HIDDEN )
uiFileAttrib |= FILE_ATTRIBUTES_HIDDEN;
if( uiAttribs & FILE_ATTRIBUTE_NORMAL )
uiFileAttrib |= FILE_ATTRIBUTES_NORMAL;
if( uiAttribs & FILE_ATTRIBUTE_OFFLINE )
uiFileAttrib |= FILE_ATTRIBUTES_OFFLINE;
if( uiAttribs & FILE_ATTRIBUTE_READONLY )
uiFileAttrib |= FILE_ATTRIBUTES_READONLY;
if( uiAttribs & FILE_ATTRIBUTE_SYSTEM )
uiFileAttrib |= FILE_ATTRIBUTES_SYSTEM;
if( uiAttribs & FILE_ATTRIBUTE_TEMPORARY )
uiFileAttrib |= FILE_ATTRIBUTES_TEMPORARY;
if( uiAttribs & FILE_ATTRIBUTE_DIRECTORY )
uiFileAttrib |= FILE_ATTRIBUTES_DIRECTORY;
return( uiFileAttrib );
}
BOOLEAN FileClearAttributes( STR strFilename )
{
#ifndef USE_VFS
return SetFileAttributes( (LPCSTR) strFilename, FILE_ATTRIBUTE_NORMAL );
#else
return TRUE;
#endif
}
//returns true if at end of file, else false
BOOLEAN FileCheckEndOfFile( HWFILE hFile )
{
#ifdef USE_VFS
vfs::size_t current_position, max_position;
vfs::IBaseFile *pFile = (vfs::IBaseFile*)hFile;
if(pFile && (s_mapFiles[pFile].op == SOperation::WRITE))
{
vfs::tWritableFile *pWF = vfs::tWritableFile::cast(pFile);
if(pWF)
{
current_position = pWF->getWritePosition();
max_position = pWF->getSize();
return current_position >= max_position;
}
}
else if(pFile && (s_mapFiles[pFile].op == SOperation::READ))
{
vfs::tReadableFile *pRF = vfs::tReadableFile::cast(pFile);
if(pRF)
{
current_position = pRF->getReadPosition();
max_position = pRF->getSize();
return current_position >= max_position;
}
}
return FALSE;
#else
INT16 sLibraryID;
UINT32 uiFileNum;
HANDLE hRealFile;
// UINT8 Data;
UINT32 uiOldFilePtrLoc=0;
UINT32 uiEndOfFilePtrLoc=0;
UINT32 temp=0;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//Get the handle to the real file
hRealFile = gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle;
//Get the current position of the file pointer
uiOldFilePtrLoc = SetFilePointer( hRealFile, 0, NULL, FILE_CURRENT );
//Get the end of file ptr location
uiEndOfFilePtrLoc = SetFilePointer( hRealFile, 0, NULL, FILE_END );
//reset back to the original location
temp = SetFilePointer( hRealFile, -( (INT32)( uiEndOfFilePtrLoc - uiOldFilePtrLoc ) ), NULL, FILE_END );
//if the 2 pointers are the same, we are at the end of a file
if( uiEndOfFilePtrLoc <= uiOldFilePtrLoc )
{
return( 1 );
}
}
//else it is a library file
else
{
//if the database is initialized
if( gFileDataBase.fInitialized )
{
//if the library is open
if( IsLibraryOpened( sLibraryID ) )
{
//if the file is opened
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFileID != 0 )
{
UINT32 uiLength; //uiOffsetInLibrary
// HANDLE hLibraryFile;
// UINT32 uiNumBytesRead;
UINT32 uiCurPos;
uiLength = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].pFileHeader->uiFileLength;
uiCurPos = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFilePosInFile;
//if we are trying to read more data then the size of the file, return an error
if( uiCurPos >= uiLength )
{
return( TRUE );
}
}
}
}
}
//we are not and the end of a file
return( 0 );
#endif
}
BOOLEAN GetFileManFileTime( HWFILE hFile, SGP_FILETIME *pCreationTime, SGP_FILETIME *pLastAccessedTime, SGP_FILETIME *pLastWriteTime )
{
#ifndef USE_VFS
HANDLE hRealFile;
INT16 sLibraryID;
UINT32 uiFileNum;
FILETIME sCreationUtcFileTime;
FILETIME sLastAccessedUtcFileTime;
FILETIME sLastWriteUtcFileTime;
//Initialize the passed in variables
if (pCreationTime) memset( pCreationTime, 0, sizeof( SGP_FILETIME ) );
if (pLastAccessedTime) memset( pLastAccessedTime, 0, sizeof( SGP_FILETIME ) );
if (pLastWriteTime) memset( pLastWriteTime, 0, sizeof( SGP_FILETIME ) );
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its a real file, read the data from the file
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//get the real file handle to the file
hRealFile = gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle;
//Gets the UTC file time for the 'real' file
GetFileTime( hRealFile, &sCreationUtcFileTime, &sLastAccessedUtcFileTime, &sLastWriteUtcFileTime );
//converts the creation UTC file time to the current time used for the file
if(pCreationTime)
FileTimeToLocalFileTime( &sCreationUtcFileTime, pCreationTime );
//converts the accessed UTC file time to the current time used for the file
if (pLastAccessedTime)
FileTimeToLocalFileTime( &sLastAccessedUtcFileTime, pLastAccessedTime );
//converts the write UTC file time to the current time used for the file
if (pLastWriteTime)
FileTimeToLocalFileTime( &sLastWriteUtcFileTime, pLastWriteTime );
}
else
{
//if the database is initialized
if( gFileDataBase.fInitialized )
{
//if the library is open
if( IsLibraryOpened( sLibraryID ) )
{
//if the file is opened
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFileID != 0 )
{
if( !GetLibraryFileTime( sLibraryID, uiFileNum, pLastWriteTime ) )
{
return( FALSE );
}
}
}
}
}
return( TRUE );
#else
return( FALSE );
#endif
}
INT32 CompareSGPFileTimes( SGP_FILETIME *pFirstFileTime, SGP_FILETIME *pSecondFileTime )
{
return( CompareFileTime( pFirstFileTime, pSecondFileTime ) );
}
UINT32 FileSize(STR strFilename)
{
#ifdef USE_VFS
vfs::IBaseFile *pFile = getVFS()->getFile(vfs::Path(strFilename));
if(pFile)
{
return pFile->getSize();
}
return 0;
#else
HWFILE hFile;
UINT32 uiSize;
if((hFile=FileOpen(strFilename, FILE_OPEN_EXISTING | FILE_ACCESS_READ, FALSE))==0)
return(0);
uiSize=FileGetSize(hFile);
FileClose(hFile);
return(uiSize);
#endif
}
HANDLE GetRealFileHandleFromFileManFileHandle( HWFILE hFile )
{
#ifndef USE_VFS
INT16 sLibraryID;
UINT32 uiFileNum;
GetLibraryAndFileIDFromLibraryFileHandle( hFile, &sLibraryID, &uiFileNum );
//if its the 'real file' library
if( sLibraryID == REAL_FILE_LIBRARY_ID )
{
//if its not already closed
if( gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].uiFileID != 0 )
{
return( gFileDataBase.RealFiles.pRealFilesOpen[ uiFileNum ].hRealFileHandle );
}
}
else
{
//if the file is not opened, dont close it
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFileID != 0 )
{
return( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle );
}
}
#endif
return( 0 );
}
//**************************************************************************
//
// AddSubdirectoryToPath
//
// Puts a subdirectory of the current working directory into the current
// task's system path.
//
// Parameter List :
// Return Value :
// Modification history :
//
// 10June98:DB ->creation
//
//**************************************************************************
BOOLEAN AddSubdirectoryToPath(CHAR8 *pDirectory)
{
CHAR8 *pSystemPath;
CHAR8 *pPath;
UINT32 uiPathLen;
// Check for NULL
if(!pDirectory)
return(FALSE);
// Check for zero length string
if(!strlen(pDirectory))
return(FALSE);
if((pSystemPath=(CHAR8 *)MemAlloc(_MAX_PATH))==NULL)
return(FALSE);
memset(pSystemPath, 0, _MAX_PATH);
if((pPath=(CHAR8 *)MemAlloc(_MAX_PATH))==NULL)
{
MemFree(pSystemPath);
return(FALSE);
}
memset(pPath, 0, _MAX_PATH);
// Builds a path to the directory with the SR DLL files.
_getcwd(pPath, _MAX_PATH);
uiPathLen=strlen(pPath);
if(uiPathLen)
uiPathLen--;
if(pPath[uiPathLen]!='\\')
strcat(pPath, "\\");
strcat(pPath, pDirectory);
// Appends it to the path for the current task
if(GetEnvironmentVariable("PATH", pSystemPath, _MAX_PATH))
{
strcat(pSystemPath, ";");
strcat(pSystemPath, pPath);
SetEnvironmentVariable("PATH", pSystemPath);
MemFree(pSystemPath);
MemFree(pPath);
return(TRUE);
}
else
{
MemFree(pSystemPath);
MemFree(pPath);
return(FALSE);
}
}
UINT32 GetFreeSpaceOnHardDriveWhereGameIsRunningFrom( )
{
STRING512 zExecDir;
STRING512 zDrive;
STRING512 zDir;
STRING512 zFileName;
STRING512 zExt;
UINT32 uiFreeSpace = 0;
GetExecutableDirectory( zExecDir );
//get the drive letter from the exec dir
_splitpath( zExecDir, zDrive, zDir, zFileName, zExt);
sprintf( zDrive, "%s\\", zDrive );
uiFreeSpace = GetFreeSpaceOnHardDrive( zDrive );
return( uiFreeSpace );
}
UINT32 GetFreeSpaceOnHardDrive( STR pzDriveLetter )
{
UINT32 uiBytesFree=0;
UINT32 uiSectorsPerCluster=0;
UINT32 uiBytesPerSector=0;
UINT32 uiNumberOfFreeClusters=0;
UINT32 uiTotalNumberOfClusters=0;
if( !GetDiskFreeSpace( pzDriveLetter, (LPDWORD) &uiSectorsPerCluster, (LPDWORD) &uiBytesPerSector,
(LPDWORD) &uiNumberOfFreeClusters, (LPDWORD) &uiTotalNumberOfClusters ) )
{
UINT32 uiLastError = GetLastError();
char zString[1024];
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, uiLastError, 0, zString, 1024, NULL);
return( TRUE );
}
uiBytesFree = uiBytesPerSector * uiNumberOfFreeClusters * uiSectorsPerCluster;
return( uiBytesFree );
}