Пример #1
0
void
BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
	if(td && ptr && !contents_only) {
		FREEMEM(ptr);
	}
}
Пример #2
0
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;
}
Пример #3
0
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);
}
Пример #4
0
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);
}
Пример #5
0
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;
}
Пример #6
0
/*
 * 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 */
	}
}
Пример #7
0
// 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;
}
Пример #8
0
// 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;
}
Пример #9
0
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) ;
}
Пример #10
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);
}
Пример #11
0
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);
}
Пример #12
0
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);
}
Пример #13
0
void
CFCPrereq_destroy(CFCPrereq *self) {
    FREEMEM(self->name);
    CFCBase_decref((CFCBase*)self->version);
    CFCBase_destroy((CFCBase*)self);
}
Пример #14
0
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;
}
Пример #15
0
/*
 * 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;
	}
}
Пример #16
0
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;
}
Пример #17
0
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;
	}
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
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;
}
Пример #22
0
/*
 * 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);
}
Пример #23
0
void
BitVec_Destroy_IMP(BitVector* self) {
    BitVectorIVARS *const ivars = BitVec_IVARS(self);
    FREEMEM(ivars->bits);
    SUPER_DESTROY(self, BITVECTOR);
}
Пример #24
0
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);
}
Пример #25
0
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;
}
Пример #26
0
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;
}
Пример #27
0
//  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;
}
Пример #28
0
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);
}
Пример #29
0
void
CFCPerlPod_set_synopsis(CFCPerlPod *self, const char *synopsis) {
    FREEMEM(self->synopsis);
    self->synopsis = CFCUtil_strdup(synopsis);
}
Пример #30
0
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;
}