public override Native.NtStatus NtCreateFileImpl(string filePath, out IntPtr handle, FileAccess access, ref Native.OBJECT_ATTRIBUTES objectAttributes, ref Native.IO_STATUS_BLOCK ioStatus, ref long allocSize, uint fileAttributes, FileShare share, uint createDisposition, uint createOptions, IntPtr eaBuffer, uint eaLength) { var result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); if (!mCpkByName.TryGetValue(filePath, out var cpk)) { mCpkByName[filePath] = cpk = new VirtualCpk(mLogger); // Load file using (var fileStream = new FileStream(new SafeFileHandle(handle, true), FileAccess.Read, 1024 * 1024)) cpk.LoadFromFile(filePath, fileStream); // Reopen file to reset it result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); mLogger.Debug($"Registered {filePath}"); // Redirect entries to a non-existent pac that will be handled by the DwPack redirector cpk.Redirect(mModDb); } mCpkByHandle[handle] = new VirtualCpkHandle() { Instance = cpk }; mLogger.Debug($"Hnd {handle} {filePath} handle registered"); CpkLoaded?.Invoke(this, cpk); return(result); }
public bool Redirect(ModDb modDb) { RedirectAttempted = true; foreach (var mod in modDb.Mods) { var pacRedirectFilePath = Path.Combine(mod.LoadDirectory, Pack.FileName, Native->Path); if (mod.Files.Contains(pacRedirectFilePath)) { // Replacement file stored in folder named after pac file Redirect(pacRedirectFilePath); mLogger.Info($"{Pack.FileName} {Native->Path} Redirected to {pacRedirectFilePath}"); return(true); } if (Pack.Cpk != null) { var cpkRedirectFilePath = Path.Combine(mod.LoadDirectory, Pack.Cpk.FileName, Native->Path); if (mod.Files.Contains(cpkRedirectFilePath)) { // Replacement file stored in folder named after cpk file Redirect(cpkRedirectFilePath); mLogger.Info($"{Pack.FileName} {Native->Path} Redirected to {cpkRedirectFilePath}"); return(true); } } mLogger.Debug($"No redirection for {Native->Path}."); } return(false); }
public override Native.NtStatus NtCreateFileImpl(string filePath, out IntPtr handle, FileAccess access, ref Native.OBJECT_ATTRIBUTES objectAttributes, ref Native.IO_STATUS_BLOCK ioStatus, ref long allocSize, uint fileAttributes, FileShare share, uint createDisposition, uint createOptions, IntPtr eaBuffer, uint eaLength) { var result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); if (!mPacksByName.TryGetValue(filePath, out var pack)) { mPacksByName[filePath] = pack = new VirtualDwPack(mLogger); // Load file using (var fileStream = new FileStream(new SafeFileHandle(handle, true), FileAccess.Read, 1024 * 1024)) pack.LoadFromFile(filePath, fileStream); // Reopen file to reset it result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); mLogger.Debug($"Registered {filePath}"); // Entries are redirected as needed to improve startup performance } mPacksByHandle[handle] = pack; mLogger.Debug($"Hnd {handle} {filePath} handle registered"); return(result); }
private void Rebuild(int addedFiles) { // Write uncompressed CPK mLogger.Debug($"{FileName}: Rebuilding"); var uncompressedSize = (int)(Native.Header->UncompressedSize + (addedFiles * CpkEntry.SIZE)); using var tempBuf = MemoryPool <byte> .Shared.Rent(uncompressedSize); var tempBufSpan = tempBuf.Memory.Span.Slice(0, uncompressedSize); mWrapper.Write(tempBufSpan); // Compress it var comBuffer = (void *)Marshal.AllocHGlobal(uncompressedSize); var comSize = CpkUtil.CompressCpk(tempBufSpan, new Span <byte>(comBuffer, uncompressedSize)); // Replace old data Native.Dispose(); Native = new CompressedCpkPtr(comBuffer); }
public bool TryRedirect(ModDb modDb) { RedirectAttempted = true; foreach (var mod in modDb.Mods) { var redirectedFilePath = Path.Combine(mod.LoadDirectory, Pack.FileName, Native->Path); if (mod.Files.Contains(redirectedFilePath)) { Redirect(redirectedFilePath); mLogger.Info($"{Pack.FileName} {Native->Path} Redirected to {redirectedFilePath}"); return(true); } else { mLogger.Debug($"No redirection for {Native->Path} because {redirectedFilePath} does not exist."); } } return(false); }
public override Native.NtStatus NtCreateFileImpl(string newFilePath, out IntPtr handle, FileAccess access, ref Native.OBJECT_ATTRIBUTES objectAttributes, ref Native.IO_STATUS_BLOCK ioStatus, ref long allocSize, uint fileAttributes, FileShare share, uint createDisposition, uint createOptions, IntPtr eaBuffer, uint eaLength) { var result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); var fileName = Path.GetFileNameWithoutExtension(newFilePath); var ext = Path.GetExtension(newFilePath); var isWaveBank = ext.Equals(".xwb", StringComparison.OrdinalIgnoreCase); VirtualWaveBank waveBank = null; VirtualSoundBank soundBank = null; if (isWaveBank && !mWaveBankByName.TryGetValue(fileName, out waveBank)) { // Try get sound bank for cue names mSoundBankByName.TryGetValue(fileName, out soundBank); // Wave bank mWaveBankByName[fileName] = waveBank = new VirtualWaveBank(mLogger); // Load wave bank using (var fileStream = new FileStream(new SafeFileHandle(handle, true), FileAccess.Read, 1024 * 1024)) waveBank.LoadFromFile(newFilePath, fileStream); // Reopen file to reset it result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); ProcessWaveBankEntries(newFilePath, soundBank, waveBank); mLogger.Debug($"{newFilePath} registered"); } else if (!mSoundBankByName.TryGetValue(fileName, out soundBank)) { // Sound bank mSoundBankByName[fileName] = soundBank = new VirtualSoundBank(mLogger); // Load wave bank using (var fileStream = new FileStream(new SafeFileHandle(handle, true), FileAccess.Read, 1024 * 1024)) soundBank.LoadFromFile(newFilePath, fileStream); // Reopen file to reset it result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); // Find associated wave bank if (!mWaveBankByName.TryGetValue(soundBank.Native.WaveBankNames[0].Name, out waveBank)) { mLogger.Error($"{newFilePath} Can't find wavebank!"); } else { ProcessWaveBankEntries(newFilePath, soundBank, waveBank); } } if (isWaveBank) { mWaveBankByHandle.Add(handle, waveBank); mLogger.Debug($"{waveBank.FileName} Hnd {handle} registered"); } else { mSoundBankByHandle.Add(handle, soundBank); } return(result); }
public override Native.NtStatus NtCreateFileImpl(string filePath, out IntPtr handle, FileAccess access, ref Native.OBJECT_ATTRIBUTES objectAttributes, ref Native.IO_STATUS_BLOCK ioStatus, ref long allocSize, uint fileAttributes, FileShare share, uint createDisposition, uint createOptions, IntPtr eaBuffer, uint eaLength) { var result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); if (!mPacksByName.TryGetValue(filePath, out var pack)) { mPacksByName[filePath] = pack = new VirtualDwPack(mLogger, filePath); var pacIndex = int.Parse(pack.FileName.Substring(pack.FileName.Length - 5, 5)); var cpkName = pack.FileName.Substring(0, pack.FileName.Length - 5); var cpk = mLoadedCpks.Find(x => x.FileName.Contains(cpkName) && x.Entries.Any(y => y.PacIndex == pacIndex)); pack.Cpk = cpk; if (result != NtStatus.ObjectNameNotFound) { // Load file using (var fileStream = new FileStream(new SafeFileHandle(handle, true), FileAccess.Read, 1024 * 1024)) pack.LoadFromFile(filePath, fileStream); //pack.AddNewFiles( cpk ); // Reopen file to reset it result = mHooks.NtCreateFileHook.OriginalFunction(out handle, access, ref objectAttributes, ref ioStatus, ref allocSize, fileAttributes, share, createDisposition, createOptions, eaBuffer, eaLength); } else { pack.LoadFromCpk(pacIndex, cpk); handle = GenerateHandle(); ioStatus.Information = (IntPtr)1; ioStatus.Status = 0; result = NtStatus.Success; } mLogger.Debug($"Registered {filePath}"); // Entries are redirected as needed to improve startup performance } else if (result == NtStatus.ObjectNameNotFound) { // Find handle from name if (!mHandleByPack.TryGetValue(pack, out handle)) { handle = GenerateHandle(); } ioStatus.Information = (IntPtr)1; ioStatus.Status = 0; result = NtStatus.Success; } mPacksByHandle[handle] = new VirtualDwPackHandle() { Instance = pack }; mHandleByPack[pack] = handle; mLogger.Debug($"Hnd {handle} {filePath} handle registered"); return(result); }