aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/common/FileStream.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2020-05-07 14:39:40 +0200
committerShauren <shauren.trinity@gmail.com>2020-05-07 14:39:40 +0200
commitea812fec1153280b94d2fff8bdefd678e86bddeb (patch)
treecd7d75fc98ab6cc2c975fe4db9be67ccb87f40c1 /dep/CascLib/src/common/FileStream.cpp
parentdfdabdb97bdd776da4add3cd4f19cf5793160abf (diff)
Dep/CascLib: Update to ladislav-zezula/CascLib@0a05c59eb8a3eab1bc5471f43934cd5f992f0aca
Diffstat (limited to 'dep/CascLib/src/common/FileStream.cpp')
-rw-r--r--dep/CascLib/src/common/FileStream.cpp238
1 files changed, 125 insertions, 113 deletions
diff --git a/dep/CascLib/src/common/FileStream.cpp b/dep/CascLib/src/common/FileStream.cpp
index ab591a2e3f1..350b0540cf4 100644
--- a/dep/CascLib/src/common/FileStream.cpp
+++ b/dep/CascLib/src/common/FileStream.cpp
@@ -89,7 +89,7 @@ static bool BaseFile_Create(TFileStream * pStream)
return true;
}
-static bool BaseFile_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
+static bool BaseFile_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags)
{
#ifdef PLATFORM_WINDOWS
{
@@ -160,66 +160,72 @@ static bool BaseFile_Read(
void * pvBuffer, // Pointer to data to be read
DWORD dwBytesToRead) // Number of bytes to read from the file
{
- ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
DWORD dwBytesRead = 0; // Must be set by platform-specific code
-#ifdef PLATFORM_WINDOWS
+ // Synchronize the access to the TFileStream structure
+ CascLock(pStream->Lock);
{
- // Note: We no longer support Windows 9x.
- // Thus, we can use the OVERLAPPED structure to specify
- // file offset to read from file. This allows us to skip
- // one system call to SetFilePointer
-
- // Update the byte offset
- pStream->Base.File.FilePos = ByteOffset;
+ ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
- // Read the data
- if(dwBytesToRead != 0)
+#ifdef PLATFORM_WINDOWS
{
- OVERLAPPED Overlapped;
+ // Note: We no longer support Windows 9x.
+ // Thus, we can use the OVERLAPPED structure to specify
+ // file offset to read from file. This allows us to skip
+ // one system call to SetFilePointer
- Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
- Overlapped.Offset = (DWORD)ByteOffset;
- Overlapped.hEvent = NULL;
- if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
- return false;
+ // Update the byte offset
+ pStream->Base.File.FilePos = ByteOffset;
+
+ // Read the data
+ if (dwBytesToRead != 0)
+ {
+ OVERLAPPED Overlapped;
+
+ Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
+ Overlapped.Offset = (DWORD)ByteOffset;
+ Overlapped.hEvent = NULL;
+ if (!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
+ return false;
+ }
}
- }
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
- {
- ssize_t bytes_read;
-
- // If the byte offset is different from the current file position,
- // we have to update the file position
- if(ByteOffset != pStream->Base.File.FilePos)
{
- if(lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
+ ssize_t bytes_read;
+
+ // If the byte offset is different from the current file position,
+ // we have to update the file position
+ if (ByteOffset != pStream->Base.File.FilePos)
{
- SetLastError(errno);
- return false;
+ if (lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
+ {
+ SetLastError(errno);
+ return false;
+ }
+ pStream->Base.File.FilePos = ByteOffset;
}
- pStream->Base.File.FilePos = ByteOffset;
- }
- // Perform the read operation
- if(dwBytesToRead != 0)
- {
- bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
- if(bytes_read == -1)
+ // Perform the read operation
+ if (dwBytesToRead != 0)
{
- SetLastError(errno);
- return false;
- }
+ bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
+ if (bytes_read == -1)
+ {
+ SetLastError(errno);
+ return false;
+ }
- dwBytesRead = (DWORD)(size_t)bytes_read;
+ dwBytesRead = (DWORD)(size_t)bytes_read;
+ }
}
- }
#endif
- // Increment the current file position by number of bytes read
- pStream->Base.File.FilePos = ByteOffset + dwBytesRead;
+ // Increment the current file position by number of bytes read
+ pStream->Base.File.FilePos = ByteOffset + dwBytesRead;
+ }
+ CascUnlock(pStream->Lock);
// If the number of bytes read doesn't match to required amount, return false
// However, Blizzard's CASC handlers read encoded data so that if less than expected
@@ -249,67 +255,73 @@ static bool BaseFile_Read(
static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite)
{
- ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
DWORD dwBytesWritten = 0; // Must be set by platform-specific code
-#ifdef PLATFORM_WINDOWS
+ // Synchronize the access to the TFileStream structure
+ CascLock(pStream->Lock);
{
- // Note: We no longer support Windows 9x.
- // Thus, we can use the OVERLAPPED structure to specify
- // file offset to read from file. This allows us to skip
- // one system call to SetFilePointer
-
- // Update the byte offset
- pStream->Base.File.FilePos = ByteOffset;
+ ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
- // Read the data
- if(dwBytesToWrite != 0)
+#ifdef PLATFORM_WINDOWS
{
- OVERLAPPED Overlapped;
+ // Note: We no longer support Windows 9x.
+ // Thus, we can use the OVERLAPPED structure to specify
+ // file offset to read from file. This allows us to skip
+ // one system call to SetFilePointer
- Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
- Overlapped.Offset = (DWORD)ByteOffset;
- Overlapped.hEvent = NULL;
- if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
- return false;
+ // Update the byte offset
+ pStream->Base.File.FilePos = ByteOffset;
+
+ // Read the data
+ if (dwBytesToWrite != 0)
+ {
+ OVERLAPPED Overlapped;
+
+ Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
+ Overlapped.Offset = (DWORD)ByteOffset;
+ Overlapped.hEvent = NULL;
+ if (!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
+ return false;
+ }
}
- }
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
- {
- ssize_t bytes_written;
-
- // If the byte offset is different from the current file position,
- // we have to update the file position
- if(ByteOffset != pStream->Base.File.FilePos)
{
- if(lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
+ ssize_t bytes_written;
+
+ // If the byte offset is different from the current file position,
+ // we have to update the file position
+ if (ByteOffset != pStream->Base.File.FilePos)
+ {
+ if (lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
+ {
+ SetLastError(errno);
+ return false;
+ }
+ pStream->Base.File.FilePos = ByteOffset;
+ }
+
+ // Perform the read operation
+ bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
+ if (bytes_written == -1)
{
SetLastError(errno);
return false;
}
- pStream->Base.File.FilePos = ByteOffset;
- }
- // Perform the read operation
- bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
- if(bytes_written == -1)
- {
- SetLastError(errno);
- return false;
+ dwBytesWritten = (DWORD)(size_t)bytes_written;
}
-
- dwBytesWritten = (DWORD)(size_t)bytes_written;
- }
#endif
- // Increment the current file position by number of bytes read
- pStream->Base.File.FilePos = ByteOffset + dwBytesWritten;
+ // Increment the current file position by number of bytes read
+ pStream->Base.File.FilePos = ByteOffset + dwBytesWritten;
- // Also modify the file size, if needed
- if(pStream->Base.File.FilePos > pStream->Base.File.FileSize)
- pStream->Base.File.FileSize = pStream->Base.File.FilePos;
+ // Also modify the file size, if needed
+ if(pStream->Base.File.FilePos > pStream->Base.File.FileSize)
+ pStream->Base.File.FileSize = pStream->Base.File.FilePos;
+ }
+ CascUnlock(pStream->Lock);
if(dwBytesWritten != dwBytesToWrite)
SetLastError(ERROR_DISK_FULL);
@@ -383,12 +395,8 @@ static bool BaseFile_GetPos(TFileStream * pStream, ULONGLONG * pByteOffset)
static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream)
{
#ifdef PLATFORM_WINDOWS
- // Delete the original stream file. Don't check the result value,
- // because if the file doesn't exist, it would fail
- DeleteFile(pStream->szFileName);
-
// Rename the new file to the old stream's file
- return (bool)MoveFile(pNewStream->szFileName, pStream->szFileName);
+ return (bool)MoveFileEx(pNewStream->szFileName, pStream->szFileName, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
@@ -405,19 +413,24 @@ static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream)
static void BaseFile_Close(TFileStream * pStream)
{
- if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE)
+ // Synchronize the access to multiple threads
+ CascLock(pStream->Lock);
{
+ if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE)
+ {
#ifdef PLATFORM_WINDOWS
- CloseHandle(pStream->Base.File.hFile);
+ CloseHandle(pStream->Base.File.hFile);
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
- close((intptr_t)pStream->Base.File.hFile);
+ close((intptr_t)pStream->Base.File.hFile);
#endif
- }
+ }
- // Also invalidate the handle
- pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
+ // Also invalidate the handle
+ pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
+ }
+ CascUnlock(pStream->Lock);
}
// Initializes base functions for the disk file
@@ -436,7 +449,7 @@ static void BaseFile_Init(TFileStream * pStream)
//-----------------------------------------------------------------------------
// Local functions - base memory-mapped file support
-static bool BaseMap_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
+static bool BaseMap_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags)
{
#ifdef PLATFORM_WINDOWS
@@ -584,7 +597,7 @@ static void BaseMap_Init(TFileStream * pStream)
//-----------------------------------------------------------------------------
// Local functions - base HTTP file support
-static const TCHAR * BaseHttp_ExtractServerName(const TCHAR * szFileName, TCHAR * szServerName)
+static LPCTSTR BaseHttp_ExtractServerName(LPCTSTR szFileName, LPTSTR szServerName)
{
// Check for HTTP
if(!_tcsnicmp(szFileName, _T("http://"), 7))
@@ -607,7 +620,7 @@ static const TCHAR * BaseHttp_ExtractServerName(const TCHAR * szFileName, TCHAR
return szFileName;
}
-static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
+static bool BaseHttp_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags)
{
#ifdef PLATFORM_WINDOWS
@@ -1018,13 +1031,13 @@ static STREAM_INIT StreamBaseInit[4] =
// The stream structure is created as flat block, variable length
// The file name is placed after the end of the stream structure data
static TFileStream * AllocateFileStream(
- const TCHAR * szFileName,
+ LPCTSTR szFileName,
size_t StreamSize,
DWORD dwStreamFlags)
{
TFileStream * pMaster = NULL;
TFileStream * pStream;
- const TCHAR * szNextFile = szFileName;
+ LPCTSTR szNextFile = szFileName;
size_t FileNameSize;
// Sanity check
@@ -1063,10 +1076,13 @@ static TFileStream * AllocateFileStream(
pStream->dwFlags = dwStreamFlags;
// Initialize the file name
- pStream->szFileName = (TCHAR *)((BYTE *)pStream + StreamSize);
+ pStream->szFileName = (LPTSTR)((BYTE *)pStream + StreamSize);
memcpy(pStream->szFileName, szFileName, FileNameSize);
pStream->szFileName[FileNameSize / sizeof(TCHAR)] = 0;
+ // Initialize the stream lock
+ CascInitLock(pStream->Lock);
+
// Initialize the stream functions
StreamBaseInit[dwStreamFlags & 0x03](pStream);
}
@@ -1367,7 +1383,7 @@ static bool FlatStream_CreateMirror(TBlockStream * pStream)
return true;
}
-static TFileStream * FlatStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
+static TFileStream * FlatStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
{
TBlockStream * pStream;
ULONGLONG ByteOffset = 0;
@@ -1788,7 +1804,7 @@ static bool PartStream_CreateMirror(TBlockStream * pStream)
return true;
}
-static TFileStream * PartStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
+static TFileStream * PartStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
{
TBlockStream * pStream;
@@ -1898,13 +1914,6 @@ static const char * AuthCodeArray[] =
NULL
};
-static DWORD Rol32(DWORD dwValue, DWORD dwRolCount)
-{
- DWORD dwShiftRight = 32 - dwRolCount;
-
- return (dwValue << dwRolCount) | (dwValue >> dwShiftRight);
-}
-
static void CreateKeyFromAuthCode(
LPBYTE pbKeyBuffer,
const char * szAuthCode)
@@ -2105,7 +2114,7 @@ static bool EncrStream_BlockRead(
return true;
}
-static TFileStream * EncrStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
+static TFileStream * EncrStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
{
TEncryptedStream * pStream;
@@ -2232,14 +2241,14 @@ static void Block4Stream_Close(TBlockStream * pStream)
return;
}
-static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
+static TFileStream * Block4Stream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
{
TBaseProviderData * NewBaseArray = NULL;
ULONGLONG RemainderBlock;
ULONGLONG BlockCount;
ULONGLONG FileSize;
TBlockStream * pStream;
- TCHAR * szNameBuff;
+ LPTSTR szNameBuff;
size_t nNameLength;
DWORD dwBaseFiles = 0;
DWORD dwBaseFlags;
@@ -2458,7 +2467,7 @@ TFileStream * FileStream_OpenFile(
*
* \a pStream Pointer to an open stream
*/
-const TCHAR * FileStream_GetFileName(TFileStream * pStream)
+LPCTSTR FileStream_GetFileName(TFileStream * pStream)
{
assert(pStream != NULL);
return pStream->szFileName;
@@ -2754,6 +2763,9 @@ void FileStream_Close(TFileStream * pStream)
else if(pStream->BaseClose != NULL)
pStream->BaseClose(pStream);
+ // Free the stream lock
+ CascFreeLock(pStream->Lock);
+
// Free the stream itself
CASC_FREE(pStream);
}