TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
FileStream.cpp File Reference
#include "../CascLib.h"
#include "../CascCommon.h"
+ Include dependency graph for FileStream.cpp:

Macros

#define __CASCLIB_SELF__
 
#define BLOCK4_BLOCK_SIZE   0x4000
 
#define BLOCK4_HASH_SIZE   0x20
 
#define BLOCK4_MAX_BLOCKS   0x00002000
 
#define BLOCK4_MAX_FSIZE   0x08040000
 

Functions

static DWORD StringToInt (const char *szString)
 
static void BaseNone_Init (TFileStream *)
 
static bool BaseFile_Create (TFileStream *pStream)
 
static bool BaseFile_Open (TFileStream *pStream, const TCHAR *szFileName, DWORD dwStreamFlags)
 
static bool BaseFile_Read (TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
 
static bool BaseFile_Write (TFileStream *pStream, ULONGLONG *pByteOffset, const void *pvBuffer, DWORD dwBytesToWrite)
 
static bool BaseFile_Resize (TFileStream *pStream, ULONGLONG NewFileSize)
 
static bool BaseFile_GetSize (TFileStream *pStream, ULONGLONG *pFileSize)
 
static bool BaseFile_GetPos (TFileStream *pStream, ULONGLONG *pByteOffset)
 
static bool BaseFile_Replace (TFileStream *pStream, TFileStream *pNewStream)
 
static void BaseFile_Close (TFileStream *pStream)
 
static void BaseFile_Init (TFileStream *pStream)
 
static bool BaseMap_Open (TFileStream *pStream, const TCHAR *szFileName, DWORD dwStreamFlags)
 
static bool BaseMap_Read (TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
 
static void BaseMap_Close (TFileStream *pStream)
 
static void BaseMap_Init (TFileStream *pStream)
 
static const TCHARBaseHttp_ExtractServerName (const TCHAR *szFileName, TCHAR *szServerName)
 
static bool BaseHttp_Open (TFileStream *pStream, const TCHAR *szFileName, DWORD dwStreamFlags)
 
static bool BaseHttp_Read (TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
 
static void BaseHttp_Close (TFileStream *pStream)
 
static void BaseHttp_Init (TFileStream *pStream)
 
static bool BlockStream_Read (TBlockStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
 
static bool BlockStream_GetSize (TFileStream *pStream, ULONGLONG *pFileSize)
 
static bool BlockStream_GetPos (TFileStream *pStream, ULONGLONG *pByteOffset)
 
static void BlockStream_Close (TBlockStream *pStream)
 
static TFileStreamAllocateFileStream (const TCHAR *szFileName, size_t StreamSize, DWORD dwStreamFlags)
 
static DWORD FlatStream_CheckFile (TBlockStream *pStream)
 
static bool FlatStream_LoadBitmap (TBlockStream *pStream)
 
static void FlatStream_UpdateBitmap (TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset)
 
static bool FlatStream_BlockCheck (TBlockStream *pStream, ULONGLONG BlockOffset)
 
static bool FlatStream_BlockRead (TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
 
static void FlatStream_Close (TBlockStream *pStream)
 
static bool FlatStream_CreateMirror (TBlockStream *pStream)
 
static TFileStreamFlatStream_Open (const TCHAR *szFileName, DWORD dwStreamFlags)
 
static bool IsPartHeader (PPART_FILE_HEADER pPartHdr)
 
static DWORD PartStream_CheckFile (TBlockStream *pStream)
 
static bool PartStream_LoadBitmap (TBlockStream *pStream)
 
static void PartStream_UpdateBitmap (TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, ULONGLONG RealOffset)
 
static bool PartStream_BlockCheck (TBlockStream *pStream, ULONGLONG BlockOffset)
 
static bool PartStream_BlockRead (TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
 
static void PartStream_Close (TBlockStream *pStream)
 
static bool PartStream_CreateMirror (TBlockStream *pStream)
 
static TFileStreamPartStream_Open (const TCHAR *szFileName, DWORD dwStreamFlags)
 
static DWORD Rol32 (DWORD dwValue, DWORD dwRolCount)
 
static void CreateKeyFromAuthCode (LPBYTE pbKeyBuffer, const char *szAuthCode)
 
static void DecryptFileChunk (DWORD *ChunkData, LPBYTE pbKey, ULONGLONG ByteOffset, DWORD dwLength)
 
static bool EncrStream_DetectFileKey (TEncryptedStream *pStream)
 
static bool EncrStream_BlockRead (TEncryptedStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
 
static TFileStreamEncrStream_Open (const TCHAR *szFileName, DWORD dwStreamFlags)
 
static bool Block4Stream_BlockRead (TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
 
static void Block4Stream_Close (TBlockStream *pStream)
 
static TFileStreamBlock4Stream_Open (const TCHAR *szFileName, DWORD dwStreamFlags)
 
TFileStreamFileStream_CreateFile (const TCHAR *szFileName, DWORD dwStreamFlags)
 
TFileStreamFileStream_OpenFile (const TCHAR *szFileName, DWORD dwStreamFlags)
 
const TCHARFileStream_GetFileName (TFileStream *pStream)
 
size_t FileStream_Prefix (const TCHAR *szFileName, DWORD *pdwProvider)
 
bool FileStream_SetCallback (TFileStream *pStream, STREAM_DOWNLOAD_CALLBACK pfnCallback, void *pvUserData)
 
bool FileStream_Read (TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
 
bool FileStream_Write (TFileStream *pStream, ULONGLONG *pByteOffset, const void *pvBuffer, DWORD dwBytesToWrite)
 
bool FileStream_GetSize (TFileStream *pStream, ULONGLONG *pFileSize)
 
bool FileStream_SetSize (TFileStream *pStream, ULONGLONG NewFileSize)
 
bool FileStream_GetPos (TFileStream *pStream, ULONGLONG *pByteOffset)
 
bool FileStream_GetTime (TFileStream *pStream, ULONGLONG *pFileTime)
 
bool FileStream_GetFlags (TFileStream *pStream, PDWORD pdwStreamFlags)
 
bool FileStream_Replace (TFileStream *pStream, TFileStream *pNewStream)
 
void FileStream_Close (TFileStream *pStream)
 

Variables

static STREAM_INIT StreamBaseInit [4]
 
static const char * szKeyTemplate = "expand 32-byte k000000000000000000000000000000000000000000000000"
 
static const char * AuthCodeArray []
 

Macro Definition Documentation

#define __CASCLIB_SELF__
#define BLOCK4_BLOCK_SIZE   0x4000
#define BLOCK4_HASH_SIZE   0x20
#define BLOCK4_MAX_BLOCKS   0x00002000
#define BLOCK4_MAX_FSIZE   0x08040000

Function Documentation

static TFileStream* AllocateFileStream ( const TCHAR szFileName,
size_t  StreamSize,
DWORD  dwStreamFlags 
)
static
981 {
982  TFileStream * pMaster = NULL;
983  TFileStream * pStream;
984  const TCHAR * szNextFile = szFileName;
985  size_t FileNameSize;
986 
987  // Sanity check
988  assert(StreamSize != 0);
989 
990  // The caller can specify chain of files in the following form:
991  // C:\archive.MPQ*http://www.server.com/MPQs/archive-server.MPQ
992  // In that case, we use the part after "*" as master file name
993  while(szNextFile[0] != 0 && szNextFile[0] != _T('*'))
994  szNextFile++;
995  FileNameSize = (size_t)((szNextFile - szFileName) * sizeof(TCHAR));
996 
997  // If we have a next file, we need to open it as master stream
998  // Note that we don't care if the master stream exists or not,
999  // If it doesn't, later attempts to read missing file block will fail
1000  if(szNextFile[0] == _T('*'))
1001  {
1002  // Don't allow another master file in the string
1003  if(_tcschr(szNextFile + 1, _T('*')) != NULL)
1004  {
1006  return NULL;
1007  }
1008 
1009  // Open the master file
1010  pMaster = FileStream_OpenFile(szNextFile + 1, STREAM_FLAG_READ_ONLY);
1011  }
1012 
1013  // Allocate the stream structure for the given stream type
1014  pStream = (TFileStream *)CASC_ALLOC(BYTE, StreamSize + FileNameSize + sizeof(TCHAR));
1015  if(pStream != NULL)
1016  {
1017  // Zero the entire structure
1018  memset(pStream, 0, StreamSize);
1019  pStream->pMaster = pMaster;
1020  pStream->dwFlags = dwStreamFlags;
1021 
1022  // Initialize the file name
1023  pStream->szFileName = (TCHAR *)((BYTE *)pStream + StreamSize);
1024  memcpy(pStream->szFileName, szFileName, FileNameSize);
1025  pStream->szFileName[FileNameSize / sizeof(TCHAR)] = 0;
1026 
1027  // Initialize the stream functions
1028  StreamBaseInit[dwStreamFlags & 0x03](pStream);
1029  }
1030 
1031  return pStream;
1032 }
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
arena_t NULL
Definition: jemalloc_internal.h:624
char TCHAR
Definition: CascPort.h:148
#define _T(x)
Definition: CascPort.h:171
void SetLastError(int nError)
Definition: Common.cpp:75
TCHAR * szFileName
Definition: FileStream.h:182
TFileStream * pMaster
Definition: FileStream.h:181
TFileStream * FileStream_OpenFile(const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:2384
#define _tcschr
Definition: CascPort.h:175
static STREAM_INIT StreamBaseInit[4]
Definition: FileStream.cpp:966
DWORD dwFlags
Definition: FileStream.h:187
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
Definition: FileStream.h:153
unsigned char BYTE
Definition: CascPort.h:136
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void BaseFile_Close ( TFileStream pStream)
static
382 {
383  if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE)
384  {
385 #ifdef PLATFORM_WINDOWS
386  CloseHandle(pStream->Base.File.hFile);
387 #endif
388 
389 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
390  close((intptr_t)pStream->Base.File.hFile);
391 #endif
392  }
393 
394  // Also invalidate the handle
395  pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
396 }
TBaseProviderData Base
Definition: FileStream.h:178
struct TBaseProviderData::@0 File
HANDLE hFile
Definition: FileStream.h:132
#define INVALID_HANDLE_VALUE
Definition: CascPort.h:169
_W64 signed int intptr_t
Definition: stdint.h:118

+ Here is the caller graph for this function:

static bool BaseFile_Create ( TFileStream pStream)
static
53 {
54 #ifdef PLATFORM_WINDOWS
55  {
56  DWORD dwWriteShare = (pStream->dwFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0;
57 
58  pStream->Base.File.hFile = CreateFile(pStream->szFileName,
59  GENERIC_READ | GENERIC_WRITE,
60  dwWriteShare | FILE_SHARE_READ,
61  NULL,
62  CREATE_ALWAYS,
63  0,
64  NULL);
65  if(pStream->Base.File.hFile == INVALID_HANDLE_VALUE)
66  return false;
67  }
68 #endif
69 
70 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
71  {
72  intptr_t handle;
73 
74  handle = open(pStream->szFileName, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
75  if(handle == -1)
76  {
77  SetLastError(errno);
78  return false;
79  }
80 
81  pStream->Base.File.hFile = (HANDLE)handle;
82  }
83 #endif
84 
85  // Reset the file size and position
86  pStream->Base.File.FileSize = 0;
87  pStream->Base.File.FilePos = 0;
88  return true;
89 }
void * HANDLE
Definition: CascPort.h:146
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
struct TBaseProviderData::@0 File
ULONGLONG FileSize
Definition: FileStream.h:129
void SetLastError(int nError)
Definition: Common.cpp:75
TCHAR * szFileName
Definition: FileStream.h:182
HANDLE hFile
Definition: FileStream.h:132
unsigned int DWORD
Definition: CascPort.h:139
#define INVALID_HANDLE_VALUE
Definition: CascPort.h:169
DWORD dwFlags
Definition: FileStream.h:187
_W64 signed int intptr_t
Definition: stdint.h:118
ULONGLONG FilePos
Definition: FileStream.h:130
#define STREAM_FLAG_WRITE_SHARE
Definition: CascLib.h:57

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool BaseFile_GetPos ( TFileStream pStream,
ULONGLONG pByteOffset 
)
static
350 {
351  // Note: Used by all thre base providers.
352  // Requires the TBaseData union to have the same layout for all three base providers
353  *pByteOffset = pStream->Base.File.FilePos;
354  return true;
355 }
TBaseProviderData Base
Definition: FileStream.h:178
struct TBaseProviderData::@0 File
ULONGLONG FilePos
Definition: FileStream.h:130

+ Here is the caller graph for this function:

static bool BaseFile_GetSize ( TFileStream pStream,
ULONGLONG pFileSize 
)
static
341 {
342  // Note: Used by all thre base providers.
343  // Requires the TBaseData union to have the same layout for all three base providers
344  *pFileSize = pStream->Base.File.FileSize;
345  return true;
346 }
TBaseProviderData Base
Definition: FileStream.h:178
struct TBaseProviderData::@0 File
ULONGLONG FileSize
Definition: FileStream.h:129

+ Here is the caller graph for this function:

static void BaseFile_Init ( TFileStream pStream)
static
400 {
401  pStream->BaseCreate = BaseFile_Create;
402  pStream->BaseOpen = BaseFile_Open;
403  pStream->BaseRead = BaseFile_Read;
404  pStream->BaseWrite = BaseFile_Write;
405  pStream->BaseResize = BaseFile_Resize;
406  pStream->BaseGetSize = BaseFile_GetSize;
407  pStream->BaseGetPos = BaseFile_GetPos;
408  pStream->BaseClose = BaseFile_Close;
409 }
static bool BaseFile_Read(TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:154
static bool BaseFile_Write(TFileStream *pStream, ULONGLONG *pByteOffset, const void *pvBuffer, DWORD dwBytesToWrite)
Definition: FileStream.cpp:229
STREAM_OPEN BaseOpen
Definition: FileStream.h:169
STREAM_READ BaseRead
Definition: FileStream.h:170
static bool BaseFile_GetPos(TFileStream *pStream, ULONGLONG *pByteOffset)
Definition: FileStream.cpp:349
static void BaseFile_Close(TFileStream *pStream)
Definition: FileStream.cpp:381
STREAM_RESIZE BaseResize
Definition: FileStream.h:172
STREAM_WRITE BaseWrite
Definition: FileStream.h:171
static bool BaseFile_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:340
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
STREAM_CREATE BaseCreate
Definition: FileStream.h:168
STREAM_GETPOS BaseGetPos
Definition: FileStream.h:174
static bool BaseFile_Resize(TFileStream *pStream, ULONGLONG NewFileSize)
Definition: FileStream.cpp:298
static bool BaseFile_Create(TFileStream *pStream)
Definition: FileStream.cpp:52
static bool BaseFile_Open(TFileStream *pStream, const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:91
STREAM_GETSIZE BaseGetSize
Definition: FileStream.h:173

+ Here is the call graph for this function:

static bool BaseFile_Open ( TFileStream pStream,
const TCHAR szFileName,
DWORD  dwStreamFlags 
)
static
92 {
93 #ifdef PLATFORM_WINDOWS
94  {
95  ULARGE_INTEGER FileSize;
96  DWORD dwWriteAccess = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? 0 : FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES;
97  DWORD dwWriteShare = (dwStreamFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0;
98 
99  // Open the file
100  pStream->Base.File.hFile = CreateFile(szFileName,
101  FILE_READ_DATA | FILE_READ_ATTRIBUTES | dwWriteAccess,
102  FILE_SHARE_READ | dwWriteShare,
103  NULL,
104  OPEN_EXISTING,
105  0,
106  NULL);
107  if(pStream->Base.File.hFile == INVALID_HANDLE_VALUE)
108  return false;
109 
110  // Query the file size
111  FileSize.LowPart = GetFileSize(pStream->Base.File.hFile, &FileSize.HighPart);
112  pStream->Base.File.FileSize = FileSize.QuadPart;
113 
114  // Query last write time
115  GetFileTime(pStream->Base.File.hFile, NULL, NULL, (LPFILETIME)&pStream->Base.File.FileTime);
116  }
117 #endif
118 
119 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
120  {
121  struct stat64 fileinfo;
122  int oflag = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? O_RDONLY : O_RDWR;
123  intptr_t handle;
124 
125  // Open the file
126  handle = open(szFileName, oflag | O_LARGEFILE);
127  if(handle == -1)
128  {
129  SetLastError(errno);
130  return false;
131  }
132 
133  // Get the file size
134  if(fstat64(handle, &fileinfo) == -1)
135  {
136  SetLastError(errno);
137  return false;
138  }
139 
140  // time_t is number of seconds since 1.1.1970, UTC.
141  // 1 second = 10000000 (decimal) in FILETIME
142  // Set the start to 1.1.1970 00:00:00
143  pStream->Base.File.FileTime = 0x019DB1DED53E8000ULL + (10000000 * fileinfo.st_mtime);
144  pStream->Base.File.FileSize = (ULONGLONG)fileinfo.st_size;
145  pStream->Base.File.hFile = (HANDLE)handle;
146  }
147 #endif
148 
149  // Reset the file position
150  pStream->Base.File.FilePos = 0;
151  return true;
152 }
void * HANDLE
Definition: CascPort.h:146
unsigned long long ULONGLONG
Definition: CascPort.h:144
ULONGLONG FileTime
Definition: FileStream.h:131
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
struct TBaseProviderData::@0 File
ULONGLONG FileSize
Definition: FileStream.h:129
void SetLastError(int nError)
Definition: Common.cpp:75
HANDLE hFile
Definition: FileStream.h:132
unsigned int DWORD
Definition: CascPort.h:139
#define INVALID_HANDLE_VALUE
Definition: CascPort.h:169
_W64 signed int intptr_t
Definition: stdint.h:118
ULONGLONG FilePos
Definition: FileStream.h:130
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56
#define STREAM_FLAG_WRITE_SHARE
Definition: CascLib.h:57

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool BaseFile_Read ( TFileStream pStream,
ULONGLONG pByteOffset,
void *  pvBuffer,
DWORD  dwBytesToRead 
)
static
159 {
160  ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
161  DWORD dwBytesRead = 0; // Must be set by platform-specific code
162 
163 #ifdef PLATFORM_WINDOWS
164  {
165  // Note: CascLib no longer supports Windows 9x.
166  // Thus, we can use the OVERLAPPED structure to specify
167  // file offset to read from file. This allows us to skip
168  // one system call to SetFilePointer
169 
170  // Update the byte offset
171  pStream->Base.File.FilePos = ByteOffset;
172 
173  // Read the data
174  if(dwBytesToRead != 0)
175  {
176  OVERLAPPED Overlapped;
177 
178  Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
179  Overlapped.Offset = (DWORD)ByteOffset;
180  Overlapped.hEvent = NULL;
181  if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
182  return false;
183  }
184  }
185 #endif
186 
187 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
188  {
189  ssize_t bytes_read;
190 
191  // If the byte offset is different from the current file position,
192  // we have to update the file position
193  if(ByteOffset != pStream->Base.File.FilePos)
194  {
195  lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET);
196  pStream->Base.File.FilePos = ByteOffset;
197  }
198 
199  // Perform the read operation
200  if(dwBytesToRead != 0)
201  {
202  bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
203  if(bytes_read == -1)
204  {
205  SetLastError(errno);
206  return false;
207  }
208 
209  dwBytesRead = (DWORD)(size_t)bytes_read;
210  }
211  }
212 #endif
213 
214  // Increment the current file position by number of bytes read
215  // If the number of bytes read doesn't match to required amount, return false
216  pStream->Base.File.FilePos = ByteOffset + dwBytesRead;
217  if(dwBytesRead != dwBytesToRead)
219  return (dwBytesRead == dwBytesToRead);
220 }
unsigned long long ULONGLONG
Definition: CascPort.h:144
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
struct TBaseProviderData::@0 File
void SetLastError(int nError)
Definition: Common.cpp:75
#define PLATFORM_WINDOWS
Definition: CompilerDefs.h:22
HANDLE hFile
Definition: FileStream.h:132
unsigned int DWORD
Definition: CascPort.h:139
#define SEEK_SET
Definition: zconf.h:475
_W64 signed int intptr_t
Definition: stdint.h:118
#define ERROR_HANDLE_EOF
Definition: CascPort.h:216
ULONGLONG FilePos
Definition: FileStream.h:130

+ Here is the caller graph for this function:

static bool BaseFile_Replace ( TFileStream pStream,
TFileStream pNewStream 
)
static
359 {
360 #ifdef PLATFORM_WINDOWS
361  // Delete the original stream file. Don't check the result value,
362  // because if the file doesn't exist, it would fail
363  DeleteFile(pStream->szFileName);
364 
365  // Rename the new file to the old stream's file
366  return (bool)MoveFile(pNewStream->szFileName, pStream->szFileName);
367 #endif
368 
369 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
370  // "rename" on Linux also works if the target file exists
371  if(rename(pNewStream->szFileName, pStream->szFileName) == -1)
372  {
373  SetLastError(errno);
374  return false;
375  }
376 
377  return true;
378 #endif
379 }
void SetLastError(int nError)
Definition: Common.cpp:75
TCHAR * szFileName
Definition: FileStream.h:182

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool BaseFile_Resize ( TFileStream pStream,
ULONGLONG  NewFileSize 
)
static

pStream Pointer to an open stream NewFileSize New size of the file

299 {
300 #ifdef PLATFORM_WINDOWS
301  {
302  LONG FileSizeHi = (LONG)(NewFileSize >> 32);
303  LONG FileSizeLo;
304  DWORD dwNewPos;
305  bool bResult;
306 
307  // Set the position at the new file size
308  dwNewPos = SetFilePointer(pStream->Base.File.hFile, (LONG)NewFileSize, &FileSizeHi, FILE_BEGIN);
309  if(dwNewPos == INVALID_SET_FILE_POINTER && GetLastError() != ERROR_SUCCESS)
310  return false;
311 
312  // Set the current file pointer as the end of the file
313  bResult = (bool)SetEndOfFile(pStream->Base.File.hFile);
314  if(bResult)
315  pStream->Base.File.FileSize = NewFileSize;
316 
317  // Restore the file position
318  FileSizeHi = (LONG)(pStream->Base.File.FilePos >> 32);
319  FileSizeLo = (LONG)(pStream->Base.File.FilePos);
320  SetFilePointer(pStream->Base.File.hFile, FileSizeLo, &FileSizeHi, FILE_BEGIN);
321  return bResult;
322  }
323 #endif
324 
325 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
326  {
327  if(ftruncate64((intptr_t)pStream->Base.File.hFile, (off64_t)NewFileSize) == -1)
328  {
329  SetLastError(errno);
330  return false;
331  }
332 
333  pStream->Base.File.FileSize = NewFileSize;
334  return true;
335  }
336 #endif
337 }
TBaseProviderData Base
Definition: FileStream.h:178
int LONG
Definition: CascPort.h:138
struct TBaseProviderData::@0 File
#define bool
Definition: CascPort.h:16
ULONGLONG FileSize
Definition: FileStream.h:129
void SetLastError(int nError)
Definition: Common.cpp:75
#define FILE_BEGIN
Definition: CascPort.h:165
HANDLE hFile
Definition: FileStream.h:132
unsigned int DWORD
Definition: CascPort.h:139
int GetLastError()
Definition: Common.cpp:70
_W64 signed int intptr_t
Definition: stdint.h:118
ULONGLONG FilePos
Definition: FileStream.h:130
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool BaseFile_Write ( TFileStream pStream,
ULONGLONG pByteOffset,
const void *  pvBuffer,
DWORD  dwBytesToWrite 
)
static

pStream Pointer to an open stream pByteOffset Pointer to file byte offset. If NULL, writes to current position pvBuffer Pointer to data to be written dwBytesToWrite Number of bytes to write to the file

230 {
231  ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
232  DWORD dwBytesWritten = 0; // Must be set by platform-specific code
233 
234 #ifdef PLATFORM_WINDOWS
235  {
236  // Note: CascLib no longer supports Windows 9x.
237  // Thus, we can use the OVERLAPPED structure to specify
238  // file offset to read from file. This allows us to skip
239  // one system call to SetFilePointer
240 
241  // Update the byte offset
242  pStream->Base.File.FilePos = ByteOffset;
243 
244  // Read the data
245  if(dwBytesToWrite != 0)
246  {
247  OVERLAPPED Overlapped;
248 
249  Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
250  Overlapped.Offset = (DWORD)ByteOffset;
251  Overlapped.hEvent = NULL;
252  if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
253  return false;
254  }
255  }
256 #endif
257 
258 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
259  {
260  ssize_t bytes_written;
261 
262  // If the byte offset is different from the current file position,
263  // we have to update the file position
264  if(ByteOffset != pStream->Base.File.FilePos)
265  {
266  lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET);
267  pStream->Base.File.FilePos = ByteOffset;
268  }
269 
270  // Perform the read operation
271  bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
272  if(bytes_written == -1)
273  {
274  SetLastError(errno);
275  return false;
276  }
277 
278  dwBytesWritten = (DWORD)(size_t)bytes_written;
279  }
280 #endif
281 
282  // Increment the current file position by number of bytes read
283  pStream->Base.File.FilePos = ByteOffset + dwBytesWritten;
284 
285  // Also modify the file size, if needed
286  if(pStream->Base.File.FilePos > pStream->Base.File.FileSize)
287  pStream->Base.File.FileSize = pStream->Base.File.FilePos;
288 
289  if(dwBytesWritten != dwBytesToWrite)
291  return (dwBytesWritten == dwBytesToWrite);
292 }
unsigned long long ULONGLONG
Definition: CascPort.h:144
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
struct TBaseProviderData::@0 File
ULONGLONG FileSize
Definition: FileStream.h:129
void SetLastError(int nError)
Definition: Common.cpp:75
#define PLATFORM_WINDOWS
Definition: CompilerDefs.h:22
HANDLE hFile
Definition: FileStream.h:132
#define ERROR_DISK_FULL
Definition: CascPort.h:211
unsigned int DWORD
Definition: CascPort.h:139
#define SEEK_SET
Definition: zconf.h:475
_W64 signed int intptr_t
Definition: stdint.h:118
ULONGLONG FilePos
Definition: FileStream.h:130

+ Here is the caller graph for this function:

static void BaseHttp_Close ( TFileStream pStream)
static
766 {
767 #ifdef PLATFORM_WINDOWS
768  if(pStream->Base.Http.hConnect != NULL)
769  InternetCloseHandle(pStream->Base.Http.hConnect);
770  pStream->Base.Http.hConnect = NULL;
771 
772  if(pStream->Base.Http.hInternet != NULL)
773  InternetCloseHandle(pStream->Base.Http.hInternet);
774  pStream->Base.Http.hInternet = NULL;
775 #else
776  pStream = pStream;
777 #endif
778 }
struct TBaseProviderData::@2 Http
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
HANDLE hInternet
Definition: FileStream.h:148
HANDLE hConnect
Definition: FileStream.h:149

+ Here is the caller graph for this function:

static const TCHAR* BaseHttp_ExtractServerName ( const TCHAR szFileName,
TCHAR szServerName 
)
static
563 {
564  // Check for HTTP
565  if(!_tcsnicmp(szFileName, _T("http://"), 7))
566  szFileName += 7;
567 
568  // Cut off the server name
569  if(szServerName != NULL)
570  {
571  while(szFileName[0] != 0 && szFileName[0] != _T('/'))
572  *szServerName++ = *szFileName++;
573  *szServerName = 0;
574  }
575  else
576  {
577  while(szFileName[0] != 0 && szFileName[0] != _T('/'))
578  szFileName++;
579  }
580 
581  // Return the remainder
582  return szFileName;
583 }
arena_t NULL
Definition: jemalloc_internal.h:624
#define _T(x)
Definition: CascPort.h:171
#define _tcsnicmp
Definition: CascPort.h:188

+ Here is the caller graph for this function:

static void BaseHttp_Init ( TFileStream pStream)
static
782 {
783  // Supply the stream functions
784  pStream->BaseOpen = BaseHttp_Open;
785  pStream->BaseRead = BaseHttp_Read;
786  pStream->BaseGetSize = BaseFile_GetSize; // Reuse BaseFile function
787  pStream->BaseGetPos = BaseFile_GetPos; // Reuse BaseFile function
788  pStream->BaseClose = BaseHttp_Close;
789 
790  // HTTP files are read-only
791  pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
792 }
STREAM_OPEN BaseOpen
Definition: FileStream.h:169
STREAM_READ BaseRead
Definition: FileStream.h:170
static bool BaseFile_GetPos(TFileStream *pStream, ULONGLONG *pByteOffset)
Definition: FileStream.cpp:349
static bool BaseFile_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:340
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
static bool BaseHttp_Open(TFileStream *pStream, const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:585
STREAM_GETPOS BaseGetPos
Definition: FileStream.h:174
static bool BaseHttp_Read(TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:688
DWORD dwFlags
Definition: FileStream.h:187
static void BaseHttp_Close(TFileStream *pStream)
Definition: FileStream.cpp:765
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56
STREAM_GETSIZE BaseGetSize
Definition: FileStream.h:173

+ Here is the call graph for this function:

static bool BaseHttp_Open ( TFileStream pStream,
const TCHAR szFileName,
DWORD  dwStreamFlags 
)
static
586 {
587 #ifdef PLATFORM_WINDOWS
588 
589  HINTERNET hRequest;
590  DWORD dwTemp = 0;
591  bool bFileAvailable = false;
592  int nError = ERROR_SUCCESS;
593 
594  // Keep compiler happy
595  dwStreamFlags = dwStreamFlags;
596 
597  // Don't connect to the internet
598  if(!InternetGetConnectedState(&dwTemp, 0))
599  nError = GetLastError();
600 
601  // Initiate the connection to the internet
602  if(nError == ERROR_SUCCESS)
603  {
604  pStream->Base.Http.hInternet = InternetOpen(_T("CascLib HTTP archive reader"),
605  INTERNET_OPEN_TYPE_PRECONFIG,
606  NULL,
607  NULL,
608  0);
609  if(pStream->Base.Http.hInternet == NULL)
610  nError = GetLastError();
611  }
612 
613  // Connect to the server
614  if(nError == ERROR_SUCCESS)
615  {
616  TCHAR szServerName[MAX_PATH];
617  DWORD dwFlags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE;
618 
619  // Initiate connection with the server
620  szFileName = BaseHttp_ExtractServerName(szFileName, szServerName);
621  pStream->Base.Http.hConnect = InternetConnect(pStream->Base.Http.hInternet,
622  szServerName,
623  INTERNET_DEFAULT_HTTP_PORT,
624  NULL,
625  NULL,
626  INTERNET_SERVICE_HTTP,
627  dwFlags,
628  0);
629  if(pStream->Base.Http.hConnect == NULL)
630  nError = GetLastError();
631  }
632 
633  // Now try to query the file size
634  if(nError == ERROR_SUCCESS)
635  {
636  // Open HTTP request to the file
637  hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
638  if(hRequest != NULL)
639  {
640  if(HttpSendRequest(hRequest, NULL, 0, NULL, 0))
641  {
642  ULONGLONG FileTime = 0;
643  DWORD dwFileSize = 0;
644  DWORD dwDataSize;
645  DWORD dwIndex = 0;
646 
647  // Check if the archive has Last Modified field
648  dwDataSize = sizeof(ULONGLONG);
649  if(HttpQueryInfo(hRequest, HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME, &FileTime, &dwDataSize, &dwIndex))
650  pStream->Base.Http.FileTime = FileTime;
651 
652  // Verify if the server supports random access
653  dwDataSize = sizeof(DWORD);
654  if(HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwFileSize, &dwDataSize, &dwIndex))
655  {
656  if(dwFileSize != 0)
657  {
658  pStream->Base.Http.FileSize = dwFileSize;
659  pStream->Base.Http.FilePos = 0;
660  bFileAvailable = true;
661  }
662  }
663  }
664  InternetCloseHandle(hRequest);
665  }
666  }
667 
668  // If the file is not there and is not available for random access,
669  // report error
670  if(bFileAvailable == false)
671  {
672  pStream->BaseClose(pStream);
673  return false;
674  }
675 
676  return true;
677 
678 #else
679 
680  // Not supported
682  pStream = pStream;
683  return false;
684 
685 #endif
686 }
struct TBaseProviderData::@2 Http
unsigned long long ULONGLONG
Definition: CascPort.h:144
ULONGLONG FileTime
Definition: FileStream.h:131
#define MAX_PATH
Definition: CascPort.h:160
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
char TCHAR
Definition: CascPort.h:148
#define _T(x)
Definition: CascPort.h:171
ULONGLONG FileSize
Definition: FileStream.h:129
HANDLE hInternet
Definition: FileStream.h:148
void SetLastError(int nError)
Definition: Common.cpp:75
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
HANDLE hConnect
Definition: FileStream.h:149
unsigned int DWORD
Definition: CascPort.h:139
int GetLastError()
Definition: Common.cpp:70
static const TCHAR * BaseHttp_ExtractServerName(const TCHAR *szFileName, TCHAR *szServerName)
Definition: FileStream.cpp:562
#define ERROR_NOT_SUPPORTED
Definition: CascPort.h:209
ULONGLONG FilePos
Definition: FileStream.h:130
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool BaseHttp_Read ( TFileStream pStream,
ULONGLONG pByteOffset,
void *  pvBuffer,
DWORD  dwBytesToRead 
)
static
693 {
694 #ifdef PLATFORM_WINDOWS
695  ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Http.FilePos;
696  DWORD dwTotalBytesRead = 0;
697 
698  // Do we have to read anything at all?
699  if(dwBytesToRead != 0)
700  {
701  HINTERNET hRequest;
702  LPCTSTR szFileName;
703  LPBYTE pbBuffer = (LPBYTE)pvBuffer;
704  TCHAR szRangeRequest[0x80];
705  DWORD dwStartOffset = (DWORD)ByteOffset;
706  DWORD dwEndOffset = dwStartOffset + dwBytesToRead;
707 
708  // Open HTTP request to the file
709  szFileName = BaseHttp_ExtractServerName(pStream->szFileName, NULL);
710  hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
711  if(hRequest != NULL)
712  {
713  // Add range request to the HTTP headers
714  // http://www.clevercomponents.com/articles/article015/resuming.asp
715  _stprintf(szRangeRequest, _T("Range: bytes=%u-%u"), (unsigned int)dwStartOffset, (unsigned int)dwEndOffset);
716  HttpAddRequestHeaders(hRequest, szRangeRequest, 0xFFFFFFFF, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
717 
718  // Send the request to the server
719  if(HttpSendRequest(hRequest, NULL, 0, NULL, 0))
720  {
721  while(dwTotalBytesRead < dwBytesToRead)
722  {
723  DWORD dwBlockBytesToRead = dwBytesToRead - dwTotalBytesRead;
724  DWORD dwBlockBytesRead = 0;
725 
726  // Read the block from the file
727  if(dwBlockBytesToRead > 0x200)
728  dwBlockBytesToRead = 0x200;
729  InternetReadFile(hRequest, pbBuffer, dwBlockBytesToRead, &dwBlockBytesRead);
730 
731  // Check for end
732  if(dwBlockBytesRead == 0)
733  break;
734 
735  // Move buffers
736  dwTotalBytesRead += dwBlockBytesRead;
737  pbBuffer += dwBlockBytesRead;
738  }
739  }
740  InternetCloseHandle(hRequest);
741  }
742  }
743 
744  // Increment the current file position by number of bytes read
745  pStream->Base.Http.FilePos = ByteOffset + dwTotalBytesRead;
746 
747  // If the number of bytes read doesn't match the required amount, return false
748  if(dwTotalBytesRead != dwBytesToRead)
750  return (dwTotalBytesRead == dwBytesToRead);
751 
752 #else
753 
754  // Not supported
755  pStream = pStream;
756  pByteOffset = pByteOffset;
757  pvBuffer = pvBuffer;
758  dwBytesToRead = dwBytesToRead;
760  return false;
761 
762 #endif
763 }
struct TBaseProviderData::@2 Http
unsigned long long ULONGLONG
Definition: CascPort.h:144
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
char TCHAR
Definition: CascPort.h:148
BYTE * LPBYTE
Definition: CascPort.h:152
#define _T(x)
Definition: CascPort.h:171
void SetLastError(int nError)
Definition: Common.cpp:75
TCHAR * szFileName
Definition: FileStream.h:182
HANDLE hConnect
Definition: FileStream.h:149
unsigned int DWORD
Definition: CascPort.h:139
static const TCHAR * BaseHttp_ExtractServerName(const TCHAR *szFileName, TCHAR *szServerName)
Definition: FileStream.cpp:562
#define ERROR_NOT_SUPPORTED
Definition: CascPort.h:209
#define ERROR_HANDLE_EOF
Definition: CascPort.h:216
#define _stprintf
Definition: CascPort.h:181
ULONGLONG FilePos
Definition: FileStream.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void BaseMap_Close ( TFileStream pStream)
static
531 {
532 #ifdef PLATFORM_WINDOWS
533  if(pStream->Base.Map.pbFile != NULL)
534  UnmapViewOfFile(pStream->Base.Map.pbFile);
535 #endif
536 
537 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
538  if(pStream->Base.Map.pbFile != NULL)
539  munmap(pStream->Base.Map.pbFile, (size_t )pStream->Base.Map.FileSize);
540 #endif
541 
542  pStream->Base.Map.pbFile = NULL;
543 }
struct TBaseProviderData::@1 Map
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
ULONGLONG FileSize
Definition: FileStream.h:129
LPBYTE pbFile
Definition: FileStream.h:140

+ Here is the caller graph for this function:

static void BaseMap_Init ( TFileStream pStream)
static
547 {
548  // Supply the file stream functions
549  pStream->BaseOpen = BaseMap_Open;
550  pStream->BaseRead = BaseMap_Read;
551  pStream->BaseGetSize = BaseFile_GetSize; // Reuse BaseFile function
552  pStream->BaseGetPos = BaseFile_GetPos; // Reuse BaseFile function
553  pStream->BaseClose = BaseMap_Close;
554 
555  // Mapped files are read-only
556  pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
557 }
static void BaseMap_Close(TFileStream *pStream)
Definition: FileStream.cpp:530
STREAM_OPEN BaseOpen
Definition: FileStream.h:169
STREAM_READ BaseRead
Definition: FileStream.h:170
static bool BaseFile_GetPos(TFileStream *pStream, ULONGLONG *pByteOffset)
Definition: FileStream.cpp:349
static bool BaseMap_Read(TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:506
static bool BaseFile_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:340
static bool BaseMap_Open(TFileStream *pStream, const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:414
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
STREAM_GETPOS BaseGetPos
Definition: FileStream.h:174
DWORD dwFlags
Definition: FileStream.h:187
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56
STREAM_GETSIZE BaseGetSize
Definition: FileStream.h:173

+ Here is the call graph for this function:

static bool BaseMap_Open ( TFileStream pStream,
const TCHAR szFileName,
DWORD  dwStreamFlags 
)
static
415 {
416 #ifdef PLATFORM_WINDOWS
417 
418  ULARGE_INTEGER FileSize;
419  HANDLE hFile;
420  HANDLE hMap;
421  bool bResult = false;
422 
423  // Keep compiler happy
424  dwStreamFlags = dwStreamFlags;
425 
426  // Open the file for read access
427  hFile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
428  if(hFile != INVALID_HANDLE_VALUE)
429  {
430  // Retrieve file size. Don't allow mapping file of a zero size.
431  FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
432  if(FileSize.QuadPart != 0)
433  {
434  // Now create mapping object
435  hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
436  if(hMap != NULL)
437  {
438  // Map the entire view into memory
439  // Note that this operation will fail if the file can't fit
440  // into usermode address space
441  pStream->Base.Map.pbFile = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
442  if(pStream->Base.Map.pbFile != NULL)
443  {
444  // Retrieve file time
445  GetFileTime(hFile, NULL, NULL, (LPFILETIME)&pStream->Base.Map.FileTime);
446 
447  // Retrieve file size and position
448  pStream->Base.Map.FileSize = FileSize.QuadPart;
449  pStream->Base.Map.FilePos = 0;
450  bResult = true;
451  }
452 
453  // Close the map handle
454  CloseHandle(hMap);
455  }
456  }
457 
458  // Close the file handle
459  CloseHandle(hFile);
460  }
461 
462  // If the file is not there and is not available for random access,
463  // report error
464  if(bResult == false)
465  return false;
466 #endif
467 
468 #if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
469  struct stat64 fileinfo;
470  intptr_t handle;
471  bool bResult = false;
472 
473  // Open the file
474  handle = open(szFileName, O_RDONLY);
475  if(handle != -1)
476  {
477  // Get the file size
478  if(fstat64(handle, &fileinfo) != -1)
479  {
480  pStream->Base.Map.pbFile = (LPBYTE)mmap(NULL, (size_t)fileinfo.st_size, PROT_READ, MAP_PRIVATE, handle, 0);
481  if(pStream->Base.Map.pbFile != NULL)
482  {
483  // time_t is number of seconds since 1.1.1970, UTC.
484  // 1 second = 10000000 (decimal) in FILETIME
485  // Set the start to 1.1.1970 00:00:00
486  pStream->Base.Map.FileTime = 0x019DB1DED53E8000ULL + (10000000 * fileinfo.st_mtime);
487  pStream->Base.Map.FileSize = (ULONGLONG)fileinfo.st_size;
488  pStream->Base.Map.FilePos = 0;
489  bResult = true;
490  }
491  }
492  close(handle);
493  }
494 
495  // Did the mapping fail?
496  if(bResult == false)
497  {
498  SetLastError(errno);
499  return false;
500  }
501 #endif
502 
503  return true;
504 }
struct TBaseProviderData::@1 Map
void * HANDLE
Definition: CascPort.h:146
unsigned long long ULONGLONG
Definition: CascPort.h:144
ULONGLONG FileTime
Definition: FileStream.h:131
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
BYTE * LPBYTE
Definition: CascPort.h:152
ULONGLONG FileSize
Definition: FileStream.h:129
void SetLastError(int nError)
Definition: Common.cpp:75
#define INVALID_HANDLE_VALUE
Definition: CascPort.h:169
LPBYTE pbFile
Definition: FileStream.h:140
_W64 signed int intptr_t
Definition: stdint.h:118
ULONGLONG FilePos
Definition: FileStream.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool BaseMap_Read ( TFileStream pStream,
ULONGLONG pByteOffset,
void *  pvBuffer,
DWORD  dwBytesToRead 
)
static
511 {
512  ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Map.FilePos;
513 
514  // Do we have to read anything at all?
515  if(dwBytesToRead != 0)
516  {
517  // Don't allow reading past file size
518  if((ByteOffset + dwBytesToRead) > pStream->Base.Map.FileSize)
519  return false;
520 
521  // Copy the required data
522  memcpy(pvBuffer, pStream->Base.Map.pbFile + (size_t)ByteOffset, dwBytesToRead);
523  }
524 
525  // Move the current file position
526  pStream->Base.Map.FilePos += dwBytesToRead;
527  return true;
528 }
struct TBaseProviderData::@1 Map
unsigned long long ULONGLONG
Definition: CascPort.h:144
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
ULONGLONG FileSize
Definition: FileStream.h:129
LPBYTE pbFile
Definition: FileStream.h:140
ULONGLONG FilePos
Definition: FileStream.h:130

+ Here is the caller graph for this function:

static void BaseNone_Init ( TFileStream )
static
45 {
46  // Nothing here
47 }
static bool Block4Stream_BlockRead ( TBlockStream pStream,
ULONGLONG  StartOffset,
ULONGLONG  EndOffset,
LPBYTE  BlockBuffer,
DWORD  BytesNeeded,
bool  bAvailable 
)
static
2119 {
2120  TBaseProviderData * BaseArray = (TBaseProviderData *)pStream->FileBitmap;
2121  ULONGLONG ByteOffset;
2122  DWORD BytesToRead;
2123  DWORD StreamIndex;
2124  DWORD BlockIndex;
2125  bool bResult;
2126 
2127  // The starting offset must be aligned to size of the block
2128  assert(pStream->FileBitmap != NULL);
2129  assert((StartOffset & (pStream->BlockSize - 1)) == 0);
2130  assert(StartOffset < EndOffset);
2131  assert(bAvailable == true);
2132 
2133  // Keep compiler happy
2134  bAvailable = bAvailable;
2135  EndOffset = EndOffset;
2136 
2137  while(BytesNeeded != 0)
2138  {
2139  // Calculate the block index and the file index
2140  StreamIndex = (DWORD)((StartOffset / pStream->BlockSize) / BLOCK4_MAX_BLOCKS);
2141  BlockIndex = (DWORD)((StartOffset / pStream->BlockSize) % BLOCK4_MAX_BLOCKS);
2142  if(StreamIndex > pStream->BitmapSize)
2143  return false;
2144 
2145  // Calculate the block offset
2146  ByteOffset = ((ULONGLONG)BlockIndex * (BLOCK4_BLOCK_SIZE + BLOCK4_HASH_SIZE));
2147  BytesToRead = CASCLIB_MIN(BytesNeeded, BLOCK4_BLOCK_SIZE);
2148 
2149  // Read from the base stream
2150  pStream->Base = BaseArray[StreamIndex];
2151  bResult = pStream->BaseRead(pStream, &ByteOffset, BlockBuffer, BytesToRead);
2152  BaseArray[StreamIndex] = pStream->Base;
2153 
2154  // Did the result succeed?
2155  if(bResult == false)
2156  return false;
2157 
2158  // Move pointers
2159  StartOffset += BytesToRead;
2160  BlockBuffer += BytesToRead;
2161  BytesNeeded -= BytesToRead;
2162  }
2163 
2164  return true;
2165 }
Definition: FileStream.h:125
DWORD BitmapSize
Definition: FileStream.h:200
void * FileBitmap
Definition: FileStream.h:198
unsigned long long ULONGLONG
Definition: CascPort.h:144
#define BLOCK4_BLOCK_SIZE
Definition: FileStream.cpp:2107
#define BLOCK4_MAX_BLOCKS
Definition: FileStream.cpp:2109
STREAM_READ BaseRead
Definition: FileStream.h:170
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
#define BLOCK4_HASH_SIZE
Definition: FileStream.cpp:2108
#define CASCLIB_MIN(a, b)
Definition: CascCommon.h:73
unsigned int DWORD
Definition: CascPort.h:139
DWORD BlockSize
Definition: FileStream.h:201

+ Here is the caller graph for this function:

static void Block4Stream_Close ( TBlockStream pStream)
static
2169 {
2170  TBaseProviderData * BaseArray = (TBaseProviderData *)pStream->FileBitmap;
2171 
2172  // If we have a non-zero count of base streams,
2173  // we have to close them all
2174  if(BaseArray != NULL)
2175  {
2176  // Close all base streams
2177  for(DWORD i = 0; i < pStream->BitmapSize; i++)
2178  {
2179  memcpy(&pStream->Base, BaseArray + i, sizeof(TBaseProviderData));
2180  pStream->BaseClose(pStream);
2181  }
2182  }
2183 
2184  // Free the data map, if any
2185  if(pStream->FileBitmap != NULL)
2186  CASC_FREE(pStream->FileBitmap);
2187  pStream->FileBitmap = NULL;
2188 
2189  // Do not call the BaseClose function,
2190  // we closed all handles already
2191  return;
2192 }
Definition: FileStream.h:125
DWORD BitmapSize
Definition: FileStream.h:200
void * FileBitmap
Definition: FileStream.h:198
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
unsigned int DWORD
Definition: CascPort.h:139

+ Here is the caller graph for this function:

static TFileStream* Block4Stream_Open ( const TCHAR szFileName,
DWORD  dwStreamFlags 
)
static
2195 {
2196  TBaseProviderData * NewBaseArray = NULL;
2197  ULONGLONG RemainderBlock;
2198  ULONGLONG BlockCount;
2199  ULONGLONG FileSize;
2200  TBlockStream * pStream;
2201  TCHAR * szNameBuff;
2202  size_t nNameLength;
2203  DWORD dwBaseFiles = 0;
2204  DWORD dwBaseFlags;
2205 
2206  // Create new empty stream
2207  pStream = (TBlockStream *)AllocateFileStream(szFileName, sizeof(TBlockStream), dwStreamFlags);
2208  if(pStream == NULL)
2209  return NULL;
2210 
2211  // Sanity check
2212  assert(pStream->BaseOpen != NULL);
2213 
2214  // Get the length of the file name without numeric suffix
2215  nNameLength = _tcslen(pStream->szFileName);
2216  if(pStream->szFileName[nNameLength - 2] == '.' && pStream->szFileName[nNameLength - 1] == '0')
2217  nNameLength -= 2;
2218  pStream->szFileName[nNameLength] = 0;
2219 
2220  // Supply the stream functions
2223  pStream->StreamGetPos = BlockStream_GetPos;
2226 
2227  // Allocate work space for numeric names
2228  szNameBuff = CASC_ALLOC(TCHAR, nNameLength + 4);
2229  if(szNameBuff != NULL)
2230  {
2231  // Set the base flags
2232  dwBaseFlags = (dwStreamFlags & STREAM_PROVIDERS_MASK) | STREAM_FLAG_READ_ONLY;
2233 
2234  // Go all suffixes from 0 to 30
2235  for(int nSuffix = 0; nSuffix < 30; nSuffix++)
2236  {
2237  // Open the n-th file
2238  _stprintf(szNameBuff, _T("%s.%u"), pStream->szFileName, nSuffix);
2239  if(!pStream->BaseOpen(pStream, szNameBuff, dwBaseFlags))
2240  break;
2241 
2242  // If the open succeeded, we re-allocate the base provider array
2243  NewBaseArray = CASC_ALLOC(TBaseProviderData, dwBaseFiles + 1);
2244  if(NewBaseArray == NULL)
2245  {
2247  return NULL;
2248  }
2249 
2250  // Copy the old base data array to the new base data array
2251  if(pStream->FileBitmap != NULL)
2252  {
2253  memcpy(NewBaseArray, pStream->FileBitmap, sizeof(TBaseProviderData) * dwBaseFiles);
2254  CASC_FREE(pStream->FileBitmap);
2255  }
2256 
2257  // Also copy the opened base array
2258  memcpy(NewBaseArray + dwBaseFiles, &pStream->Base, sizeof(TBaseProviderData));
2259  pStream->FileBitmap = NewBaseArray;
2260  dwBaseFiles++;
2261 
2262  // Get the size of the base stream
2263  pStream->BaseGetSize(pStream, &FileSize);
2264  assert(FileSize <= BLOCK4_MAX_FSIZE);
2265  RemainderBlock = FileSize % (BLOCK4_BLOCK_SIZE + BLOCK4_HASH_SIZE);
2266  BlockCount = FileSize / (BLOCK4_BLOCK_SIZE + BLOCK4_HASH_SIZE);
2267 
2268  // Increment the stream size and number of blocks
2269  pStream->StreamSize += (BlockCount * BLOCK4_BLOCK_SIZE);
2270  pStream->BlockCount += (DWORD)BlockCount;
2271 
2272  // Is this the last file?
2273  if(FileSize < BLOCK4_MAX_FSIZE)
2274  {
2275  if(RemainderBlock)
2276  {
2277  pStream->StreamSize += (RemainderBlock - BLOCK4_HASH_SIZE);
2278  pStream->BlockCount++;
2279  }
2280  break;
2281  }
2282  }
2283 
2284  // Fill the remainining block stream variables
2285  pStream->BitmapSize = dwBaseFiles;
2286  pStream->BlockSize = BLOCK4_BLOCK_SIZE;
2287  pStream->IsComplete = 1;
2288  pStream->IsModified = 0;
2289 
2290  // Fill the remaining stream variables
2291  pStream->StreamPos = 0;
2292  pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
2293 
2294  CASC_FREE(szNameBuff);
2295  }
2296 
2297  // If we opened something, return success
2298  if(dwBaseFiles == 0)
2299  {
2300  FileStream_Close(pStream);
2302  pStream = NULL;
2303  }
2304 
2305  return pStream;
2306 }
Definition: FileStream.h:125
STREAM_GETPOS StreamGetPos
Definition: FileStream.h:160
DWORD BitmapSize
Definition: FileStream.h:200
STREAM_CLOSE StreamClose
Definition: FileStream.h:161
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
void * FileBitmap
Definition: FileStream.h:198
unsigned long long ULONGLONG
Definition: CascPort.h:144
#define BLOCK4_MAX_FSIZE
Definition: FileStream.cpp:2110
static TFileStream * AllocateFileStream(const TCHAR *szFileName, size_t StreamSize, DWORD dwStreamFlags)
Definition: FileStream.cpp:977
#define BLOCK4_BLOCK_SIZE
Definition: FileStream.cpp:2107
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
STREAM_OPEN BaseOpen
Definition: FileStream.h:169
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
static bool Block4Stream_BlockRead(TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
Definition: FileStream.cpp:2112
char TCHAR
Definition: CascPort.h:148
BLOCK_READ BlockRead
Definition: FileStream.h:164
bool(* STREAM_READ)(struct TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.h:31
void(* STREAM_CLOSE)(struct TFileStream *pStream)
Definition: FileStream.h:60
#define _T(x)
Definition: CascPort.h:171
#define BLOCK4_HASH_SIZE
Definition: FileStream.cpp:2108
ULONGLONG StreamPos
Definition: FileStream.h:185
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
#define _tcslen
Definition: CascPort.h:172
void SetLastError(int nError)
Definition: Common.cpp:75
#define ERROR_FILE_NOT_FOUND
Definition: CascPort.h:205
TCHAR * szFileName
Definition: FileStream.h:182
static bool BlockStream_Read(TBlockStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:800
DWORD IsComplete
Definition: FileStream.h:203
static bool BlockStream_GetPos(TFileStream *pStream, ULONGLONG *pByteOffset)
Definition: FileStream.cpp:946
DWORD BlockCount
Definition: FileStream.h:202
static void Block4Stream_Close(TBlockStream *pStream)
Definition: FileStream.cpp:2168
void FileStream_Close(TFileStream *pStream)
Definition: FileStream.cpp:2707
unsigned int DWORD
Definition: CascPort.h:139
static bool BlockStream_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:940
DWORD dwFlags
Definition: FileStream.h:187
STREAM_GETSIZE StreamGetSize
Definition: FileStream.h:159
bool(* BLOCK_READ)(struct TFileStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
Definition: FileStream.h:64
DWORD IsModified
Definition: FileStream.h:204
DWORD BlockSize
Definition: FileStream.h:201
#define STREAM_PROVIDERS_MASK
Definition: CascLib.h:61
#define _stprintf
Definition: CascPort.h:181
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56
ULONGLONG StreamSize
Definition: FileStream.h:184
Definition: FileStream.h:195
STREAM_GETSIZE BaseGetSize
Definition: FileStream.h:173
STREAM_READ StreamRead
Definition: FileStream.h:156

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void BlockStream_Close ( TBlockStream pStream)
static
953 {
954  // Free the data map, if any
955  if(pStream->FileBitmap != NULL)
956  CASC_FREE(pStream->FileBitmap);
957  pStream->FileBitmap = NULL;
958 
959  // Call the base class for closing the stream
960  pStream->BaseClose(pStream);
961 }
void * FileBitmap
Definition: FileStream.h:198
arena_t NULL
Definition: jemalloc_internal.h:624
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
STREAM_CLOSE BaseClose
Definition: FileStream.h:175

+ Here is the caller graph for this function:

static bool BlockStream_GetPos ( TFileStream pStream,
ULONGLONG pByteOffset 
)
static
947 {
948  *pByteOffset = pStream->StreamPos;
949  return true;
950 }
ULONGLONG StreamPos
Definition: FileStream.h:185

+ Here is the caller graph for this function:

static bool BlockStream_GetSize ( TFileStream pStream,
ULONGLONG pFileSize 
)
static
941 {
942  *pFileSize = pStream->StreamSize;
943  return true;
944 }
ULONGLONG StreamSize
Definition: FileStream.h:184

+ Here is the caller graph for this function:

static bool BlockStream_Read ( TBlockStream pStream,
ULONGLONG pByteOffset,
void *  pvBuffer,
DWORD  dwBytesToRead 
)
static
805 {
806  ULONGLONG BlockOffset0;
807  ULONGLONG BlockOffset;
808  ULONGLONG ByteOffset;
809  ULONGLONG EndOffset;
810  LPBYTE TransferBuffer;
811  LPBYTE BlockBuffer;
812  DWORD BlockBufferOffset; // Offset of the desired data in the block buffer
813  DWORD BytesNeeded; // Number of bytes that really need to be read
814  DWORD BlockSize = pStream->BlockSize;
815  DWORD BlockCount;
816  bool bPrevBlockAvailable;
817  bool bCallbackCalled = false;
818  bool bBlockAvailable;
819  bool bResult = true;
820 
821  // The base block read function must be present
822  assert(pStream->BlockRead != NULL);
823 
824  // NOP reading of zero bytes
825  if(dwBytesToRead == 0)
826  return true;
827 
828  // Get the current position in the stream
829  ByteOffset = (pByteOffset != NULL) ? pByteOffset[0] : pStream->StreamPos;
830  EndOffset = ByteOffset + dwBytesToRead;
831  if(EndOffset > pStream->StreamSize)
832  {
834  return false;
835  }
836 
837  // Calculate the block parameters
838  BlockOffset0 = BlockOffset = ByteOffset & ~((ULONGLONG)BlockSize - 1);
839  BlockCount = (DWORD)(((EndOffset - BlockOffset) + (BlockSize - 1)) / BlockSize);
840  BytesNeeded = (DWORD)(EndOffset - BlockOffset);
841 
842  // Remember where we have our data
843  assert((BlockSize & (BlockSize - 1)) == 0);
844  BlockBufferOffset = (DWORD)(ByteOffset & (BlockSize - 1));
845 
846  // Allocate buffer for reading blocks
847  TransferBuffer = BlockBuffer = CASC_ALLOC(BYTE, (BlockCount * BlockSize));
848  if(TransferBuffer == NULL)
849  {
851  return false;
852  }
853 
854  // If all blocks are available, just read all blocks at once
855  if(pStream->IsComplete == 0)
856  {
857  // Now parse the blocks and send the block read request
858  // to all blocks with the same availability
859  assert(pStream->BlockCheck != NULL);
860  bPrevBlockAvailable = pStream->BlockCheck(pStream, BlockOffset);
861 
862  // Loop as long as we have something to read
863  while(BlockOffset < EndOffset)
864  {
865  // Determine availability of the next block
866  bBlockAvailable = pStream->BlockCheck(pStream, BlockOffset);
867 
868  // If the availability has changed, read all blocks up to this one
869  if(bBlockAvailable != bPrevBlockAvailable)
870  {
871  // Call the file stream callback, if the block is not available
872  if(pStream->pMaster && pStream->pfnCallback && bPrevBlockAvailable == false)
873  {
874  pStream->pfnCallback(pStream->UserData, BlockOffset0, (DWORD)(BlockOffset - BlockOffset0));
875  bCallbackCalled = true;
876  }
877 
878  // Load the continuous blocks with the same availability
879  assert(BlockOffset > BlockOffset0);
880  bResult = pStream->BlockRead(pStream, BlockOffset0, BlockOffset, BlockBuffer, BytesNeeded, bPrevBlockAvailable);
881  if(!bResult)
882  break;
883 
884  // Move the block offset
885  BlockBuffer += (DWORD)(BlockOffset - BlockOffset0);
886  BytesNeeded -= (DWORD)(BlockOffset - BlockOffset0);
887  bPrevBlockAvailable = bBlockAvailable;
888  BlockOffset0 = BlockOffset;
889  }
890 
891  // Move to the block offset in the stream
892  BlockOffset += BlockSize;
893  }
894 
895  // If there is a block(s) remaining to be read, do it
896  if(BlockOffset > BlockOffset0)
897  {
898  // Call the file stream callback, if the block is not available
899  if(pStream->pMaster && pStream->pfnCallback && bPrevBlockAvailable == false)
900  {
901  pStream->pfnCallback(pStream->UserData, BlockOffset0, (DWORD)(BlockOffset - BlockOffset0));
902  bCallbackCalled = true;
903  }
904 
905  // Read the complete blocks from the file
906  if(BlockOffset > pStream->StreamSize)
907  BlockOffset = pStream->StreamSize;
908  bResult = pStream->BlockRead(pStream, BlockOffset0, BlockOffset, BlockBuffer, BytesNeeded, bPrevBlockAvailable);
909  }
910  }
911  else
912  {
913  // Read the complete blocks from the file
914  if(EndOffset > pStream->StreamSize)
915  EndOffset = pStream->StreamSize;
916  bResult = pStream->BlockRead(pStream, BlockOffset, EndOffset, BlockBuffer, BytesNeeded, true);
917  }
918 
919  // Now copy the data to the user buffer
920  if(bResult)
921  {
922  memcpy(pvBuffer, TransferBuffer + BlockBufferOffset, dwBytesToRead);
923  pStream->StreamPos = ByteOffset + dwBytesToRead;
924  }
925  else
926  {
927  // If the block read failed, set the last error
929  }
930 
931  // Call the callback to indicate we are done
932  if(bCallbackCalled)
933  pStream->pfnCallback(pStream->UserData, 0, 0);
934 
935  // Free the block buffer and return
936  CASC_FREE(TransferBuffer);
937  return bResult;
938 }
void * UserData
Definition: FileStream.h:199
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
unsigned long long ULONGLONG
Definition: CascPort.h:144
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
arena_t NULL
Definition: jemalloc_internal.h:624
BLOCK_READ BlockRead
Definition: FileStream.h:164
BYTE * LPBYTE
Definition: CascPort.h:152
ULONGLONG StreamPos
Definition: FileStream.h:185
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
#define ERROR_FILE_INCOMPLETE
Definition: CascLib.h:36
void SetLastError(int nError)
Definition: Common.cpp:75
STREAM_DOWNLOAD_CALLBACK pfnCallback
Definition: FileStream.h:197
DWORD IsComplete
Definition: FileStream.h:203
TFileStream * pMaster
Definition: FileStream.h:181
unsigned int DWORD
Definition: CascPort.h:139
DWORD BlockSize
Definition: FileStream.h:201
BLOCK_CHECK BlockCheck
Definition: FileStream.h:165
#define ERROR_HANDLE_EOF
Definition: CascPort.h:216
unsigned char BYTE
Definition: CascPort.h:136
ULONGLONG StreamSize
Definition: FileStream.h:184

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void CreateKeyFromAuthCode ( LPBYTE  pbKeyBuffer,
const char *  szAuthCode 
)
static
1868 {
1869  PDWORD KeyPosition = (PDWORD)(pbKeyBuffer + 0x10);
1870  PDWORD AuthCode32 = (PDWORD)szAuthCode;
1871 
1872  memcpy(pbKeyBuffer, szKeyTemplate, ENCRYPTED_CHUNK_SIZE);
1873  KeyPosition[0x00] = AuthCode32[0x03];
1874  KeyPosition[0x02] = AuthCode32[0x07];
1875  KeyPosition[0x03] = AuthCode32[0x02];
1876  KeyPosition[0x05] = AuthCode32[0x06];
1877  KeyPosition[0x06] = AuthCode32[0x01];
1878  KeyPosition[0x08] = AuthCode32[0x05];
1879  KeyPosition[0x09] = AuthCode32[0x00];
1880  KeyPosition[0x0B] = AuthCode32[0x04];
1882 }
DWORD * PDWORD
Definition: CascPort.h:151
static const char * szKeyTemplate
Definition: FileStream.cpp:1805
#define BSWAP_ARRAY32_UNSIGNED(a, b)
Definition: CascPort.h:232
#define ENCRYPTED_CHUNK_SIZE
Definition: FileStream.h:210

+ Here is the caller graph for this function:

static void DecryptFileChunk ( DWORD ChunkData,
LPBYTE  pbKey,
ULONGLONG  ByteOffset,
DWORD  dwLength 
)
static
1889 {
1890  ULONGLONG ChunkOffset;
1891  DWORD KeyShuffled[0x10];
1892  DWORD KeyMirror[0x10];
1893  DWORD RoundCount = 0x14;
1894 
1895  // Prepare the key
1896  ChunkOffset = ByteOffset / ENCRYPTED_CHUNK_SIZE;
1897  memcpy(KeyMirror, pbKey, ENCRYPTED_CHUNK_SIZE);
1899  KeyMirror[0x05] = (DWORD)(ChunkOffset >> 32);
1900  KeyMirror[0x08] = (DWORD)(ChunkOffset);
1901 
1902  while(dwLength >= ENCRYPTED_CHUNK_SIZE)
1903  {
1904  // Shuffle the key - part 1
1905  KeyShuffled[0x0E] = KeyMirror[0x00];
1906  KeyShuffled[0x0C] = KeyMirror[0x01];
1907  KeyShuffled[0x05] = KeyMirror[0x02];
1908  KeyShuffled[0x0F] = KeyMirror[0x03];
1909  KeyShuffled[0x0A] = KeyMirror[0x04];
1910  KeyShuffled[0x07] = KeyMirror[0x05];
1911  KeyShuffled[0x0B] = KeyMirror[0x06];
1912  KeyShuffled[0x09] = KeyMirror[0x07];
1913  KeyShuffled[0x03] = KeyMirror[0x08];
1914  KeyShuffled[0x06] = KeyMirror[0x09];
1915  KeyShuffled[0x08] = KeyMirror[0x0A];
1916  KeyShuffled[0x0D] = KeyMirror[0x0B];
1917  KeyShuffled[0x02] = KeyMirror[0x0C];
1918  KeyShuffled[0x04] = KeyMirror[0x0D];
1919  KeyShuffled[0x01] = KeyMirror[0x0E];
1920  KeyShuffled[0x00] = KeyMirror[0x0F];
1921 
1922  // Shuffle the key - part 2
1923  for(DWORD i = 0; i < RoundCount; i += 2)
1924  {
1925  KeyShuffled[0x0A] = KeyShuffled[0x0A] ^ Rol32((KeyShuffled[0x0E] + KeyShuffled[0x02]), 0x07);
1926  KeyShuffled[0x03] = KeyShuffled[0x03] ^ Rol32((KeyShuffled[0x0A] + KeyShuffled[0x0E]), 0x09);
1927  KeyShuffled[0x02] = KeyShuffled[0x02] ^ Rol32((KeyShuffled[0x03] + KeyShuffled[0x0A]), 0x0D);
1928  KeyShuffled[0x0E] = KeyShuffled[0x0E] ^ Rol32((KeyShuffled[0x02] + KeyShuffled[0x03]), 0x12);
1929 
1930  KeyShuffled[0x07] = KeyShuffled[0x07] ^ Rol32((KeyShuffled[0x0C] + KeyShuffled[0x04]), 0x07);
1931  KeyShuffled[0x06] = KeyShuffled[0x06] ^ Rol32((KeyShuffled[0x07] + KeyShuffled[0x0C]), 0x09);
1932  KeyShuffled[0x04] = KeyShuffled[0x04] ^ Rol32((KeyShuffled[0x06] + KeyShuffled[0x07]), 0x0D);
1933  KeyShuffled[0x0C] = KeyShuffled[0x0C] ^ Rol32((KeyShuffled[0x04] + KeyShuffled[0x06]), 0x12);
1934 
1935  KeyShuffled[0x0B] = KeyShuffled[0x0B] ^ Rol32((KeyShuffled[0x05] + KeyShuffled[0x01]), 0x07);
1936  KeyShuffled[0x08] = KeyShuffled[0x08] ^ Rol32((KeyShuffled[0x0B] + KeyShuffled[0x05]), 0x09);
1937  KeyShuffled[0x01] = KeyShuffled[0x01] ^ Rol32((KeyShuffled[0x08] + KeyShuffled[0x0B]), 0x0D);
1938  KeyShuffled[0x05] = KeyShuffled[0x05] ^ Rol32((KeyShuffled[0x01] + KeyShuffled[0x08]), 0x12);
1939 
1940  KeyShuffled[0x09] = KeyShuffled[0x09] ^ Rol32((KeyShuffled[0x0F] + KeyShuffled[0x00]), 0x07);
1941  KeyShuffled[0x0D] = KeyShuffled[0x0D] ^ Rol32((KeyShuffled[0x09] + KeyShuffled[0x0F]), 0x09);
1942  KeyShuffled[0x00] = KeyShuffled[0x00] ^ Rol32((KeyShuffled[0x0D] + KeyShuffled[0x09]), 0x0D);
1943  KeyShuffled[0x0F] = KeyShuffled[0x0F] ^ Rol32((KeyShuffled[0x00] + KeyShuffled[0x0D]), 0x12);
1944 
1945  KeyShuffled[0x04] = KeyShuffled[0x04] ^ Rol32((KeyShuffled[0x0E] + KeyShuffled[0x09]), 0x07);
1946  KeyShuffled[0x08] = KeyShuffled[0x08] ^ Rol32((KeyShuffled[0x04] + KeyShuffled[0x0E]), 0x09);
1947  KeyShuffled[0x09] = KeyShuffled[0x09] ^ Rol32((KeyShuffled[0x08] + KeyShuffled[0x04]), 0x0D);
1948  KeyShuffled[0x0E] = KeyShuffled[0x0E] ^ Rol32((KeyShuffled[0x09] + KeyShuffled[0x08]), 0x12);
1949 
1950  KeyShuffled[0x01] = KeyShuffled[0x01] ^ Rol32((KeyShuffled[0x0C] + KeyShuffled[0x0A]), 0x07);
1951  KeyShuffled[0x0D] = KeyShuffled[0x0D] ^ Rol32((KeyShuffled[0x01] + KeyShuffled[0x0C]), 0x09);
1952  KeyShuffled[0x0A] = KeyShuffled[0x0A] ^ Rol32((KeyShuffled[0x0D] + KeyShuffled[0x01]), 0x0D);
1953  KeyShuffled[0x0C] = KeyShuffled[0x0C] ^ Rol32((KeyShuffled[0x0A] + KeyShuffled[0x0D]), 0x12);
1954 
1955  KeyShuffled[0x00] = KeyShuffled[0x00] ^ Rol32((KeyShuffled[0x05] + KeyShuffled[0x07]), 0x07);
1956  KeyShuffled[0x03] = KeyShuffled[0x03] ^ Rol32((KeyShuffled[0x00] + KeyShuffled[0x05]), 0x09);
1957  KeyShuffled[0x07] = KeyShuffled[0x07] ^ Rol32((KeyShuffled[0x03] + KeyShuffled[0x00]), 0x0D);
1958  KeyShuffled[0x05] = KeyShuffled[0x05] ^ Rol32((KeyShuffled[0x07] + KeyShuffled[0x03]), 0x12);
1959 
1960  KeyShuffled[0x02] = KeyShuffled[0x02] ^ Rol32((KeyShuffled[0x0F] + KeyShuffled[0x0B]), 0x07);
1961  KeyShuffled[0x06] = KeyShuffled[0x06] ^ Rol32((KeyShuffled[0x02] + KeyShuffled[0x0F]), 0x09);
1962  KeyShuffled[0x0B] = KeyShuffled[0x0B] ^ Rol32((KeyShuffled[0x06] + KeyShuffled[0x02]), 0x0D);
1963  KeyShuffled[0x0F] = KeyShuffled[0x0F] ^ Rol32((KeyShuffled[0x0B] + KeyShuffled[0x06]), 0x12);
1964  }
1965 
1966  // Decrypt one data chunk
1968  ChunkData[0x00] = ChunkData[0x00] ^ (KeyShuffled[0x0E] + KeyMirror[0x00]);
1969  ChunkData[0x01] = ChunkData[0x01] ^ (KeyShuffled[0x04] + KeyMirror[0x0D]);
1970  ChunkData[0x02] = ChunkData[0x02] ^ (KeyShuffled[0x08] + KeyMirror[0x0A]);
1971  ChunkData[0x03] = ChunkData[0x03] ^ (KeyShuffled[0x09] + KeyMirror[0x07]);
1972  ChunkData[0x04] = ChunkData[0x04] ^ (KeyShuffled[0x0A] + KeyMirror[0x04]);
1973  ChunkData[0x05] = ChunkData[0x05] ^ (KeyShuffled[0x0C] + KeyMirror[0x01]);
1974  ChunkData[0x06] = ChunkData[0x06] ^ (KeyShuffled[0x01] + KeyMirror[0x0E]);
1975  ChunkData[0x07] = ChunkData[0x07] ^ (KeyShuffled[0x0D] + KeyMirror[0x0B]);
1976  ChunkData[0x08] = ChunkData[0x08] ^ (KeyShuffled[0x03] + KeyMirror[0x08]);
1977  ChunkData[0x09] = ChunkData[0x09] ^ (KeyShuffled[0x07] + KeyMirror[0x05]);
1978  ChunkData[0x0A] = ChunkData[0x0A] ^ (KeyShuffled[0x05] + KeyMirror[0x02]);
1979  ChunkData[0x0B] = ChunkData[0x0B] ^ (KeyShuffled[0x00] + KeyMirror[0x0F]);
1980  ChunkData[0x0C] = ChunkData[0x0C] ^ (KeyShuffled[0x02] + KeyMirror[0x0C]);
1981  ChunkData[0x0D] = ChunkData[0x0D] ^ (KeyShuffled[0x06] + KeyMirror[0x09]);
1982  ChunkData[0x0E] = ChunkData[0x0E] ^ (KeyShuffled[0x0B] + KeyMirror[0x06]);
1983  ChunkData[0x0F] = ChunkData[0x0F] ^ (KeyShuffled[0x0F] + KeyMirror[0x03]);
1985 
1986  // Update byte offset in the key
1987  KeyMirror[0x08]++;
1988  if(KeyMirror[0x08] == 0)
1989  KeyMirror[0x05]++;
1990 
1991  // Move pointers and decrease number of bytes to decrypt
1992  ChunkData += (ENCRYPTED_CHUNK_SIZE / sizeof(DWORD));
1993  dwLength -= ENCRYPTED_CHUNK_SIZE;
1994  }
1995 }
unsigned long long ULONGLONG
Definition: CascPort.h:144
static DWORD Rol32(DWORD dwValue, DWORD dwRolCount)
Definition: FileStream.cpp:1858
unsigned int DWORD
Definition: CascPort.h:139
#define BSWAP_ARRAY32_UNSIGNED(a, b)
Definition: CascPort.h:232
#define ENCRYPTED_CHUNK_SIZE
Definition: FileStream.h:210

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool EncrStream_BlockRead ( TEncryptedStream pStream,
ULONGLONG  StartOffset,
ULONGLONG  EndOffset,
LPBYTE  BlockBuffer,
DWORD  BytesNeeded,
bool  bAvailable 
)
static
2044 {
2045  DWORD dwBytesToRead;
2046 
2047  assert((StartOffset & (pStream->BlockSize - 1)) == 0);
2048  assert(StartOffset < EndOffset);
2049  assert(bAvailable != false);
2050  BytesNeeded = BytesNeeded;
2051  bAvailable = bAvailable;
2052 
2053  // Read the file from the stream as-is
2054  // Limit the reading to number of blocks really needed
2055  dwBytesToRead = (DWORD)(EndOffset - StartOffset);
2056  if(!pStream->BaseRead(pStream, &StartOffset, BlockBuffer, dwBytesToRead))
2057  return false;
2058 
2059  // Decrypt the data
2060  dwBytesToRead = (dwBytesToRead + ENCRYPTED_CHUNK_SIZE - 1) & ~(ENCRYPTED_CHUNK_SIZE - 1);
2061  DecryptFileChunk((PDWORD)BlockBuffer, pStream->Key, StartOffset, dwBytesToRead);
2062  return true;
2063 }
DWORD * PDWORD
Definition: CascPort.h:151
STREAM_READ BaseRead
Definition: FileStream.h:170
BYTE Key[ENCRYPTED_CHUNK_SIZE]
Definition: FileStream.h:214
static void DecryptFileChunk(DWORD *ChunkData, LPBYTE pbKey, ULONGLONG ByteOffset, DWORD dwLength)
Definition: FileStream.cpp:1884
unsigned int DWORD
Definition: CascPort.h:139
DWORD BlockSize
Definition: FileStream.h:201
#define ENCRYPTED_CHUNK_SIZE
Definition: FileStream.h:210

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool EncrStream_DetectFileKey ( TEncryptedStream pStream)
static
1998 {
1999  ULONGLONG ByteOffset = 0;
2000  BYTE EncryptedHeader[ENCRYPTED_CHUNK_SIZE];
2001  BYTE FileHeader[ENCRYPTED_CHUNK_SIZE];
2002 
2003  // Read the first file chunk
2004  if(pStream->BaseRead(pStream, &ByteOffset, EncryptedHeader, sizeof(EncryptedHeader)))
2005  {
2006  // We just try all known keys one by one
2007  for(int i = 0; AuthCodeArray[i] != NULL; i++)
2008  {
2009  // Prepare they decryption key from game serial number
2010  CreateKeyFromAuthCode(pStream->Key, AuthCodeArray[i]);
2011 
2012  // Try to decrypt with the given key
2013  memcpy(FileHeader, EncryptedHeader, ENCRYPTED_CHUNK_SIZE);
2014  DecryptFileChunk((PDWORD)FileHeader, pStream->Key, ByteOffset, ENCRYPTED_CHUNK_SIZE);
2015 
2016  // We check the decrypted data
2017  // All known encrypted archives have header at the begin of the file,
2018  // so we check for archive signature there.
2019  if(FileHeader[0] == 'M' && FileHeader[1] == 'P' && FileHeader[2] == 'Q')
2020  {
2021  // Update the stream size
2022  pStream->StreamSize = pStream->Base.File.FileSize;
2023 
2024  // Fill the block information
2025  pStream->BlockSize = ENCRYPTED_CHUNK_SIZE;
2027  pStream->IsComplete = 1;
2028  return true;
2029  }
2030  }
2031  }
2032 
2033  // Key not found, sorry
2034  return false;
2035 }
unsigned long long ULONGLONG
Definition: CascPort.h:144
DWORD * PDWORD
Definition: CascPort.h:151
static void CreateKeyFromAuthCode(LPBYTE pbKeyBuffer, const char *szAuthCode)
Definition: FileStream.cpp:1865
STREAM_READ BaseRead
Definition: FileStream.h:170
BYTE Key[ENCRYPTED_CHUNK_SIZE]
Definition: FileStream.h:214
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
static void DecryptFileChunk(DWORD *ChunkData, LPBYTE pbKey, ULONGLONG ByteOffset, DWORD dwLength)
Definition: FileStream.cpp:1884
struct TBaseProviderData::@0 File
ULONGLONG FileSize
Definition: FileStream.h:129
DWORD IsComplete
Definition: FileStream.h:203
DWORD BlockCount
Definition: FileStream.h:202
unsigned int DWORD
Definition: CascPort.h:139
static const char * AuthCodeArray[]
Definition: FileStream.cpp:1807
DWORD BlockSize
Definition: FileStream.h:201
unsigned char BYTE
Definition: CascPort.h:136
ULONGLONG StreamSize
Definition: FileStream.h:184
#define ENCRYPTED_CHUNK_SIZE
Definition: FileStream.h:210

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static TFileStream* EncrStream_Open ( const TCHAR szFileName,
DWORD  dwStreamFlags 
)
static
2066 {
2067  TEncryptedStream * pStream;
2068 
2069  // Create new empty stream
2070  pStream = (TEncryptedStream *)AllocateFileStream(szFileName, sizeof(TEncryptedStream), dwStreamFlags);
2071  if(pStream == NULL)
2072  return NULL;
2073 
2074  // Attempt to open the base stream
2075  assert(pStream->BaseOpen != NULL);
2076  if(!pStream->BaseOpen(pStream, pStream->szFileName, dwStreamFlags))
2077  return NULL;
2078 
2079  // Determine the encryption key for the archive
2080  if(EncrStream_DetectFileKey(pStream))
2081  {
2082  // Set the stream position and size
2083  assert(pStream->StreamSize != 0);
2084  pStream->StreamPos = 0;
2085  pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
2086 
2087  // Set new function pointers
2089  pStream->StreamGetPos = BlockStream_GetPos;
2091  pStream->StreamClose = pStream->BaseClose;
2092 
2093  // Supply the block functions
2095  return pStream;
2096  }
2097 
2098  // Cleanup the stream and return
2099  FileStream_Close(pStream);
2101  return NULL;
2102 }
STREAM_GETPOS StreamGetPos
Definition: FileStream.h:160
STREAM_CLOSE StreamClose
Definition: FileStream.h:161
Definition: FileStream.h:212
#define ERROR_UNKNOWN_FILE_KEY
Definition: CascLib.h:35
static bool EncrStream_DetectFileKey(TEncryptedStream *pStream)
Definition: FileStream.cpp:1997
static TFileStream * AllocateFileStream(const TCHAR *szFileName, size_t StreamSize, DWORD dwStreamFlags)
Definition: FileStream.cpp:977
STREAM_OPEN BaseOpen
Definition: FileStream.h:169
arena_t NULL
Definition: jemalloc_internal.h:624
BLOCK_READ BlockRead
Definition: FileStream.h:164
static bool EncrStream_BlockRead(TEncryptedStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
Definition: FileStream.cpp:2037
bool(* STREAM_READ)(struct TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.h:31
ULONGLONG StreamPos
Definition: FileStream.h:185
void SetLastError(int nError)
Definition: Common.cpp:75
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
TCHAR * szFileName
Definition: FileStream.h:182
static bool BlockStream_Read(TBlockStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:800
static bool BlockStream_GetPos(TFileStream *pStream, ULONGLONG *pByteOffset)
Definition: FileStream.cpp:946
void FileStream_Close(TFileStream *pStream)
Definition: FileStream.cpp:2707
static bool BlockStream_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:940
DWORD dwFlags
Definition: FileStream.h:187
STREAM_GETSIZE StreamGetSize
Definition: FileStream.h:159
bool(* BLOCK_READ)(struct TFileStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
Definition: FileStream.h:64
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56
ULONGLONG StreamSize
Definition: FileStream.h:184
STREAM_READ StreamRead
Definition: FileStream.h:156

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void FileStream_Close ( TFileStream pStream)

This function closes an archive file and frees any data buffers that have been allocated for stream management. The function must also support partially allocated structure, i.e. one or more buffers can be NULL, if there was an allocation failure during the process

pStream Pointer to an open stream

2708 {
2709  // Check if the stream structure is allocated at all
2710  if(pStream != NULL)
2711  {
2712  // Free the master stream, if any
2713  if(pStream->pMaster != NULL)
2714  FileStream_Close(pStream->pMaster);
2715  pStream->pMaster = NULL;
2716 
2717  // Close the stream provider.
2718  if(pStream->StreamClose != NULL)
2719  pStream->StreamClose(pStream);
2720 
2721  // Also close base stream, if any
2722  else if(pStream->BaseClose != NULL)
2723  pStream->BaseClose(pStream);
2724 
2725  // Free the stream itself
2726  CASC_FREE(pStream);
2727  }
2728 }
STREAM_CLOSE StreamClose
Definition: FileStream.h:161
arena_t NULL
Definition: jemalloc_internal.h:624
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
void FileStream_Close(TFileStream *pStream)
Definition: FileStream.cpp:2707
TFileStream * pMaster
Definition: FileStream.h:181

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

TFileStream* FileStream_CreateFile ( const TCHAR szFileName,
DWORD  dwStreamFlags 
)

This function creates a new file for read-write access

  • If the current platform supports file sharing, the file must be created for read sharing (i.e. another application can open the file for read, but not for write)
  • If the file does not exist, the function must create new one
  • If the file exists, the function must rewrite it and set to zero size
  • The parameters of the function must be validate by the caller
  • The function must initialize all stream function pointers in TFileStream
  • If the function fails from any reason, it must close all handles and free all memory that has been allocated in the process of stream creation, including the TFileStream structure itself

szFileName Name of the file to create

2331 {
2332  TFileStream * pStream;
2333 
2334  // We only support creation of flat, local file
2335  if((dwStreamFlags & (STREAM_PROVIDERS_MASK)) != (STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE))
2336  {
2338  return NULL;
2339  }
2340 
2341  // Allocate file stream structure for flat stream
2342  pStream = AllocateFileStream(szFileName, sizeof(TBlockStream), dwStreamFlags);
2343  if(pStream != NULL)
2344  {
2345  // Attempt to create the disk file
2346  if(BaseFile_Create(pStream))
2347  {
2348  // Fill the stream provider functions
2349  pStream->StreamRead = pStream->BaseRead;
2350  pStream->StreamWrite = pStream->BaseWrite;
2351  pStream->StreamResize = pStream->BaseResize;
2352  pStream->StreamGetSize = pStream->BaseGetSize;
2353  pStream->StreamGetPos = pStream->BaseGetPos;
2354  pStream->StreamClose = pStream->BaseClose;
2355  return pStream;
2356  }
2357 
2358  // File create failed, delete the stream
2359  CASC_FREE(pStream);
2360  pStream = NULL;
2361  }
2362 
2363  // Return the stream
2364  return pStream;
2365 }
STREAM_GETPOS StreamGetPos
Definition: FileStream.h:160
STREAM_CLOSE StreamClose
Definition: FileStream.h:161
static TFileStream * AllocateFileStream(const TCHAR *szFileName, size_t StreamSize, DWORD dwStreamFlags)
Definition: FileStream.cpp:977
STREAM_READ BaseRead
Definition: FileStream.h:170
arena_t NULL
Definition: jemalloc_internal.h:624
STREAM_RESIZE BaseResize
Definition: FileStream.h:172
STREAM_WRITE BaseWrite
Definition: FileStream.h:171
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
void SetLastError(int nError)
Definition: Common.cpp:75
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
STREAM_GETPOS BaseGetPos
Definition: FileStream.h:174
STREAM_WRITE StreamWrite
Definition: FileStream.h:157
#define STREAM_PROVIDER_FLAT
Definition: CascLib.h:50
STREAM_RESIZE StreamResize
Definition: FileStream.h:158
#define BASE_PROVIDER_FILE
Definition: CascLib.h:45
static bool BaseFile_Create(TFileStream *pStream)
Definition: FileStream.cpp:52
STREAM_GETSIZE StreamGetSize
Definition: FileStream.h:159
Definition: FileStream.h:153
#define ERROR_NOT_SUPPORTED
Definition: CascPort.h:209
#define STREAM_PROVIDERS_MASK
Definition: CascLib.h:61
Definition: FileStream.h:195
STREAM_GETSIZE BaseGetSize
Definition: FileStream.h:173
STREAM_READ StreamRead
Definition: FileStream.h:156

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

const TCHAR* FileStream_GetFileName ( TFileStream pStream)

Returns the file name of the stream

pStream Pointer to an open stream

2422 {
2423  assert(pStream != NULL);
2424  return pStream->szFileName;
2425 }
arena_t NULL
Definition: jemalloc_internal.h:624
TCHAR * szFileName
Definition: FileStream.h:182
bool FileStream_GetFlags ( TFileStream pStream,
PDWORD  pdwStreamFlags 
)

Returns the stream flags

pStream Pointer to an open stream pdwStreamFlags Pointer where to store the stream flags

2650 {
2651  *pdwStreamFlags = pStream->dwFlags;
2652  return true;
2653 }
DWORD dwFlags
Definition: FileStream.h:187
bool FileStream_GetPos ( TFileStream pStream,
ULONGLONG pByteOffset 
)

This function returns the current file position pStream pByteOffset

2625 {
2626  assert(pStream->StreamGetPos != NULL);
2627  return pStream->StreamGetPos(pStream, pByteOffset);
2628 }
STREAM_GETPOS StreamGetPos
Definition: FileStream.h:160
arena_t NULL
Definition: jemalloc_internal.h:624
bool FileStream_GetSize ( TFileStream pStream,
ULONGLONG pFileSize 
)

Returns the size of a file

pStream Pointer to an open stream FileSize Pointer where to store the file size

2596 {
2597  assert(pStream->StreamGetSize != NULL);
2598  return pStream->StreamGetSize(pStream, pFileSize);
2599 }
arena_t NULL
Definition: jemalloc_internal.h:624
STREAM_GETSIZE StreamGetSize
Definition: FileStream.h:159

+ Here is the caller graph for this function:

bool FileStream_GetTime ( TFileStream pStream,
ULONGLONG pFileTime 
)

Returns the last write time of a file

pStream Pointer to an open stream pFileType Pointer where to store the file last write time

2637 {
2638  // Just use the saved filetime value
2639  *pFileTime = pStream->Base.File.FileTime;
2640  return true;
2641 }
ULONGLONG FileTime
Definition: FileStream.h:131
TBaseProviderData Base
Definition: FileStream.h:178
struct TBaseProviderData::@0 File
TFileStream* FileStream_OpenFile ( const TCHAR szFileName,
DWORD  dwStreamFlags 
)

This function opens an existing file for read or read-write access

  • If the current platform supports file sharing, the file must be open for read sharing (i.e. another application can open the file for read, but not for write)
  • If the file does not exist, the function must return NULL
  • If the file exists but cannot be open, then function must return NULL
  • The parameters of the function must be validate by the caller
  • The function must initialize all stream function pointers in TFileStream
  • If the function fails from any reason, it must close all handles and free all memory that has been allocated in the process of stream creation, including the TFileStream structure itself

szFileName Name of the file to open dwStreamFlags specifies the provider and base storage type

2387 {
2388  DWORD dwProvider = dwStreamFlags & STREAM_PROVIDERS_MASK;
2389  size_t nPrefixLength = FileStream_Prefix(szFileName, &dwProvider);
2390 
2391  // Re-assemble the stream flags
2392  dwStreamFlags = (dwStreamFlags & STREAM_OPTIONS_MASK) | dwProvider;
2393  szFileName += nPrefixLength;
2394 
2395  // Perform provider-specific open
2396  switch(dwStreamFlags & STREAM_PROVIDER_MASK)
2397  {
2398  case STREAM_PROVIDER_FLAT:
2399  return FlatStream_Open(szFileName, dwStreamFlags);
2400 
2402  return PartStream_Open(szFileName, dwStreamFlags);
2403 
2405  return EncrStream_Open(szFileName, dwStreamFlags);
2406 
2408  return Block4Stream_Open(szFileName, dwStreamFlags);
2409 
2410  default:
2412  return NULL;
2413  }
2414 }
#define STREAM_OPTIONS_MASK
Definition: CascLib.h:59
static TFileStream * Block4Stream_Open(const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:2194
arena_t NULL
Definition: jemalloc_internal.h:624
void SetLastError(int nError)
Definition: Common.cpp:75
size_t FileStream_Prefix(const TCHAR *szFileName, DWORD *pdwProvider)
Definition: FileStream.cpp:2434
#define STREAM_PROVIDER_ENCRYPTED
Definition: CascLib.h:52
static TFileStream * FlatStream_Open(const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:1328
#define STREAM_PROVIDER_FLAT
Definition: CascLib.h:50
#define STREAM_PROVIDER_MASK
Definition: CascLib.h:54
unsigned int DWORD
Definition: CascPort.h:139
#define STREAM_PROVIDER_PARTIAL
Definition: CascLib.h:51
static TFileStream * PartStream_Open(const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:1748
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
#define STREAM_PROVIDERS_MASK
Definition: CascLib.h:61
#define STREAM_PROVIDER_BLOCK4
Definition: CascLib.h:53
static TFileStream * EncrStream_Open(const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:2065

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

size_t FileStream_Prefix ( const TCHAR szFileName,
DWORD pdwProvider 
)

Returns the length of the provider prefix. Returns zero if no prefix

szFileName Pointer to a stream name (file, mapped file, URL) pdwStreamProvider Pointer to a DWORD variable that receives stream provider (STREAM_PROVIDER_XXX)

2435 {
2436  size_t nPrefixLength1 = 0;
2437  size_t nPrefixLength2 = 0;
2438  DWORD dwProvider = 0;
2439 
2440  if(szFileName != NULL)
2441  {
2442  //
2443  // Determine the stream provider
2444  //
2445 
2446  if(!_tcsnicmp(szFileName, _T("flat-"), 5))
2447  {
2448  dwProvider |= STREAM_PROVIDER_FLAT;
2449  nPrefixLength1 = 5;
2450  }
2451 
2452  else if(!_tcsnicmp(szFileName, _T("part-"), 5))
2453  {
2454  dwProvider |= STREAM_PROVIDER_PARTIAL;
2455  nPrefixLength1 = 5;
2456  }
2457 
2458  else if(!_tcsnicmp(szFileName, _T("mpqe-"), 5))
2459  {
2460  dwProvider |= STREAM_PROVIDER_ENCRYPTED;
2461  nPrefixLength1 = 5;
2462  }
2463 
2464  else if(!_tcsnicmp(szFileName, _T("blk4-"), 5))
2465  {
2466  dwProvider |= STREAM_PROVIDER_BLOCK4;
2467  nPrefixLength1 = 5;
2468  }
2469 
2470  //
2471  // Determine the base provider
2472  //
2473 
2474  if(!_tcsnicmp(szFileName+nPrefixLength1, _T("file:"), 5))
2475  {
2476  dwProvider |= BASE_PROVIDER_FILE;
2477  nPrefixLength2 = 5;
2478  }
2479 
2480  else if(!_tcsnicmp(szFileName+nPrefixLength1, _T("map:"), 4))
2481  {
2482  dwProvider |= BASE_PROVIDER_MAP;
2483  nPrefixLength2 = 4;
2484  }
2485 
2486  else if(!_tcsnicmp(szFileName+nPrefixLength1, _T("http:"), 5))
2487  {
2488  dwProvider |= BASE_PROVIDER_HTTP;
2489  nPrefixLength2 = 5;
2490  }
2491 
2492  // Only accept stream provider if we recognized the base provider
2493  if(nPrefixLength2 != 0)
2494  {
2495  // It is also allowed to put "//" after the base provider, e.g. "file://", "http://"
2496  if(szFileName[nPrefixLength1+nPrefixLength2] == '/' && szFileName[nPrefixLength1+nPrefixLength2+1] == '/')
2497  nPrefixLength2 += 2;
2498 
2499  if(pdwProvider != NULL)
2500  *pdwProvider = dwProvider;
2501  return nPrefixLength1 + nPrefixLength2;
2502  }
2503  }
2504 
2505  return 0;
2506 }
arena_t NULL
Definition: jemalloc_internal.h:624
#define BASE_PROVIDER_HTTP
Definition: CascLib.h:47
#define _T(x)
Definition: CascPort.h:171
#define BASE_PROVIDER_MAP
Definition: CascLib.h:46
#define STREAM_PROVIDER_ENCRYPTED
Definition: CascLib.h:52
#define STREAM_PROVIDER_FLAT
Definition: CascLib.h:50
unsigned int DWORD
Definition: CascPort.h:139
#define STREAM_PROVIDER_PARTIAL
Definition: CascLib.h:51
#define BASE_PROVIDER_FILE
Definition: CascLib.h:45
#define _tcsnicmp
Definition: CascPort.h:188
#define STREAM_PROVIDER_BLOCK4
Definition: CascLib.h:53

+ Here is the caller graph for this function:

bool FileStream_Read ( TFileStream pStream,
ULONGLONG pByteOffset,
void *  pvBuffer,
DWORD  dwBytesToRead 
)

Reads data from the stream

  • Returns true if the read operation succeeded and all bytes have been read
  • Returns false if either read failed or not all bytes have been read
  • If the pByteOffset is NULL, the function must read the data from the current file position
  • The function can be called with dwBytesToRead = 0. In that case, pvBuffer is ignored and the function just adjusts file pointer.

pStream Pointer to an open stream pByteOffset Pointer to file byte offset. If NULL, it reads from the current position pvBuffer Pointer to data to be read dwBytesToRead Number of bytes to read from the file

Returns
  • If the function reads the required amount of bytes, it returns true.
  • If the function reads less than required bytes, it returns false and GetLastError() returns ERROR_HANDLE_EOF
  • If the function fails, it reads false and GetLastError() returns an error code different from ERROR_HANDLE_EOF
2552 {
2553  //FILE * fp = fopen("E:\\Loading.txt", "at");
2554  //if(fp != NULL)
2555  //{
2556  // ULONGLONG ByteOffset = (pByteOffset != NULL) ? pByteOffset[0] : 0;
2557  // fprintf(fp, "%-32ws\t%08X\t%08X\n", GetPlainFileName(pStream->szFileName), (ULONG)ByteOffset, dwBytesToRead);
2558  // fclose(fp);
2559  //}
2560 
2561  assert(pStream->StreamRead != NULL);
2562  return pStream->StreamRead(pStream, pByteOffset, pvBuffer, dwBytesToRead);
2563 }
arena_t NULL
Definition: jemalloc_internal.h:624
STREAM_READ StreamRead
Definition: FileStream.h:156

+ Here is the caller graph for this function:

bool FileStream_Replace ( TFileStream pStream,
TFileStream pNewStream 
)

Switches a stream with another. Used for final phase of archive compacting. Performs these steps:

1) Closes the handle to the existing file 2) Renames the temporary file to the original file, overwrites existing one 3) Opens the file stores the handle and stream position to the new stream structure

pStream Pointer to an open stream pNewStream Temporary ("working") stream (created during archive compacting)

2667 {
2668  // Only supported on flat files
2670  {
2672  return false;
2673  }
2674 
2675  // Not supported on read-only streams
2676  if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
2677  {
2679  return false;
2680  }
2681 
2682  // Close both stream's base providers
2683  pNewStream->BaseClose(pNewStream);
2684  pStream->BaseClose(pStream);
2685 
2686  // Now we have to delete the (now closed) old file and rename the new file
2687  if(!BaseFile_Replace(pStream, pNewStream))
2688  return false;
2689 
2690  // Now open the base file again
2691  if(!BaseFile_Open(pStream, pStream->szFileName, pStream->dwFlags))
2692  return false;
2693 
2694  // Cleanup the new stream
2695  FileStream_Close(pNewStream);
2696  return true;
2697 }
void SetLastError(int nError)
Definition: Common.cpp:75
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
TCHAR * szFileName
Definition: FileStream.h:182
#define ERROR_ACCESS_DENIED
Definition: CascPort.h:206
#define STREAM_PROVIDER_FLAT
Definition: CascLib.h:50
void FileStream_Close(TFileStream *pStream)
Definition: FileStream.cpp:2707
DWORD dwFlags
Definition: FileStream.h:187
#define BASE_PROVIDER_FILE
Definition: CascLib.h:45
#define ERROR_NOT_SUPPORTED
Definition: CascPort.h:209
#define STREAM_PROVIDERS_MASK
Definition: CascLib.h:61
static bool BaseFile_Replace(TFileStream *pStream, TFileStream *pNewStream)
Definition: FileStream.cpp:358
static bool BaseFile_Open(TFileStream *pStream, const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:91
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56

+ Here is the call graph for this function:

bool FileStream_SetCallback ( TFileStream pStream,
STREAM_DOWNLOAD_CALLBACK  pfnCallback,
void *  pvUserData 
)

Sets a download callback. Whenever the stream needs to download one or more blocks from the server, the callback is called

pStream Pointer to an open stream pfnCallback Pointer to callback function pvUserData Arbitrary user pointer passed to the download callback

2518 {
2519  TBlockStream * pBlockStream = (TBlockStream *)pStream;
2520 
2521  if(pStream->BlockRead == NULL)
2522  {
2524  return false;
2525  }
2526 
2527  pBlockStream->pfnCallback = pfnCallback;
2528  pBlockStream->UserData = pvUserData;
2529  return true;
2530 }
void * UserData
Definition: FileStream.h:199
arena_t NULL
Definition: jemalloc_internal.h:624
BLOCK_READ BlockRead
Definition: FileStream.h:164
void SetLastError(int nError)
Definition: Common.cpp:75
STREAM_DOWNLOAD_CALLBACK pfnCallback
Definition: FileStream.h:197
#define ERROR_NOT_SUPPORTED
Definition: CascPort.h:209
Definition: FileStream.h:195

+ Here is the call graph for this function:

bool FileStream_SetSize ( TFileStream pStream,
ULONGLONG  NewFileSize 
)

Sets the size of a file

pStream Pointer to an open stream NewFileSize File size to set

2608 {
2609  if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
2610  {
2612  return false;
2613  }
2614 
2615  assert(pStream->StreamResize != NULL);
2616  return pStream->StreamResize(pStream, NewFileSize);
2617 }
arena_t NULL
Definition: jemalloc_internal.h:624
void SetLastError(int nError)
Definition: Common.cpp:75
#define ERROR_ACCESS_DENIED
Definition: CascPort.h:206
STREAM_RESIZE StreamResize
Definition: FileStream.h:158
DWORD dwFlags
Definition: FileStream.h:187
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56

+ Here is the call graph for this function:

bool FileStream_Write ( TFileStream pStream,
ULONGLONG pByteOffset,
const void *  pvBuffer,
DWORD  dwBytesToWrite 
)

This function writes data to the stream

  • Returns true if the write operation succeeded and all bytes have been written
  • Returns false if either write failed or not all bytes have been written
  • If the pByteOffset is NULL, the function must write the data to the current file position

pStream Pointer to an open stream pByteOffset Pointer to file byte offset. If NULL, it reads from the current position pvBuffer Pointer to data to be written dwBytesToWrite Number of bytes to write to the file

2578 {
2579  if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
2580  {
2582  return false;
2583  }
2584 
2585  assert(pStream->StreamWrite != NULL);
2586  return pStream->StreamWrite(pStream, pByteOffset, pvBuffer, dwBytesToWrite);
2587 }
arena_t NULL
Definition: jemalloc_internal.h:624
void SetLastError(int nError)
Definition: Common.cpp:75
STREAM_WRITE StreamWrite
Definition: FileStream.h:157
#define ERROR_ACCESS_DENIED
Definition: CascPort.h:206
DWORD dwFlags
Definition: FileStream.h:187
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool FlatStream_BlockCheck ( TBlockStream pStream,
ULONGLONG  BlockOffset 
)
static
1166 {
1167  LPBYTE FileBitmap = (LPBYTE)pStream->FileBitmap;
1168  DWORD BlockIndex;
1169  BYTE BitMask;
1170 
1171  // Sanity checks
1172  assert((BlockOffset & (pStream->BlockSize - 1)) == 0);
1173  assert(FileBitmap != NULL);
1174 
1175  // Calculate the index of the block
1176  BlockIndex = (DWORD)(BlockOffset / pStream->BlockSize);
1177  BitMask = (BYTE)(1 << (BlockIndex & 0x07));
1178 
1179  // Check if the bit is present
1180  return (FileBitmap[BlockIndex / 0x08] & BitMask) ? true : false;
1181 }
void * FileBitmap
Definition: FileStream.h:198
arena_t NULL
Definition: jemalloc_internal.h:624
BYTE * LPBYTE
Definition: CascPort.h:152
unsigned int DWORD
Definition: CascPort.h:139
DWORD BlockSize
Definition: FileStream.h:201
unsigned char BYTE
Definition: CascPort.h:136

+ Here is the caller graph for this function:

static bool FlatStream_BlockRead ( TBlockStream pStream,
ULONGLONG  StartOffset,
ULONGLONG  EndOffset,
LPBYTE  BlockBuffer,
DWORD  BytesNeeded,
bool  bAvailable 
)
static
1190 {
1191  DWORD BytesToRead = (DWORD)(EndOffset - StartOffset);
1192 
1193  // The starting offset must be aligned to size of the block
1194  assert(pStream->FileBitmap != NULL);
1195  assert((StartOffset & (pStream->BlockSize - 1)) == 0);
1196  assert(StartOffset < EndOffset);
1197 
1198  // If the blocks are not available, we need to load them from the master
1199  // and then save to the mirror
1200  if(bAvailable == false)
1201  {
1202  // If we have no master, we cannot satisfy read request
1203  if(pStream->pMaster == NULL)
1204  return false;
1205 
1206  // Load the blocks from the master stream
1207  // Note that we always have to read complete blocks
1208  // so they get properly stored to the mirror stream
1209  if(!FileStream_Read(pStream->pMaster, &StartOffset, BlockBuffer, BytesToRead))
1210  return false;
1211 
1212  // Store the loaded blocks to the mirror file.
1213  // Note that this operation is not required to succeed
1214  if(pStream->BaseWrite(pStream, &StartOffset, BlockBuffer, BytesToRead))
1215  FlatStream_UpdateBitmap(pStream, StartOffset, EndOffset);
1216 
1217  return true;
1218  }
1219  else
1220  {
1221  if(BytesToRead > BytesNeeded)
1222  BytesToRead = BytesNeeded;
1223  return pStream->BaseRead(pStream, &StartOffset, BlockBuffer, BytesToRead);
1224  }
1225 }
void * FileBitmap
Definition: FileStream.h:198
bool FileStream_Read(TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:2551
STREAM_READ BaseRead
Definition: FileStream.h:170
arena_t NULL
Definition: jemalloc_internal.h:624
static void FlatStream_UpdateBitmap(TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset)
Definition: FileStream.cpp:1127
STREAM_WRITE BaseWrite
Definition: FileStream.h:171
TFileStream * pMaster
Definition: FileStream.h:181
unsigned int DWORD
Definition: CascPort.h:139
DWORD BlockSize
Definition: FileStream.h:201

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static DWORD FlatStream_CheckFile ( TBlockStream pStream)
static
1038 {
1039  LPBYTE FileBitmap = (LPBYTE)pStream->FileBitmap;
1040  DWORD WholeByteCount = (pStream->BlockCount / 8);
1041  DWORD ExtraBitsCount = (pStream->BlockCount & 7);
1042  BYTE ExpectedValue;
1043 
1044  // Verify the whole bytes - their value must be 0xFF
1045  for(DWORD i = 0; i < WholeByteCount; i++)
1046  {
1047  if(FileBitmap[i] != 0xFF)
1048  return 0;
1049  }
1050 
1051  // If there are extra bits, calculate the mask
1052  if(ExtraBitsCount != 0)
1053  {
1054  ExpectedValue = (BYTE)((1 << ExtraBitsCount) - 1);
1055  if(FileBitmap[WholeByteCount] != ExpectedValue)
1056  return 0;
1057  }
1058 
1059  // Yes, the file is complete
1060  return 1;
1061 }
void * FileBitmap
Definition: FileStream.h:198
BYTE * LPBYTE
Definition: CascPort.h:152
DWORD BlockCount
Definition: FileStream.h:202
unsigned int DWORD
Definition: CascPort.h:139
unsigned char BYTE
Definition: CascPort.h:136

+ Here is the caller graph for this function:

static void FlatStream_Close ( TBlockStream pStream)
static
1228 {
1229  FILE_BITMAP_FOOTER Footer;
1230 
1231  if(pStream->FileBitmap && pStream->IsModified)
1232  {
1233  // Write the file bitmap
1234  pStream->BaseWrite(pStream, &pStream->StreamSize, pStream->FileBitmap, pStream->BitmapSize);
1235 
1236  // Prepare and write the file footer
1238  Footer.Version = 3;
1239  Footer.BuildNumber = pStream->BuildNumber;
1240  Footer.MapOffsetLo = (DWORD)(pStream->StreamSize & 0xFFFFFFFF);
1241  Footer.MapOffsetHi = (DWORD)(pStream->StreamSize >> 0x20);
1242  Footer.BlockSize = pStream->BlockSize;
1243  BSWAP_ARRAY32_UNSIGNED(&Footer, sizeof(FILE_BITMAP_FOOTER));
1244  pStream->BaseWrite(pStream, NULL, &Footer, sizeof(FILE_BITMAP_FOOTER));
1245  }
1246 
1247  // Close the base class
1248  BlockStream_Close(pStream);
1249 }
DWORD BitmapSize
Definition: FileStream.h:200
void * FileBitmap
Definition: FileStream.h:198
arena_t NULL
Definition: jemalloc_internal.h:624
STREAM_WRITE BaseWrite
Definition: FileStream.h:171
DWORD BuildNumber
Definition: FileStream.h:186
#define ID_FILE_BITMAP_FOOTER
Definition: FileStream.h:85
unsigned int DWORD
Definition: CascPort.h:139
DWORD IsModified
Definition: FileStream.h:204
DWORD BlockSize
Definition: FileStream.h:201
ULONGLONG StreamSize
Definition: FileStream.h:184
#define BSWAP_ARRAY32_UNSIGNED(a, b)
Definition: CascPort.h:232
static void BlockStream_Close(TBlockStream *pStream)
Definition: FileStream.cpp:952

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool FlatStream_CreateMirror ( TBlockStream pStream)
static
1252 {
1253  ULONGLONG MasterSize = 0;
1254  ULONGLONG MirrorSize = 0;
1255  LPBYTE FileBitmap = NULL;
1256  DWORD dwBitmapSize;
1257  DWORD dwBlockCount;
1258  bool bNeedCreateMirrorStream = true;
1259  bool bNeedResizeMirrorStream = true;
1260 
1261  // Do we have master function and base creation function?
1262  if(pStream->pMaster == NULL || pStream->BaseCreate == NULL)
1263  return false;
1264 
1265  // Retrieve the master file size, block count and bitmap size
1266  FileStream_GetSize(pStream->pMaster, &MasterSize);
1267  dwBlockCount = (DWORD)((MasterSize + DEFAULT_BLOCK_SIZE - 1) / DEFAULT_BLOCK_SIZE);
1268  dwBitmapSize = (DWORD)((dwBlockCount + 7) / 8);
1269 
1270  // Setup stream size and position
1271  pStream->BuildNumber = DEFAULT_BUILD_NUMBER; // BUGBUG: Really???
1272  pStream->StreamSize = MasterSize;
1273  pStream->StreamPos = 0;
1274 
1275  // Open the base stream for write access
1276  if(pStream->BaseOpen(pStream, pStream->szFileName, 0))
1277  {
1278  // If the file open succeeded, check if the file size matches required size
1279  pStream->BaseGetSize(pStream, &MirrorSize);
1280  if(MirrorSize == MasterSize + dwBitmapSize + sizeof(FILE_BITMAP_FOOTER))
1281  {
1282  // Attempt to load an existing file bitmap
1283  if(FlatStream_LoadBitmap(pStream))
1284  return true;
1285 
1286  // We need to create new file bitmap
1287  bNeedResizeMirrorStream = false;
1288  }
1289 
1290  // We need to create mirror stream
1291  bNeedCreateMirrorStream = false;
1292  }
1293 
1294  // Create a new stream, if needed
1295  if(bNeedCreateMirrorStream)
1296  {
1297  if(!pStream->BaseCreate(pStream))
1298  return false;
1299  }
1300 
1301  // If we need to, then resize the mirror stream
1302  if(bNeedResizeMirrorStream)
1303  {
1304  if(!pStream->BaseResize(pStream, MasterSize + dwBitmapSize + sizeof(FILE_BITMAP_FOOTER)))
1305  return false;
1306  }
1307 
1308  // Allocate the bitmap array
1309  FileBitmap = CASC_ALLOC(BYTE, dwBitmapSize);
1310  if(FileBitmap == NULL)
1311  return false;
1312 
1313  // Initialize the bitmap
1314  memset(FileBitmap, 0, dwBitmapSize);
1315  pStream->FileBitmap = FileBitmap;
1316  pStream->BitmapSize = dwBitmapSize;
1317  pStream->BlockSize = DEFAULT_BLOCK_SIZE;
1318  pStream->BlockCount = dwBlockCount;
1319  pStream->IsComplete = 0;
1320  pStream->IsModified = 1;
1321 
1322  // Note: Don't write the stream bitmap right away.
1323  // Doing so would cause sparse file resize on NTFS,
1324  // which would take long time on larger files.
1325  return true;
1326 }
DWORD BitmapSize
Definition: FileStream.h:200
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
void * FileBitmap
Definition: FileStream.h:198
unsigned long long ULONGLONG
Definition: CascPort.h:144
STREAM_OPEN BaseOpen
Definition: FileStream.h:169
bool FileStream_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:2595
arena_t NULL
Definition: jemalloc_internal.h:624
BYTE * LPBYTE
Definition: CascPort.h:152
STREAM_RESIZE BaseResize
Definition: FileStream.h:172
ULONGLONG StreamPos
Definition: FileStream.h:185
TCHAR * szFileName
Definition: FileStream.h:182
DWORD BuildNumber
Definition: FileStream.h:186
STREAM_CREATE BaseCreate
Definition: FileStream.h:168
DWORD IsComplete
Definition: FileStream.h:203
DWORD BlockCount
Definition: FileStream.h:202
TFileStream * pMaster
Definition: FileStream.h:181
unsigned int DWORD
Definition: CascPort.h:139
DWORD IsModified
Definition: FileStream.h:204
DWORD BlockSize
Definition: FileStream.h:201
unsigned char BYTE
Definition: CascPort.h:136
#define DEFAULT_BLOCK_SIZE
Definition: FileStream.h:86
ULONGLONG StreamSize
Definition: FileStream.h:184
#define DEFAULT_BUILD_NUMBER
Definition: FileStream.h:87
STREAM_GETSIZE BaseGetSize
Definition: FileStream.h:173
static bool FlatStream_LoadBitmap(TBlockStream *pStream)
Definition: FileStream.cpp:1063

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool FlatStream_LoadBitmap ( TBlockStream pStream)
static
1064 {
1065  FILE_BITMAP_FOOTER Footer;
1066  ULONGLONG ByteOffset;
1067  LPBYTE FileBitmap;
1068  DWORD BlockCount;
1069  DWORD BitmapSize;
1070 
1071  // Do not load the bitmap if we should not have to
1072  if(!(pStream->dwFlags & STREAM_FLAG_USE_BITMAP))
1073  return false;
1074 
1075  // Only if the size is greater than size of bitmap footer
1076  if(pStream->Base.File.FileSize > sizeof(FILE_BITMAP_FOOTER))
1077  {
1078  // Load the bitmap footer
1079  ByteOffset = pStream->Base.File.FileSize - sizeof(FILE_BITMAP_FOOTER);
1080  if(pStream->BaseRead(pStream, &ByteOffset, &Footer, sizeof(FILE_BITMAP_FOOTER)))
1081  {
1082  // Make sure that the array is properly BSWAP-ed
1083  BSWAP_ARRAY32_UNSIGNED((PDWORD)(&Footer), sizeof(FILE_BITMAP_FOOTER));
1084 
1085  // Verify if there is actually a footer
1086  if(Footer.Signature == ID_FILE_BITMAP_FOOTER && Footer.Version == 0x03)
1087  {
1088  // Get the offset of the bitmap, number of blocks and size of the bitmap
1089  ByteOffset = MAKE_OFFSET64(Footer.MapOffsetHi, Footer.MapOffsetLo);
1090  BlockCount = (DWORD)(((ByteOffset - 1) / Footer.BlockSize) + 1);
1091  BitmapSize = ((BlockCount + 7) / 8);
1092 
1093  // Check if the sizes match
1094  if(ByteOffset + BitmapSize + sizeof(FILE_BITMAP_FOOTER) == pStream->Base.File.FileSize)
1095  {
1096  // Allocate space for the bitmap
1097  FileBitmap = CASC_ALLOC(BYTE, BitmapSize);
1098  if(FileBitmap != NULL)
1099  {
1100  // Load the bitmap bits
1101  if(!pStream->BaseRead(pStream, &ByteOffset, FileBitmap, BitmapSize))
1102  {
1103  CASC_FREE(FileBitmap);
1104  return false;
1105  }
1106 
1107  // Update the stream size
1108  pStream->BuildNumber = Footer.BuildNumber;
1109  pStream->StreamSize = ByteOffset;
1110 
1111  // Fill the bitmap information
1112  pStream->FileBitmap = FileBitmap;
1113  pStream->BitmapSize = BitmapSize;
1114  pStream->BlockSize = Footer.BlockSize;
1115  pStream->BlockCount = BlockCount;
1116  pStream->IsComplete = FlatStream_CheckFile(pStream);
1117  return true;
1118  }
1119  }
1120  }
1121  }
1122  }
1123 
1124  return false;
1125 }
struct _FILE_BITMAP_FOOTER FILE_BITMAP_FOOTER
DWORD BitmapSize
Definition: FileStream.h:200
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
void * FileBitmap
Definition: FileStream.h:198
unsigned long long ULONGLONG
Definition: CascPort.h:144
DWORD * PDWORD
Definition: CascPort.h:151
#define STREAM_FLAG_USE_BITMAP
Definition: CascLib.h:58
STREAM_READ BaseRead
Definition: FileStream.h:170
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
BYTE * LPBYTE
Definition: CascPort.h:152
struct TBaseProviderData::@0 File
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
ULONGLONG FileSize
Definition: FileStream.h:129
DWORD BuildNumber
Definition: FileStream.h:186
DWORD IsComplete
Definition: FileStream.h:203
DWORD BlockCount
Definition: FileStream.h:202
#define ID_FILE_BITMAP_FOOTER
Definition: FileStream.h:85
unsigned int DWORD
Definition: CascPort.h:139
DWORD dwFlags
Definition: FileStream.h:187
static DWORD FlatStream_CheckFile(TBlockStream *pStream)
Definition: FileStream.cpp:1037
DWORD BlockSize
Definition: FileStream.h:201
unsigned char BYTE
Definition: CascPort.h:136
#define MAKE_OFFSET64(hi, lo)
Definition: Common.h:18
ULONGLONG StreamSize
Definition: FileStream.h:184
#define BSWAP_ARRAY32_UNSIGNED(a, b)
Definition: CascPort.h:232

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static TFileStream* FlatStream_Open ( const TCHAR szFileName,
DWORD  dwStreamFlags 
)
static
1329 {
1330  TBlockStream * pStream;
1331  ULONGLONG ByteOffset = 0;
1332 
1333  // Create new empty stream
1334  pStream = (TBlockStream *)AllocateFileStream(szFileName, sizeof(TBlockStream), dwStreamFlags);
1335  if(pStream == NULL)
1336  return NULL;
1337 
1338  // Do we have a master stream?
1339  if(pStream->pMaster != NULL)
1340  {
1341  if(!FlatStream_CreateMirror(pStream))
1342  {
1343  FileStream_Close(pStream);
1345  return NULL;
1346  }
1347  }
1348  else
1349  {
1350  // Attempt to open the base stream
1351  if(!pStream->BaseOpen(pStream, pStream->szFileName, dwStreamFlags))
1352  {
1353  FileStream_Close(pStream);
1354  return NULL;
1355  }
1356 
1357  // Load the bitmap, if required to
1358  if(dwStreamFlags & STREAM_FLAG_USE_BITMAP)
1359  FlatStream_LoadBitmap(pStream);
1360  }
1361 
1362  // If we have a stream bitmap, set the reading functions
1363  // which check presence of each file block
1364  if(pStream->FileBitmap != NULL)
1365  {
1366  // Set the stream position to zero. Stream size is already set
1367  assert(pStream->StreamSize != 0);
1368  pStream->StreamPos = 0;
1369  pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
1370 
1371  // Supply the stream functions
1374  pStream->StreamGetPos = BlockStream_GetPos;
1376 
1377  // Supply the block functions
1380  }
1381  else
1382  {
1383  // Reset the base position to zero
1384  pStream->BaseRead(pStream, &ByteOffset, NULL, 0);
1385 
1386  // Setup stream size and position
1387  pStream->StreamSize = pStream->Base.File.FileSize;
1388  pStream->StreamPos = 0;
1389 
1390  // Set the base functions
1391  pStream->StreamRead = pStream->BaseRead;
1392  pStream->StreamWrite = pStream->BaseWrite;
1393  pStream->StreamResize = pStream->BaseResize;
1394  pStream->StreamGetSize = pStream->BaseGetSize;
1395  pStream->StreamGetPos = pStream->BaseGetPos;
1396  pStream->StreamClose = pStream->BaseClose;
1397  }
1398 
1399  return pStream;
1400 }
STREAM_GETPOS StreamGetPos
Definition: FileStream.h:160
STREAM_CLOSE StreamClose
Definition: FileStream.h:161
void * FileBitmap
Definition: FileStream.h:198
unsigned long long ULONGLONG
Definition: CascPort.h:144
#define STREAM_FLAG_USE_BITMAP
Definition: CascLib.h:58
static TFileStream * AllocateFileStream(const TCHAR *szFileName, size_t StreamSize, DWORD dwStreamFlags)
Definition: FileStream.cpp:977
STREAM_OPEN BaseOpen
Definition: FileStream.h:169
STREAM_READ BaseRead
Definition: FileStream.h:170
arena_t NULL
Definition: jemalloc_internal.h:624
TBaseProviderData Base
Definition: FileStream.h:178
BLOCK_READ BlockRead
Definition: FileStream.h:164
bool(* BLOCK_CHECK)(struct TFileStream *pStream, ULONGLONG BlockOffset)
Definition: FileStream.h:73
bool(* STREAM_READ)(struct TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.h:31
void(* STREAM_CLOSE)(struct TFileStream *pStream)
Definition: FileStream.h:60
struct TBaseProviderData::@0 File
STREAM_RESIZE BaseResize
Definition: FileStream.h:172
STREAM_WRITE BaseWrite
Definition: FileStream.h:171
ULONGLONG StreamPos
Definition: FileStream.h:185
ULONGLONG FileSize
Definition: FileStream.h:129
static bool FlatStream_BlockCheck(TBlockStream *pStream, ULONGLONG BlockOffset)
Definition: FileStream.cpp:1163
void SetLastError(int nError)
Definition: Common.cpp:75
STREAM_CLOSE BaseClose
Definition: FileStream.h:175
#define ERROR_FILE_NOT_FOUND
Definition: CascPort.h:205
TCHAR * szFileName
Definition: FileStream.h:182
static bool BlockStream_Read(TBlockStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:800
static bool BlockStream_GetPos(TFileStream *pStream, ULONGLONG *pByteOffset)
Definition: FileStream.cpp:946
STREAM_GETPOS BaseGetPos
Definition: FileStream.h:174
STREAM_WRITE StreamWrite
Definition: FileStream.h:157
void FileStream_Close(TFileStream *pStream)
Definition: FileStream.cpp:2707
TFileStream * pMaster
Definition: FileStream.h:181
STREAM_RESIZE StreamResize
Definition: FileStream.h:158
static bool BlockStream_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:940
DWORD dwFlags
Definition: FileStream.h:187
STREAM_GETSIZE StreamGetSize
Definition: FileStream.h:159
static bool FlatStream_BlockRead(TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
Definition: FileStream.cpp:1183
static bool FlatStream_CreateMirror(TBlockStream *pStream)
Definition: FileStream.cpp:1251
static void FlatStream_Close(TBlockStream *pStream)
Definition: FileStream.cpp:1227
bool(* BLOCK_READ)(struct TFileStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, LPBYTE BlockBuffer, DWORD BytesNeeded, bool bAvailable)
Definition: FileStream.h:64
BLOCK_CHECK BlockCheck
Definition: FileStream.h:165
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56
ULONGLONG StreamSize
Definition: FileStream.h:184
Definition: FileStream.h:195
STREAM_GETSIZE BaseGetSize
Definition: FileStream.h:173
static bool FlatStream_LoadBitmap(TBlockStream *pStream)
Definition: FileStream.cpp:1063
STREAM_READ StreamRead
Definition: FileStream.h:156

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void FlatStream_UpdateBitmap ( TBlockStream pStream,
ULONGLONG  StartOffset,
ULONGLONG  EndOffset 
)
static
1131 {
1132  LPBYTE FileBitmap = (LPBYTE)pStream->FileBitmap;
1133  DWORD BlockIndex;
1134  DWORD BlockSize = pStream->BlockSize;
1135  DWORD ByteIndex;
1136  BYTE BitMask;
1137 
1138  // Sanity checks
1139  assert((StartOffset & (BlockSize - 1)) == 0);
1140  assert(FileBitmap != NULL);
1141 
1142  // Calculate the index of the block
1143  BlockIndex = (DWORD)(StartOffset / BlockSize);
1144  ByteIndex = (BlockIndex / 0x08);
1145  BitMask = (BYTE)(1 << (BlockIndex & 0x07));
1146 
1147  // Set all bits for the specified range
1148  while(StartOffset < EndOffset)
1149  {
1150  // Set the bit
1151  FileBitmap[ByteIndex] |= BitMask;
1152 
1153  // Move all
1154  StartOffset += BlockSize;
1155  ByteIndex += (BitMask >> 0x07);
1156  BitMask = (BitMask >> 0x07) | (BitMask << 0x01);
1157  }
1158 
1159  // Increment the bitmap update count
1160  pStream->IsModified = 1;
1161 }
void * FileBitmap
Definition: FileStream.h:198
arena_t NULL
Definition: jemalloc_internal.h:624
BYTE * LPBYTE
Definition: CascPort.h:152
unsigned int DWORD
Definition: CascPort.h:139
DWORD IsModified
Definition: FileStream.h:204
DWORD BlockSize
Definition: FileStream.h:201
unsigned char BYTE
Definition: CascPort.h:136

+ Here is the caller graph for this function:

static bool IsPartHeader ( PPART_FILE_HEADER  pPartHdr)
static
1406 {
1407  // Version number must be 2
1408  if(pPartHdr->PartialVersion == 2)
1409  {
1410  // GameBuildNumber must be an ASCII number
1411  if(isdigit(pPartHdr->GameBuildNumber[0]) && isdigit(pPartHdr->GameBuildNumber[1]) && isdigit(pPartHdr->GameBuildNumber[2]))
1412  {
1413  // Block size must be power of 2
1414  if((pPartHdr->BlockSize & (pPartHdr->BlockSize - 1)) == 0)
1415  return true;
1416  }
1417  }
1418 
1419  return false;
1420 }
DWORD BlockSize
Definition: FileStream.h:96
char GameBuildNumber[0x20]
Definition: FileStream.h:92
DWORD PartialVersion
Definition: FileStream.h:91

+ Here is the caller graph for this function:

static bool PartStream_BlockCheck ( TBlockStream pStream,
ULONGLONG  BlockOffset 
)
static
1548 {
1549  PPART_FILE_MAP_ENTRY FileBitmap;
1550 
1551  // Sanity checks
1552  assert((BlockOffset & (pStream->BlockSize - 1)) == 0);
1553  assert(pStream->FileBitmap != NULL);
1554 
1555  // Calculate the block map entry
1556  FileBitmap = (PPART_FILE_MAP_ENTRY)pStream->FileBitmap + (BlockOffset / pStream->BlockSize);
1557 
1558  // Check if the flags are present
1559  return (FileBitmap->Flags & 0x03) ? true : false;
1560 }
void * FileBitmap
Definition: FileStream.h:198
DWORD Flags
Definition: FileStream.h:103
arena_t NULL
Definition: jemalloc_internal.h:624
Definition: FileStream.h:101
DWORD BlockSize
Definition: FileStream.h:201
struct _PART_FILE_MAP_ENTRY * PPART_FILE_MAP_ENTRY

+ Here is the caller graph for this function:

static bool PartStream_BlockRead ( TBlockStream pStream,
ULONGLONG  StartOffset,
ULONGLONG  EndOffset,
LPBYTE  BlockBuffer,
DWORD  BytesNeeded,
bool  bAvailable 
)
static
1569 {
1570  PPART_FILE_MAP_ENTRY FileBitmap;
1571  ULONGLONG ByteOffset;
1572  DWORD BytesToRead;
1573  DWORD BlockIndex = (DWORD)(StartOffset / pStream->BlockSize);
1574 
1575  // The starting offset must be aligned to size of the block
1576  assert(pStream->FileBitmap != NULL);
1577  assert((StartOffset & (pStream->BlockSize - 1)) == 0);
1578  assert(StartOffset < EndOffset);
1579 
1580  // If the blocks are not available, we need to load them from the master
1581  // and then save to the mirror
1582  if(bAvailable == false)
1583  {
1584  // If we have no master, we cannot satisfy read request
1585  if(pStream->pMaster == NULL)
1586  return false;
1587 
1588  // Load the blocks from the master stream
1589  // Note that we always have to read complete blocks
1590  // so they get properly stored to the mirror stream
1591  BytesToRead = (DWORD)(EndOffset - StartOffset);
1592  if(!FileStream_Read(pStream->pMaster, &StartOffset, BlockBuffer, BytesToRead))
1593  return false;
1594 
1595  // The loaded blocks are going to be stored to the end of the file
1596  // Note that this operation is not required to succeed
1597  if(pStream->BaseGetSize(pStream, &ByteOffset))
1598  {
1599  // Store the loaded blocks to the mirror file.
1600  if(pStream->BaseWrite(pStream, &ByteOffset, BlockBuffer, BytesToRead))
1601  {
1602  PartStream_UpdateBitmap(pStream, StartOffset, EndOffset, ByteOffset);
1603  }
1604  }
1605  }
1606  else
1607  {
1608  // Get the file map entry
1609  FileBitmap = (PPART_FILE_MAP_ENTRY)pStream->FileBitmap + BlockIndex;
1610 
1611  // Read all blocks
1612  while(StartOffset < EndOffset)
1613  {
1614  // Get the number of bytes to be read
1615  BytesToRead = (DWORD)(EndOffset - StartOffset);
1616  if(BytesToRead > pStream->BlockSize)
1617  BytesToRead = pStream->BlockSize;
1618  if(BytesToRead > BytesNeeded)
1619  BytesToRead = BytesNeeded;
1620 
1621  // Read the block
1622  ByteOffset = MAKE_OFFSET64(FileBitmap->BlockOffsHi, FileBitmap->BlockOffsLo);
1623  if(!pStream->BaseRead(pStream, &ByteOffset, BlockBuffer, BytesToRead))
1624  return false;
1625 
1626  // Move the pointers
1627  StartOffset += pStream->BlockSize;
1628  BlockBuffer += pStream->BlockSize;
1629  BytesNeeded -= pStream->BlockSize;
1630  FileBitmap++;
1631  }
1632  }
1633 
1634  return true;
1635 }
void * FileBitmap
Definition: FileStream.h:198
unsigned long long ULONGLONG
Definition: CascPort.h:144
DWORD BlockOffsLo
Definition: FileStream.h:104
bool FileStream_Read(TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:2551
STREAM_READ BaseRead
Definition: FileStream.h:170
arena_t NULL
Definition: jemalloc_internal.h:624
STREAM_WRITE BaseWrite
Definition: FileStream.h:171
Definition: FileStream.h:101
TFileStream * pMaster
Definition: FileStream.h:181
unsigned int DWORD
Definition: CascPort.h:139
DWORD BlockOffsHi
Definition: FileStream.h:105
DWORD BlockSize
Definition: FileStream.h:201
#define MAKE_OFFSET64(hi, lo)
Definition: Common.h:18
struct _PART_FILE_MAP_ENTRY * PPART_FILE_MAP_ENTRY
STREAM_GETSIZE BaseGetSize
Definition: FileStream.h:173
static void PartStream_UpdateBitmap(TBlockStream *pStream, ULONGLONG StartOffset, ULONGLONG EndOffset, ULONGLONG RealOffset)
Definition: FileStream.cpp:1511

+ Here is the call graph for this function:

+ Here is the caller graph for this function: