X-Git-Url: https://sfsrealm.hopto.org/projects/gitweb.cgi?a=blobdiff_plain;f=SFmpqapi.cpp;h=faf2701904a1232e928bb361d115def454eb3811;hb=a9570bb3ec72a45f97b433a43807de356120625a;hp=a0d5a13991c63c51249f1cdce8d5c5afd5eba114;hpb=7214af3eb69acdaef221c1846157ed07438bd0c1;p=SFmpqapi.git diff --git a/SFmpqapi.cpp b/SFmpqapi.cpp index a0d5a13..faf2701 100644 --- a/SFmpqapi.cpp +++ b/SFmpqapi.cpp @@ -101,9 +101,6 @@ MPQFILE * FirstLastFile[2] = {0,0}; 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) { @@ -1073,7 +1070,7 @@ DWORD SFMPQAPI WINAPI SFileGetFileInfo(MPQHANDLE hFile, DWORD dwInfoType) case SFILE_INFO_PRIORITY: return mpqOpenArc->dwPriority; case SFILE_INFO_HASH_INDEX: - return ((INT_PTR)mpqOpenFile->lpHashEntry-(INT_PTR)mpqOpenArc->lpHashTable)/sizeof(HASHTABLEENTRY); + return ((UIntPtr)mpqOpenFile->lpHashEntry-(UIntPtr)mpqOpenArc->lpHashTable)/sizeof(HASHTABLEENTRY); case SFILE_INFO_BLOCK_INDEX: return mpqOpenFile->lpHashEntry->dwBlockTableIndex; default: @@ -1127,7 +1124,7 @@ DWORD SFMPQAPI WINAPI SFileGetFileInfo(MPQHANDLE hFile, DWORD dwInfoType) 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); @@ -1179,7 +1176,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 +1195,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 +1214,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 +1242,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 +1260,31 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber { for (i=0;ilpBlockTable[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;ihFile,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 +1293,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 +1303,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 +1388,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 +2187,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 +2234,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileFromBufferEx(MPQHANDLE hMPQ, LPVOID lpBuffer, DWO memcpy((char *)newbuffer+LastOffset,outbuffer,outLength); LastOffset+=outLength; } + outbuffer = oldoutbuffer; CurPos += blockSize; } fsz = LastOffset; @@ -2555,7 +2578,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) 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; @@ -3383,7 +3406,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