FAFile* FAfopen(const std::string& filename) { bfs::path path(filename); path.make_preferred(); if(!bfs::exists(filename)) { int nError = ERROR_SUCCESS; if(diabdat == NULL && !SFileOpenArchive(getMPQFileName().c_str(), 0, STREAM_FLAG_READ_ONLY, &diabdat)) nError = GetLastError(); if(nError != ERROR_SUCCESS) { std::cerr << "Failed to open " << DIABDAT_MPQ << std::endl; return NULL; } std::string stormPath = getStormLibPath(path); if(!SFileHasFile(diabdat, stormPath.c_str())) { std::cerr << "File " << path << " not found" << std::endl; return NULL; } FAFile* file = new FAFile(); file->data.mpqFile = malloc(sizeof(HANDLE)); if(!SFileOpenFileEx(diabdat, stormPath.c_str(), 0, (HANDLE*)file->data.mpqFile)) { std::cerr << "Failed to open " << filename << " in " << DIABDAT_MPQ; delete file; return NULL; } file->mode = FAFile::MPQFile; return file; } else { FILE* plainFile = fopen(filename.c_str(), "rb"); if(plainFile == NULL) return NULL; FAFile* file = new FAFile(); file->mode = FAFile::PlainFile; file->data.plainFile.file = plainFile; file->data.plainFile.filename = new std::string(filename); return file; } }
bool exists(const std::string& filename) { bfs::path path(filename); path.make_preferred(); if(bfs::exists(filename)) return true; std::lock_guard<std::mutex> lock(m); std::string stormPath = getStormLibPath(path); return SFileHasFile(diabdat, stormPath.c_str()); }
FAFile* FAfopen(const std::string& filename) { bfs::path path(filename); path.make_preferred(); if(!bfs::exists(filename)) { std::lock_guard<std::mutex> lock(m); std::string stormPath = getStormLibPath(path); if(!SFileHasFile(diabdat, stormPath.c_str())) { std::cerr << "File " << path << " not found" << std::endl; return NULL; } FAFile* file = new FAFile(); file->data.mpqFile = malloc(sizeof(HANDLE)); if(!SFileOpenFileEx(diabdat, stormPath.c_str(), 0, (HANDLE*)file->data.mpqFile)) { std::cerr << "Failed to open " << filename << " in " << DIABDAT_MPQ; delete file; return NULL; } file->mode = FAFile::MPQFile; return file; } else { FILE* plainFile = fopen(filename.c_str(), "rb"); if(plainFile == NULL) return NULL; FAFile* file = new FAFile(); file->mode = FAFile::PlainFile; file->data.plainFile.file = plainFile; file->data.plainFile.filename = new std::string(filename); return file; } }
bool MpkManip::hasFile(const char* filename) { return SFileHasFile(m_hMpk,(char*)filename) != FALSE; }
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; }
int SC2Map::readGameStrings_txt( const HANDLE archive ) { string gameStrings; string suffix( ".SC2Data\\LocalizedData\\GameStrings.txt" ); list<string>::iterator itr; bool localeFound = false; // first check local user config itr = configUserLocal.localePreferences.begin(); while( itr != configUserLocal.localePreferences.end() && !localeFound ) { gameStrings.assign( *itr ); gameStrings.append( suffix ); if( SFileHasFile( archive, gameStrings.data() ) ) { // gameStrings now holds name of valid file in archive localeFound = true; } ++itr; } // then global user config itr = configUserGlobal.localePreferences.begin(); while( itr != configUserGlobal.localePreferences.end() && !localeFound ) { gameStrings.assign( *itr ); gameStrings.append( suffix ); if( SFileHasFile( archive, gameStrings.data() ) ) { // gameStrings now holds name of valid file in archive localeFound = true; } ++itr; } // last resort is global internal config itr = configInternal.localePreferences.begin(); while( itr != configInternal.localePreferences.end() && !localeFound ) { gameStrings.assign( *itr ); gameStrings.append( suffix ); if( SFileHasFile( archive, gameStrings.data() ) ) { // gameStrings now holds name of valid file in archive localeFound = true; } ++itr; } int bufferSize; u8* bufferFreeAfterUse; if( readArchiveFile( archive, gameStrings.data(), &bufferSize, &bufferFreeAfterUse ) < 0 ) { return -1; } // this is a plain text file, so copy the data into a null-terminated character // buffer so we can use string searching on it char bufferString[bufferSize + 1]; memcpy( bufferString, bufferFreeAfterUse, bufferSize ); bufferString[sizeof( bufferString ) - 1] = '\0'; // release the buffer with the file's data delete bufferFreeAfterUse; // try to find the map's name here, otherwise use the // filename--the goal is to name the output files char strMapName[FILENAME_LENGTH]; char attributeName[] = "DocInfo/Name="; char* findAttribute = strstr( bufferString, attributeName ); if( findAttribute == NULL ) { // return -1 because we should choose another name return -1; } // we did find a name int nameStartIndex = (int)findAttribute - (int)bufferString + strlen( attributeName ); int i = 0; while( nameStartIndex + i < bufferSize && bufferString[nameStartIndex + i] != '\r' ) { strMapName[i] = bufferString[nameStartIndex + i]; ++i; } strMapName[i] = '\0'; // put it in a nice string and done! mapName.assign( strMapName ); return 0; }
QByteArray MPQ::readFile(const QString &fileName) { static QHash<QString, QByteArray> files; static const QString mpqs[] = { "patch-2.MPQ", "patch.MPQ", "dbc.MPQ", "model.MPQ", "interface.MPQ", "texture.MPQ", "" }; if (files.contains(fileName)) return files[fileName]; const QString *mpq = mpqs; HANDLE hMPQ = 0; while (!mpq->isEmpty()) { QString path = MPQ::gameDir() + "Data/" + *mpq; hMPQ = getHandle(path); if (hMPQ && SFileHasFile(hMPQ, fileName.toUtf8().constData())) break; else hMPQ = 0; mpq++; } if (!hMPQ) { qCritical("File '%s' not found", qPrintable(fileName)); return files[fileName]; } HANDLE hFile; if (!SFileOpenFileEx(hMPQ, fileName.toUtf8().constData(), SFILE_OPEN_FROM_MPQ, &hFile)) { qCritical("Cannot open file '%s' from archive", qPrintable(fileName)); return files[fileName]; } DWORD size = SFileGetFileSize(hFile, NULL); if (size == SFILE_INVALID_SIZE) { qCritical("Cannot read file '%s' from archive", qPrintable(fileName)); return files[fileName]; } char *data = new char[size]; if (!SFileReadFile(hFile, data, size, NULL, NULL)) { qCritical("Cannot read file '%s' from archive", qPrintable(fileName)); SFileCloseFile(hFile); delete[] data; return files[fileName]; } SFileCloseFile(hFile); files[fileName] = QByteArray(data, size); delete[] data; return files[fileName]; }