aboutsummaryrefslogtreecommitdiff
path: root/src/SFileReadFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFileReadFile.cpp')
-rw-r--r--src/SFileReadFile.cpp98
1 files changed, 51 insertions, 47 deletions
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp
index 30dc587..485b361 100644
--- a/src/SFileReadFile.cpp
+++ b/src/SFileReadFile.cpp
@@ -801,9 +801,10 @@ DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh)
DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHigh, DWORD dwMoveMethod)
{
TMPQFile * hf = (TMPQFile *)hFile;
- ULONGLONG FilePosition;
- ULONGLONG MoveOffset;
- DWORD dwFilePosHi;
+ ULONGLONG OldPosition;
+ ULONGLONG NewPosition;
+ ULONGLONG FileSize;
+ ULONGLONG DeltaPos;
// If the hFile is not a valid file handle, return an error.
if(!IsValidFileHandle(hFile))
@@ -812,33 +813,47 @@ DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHi
return SFILE_INVALID_POS;
}
+ // Retrieve the file size for handling the limits
+ if(hf->pStream != NULL)
+ {
+ FileStream_GetSize(hf->pStream, &FileSize);
+ }
+ else
+ {
+ FileSize = SFileGetFileSize(hFile, NULL);
+ }
+
+ // Handle the NULL and non-NULL values of plFilePosHigh
+ // Non-NULL: The DeltaPos is combined from lFilePos and *lpFilePosHigh
+ // NULL: The DeltaPos is sign-extended value of lFilePos
+ DeltaPos = (plFilePosHigh != NULL) ? MAKE_OFFSET64(plFilePosHigh[0], lFilePos) : (ULONGLONG)(LONGLONG)lFilePos;
+
// Get the relative point where to move from
switch(dwMoveMethod)
{
case FILE_BEGIN:
- FilePosition = 0;
+
+ // Move relative to the file begin.
+ OldPosition = 0;
break;
case FILE_CURRENT:
+
+ // Retrieve the current file position
if(hf->pStream != NULL)
{
- FileStream_GetPos(hf->pStream, &FilePosition);
+ FileStream_GetPos(hf->pStream, &OldPosition);
}
else
{
- FilePosition = hf->dwFilePos;
+ OldPosition = hf->dwFilePos;
}
break;
case FILE_END:
- if(hf->pStream != NULL)
- {
- FileStream_GetSize(hf->pStream, &FilePosition);
- }
- else
- {
- FilePosition = SFileGetFileSize(hFile, NULL);
- }
+
+ // Move relative to the end of the file
+ OldPosition = FileSize;
break;
default:
@@ -846,47 +861,36 @@ DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHi
return SFILE_INVALID_POS;
}
- // Now get the move offset. Note that both values form
- // a signed 64-bit value (a file pointer can be moved backwards)
- if(plFilePosHigh != NULL)
- dwFilePosHi = *plFilePosHigh;
- else
- dwFilePosHi = (lFilePos & 0x80000000) ? 0xFFFFFFFF : 0;
- MoveOffset = MAKE_OFFSET64(dwFilePosHi, lFilePos);
+ // Calculate the new position
+ NewPosition = OldPosition + DeltaPos;
- // Now calculate the new file pointer
- // Do not allow the file pointer to overflow
- FilePosition = ((FilePosition + MoveOffset) >= FilePosition) ? (FilePosition + MoveOffset) : 0;
+ // If moving backward, don't allow the new position go negative
+ if((LONGLONG)DeltaPos < 0)
+ {
+ if(NewPosition > FileSize)
+ NewPosition = 0;
+ }
+
+ // If moving forward, don't allow the new position go past the end of the file
+ else
+ {
+ if(NewPosition > FileSize)
+ NewPosition = FileSize;
+ }
// Now apply the file pointer to the file
if(hf->pStream != NULL)
{
- // Apply the new file position
- if(!FileStream_Read(hf->pStream, &FilePosition, NULL, 0))
+ if(!FileStream_Read(hf->pStream, &NewPosition, NULL, 0))
return SFILE_INVALID_POS;
-
- // Return the new file position
- if(plFilePosHigh != NULL)
- *plFilePosHigh = (LONG)(FilePosition >> 32);
- return (DWORD)FilePosition;
}
else
{
- // Files in MPQ can't be bigger than 4 GB.
- // We don't allow to go past 4 GB
- if(FilePosition >> 32)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return SFILE_INVALID_POS;
- }
-
- // Change the file position
- hf->dwFilePos = (DWORD)FilePosition;
-
- // Return the new file position
- if(plFilePosHigh != NULL)
- *plFilePosHigh = 0;
- return (DWORD)FilePosition;
+ hf->dwFilePos = (DWORD)NewPosition;
}
-}
+ // Return the new file position
+ if(plFilePosHigh != NULL)
+ *plFilePosHigh = (LONG)(NewPosition >> 32);
+ return (DWORD)NewPosition;
+}