bool WINAPI SFileOpenPatchArchive(
    HANDLE hMpq,
    const TCHAR * szPatchMpqName,
    const char * szPatchPathPrefix,
    DWORD dwFlags)
{
    TMPQArchive * haPatch;
    TMPQArchive * ha = (TMPQArchive *)hMpq;
    HANDLE hPatchMpq = NULL;
    char szPatchPrefixBuff[MPQ_PATCH_PREFIX_LEN];
    int nError = ERROR_SUCCESS;

    // Keep compiler happy
    dwFlags = dwFlags;

    // Verify input parameters
    if(!IsValidMpqHandle(ha))
        nError = ERROR_INVALID_HANDLE;
    if(szPatchMpqName == NULL || *szPatchMpqName == 0)
        nError = ERROR_INVALID_PARAMETER;

    // If the user didn't give the patch prefix, get default one
    if(szPatchPathPrefix != NULL)
    {
        // Save length of the patch prefix
        if(strlen(szPatchPathPrefix) > MPQ_PATCH_PREFIX_LEN - 2)
            nError = ERROR_INVALID_PARAMETER;
    }

    //
    // We don't allow adding patches to archives that have been open for write
    //
    // Error scenario:
    //
    // 1) Open archive for writing
    // 2) Modify or replace a file
    // 3) Add patch archive to the opened MPQ
    // 4) Read patched file
    // 5) Now what ?
    //

    if(nError == ERROR_SUCCESS)
    {
        if((ha->pStream->StreamFlags & STREAM_FLAG_READ_ONLY) == 0)
            nError = ERROR_ACCESS_DENIED;
    }

    // Open the archive like it is normal archive
    if(nError == ERROR_SUCCESS)
    {
        if(!SFileOpenArchive(szPatchMpqName, 0, MPQ_OPEN_READ_ONLY, &hPatchMpq))
            return false;
        haPatch = (TMPQArchive *)hPatchMpq;

        // Older WoW patches (build 13914) used to have
        // several language versions in one patch file
        // Those patches needed to have a path prefix
        // We can distinguish such patches by not having the (patch_metadata) file
        if(szPatchPathPrefix == NULL)
        {
            if(!SFileHasFile(hPatchMpq, PATCH_METADATA_NAME))
            {
                GetDefaultPatchPrefix(ha->pStream->szFileName, szPatchPrefixBuff);
                szPatchPathPrefix = szPatchPrefixBuff;
            }
        }

        // Save the prefix for patch file names.
        // Make sure that there is backslash after it
        if(szPatchPathPrefix != NULL && *szPatchPathPrefix != 0)
        {
            strcpy(haPatch->szPatchPrefix, szPatchPathPrefix);
            strcat(haPatch->szPatchPrefix, "\\");
            haPatch->cchPatchPrefix = strlen(haPatch->szPatchPrefix);
        }

        // Now add the patch archive to the list of patches to the original MPQ
        while(ha != NULL)
        {
            if(ha->haPatch == NULL)
            {
                haPatch->haBase = ha;
                ha->haPatch = haPatch;
                return true;
            }

            // Move to the next archive
            ha = ha->haPatch;
        }

        // Should never happen
        nError = ERROR_CAN_NOT_COMPLETE;
    }

    SetLastError(nError);
    return false;
}
示例#2
0
bool WINAPI SFileOpenPatchArchive(
    HANDLE hMpq,
    const TCHAR * szPatchMpqName,
    const char * szPatchPathPrefix,
    DWORD dwFlags)
{
    TMPQArchive * haPatch;
    TMPQArchive * ha = (TMPQArchive *)hMpq;
    HANDLE hPatchMpq = NULL;
    size_t nLength = 0;
    char szPatchPrefixBuff[MPQ_PATCH_PREFIX_LEN];
    int nError = ERROR_SUCCESS;

    // Keep compiler happy
    dwFlags = dwFlags;

    // Verify input parameters
    if(!IsValidMpqHandle(ha))
        nError = ERROR_INVALID_HANDLE;
    if(szPatchMpqName == NULL || *szPatchMpqName == 0)
        nError = ERROR_INVALID_PARAMETER;

    // If the user didn't give the patch prefix, get default one
    if(szPatchPathPrefix == NULL)
    {
        // Get the default patch prefix from the base MPQ
        GetDefaultPatchPrefix(ha->pStream->szFileName, szPatchMpqName, szPatchPrefixBuff);
        szPatchPathPrefix = szPatchPrefixBuff;
    }

    // Save length of the patch prefix
    nLength = strlen(szPatchPathPrefix);
    if(nLength > MPQ_PATCH_PREFIX_LEN - 2)
        nError = ERROR_INVALID_PARAMETER;

    //
    // We don't allow adding patches to archives that have been open for write
    //
    // Error scenario:
    //
    // 1) Open archive for writing
    // 2) Modify or replace a file
    // 3) Add patch archive to the opened MPQ
    // 4) Read patched file
    // 5) Now what ?
    //

    if(nError == ERROR_SUCCESS)
    {
        if((ha->pStream->StreamFlags & STREAM_FLAG_READ_ONLY) == 0)
            nError = ERROR_ACCESS_DENIED;
    }

    // Open the archive like it is normal archive
    if(nError == ERROR_SUCCESS)
    {
        if(!SFileOpenArchive(szPatchMpqName, 0, MPQ_OPEN_READ_ONLY, &hPatchMpq))
            return false;
        haPatch = (TMPQArchive *)hPatchMpq;

        // Save the prefix for patch file names.
        // Make sure that there is backslash after it
        if(nLength > 0)
        {
            strcpy(haPatch->szPatchPrefix, szPatchPathPrefix);
            if(haPatch->szPatchPrefix[nLength - 1] != '\\')
            {
                haPatch->szPatchPrefix[nLength++] = '\\';
                haPatch->szPatchPrefix[nLength] = 0;
            }
            haPatch->cchPatchPrefix = nLength;
        }

        // Now add the patch archive to the list of patches to the original MPQ
        while(ha != NULL)
        {
            if(ha->haPatch == NULL)
            {
                haPatch->haBase = ha;
                ha->haPatch = haPatch;
                return true;
            }

            // Move to the next archive
            ha = ha->haPatch;
        }

        // Should never happen
        nError = ERROR_CAN_NOT_COMPLETE;
    }

    SetLastError(nError);
    return false;
}