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; }
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; }