void AddFile(File f) { listView1.Invoke((MethodInvoker)delegate { ListViewItem li = new ListViewItem(f.Name); li.Tag = f; ListViewItem.ListViewSubItem l1 = new ListViewItem.ListViewSubItem(li, f.EntryType); ListViewItem.ListViewSubItem l2 = new ListViewItem.ListViewSubItem(li, f.SizeFriendly); ListViewItem.ListViewSubItem l3 = new ListViewItem.ListViewSubItem(li, f.ModifiedDate.ToString()); li.SubItems.Add(l1); li.SubItems.Add(l2); li.SubItems.Add(l3); if (stfsInfo.Checked && f.IsSTFSPackage()) { ListViewItem.ListViewSubItem lsi = new ListViewItem.ListViewSubItem(li, f.ContentName()); li.SubItems.Add(lsi); } else { ListViewItem.ListViewSubItem lsi = new ListViewItem.ListViewSubItem(li, ""); li.SubItems.Add(lsi); } ListViewItem.ListViewSubItem l4 = new ListViewItem.ListViewSubItem(li, f.FullPath); li.SubItems.Add(l4); listView1.Invoke((MethodInvoker)delegate { listView1.Items.Add(li); }); }); }
public PropertiesForm(File f) { InitializeComponent(); contentImage1.ContextMenu = c_pic1; contentImage2.ContextMenu = c_pic2; xFile = f; this.Text = "Properties -- " + f.Name; if (!f.IsSTFSPackage()) { //The package isn't an stfs package -- disable that shit groupBox4.Enabled = false; } else { LoadSTFS(); } LoadGeneral(f); tabPage1.Click += new EventHandler(tabPage1_Click); #if TRACE //groupBox1.Visible = false; #endif #if DEBUG TabPage tabPage2 = new TabPage(); propertyGrid1.Dock = DockStyle.Fill; tabPage2.Controls.Add(this.propertyGrid1); tabPage2.Location = new System.Drawing.Point(4, 22); tabPage2.Name = "tabPage2"; tabPage2.Padding = new System.Windows.Forms.Padding(3); tabPage2.Size = new System.Drawing.Size(509, 320); tabPage2.TabIndex = 1; tabPage2.Text = "Entry"; tabPage2.UseVisualStyleBackColor = true; tabControl1.TabPages.Add(tabPage2); #endif this.Load += new EventHandler(PropertiesForm_Load); }
/// <summary> /// Gets the title names that correspond with title ID's from a file /// </summary> /// <returns>List of title ID's with their accurate title names</returns> private Structs.CachedTitleName[] CachedFromFile(File f) { List<Structs.CachedTitleName> tnl = new List<CLKsFATXLib.Structs.CachedTitleName>(); int BlockLength = 0x34; Streams.Reader r = new CLKsFATXLib.Streams.Reader(f.GetStream()); for (int i = 0, Previous = 0; i < r.BaseStream.Length / BlockLength; i++, Previous += 0x34) { // Set the position of the stream r.BaseStream.Position = Previous; // Create the new CachedTitleName struct Structs.CachedTitleName TN = new CLKsFATXLib.Structs.CachedTitleName(); // Read the title ID TN.ID = r.ReadUInt32(); // Read the name TN.Name = r.ReadCString(); // Add that to the list tnl.Add(TN); } return tnl.ToArray(); }
/// <summary> /// Returns the remaining size of a file/folder /// </summary> public static long RemainingData(File f) { long length = (long)(f.BlocksOccupied.Length - 1) * f.PartitionInfo.ClusterSize; return f.Size - length; }
public object[] GetEntries(Folder Parent) { List<Folder> cachedFolders = new List<Folder>(); List<Folder> cachedDeletedFolders = new List<Folder>(); List<File> cachedFiles = new List<File>(); List<File> cachedDeletedFiles = new List<File>(); EntryData[] Entries = GetEntryData(Parent); for (int i = 0; i < Entries.Length; i++) { EntryData newEdata = Entries[i]; bool Deleted = false; if (newEdata.NameSize == 0xE5) { // Remove the question marks and shit try { newEdata.Name = newEdata.Name.Remove(newEdata.Name.IndexOf('?')); newEdata.NameSize = (byte)newEdata.Name.Length; } catch { try { if (newEdata.Name.Contains("\0")) { newEdata.Name = newEdata.Name.Remove(newEdata.Name.IndexOf("\0")); newEdata.NameSize = (byte)newEdata.Name.Length; } else { newEdata.NameSize = 0x2A; } } catch { newEdata.NameSize = 0x2A; } } Deleted = true; } List<Geometry.Flags> FL = new List<Geometry.Flags>(); // Read bit zero, mask the rest of that shit for (short s = 1, j = 0; s <= 80; s <<= 1, j++) { if (((newEdata.Flags & s) >> j) == 1) { FL.Add((Geometry.Flags)Enum.Parse(typeof(Geometry.Flags), Enum.GetName(typeof(Geometry.Flags), j))); } } // Folder if (newEdata.StartingCluster != 0 && newEdata.Size == 0 && FL.Contains(Geometry.Flags.Directory)) { Folder f = new Folder(Parent.PartitionInfo, newEdata, Parent.Drive); f.FullPath = Parent.FullPath + "\\" + f.Name; f.Parent = Parent; if (Deleted) { f.IsDeleted = true; cachedDeletedFolders.Add(f); } else { cachedFolders.Add(f); } } // File else { File f = new File(Parent.PartitionInfo, newEdata, Parent.Drive); f.FullPath = Parent.FullPath + "\\" + f.Name; f.Parent = Parent; if (Deleted) { f.IsDeleted = true; cachedDeletedFiles.Add(f); } else { cachedFiles.Add(f); } } } return new object[] { cachedFiles, cachedFolders, cachedDeletedFiles, cachedDeletedFolders }; }
/// <summary> /// Gets the files contained in this folder /// </summary> /// <returns>File[] Files</returns> public File[] Files() { // If all of those guys are null, that means we have to re-load them. if (cachedFolders == null && cachedFiles == null && cachedDeletedFiles == null && cachedDeletedFolders == null) { object[] entries = new EntryFunctions(this).GetEntries(this); cachedFiles = (List<File>)entries[0]; cachedFolders = (List<Folder>)entries[1]; cachedDeletedFolders = (List<Folder>)entries[3]; cachedDeletedFiles = (List<File>)entries[2]; } if (ReturnDeletedEntries) { File[] list = new File[cachedFiles.Count + cachedDeletedFiles.Count]; Array.Copy(cachedFiles.ToArray(), 0, list, 0, cachedFiles.Count); Array.Copy(cachedDeletedFiles.ToArray(), 0, list, cachedFiles.Count, cachedDeletedFiles.Count); return list; } return cachedFiles.ToArray(); }
/// <summary> /// Creates a new file from the given path /// </summary> /// <param name="Path">Path to the file</param> /// <returns>Returns a WriteResult with a bool indicating whether or not there were problems writing the file. If true, then the Entry property will be the conflicting entry</returns> public Structs.WriteResult CreateNewFile(string Path) { // Check to see if the file they want to use is currently in use try { System.IO.FileStream fs = System.IO.File.Open(Path, System.IO.FileMode.Open); // Check file length if (fs.Length > UInt32.MaxValue) { throw new Exception("File size too large! Must be smaller than " + UInt32.MaxValue.ToString() + " bytes!"); } // File was good, continue fs.Close(); } catch (Exception x) { Console.WriteLine("Error occured when creating new file. File in use"); throw x; } if (fa.Cancel) { return new WriteResult() { CouldNotWrite = false, }; } System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); EntryEventArgs eea = new EntryEventArgs(); string NewName = System.IO.Path.GetFileName(Path); fa.CurrentFilePath = this.FullPath + "\\" + NewName; fa.CurrentFile = NewName; fa.MaxValue = 1; fa.Progress = 0; OnFolderAction(ref fa); WriteResult Return = new WriteResult(); Console.WriteLine("Comparing folder/file names"); foreach (Folder f in Folders()) { if (f.Name.ToLower() == NewName.ToLower()) { Return.Entry = f; Return.CouldNotWrite = true; Return.ConflictingEntryPath = f.FullPath; return Return; } } foreach (File f in Files()) { if (f.Name.ToLower() == NewName.ToLower()) { Return.Entry = f; Return.CouldNotWrite = true; Return.ConflictingEntryPath = f.FullPath; return Return; } } if (new System.IO.FileInfo(Path).Length == 0) { Console.WriteLine("Creating null file"); EntryData newE = new EntryFunctions(this).GetNewEntry(this, 0, new Geometry.Flags[0], NewName); try { Console.WriteLine("Getting blocks needed"); int BlocksNeeded = 1; Console.WriteLine(sw.Elapsed.ToString()); List<uint> Blocks = new List<uint>(); Console.WriteLine("Getting new entry"); if (newE.EntryOffset >= VariousFunctions.GetBlockOffset(this.BlocksOccupied[BlocksOccupied.Length - 1], this) + this.PartitionInfo.ClusterSize) { List<uint> blocks = this.BlocksOccupied.ToList(); blocks.Add(VariousFunctions.GetBlockFromOffset(newE.EntryOffset, this.PartitionInfo)); this.BlocksOccupied = blocks.ToArray(); } Console.WriteLine(sw.Elapsed.ToString()); Blocks.Add(newE.StartingCluster); // Write the file data... // FileAction to be used fa.MaxValue = Blocks.Count; File f = new File(this.PartitionInfo, newE, this.Drive); f.Parent = this; f.FullPath = this.FullPath + "\\" + f.Name; eea.ModifiedEntry = f; Return.Entry = f; this.cachedFiles.Add(f); fa.Progress = Blocks.Count; } // This excpetion here is going to be that we're out of space... catch (Exception x) { Console.WriteLine("Exception thrown, deleting written entry"); // Delete this entry newE.NameSize = 0xE5; // Create a new entry functions class so we can get rid of this entry EntryFunctions ef = new EntryFunctions(this); // Clear the FAT chain Console.WriteLine("Clearing FAT chain"); ef.ClearFATChain(new uint[] { newE.StartingCluster }); // Mark this entry as deleted ef.CreateNewEntry(newE); throw x; } } else { Console.WriteLine(sw.Elapsed.ToString()); Console.WriteLine("Getting blocks needed"); int BlocksNeeded = (int)(VariousFunctions.UpToNearestCluster(new System.IO.FileInfo(Path).Length, PartitionInfo.ClusterSize) / PartitionInfo.ClusterSize); Console.WriteLine(sw.Elapsed.ToString()); List<uint> Blocks = new List<uint>(); Console.WriteLine("Getting new entry"); EntryData newE = new EntryFunctions(this).GetNewEntry(this, (uint)new System.IO.FileInfo(Path).Length, new Geometry.Flags[0], NewName); if (newE.EntryOffset >= VariousFunctions.GetBlockOffset(this.BlocksOccupied[BlocksOccupied.Length - 1], this) + this.PartitionInfo.ClusterSize) { List<uint> blocks = this.BlocksOccupied.ToList(); blocks.Add(VariousFunctions.GetBlockFromOffset(newE.EntryOffset, this.PartitionInfo)); this.BlocksOccupied = blocks.ToArray(); } Console.WriteLine(sw.Elapsed.ToString()); Blocks.Add(newE.StartingCluster); try { Console.WriteLine("Getting free blocks"); Blocks.AddRange(Drive.GetFreeBlocks(this, BlocksNeeded - 1, newE.StartingCluster, 0, false)); Console.WriteLine(sw.Elapsed.ToString()); } // This excpetion here is going to be that we're out of space... catch (Exception x) { Console.WriteLine("Exception thrown, deleting written entry"); // Delete this entry newE.NameSize = 0xE5; // Create a new entry functions class so we can get rid of this entry EntryFunctions ef = new EntryFunctions(this); // Clear the FAT chain Console.WriteLine("Clearing FAT chain"); ef.ClearFATChain(new uint[] { newE.StartingCluster }); // Mark this entry as deleted ef.CreateNewEntry(newE); throw x; } Console.WriteLine("Writing FAT chain"); // Write that FAT chain new EntryFunctions(this).WriteFATChain(Blocks.ToArray()); Console.WriteLine(sw.Elapsed.ToString()); // Write the file data... // FileAction to be used fa.MaxValue = Blocks.Count; // The IO to read the file Streams.Reader FileReader = null; try { FileReader = new CLKsFATXLib.Streams.Reader(new System.IO.FileStream(Path, System.IO.FileMode.Open)); } catch { System.Threading.Thread.Sleep(1000); try { FileReader = new CLKsFATXLib.Streams.Reader(new System.IO.FileStream(Path, System.IO.FileMode.Open)); } catch (Exception x) { Console.WriteLine("Exception thrown, deleting written entry"); // Delete this entry newE.NameSize = 0xE5; // Create a new entry functions class so we can get rid of this entry EntryFunctions ef = new EntryFunctions(this); // Clear the FAT chain Console.WriteLine("Clearing FAT chain"); ef.ClearFATChain(Blocks.ToArray()); // Mark this entry as deleted ef.CreateNewEntry(newE); throw x; } } // The IO to write to the destination file Streams.Writer FileWriter = Drive.Writer(); // Loop for each block... for (int i = 0; i < Blocks.Count - 1; i++) { if (fa.Cancel) { Console.WriteLine("Cancel engaged"); FileReader.Close(); File newfile = new File(this.PartitionInfo, newE, this.Drive); newfile.Parent = this; newfile.FullPath = this.FullPath + "\\" + newfile.Name; this.cachedFiles.Add(newfile); eea.FullParentPath = FullPath; eea.ModifiedEntry = newfile; eea.ParentFolder = this; OnEntryEvent(ref eea); UpdateModifiedTime(); Return.Entry = newfile; return Return; } // Set the position to the beginning of the block FileWriter.BaseStream.Position = VariousFunctions.GetBlockOffset(Blocks[i], this); for (int j = 1, k = 0; j <= 0x100; j++, k++) { if (i + k == Blocks.Count - 1) { //Console.WriteLine("Writing part of file"); FileWriter.Write(FileReader.ReadBytes((int)PartitionInfo.ClusterSize * k)); i += k; fa.Progress += k; break; } else if (Blocks[i + k] == Blocks.Count - 2 || Blocks[i + k] + 1 != Blocks[i + j] || j == 10) { //Console.WriteLine("Writing part of file"); FileWriter.Write(FileReader.ReadBytes((int)PartitionInfo.ClusterSize * j)); i += k; fa.Progress += j; break; } } OnFolderAction(ref fa); } Console.WriteLine(sw.Elapsed.ToString()); // For the last cluster, we don't know how long it is... so we use // this nifty function I made to do that for us Console.WriteLine("Seeking to final cluster"); FileWriter.BaseStream.Position = VariousFunctions.GetBlockOffset(Blocks[Blocks.Count - 1], this); // Read/write data byte[] ToWrite = new byte[(int)VariousFunctions.UpToNearest200(VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this))]; if ((int)VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this) < (int)VariousFunctions.UpToNearest200((int)VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this))) { for (int i = (int)VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this) + 1; i < ToWrite.Length; i++) { ToWrite[i] = 0xFF; } } byte[] Buffer = FileReader.ReadBytes((int)VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this)); Array.Copy(Buffer, 0, ToWrite, 0, Buffer.Length); Buffer = null; Console.WriteLine("Writing final cluster"); FileWriter.Write(ToWrite); fa.Progress++; OnFolderAction(ref fa); Console.WriteLine("Closing streams"); FileReader.Close(); Console.WriteLine(sw.Elapsed.ToString()); File newF = new File(this.PartitionInfo, newE, this.Drive); newF.Parent = this; newF.FullPath = this.FullPath + "\\" + newF.Name; this.cachedFiles.Add(newF); Return.Entry = newF; eea.ModifiedEntry = newF; } eea.FullParentPath = FullPath; eea.ParentFolder = this; OnEntryEvent(ref eea); UpdateModifiedTime(); return Return; }
/// <summary> /// Creates a new, emptry file from the given path /// </summary> /// <param name="Path">Path to the file</param> /// <returns>Returns a WriteResult with a bool indicating whether or not there were problems writing the file. If true, then the Entry property will be the conflicting entry</returns> public Structs.WriteResult CreateFile(string NewName) { WriteResult Return = new WriteResult(); EntryEventArgs eea = new EntryEventArgs(); fa.CurrentFilePath = this.FullPath + "\\" + NewName; fa.CurrentFile = NewName; fa.MaxValue = 1; fa.Progress = 0; OnFolderAction(ref fa); foreach (Folder f in Folders()) { if (f.Name.ToLower() == NewName.ToLower()) { Return.Entry = f; Return.CouldNotWrite = true; Return.ConflictingEntryPath = f.FullPath; return Return; } } foreach (File f in Files()) { if (f.Name.ToLower() == NewName.ToLower()) { Return.Entry = f; Return.CouldNotWrite = true; Return.ConflictingEntryPath = f.FullPath; return Return; } } EntryData newE = new EntryFunctions(this).GetNewEntry(this, 0, new Geometry.Flags[0], NewName); int BlocksNeeded = 1; List<uint> Blocks = new List<uint>(); Console.WriteLine("Getting new entry"); if (newE.EntryOffset >= VariousFunctions.GetBlockOffset(this.BlocksOccupied[BlocksOccupied.Length - 1], this) + this.PartitionInfo.ClusterSize) { List<uint> blocks = this.BlocksOccupied.ToList(); blocks.Add(VariousFunctions.GetBlockFromOffset(newE.EntryOffset, this.PartitionInfo)); this.BlocksOccupied = blocks.ToArray(); } { Blocks.Add(newE.StartingCluster); // Write the file data... // FileAction to be used fa.MaxValue = Blocks.Count; OnFolderAction(ref fa); File f = new File(this.PartitionInfo, newE, this.Drive); f.Parent = this; f.FullPath = this.FullPath + "\\" + f.Name; eea.ModifiedEntry = f; Return.Entry = f; this.cachedFiles.Add(f); fa.Progress = Blocks.Count; OnFolderAction(ref fa); eea.FullParentPath = FullPath; eea.ParentFolder = this; OnEntryEvent(ref eea); return Return; } }
/** * Title: Xbox 360 Forensic Toolkit. * Description: Xbox 360 Forensic Toolkit is built on top of the Party buffalo application. It allows users to read and * write to Xbox 360 devices, with support for reading Xbox 360 STFS package names. A number of Forensic Tools have * been added to extract/view sectors, extract partitions, view file details, examine files in HEX. It also incorporates the wxPIRS * Application so that we can sissamble STFS packages and see their contents. * * Original Author: Party Buffalo - [email protected], wxPIRS - gael360 * Another Author: [email protected] * License: http://www.gnu.org/licenses/gpl.html GNU GENERAL PUBLIC LICENSE * Link: https://code.google.com/p/party-buffalo/ * http://gael360.free.fr/ * Note: All Code that follows to the End point was added by [email protected] */ public MainForm(CLKsFATXLib.File f) { xFile = f; STFSFile = true; InitializeComponent(); }