void BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { if(td && ptr && !contents_only) { FREEMEM(ptr); } }
static int ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwToRead, LPDWORD pdwBytesRead) { ULONGLONG RawFilePos = hf->RawFilePos; TMPQArchive * ha = hf->ha; TFileEntry * pFileEntry = hf->pFileEntry; LPBYTE pbCompressed = NULL; LPBYTE pbRawData = NULL; int nError; // If the file buffer is not allocated yet, do it. if (hf->pbFileSector == NULL) { nError = AllocateSectorBuffer(hf); if (nError != ERROR_SUCCESS) return nError; pbRawData = hf->pbFileSector; } // If the file is a patch file, adjust raw data offset if (hf->PatchInfo != NULL) RawFilePos += hf->PatchInfo->dwLength; // If the file buffer is not loaded yet, do it if (hf->dwSectorOffs != 0) { // // In "wow-update-12694.MPQ" from Wow-Cataclysm BETA: // // File CmpSize FileSize Data // -------------------------------------- ------- -------- --------------- // esES\DBFilesClient\LightSkyBox.dbc 0xBE 0xBC Is compressed // deDE\DBFilesClient\MountCapability.dbc 0x93 0x77 Is uncompressed // // Now tell me how to deal with this mess. Apparently // someone made a mistake at Blizzard ... // if (hf->PatchInfo != NULL) { // Allocate space for pbCompressed = ALLOCMEM(BYTE, pFileEntry->dwCmpSize); if (pbCompressed == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Read the entire file if (!FileStream_Read(ha->pStream, &RawFilePos, pbCompressed, pFileEntry->dwCmpSize)) { FREEMEM(pbCompressed); return GetLastError(); } // We assume that patch files are not encrypted assert((pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) == 0); assert((pFileEntry->dwFlags & MPQ_FILE_IMPLODE) == 0); // Check the 'PTCH' signature to find out if it's compressed or not if (pbCompressed[0] != 'P' || pbCompressed[1] != 'T' || pbCompressed[2] != 'C' || pbCompressed[3] != 'H') { int cbOutBuffer = (int)hf->dwDataSize; int nResult = SCompDecompress((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbCompressed, (int)pFileEntry->dwCmpSize); if (nResult == 0) { FREEMEM(pbCompressed); return ERROR_FILE_CORRUPT; } } else { memcpy(hf->pbFileSector, pbCompressed, hf->dwDataSize); } // Free the decompression buffer. FREEMEM(pbCompressed); } else { // If the file is compressed, we have to allocate buffer for compressed data if (pFileEntry->dwCmpSize < hf->dwDataSize) { pbCompressed = ALLOCMEM(BYTE, pFileEntry->dwCmpSize); if (pbCompressed == NULL) return ERROR_NOT_ENOUGH_MEMORY; pbRawData = pbCompressed; } // Read the entire file if (!FileStream_Read(ha->pStream, &RawFilePos, pbRawData, pFileEntry->dwCmpSize)) { FREEMEM(pbCompressed); return GetLastError(); } // If the file is encrypted, we have to decrypt the data first if (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) { BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize); DecryptMpqBlock(pbRawData, pFileEntry->dwCmpSize, hf->dwFileKey); BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize); } // If the file is compressed, we have to decompress it now if (pFileEntry->dwCmpSize < hf->dwDataSize) { int cbOutBuffer = (int)hf->dwDataSize; int nResult = 0; // Note: Single unit files compressed with IMPLODE are not supported by Blizzard if (pFileEntry->dwFlags & MPQ_FILE_IMPLODE) nResult = SCompExplode((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, (int)pFileEntry->dwCmpSize); if (pFileEntry->dwFlags & MPQ_FILE_COMPRESS) nResult = SCompDecompress((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, (int)pFileEntry->dwCmpSize); // Free the decompression buffer. FREEMEM(pbCompressed); if (nResult == 0) return ERROR_FILE_CORRUPT; } } // The file sector is now properly loaded hf->dwSectorOffs = 0; } // At this moment, we have the file loaded into the file buffer. // Copy as much as the caller wants if (hf->dwSectorOffs == 0) { // File position is greater or equal to file size ? if (hf->dwFilePos >= hf->dwDataSize) { *pdwBytesRead = 0; return ERROR_SUCCESS; } // If not enough bytes remaining in the file, cut them if ((hf->dwDataSize - hf->dwFilePos) < dwToRead) dwToRead = (hf->dwDataSize - hf->dwFilePos); // Copy the bytes memcpy(pvBuffer, hf->pbFileSector + hf->dwFilePos, dwToRead); hf->dwFilePos += dwToRead; // Give the number of bytes read *pdwBytesRead = dwToRead; return ERROR_SUCCESS; } // An error, sorry return ERROR_CAN_NOT_COMPLETE; }
void CFCPerlPod_destroy(CFCPerlPod *self) { FREEMEM(self->synopsis); FREEMEM(self->description); for (size_t i = 0; i < self->num_methods; i++) { FREEMEM(self->methods[i].alias); FREEMEM(self->methods[i].pod); FREEMEM(self->methods[i].func); FREEMEM(self->methods[i].sample); } FREEMEM(self->methods); for (size_t i = 0; i < self->num_constructors; i++) { FREEMEM(self->constructors[i].alias); FREEMEM(self->constructors[i].pod); FREEMEM(self->constructors[i].func); FREEMEM(self->constructors[i].sample); } FREEMEM(self->constructors); CFCBase_destroy((CFCBase*)self); }
bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile, bool /* bReserved */) { LARGE_INTEGER ByteOffset; LARGE_INTEGER ByteCount; TFileStream * pTempStream = NULL; TMPQArchive * ha = (TMPQArchive *)hMpq; DWORD * pFileKeys = NULL; char szTempFile[MAX_PATH] = ""; char * szTemp = NULL; int nError = ERROR_SUCCESS; // Test the valid parameters if(!IsValidMpqHandle(ha)) nError = ERROR_INVALID_HANDLE; if(ha->dwFlags & MPQ_FLAG_READ_ONLY) nError = ERROR_ACCESS_DENIED; // Create the table with file keys if(nError == ERROR_SUCCESS) { if((pFileKeys = ALLOCMEM(DWORD, ha->pHeader->dwBlockTableSize)) != NULL) memset(pFileKeys, 0, sizeof(DWORD) * ha->pHeader->dwBlockTableSize); else nError = ERROR_NOT_ENOUGH_MEMORY; } // First of all, we have to check of we are able to decrypt all files. // If not, sorry, but the archive cannot be compacted. if(nError == ERROR_SUCCESS) { // Initialize the progress variables for compact callback FileStream_GetSize(ha->pStream, &CompactTotalBytes); CompactBytesProcessed.QuadPart = 0; nError = CheckIfAllFilesKnown(ha, szListFile, pFileKeys); } // Get the temporary file name and create it if(nError == ERROR_SUCCESS) { strcpy(szTempFile, ha->pStream->szFileName); if((szTemp = strrchr(szTempFile, '.')) != NULL) strcpy(szTemp + 1, "mp_"); else strcat(szTempFile, "_"); pTempStream = FileStream_CreateFile(szTempFile); if(pTempStream == NULL) nError = GetLastError(); } // Write the data before MPQ user data (if any) if(nError == ERROR_SUCCESS && ha->UserDataPos.QuadPart != 0) { // Inform the application about the progress if(CompactCB != NULL) CompactCB(pvUserData, CCB_COPYING_NON_MPQ_DATA, &CompactBytesProcessed, &CompactTotalBytes); ByteOffset.QuadPart = 0; ByteCount.QuadPart = ha->UserDataPos.QuadPart; nError = CopyNonMpqData(ha->pStream, pTempStream, ByteOffset, ByteCount); } // Write the MPQ user data (if any) if(nError == ERROR_SUCCESS && ha->MpqPos.QuadPart > ha->UserDataPos.QuadPart) { // At this point, we assume that the user data size is equal // to pUserData->dwHeaderOffs. // If this assumption doesn't work, then we have an unknown version of MPQ ByteOffset.QuadPart = ha->UserDataPos.QuadPart; ByteCount.QuadPart = ha->MpqPos.QuadPart - ha->UserDataPos.QuadPart; assert(ha->pUserData != NULL); assert(ha->pUserData->dwHeaderOffs == ByteCount.LowPart); nError = CopyNonMpqData(ha->pStream, pTempStream, ByteOffset, ByteCount); } // Write the MPQ header if(nError == ERROR_SUCCESS) { // Remember the header size before swapping DWORD dwBytesToWrite = ha->pHeader->dwHeaderSize; BSWAP_TMPQHEADER(ha->pHeader); if(!FileStream_Write(pTempStream, NULL, ha->pHeader, dwBytesToWrite)) nError = GetLastError(); BSWAP_TMPQHEADER(ha->pHeader); // Update the progress CompactBytesProcessed.QuadPart += ha->pHeader->dwHeaderSize; ha->dwFlags &= ~MPQ_FLAG_NO_HEADER; } // Now copy all files if(nError == ERROR_SUCCESS) { nError = CopyMpqFiles(ha, pFileKeys, pTempStream); } // If succeeded, switch the streams if(nError == ERROR_SUCCESS) { if(FileStream_MoveFile(ha->pStream, pTempStream)) pTempStream = NULL; else nError = ERROR_CAN_NOT_COMPLETE; } // If all succeeded, save the MPQ tables if(nError == ERROR_SUCCESS) { // // Note: We don't recalculate position of the MPQ tables at this point. // SaveMPQTables does it automatically. // nError = SaveMPQTables(ha); if(nError == ERROR_SUCCESS && CompactCB != NULL) { CompactBytesProcessed.QuadPart += (ha->pHeader->dwHashTableSize * sizeof(TMPQHash)); CompactBytesProcessed.QuadPart += (ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock)); CompactCB(pvUserData, CCB_CLOSING_ARCHIVE, &CompactBytesProcessed, &CompactTotalBytes); } } // Invalidate the compact callback pvUserData = NULL; CompactCB = NULL; // Cleanup and return if(pTempStream != NULL) FileStream_Close(pTempStream); if(pFileKeys != NULL) FREEMEM(pFileKeys); if(nError != ERROR_SUCCESS) SetLastError(nError); return (nError == ERROR_SUCCESS); }
UDWORD BMGlobalEnd(void) { // Delete debug if (BMDebugEnd () != BMTRUE) KMLWarning ("Probleme dans la liberation de BMDebug"); // Delete User Config if (BMDeleteUserConfig () != BMTRUE) KMLWarning ("Probleme dans la liberation de Local config"); // Bombs if (BMBombsEnd () != BMTRUE) KMLWarning ("Probleme dans la liberation de BMBombs"); // Bonus if (BMBonusEnd () != BMTRUE) KMLWarning ("Probleme dans la liberation de BMBonus"); // Player if (BMPlayerEnd () != BMTRUE) KMLWarning ("Probleme dans la liberation de BMPlayer"); //Entity if (BMEntityEnd () != BMTRUE) KMLWarning ("Probleme dans la liberation de BMEntity"); //Sprite if (BMSpriteEnd () != BMTRUE) KMLWarning ("Probleme dans la liberation de BMSprite"); //Delete Map if (BMMapEnd () != BMTRUE) KMLWarning ("Probleme dans la liberation de BMMap"); // Delete Animation if (BMAnimEnd() != BMTRUE) KMLWarning ("Probleme dans la liberation de BMAnim"); // Delete UI BMUIFontStop(); //Delete Console BMConsoleEnd(); //Delete OS BMMenuEnd (); BMUIOSEnd (); //Delete Image BMImageEnd (); //Always after the tools !!! because we must call the callback before unload dll // Delete players BMClCleanUpPlayers(); // Delete Server BMSvCleanUp(); // Delete KML KMLQuitLib(); KMLControlQuitLib(); SDWORD value; value = FREEMEM(); if (value != 0) { KMLWarning ("Memoire non libérée %d", value); } // EndTimer BMTimerEnd(); if (BMListMemory != 0) { KMLWarning ("BMList non libere %d", BMListMemory); } if (BMSpriteMemory != 0) { KMLWarning ("BMSprite non libere %d", BMSpriteMemory); } if (BMAnimMemory != 0) { KMLWarning ("BMAnim non libere %d", BMAnimMemory); } if (BMMapMemory != 0) { KMLWarning ("BMMap non libere %d", BMMapMemory); } if (BMPlayerMemory != 0) { KMLWarning ("BMPlayer non libere %d", BMPlayerMemory); } if (BMWin32KeysMemory != 0) { KMLWarning ("BMWin32Keys non libere %d", BMWin32KeysMemory); } if (BMServerMemory != 0) { KMLWarning ("BMServer non libere %d", BMServerMemory); } if (BMClientServerMemory != 0) { KMLWarning ("BMClientServer non libere %d", BMClientServerMemory); } if (GetKMLLightMemory() != 0) { KMLWarning ("BMKMLLight non libere %d", GetKMLLightMemory()); } if (BMOSMemory != 0) { KMLWarning ("BMOS non libere %d", BMOSMemory); } if (BMConsoleMemory != 0) { KMLWarning ("CONSOLE non libere %d", BMConsoleMemory); } if (BMEntityMemory != 0) { KMLWarning ("Entity non libere %d", BMEntityMemory); } if (BMBonusMemory != 0) { KMLWarning ("Bonus non libere %d", BMBonusMemory); } if (BMBombsMemory != 0) { KMLWarning ("Bombs non libere %d", BMBombsMemory); } if (BMImageMemory != 0) { KMLWarning ("Image non libere %d", BMImageMemory); } return 1; }
/* * Fetch the next tuple in either forward or back direction. * Returns NULL if no more tuples. If should_free is set, the * caller must pfree the returned tuple when done with it. * * Backward scan is only allowed if randomAccess was set true or * EXEC_FLAG_BACKWARD was specified to tuplestore_set_eflags(). */ static GenericTuple tuplestore_gettuple(Tuplestorestate *state, bool forward, bool *should_free) { TSReadPointer *readptr = &state->readptrs[state->activeptr]; unsigned int tuplen; void *tup; Assert(forward || (readptr->eflags & EXEC_FLAG_BACKWARD)); switch (state->status) { case TSS_INMEM: *should_free = false; if (forward) { if (readptr->eof_reached) return NULL; if (readptr->current < state->memtupcount) { /* We have another tuple, so return it */ return state->memtuples[readptr->current++]; } readptr->eof_reached = true; return NULL; } else { /* * if all tuples are fetched already then we return last * tuple, else tuple before last returned. */ if (readptr->eof_reached) { readptr->current = state->memtupcount; readptr->eof_reached = false; } else { if (readptr->current <= state->memtupdeleted) { Assert(!state->truncated); return NULL; } readptr->current--; /* last returned tuple */ } if (readptr->current <= state->memtupdeleted) { Assert(!state->truncated); return NULL; } return state->memtuples[readptr->current - 1]; } break; case TSS_WRITEFILE: /* Skip state change if we'll just return NULL */ if (readptr->eof_reached && forward) return NULL; /* * Switch from writing to reading. */ BufFileTell(state->myfile, &state->writepos_file, &state->writepos_offset); if (!readptr->eof_reached) if (BufFileSeek(state->myfile, readptr->file, readptr->offset, SEEK_SET) != 0) elog(ERROR, "tuplestore seek failed"); state->status = TSS_READFILE; /* FALL THRU into READFILE case */ case TSS_READFILE: *should_free = true; if (forward) { if ((tuplen = getlen(state, true)) != 0) { tup = READTUP(state, tuplen); /* CDB XXX XXX XXX XXX */ /* MPP-1347: EXPLAIN ANALYZE shows runaway memory usage. * Readtup does a usemem, but the free happens in * ExecStoreTuple. Do a free so state->availMem * doesn't go massively negative to screw up * stats. It would be better to interrogate the * heap for actual memory usage than use this * homemade accounting. */ FREEMEM(state, GetMemoryChunkSpace(tup)); /* CDB XXX XXX XXX XXX */ return tup; } else { readptr->eof_reached = true; return NULL; } } /* * Backward. * * if all tuples are fetched already then we return last tuple, * else tuple before last returned. * * Back up to fetch previously-returned tuple's ending length * word. If seek fails, assume we are at start of file. */ insist_log(false, "Backward scanning of tuplestores are not supported at this time"); if (BufFileSeek(state->myfile, readptr->file, -(long) sizeof(unsigned int), SEEK_CUR) != 0) { /* even a failed backwards fetch gets you out of eof state */ readptr->eof_reached = false; Assert(!state->truncated); return NULL; } tuplen = getlen(state, false); if (readptr->eof_reached) { readptr->eof_reached = false; /* We will return the tuple returned before returning NULL */ } else { /* * Back up to get ending length word of tuple before it. */ if (BufFileSeek(state->myfile, readptr->file, -(long) (tuplen + 2 * sizeof(unsigned int)), SEEK_CUR) != 0) { /* * If that fails, presumably the prev tuple is the first * in the file. Back up so that it becomes next to read * in forward direction (not obviously right, but that is * what in-memory case does). */ if (BufFileSeek(state->myfile, readptr->file, -(long) (tuplen + sizeof(unsigned int)), SEEK_CUR) != 0) elog(ERROR, "bogus tuple length in backward scan"); Assert(!state->truncated); return NULL; } tuplen = getlen(state, false); } /* * Now we have the length of the prior tuple, back up and read it. * Note: READTUP expects we are positioned after the initial * length word of the tuple, so back up to that point. */ if (BufFileSeek(state->myfile, readptr->file, -(long) tuplen, SEEK_CUR) != 0) elog(ERROR, "bogus tuple length in backward scan"); tup = READTUP(state, tuplen); return tup; default: elog(ERROR, "invalid tuplestore state"); return NULL; /* keep compiler quiet */ } }
// Copies all file sectors into another archive. static int CopyMpqFileSectors( TMPQArchive * ha, TMPQFile * hf, TFileStream * pNewStream) { LARGE_INTEGER RawFilePos; // Used for calculating sector offset in the old MPQ archive LARGE_INTEGER MpqFilePos; // MPQ file position in the new archive TMPQBlockEx * pBlockEx = hf->pBlockEx; TMPQBlock * pBlock = hf->pBlock; DWORD dwBytesToCopy = pBlock->dwCSize; DWORD dwFileKey1 = 0; // File key used for decryption DWORD dwFileKey2 = 0; // File key used for encryption DWORD dwCSize = 0; // Compressed file size int nError = ERROR_SUCCESS; // Remember the position in the destination file FileStream_GetPos(pNewStream, &MpqFilePos); MpqFilePos.QuadPart -= ha->MpqPos.QuadPart; // Resolve decryption keys. Note that the file key given // in the TMPQFile structure also includes the key adjustment if(nError == ERROR_SUCCESS && (pBlock->dwFlags & MPQ_FILE_ENCRYPTED)) { dwFileKey2 = dwFileKey1 = hf->dwFileKey; if(pBlock->dwFlags & MPQ_FILE_FIX_KEY) { dwFileKey2 = (dwFileKey1 ^ pBlock->dwFSize) - pBlock->dwFilePos; dwFileKey2 = (dwFileKey2 + MpqFilePos.LowPart) ^ pBlock->dwFSize; } } // If we have to save sector offset table, do it. if(nError == ERROR_SUCCESS && hf->SectorOffsets != NULL) { DWORD * SectorOffsetsCopy = ALLOCMEM(DWORD, hf->dwSectorCount); DWORD dwSectorPosLen = hf->dwSectorCount * sizeof(DWORD); assert((pBlock->dwFlags & MPQ_FILE_SINGLE_UNIT) == 0); assert(pBlock->dwFlags & MPQ_FILE_COMPRESSED); if(SectorOffsetsCopy == NULL) nError = ERROR_NOT_ENOUGH_MEMORY; // Encrypt the secondary sector offset table and write it to the target file if(nError == ERROR_SUCCESS) { memcpy(SectorOffsetsCopy, hf->SectorOffsets, dwSectorPosLen); if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED) EncryptMpqBlock(SectorOffsetsCopy, dwSectorPosLen, dwFileKey2 - 1); BSWAP_ARRAY32_UNSIGNED(SectorOffsetsCopy, dwSectorPosLen); if(!FileStream_Write(pNewStream, NULL, SectorOffsetsCopy, dwSectorPosLen)) nError = GetLastError(); dwCSize += dwSectorPosLen; } // Update compact progress if(CompactCB != NULL) { CompactBytesProcessed.QuadPart += dwSectorPosLen; CompactCB(pvUserData, CCB_COMPACTING_FILES, &CompactBytesProcessed, &CompactTotalBytes); } FREEMEM(SectorOffsetsCopy); } // Now we have to copy all file sectors. We do it without // recompression, because recompression is not necessary in this case if(nError == ERROR_SUCCESS) { for(DWORD dwSector = 0; dwSector < hf->dwDataSectors; dwSector++) { DWORD dwRawDataInSector = hf->dwSectorSize; DWORD dwRawByteOffset = dwSector * hf->dwSectorSize; // Last sector: If there is not enough bytes remaining in the file, cut the raw size if(dwRawDataInSector > dwBytesToCopy) dwRawDataInSector = dwBytesToCopy; // Fix the raw data length if the file is compressed if(hf->SectorOffsets != NULL) { dwRawDataInSector = hf->SectorOffsets[dwSector+1] - hf->SectorOffsets[dwSector]; dwRawByteOffset = hf->SectorOffsets[dwSector]; } // Calculate the raw file offset of the file sector CalculateRawSectorOffset(RawFilePos, hf, dwRawByteOffset); // Read the file sector if(!FileStream_Read(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector)) { nError = GetLastError(); break; } // If necessary, re-encrypt the sector // Note: Recompression is not necessary here. Unlike encryption, // the compression does not depend on the position of the file in MPQ. if((pBlock->dwFlags & MPQ_FILE_ENCRYPTED) && dwFileKey1 != dwFileKey2) { BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector); DecryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwFileKey1 + dwSector); EncryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwFileKey2 + dwSector); BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector); } // Now write the sector back to the file if(!FileStream_Write(pNewStream, NULL, hf->pbFileSector, dwRawDataInSector)) { nError = GetLastError(); break; } // Update compact progress if(CompactCB != NULL) { CompactBytesProcessed.QuadPart += dwRawDataInSector; CompactCB(pvUserData, CCB_COMPACTING_FILES, &CompactBytesProcessed, &CompactTotalBytes); } // Adjust byte counts dwBytesToCopy -= hf->dwSectorSize; dwCSize += dwRawDataInSector; } } // Copy the sector CRCs, if any // Sector CRCs are always compressed (not imploded) and unencrypted if(nError == ERROR_SUCCESS && hf->SectorOffsets != NULL && hf->SectorChksums != NULL) { DWORD dwCrcLength; dwCrcLength = hf->SectorOffsets[hf->dwSectorCount - 1] - hf->SectorOffsets[hf->dwSectorCount - 2]; if(dwCrcLength != 0) { if(!FileStream_Read(ha->pStream, NULL, hf->SectorChksums, dwCrcLength)) nError = GetLastError(); if(!FileStream_Write(pNewStream, NULL, hf->SectorChksums, dwCrcLength)) nError = GetLastError(); // Update compact progress if(CompactCB != NULL) { CompactBytesProcessed.QuadPart += dwCrcLength; CompactCB(pvUserData, CCB_COMPACTING_FILES, &CompactBytesProcessed, &CompactTotalBytes); } // Size of the CRC block is also included in the compressed file size dwCSize += dwCrcLength; } } // Update file position in the block table if(nError == ERROR_SUCCESS) { // At this point, number of bytes written should be exactly // the same like the compressed file size. If it isn't, // there's something wrong (an unknown archive version, MPQ protection, ...) // // Note: Diablo savegames have very weird layout, and the file "hero" // seems to have improper compressed size. Instead of real compressed size, // the "dwCSize" member of the block table entry contains // uncompressed size of file data + size of the sector table. // If we compact the archive, Diablo will refuse to load the game // Seems like some sort of protection to me. if(dwCSize == pBlock->dwCSize) { // Update file pos in the block table pBlockEx->wFilePosHigh = (USHORT)MpqFilePos.HighPart; pBlock->dwFilePos = MpqFilePos.LowPart; } else { nError = ERROR_FILE_CORRUPT; assert(false); } } return nError; }
// TODO: Test for archives > 4GB static DWORD WINAPI ReadMPQBlocks(TMPQFile * hf, DWORD dwBlockPos, BYTE * buffer, DWORD blockBytes) { LARGE_INTEGER FilePos; TMPQArchive * ha = hf->ha; // Archive handle BYTE * tempBuffer = NULL; // Buffer for reading compressed data from the file DWORD dwFilePos = dwBlockPos; // Reading position from the file DWORD dwToRead; // Number of bytes to read DWORD blockNum; // Block number (needed for decrypt) DWORD dwBytesRead = 0; // Total number of bytes read DWORD bytesRemain = 0; // Number of data bytes remaining up to the end of the file DWORD nBlocks; // Number of blocks to load DWORD i; // Test parameters. Block position and block size must be block-aligned, block size nonzero if((dwBlockPos & (ha->dwBlockSize - 1)) || blockBytes == 0) return 0; // Check the end of file if((dwBlockPos + blockBytes) > hf->pBlock->dwFSize) blockBytes = hf->pBlock->dwFSize - dwBlockPos; bytesRemain = hf->pBlock->dwFSize - dwBlockPos; blockNum = dwBlockPos / ha->dwBlockSize; nBlocks = blockBytes / ha->dwBlockSize; if(blockBytes % ha->dwBlockSize) nBlocks++; // If file has variable block positions, we have to load them if((hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) && hf->bBlockPosLoaded == FALSE) { // Move file pointer to the begin of the file in the MPQ if(hf->MpqFilePos.QuadPart != ha->FilePointer.QuadPart) { SetFilePointer(ha->hFile, hf->MpqFilePos.LowPart, &hf->MpqFilePos.HighPart, FILE_BEGIN); } // Read block positions from begin of file. dwToRead = (hf->nBlocks+1) * sizeof(DWORD); if(hf->pBlock->dwFlags & MPQ_FILE_HAS_EXTRA) dwToRead += sizeof(DWORD); // Read the block pos table and convert the buffer to little endian ReadFile(ha->hFile, hf->pdwBlockPos, dwToRead, &dwBytesRead, NULL); BSWAP_ARRAY32_UNSIGNED(hf->pdwBlockPos, (hf->nBlocks+1)); // // If the archive if protected some way, perform additional check // Sometimes, the file appears not to be encrypted, but it is. // // Note: In WoW 1.10+, there's a new flag. With this flag present, // there's one additional entry in the block table. // if(hf->pdwBlockPos[0] != dwBytesRead) hf->pBlock->dwFlags |= MPQ_FILE_ENCRYPTED; // Decrypt loaded block positions if necessary if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED) { // If we don't know the file seed, try to find it. if(hf->dwSeed1 == 0) hf->dwSeed1 = DetectFileSeed(hf->pdwBlockPos, dwBytesRead); // If we don't know the file seed, sorry but we cannot extract the file. if(hf->dwSeed1 == 0) return 0; // Decrypt block positions DecryptMPQBlock(hf->pdwBlockPos, dwBytesRead, hf->dwSeed1 - 1); // Check if the block positions are correctly decrypted // I don't know why, but sometimes it will result invalid block positions on some files if(hf->pdwBlockPos[0] != dwBytesRead) { // Try once again to detect file seed and decrypt the blocks // TODO: Test with >4GB SetFilePointer(ha->hFile, hf->MpqFilePos.LowPart, &hf->MpqFilePos.HighPart, FILE_BEGIN); ReadFile(ha->hFile, hf->pdwBlockPos, dwToRead, &dwBytesRead, NULL); BSWAP_ARRAY32_UNSIGNED(hf->pdwBlockPos, (hf->nBlocks+1)); hf->dwSeed1 = DetectFileSeed(hf->pdwBlockPos, dwBytesRead); DecryptMPQBlock(hf->pdwBlockPos, dwBytesRead, hf->dwSeed1 - 1); // Check if the block positions are correctly decrypted if(hf->pdwBlockPos[0] != dwBytesRead) return 0; } } // Update hf's variables ha->FilePointer.QuadPart = hf->MpqFilePos.QuadPart + dwBytesRead; hf->bBlockPosLoaded = TRUE; } // Get file position and number of bytes to read dwFilePos = dwBlockPos; dwToRead = blockBytes; if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) { dwFilePos = hf->pdwBlockPos[blockNum]; dwToRead = hf->pdwBlockPos[blockNum + nBlocks] - dwFilePos; } FilePos.QuadPart = hf->MpqFilePos.QuadPart + dwFilePos; // Get work buffer for store read data tempBuffer = buffer; if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) { if((tempBuffer = ALLOCMEM(BYTE, dwToRead)) == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } } // Set file pointer, if necessary if(ha->FilePointer.QuadPart != FilePos.QuadPart) { SetFilePointer(ha->hFile, FilePos.LowPart, &FilePos.HighPart, FILE_BEGIN); } // 15018F87 : Read all requested blocks ReadFile(ha->hFile, tempBuffer, dwToRead, &dwBytesRead, NULL); ha->FilePointer.QuadPart = FilePos.QuadPart + dwBytesRead; // Block processing part. DWORD blockStart = 0; // Index of block start in work buffer DWORD blockSize = min(blockBytes, ha->dwBlockSize); DWORD index = blockNum; // Current block index dwBytesRead = 0; // Clear read byte counter // Walk through all blocks for(i = 0; i < nBlocks; i++, index++) { BYTE * inputBuffer = tempBuffer + blockStart; int outLength = ha->dwBlockSize; if(bytesRemain < (DWORD)outLength) outLength = bytesRemain; // Get current block length if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) blockSize = hf->pdwBlockPos[index+1] - hf->pdwBlockPos[index]; // If block is encrypted, we have to decrypt it. if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED) { BSWAP_ARRAY32_UNSIGNED((DWORD *)inputBuffer, blockSize / sizeof(DWORD)); // If we don't know the seed, try to decode it as WAVE file if(hf->dwSeed1 == 0) hf->dwSeed1 = DetectFileSeed2((DWORD *)inputBuffer, 3, ID_WAVE, hf->pBlock->dwFSize - 8, 0x45564157); // Let's try MSVC's standard EXE or header if(hf->dwSeed1 == 0) hf->dwSeed1 = DetectFileSeed2((DWORD *)inputBuffer, 2, 0x00905A4D, 0x00000003); if(hf->dwSeed1 == 0) return 0; DecryptMPQBlock((DWORD *)inputBuffer, blockSize, hf->dwSeed1 + index); BSWAP_ARRAY32_UNSIGNED((DWORD *)inputBuffer, blockSize / sizeof(DWORD)); } // If the block is really compressed, decompress it. // WARNING : Some block may not be compressed, it can be determined only // by comparing uncompressed and compressed size !!! if(blockSize < (DWORD)outLength) { // Is the file compressed with PKWARE Data Compression Library ? if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESS_PKWARE) Decompress_pklib((char *)buffer, &outLength, (char *)inputBuffer, (int)blockSize); // Is it a file compressed by Blizzard's multiple compression ? // Note that Storm.dll v 1.0.9 distributed with Warcraft III // passes the full path name of the opened archive as the new last parameter if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESS_MULTI) SCompDecompress((char *)buffer, &outLength, (char *)inputBuffer, (int)blockSize); dwBytesRead += outLength; buffer += outLength; } else { if(buffer != inputBuffer) memcpy(buffer, inputBuffer, blockSize); dwBytesRead += blockSize; buffer += blockSize; } blockStart += blockSize; bytesRemain -= outLength; } // Delete input buffer, if necessary if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) FREEMEM(tempBuffer); return dwBytesRead; }
int editor( int stepflag ) { char *name; int ir; int iblk; int len; int is; int i; double *buffer; RGST_AttributeElem_t *editvars; RGST_AttributeElem_t *editvars_ptr; double *regetot = (double *) ProblemArray_ptr("regetot", NULL); double *regke = (double *) ProblemArray_ptr("regke", NULL); double *regie = (double *) ProblemArray_ptr("regie", NULL); double *regpe = (double *) ProblemArray_ptr("regpe", NULL); double *regtke = (double *) ProblemArray_ptr("regtke", NULL); double *regmass = (double *) ProblemArray_ptr("regmass", NULL); double *regvol = (double *) ProblemArray_ptr("regvol", NULL); double *regxmom = (double *) ProblemArray_ptr("regxmom", NULL); double *regymom = (double *) ProblemArray_ptr("regymom", NULL); double *regzmom = (double *) ProblemArray_ptr("regzmom", NULL); double *regxmomp = (double *) ProblemArray_ptr("regxmomp", NULL); double *regymomp = (double *) ProblemArray_ptr("regymomp", NULL); double *regzmomp = (double *) ProblemArray_ptr("regzmomp", NULL); double *regxmomn = (double *) ProblemArray_ptr("regxmomn", NULL); double *regymomn = (double *) ProblemArray_ptr("regymomn", NULL); double *regzmomn = (double *) ProblemArray_ptr("regzmomn", NULL); double *tmatavg = (double *) ProblemArray_ptr("regtmatavg", NULL); double *tionavg = (double *) ProblemArray_ptr("regtionavg", NULL); double *tradavg = (double *) ProblemArray_ptr("regtradavg", NULL); double *cveavg = (double *) ProblemArray_ptr("regcveavg", NULL); double *cviavg = (double *) ProblemArray_ptr("regcviavg", NULL); double *regtne = (double *) ProblemArray_ptr("regtnetot", NULL); double *regdtne = (double *) ProblemArray_ptr("regdtnetot", NULL); double *regpartmass = (double *) ProblemArray_ptr("regpartmass", NULL); double *regpartke = (double *) ProblemArray_ptr("regpartke", NULL); double *regpartdke = (double *) ProblemArray_ptr("regpartdke", NULL); double *regpartnum = (double *) ProblemArray_ptr("regpartnum", NULL); double *regpartnump = (double *) ProblemArray_ptr("regpartnump", NULL); double *regpartxmom = (double *) ProblemArray_ptr("regpartxmom", NULL); double *regpartymom = (double *) ProblemArray_ptr("regpartymom", NULL); double *regpartzmom = (double *) ProblemArray_ptr("regpartzmom", NULL); len = 0 ; for ( ir = 1 ; ir <= nreg ; ir++ ) { regetot[ir] = 0.0; len++ ; regke[ir] = 0.0; len++ ; regie[ir] = 0.0; len++ ; regtke[ir] = 0.0; len++ ; regpe[ir] = 0.0; len++ ; regmass[ir] = 0.0; len++ ; regvol[ir] = 0.0; len++ ; regxmom[ir] = 0.0; len++ ; regymom[ir] = 0.0; len++ ; regzmom[ir] = 0.0; len++ ; regxmomp[ir] = 0.0; len++ ; regymomp[ir] = 0.0; len++ ; regzmomp[ir] = 0.0; len++ ; regxmomn[ir] = 0.0; len++ ; regymomn[ir] = 0.0; len++ ; regzmomn[ir] = 0.0; len++ ; tmatavg[ir] = 0.0; len++ ; tionavg[ir] = 0.0; len++ ; tradavg[ir] = 0.0; len++ ; cveavg[ir] = 0.0; len++ ; cviavg[ir] = 0.0; len++ ; regpartmass[ir] = 0.0; len++ ; regpartke[ir] = 0.0; len++ ; regpartdke[ir] = 0.0; len++ ; regpartnum[ir] = 0.0; len++ ; regpartnump[ir] = 0.0; len++ ; regpartxmom[ir] = 0.0; len++ ; regpartymom[ir] = 0.0; len++ ; regpartzmom[ir] = 0.0; len++ ; for ( is = 0 ; is < reg[ir].nspec ; is++ ) { reg[ir].species[is].mass = 0.0 ; len++ ; } len++; } len += RGST_NUM_OBJECTS_WITH_ATTR("SourceList"); for ( iblk = 0 ; iblk < nblk ; iblk++ ) { if ( ndims == 2 ) { regenrgy2d( domains[iblk].x, domains[iblk].y, domains[iblk].xdot, domains[iblk].ydot, &domains[iblk] ) ; } else { regenrgy3d( domains[iblk].x, domains[iblk].y, domains[iblk].z, domains[iblk].xdot, domains[iblk].ydot, domains[iblk].zdot, &domains[iblk] ); } } for ( iblk = 0 ; iblk < nblk ; iblk++ ) { HashTable_t *hash = domains[iblk].hash; double *retot = (double *) ProblemArray_ptr("regetot", hash); double *rke = (double *) ProblemArray_ptr("regke", hash); double *rie = (double *) ProblemArray_ptr("regie", hash); double *rpe = (double *) ProblemArray_ptr("regpe", hash); double *rtke = (double *) ProblemArray_ptr("regtke", hash); double *rmass = (double *) ProblemArray_ptr("regmass", hash); double *rvol = (double *) ProblemArray_ptr("regvol", hash); double *rxmom = (double *) ProblemArray_ptr("regxmom", hash); double *rymom = (double *) ProblemArray_ptr("regymom", hash); double *rzmom = (double *) ProblemArray_ptr("regzmom", hash); double *rxmomp = (double *) ProblemArray_ptr("regxmomp",hash); double *rymomp = (double *) ProblemArray_ptr("regymomp",hash); double *rzmomp = (double *) ProblemArray_ptr("regzmomp",hash); double *rxmomn = (double *) ProblemArray_ptr("regxmomn",hash); double *rymomn = (double *) ProblemArray_ptr("regymomn",hash); double *rzmomn = (double *) ProblemArray_ptr("regzmomn",hash); double *rtmatavg = (double *) ProblemArray_ptr("regtmatavg",hash); double *rtionavg = (double *) ProblemArray_ptr("regtionavg",hash); double *rtradavg = (double *) ProblemArray_ptr("regtradavg",hash); double *rcveavg = (double *) ProblemArray_ptr("regcveavg",hash); double *rcviavg = (double *) ProblemArray_ptr("regcviavg",hash); double *rdtne = (double *) ProblemArray_ptr("regdtnetot",hash); double *rpartms = (double *) ProblemArray_ptr("regpartmass",hash); double *rpartke = (double *) ProblemArray_ptr("regpartke",hash); double *rpartdke = (double *) ProblemArray_ptr("regpartdke",hash); double *rpartnum = (double *) ProblemArray_ptr("regpartnum",hash); double *rpartnmp = (double *) ProblemArray_ptr("regpartnump",hash); double *rpartxmo = (double *) ProblemArray_ptr("regpartxmom",hash); double *rpartymo = (double *) ProblemArray_ptr("regpartymom",hash); double *rpartzmo = (double *) ProblemArray_ptr("regpartzmom",hash); for ( ir = 1 ; ir <= nreg ; ir++ ) { regetot[ir] += retot[ir] ; regke[ir] += rke[ir] ; regie[ir] += rie[ir] ; regtke[ir] += rtke[ir] ; regpe[ir] += rpe[ir] ; regmass[ir] += rmass[ir] ; regvol[ir] += rvol[ir] ; regxmom[ir] += rxmom[ir] ; regymom[ir] += rymom[ir] ; regzmom[ir] += rzmom[ir] ; regxmomp[ir] += rxmomp[ir] ; regymomp[ir] += rymomp[ir] ; regzmomp[ir] += rzmomp[ir] ; regxmomn[ir] += rxmomn[ir] ; regymomn[ir] += rymomn[ir] ; regzmomn[ir] += rzmomn[ir] ; tmatavg[ir] += rtmatavg[ir] ; tionavg[ir] += rtionavg[ir] ; tradavg[ir] += rtradavg[ir] ; cveavg[ir] += rcveavg[ir] ; cviavg[ir] += rcviavg[ir] ; regdtne[ir] += rdtne[ir] ; regpartmass[ir] += rpartms[ir] ; regpartke[ir] += rpartke[ir] ; regpartdke[ir] += rpartdke[ir] ; regpartnum[ir] += rpartnum[ir] ; regpartnump[ir] += rpartnmp[ir] ; regpartxmom[ir] += rpartxmo[ir] ; regpartymom[ir] += rpartymo[ir] ; regpartzmom[ir] += rpartzmo[ir] ; } } SourceNew_sumedits(); if (ifparallel) { buffer = ALLOT(double,len); len = 0 ; for ( ir = 1 ; ir <= nreg ; ir++ ) { buffer[len++] = regetot[ir] ; buffer[len++] = regke[ir] ; buffer[len++] = regie[ir] ; buffer[len++] = regtke[ir] ; buffer[len++] = regpe[ir] ; buffer[len++] = regmass[ir] ; buffer[len++] = regvol[ir] ; buffer[len++] = regxmom[ir] ; buffer[len++] = regymom[ir] ; buffer[len++] = regzmom[ir] ; buffer[len++] = regxmomp[ir] ; buffer[len++] = regymomp[ir] ; buffer[len++] = regzmomp[ir] ; buffer[len++] = regxmomn[ir] ; buffer[len++] = regymomn[ir] ; buffer[len++] = regzmomn[ir] ; buffer[len++] = tmatavg[ir] ; buffer[len++] = tionavg[ir] ; buffer[len++] = tradavg[ir] ; buffer[len++] = cveavg[ir] ; buffer[len++] = cviavg[ir] ; buffer[len++] = regdtne[ir] ; buffer[len++] = regpartmass[ir] ; buffer[len++] = regpartke[ir] ; buffer[len++] = regpartdke[ir] ; buffer[len++] = regpartnum[ir] ; buffer[len++] = regpartnump[ir] ; buffer[len++] = regpartxmom[ir] ; buffer[len++] = regpartymom[ir] ; buffer[len++] = regpartzmom[ir] ; for (is = 0; is < reg[ir].nspec; is++) { buffer[len++] = reg[ir].species[is].mass; } } SourceNew_packedit( buffer, &len); comreduce(buffer,len,COM_SUM,COM_ALL,COM_DOUBLE); len = 0 ; for ( ir = 1 ; ir <= nreg ; ir++ ) { regetot[ir] = buffer[len++] ; regke[ir] = buffer[len++] ; regie[ir] = buffer[len++] ; regtke[ir] = buffer[len++] ; regpe[ir] = buffer[len++] ; regmass[ir] = buffer[len++] ; regvol[ir] = buffer[len++] ; regxmom[ir] = buffer[len++] ; regymom[ir] = buffer[len++] ; regzmom[ir] = buffer[len++] ; regxmomp[ir] = buffer[len++] ; regymomp[ir] = buffer[len++] ; regzmomp[ir] = buffer[len++] ; regxmomn[ir] = buffer[len++] ; regymomn[ir] = buffer[len++] ; regzmomn[ir] = buffer[len++] ; tmatavg[ir] = buffer[len++] ; tionavg[ir] = buffer[len++] ; tradavg[ir] = buffer[len++] ; cveavg[ir] = buffer[len++] ; cviavg[ir] = buffer[len++] ; regdtne[ir] = buffer[len++] ; regpartmass[ir] = buffer[len++] ; regpartke[ir] = buffer[len++] ; regpartdke[ir] = buffer[len++] ; regpartnum[ir] = buffer[len++] ; regpartnump[ir] = buffer[len++] ; regpartxmom[ir] = buffer[len++] ; regpartymom[ir] = buffer[len++] ; regpartzmom[ir] = buffer[len++] ; for (is = 0; is < reg[ir].nspec; is++) { reg[ir].species[is].mass = buffer[len++]; } } SourceNew_unpackedit(buffer, &len); FREEMEM(buffer) ; } etot = 0.0 ; ketot = 0.0 ; ietot = 0.0 ; tketot = 0.0 ; petot = 0.0 ; masstot = 0.0 ; volumetot = 0.0 ; xmomtot = 0.0 ; ymomtot = 0.0 ; zmomtot = 0.0 ; xmomtotp = 0.0 ; ymomtotp = 0.0 ; zmomtotp = 0.0 ; xmomtotn = 0.0 ; ymomtotn = 0.0 ; zmomtotn = 0.0 ; dtnetot = 0.0 ; for ( ir = 1 ; ir <= nreg ; ir++ ) { tmatavg[ir] /= ( cveavg[ir] + ptiny ) ; tionavg[ir] /= ( cviavg[ir] + ptiny ) ; cveavg[ir] /= ( regmass[ir] + ptiny ) ; cviavg[ir] /= ( regmass[ir] + ptiny ) ; tradavg[ir] /= ( regvol[ir] + ptiny ) ; tradavg[ir] = MAX( tradavg[ir], 0.0 ) ; tradavg[ir] = sqrt( sqrt( tradavg[ir] ) ) ; etot += regetot[ir] ; ketot += regke[ir] ; ietot += regie[ir] ; tketot += regtke[ir] ; petot += regpe[ir] ; masstot += regmass[ir] ; volumetot += regvol[ir] ; xmomtot += regxmom[ir] ; ymomtot += regymom[ir] ; zmomtot += regzmom[ir] ; xmomtotp += regxmomp[ir] ; ymomtotp += regymomp[ir] ; zmomtotp += regzmomp[ir] ; xmomtotn += regxmomn[ir] ; ymomtotn += regymomn[ir] ; zmomtotn += regzmomn[ir] ; dtnetot += regdtne[ir] ; tnetot += regdtne[ir] ; regtne[ir] += regdtne[ir]; regdtne[ir] = 0.; } return(0) ; }
void CFCPerl_write_bindings(CFCPerl *self) { CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy); CFCPerlClass **registry = CFCPerlClass_registry(); char *hand_rolled_xs = CFCUtil_strdup(""); char *generated_xs = CFCUtil_strdup(""); char *xs_init = CFCUtil_strdup(""); // Pound-includes for generated headers. for (size_t i = 0; ordered[i] != NULL; i++) { CFCClass *klass = ordered[i]; // TODO: Don't include headers for parcels the source parcels don't // depend on. const char *include_h = CFCClass_include_h(klass); generated_xs = CFCUtil_cat(generated_xs, "#include \"", include_h, "\"\n", NULL); } generated_xs = CFCUtil_cat(generated_xs, "\n", NULL); for (size_t i = 0; ordered[i] != NULL; i++) { CFCClass *klass = ordered[i]; if (CFCClass_included(klass)) { continue; } // Constructors. CFCPerlConstructor **constructors = CFCPerlClass_constructor_bindings(klass); for (size_t j = 0; constructors[j] != NULL; j++) { CFCPerlSub *xsub = (CFCPerlSub*)constructors[j]; // Add the XSUB function definition. char *xsub_def = CFCPerlConstructor_xsub_def(constructors[j]); generated_xs = CFCUtil_cat(generated_xs, xsub_def, "\n", NULL); FREEMEM(xsub_def); // Add XSUB initialization at boot. xs_init = S_add_xs_init(xs_init, xsub); } FREEMEM(constructors); // Methods. CFCPerlMethod **methods = CFCPerlClass_method_bindings(klass); for (size_t j = 0; methods[j] != NULL; j++) { CFCPerlSub *xsub = (CFCPerlSub*)methods[j]; // Add the XSUB function definition. char *xsub_def = CFCPerlMethod_xsub_def(methods[j]); generated_xs = CFCUtil_cat(generated_xs, xsub_def, "\n", NULL); FREEMEM(xsub_def); // Add XSUB initialization at boot. xs_init = S_add_xs_init(xs_init, xsub); } FREEMEM(methods); } // Hand-rolled XS. for (size_t i = 0; registry[i] != NULL; i++) { const char *xs = CFCPerlClass_get_xs_code(registry[i]); hand_rolled_xs = CFCUtil_cat(hand_rolled_xs, xs, "\n", NULL); } // Write out if there have been any changes. char *xs_file_contents = S_xs_file_contents(self, generated_xs, xs_init, hand_rolled_xs); CFCUtil_write_if_changed(self->xs_path, xs_file_contents, strlen(xs_file_contents)); FREEMEM(xs_file_contents); FREEMEM(hand_rolled_xs); FREEMEM(xs_init); FREEMEM(generated_xs); FREEMEM(ordered); }
static void S_write_callbacks_c(CFCPerl *self) { CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy); static const char pattern[] = "%s" "\n" "#include \"XSBind.h\"\n" "#include \"callbacks.h\"\n" "\n" "static void\n" "S_finish_callback_void(const char *meth_name) {\n" " int count = call_method(meth_name, G_VOID | G_DISCARD);\n" " if (count != 0) {\n" " CFISH_THROW(CFISH_ERR, \"Bad callback to '%%s': %%i32\",\n" " meth_name, (int32_t)count);\n" " }\n" " FREETMPS;\n" " LEAVE;\n" "}\n" "\n" "static CFISH_INLINE SV*\n" "SI_do_callback_sv(const char *meth_name) {\n" " int count = call_method(meth_name, G_SCALAR);\n" " if (count != 1) {\n" " CFISH_THROW(CFISH_ERR, \"Bad callback to '%%s': %%i32\",\n" " meth_name, (int32_t)count);\n" " }\n" " dSP;\n" " SV *return_sv = POPs;\n" " PUTBACK;\n" " return return_sv;\n" "}\n" "\n" "static int64_t\n" "S_finish_callback_i64(const char *meth_name) {\n" " SV *return_sv = SI_do_callback_sv(meth_name);\n" " int64_t retval;\n" " if (sizeof(IV) == 8) {\n" " retval = (int64_t)SvIV(return_sv);\n" " }\n" " else {\n" " if (SvIOK(return_sv)) {\n" " // It's already no more than 32 bits, so don't convert.\n" " retval = SvIV(return_sv);\n" " }\n" " else {\n" " // Maybe lossy.\n" " double temp = SvNV(return_sv);\n" " retval = (int64_t)temp;\n" " }\n" " }\n" " FREETMPS;\n" " LEAVE;\n" " return retval;\n" "}\n" "\n" "static double\n" "S_finish_callback_f64(const char *meth_name) {\n" " SV *return_sv = SI_do_callback_sv(meth_name);\n" " double retval = SvNV(return_sv);\n" " FREETMPS;\n" " LEAVE;\n" " return retval;\n" "}\n" "\n" "static cfish_Obj*\n" "S_finish_callback_obj(void *vself, const char *meth_name,\n" " int nullable) {\n" " SV *return_sv = SI_do_callback_sv(meth_name);\n" " cfish_Obj *retval = XSBind_perl_to_cfish(return_sv);\n" " FREETMPS;\n" " LEAVE;\n" " if (!nullable && !retval) {\n" " CFISH_THROW(CFISH_ERR, \"%%o#%%s cannot return NULL\",\n" " Cfish_Obj_Get_Class_Name((cfish_Obj*)vself),\n" " meth_name);\n" " }\n" " return retval;\n" "}\n" "\n"; char *content = CFCUtil_sprintf(pattern, self->header); for (size_t i = 0; ordered[i] != NULL; i++) { CFCClass *klass = ordered[i]; if (CFCClass_inert(klass)) { continue; } CFCMethod **fresh_methods = CFCClass_fresh_methods(klass); for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) { CFCMethod *method = fresh_methods[meth_num]; // Define callback. if (CFCMethod_novel(method) && !CFCMethod_final(method)) { char *cb_def = CFCPerlMethod_callback_def(method); content = CFCUtil_cat(content, cb_def, "\n", NULL); FREEMEM(cb_def); } } FREEMEM(fresh_methods); } content = CFCUtil_cat(content, self->footer, NULL); // Write if changed. const char *src_dest = CFCHierarchy_get_source_dest(self->hierarchy); char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "callbacks.c", src_dest); CFCUtil_write_if_changed(filepath, content, strlen(content)); FREEMEM(filepath); FREEMEM(content); FREEMEM(ordered); }
static void S_write_boot_c(CFCPerl *self) { CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy); CFCParcel **parcels = CFCParcel_all_parcels(); char *pound_includes = CFCUtil_strdup(""); char *bootstrap_code = CFCUtil_strdup(""); char *alias_adds = CFCUtil_strdup(""); char *isa_pushes = CFCUtil_strdup(""); for (size_t i = 0; parcels[i]; ++i) { if (!CFCParcel_included(parcels[i])) { const char *prefix = CFCParcel_get_prefix(parcels[i]); bootstrap_code = CFCUtil_cat(bootstrap_code, " ", prefix, "bootstrap_parcel();\n", NULL); } } for (size_t i = 0; ordered[i] != NULL; i++) { CFCClass *klass = ordered[i]; if (CFCClass_included(klass)) { continue; } const char *class_name = CFCClass_get_class_name(klass); const char *include_h = CFCClass_include_h(klass); pound_includes = CFCUtil_cat(pound_includes, "#include \"", include_h, "\"\n", NULL); if (CFCClass_inert(klass)) { continue; } // Add aliases for selected KinoSearch classes which allow old indexes // to be read. CFCPerlClass *class_binding = CFCPerlClass_singleton(class_name); if (class_binding) { const char *vtable_var = CFCClass_full_vtable_var(klass); const char **aliases = CFCPerlClass_get_class_aliases(class_binding); for (size_t j = 0; aliases[j] != NULL; j++) { const char *alias = aliases[j]; size_t alias_len = strlen(alias); const char pattern[] = "%s" " Cfish_ZCB_Assign_Str(alias, \"%s\", %u);\n" " cfish_VTable_add_alias_to_registry(%s,\n" " (cfish_CharBuf*)alias);\n"; char *new_alias_adds = CFCUtil_sprintf(pattern, alias_adds, alias, (unsigned)alias_len, vtable_var); FREEMEM(alias_adds); alias_adds = new_alias_adds; } char *metadata_code = CFCPerlClass_method_metadata_code(class_binding); alias_adds = CFCUtil_cat(alias_adds, metadata_code, NULL); FREEMEM(metadata_code); } CFCClass *parent = CFCClass_get_parent(klass); if (parent) { const char *parent_class_name = CFCClass_get_class_name(parent); isa_pushes = CFCUtil_cat(isa_pushes, " isa = get_av(\"", class_name, "::ISA\", 1);\n", NULL); isa_pushes = CFCUtil_cat(isa_pushes, " av_push(isa, newSVpv(\"", parent_class_name, "\", 0));\n", NULL); } } const char pattern[] = "%s\n" "\n" "#include \"cfish_parcel.h\"\n" "#include \"EXTERN.h\"\n" "#include \"perl.h\"\n" "#include \"XSUB.h\"\n" "#include \"boot.h\"\n" "#include \"Clownfish/CharBuf.h\"\n" "#include \"Clownfish/VTable.h\"\n" "%s\n" "\n" "void\n" "%s() {\n" "%s" "\n" " cfish_ZombieCharBuf *alias = CFISH_ZCB_WRAP_STR(\"\", 0);\n" "%s" "\n" " AV *isa;\n" "%s" "}\n" "\n" "%s\n" "\n"; char *content = CFCUtil_sprintf(pattern, self->header, pound_includes, self->boot_func, bootstrap_code, alias_adds, isa_pushes, self->footer); const char *src_dest = CFCHierarchy_get_source_dest(self->hierarchy); char *boot_c_path = CFCUtil_sprintf("%s" CHY_DIR_SEP "boot.c", src_dest); CFCUtil_write_file(boot_c_path, content, strlen(content)); FREEMEM(boot_c_path); FREEMEM(content); FREEMEM(isa_pushes); FREEMEM(alias_adds); FREEMEM(bootstrap_code); FREEMEM(pound_includes); FREEMEM(parcels); FREEMEM(ordered); }
void CFCPrereq_destroy(CFCPrereq *self) { FREEMEM(self->name); CFCBase_decref((CFCBase*)self->version); CFCBase_destroy((CFCBase*)self); }
void CFCParcel_connect_and_sort_classes(CFCParcel *self) { size_t num_classes = self->num_classes; size_t alloc_size = (num_classes + 1) * sizeof(CFCClass*); CFCClass **classes = self->classes; CFCClass **sorted = (CFCClass**)MALLOCATE(alloc_size); // Perform a depth-first search of the classes in the parcel, and store // the classes in the order that they were visited. This makes sure // that subclasses are sorted after their parents. // // To avoid a recursive algorithm, the end of the sorted array is used // as a stack for classes that have yet to be visited. // // Root and child classes are sorted by name to get a deterministic // order. // Set up parent/child relationship of classes and find subtree roots // in parcel. size_t todo = num_classes; for (size_t i = 0; i < num_classes; i++) { CFCClass *klass = classes[i]; CFCClass *parent = NULL; const char *parent_name = CFCClass_get_parent_class_name(klass); if (parent_name) { parent = S_fetch_class(self, parent_name, 1); if (!parent) { CFCUtil_die("Parent class '%s' of '%s' not found in parcel" " '%s' or its prerequisites", parent_name, CFCClass_get_name(klass), self->name); } CFCClass_add_child(parent, klass); } if (!parent || !CFCClass_in_parcel(parent, self)) { // Subtree root. sorted[--todo] = klass; } // Resolve types. CFCClass_resolve_types(klass); } qsort(&sorted[todo], num_classes - todo, sizeof(sorted[0]), S_compare_class_name); size_t num_sorted = 0; while (todo < num_classes) { CFCClass *klass = sorted[todo++]; sorted[num_sorted++] = klass; // Push children on stack. Since this function is called first for // prereq parcels, we can be sure that the class doesn't have // children from another parcel yet. CFCClass **children = CFCClass_children(klass); size_t prev_todo = todo; for (size_t i = 0; children[i]; i++) { if (todo <= num_sorted) { CFCUtil_die("Internal error in CFCParcel_sort_classes"); } sorted[--todo] = children[i]; } qsort(&sorted[todo], prev_todo - todo, sizeof(sorted[0]), S_compare_class_name); } if (num_sorted != num_classes) { CFCUtil_die("Internal error in CFCParcel_sort_classes"); } sorted[num_classes] = NULL; FREEMEM(self->classes); self->classes = sorted; }
/* * tuplestore_trim - remove all no-longer-needed tuples * * Calling this function authorizes the tuplestore to delete all tuples * before the oldest read pointer, if no read pointer is marked as requiring * REWIND capability. * * Note: this is obviously safe if no pointer has BACKWARD capability either. * If a pointer is marked as BACKWARD but not REWIND capable, it means that * the pointer can be moved backward but not before the oldest other read * pointer. */ void tuplestore_trim(Tuplestorestate *state) { int oldest; int nremove; int i; /* * Truncation is disallowed if any read pointer requires rewind * capability. */ if (state->eflags & EXEC_FLAG_REWIND) return; /* * We don't bother trimming temp files since it usually would mean more * work than just letting them sit in kernel buffers until they age out. */ if (state->status != TSS_INMEM) return; /* Find the oldest read pointer */ oldest = state->memtupcount; for (i = 0; i < state->readptrcount; i++) { if (!state->readptrs[i].eof_reached) oldest = Min(oldest, state->readptrs[i].current); } /* * Note: you might think we could remove all the tuples before the oldest * "current", since that one is the next to be returned. However, since * tuplestore_gettuple returns a direct pointer to our internal copy of * the tuple, it's likely that the caller has still got the tuple just * before "current" referenced in a slot. So we keep one extra tuple * before the oldest "current". (Strictly speaking, we could require such * callers to use the "copy" flag to tuplestore_gettupleslot, but for * efficiency we allow this one case to not use "copy".) */ nremove = oldest - 1; if (nremove <= 0) return; /* nothing to do */ Assert(nremove >= state->memtupdeleted); Assert(nremove <= state->memtupcount); /* Release no-longer-needed tuples */ for (i = state->memtupdeleted; i < nremove; i++) { FREEMEM(state, GetMemoryChunkSpace(state->memtuples[i])); pfree(state->memtuples[i]); state->memtuples[i] = NULL; } state->memtupdeleted = nremove; /* mark tuplestore as truncated (used for Assert crosschecks only) */ state->truncated = true; /* * If nremove is less than 1/8th memtupcount, just stop here, leaving the * "deleted" slots as NULL. This prevents us from expending O(N^2) time * repeatedly memmove-ing a large pointer array. The worst case space * wastage is pretty small, since it's just pointers and not whole tuples. */ if (nremove < state->memtupcount / 8) return; /* * Slide the array down and readjust pointers. * * In mergejoin's current usage, it's demonstrable that there will always * be exactly one non-removed tuple; so optimize that case. */ if (nremove + 1 == state->memtupcount) state->memtuples[0] = state->memtuples[nremove]; else memmove(state->memtuples, state->memtuples + nremove, (state->memtupcount - nremove) * sizeof(void *)); state->memtupdeleted = 0; state->memtupcount -= nremove; for (i = 0; i < state->readptrcount; i++) { if (!state->readptrs[i].eof_reached) state->readptrs[i].current -= nremove; } }
GeneralizedTime_t * asn_time2GT_frac(GeneralizedTime_t *opt_gt, const struct tm *tm, int frac_value, int frac_digits, int force_gmt) { struct tm tm_s; long gmtoff; const unsigned int buf_size = 4 + 2 + 2 /* yyyymmdd */ + 2 + 2 + 2 /* hhmmss */ + 1 + 6 /* .ffffff */ + 1 + 4 /* +hhmm */ + 1 /* '\0' */ ; char *buf; char *p; int size; /* Check arguments */ if(!tm) { errno = EINVAL; return 0; } /* Pre-allocate a buffer of sufficient yet small length */ buf = (char *)MALLOC(buf_size); if(!buf) return 0; gmtoff = GMTOFF(*tm); if(force_gmt && gmtoff) { tm_s = *tm; tm_s.tm_sec -= gmtoff; timegm(&tm_s); /* Fix the time */ tm = &tm_s; #ifdef HAVE_TM_GMTOFF assert(!GMTOFF(tm_s)); /* Will fix itself */ #else /* !HAVE_TM_GMTOFF */ gmtoff = 0; #endif } size = snprintf(buf, buf_size, "%04d%02d%02d%02d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec ); if(size != 14) { /* Could be assert(size == 14); */ FREEMEM(buf); errno = EINVAL; return 0; } p = buf + size; /* * Deal with fractions. */ if(frac_value > 0 && frac_digits > 0) { char *end = p + 1 + 6; /* '.' + maximum 6 digits */ char *z = p; long fbase; *z++ = '.'; /* Place bounds on precision */ while(frac_digits-- > 6) frac_value /= 10; /* emulate fbase = pow(10, frac_digits) */ for(fbase = 1; frac_digits--;) fbase *= 10; do { int digit = frac_value / fbase; if(digit > 9) { z = 0; break; } *z++ = digit + 0x30; frac_value %= fbase; fbase /= 10; } while(fbase > 0 && frac_value > 0 && z < end); if(z) { for(--z; *z == 0x30; --z); /* Strip zeroes */ p = z + (*z != '.'); size = p - buf; } } if(force_gmt) { *p++ = 0x5a; /* "Z" */ *p++ = 0; size++; } else { int ret; gmtoff %= 86400; ret = snprintf(p, buf_size - size, "%+03ld%02ld", gmtoff / 3600, labs(gmtoff % 3600) / 60); if(ret != 5) { FREEMEM(buf); errno = EINVAL; return 0; } size += ret; } if(opt_gt) { if(opt_gt->buf) FREEMEM(opt_gt->buf); } else { opt_gt = (GeneralizedTime_t *)CALLOC(1, sizeof *opt_gt); if(!opt_gt) { FREEMEM(buf); return 0; } } opt_gt->buf = (unsigned char *)buf; opt_gt->size = size; return opt_gt; }
static void tuplestore_puttuple_common(Tuplestorestate *state, void *tuple) { TSReadPointer *readptr; int i; ResourceOwner oldowner; switch (state->status) { case TSS_INMEM: /* * Update read pointers as needed; see API spec above. */ readptr = state->readptrs; for (i = 0; i < state->readptrcount; readptr++, i++) { if (readptr->eof_reached && i != state->activeptr) { readptr->eof_reached = false; readptr->current = state->memtupcount; } } /* * Grow the array as needed. Note that we try to grow the array * when there is still one free slot remaining --- if we fail, * there'll still be room to store the incoming tuple, and then * we'll switch to tape-based operation. */ if (state->memtupcount >= state->memtupsize - 1) { /* * See grow_memtuples() in tuplesort.c for the rationale * behind these two tests. */ if (state->availMem > (long) (state->memtupsize * sizeof(void *)) && (Size) (state->memtupsize * 2) < MaxAllocSize / sizeof(void *)) { FREEMEM(state, GetMemoryChunkSpace(state->memtuples)); state->memtupsize *= 2; state->memtuples = (void **) repalloc(state->memtuples, state->memtupsize * sizeof(void *)); USEMEM(state, GetMemoryChunkSpace(state->memtuples)); if (LACKMEM(state)) elog(ERROR, "unexpected out-of-memory situation in tuplestore"); } } /* Stash the tuple in the in-memory array */ state->memtuples[state->memtupcount++] = tuple; /* * Done if we still fit in available memory and have array slots. */ if (state->memtupcount < state->memtupsize && !LACKMEM(state)) return; /* * Nope; time to switch to tape-based operation. Make sure that * the temp file(s) are created in suitable temp tablespaces. */ PrepareTempTablespaces(); /* associate the file with the store's resource owner */ oldowner = CurrentResourceOwner; CurrentResourceOwner = state->resowner; char tmpprefix[50]; snprintf(tmpprefix, 50, "slice%d_tuplestore", currentSliceId); state->myfile = BufFileCreateTemp(tmpprefix, state->interXact); CurrentResourceOwner = oldowner; /* * Freeze the decision about whether trailing length words will be * used. We can't change this choice once data is on tape, even * though callers might drop the requirement. */ state->backward = (state->eflags & EXEC_FLAG_BACKWARD) != 0; state->status = TSS_WRITEFILE; dumptuples(state); break; case TSS_WRITEFILE: /* * Update read pointers as needed; see API spec above. Note: * BufFileTell is quite cheap, so not worth trying to avoid * multiple calls. */ readptr = state->readptrs; for (i = 0; i < state->readptrcount; readptr++, i++) { if (readptr->eof_reached && i != state->activeptr) { readptr->eof_reached = false; BufFileTell(state->myfile, &readptr->file, &readptr->offset); } } WRITETUP(state, tuple); break; case TSS_READFILE: /* * Switch from reading to writing. */ if (!state->readptrs[state->activeptr].eof_reached) BufFileTell(state->myfile, &state->readptrs[state->activeptr].file, &state->readptrs[state->activeptr].offset); if (BufFileSeek(state->myfile, state->writepos_file, state->writepos_offset, SEEK_SET) != 0) elog(ERROR, "tuplestore seek to EOF failed"); state->status = TSS_WRITEFILE; /* * Update read pointers as needed; see API spec above. */ readptr = state->readptrs; for (i = 0; i < state->readptrcount; readptr++, i++) { if (readptr->eof_reached && i != state->activeptr) { readptr->eof_reached = false; readptr->file = state->writepos_file; readptr->offset = state->writepos_offset; } } WRITETUP(state, tuple); break; default: elog(ERROR, "invalid tuplestore state"); break; } }
char* CFCPerlTypeMap_to_perl(CFCType *type, const char *cf_var) { const char *type_str = CFCType_to_c(type); char *result = NULL; if (CFCType_is_object(type)) { result = CFCUtil_cat(CFCUtil_strdup(""), "(", cf_var, " == NULL ? newSV(0) : " "XSBind_cfish_to_perl((cfish_Obj*)", cf_var, "))", NULL); } else if (CFCType_is_primitive(type)) { // Convert from a primitive type to a Perl scalar. const char *specifier = CFCType_get_specifier(type); size_t size = 80 + strlen(cf_var) * 2; result = (char*)MALLOCATE(size); if (strcmp(specifier, "double") == 0) { sprintf(result, "newSVnv(%s)", cf_var); } else if (strcmp(specifier, "float") == 0) { sprintf(result, "newSVnv(%s)", cf_var); } else if (strcmp(specifier, "int") == 0) { sprintf(result, "newSViv(%s)", cf_var); } else if (strcmp(specifier, "short") == 0) { sprintf(result, "newSViv(%s)", cf_var); } else if (strcmp(specifier, "long") == 0) { char pattern[] = "((sizeof(long) <= sizeof(IV)) ? " "newSViv((IV)%s) : newSVnv((NV)%s))"; sprintf(result, pattern, cf_var, cf_var); } else if (strcmp(specifier, "size_t") == 0) { sprintf(result, "newSViv(%s)", cf_var); } else if (strcmp(specifier, "uint64_t") == 0) { char pattern[] = "sizeof(UV) == 8 ? newSVuv((UV)%s) : newSVnv((NV)%s)"; sprintf(result, pattern, cf_var, cf_var); } else if (strcmp(specifier, "uint32_t") == 0) { sprintf(result, "newSVuv(%s)", cf_var); } else if (strcmp(specifier, "uint16_t") == 0) { sprintf(result, "newSVuv(%s)", cf_var); } else if (strcmp(specifier, "uint8_t") == 0) { sprintf(result, "newSVuv(%s)", cf_var); } else if (strcmp(specifier, "int64_t") == 0) { char pattern[] = "sizeof(IV) == 8 ? newSViv((IV)%s) : newSVnv((NV)%s)"; sprintf(result, pattern, cf_var, cf_var); } else if (strcmp(specifier, "int32_t") == 0) { sprintf(result, "newSViv(%s)", cf_var); } else if (strcmp(specifier, "int16_t") == 0) { sprintf(result, "newSViv(%s)", cf_var); } else if (strcmp(specifier, "int8_t") == 0) { sprintf(result, "newSViv(%s)", cf_var); } else if (strcmp(specifier, "chy_bool_t") == 0) { sprintf(result, "newSViv(%s)", cf_var); } else { FREEMEM(result); result = NULL; } } else if (CFCType_is_composite(type)) { if (strcmp(type_str, "void*") == 0) { // Assume that void* is a reference SV -- either a hashref or an // arrayref. result = CFCUtil_cat(CFCUtil_strdup(""), "newRV_inc((SV*)", cf_var, ")", NULL); } } return result; }
static int CheckIfAllFilesKnown(TMPQArchive * ha, const char * szListFile, DWORD * pFileKeys) { TMPQHash * pHashTableCopy = NULL; // Copy of the hash table TMPQHash * pHash; TMPQHash * pHashEnd = NULL; // End of the hash table DWORD dwFileCount = 0; int nError = ERROR_SUCCESS; // First of all, create a copy of hash table if(nError == ERROR_SUCCESS) { if((pHashTableCopy = CopyHashTable(ha)) == NULL) nError = ERROR_NOT_ENOUGH_MEMORY; pHashEnd = pHashTableCopy + ha->pHeader->dwHashTableSize; // Notify the user if(CompactCB != NULL) CompactCB(pvUserData, CCB_CHECKING_FILES, &CompactBytesProcessed, &CompactTotalBytes); } // Now check all the files from the listfile if(nError == ERROR_SUCCESS) { SFILE_FIND_DATA wf; HANDLE hFind = SFileFindFirstFile((HANDLE)ha, "*", &wf, szListFile); bool bResult = true; // Do while something has been found while(hFind != NULL && bResult) { TMPQHash * pHash = ha->pHashTable + wf.dwHashIndex; // Find the entry in the hash table copy pHash = pHashTableCopy + (pHash - ha->pHashTable); if(pHash->dwBlockIndex != HASH_ENTRY_FREE) { TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex; DWORD dwFileKey = 0; // Resolve the file key. Use plain file name for it if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED) { const char * szPlainName = GetPlainMpqFileName(wf.cFileName); dwFileKey = DecryptFileKey(szPlainName); if(pBlock->dwFlags & MPQ_FILE_FIX_KEY) dwFileKey = (dwFileKey + pBlock->dwFilePos) ^ pBlock->dwFSize; } // Give the key to the caller pFileKeys[pHash->dwBlockIndex] = dwFileKey; pHash->dwName1 = 0xFFFFFFFF; pHash->dwName2 = 0xFFFFFFFF; pHash->lcLocale = 0xFFFF; pHash->wPlatform = 0xFFFF; pHash->dwBlockIndex = HASH_ENTRY_FREE; } // Find the next file in the archive bResult = SFileFindNextFile(hFind, &wf); } if(hFind != NULL) SFileFindClose(hFind); } // When the filelist checking is complete, parse the hash table copy and find the if(nError == ERROR_SUCCESS) { // Notify the user about checking hash table dwFileCount = 0; if(CompactCB != NULL) CompactCB(pvUserData, CCB_CHECKING_HASH_TABLE, &CompactBytesProcessed, &CompactTotalBytes); for(pHash = pHashTableCopy; pHash < pHashEnd; pHash++) { // If there is an unresolved entry, try to detect its key. If it fails, // we cannot complete the work if(pHash->dwBlockIndex < ha->pHeader->dwBlockTableSize) { HANDLE hFile = NULL; DWORD dwFlags = 0; DWORD dwFileKey = 0; if(SFileOpenFileEx((HANDLE)ha, (char *)(DWORD_PTR)pHash->dwBlockIndex, SFILE_OPEN_BY_INDEX, &hFile)) { TMPQFile * hf = (TMPQFile *)hFile; dwFlags = hf->pBlock->dwFlags; dwFileKey = hf->dwFileKey; SFileCloseFile(hFile); } // If the file is encrypted, we have to check // If we can apply the file decryption key if((dwFlags & MPQ_FILE_ENCRYPTED) && dwFileKey == 0) { nError = ERROR_CAN_NOT_COMPLETE; break; } // Give the key to the caller pFileKeys[pHash->dwBlockIndex] = dwFileKey; } } } // Delete the copy of hash table if(pHashTableCopy != NULL) FREEMEM(pHashTableCopy); return nError; }
char* CFCPerlTypeMap_from_perl(CFCType *type, const char *xs_var) { char *result = NULL; if (CFCType_is_object(type)) { const char *struct_sym = CFCType_get_specifier(type); const char *vtable_var = CFCType_get_vtable_var(type); if (strcmp(struct_sym, "lucy_CharBuf") == 0 || strcmp(struct_sym, "cfish_CharBuf") == 0 || strcmp(struct_sym, "lucy_Obj") == 0 || strcmp(struct_sym, "cfish_Obj") == 0 ) { // Share buffers rather than copy between Perl scalars and // Clownfish string types. result = CFCUtil_cat(CFCUtil_strdup(""), "(", struct_sym, "*)XSBind_sv_to_cfish_obj(", xs_var, ", ", vtable_var, ", alloca(cfish_ZCB_size()))", NULL); } else { result = CFCUtil_cat(CFCUtil_strdup(""), "(", struct_sym, "*)XSBind_sv_to_cfish_obj(", xs_var, ", ", vtable_var, ", NULL)", NULL); } } else if (CFCType_is_primitive(type)) { const char *specifier = CFCType_get_specifier(type); size_t size = 80 + strlen(xs_var) * 2; result = (char*)MALLOCATE(size); if (strcmp(specifier, "double") == 0) { sprintf(result, "SvNV(%s)", xs_var); } else if (strcmp(specifier, "float") == 0) { sprintf(result, "(float)SvNV(%s)", xs_var); } else if (strcmp(specifier, "int") == 0) { sprintf(result, "(int)SvIV(%s)", xs_var); } else if (strcmp(specifier, "short") == 0) { sprintf(result, "(short)SvIV(%s)", xs_var); } else if (strcmp(specifier, "long") == 0) { const char pattern[] = "((sizeof(long) <= sizeof(IV)) ? (long)SvIV(%s) " ": (long)SvNV(%s))"; sprintf(result, pattern, xs_var, xs_var); } else if (strcmp(specifier, "size_t") == 0) { sprintf(result, "(size_t)SvIV(%s)", xs_var); } else if (strcmp(specifier, "uint64_t") == 0) { sprintf(result, "(uint64_t)SvNV(%s)", xs_var); } else if (strcmp(specifier, "uint32_t") == 0) { sprintf(result, "(uint32_t)SvUV(%s)", xs_var); } else if (strcmp(specifier, "uint16_t") == 0) { sprintf(result, "(uint16_t)SvUV(%s)", xs_var); } else if (strcmp(specifier, "uint8_t") == 0) { sprintf(result, "(uint8_t)SvUV(%s)", xs_var); } else if (strcmp(specifier, "int64_t") == 0) { sprintf(result, "(int64_t)SvNV(%s)", xs_var); } else if (strcmp(specifier, "int32_t") == 0) { sprintf(result, "(int32_t)SvIV(%s)", xs_var); } else if (strcmp(specifier, "int16_t") == 0) { sprintf(result, "(int16_t)SvIV(%s)", xs_var); } else if (strcmp(specifier, "int8_t") == 0) { sprintf(result, "(int8_t)SvIV(%s)", xs_var); } else if (strcmp(specifier, "chy_bool_t") == 0) { sprintf(result, "SvTRUE(%s) ? 1 : 0", xs_var); } else { FREEMEM(result); result = NULL; } } return result; }
static int ReallocateBlockTable(TMPQArchive * ha, DWORD dwNewTableSize) { TMPQFileTime * pFileTime; TMPQBlockEx * pExtBlockTable; TMPQBlock * pBlockTable; TMPQMD5 * pMd5; DWORD * pCrc32; // Reallocate the the block table pBlockTable = ALLOCMEM(TMPQBlock, dwNewTableSize); if(pBlockTable == NULL) return ERROR_NOT_ENOUGH_MEMORY; memset(pBlockTable, 0, dwNewTableSize * sizeof(TMPQBlock)); memcpy(pBlockTable, ha->pBlockTable, ha->dwBlockTableMax * sizeof(TMPQBlock)); FREEMEM(ha->pBlockTable); ha->pBlockTable = pBlockTable; // Reallocate the extended block table pExtBlockTable = ALLOCMEM(TMPQBlockEx, dwNewTableSize); if(pExtBlockTable == NULL) return ERROR_NOT_ENOUGH_MEMORY; memset(pExtBlockTable, 0, dwNewTableSize * sizeof(TMPQBlockEx)); memcpy(pExtBlockTable, ha->pExtBlockTable, ha->dwBlockTableMax * sizeof(TMPQBlockEx)); FREEMEM(ha->pExtBlockTable); ha->pExtBlockTable = pExtBlockTable; // We also have to reallocate the (attributes) data if(ha->pAttributes != NULL) { // Reallocate the array of file CRCs pCrc32 = ALLOCMEM(DWORD, dwNewTableSize); if(pCrc32 == NULL) return ERROR_NOT_ENOUGH_MEMORY; memset(pCrc32, 0, dwNewTableSize * sizeof(DWORD)); memcpy(pCrc32, ha->pAttributes->pCrc32, ha->dwBlockTableMax * sizeof(DWORD)); FREEMEM(ha->pAttributes->pCrc32); ha->pAttributes->pCrc32 = pCrc32; // Reallocate the array of file times pFileTime = ALLOCMEM(TMPQFileTime, dwNewTableSize); if(pFileTime == NULL) return ERROR_NOT_ENOUGH_MEMORY; memset(pFileTime, 0, dwNewTableSize * sizeof(TMPQFileTime)); memcpy(pFileTime, ha->pAttributes->pFileTime, ha->dwBlockTableMax * sizeof(TMPQFileTime)); FREEMEM(ha->pAttributes->pFileTime); ha->pAttributes->pFileTime = pFileTime; // Reallocate the array of file MD5 pMd5 = ALLOCMEM(TMPQMD5, dwNewTableSize); if(pMd5 == NULL) return ERROR_NOT_ENOUGH_MEMORY; memset(pMd5, 0, dwNewTableSize * sizeof(TMPQMD5)); memcpy(pMd5, ha->pAttributes->pMd5, ha->dwBlockTableMax * sizeof(TMPQMD5)); FREEMEM(ha->pAttributes->pMd5); ha->pAttributes->pMd5 = pMd5; } // If all succeeded, remember the new size of the tables ha->dwBlockTableMax = dwNewTableSize; return ERROR_SUCCESS; }
/* * The DER encoder of the SET OF type. */ asn_enc_rval_t SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_TYPE_member_t *elm = td->elements; asn_TYPE_descriptor_t *elm_type = elm->type; der_type_encoder_f *der_encoder = elm_type->der_encoder; asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); size_t computed_size = 0; ssize_t encoding_size = 0; struct _el_buffer *encoded_els; ssize_t eels_count = 0; size_t max_encoded_len = 1; asn_enc_rval_t erval; int ret; int edx; ASN_DEBUG("Estimating size for SET OF %s", td->name); /* * Gather the length of the underlying members sequence. */ for(edx = 0; edx < list->count; edx++) { void *memb_ptr = list->array[edx]; if(!memb_ptr) continue; erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0); if(erval.encoded == -1) return erval; computed_size += erval.encoded; /* Compute maximum encoding's size */ if(max_encoded_len < (size_t)erval.encoded) max_encoded_len = erval.encoded; } /* * Encode the TLV for the sequence itself. */ encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key); if(encoding_size == -1) { erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; return erval; } computed_size += encoding_size; if(!cb || list->count == 0) { erval.encoded = computed_size; ASN__ENCODED_OK(erval); } /* * DER mandates dynamic sorting of the SET OF elements * according to their encodings. Build an array of the * encoded elements. */ encoded_els = (struct _el_buffer *)MALLOC( list->count * sizeof(encoded_els[0])); if(encoded_els == NULL) { erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; return erval; } ASN_DEBUG("Encoding members of %s SET OF", td->name); /* * Encode all members. */ for(edx = 0; edx < list->count; edx++) { void *memb_ptr = list->array[edx]; struct _el_buffer *encoded_el = &encoded_els[eels_count]; if(!memb_ptr) continue; /* * Prepare space for encoding. */ encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len); if(encoded_el->buf) { encoded_el->length = 0; encoded_el->size = max_encoded_len; } else { for(edx--; edx >= 0; edx--) FREEMEM(encoded_els[edx].buf); FREEMEM(encoded_els); erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; return erval; } /* * Encode the member into the prepared space. */ erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, _el_addbytes, encoded_el); if(erval.encoded == -1) { for(; edx >= 0; edx--) FREEMEM(encoded_els[edx].buf); FREEMEM(encoded_els); return erval; } encoding_size += erval.encoded; eels_count++; } /* * Sort the encoded elements according to their encoding. */ qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp); /* * Report encoded elements to the application. * Dispose of temporary sorted members table. */ ret = 0; for(edx = 0; edx < eels_count; edx++) { struct _el_buffer *encoded_el = &encoded_els[edx]; /* Report encoded chunks to the application */ if(ret == 0 && cb(encoded_el->buf, encoded_el->length, app_key) < 0) ret = -1; FREEMEM(encoded_el->buf); } FREEMEM(encoded_els); if(ret || computed_size != (size_t)encoding_size) { /* * Standard callback failed, or * encoded size is not equal to the computed size. */ erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; } else { erval.encoded = computed_size; } ASN__ENCODED_OK(erval); }
void BitVec_Destroy_IMP(BitVector* self) { BitVectorIVARS *const ivars = BitVec_IVARS(self); FREEMEM(ivars->bits); SUPER_DESTROY(self, BITVECTOR); }
asn_enc_rval_t SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, int ilevel, enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb, void *app_key) { asn_enc_rval_t er; asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; asn_TYPE_member_t *elm = td->elements; asn_anonymous_set_ *list = _A_SET_FROM_VOID(sptr); const char *mname = specs->as_XMLValueList ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag); size_t mlen = mname ? strlen(mname) : 0; int xcan = (flags & XER_F_CANONICAL); xer_tmp_enc_t *encs = 0; size_t encs_count = 0; void *original_app_key = app_key; asn_app_consume_bytes_f *original_cb = cb; int i; if(!sptr) ASN__ENCODE_FAILED; if(xcan) { encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0])); if(!encs) ASN__ENCODE_FAILED; cb = SET_OF_encode_xer_callback; } er.encoded = 0; for(i = 0; i < list->count; i++) { asn_enc_rval_t tmper; void *memb_ptr = list->array[i]; if(!memb_ptr) continue; if(encs) { memset(&encs[encs_count], 0, sizeof(encs[0])); app_key = &encs[encs_count]; encs_count++; } if(mname) { if(!xcan) ASN__TEXT_INDENT(1, ilevel); ASN__CALLBACK3("<", 1, mname, mlen, ">", 1); } if(!xcan && specs->as_XMLValueList == 1) ASN__TEXT_INDENT(1, ilevel + 1); tmper = elm->type->xer_encoder(elm->type, memb_ptr, ilevel + (specs->as_XMLValueList != 2), flags, cb, app_key); if(tmper.encoded == -1) { td = tmper.failed_type; sptr = tmper.structure_ptr; goto cb_failed; } if(tmper.encoded == 0 && specs->as_XMLValueList) { const char *name = elm->type->xml_tag; size_t len = strlen(name); ASN__CALLBACK3("<", 1, name, len, "/>", 2); } if(mname) { ASN__CALLBACK3("</", 2, mname, mlen, ">", 1); er.encoded += 5; } er.encoded += (2 * mlen) + tmper.encoded; } if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1); if(encs) { xer_tmp_enc_t *enc = encs; xer_tmp_enc_t *end = encs + encs_count; ssize_t control_size = 0; cb = original_cb; app_key = original_app_key; qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order); for(; enc < end; enc++) { ASN__CALLBACK(enc->buffer, enc->offset); FREEMEM(enc->buffer); enc->buffer = 0; control_size += enc->offset; } assert(control_size == er.encoded); } goto cleanup; cb_failed: er.encoded = -1; er.failed_type = td; er.structure_ptr = sptr; cleanup: if(encs) { while(encs_count-- > 0) { if(encs[encs_count].buffer) FREEMEM(encs[encs_count].buffer); } FREEMEM(encs); } ASN__ENCODED_OK(er); }
enum xer_equivalence_e xer_equivalent(const struct asn_TYPE_descriptor_s *td, const void *struct1, const void *struct2, FILE *opt_debug_stream) { struct xer_buffer xb1 = {0, 0, 0}; struct xer_buffer xb2 = {0, 0, 0}; asn_enc_rval_t e1, e2; asn_dec_rval_t rval; void *sptr = NULL; if(!td || !struct1 || !struct2) { if(opt_debug_stream) { if(!td) fprintf(opt_debug_stream, "Type descriptor missing\n"); if(!struct1) fprintf(opt_debug_stream, "Structure 1 missing\n"); if(!struct2) fprintf(opt_debug_stream, "Structure 2 missing\n"); } return XEQ_FAILURE; } e1 = xer_encode(td, struct1, XER_F_BASIC, xer__buffer_append, &xb1); if(e1.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of %s failed\n", td->name); } FREEMEM(xb1.buffer); return XEQ_ENCODE1_FAILED; } e2 = xer_encode(td, struct2, XER_F_BASIC, xer__buffer_append, &xb2); if(e2.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of %s failed\n", td->name); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ENCODE1_FAILED; } if(xb1.buffer_size != xb2.buffer_size || memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) { if(opt_debug_stream) { fprintf(opt_debug_stream, "Structures XER-encoded into different byte streams:\n=== " "Structure 1 ===\n%s\n=== Structure 2 ===\n%s\n", xb1.buffer, xb2.buffer); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_DIFFERENT; } else { if(opt_debug_stream) { fprintf(opt_debug_stream, "Both structures encoded into the same XER byte stream " "of size %" ASN_PRI_SIZE ":\n%s", xb1.buffer_size, xb1.buffer); } } rval = xer_decode(NULL, td, (void **)&sptr, xb1.buffer, xb1.buffer_size); switch(rval.code) { case RC_OK: break; case RC_WMORE: if(opt_debug_stream) { fprintf(opt_debug_stream, "Structure %s XER decode unexpectedly requires " "more data:\n%s\n", td->name, xb1.buffer); } /* Fall through */ case RC_FAIL: default: if(opt_debug_stream) { fprintf(opt_debug_stream, "Structure %s XER decoding resulted in failure.\n", td->name); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_DECODE_FAILED; } if(rval.consumed != xb1.buffer_size && ((rval.consumed > xb1.buffer_size) || xer_whitespace_span(xb1.buffer + rval.consumed, xb1.buffer_size - rval.consumed) != (xb1.buffer_size - rval.consumed))) { if(opt_debug_stream) { fprintf(opt_debug_stream, "Round-trip decode of %s required less bytes (%" ASN_PRI_SIZE ") than " "encoded (%" ASN_PRI_SIZE ")\n", td->name, rval.consumed, xb1.buffer_size); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } /* * Reuse xb2 to encode newly decoded structure. */ FREEMEM(xb2.buffer); memset(&xb2, 0, sizeof(xb2)); e2 = xer_encode(td, sptr, XER_F_BASIC, xer__buffer_append, &xb2); if(e2.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of round-trip decode of %s failed\n", td->name); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } ASN_STRUCT_FREE(*td, sptr); sptr = 0; if(xb1.buffer_size != xb2.buffer_size || memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) { if(opt_debug_stream) { fprintf(opt_debug_stream, "XER Encoding of round-trip decode of %s resulted in " "different byte stream:\n" "=== Original ===\n%s\n" "=== Round-tripped ===\n%s\n", xb1.buffer, xb2.buffer, td->name); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_SUCCESS; }
static asn_dec_rval_t uper_open_type_get_simple(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td, const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { asn_dec_rval_t rv; ssize_t chunk_bytes; int repeat; uint8_t *buf = 0; size_t bufLen = 0; size_t bufSize = 0; asn_per_data_t spd; size_t padding; ASN__STACK_OVERFLOW_CHECK(ctx); ASN_DEBUG("Getting open type %s...", td->name); do { chunk_bytes = uper_get_length(pd, -1, 0, &repeat); if(chunk_bytes < 0) { FREEMEM(buf); ASN__DECODE_STARVED; } if(bufLen + chunk_bytes > bufSize) { void *ptr; bufSize = chunk_bytes + (bufSize << 2); ptr = REALLOC(buf, bufSize); if(!ptr) { FREEMEM(buf); ASN__DECODE_FAILED; } buf = ptr; } if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) { FREEMEM(buf); ASN__DECODE_STARVED; } bufLen += chunk_bytes; } while(repeat); ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name, (long)bufLen); memset(&spd, 0, sizeof(spd)); spd.buffer = buf; spd.nbits = bufLen << 3; ASN_DEBUG_INDENT_ADD(+4); rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd); ASN_DEBUG_INDENT_ADD(-4); if(rv.code == RC_OK) { /* Check padding validity */ padding = spd.nbits - spd.nboff; if ((padding < 8 || /* X.691#10.1.3 */ (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) && per_get_few_bits(&spd, padding) == 0) { /* Everything is cool */ FREEMEM(buf); return rv; } FREEMEM(buf); if(padding >= 8) { ASN_DEBUG("Too large padding %d in open type", (int)padding); ASN__DECODE_FAILED; } else { ASN_DEBUG("Non-zero padding"); ASN__DECODE_FAILED; } } else { FREEMEM(buf); /* rv.code could be RC_WMORE, nonsense in this context */ rv.code = RC_FAIL; /* Noone would give us more */ } return rv; }
// hf - MPQ File handle. // pbBuffer - Pointer to target buffer to store sectors. // dwByteOffset - Position of sector in the file (relative to file begin) // dwBytesToRead - Number of bytes to read. Must be multiplier of sector size. // pdwBytesRead - Stored number of bytes loaded static int ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, DWORD dwBytesToRead, LPDWORD pdwBytesRead) { ULONGLONG RawFilePos; TMPQArchive * ha = hf->ha; TFileEntry * pFileEntry = hf->pFileEntry; LPBYTE pbRawSector = NULL; LPBYTE pbOutSector = pbBuffer; LPBYTE pbInSector = pbBuffer; DWORD dwRawBytesToRead; DWORD dwRawSectorOffset = dwByteOffset; DWORD dwSectorsToRead = dwBytesToRead / ha->dwSectorSize; DWORD dwSectorIndex = dwByteOffset / ha->dwSectorSize; DWORD dwSectorsDone = 0; DWORD dwBytesRead = 0; int nError = ERROR_SUCCESS; // Note that dwByteOffset must be aligned to size of one sector // Note that dwBytesToRead must be a multiplier of one sector size // This is local function, so we won't check if that's true. // Note that files stored in single units are processed by a separate function // If there is not enough bytes remaining, cut dwBytesToRead if ((dwByteOffset + dwBytesToRead) > hf->dwDataSize) dwBytesToRead = hf->dwDataSize - dwByteOffset; dwRawBytesToRead = dwBytesToRead; // Perform all necessary work to do with compressed files if (pFileEntry->dwFlags & MPQ_FILE_COMPRESSED) { // If the sector positions are not loaded yet, do it if (hf->SectorOffsets == NULL) { nError = AllocateSectorOffsets(hf, true); if (nError != ERROR_SUCCESS) return nError; } // If the sector checksums are not loaded yet, load them now. if (hf->SectorChksums == NULL && (pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC)) { nError = AllocateSectorChecksums(hf, true); if (nError != ERROR_SUCCESS) return nError; } // If the file is compressed, also allocate secondary buffer pbInSector = pbRawSector = ALLOCMEM(BYTE, dwBytesToRead); if (pbRawSector == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Assign the temporary buffer as target for read operation dwRawSectorOffset = hf->SectorOffsets[dwSectorIndex]; dwRawBytesToRead = hf->SectorOffsets[dwSectorIndex + dwSectorsToRead] - dwRawSectorOffset; } // Calculate raw file offset where the sector(s) are stored. CalculateRawSectorOffset(RawFilePos, hf, dwRawSectorOffset); // Set file pointer and read all required sectors if (!FileStream_Read(ha->pStream, &RawFilePos, pbInSector, dwRawBytesToRead)) return GetLastError(); dwBytesRead = 0; // Now we have to decrypt and decompress all file sectors that have been loaded for (DWORD i = 0; i < dwSectorsToRead; i++) { DWORD dwRawBytesInThisSector = ha->dwSectorSize; DWORD dwBytesInThisSector = ha->dwSectorSize; DWORD dwIndex = dwSectorIndex + i; // If there is not enough bytes in the last sector, // cut the number of bytes in this sector if (dwRawBytesInThisSector > dwBytesToRead) dwRawBytesInThisSector = dwBytesToRead; if (dwBytesInThisSector > dwBytesToRead) dwBytesInThisSector = dwBytesToRead; // If the file is compressed, we have to adjust the raw sector size if (pFileEntry->dwFlags & MPQ_FILE_COMPRESSED) dwRawBytesInThisSector = hf->SectorOffsets[dwIndex + 1] - hf->SectorOffsets[dwIndex]; // If the file is encrypted, we have to decrypt the sector if (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) { BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector); // If we don't know the key, try to detect it by file content if (hf->dwFileKey == 0) { hf->dwFileKey = DetectFileKeyByContent(pbInSector, dwBytesInThisSector); if (hf->dwFileKey == 0) { nError = ERROR_UNKNOWN_FILE_KEY; break; } } DecryptMpqBlock(pbInSector, dwRawBytesInThisSector, hf->dwFileKey + dwIndex); BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector); } // If the file has sector CRC check turned on, perform it if (hf->bCheckSectorCRCs && hf->SectorChksums != NULL) { DWORD dwAdlerExpected = hf->SectorChksums[dwIndex]; DWORD dwAdlerValue = 0; // We can only check sector CRC when it's not zero // Neither can we check it if it's 0xFFFFFFFF. if (dwAdlerExpected != 0 && dwAdlerExpected != 0xFFFFFFFF) { dwAdlerValue = adler32(0, pbInSector, dwRawBytesInThisSector); if (dwAdlerValue != dwAdlerExpected) { nError = ERROR_CHECKSUM_ERROR; break; } } } // If the sector is really compressed, decompress it. // WARNING : Some sectors may not be compressed, it can be determined only // by comparing uncompressed and compressed size !!! if (dwRawBytesInThisSector < dwBytesInThisSector) { int cbOutSector = dwBytesInThisSector; int cbInSector = dwRawBytesInThisSector; int nResult = 0; // Is the file compressed by PKWARE Data Compression Library ? if (pFileEntry->dwFlags & MPQ_FILE_IMPLODE) nResult = SCompExplode((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector); // Is the file compressed by Blizzard's multiple compression ? if (pFileEntry->dwFlags & MPQ_FILE_COMPRESS) nResult = SCompDecompress((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector); // Did the decompression fail ? if (nResult == 0) { nError = ERROR_FILE_CORRUPT; break; } } else { if (pbOutSector != pbInSector) memcpy(pbOutSector, pbInSector, dwBytesInThisSector); } // Move pointers dwBytesToRead -= dwBytesInThisSector; dwByteOffset += dwBytesInThisSector; dwBytesRead += dwBytesInThisSector; pbOutSector += dwBytesInThisSector; pbInSector += dwRawBytesInThisSector; dwSectorsDone++; } // Free all used buffers if (pbRawSector != NULL) FREEMEM(pbRawSector); // Give the caller thenumber of bytes read *pdwBytesRead = dwBytesRead; return nError; }
int rdsilogrid( void ) { char *me = "rdsilogrid"; char msg[MAXLINE]; char op[MAXLINE]; char name[MAXLINE]; int i; int gblk; int nlocaldom; int error; int *localdom; DBfile *idbid; Extents_t ext; geta(op); if (genmd != 1) { sprintf(msg, "Attempting to read silo mesh before memory has been allocated.\n\t\tAre you in merge phase?\n\t\t Did you forget the -sew on the command line?"); ctlerror(me,msg); } comlock(dmp_nbaton); idbid = DBOpen (op, DB_PDB, DB_READ); if (idbid == NULL) { sprintf(msg,"Cannot open silo file %s.\n",op); ctlerror(me,msg); } decomp_setdir(idbid); decomp_read(idbid, name, 0, 0); error = DBSetDir(idbid,"/"); DBShowErrors(DB_NONE, NULL); error = DBSetDir(idbid,"/Global/Nodelists"); if (error != 0) error = DBSetDir(idbid,"Nodelists"); if (error == 0) { NodeList_rdsilo(idbid,0); } DBShowErrors(DB_TOP, NULL); error = DBSetDir(idbid,"/"); nlocaldom = 0; localdom = MALLOT(int,gnblk); for (gblk = 0; gblk < gnblk; gblk++) { if (gmap[gblk].lblk >= 0) { localdom[nlocaldom++] = gblk; } } calculate_mappings(); for (i = 0; i < nlocaldom; i++) { gblk = localdom[i]; if (gmap[gblk].proc == myid) { sprintf(op,"/%s%i",name,i); error = DBSetDir(idbid,op); TRSEXT(domains[nblk],gmap[gblk],gmap[gblk]); if (ndims == 2) { domains[nblk].kmin = 0; domains[nblk].kmax = 0; domains[nblk].type = QUAD2D; } else { domains[nblk].type = HEX3D; } domains[nblk].sclnamix = sclnamix; initblk(nblk,&domains[nblk]); domains[nblk].gblk = gblk; domain_hash_tbl_rgst(&(domains[nblk])); CPYEXT(ext,domains[nblk]); rdsilomesh(idbid, "hydro_mesh", domains[nblk].x, domains[nblk].y, domains[nblk].z, domains[nblk].node, ext, domains[nblk].jp, domains[nblk].kp); nblk++; error = DBSetDir(idbid,"/"); } } FREEMEM(localdom); DBClose(idbid); comunlock(dmp_nbaton); if (ifparallel) { bndry_init(); initcom( NULL, 0); varcom_bufinit(); } return(0); }
void CFCPerlPod_set_synopsis(CFCPerlPod *self, const char *synopsis) { FREEMEM(self->synopsis); self->synopsis = CFCUtil_strdup(synopsis); }
static int ApplyMpqPatch_BSD0( TMPQFile * hf, TPatchHeader * pPatchHeader) { PBLIZZARD_BSDIFF40_FILE pBsdiff; LPDWORD pCtrlBlock; LPBYTE pbPatchData = (LPBYTE)pPatchHeader + sizeof(TPatchHeader); LPBYTE pDataBlock; LPBYTE pExtraBlock; LPBYTE pbNewData = NULL; LPBYTE pbOldData = (LPBYTE)hf->pbFileData; DWORD dwNewOffset = 0; // Current position to patch DWORD dwOldOffset = 0; // Current source position DWORD dwNewSize; // Patched file size DWORD dwOldSize = hf->cbFileData; // File size before patch // Get pointer to the patch header // Format of BSDIFF header corresponds to original BSDIFF, which is: // 0000 8 bytes signature "BSDIFF40" // 0008 8 bytes size of the control block // 0010 8 bytes size of the data block // 0018 8 bytes new size of the patched file pBsdiff = (PBLIZZARD_BSDIFF40_FILE)pbPatchData; pbPatchData += sizeof(BLIZZARD_BSDIFF40_FILE); // Get pointer to the 32-bit BSDIFF control block // The control block follows immediately after the BSDIFF header // and consists of three 32-bit integers // 0000 4 bytes Length to copy from the BSDIFF data block the new file // 0004 4 bytes Length to copy from the BSDIFF extra block // 0008 4 bytes Size to increment source file offset pCtrlBlock = (LPDWORD)pbPatchData; pbPatchData += (size_t)BSWAP_INT64_UNSIGNED(pBsdiff->CtrlBlockSize); // Get the pointer to the data block pDataBlock = (LPBYTE)pbPatchData; pbPatchData += (size_t)BSWAP_INT64_UNSIGNED(pBsdiff->DataBlockSize); // Get the pointer to the extra block pExtraBlock = (LPBYTE)pbPatchData; dwNewSize = (DWORD)BSWAP_INT64_UNSIGNED(pBsdiff->NewFileSize); // Allocate new buffer pbNewData = ALLOCMEM(BYTE, dwNewSize); if (pbNewData == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Now patch the file while(dwNewOffset < dwNewSize) { DWORD dwAddDataLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[0]); DWORD dwMovDataLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[1]); DWORD dwOldMoveLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[2]); DWORD i; // Sanity check if ((dwNewOffset + dwAddDataLength) > dwNewSize) { FREEMEM(pbNewData); return ERROR_FILE_CORRUPT; } // Read the diff string to the target buffer memcpy(pbNewData + dwNewOffset, pDataBlock, dwAddDataLength); pDataBlock += dwAddDataLength; // Now combine the patch data with the original file for(i = 0; i < dwAddDataLength; i++) { if (dwOldOffset < dwOldSize) pbNewData[dwNewOffset] = pbNewData[dwNewOffset] + pbOldData[dwOldOffset]; dwNewOffset++; dwOldOffset++; } // Sanity check if ((dwNewOffset + dwMovDataLength) > dwNewSize) { FREEMEM(pbNewData); return ERROR_FILE_CORRUPT; } // Copy the data from the extra block in BSDIFF patch memcpy(pbNewData + dwNewOffset, pExtraBlock, dwMovDataLength); pExtraBlock += dwMovDataLength; dwNewOffset += dwMovDataLength; // Move the old offset if (dwOldMoveLength & 0x80000000) dwOldMoveLength = 0x80000000 - dwOldMoveLength; dwOldOffset += dwOldMoveLength; pCtrlBlock += 3; } // Free the old file data FREEMEM(hf->pbFileData); // Put the new data to the fil structure hf->pbFileData = pbNewData; hf->cbFileData = dwNewSize; return ERROR_SUCCESS; }