Ejemplo n.º 1
0
BOOL WINAPI SFileGetFileName_stub(MPQHANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength)
{
	LoadSFMpqDll();
	if (hSFMpq) {
		*(FARPROC *)&SFileGetFileName = GetProcAddress(hSFMpq,"SFileGetFileName");
		if (SFileGetFileName) return SFileGetFileName(hFile,lpBuffer,dwBufferLength);
	}
	return FALSE;
}
Ejemplo n.º 2
0
static bool DoMPQSearch_FileEntry(
    TMPQSearch * hs,
    SFILE_FIND_DATA * lpFindFileData,
    TMPQArchive * ha,
    TMPQHash * pHashEntry,
    TFileEntry * pFileEntry)
{
    TFileEntry * pPatchEntry;
    HANDLE hFile = NULL;
    const char * szFileName;
    size_t nPrefixLength = (ha->pPatchPrefix != NULL) ? ha->pPatchPrefix->nLength : 0;
    DWORD dwBlockIndex;
    char szNameBuff[MAX_PATH];

    // Is it a file but not a patch file?
    if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
    {
        // Now we have to check if this file was not enumerated before
        if(!FileWasFoundBefore(ha, hs, pFileEntry))
        {
//          if(pFileEntry != NULL && !_stricmp(pFileEntry->szFileName, "TriggerLibs\\NativeLib.galaxy"))
//              DebugBreak();

            // Find a patch to this file
            pPatchEntry = FindPatchEntry(ha, pFileEntry);
            if(pPatchEntry == NULL)
                pPatchEntry = pFileEntry;

            // Prepare the block index
            dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);

            // Get the file name. If it's not known, we will create pseudo-name
            szFileName = pFileEntry->szFileName;
            if(szFileName == NULL)
            {
                // Open the file by its pseudo-name.
                sprintf(szNameBuff, "File%08u.xxx", (unsigned int)dwBlockIndex);
                if(SFileOpenFileEx((HANDLE)hs->ha, szNameBuff, SFILE_OPEN_BASE_FILE, &hFile))
                {
                    SFileGetFileName(hFile, szNameBuff);
                    szFileName = szNameBuff;
                    SFileCloseFile(hFile);
                }
            }

            // If the file name is still NULL, we cannot include the file to search results
            if(szFileName != NULL)
            {
                // Check the file name against the wildcard
                if(CheckWildCard(szFileName + nPrefixLength, hs->szSearchMask))
                {
                    // Fill the found entry. hash entry and block index are taken from the base MPQ
                    lpFindFileData->dwHashIndex  = HASH_ENTRY_FREE;
                    lpFindFileData->dwBlockIndex = dwBlockIndex;
                    lpFindFileData->dwFileSize   = pPatchEntry->dwFileSize;
                    lpFindFileData->dwFileFlags  = pPatchEntry->dwFlags;
                    lpFindFileData->dwCompSize   = pPatchEntry->dwCmpSize;
                    lpFindFileData->lcLocale     = 0;   // pPatchEntry->lcLocale;

                    // Fill the filetime
                    lpFindFileData->dwFileTimeHi = (DWORD)(pPatchEntry->FileTime >> 32);
                    lpFindFileData->dwFileTimeLo = (DWORD)(pPatchEntry->FileTime);

                    // Fill-in the entries from hash table entry, if given
                    if(pHashEntry != NULL)
                    {
                        lpFindFileData->dwHashIndex = (DWORD)(pHashEntry - ha->pHashTable);
                        lpFindFileData->lcLocale = pHashEntry->lcLocale;
                    }

                    // Fill the file name and plain file name
                    StringCopyA(lpFindFileData->cFileName, szFileName + nPrefixLength, MAX_PATH-1);
                    lpFindFileData->szPlainName = (char *)GetPlainFileName(lpFindFileData->cFileName);
                    return true;
                }
            }
        }
Ejemplo n.º 3
0
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile)
{
    TMPQArchive * ha = (TMPQArchive *)hMpq;
    TFileEntry  * pFileEntry = NULL;
    TMPQFile    * hf = NULL;
    DWORD dwBlockIndex = 0;             // Found table index
    int nError = ERROR_SUCCESS;

    // Don't accept NULL pointer to file handle
    if (phFile == NULL)
        nError = ERROR_INVALID_PARAMETER;

    // Prepare the file opening
    if (nError == ERROR_SUCCESS)
    {
        switch(dwSearchScope)
        {
            case SFILE_OPEN_PATCHED_FILE:

                // We want to open the updated version of the file
                return OpenPatchedFile(hMpq, szFileName, 0, phFile);

            case SFILE_OPEN_FROM_MPQ:

                if (!IsValidMpqHandle(ha))
                {
                    nError = ERROR_INVALID_HANDLE;
                    break;
                }

                if (szFileName == NULL || *szFileName == 0)
                {
                    nError = ERROR_INVALID_PARAMETER;
                    break;
                }

                // First of all, check the name as-is
                pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale);
                if (pFileEntry != NULL)
                    break;

                // If the file doesn't exist in the MPQ, check file pseudo-name ("FileXXXXXXXX.ext")
                if (!IsPseudoFileName(szFileName, &dwBlockIndex))
                {
                    nError = ERROR_FILE_NOT_FOUND;
                    break;
                }

                // Set the file name to the file index and fall through
                szFileName = (const char *)(DWORD_PTR)dwBlockIndex;
                dwSearchScope = SFILE_OPEN_BY_INDEX;
                // No break here, fall through.

            case SFILE_OPEN_BY_INDEX:

                if (!IsValidMpqHandle(ha))
                {
                    nError = ERROR_INVALID_HANDLE;
                    break;
                }

                // Set handle size to be sizeof(TMPQFile) + length of FileXXXXXXXX.xxx
                pFileEntry = GetFileEntryByIndex(ha, (DWORD)(DWORD_PTR)szFileName);
                if (pFileEntry == NULL)
                    nError = ERROR_FILE_NOT_FOUND;
                break;

            case SFILE_OPEN_ANY_LOCALE:

                // This open option is reserved for opening MPQ internal listfile.
                // No argument validation. Tries to open file with neutral locale first,
                // then any other available.
                dwSearchScope = SFILE_OPEN_FROM_MPQ;
                pFileEntry = GetFileEntryAny(ha, szFileName);
                if (pFileEntry == NULL)
                    nError = ERROR_FILE_NOT_FOUND;
                break;

            case SFILE_OPEN_LOCAL_FILE:

                if (szFileName == NULL || *szFileName == 0)
                {
                    nError = ERROR_INVALID_PARAMETER;
                    break;
                }

                return OpenLocalFile(szFileName, phFile);

            default:

                // Don't accept any other value
                nError = ERROR_INVALID_PARAMETER;
                break;
        }

        // Quick return if something failed
        if (nError != ERROR_SUCCESS)
        {
            SetLastError(nError);
            return false;
        }
    }

    // Test if the file was not already deleted.
    if (nError == ERROR_SUCCESS)
    {
        if ((pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
            nError = ERROR_FILE_NOT_FOUND;
        if (pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
            nError = ERROR_NOT_SUPPORTED;
    }

    // Allocate file handle
    if (nError == ERROR_SUCCESS)
    {
        if ((hf = ALLOCMEM(TMPQFile, 1)) == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Initialize file handle
    if (nError == ERROR_SUCCESS)
    {
        memset(hf, 0, sizeof(TMPQFile));
        hf->pFileEntry = pFileEntry;
        hf->dwMagic = ID_MPQ_FILE;
        hf->ha = ha;

        hf->MpqFilePos   = pFileEntry->ByteOffset;
        hf->RawFilePos   = ha->MpqPos + hf->MpqFilePos;

        hf->dwDataSize   = pFileEntry->dwFileSize;
        hf->dwHashIndex  = pFileEntry->dwHashIndex;
        hf->dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);

        // If the MPQ has sector CRC enabled, enable if for the file
        if (ha->dwFlags & MPQ_FLAG_CHECK_SECTOR_CRC)
            hf->bCheckSectorCRCs = true;

        // Decrypt file key. Cannot be used if the file is given by index
        if (dwSearchScope == SFILE_OPEN_FROM_MPQ)
        {
            if (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
            {
                hf->dwFileKey = DecryptFileKey(szFileName,
                                               pFileEntry->ByteOffset,
                                               pFileEntry->dwFileSize,
                                               pFileEntry->dwFlags);
            }
        }
        else
        {
            // If the file is encrypted and not compressed, we cannot detect the file key
            if (!SFileGetFileName(hf, NULL))
                nError = GetLastError();
        }
    }

    // If the file is actually a patch file, we have to load the patch file header
    if (nError == ERROR_SUCCESS && pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
    {
        assert(hf->PatchInfo == NULL);
        nError = AllocatePatchInfo(hf, true);
    }

    // Cleanup
    if (nError != ERROR_SUCCESS)
    {
        SetLastError(nError);
        FreeMPQFile(hf);
    }

    *phFile = hf;
    return (nError == ERROR_SUCCESS);
}
Ejemplo n.º 4
0
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile)
{
    TMPQArchive * ha = (TMPQArchive *)hMpq;
    TFileEntry  * pFileEntry = NULL;
    TMPQFile    * hf = NULL;
    DWORD dwFileIndex = 0;
    bool bOpenByIndex = false;
    int nError = ERROR_SUCCESS;

    // Don't accept NULL pointer to file handle
    if(phFile == NULL)
        nError = ERROR_INVALID_PARAMETER;

    // Prepare the file opening
    if(nError == ERROR_SUCCESS)
    {
        switch(dwSearchScope)
        {
            case SFILE_OPEN_FROM_MPQ:
            case SFILE_OPEN_BASE_FILE:
                
                if(!IsValidMpqHandle(ha))
                {
                    nError = ERROR_INVALID_HANDLE;
                    break;
                }

                if(szFileName == NULL || *szFileName == 0)
                {
                    nError = ERROR_INVALID_PARAMETER;
                    break;
                }

                // Check the pseudo-file name
                if(IsPseudoFileName(szFileName, &dwFileIndex))
                {
                    pFileEntry = GetFileEntryByIndex(ha, dwFileIndex);
                    bOpenByIndex = true;
                    if(pFileEntry == NULL)
                        nError = ERROR_FILE_NOT_FOUND;
                }
                else
                {
                    // If this MPQ is a patched archive, open the file as patched
                    if(ha->haPatch == NULL || dwSearchScope == SFILE_OPEN_BASE_FILE)
                    {
                        // Otherwise, open the file from *this* MPQ
                        pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale);
                        if(pFileEntry == NULL)
                            nError = ERROR_FILE_NOT_FOUND;
                    }
                    else
                    {
                        return OpenPatchedFile(hMpq, szFileName, 0, phFile);
                    }
                }
                break;

            case SFILE_OPEN_ANY_LOCALE:

                // This open option is reserved for opening MPQ internal listfile.
                // No argument validation. Tries to open file with neutral locale first,
                // then any other available.
                pFileEntry = GetFileEntryAny(ha, szFileName);
                if(pFileEntry == NULL)
                    nError = ERROR_FILE_NOT_FOUND;
                break;

            case SFILE_OPEN_LOCAL_FILE:

                if(szFileName == NULL || *szFileName == 0)
                {
                    nError = ERROR_INVALID_PARAMETER;
                    break;
                }

                return OpenLocalFile(szFileName, phFile); 

            default:

                // Don't accept any other value
                nError = ERROR_INVALID_PARAMETER;
                break;
        }

        // Quick return if something failed
        if(nError != ERROR_SUCCESS)
        {
            SetLastError(nError);
            return false;
        }
    }

    // Test if the file was not already deleted.
    if(nError == ERROR_SUCCESS)
    {
        if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
            nError = ERROR_FILE_NOT_FOUND;
        if(pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
            nError = ERROR_NOT_SUPPORTED;
    }

    // Allocate file handle
    if(nError == ERROR_SUCCESS)
    {
        if((hf = STORM_ALLOC(TMPQFile, 1)) == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Initialize file handle
    if(nError == ERROR_SUCCESS)
    {
        memset(hf, 0, sizeof(TMPQFile));
        hf->pFileEntry = pFileEntry;
        hf->dwMagic = ID_MPQ_FILE;
        hf->ha = ha;

        hf->MpqFilePos   = pFileEntry->ByteOffset;
        hf->RawFilePos   = ha->MpqPos + hf->MpqFilePos;
        hf->dwDataSize   = pFileEntry->dwFileSize;

        // If the MPQ has sector CRC enabled, enable if for the file
        if(ha->dwFlags & MPQ_FLAG_CHECK_SECTOR_CRC)
            hf->bCheckSectorCRCs = true;

        // If we know the real file name, copy it to the file entry
        if(bOpenByIndex == false)
        {
            // If there is no file name yet, allocate it
            AllocateFileName(pFileEntry, szFileName);

            // If the file is encrypted, we should detect the file key
            if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
            {
                hf->dwFileKey = DecryptFileKey(szFileName,
                                               pFileEntry->ByteOffset,
                                               pFileEntry->dwFileSize,
                                               pFileEntry->dwFlags);
            }
        }
        else
        {
            // Try to auto-detect the file name
            if(!SFileGetFileName(hf, NULL))
                nError = GetLastError();
        }
    }

    // If the file is actually a patch file, we have to load the patch file header
    if(nError == ERROR_SUCCESS && pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
    {
        assert(hf->pPatchInfo == NULL);
        nError = AllocatePatchInfo(hf, true);
    }

    // Cleanup
    if(nError != ERROR_SUCCESS)
    {
        SetLastError(nError);
        FreeMPQFile(hf);
    }

    *phFile = hf;
    return (nError == ERROR_SUCCESS);
}