Current News Archived News Search News Discussion Forum Old Forum Install Programs More Downloads... Troubleshooting Source Code Format Specs. Misc. Information Non-SF Stuff Links Small banner for links to this site: |
diff --git a/SFmpqapi.cpp b/SFmpqapi.cpp
--- a/SFmpqapi.cpp
+++ b/SFmpqapi.cpp
char StormBasePath[MAX_PATH+1];
-#define UNSUPPORTED_COMPRESSION (0xFF ^ (0x40 | 0x80 | 0x01 | 0x02 | 0x08 | 0x10))
-#define UNSUPPORTED_DECOMPRESSION (0xFF ^ (0x40 | 0x80 | 0x01 | 0x02 | 0x08 | 0x10))
-
typedef BOOL (WINAPI* funcSCompCompress)(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwWAVQuality);
typedef BOOL (WINAPI* funcSCompDecompress)(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
funcSCompCompress stormSCompCompress = 0;
@@ -567,7 +564,7 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN
}
DWORD dwMpqStart;
MPQARCHIVE *mpqOpenArc;
- dwMpqStart = mpqArcFile.lpBlockEntry->dwFileOffset;
+ dwMpqStart = mpqArcFile.lpParentArc->dwMPQStart + mpqArcFile.lpBlockEntry->dwFileOffset;
flen = mpqArcFile.lpBlockEntry->dwFullSize;
dwMpqStart = FindMpqHeaderAtLocation(hFile,dwMpqStart,flen);
if (dwMpqStart==0xFFFFFFFF) {
return (DWORD)-1;
}
-DWORD SFMPQAPI WINAPI SFileSetFilePointer(MPQHANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod)
+DWORD SFMPQAPI WINAPI SFileSetFilePointer(MPQHANDLE hFile, LONG lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod)
{
if (!hFile) {
SetLastError(ERROR_INVALID_PARAMETER);
@@ -1139,21 +1136,18 @@ DWORD SFMPQAPI WINAPI SFileSetFilePointer(MPQHANDLE hFile, long lDistanceToMove,
long fsz = mpqOpenFile->lpBlockEntry->dwFullSize;
long cpos = mpqOpenFile->dwFilePointer;
switch (dwMoveMethod) {
- case FILE_BEGIN:
- if (lDistanceToMove<0 || lDistanceToMove>fsz) return (DWORD)-1;
- mpqOpenFile->dwFilePointer = lDistanceToMove;
- break;
case FILE_CURRENT:
- if (lDistanceToMove<cpos || cpos+lDistanceToMove>fsz) return (DWORD)-1;
+ if (cpos + lDistanceToMove < 0 || cpos + lDistanceToMove > fsz) return (DWORD)-1;
mpqOpenFile->dwFilePointer += lDistanceToMove;
break;
case FILE_END:
- if (lDistanceToMove<fsz || lDistanceToMove>0) return (DWORD)-1;
- mpqOpenFile->dwFilePointer = fsz+lDistanceToMove;
+ if (fsz + lDistanceToMove < 0 || lDistanceToMove > 0) return (DWORD)-1;
+ mpqOpenFile->dwFilePointer = fsz + lDistanceToMove;
break;
+ case FILE_BEGIN:
default:
- if (lDistanceToMove<0 || lDistanceToMove>fsz) return (DWORD)-1;
+ if (lDistanceToMove < 0 || lDistanceToMove > fsz) return (DWORD)-1;
mpqOpenFile->dwFilePointer = lDistanceToMove;
}
if (lplDistanceToMoveHigh!=0) *lplDistanceToMoveHigh = 0;
@@ -1179,7 +1173,7 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
}
if (lpOverlapped)
if (lpOverlapped->Internal || lpOverlapped->InternalHigh || lpOverlapped->Offset || lpOverlapped->OffsetHigh || lpOverlapped->hEvent)
- SFileSetFilePointer(hFile,lpOverlapped->Offset,(long *)&lpOverlapped->OffsetHigh,FILE_BEGIN);
+ SFileSetFilePointer(hFile,lpOverlapped->Offset,(LONG *)&lpOverlapped->OffsetHigh,FILE_BEGIN);
if (nNumberOfBytesToRead==0) {
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
if (lpOverlapped) lpOverlapped->InternalHigh = 0;
@@ -1198,6 +1192,8 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
DWORD BlockIndex = mpqOpenFile->lpHashEntry->dwBlockTableIndex;
if (mpqOpenFile->dwFilePointer+nNumberOfBytesToRead>mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize) nNumberOfBytesToRead = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize-mpqOpenFile->dwFilePointer;
DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
+ if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_SINGLEBLOCK)
+ blockSize = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize;
DWORD dwBlockStart = mpqOpenFile->dwFilePointer - (mpqOpenFile->dwFilePointer % blockSize);
DWORD blockNum = dwBlockStart / blockSize;
DWORD nBlocks = (mpqOpenFile->dwFilePointer+nNumberOfBytesToRead) / blockSize;
@@ -1215,12 +1211,18 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
if (lpOverlapped) lpOverlapped->InternalHigh = 0;
return FALSE;
}
- void *blk16Buffer = SFAlloc(blockSize * 16);
- if (!blk16Buffer) {
- SFFree(blkBuffer);
- if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
- if (lpOverlapped) lpOverlapped->InternalHigh = 0;
- return FALSE;
+ DWORD nBufferCount;
+ for (nBufferCount = 1; nBufferCount < nBlocks - blockNum && blockSize * nBufferCount < 65536; nBufferCount *= 2) {}
+ if (nBufferCount > nBlocks - blockNum) nBufferCount = nBlocks - blockNum;
+ void *blkLargeBuffer = NULL;
+ if (nBufferCount > 1) {
+ blkLargeBuffer = SFAlloc(blockSize * nBufferCount);
+ if (!blkLargeBuffer) {
+ SFFree(blkBuffer);
+ if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
+ if (lpOverlapped) lpOverlapped->InternalHigh = 0;
+ return FALSE;
+ }
}
DWORD dwCryptKey = mpqOpenFile->dwCryptKey;
//if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT) dwCryptKey = HashString(mpqOpenFile->lpFileName,HASH_KEY);
@@ -1237,13 +1239,13 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
DWORD *dwBlockPtrTable = (DWORD *)SFAlloc((TotalBlocks+1)*4);
if (!dwBlockPtrTable) {
- SFFree(blk16Buffer);
+ if (blkLargeBuffer) SFFree(blkLargeBuffer);
SFFree(blkBuffer);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
if (lpOverlapped) lpOverlapped->InternalHigh = 0;
return FALSE;
}
- if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2))
+ if (((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) && !(mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_SINGLEBLOCK))
{
SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,FILE_BEGIN);
ReadFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&nBytesRead,0);
@@ -1255,28 +1257,31 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
{
for (i=0;i<TotalBlocks+1;i++) {
if (i<TotalBlocks) dwBlockPtrTable[i] = i * blockSize;
- else dwBlockPtrTable[i] = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize;
+ else dwBlockPtrTable[i] = mpqOpenArc->lpBlockTable[BlockIndex].dwCompressedSize - HeaderLength;
}
}
mpqOpenFile->lpdwBlockOffsets = dwBlockPtrTable;
}
- BYTE *compbuffer = (BYTE *)SFAlloc(blockSize+3);
- if (!compbuffer) {
- SFFree(blk16Buffer);
- SFFree(blkBuffer);
- if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
- if (lpOverlapped) lpOverlapped->InternalHigh = 0;
- return FALSE;
+ BYTE *compbuffer = NULL;
+ if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) {
+ compbuffer = (BYTE *)SFAlloc(blockSize+3);
+ if (!compbuffer) {
+ if (blkLargeBuffer) SFFree(blkLargeBuffer);
+ SFFree(blkBuffer);
+ if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
+ if (lpOverlapped) lpOverlapped->InternalHigh = 0;
+ return FALSE;
+ }
}
DWORD blk=0,blki=0;
for (i=blockNum;i<nBlocks;i++) {
- if (blk==0) {
+ if (blk==0 && blkLargeBuffer) {
SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+mpqOpenFile->lpdwBlockOffsets[i],FILE_BEGIN);
blki=i;
- if (i+16>nBlocks) {
- if (ReadFile(mpqOpenArc->hFile,blk16Buffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
- SFFree(compbuffer);
- SFFree(blk16Buffer);
+ if (i+nBufferCount>nBlocks) {
+ if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
+ if (compbuffer) SFFree(compbuffer);
+ SFFree(blkLargeBuffer);
SFFree(blkBuffer);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
@@ -1285,9 +1290,9 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
}
else {
- if (ReadFile(mpqOpenArc->hFile,blk16Buffer,mpqOpenFile->lpdwBlockOffsets[i+16]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
- SFFree(compbuffer);
- SFFree(blk16Buffer);
+ if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[i+nBufferCount]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
+ if (compbuffer) SFFree(compbuffer);
+ SFFree(blkLargeBuffer);
SFFree(blkBuffer);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
@@ -1295,7 +1300,20 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
}
}
}
- memcpy(blkBuffer,((char *)blk16Buffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]);
+ if (blkLargeBuffer) {
+ memcpy(blkBuffer,((char *)blkLargeBuffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]);
+ }
+ else {
+ SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+mpqOpenFile->lpdwBlockOffsets[i],FILE_BEGIN);
+ blki=i;
+ if (ReadFile(mpqOpenArc->hFile,blkBuffer,mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
+ if (compbuffer) SFFree(compbuffer);
+ SFFree(blkBuffer);
+ if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
+ if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
+ return FALSE;
+ }
+ }
if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT)
{
DecryptData((LPBYTE)blkBuffer,mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i],dwCryptKey+i);
@@ -1367,10 +1385,10 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
nNumberOfBytesToRead-=nNumberOfBytesToRead;
}
}
- blk = (blk+1) % 16;
+ blk = (blk+1) % nBufferCount;
}
- SFFree(compbuffer);
- SFFree(blk16Buffer);
+ if (compbuffer) SFFree(compbuffer);
+ if (blkLargeBuffer) SFFree(blkLargeBuffer);
SFFree(blkBuffer);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
@@ -2166,6 +2184,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileFromBufferEx(MPQHANDLE hMPQ, LPVOID lpBuffer, DWO
if (i==TotalBlocks-1 && (ucfsz % blockSize)!=0) blockSize=ucfsz % blockSize;
DWORD outLength=blockSize;
BYTE *compdata = compbuffer;
+ char *oldoutbuffer = outbuffer;
if (dwFlags & MAFA_COMPRESS)
{
memcpy(compdata,(char *)buffer+CurPos,blockSize);
@@ -2212,6 +2231,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileFromBufferEx(MPQHANDLE hMPQ, LPVOID lpBuffer, DWO
memcpy((char *)newbuffer+LastOffset,outbuffer,outLength);
LastOffset+=outLength;
}
+ outbuffer = oldoutbuffer;
CurPos += blockSize;
}
fsz = LastOffset;
DWORD i;
if (hFile==INVALID_HANDLE_VALUE) {
for (i=0;i<10000;i++) {
- sprintf(lpFileName,"%s.compact.%04ld",mpqOpenArc->lpFileName,i);
+ sprintf(lpFileName,"%s.compact.%04d",mpqOpenArc->lpFileName,i);
hFile = CreateFile(lpFileName,GENERIC_READ|GENERIC_WRITE,0,0,CREATE_NEW,0,0);
if (hFile!=INVALID_HANDLE_VALUE) break;
@@ -3095,16 +3115,19 @@ MPQHANDLE GetFreeHashTableEntry(MPQHANDLE hMPQ, LPCSTR lpFileName, LCID FileLoca
DWORD i=dwTablePos, nFirstFree = 0xFFFFFFFF;
do
{
- if ((mpqOpenArc->lpHashTable[i].dwBlockTableIndex&0xFFFFFFFE)==0xFFFFFFFE && (nFirstFree == 0xFFFFFFFF || mpqOpenArc->lpHashTable[i].dwBlockTableIndex == 0xFFFFFFFF))
+ if ((mpqOpenArc->lpHashTable[i].dwBlockTableIndex&0xFFFFFFFE)==0xFFFFFFFE)
{
- if (mpqOpenArc->lpHashTable[i].dwBlockTableIndex == 0xFFFFFFFF)
+ if (nFirstFree == 0xFFFFFFFF || mpqOpenArc->lpHashTable[i].dwBlockTableIndex == 0xFFFFFFFF)
{
- if (nFirstFree == 0xFFFFFFFF)
- return (MPQHANDLE)&mpqOpenArc->lpHashTable[i];
- else
- return (MPQHANDLE)&mpqOpenArc->lpHashTable[nFirstFree];
+ if (mpqOpenArc->lpHashTable[i].dwBlockTableIndex == 0xFFFFFFFF)
+ {
+ if (nFirstFree == 0xFFFFFFFF)
+ return (MPQHANDLE)&mpqOpenArc->lpHashTable[i];
+ else
+ return (MPQHANDLE)&mpqOpenArc->lpHashTable[nFirstFree];
+ }
+ else nFirstFree = i;
}
- else nFirstFree = i;
}
else if (mpqOpenArc->lpHashTable[i].dwNameHashA==dwNameHashA && mpqOpenArc->lpHashTable[i].dwNameHashB==dwNameHashB && mpqOpenArc->lpHashTable[i].lcLocale==FileLocale)
{
@@ -3117,6 +3140,8 @@ MPQHANDLE GetFreeHashTableEntry(MPQHANDLE hMPQ, LPCSTR lpFileName, LCID FileLoca
}
i = (i + 1) % mpqOpenArc->MpqHeader.dwHashTableSize;
} while (i!=dwTablePos);
+ if (nFirstFree != 0xFFFFFFFF)
+ return (MPQHANDLE)&mpqOpenArc->lpHashTable[nFirstFree];
SetLastError(MPQ_ERROR_HASH_TABLE_FULL);
return 0;
}
@@ -3383,7 +3408,7 @@ DWORD DetectFileSeedEx(MPQARCHIVE * mpqOpenArc, HASHTABLEENTRY * lpHashEntry, LP
else {
HANDLE hlFile,hMPQ=(HANDLE)mpqOpenArc;
DWORD fsz;
- char *listbuffer;
+ char *listbuffer = 0;
LCID lcOldLocale = LocaleID;
for (DWORD lcn=0;lcn<nLocales;lcn++) {
LocaleID = availLocales[lcn];
@@ -3406,7 +3431,7 @@ DWORD DetectFileSeedEx(MPQARCHIVE * mpqOpenArc, HASHTABLEENTRY * lpHashEntry, LP
}
SFileCloseFile(hlFile);
if (listbuffer!=0) {
- char *listline;
+ char *listline = 0;
for (listline=listbuffer;listline!=0;listline=nextline(listline)) {
if (listline[0]==0) break;
DWORD lnlen=strlnlen(listline);
|