ULONG64 CMPQFileAccessor::GetCurPos() { if(m_hFile) { ULONG64_CONVERTER FilePos; FilePos.QuadPart=0; FilePos.LowPart=SFileSetFilePointer(m_hFile,FilePos.LowPart,(LONG *)&FilePos.HighPart,FILE_CURRENT); if(FilePos.LowPart==0xFFFFFFFF) { if(GetLastError()==NO_ERROR) return FilePos.QuadPart; else return 0; } else { return FilePos.QuadPart; } } else if(m_pRealFSFile) { return m_pRealFSFile->GetCurPos(); } return 0; }
static int MPQ_seek(PHYSFS_Io *io, PHYSFS_uint64 offset) { MPQFileHandle *handle = (MPQFileHandle*)io->opaque; LONG DeltaPosHi = (LONG)(offset >> 32); LONG DeltaPosLo = (LONG)(offset); SFileSetFilePointer(handle->fileHandle, DeltaPosLo, &DeltaPosHi, FILE_BEGIN); return 1; }
static PHYSFS_sint64 MPQ_tell(PHYSFS_Io *io) { MPQFileHandle *handle = (MPQFileHandle*)io->opaque; LONG FilePosHi = 0; DWORD FilePosLo; FilePosLo = SFileSetFilePointer(handle->fileHandle, 0, &FilePosHi, FILE_CURRENT); return (((PHYSFS_sint64)FilePosHi << 32) | (PHYSFS_sint64)FilePosLo); }
DWORD WINAPI SFileSetFilePointer_stub(MPQHANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod) { LoadSFMpqDll(); if (hSFMpq) { *(FARPROC *)&SFileSetFilePointer = GetProcAddress(hSFMpq,"SFileSetFilePointer"); if (SFileSetFilePointer) return SFileSetFilePointer(hFile,lDistanceToMove,lplDistanceToMoveHigh,dwMoveMethod); } return (DWORD)-1; }
static int CreatePseudoFileName(void * hFile, TFileEntry * pFileEntry, char * szFileName) { TMPQFile * hf = (TMPQFile *)hFile; /* MPQ File handle */ uint32_t FirstBytes[2] = {0, 0}; /* The first 4 bytes of the file */ size_t dwBytesRead = 0; size_t dwFilePos; /* Saved file position */ /* Read the first 2 uint32_ts bytes from the file */ dwFilePos = SFileSetFilePointer(hFile, 0, NULL, SEEK_CUR); SFileReadFile(hFile, FirstBytes, sizeof(FirstBytes), &dwBytesRead); SFileSetFilePointer(hFile, dwFilePos, NULL, SEEK_SET); /* If we read at least 8 bytes */ if(dwBytesRead == sizeof(FirstBytes)) { size_t i; /* Make sure that the array is properly BSWAP-ed */ BSWAP_ARRAY32_UNSIGNED(FirstBytes, sizeof(FirstBytes)); /* Try to guess file extension from those 2 ints */ for(i = 0; data2ext[i].szExt != NULL; i++) { if((FirstBytes[0] & data2ext[i].dwOffset00Mask) == data2ext[i].dwOffset00Data && (FirstBytes[1] & data2ext[i].dwOffset04Mask) == data2ext[i].dwOffset04Data) { char szPseudoName[20] = ""; /* Format the pseudo-name */ sprintf(szPseudoName, "File%08u.%s", (unsigned int)(pFileEntry - hf->ha->pFileTable), data2ext[i].szExt); /* Save the pseudo-name in the file entry as well */ AllocateFileName(hf->ha, pFileEntry, szPseudoName); /* If the caller wants to copy the file name, do it */ if(szFileName != NULL) strcpy(szFileName, szPseudoName); return ERROR_SUCCESS; } } } return ERROR_CAN_NOT_COMPLETE; }
static int CreatePseudoFileName(HANDLE hFile, TFileEntry * pFileEntry, char * szFileName) { TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle DWORD FirstBytes[2] = {0, 0}; // The first 4 bytes of the file DWORD dwBytesRead = 0; DWORD dwFilePos; // Saved file position // Read the first 2 DWORDs bytes from the file dwFilePos = SFileSetFilePointer(hFile, 0, NULL, FILE_CURRENT); SFileReadFile(hFile, FirstBytes, sizeof(FirstBytes), &dwBytesRead, NULL); SFileSetFilePointer(hFile, dwFilePos, NULL, FILE_BEGIN); // If we read at least 8 bytes if(dwBytesRead == sizeof(FirstBytes)) { // Make sure that the array is properly BSWAP-ed BSWAP_ARRAY32_UNSIGNED(FirstBytes, sizeof(FirstBytes)); // Try to guess file extension from those 2 DWORDs for(size_t i = 0; data2ext[i].szExt != NULL; i++) { if((FirstBytes[0] & data2ext[i].dwOffset00Mask) == data2ext[i].dwOffset00Data && (FirstBytes[1] & data2ext[i].dwOffset04Mask) == data2ext[i].dwOffset04Data) { char szPseudoName[20] = ""; // Format the pseudo-name sprintf(szPseudoName, "File%08u.%s", (unsigned int)(pFileEntry - hf->ha->pFileTable), data2ext[i].szExt); // Save the pseudo-name in the file entry as well AllocateFileName(hf->ha, pFileEntry, szPseudoName); // If the caller wants to copy the file name, do it if(szFileName != NULL) strcpy(szFileName, szPseudoName); return ERROR_SUCCESS; } } } return ERROR_CAN_NOT_COMPLETE; }
size_t FAftell(FAFile* stream) { switch(stream->mode) { case FAFile::PlainFile: return ftell(stream->data.plainFile.file); case FAFile::MPQFile: return SFileSetFilePointer(*((HANDLE*)stream->data.mpqFile), 0, NULL, FILE_CURRENT); default: return 0; } }
BOOL CMPQFileAccessor::Seek(LONG64 Offset,int SeekMode) { if(m_hFile) { ULONG64_CONVERTER FilePos; FilePos.QuadPart=Offset; FilePos.LowPart=SFileSetFilePointer(m_hFile,FilePos.LowPart,(LONG *)&FilePos.HighPart,SeekMode); if(FilePos.LowPart==0xFFFFFFFF&&GetLastError()!=NO_ERROR) return false; else return true; } else if(m_pRealFSFile) { return m_pRealFSFile->Seek(Offset,SeekMode); } return false; }
int FAfseek (FAFile* stream, size_t offset, int origin) { switch(stream->mode) { case FAFile::PlainFile: return fseek(stream->data.plainFile.file, offset, origin); case FAFile::MPQFile: { std::lock_guard<std::mutex> lock(m); DWORD moveMethod; switch(origin) { case SEEK_SET: moveMethod = FILE_BEGIN; break; case SEEK_CUR: moveMethod = FILE_CURRENT; break; case SEEK_END: moveMethod = FILE_END; break; default: return 1; // error, incorrect origin } SFileSetFilePointer(*((HANDLE*)stream->data.mpqFile), offset, NULL, moveMethod); int nError = ERROR_SUCCESS; nError = GetLastError(); return nError != ERROR_SUCCESS; } } return 0; }
// Reloads the cache. Returns number of characters // that has been loaded into the cache. static DWORD ReloadListFileCache(TListFileCache * pCache) { DWORD dwBytesToRead; DWORD dwBytesRead = 0; // Only do something if the cache is empty if(pCache->pPos >= pCache->pEnd) { // Move the file position forward pCache->dwFilePos += CACHE_BUFFER_SIZE; if(pCache->dwFilePos >= pCache->dwFileSize) return 0; // Get the number of bytes remaining dwBytesToRead = pCache->dwFileSize - pCache->dwFilePos; if(dwBytesToRead > CACHE_BUFFER_SIZE) dwBytesToRead = CACHE_BUFFER_SIZE; // Load the next data chunk to the cache SFileSetFilePointer(pCache->hFile, pCache->dwFilePos, NULL, FILE_BEGIN); SFileReadFile(pCache->hFile, pCache->Buffer, CACHE_BUFFER_SIZE, &dwBytesRead, NULL); // If we didn't read anything, it might mean that the block // of the file is not available (in case of partial MPQs). // We stop reading the file at this point, because the rest // of the listfile is unreliable if(dwBytesRead == 0) return 0; // Set the buffer pointers pCache->pBegin = pCache->pPos = &pCache->Buffer[0]; pCache->pEnd = pCache->pBegin + dwBytesRead; } return dwBytesRead; }
// TODO: Test for archives > 4GB BOOL WINAPI SFileGetFileName(HANDLE hFile, char * szFileName) { TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle char * szExt = "xxx"; // Default extension DWORD dwFirstBytes[2]; // The first 4 bytes of the file DWORD dwFilePos; // Saved file position int nError = ERROR_SUCCESS; int i; // Pre-zero the output buffer if(szFileName != NULL) *szFileName = 0; // Check valid parameters if(nError == ERROR_SUCCESS) { if(hf == NULL || szFileName == NULL) nError = ERROR_INVALID_PARAMETER; } // If the file name is already filled, return it. if(nError == ERROR_SUCCESS && *hf->szFileName != 0) { if(szFileName != hf->szFileName) strcpy(szFileName, hf->szFileName); return TRUE; } if(nError == ERROR_SUCCESS) { if(hf->dwFileIndex == (DWORD)-1) nError = ERROR_CAN_NOT_COMPLETE; } // Read the first 8 bytes from the file if(nError == ERROR_SUCCESS) { dwFirstBytes[0] = dwFirstBytes[1] = 0; dwFilePos = SFileSetFilePointer(hf, 0, NULL, FILE_CURRENT); if(!SFileReadFile(hFile, &dwFirstBytes, sizeof(dwFirstBytes), NULL)) nError = GetLastError(); BSWAP_ARRAY32_UNSIGNED(dwFirstBytes, sizeof(dwFirstBytes) / sizeof(DWORD)); SFileSetFilePointer(hf, dwFilePos, NULL, FILE_BEGIN); } if(nError == ERROR_SUCCESS) { if((dwFirstBytes[0] & 0x0000FFFF) == ID_EXE) szExt = "exe"; else if(dwFirstBytes[0] == 0x00000006 && dwFirstBytes[1] == 0x00000001) szExt = "dc6"; else { for(i = 0; id2ext[i].szExt != NULL; i++) { if(id2ext[i].dwID == dwFirstBytes[0]) { szExt = id2ext[i].szExt; break; } } } // Create the file name sprintf(hf->szFileName, "File%08lu.%s", hf->dwFileIndex, szExt); if(szFileName != hf->szFileName) strcpy(szFileName, hf->szFileName); } return (nError == ERROR_SUCCESS); }