diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-02-08 20:57:52 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-02-08 20:57:52 +0100 |
commit | 43642630c7cc8a96009a6cb7edbaa895c41f63c0 (patch) | |
tree | 635226da8506d47a04c610f76272356b57eb16de /dep/CascLib/src/CascReadFile.cpp | |
parent | f5ccb7b47480cd9064423da8fe2878992175d8b4 (diff) |
Dep/CascLib: Update to ladislav-zezula/CascLib@919a2d670cb749c501ee15887a88e9b9a538961b
Diffstat (limited to 'dep/CascLib/src/CascReadFile.cpp')
-rw-r--r-- | dep/CascLib/src/CascReadFile.cpp | 142 |
1 files changed, 106 insertions, 36 deletions
diff --git a/dep/CascLib/src/CascReadFile.cpp b/dep/CascLib/src/CascReadFile.cpp index 83fdd0d2096..72eb2c4b647 100644 --- a/dep/CascLib/src/CascReadFile.cpp +++ b/dep/CascLib/src/CascReadFile.cpp @@ -98,9 +98,10 @@ static int LoadFileFrames(TCascFile * hf) else nError = GetLastError(); - // Note: Do not take the FileSize from the sum of frames. - // This value is invalid when loading the ENCODING file. -// hf->FileSize = FileSize; + // Note: on ENCODING file, this value is almost always bigger + // then the real size of ENCODING. We handle this problem + // by calculating size of the ENCODIG file from its header. + hf->FileSize = FileSize; #ifdef CASCLIB_TEST hf->FileSize_FrameSum = FileSize; @@ -264,6 +265,85 @@ static PCASC_FILE_FRAME FindFileFrame(TCascFile * hf, DWORD FilePointer) return NULL; } +static int ProcessFileFrame( + LPBYTE pbOutBuffer, + DWORD cbOutBuffer, + LPBYTE pbInBuffer, + DWORD cbInBuffer, + DWORD dwFrameIndex) +{ + LPBYTE pbTempBuffer; + LPBYTE pbWorkBuffer; + DWORD cbTempBuffer = CASCLIB_MAX(cbInBuffer, cbOutBuffer); + DWORD cbWorkBuffer = cbOutBuffer + 1; + DWORD dwStepCount = 0; + bool bWorkComplete = false; + int nError = ERROR_SUCCESS; + + // Allocate the temporary buffer that will serve as output + pbWorkBuffer = pbTempBuffer = CASC_ALLOC(BYTE, cbTempBuffer); + if(pbWorkBuffer == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + // Perform the loop + for(;;) + { + // Set the output buffer. + // Even operations: extract to temporary buffer + // Odd operations: extract to output buffer + pbWorkBuffer = (dwStepCount & 0x01) ? pbOutBuffer : pbTempBuffer; + cbWorkBuffer = (dwStepCount & 0x01) ? cbOutBuffer : cbTempBuffer; + + // Perform the operation specific to the operation ID + switch(pbInBuffer[0]) + { + case 'E': // Encrypted files + nError = CascDecrypt(pbWorkBuffer, &cbWorkBuffer, pbInBuffer + 1, cbInBuffer - 1, dwFrameIndex); + bWorkComplete = (nError != ERROR_SUCCESS); + break; + + case 'Z': // ZLIB compressed files + nError = CascDecompress(pbWorkBuffer, &cbWorkBuffer, pbInBuffer + 1, cbInBuffer - 1); + bWorkComplete = true; + break; + + case 'N': // Normal stored files + nError = CascDirectCopy(pbWorkBuffer, &cbWorkBuffer, pbInBuffer + 1, cbInBuffer - 1); + bWorkComplete = true; + break; + + case 'F': // Recursive frames - not supported + default: // Unrecognized - if we unpacked something, we consider it done + nError = ERROR_NOT_SUPPORTED; + bWorkComplete = true; + assert(false); + break; + } + + // Are we done? + if(bWorkComplete) + break; + + // Set the input buffer to the work buffer + pbInBuffer = pbWorkBuffer; + cbInBuffer = cbWorkBuffer; + dwStepCount++; + } + + // If the data are currently in the temporary buffer, + // we need to copy them to output buffer + if(nError == ERROR_SUCCESS && pbWorkBuffer != pbOutBuffer) + { + if(cbWorkBuffer != cbOutBuffer) + nError = ERROR_INSUFFICIENT_BUFFER; + memcpy(pbOutBuffer, pbWorkBuffer, cbOutBuffer); + } + + // Free the temporary buffer + CASC_FREE(pbTempBuffer); + return nError; +} + //----------------------------------------------------------------------------- // Public functions @@ -299,7 +379,7 @@ DWORD WINAPI CascGetFileSize(HANDLE hFile, PDWORD pdwFileSizeHigh) } // Make sure that the file header area is loaded - nError = EnsureHeaderAreaIsLoaded(hf); + nError = EnsureFrameHeadersLoaded(hf); if(nError != ERROR_SUCCESS) { SetLastError(nError); @@ -387,7 +467,6 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW DWORD dwFilePointer = 0; DWORD dwEndPointer = 0; DWORD dwFrameSize; - DWORD cbOutBuffer; bool bReadResult; int nError = ERROR_SUCCESS; @@ -423,7 +502,7 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW { // Get the frame pFrame = FindFileFrame(hf, hf->FilePointer); - if(pFrame == NULL) + if(pFrame == NULL || pFrame->CompressedSize < 1) nError = ERROR_FILE_CORRUPT; } @@ -439,7 +518,7 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW // Perform block read from each file frame while(dwFilePointer < dwEndPointer) { - LPBYTE pbRawData = NULL; + LPBYTE pbFrameData = NULL; DWORD dwFrameStart = pFrame->FrameFileOffset; DWORD dwFrameEnd = pFrame->FrameFileOffset + pFrame->FrameSize; @@ -457,8 +536,8 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW } // We also need to allocate buffer for the raw data - pbRawData = CASC_ALLOC(BYTE, pFrame->CompressedSize); - if(pbRawData == NULL) + pbFrameData = CASC_ALLOC(BYTE, pFrame->CompressedSize); + if(pbFrameData == NULL) { nError = ERROR_NOT_ENOUGH_MEMORY; break; @@ -466,7 +545,7 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW // Load the raw file data to memory FileOffset = pFrame->FrameArchiveOffset; - bReadResult = FileStream_Read(hf->pStream, &FileOffset, pbRawData, pFrame->CompressedSize); + bReadResult = FileStream_Read(hf->pStream, &FileOffset, pbFrameData, pFrame->CompressedSize); // Note: The raw file data size could be less than expected // Happened in WoW build 19342 with the ROOT file. MD5 in the frame header @@ -484,43 +563,34 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW // If the frame offset is before EOF and frame end is beyond EOF, correct it if(FileOffset < StreamSize && dwFrameSize < pFrame->CompressedSize) { - memset(pbRawData + dwFrameSize, 0, (pFrame->CompressedSize - dwFrameSize)); + memset(pbFrameData + dwFrameSize, 0, (pFrame->CompressedSize - dwFrameSize)); bReadResult = true; } } // If the read result failed, we cannot finish reading it - if(bReadResult == false) - { - CASC_FREE(pbRawData); - nError = GetLastError(); - break; - } - - // Verify the block MD5 - if(!VerifyDataBlockHash(pbRawData, pFrame->CompressedSize, pFrame->md5)) + if(bReadResult && VerifyDataBlockHash(pbFrameData, pFrame->CompressedSize, pFrame->md5)) { - CASC_FREE(pbRawData); - nError = ERROR_FILE_CORRUPT; - break; + // Convert the source frame to the file cache + nError = ProcessFileFrame(hf->pbFileCache, + pFrame->FrameSize, + pbFrameData, + pFrame->CompressedSize, + (DWORD)(pFrame - hf->pFrames)); + if(nError == ERROR_SUCCESS) + { + // Set the start and end of the cache + hf->CacheStart = dwFrameStart; + hf->CacheEnd = dwFrameEnd; + } } - - // Decompress the file frame - cbOutBuffer = pFrame->FrameSize; - nError = CascDecompress(hf->pbFileCache, &cbOutBuffer, pbRawData, pFrame->CompressedSize); - if(nError != ERROR_SUCCESS || cbOutBuffer != pFrame->FrameSize) + else { - CASC_FREE(pbRawData); nError = ERROR_FILE_CORRUPT; - break; } - // Set the start and end of the cache - hf->CacheStart = dwFrameStart; - hf->CacheEnd = dwFrameEnd; - - // Free the decompress buffer, if needed - CASC_FREE(pbRawData); + // Free the raw frame data + CASC_FREE(pbFrameData); } // Copy the decompressed data |