JNIH_EXCEPTION_TRAP_BEGIN() { JByteArray jInBuffer(env, inBuffer); JByteArray tempBuffer(env, inBufferLength); jsize outBufferLength = inBufferLength; jboolean result = SCompCompress( tempBuffer.getData(), reinterpret_cast<int*>(&outBufferLength), (jInBuffer.getData() + inBufferOffset), inBufferLength, compressionMask, 0, compressionLevel ); if (!result) { ErrorCodeToException(env, GetLastError()); } else { JByteArray outBuffer(env, outBufferLength); memcpy(outBuffer.getData(), tempBuffer.getData(), outBufferLength); return outBuffer.getArray(); } } JNIH_EXCEPTION_TRAP_END
static int WriteDataToMpqFile( TMPQArchive * ha, TMPQFile * hf, LPBYTE pbFileData, DWORD dwDataSize, DWORD dwCompression) { TFileEntry * pFileEntry = hf->pFileEntry; ULONGLONG ByteOffset; LPBYTE pbCompressed = NULL; // Compressed (target) data LPBYTE pbToWrite = NULL; // Data to write to the file int nCompressionLevel = -1; // ADPCM compression level (only used for wave files) int nError = ERROR_SUCCESS; // If the caller wants ADPCM compression, we will set wave compression level to 4, // which corresponds to medium quality if(dwCompression & LOSSY_COMPRESSION_MASK) nCompressionLevel = 4; // Make sure that the caller won't overrun the previously initiated file size assert(hf->dwFilePos + dwDataSize <= pFileEntry->dwFileSize); assert(hf->dwSectorCount != 0); assert(hf->pbFileSector != NULL); if((hf->dwFilePos + dwDataSize) > pFileEntry->dwFileSize) return ERROR_DISK_FULL; pbToWrite = hf->pbFileSector; // Now write all data to the file sector buffer if(nError == ERROR_SUCCESS) { DWORD dwBytesInSector = hf->dwFilePos % hf->dwSectorSize; DWORD dwSectorIndex = hf->dwFilePos / hf->dwSectorSize; DWORD dwBytesToCopy; // Process all data. while(dwDataSize != 0) { dwBytesToCopy = dwDataSize; // Check for sector overflow if(dwBytesToCopy > (hf->dwSectorSize - dwBytesInSector)) dwBytesToCopy = (hf->dwSectorSize - dwBytesInSector); // Copy the data to the file sector memcpy(hf->pbFileSector + dwBytesInSector, pbFileData, dwBytesToCopy); dwBytesInSector += dwBytesToCopy; pbFileData += dwBytesToCopy; dwDataSize -= dwBytesToCopy; // Update the file position hf->dwFilePos += dwBytesToCopy; // If the current sector is full, or if the file is already full, // then write the data to the MPQ if(dwBytesInSector >= hf->dwSectorSize || hf->dwFilePos >= pFileEntry->dwFileSize) { // Set the position in the file ByteOffset = hf->RawFilePos + pFileEntry->dwCmpSize; // Update CRC32 and MD5 of the file md5_process((hash_state *)hf->hctx, hf->pbFileSector, dwBytesInSector); hf->dwCrc32 = crc32(hf->dwCrc32, hf->pbFileSector, dwBytesInSector); // Compress the file sector, if needed if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED) { int nOutBuffer = (int)dwBytesInSector; int nInBuffer = (int)dwBytesInSector; // If the file is compressed, allocate buffer for the compressed data. // Note that we allocate buffer that is a bit longer than sector size, // for case if the compression method performs a buffer overrun if(pbCompressed == NULL) { pbToWrite = pbCompressed = STORM_ALLOC(BYTE, hf->dwSectorSize + 0x100); if(pbCompressed == NULL) { nError = ERROR_NOT_ENOUGH_MEMORY; break; } } // // Note that both SCompImplode and SCompCompress give original buffer, // if they are unable to comperss the data. // if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE) { SCompImplode((char *)pbCompressed, &nOutBuffer, (char *)hf->pbFileSector, nInBuffer); } if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS) { SCompCompress((char *)pbCompressed, &nOutBuffer, (char *)hf->pbFileSector, nInBuffer, (unsigned)dwCompression, 0, nCompressionLevel); } // Update sector positions dwBytesInSector = nOutBuffer; if(hf->SectorOffsets != NULL) hf->SectorOffsets[dwSectorIndex+1] = hf->SectorOffsets[dwSectorIndex] + dwBytesInSector; // We have to calculate sector CRC, if enabled if(hf->SectorChksums != NULL) hf->SectorChksums[dwSectorIndex] = adler32(0, pbCompressed, nOutBuffer); } // Encrypt the sector, if necessary if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) { BSWAP_ARRAY32_UNSIGNED(pbToWrite, dwBytesInSector); EncryptMpqBlock(pbToWrite, dwBytesInSector, hf->dwFileKey + dwSectorIndex); BSWAP_ARRAY32_UNSIGNED(pbToWrite, dwBytesInSector); } // Write the file sector if(!FileStream_Write(ha->pStream, &ByteOffset, pbToWrite, dwBytesInSector)) { nError = GetLastError(); break; } // Call the compact callback, if any if(AddFileCB != NULL) AddFileCB(pvUserData, hf->dwFilePos, hf->dwDataSize, false); // Update the compressed file size pFileEntry->dwCmpSize += dwBytesInSector; dwBytesInSector = 0; dwSectorIndex++; } } } // Cleanup if(pbCompressed != NULL) STORM_FREE(pbCompressed); return nError; }