📄 sfilecreatearchiveex.cpp.svn-base
字号:
// Cleanup : If an error, delete all buffers and return
if(nError != ERROR_SUCCESS)
{
FreeMPQArchive(ha);
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
SetLastError(nError);
}
// Return the values
*phMPQ = (HANDLE)ha;
return (nError == ERROR_SUCCESS);
}
//-----------------------------------------------------------------------------
// Changes locale ID of a file
// TODO: Test for archives > 4GB
BOOL WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale)
{
TMPQFile * hf = (TMPQFile *)hFile;
// Invalid handle => do nothing
if(IsValidFileHandle(hf) == FALSE || IsValidMpqHandle(hf->ha) == FALSE)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// If the file has not been open for writing, do nothing.
if(hf->ha->pListFile == NULL)
return ERROR_ACCESS_DENIED;
hf->pHash->lcLocale = (USHORT)lcNewLocale;
hf->ha->dwFlags |= MPQ_FLAG_CHANGED;
return TRUE;
}
//-----------------------------------------------------------------------------
// Adds a file into the archive
// TODO: Test for archives > 4GB
BOOL WINAPI SFileAddFileEx(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality, int nFileType)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
HANDLE hFile = INVALID_HANDLE_VALUE;
BOOL bReplaced = FALSE; // TRUE if replacing file in the archive
int nError = ERROR_SUCCESS;
if(nError == ERROR_SUCCESS)
{
// Check valid parameters
if(IsValidMpqHandle(ha) == FALSE || szFileName == NULL || *szFileName == 0 || szArchivedName == NULL || *szArchivedName == 0)
nError = ERROR_INVALID_PARAMETER;
// Check the values of dwFlags
if((dwFlags & MPQ_FILE_COMPRESS_PKWARE) && (dwFlags & MPQ_FILE_COMPRESS_MULTI))
nError = ERROR_INVALID_PARAMETER;
}
// If anyone is trying to add listfile, and the archive already has a listfile,
// deny the operation, but return success.
if(nError == ERROR_SUCCESS)
{
if(ha->pListFile != NULL && !_stricmp(szFileName, LISTFILE_NAME))
return ERROR_SUCCESS;
}
// Open added file
if(nError == ERROR_SUCCESS)
{
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
nError = GetLastError();
}
if(nError == ERROR_SUCCESS)
nError = AddFileToArchive(ha, hFile, szArchivedName, dwFlags, dwQuality, nFileType, &bReplaced);
// Add the file into listfile also
if(nError == ERROR_SUCCESS && bReplaced == FALSE)
nError = SListFileAddNode(ha, szArchivedName);
// Cleanup and exit
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
// Adds a data file into the archive
// TODO: Test for archives > 4GB
BOOL WINAPI SFileAddFile(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags)
{
return SFileAddFileEx(hMPQ, szFileName, szArchivedName, dwFlags, 0, SFILE_TYPE_DATA);
}
// Adds a WAVE file into the archive
// TODO: Test for archives > 4GB
BOOL WINAPI SFileAddWave(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality)
{
return SFileAddFileEx(hMPQ, szFileName, szArchivedName, dwFlags, dwQuality, SFILE_TYPE_WAVE);
}
//-----------------------------------------------------------------------------
// BOOL SFileRemoveFile(HANDLE hMPQ, char * szFileName)
//
// This function removes a file from the archive. The file content
// remains there, only the entries in the hash table and in the block
// table are updated.
// TODO: Test for archives > 4GB
BOOL WINAPI SFileRemoveFile(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
TMPQBlockEx * pBlockEx = NULL; // Block entry of deleted file
TMPQBlock * pBlock = NULL; // Block entry of deleted file
TMPQHash * pHash = NULL; // Hash entry of deleted file
DWORD dwBlockIndex = 0;
int nError = ERROR_SUCCESS;
// Check the parameters
if(nError == ERROR_SUCCESS)
{
if(IsValidMpqHandle(ha) == FALSE)
nError = ERROR_INVALID_PARAMETER;
if(dwSearchScope != SFILE_OPEN_BY_INDEX && *szFileName == 0)
nError = ERROR_INVALID_PARAMETER;
}
// Do not allow to remove listfile
if(nError == ERROR_SUCCESS)
{
if(dwSearchScope != SFILE_OPEN_BY_INDEX && !_stricmp(szFileName, LISTFILE_NAME))
nError = ERROR_ACCESS_DENIED;
}
// Get hash entry belonging to this file
if(nError == ERROR_SUCCESS)
{
if((pHash = GetHashEntryEx(ha, (char *)szFileName, lcLocale)) == NULL)
nError = ERROR_FILE_NOT_FOUND;
}
// If index was not found, or is greater than number of files, exit.
if(nError == ERROR_SUCCESS)
{
if((dwBlockIndex = pHash->dwBlockIndex) > ha->pHeader->dwBlockTableSize)
nError = ERROR_FILE_NOT_FOUND;
}
// Get block and test if the file is not already deleted
if(nError == ERROR_SUCCESS)
{
pBlockEx = ha->pExtBlockTable + dwBlockIndex;
pBlock = ha->pBlockTable + dwBlockIndex;
if((pBlock->dwFlags & MPQ_FILE_EXISTS) == 0)
nError = ERROR_FILE_NOT_FOUND;
}
// Now invalidate the block entry and the hash entry. Do not make any
// relocations and file copying, use SFileCompactArchive for it.
if(nError == ERROR_SUCCESS)
{
pBlockEx->wFilePosHigh = 0;
pBlock->dwFilePos = 0;
pBlock->dwFSize = 0;
pBlock->dwCSize = 0;
pBlock->dwFlags = 0;
pHash->dwName1 = 0xFFFFFFFF;
pHash->dwName2 = 0xFFFFFFFF;
pHash->lcLocale = 0xFFFF;
pHash->wPlatform = 0xFFFF;
pHash->dwBlockIndex = HASH_ENTRY_DELETED;
// Update MPQ archive
ha->dwFlags |= MPQ_FLAG_CHANGED;
}
// Remove the file from the list file
if(nError == ERROR_SUCCESS && lcLocale == LANG_NEUTRAL)
nError = SListFileRemoveNode(ha, szFileName);
// Resolve error and exit
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
// Renames the file within the archive.
// TODO: Test for archives > 4GB
BOOL WINAPI SFileRenameFile(HANDLE hMPQ, const char * szFileName, const char * szNewFileName)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
TMPQHash * pOldHash = NULL; // Hash entry for the original file
TMPQHash * pNewHash = NULL; // Hash entry for the renamed file
DWORD dwBlockIndex = 0;
int nError = ERROR_SUCCESS;
// Test the valid parameters
if(nError == ERROR_SUCCESS)
{
if(hMPQ == NULL || szNewFileName == NULL || *szNewFileName == 0)
nError = ERROR_INVALID_PARAMETER;
if(szFileName == NULL || *szFileName == 0)
nError = ERROR_INVALID_PARAMETER;
}
// Do not allow to rename listfile
if(nError == ERROR_SUCCESS)
{
if(!_stricmp(szFileName, LISTFILE_NAME))
nError = ERROR_ACCESS_DENIED;
}
// Test if the file already exists in the archive
if(nError == ERROR_SUCCESS)
{
if((pNewHash = GetHashEntryEx(ha, szNewFileName, lcLocale)) != NULL)
nError = ERROR_ALREADY_EXISTS;
}
// Get the hash table entry for the original file
if(nError == ERROR_SUCCESS)
{
if((pOldHash = GetHashEntryEx(ha, szFileName, lcLocale)) == NULL)
nError = ERROR_FILE_NOT_FOUND;
}
// Get the hash table entry for the renamed file
if(nError == ERROR_SUCCESS)
{
// Save block table index and remove the hash table entry
dwBlockIndex = pOldHash->dwBlockIndex;
pOldHash->dwName1 = 0xFFFFFFFF;
pOldHash->dwName2 = 0xFFFFFFFF;
pOldHash->lcLocale = 0xFFFF;
pOldHash->wPlatform = 0xFFFF;
pOldHash->dwBlockIndex = HASH_ENTRY_DELETED;
if((pNewHash = FindFreeHashEntry(ha, szNewFileName)) == NULL)
nError = ERROR_CAN_NOT_COMPLETE;
}
// Save the block index and clear the hash entry
if(nError == ERROR_SUCCESS)
{
// Copy the block table index
pNewHash->dwBlockIndex = dwBlockIndex;
ha->dwFlags |= MPQ_FLAG_CHANGED;
}
// Rename the file in the list file
if(nError == ERROR_SUCCESS)
nError = SListFileRenameNode(ha, szFileName, szNewFileName);
// Resolve error and return
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -