| 275 | // Recrypts file data for file renaming |
| 276 | |
| 277 | static DWORD RecryptFileData( |
| 278 | TMPQArchive * ha, |
| 279 | TMPQFile * hf, |
| 280 | const char * szFileName, |
| 281 | const char * szNewFileName) |
| 282 | { |
| 283 | ULONGLONG RawFilePos; |
| 284 | TFileEntry * pFileEntry = hf->pFileEntry; |
| 285 | DWORD dwBytesToRecrypt = pFileEntry->dwCmpSize; |
| 286 | DWORD dwOldKey; |
| 287 | DWORD dwNewKey; |
| 288 | DWORD dwErrCode = ERROR_SUCCESS; |
| 289 | |
| 290 | // The file must be encrypted |
| 291 | assert(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED); |
| 292 | |
| 293 | // File decryption key is calculated from the plain name |
| 294 | szNewFileName = GetPlainFileName(szNewFileName); |
| 295 | szFileName = GetPlainFileName(szFileName); |
| 296 | |
| 297 | // Calculate both file keys |
| 298 | dwOldKey = DecryptFileKey(szFileName, pFileEntry->ByteOffset, pFileEntry->dwFileSize, pFileEntry->dwFlags); |
| 299 | dwNewKey = DecryptFileKey(szNewFileName, pFileEntry->ByteOffset, pFileEntry->dwFileSize, pFileEntry->dwFlags); |
| 300 | |
| 301 | // Incase the keys are equal, don't recrypt the file |
| 302 | if(dwNewKey == dwOldKey) |
| 303 | return ERROR_SUCCESS; |
| 304 | hf->dwFileKey = dwOldKey; |
| 305 | |
| 306 | // Calculate the raw position of the file in the archive |
| 307 | hf->MpqFilePos = pFileEntry->ByteOffset; |
| 308 | hf->RawFilePos = ha->MpqPos + hf->MpqFilePos; |
| 309 | |
| 310 | // Allocate buffer for file transfer |
| 311 | dwErrCode = AllocateSectorBuffer(hf); |
| 312 | if(dwErrCode != ERROR_SUCCESS) |
| 313 | return dwErrCode; |
| 314 | |
| 315 | // Also allocate buffer for sector offsets |
| 316 | // Note: Don't load sector checksums, we don't need to recrypt them |
| 317 | dwErrCode = AllocateSectorOffsets(hf, true); |
| 318 | if(dwErrCode != ERROR_SUCCESS) |
| 319 | return dwErrCode; |
| 320 | |
| 321 | // If we have sector offsets, recrypt these as well |
| 322 | if(hf->SectorOffsets != NULL) |
| 323 | { |
| 324 | // Allocate secondary buffer for sectors copy |
| 325 | DWORD * SectorOffsetsCopy = STORM_ALLOC(DWORD, hf->SectorOffsets[0] / sizeof(DWORD)); |
| 326 | DWORD dwSectorOffsLen = hf->SectorOffsets[0]; |
| 327 | |
| 328 | if(SectorOffsetsCopy == NULL) |
| 329 | return ERROR_NOT_ENOUGH_MEMORY; |
| 330 | |
| 331 | // Recrypt the array of sector offsets |
| 332 | memcpy(SectorOffsetsCopy, hf->SectorOffsets, dwSectorOffsLen); |
| 333 | EncryptMpqBlock(SectorOffsetsCopy, dwSectorOffsLen, dwNewKey - 1); |
| 334 | BSWAP_ARRAY32_UNSIGNED(SectorOffsetsCopy, dwSectorOffsLen); |
no test coverage detected