void CFileSystem::GetResource(const bfs::path &path, IResource** ppRes) { bfs::path p = bfs::system_complete(path); // Is already loaded? TryGetResource(p, ppRes); if(*ppRes) return; // Resolve type and create if(bfs::exists(p) && bfs::is_regular_file(p)) { if(bfs::extension(p) == ".zip") { IArchive* parch; CreateArchiveHandle(p, &parch); *ppRes = parch; } else { IFile* pfile; CreateFileHandle(p, &pfile); *ppRes = pfile; } } else if(bfs::is_directory(path)) { IFolder* pfld; CreateFolderHandle(p, &pfld); *ppRes = pfld; } }
static bool OpenLocalFile(const char * szFileName, HANDLE * phFile) { TFileStream * pStream; TMPQFile * hf = NULL; TCHAR szFileNameT[MAX_PATH]; // Convert the file name to UNICODE (if needed) CopyFileName(szFileNameT, szFileName, strlen(szFileName)); // Open the file and create the TMPQFile structure pStream = FileStream_OpenFile(szFileNameT, STREAM_FLAG_READ_ONLY); if(pStream != NULL) { // Allocate and initialize file handle hf = CreateFileHandle(NULL, NULL); if(hf != NULL) { hf->pStream = pStream; *phFile = hf; return true; } else { FileStream_Close(pStream); SetLastError(ERROR_NOT_ENOUGH_MEMORY); } } *phFile = NULL; return false; }
int SFileAddFile_Init( TMPQArchive * ha, const char * szFileName, ULONGLONG FileTime, DWORD dwFileSize, LCID lcLocale, DWORD dwFlags, TMPQFile ** phf) { TFileEntry * pFileEntry = NULL; ULONGLONG TempPos; // For various file offset calculations TMPQFile * hf = NULL; // File structure for newly added file int nError = ERROR_SUCCESS; // // Note: This is an internal function so no validity checks are done. // It is the caller's responsibility to make sure that no invalid // flags get to this point // // Sestor CRC is not allowed with single unit files if(dwFlags & MPQ_FILE_SINGLE_UNIT) dwFlags &= ~MPQ_FILE_SECTOR_CRC; // Sector CRC is not allowed if the file is not compressed if(!(dwFlags & MPQ_FILE_COMPRESS_MASK)) dwFlags &= ~MPQ_FILE_SECTOR_CRC; // Fix Key is not allowed if the file is not enrypted if(!(dwFlags & MPQ_FILE_ENCRYPTED)) dwFlags &= ~MPQ_FILE_FIX_KEY; // If the MPQ is of version 3.0 or higher, we ignore file locale. // This is because HET and BET tables have no known support for it if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_3) lcLocale = 0; // Allocate the TMPQFile entry for newly added file hf = CreateFileHandle(ha, NULL); if(hf == NULL) nError = ERROR_NOT_ENOUGH_MEMORY; // Find a free space in the MPQ and verify if it's not over 4 GB on MPQs v1 if(nError == ERROR_SUCCESS) { // Find the position where the file will be stored hf->MpqFilePos = FindFreeMpqSpace(ha); hf->RawFilePos = ha->MpqPos + hf->MpqFilePos; hf->bIsWriteHandle = true; // When format V1, the size of the archive cannot exceed 4 GB if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) { TempPos = hf->MpqFilePos + dwFileSize; TempPos += ha->pHeader->dwHashTableSize * sizeof(TMPQHash); TempPos += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock); TempPos += ha->pHeader->dwBlockTableSize * sizeof(USHORT); if((TempPos >> 32) != 0) nError = ERROR_DISK_FULL; }
void FileInfo::WriteBackFileSizeAsync(const RPCOptions& options) { boost::mutex::scoped_lock lock(osd_write_response_mutex_); // Only update pending file size updates. if (osd_write_response_.get() && osd_write_response_status_ == kDirty) { FileHandleImplementation* file_handle = CreateFileHandle(osd_write_response_xcap_, false, true); pending_filesize_updates_.push_back(file_handle); osd_write_response_status_ = kDirtyAndAsyncPending; file_handle->set_osd_write_response_for_async_write_back( *(osd_write_response_.get())); file_handle->WriteBackFileSizeAsync(options); } }
FileHandleImplementation* FileInfo::CreateFileHandle( const xtreemfs::pbrpc::XCap& xcap, bool async_writes_enabled) { return CreateFileHandle(xcap, async_writes_enabled, false); }
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(hMpq)) { 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); *phFile = NULL; 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) { hf = CreateFileHandle(ha, pFileEntry); if(hf == NULL) nError = ERROR_NOT_ENOUGH_MEMORY; } // Initialize file handle if(nError == ERROR_SUCCESS) { // 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(ha, 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(); } } // Cleanup and exit if(nError != ERROR_SUCCESS) { SetLastError(nError); FreeFileHandle(hf); return false; } *phFile = hf; return true; }
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * PtrFile) { TMPQArchive * ha = IsValidMpqHandle(hMpq); TFileEntry * pFileEntry = NULL; TMPQFile * hf = NULL; DWORD dwHashIndex = HASH_ENTRY_FREE; DWORD dwFileIndex = 0; bool bOpenByIndex = false; int nError = ERROR_SUCCESS; // Don't accept NULL pointer to file handle if(szFileName == NULL || *szFileName == 0) nError = ERROR_INVALID_PARAMETER; // When opening a file from MPQ, the handle must be valid if(dwSearchScope != SFILE_OPEN_LOCAL_FILE && ha == NULL) nError = ERROR_INVALID_HANDLE; // When not checking for existence, the pointer to file handle must be valid if(dwSearchScope != SFILE_OPEN_CHECK_EXISTS && PtrFile == 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: case SFILE_OPEN_CHECK_EXISTS: // Check the pseudo-file name if((bOpenByIndex = IsPseudoFileName(szFileName, &dwFileIndex)) == true) { // Get the file entry for the file if(dwFileIndex > ha->dwFileTableSize) break; pFileEntry = ha->pFileTable + dwFileIndex; } else { // If this MPQ has no patches, open the file from this MPQ directly if(ha->haPatch == NULL || dwSearchScope == SFILE_OPEN_BASE_FILE) { pFileEntry = GetFileEntryLocale2(ha, szFileName, lcFileLocale, &dwHashIndex); } // If this MPQ is a patched archive, open the file as patched else { return OpenPatchedFile(hMpq, szFileName, PtrFile); } } 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 = GetFileEntryLocale2(ha, szFileName, 0, &dwHashIndex); break; case SFILE_OPEN_LOCAL_FILE: // Open a local file return OpenLocalFile(szFileName, PtrFile); default: // Don't accept any other value nError = ERROR_INVALID_PARAMETER; break; } } // Check whether the file really exists in the MPQ if(nError == ERROR_SUCCESS) { if(pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0) nError = ERROR_FILE_NOT_FOUND; // Ignore unknown loading flags (example: MPQ_2016_v1_WME4_4.w3x) // if(pFileEntry != NULL && pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS) // nError = ERROR_NOT_SUPPORTED; } // Did the caller just wanted to know if the file exists? if(nError == ERROR_SUCCESS && dwSearchScope != SFILE_OPEN_CHECK_EXISTS) { // Allocate file handle hf = CreateFileHandle(ha, pFileEntry); if(hf != NULL) { // Get the hash index for the file if(ha->pHashTable != NULL && dwHashIndex == HASH_ENTRY_FREE) dwHashIndex = FindHashIndex(ha, dwFileIndex); if(dwHashIndex != HASH_ENTRY_FREE) hf->pHashEntry = ha->pHashTable + dwHashIndex; hf->dwHashIndex = dwHashIndex; // 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(ha, 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 { nError = ERROR_NOT_ENOUGH_MEMORY; } } // Give the file entry if(PtrFile != NULL) PtrFile[0] = hf; // Return error code if(nError != ERROR_SUCCESS) SetLastError(nError); return (nError == ERROR_SUCCESS); }
static int CopyMpqFiles(TMPQArchive * ha, LPDWORD pFileKeys, TFileStream * pNewStream) { TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; TFileEntry * pFileEntry; TMPQFile * hf = NULL; ULONGLONG MpqFilePos; int nError = ERROR_SUCCESS; // Walk through all files and write them to the destination MPQ archive for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++) { // Copy all the file sectors // Only do that when the file has nonzero size if((pFileEntry->dwFlags & MPQ_FILE_EXISTS)) { // Query the position where the destination file will be FileStream_GetPos(pNewStream, &MpqFilePos); MpqFilePos = MpqFilePos - ha->MpqPos; // Perform file copy ONLY if the file has nonzero size if(pFileEntry->dwFileSize != 0) { // Allocate structure for the MPQ file hf = CreateFileHandle(ha, pFileEntry); if(hf == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Set the file decryption key hf->dwFileKey = pFileKeys[pFileEntry - ha->pFileTable]; // If the file is a patch file, load the patch header if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) { nError = AllocatePatchInfo(hf, true); if(nError != ERROR_SUCCESS) break; } // Allocate buffers for file sector and sector offset table nError = AllocateSectorBuffer(hf); if(nError != ERROR_SUCCESS) break; // Also allocate sector offset table and sector checksum table nError = AllocateSectorOffsets(hf, true); if(nError != ERROR_SUCCESS) break; // Also load sector checksums, if any if(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) { nError = AllocateSectorChecksums(hf, false); if(nError != ERROR_SUCCESS) break; } // Copy all file sectors nError = CopyMpqFileSectors(ha, hf, pNewStream, MpqFilePos); if(nError != ERROR_SUCCESS) break; // Free buffers. This also sets "hf" to NULL. FreeFileHandle(hf); } // Note: DO NOT update the compressed size in the file entry, no matter how bad it is. pFileEntry->ByteOffset = MpqFilePos; } } // Cleanup and exit if(hf != NULL) FreeFileHandle(hf); return nError; }