internal void FlashMMOSTask(string MMOSPath) { NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel; if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) { Phone.SwitchToFlashAppContext(); } new Thread(() => { bool Result = true; ActivateSubContext(new BusyViewModel("Initializing flash...")); string ErrorSubMessage = null; try { FileInfo info = new FileInfo(MMOSPath); uint length = uint.Parse(info.Length.ToString()); int maximumbuffersize = 0x00240000; uint totalcounts = (uint)Math.Truncate((decimal)length / maximumbuffersize); BusyViewModel Busy = new BusyViewModel("Flashing Test Mode package...", MaxProgressValue: totalcounts, UIContext: UIContext); ActivateSubContext(Busy); Phone.FlashMMOS(MMOSPath, Busy.ProgressUpdater); ActivateSubContext(new BusyViewModel("And now booting phone to MMOS...", "If the phone stays on the lightning cog screen for a while, you may need to unplug and replug the phone to continue the boot process.")); PhoneNotifier.NewDeviceArrived += NewDeviceArrived; } catch (Exception Ex) { LogFile.LogException(Ex); if (Ex is WPinternalsException) { ErrorSubMessage = ((WPinternalsException)Ex).SubMessage; } Result = false; } if (!Result) { ExitFailure("Flash failed!", ErrorSubMessage); return; } }).Start(); }
internal void UpdateWorkingStatus(string Message, string SubMessage, ulong?CurrentProgressValue, WPinternalsStatus Status = WPinternalsStatus.Undefined) { if (SubContextViewModel is BusyViewModel) { BusyViewModel Busy = (BusyViewModel)SubContextViewModel; if (Message != null) { Busy.Message = Message; Busy.SubMessage = SubMessage; } if ((CurrentProgressValue != null) && (Busy.ProgressUpdater != null)) { try { Busy.ProgressUpdater.SetProgress((ulong)CurrentProgressValue); } catch (Exception Ex) { LogFile.LogException(Ex); } } } }
internal void FlashPartitionsTask(string EFIESPPath, string MainOSPath, string DataPath) { new Thread(() => { bool Result = true; ActivateSubContext(new BusyViewModel("Initializing flash...")); NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel; GPT GPT = Phone.ReadGPT(); ulong TotalSizeSectors = 0; int PartitionCount = 0; ulong MainOSOldSectorCount = 0; ulong MainOSNewSectorCount = 0; ulong DataOldSectorCount = 0; ulong DataNewSectorCount = 0; ulong FirstMainOSSector = 0; try { if (EFIESPPath != null) { using (Stream Stream = new DecompressedStream(File.Open(EFIESPPath, FileMode.Open))) { ulong StreamLengthInSectors = (ulong)Stream.Length / 0x200; TotalSizeSectors += StreamLengthInSectors; PartitionCount++; Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, "EFIESP", true) == 0).FirstOrDefault(); if (StreamLengthInSectors > Partition.SizeInSectors) { LogFile.Log("Flash failed! Size of partition 'EFIESP' is too big."); ExitFailure("Flash failed!", "Size of partition 'EFIESP' is too big."); return; } } } if (MainOSPath != null) { using (Stream Stream = new DecompressedStream(File.Open(MainOSPath, FileMode.Open))) { ulong StreamLengthInSectors = (ulong)Stream.Length / 0x200; TotalSizeSectors += StreamLengthInSectors; PartitionCount++; Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, "MainOS", true) == 0).FirstOrDefault(); MainOSOldSectorCount = Partition.SizeInSectors; MainOSNewSectorCount = StreamLengthInSectors; FirstMainOSSector = Partition.FirstSector; } } if (DataPath != null) { using (Stream Stream = new DecompressedStream(File.Open(DataPath, FileMode.Open))) { ulong StreamLengthInSectors = (ulong)Stream.Length / 0x200; TotalSizeSectors += StreamLengthInSectors; PartitionCount++; Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, "Data", true) == 0).FirstOrDefault(); DataOldSectorCount = Partition.SizeInSectors; DataNewSectorCount = StreamLengthInSectors; } } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } if ((MainOSNewSectorCount > 0) && (DataNewSectorCount > 0)) { if ((MainOSNewSectorCount > MainOSOldSectorCount) || (DataNewSectorCount > DataOldSectorCount)) { UInt64 OSSpace = GPT.LastUsableSector - FirstMainOSSector + 1; if ((MainOSNewSectorCount + DataNewSectorCount) <= OSSpace) { // MainOS and Data partitions need to be re-aligned! Partition MainOSPartition = GPT.Partitions.Where(p => string.Compare(p.Name, "MainOS", true) == 0).Single(); Partition DataPartition = GPT.Partitions.Where(p => string.Compare(p.Name, "Data", true) == 0).Single(); MainOSPartition.LastSector = MainOSPartition.FirstSector + MainOSNewSectorCount - 1; DataPartition.FirstSector = MainOSPartition.LastSector + 1; DataPartition.LastSector = DataPartition.FirstSector + DataNewSectorCount - 1; Phone.WriteGPT(GPT); } else { LogFile.Log("Flash failed! Size of partitions 'MainOS' and 'Data' together are too big."); ExitFailure("Flash failed!", "Sizes of partitions 'MainOS' and 'Data' together are too big."); return; } } } else if ((MainOSNewSectorCount > 0) && (MainOSNewSectorCount > MainOSOldSectorCount)) { LogFile.Log("Flash failed! Size of partition 'MainOS' is too big."); ExitFailure("Flash failed!", "Size of partition 'MainOS' is too big."); return; } else if ((DataNewSectorCount > 0) && (DataNewSectorCount > DataOldSectorCount)) { LogFile.Log("Flash failed! Size of partition 'Data' is too big."); ExitFailure("Flash failed!", "Size of partition 'Data' together is too big."); return; } BusyViewModel Busy = new BusyViewModel("Flashing...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); ProgressUpdater Updater = Busy.ProgressUpdater; ActivateSubContext(Busy); int i = 0; if (Result) { try { if (EFIESPPath != null) { i++; Busy.Message = "Flashing partition EFIESP (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(EFIESPPath, "EFIESP", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (MainOSPath != null) { i++; Busy.Message = "Flashing partition MainOS (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(MainOSPath, "MainOS", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (DataPath != null) { i++; Busy.Message = "Flashing partition Data (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(DataPath, "Data", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (!Result) { ExitFailure("Flash failed!", null); return; } ExitSuccess("Flash successful! Make sure you disable Windows Update on the phone!", null); }).Start(); }
internal void FlashFFUTask(string FFUPath) { new Thread(() => { bool Result = true; NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel; PhoneInfo Info = Phone.ReadPhoneInfo(false); #region Remove bootloader changes // If necessary remove bootloader changes // In case the NV vars were redirected, and a stock FFU is flashed, then the IsFlashing flag will be cleared in the redirected NV vars // And after a reboot the original NV vars are active again, but the IsFlashing flag is still set from when the bootloader was unlocked // So we will first restore the GPT, so the original vars are active again. // Then IsFlashing is true and the phone boots forcibly to FlashApp again. // Then we start normal FFU flasing and at the end the IsFlashing flag is cleared in the original vars. if (Info.FlashAppProtocolVersionMajor >= 2) { byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(Phone, 0x20000); // TODO: Get proper profile FFU and get ChunkSizeInBytes GPT GPT = new GPT(GPTChunk); FlashPart Part; List <FlashPart> FlashParts = new List <FlashPart>(); Partition NvBackupPartition = GPT.GetPartition("BACKUP_BS_NV"); if (NvBackupPartition != null) { // This must be a left over of a half unlocked bootloader Partition NvPartition = GPT.GetPartition("UEFI_BS_NV"); NvBackupPartition.Name = "UEFI_BS_NV"; NvBackupPartition.PartitionGuid = NvPartition.PartitionGuid; NvBackupPartition.PartitionTypeGuid = NvPartition.PartitionTypeGuid; GPT.Partitions.Remove(NvPartition); GPT.Rebuild(); Part = new FlashPart(); Part.StartSector = 0; Part.Stream = new MemoryStream(GPTChunk); FlashParts.Add(Part); } bool ClearFlashingStatus = true; // We should only clear NV if there was no backup NV to be restored and the current NV contains the SB unlock. if ((NvBackupPartition == null) && !Info.UefiSecureBootEnabled) { // ClearNV Part = new FlashPart(); Partition Target = GPT.GetPartition("UEFI_BS_NV"); Part.StartSector = (UInt32)Target.FirstSector; Part.Stream = new MemoryStream(new byte[0x40000]); FlashParts.Add(Part); ClearFlashingStatus = false; } if (FlashParts.Count > 0) { ActivateSubContext(new BusyViewModel("Restoring bootloader...")); WPinternalsStatus LastStatus = WPinternalsStatus.Undefined; LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, FFUPath, false, false, FlashParts, true, ClearFlashingStatusAtEnd: ClearFlashingStatus, SetWorkingStatus: (m, s, v, a, st) => { if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset)) { SetWorkingStatus(m, s, v, a, st); } else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset)) { SetWorkingStatus("Restoring bootloader...", null, null, Status: WPinternalsStatus.Flashing); } LastStatus = st; }, UpdateWorkingStatus: (m, s, v, st) => { if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset)) { UpdateWorkingStatus(m, s, v, st); } else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset)) { SetWorkingStatus("Restoring bootloader...", null, null, Status: WPinternalsStatus.Flashing); } LastStatus = st; } ).Wait(); if ((PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)) { PhoneNotifier.WaitForArrival().Wait(); } if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) { ((NokiaFlashModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext(); } } } #endregion Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel; ActivateSubContext(new BusyViewModel("Initializing flash...")); string ErrorSubMessage = null; try { FFU FFU = new FFU(FFUPath); BusyViewModel Busy = new BusyViewModel("Flashing original FFU...", MaxProgressValue: FFU.TotalChunkCount, UIContext: UIContext); ActivateSubContext(Busy); byte Options = 0; if (!Info.IsBootloaderSecure) { Options = (byte)((FlashOptions)Options | FlashOptions.SkipSignatureCheck); } Phone.FlashFFU(FFU, Busy.ProgressUpdater, true, Options); } catch (Exception Ex) { LogFile.LogException(Ex); if (Ex is WPinternalsException) { ErrorSubMessage = ((WPinternalsException)Ex).SubMessage; } Result = false; } if (!Result) { ExitFailure("Flash failed!", ErrorSubMessage); return; } ExitSuccess("Flash successful!", null); }).Start(); }
internal void FlashArchiveTask(string ArchivePath) { new Thread(() => { ActivateSubContext(new BusyViewModel("Initializing flash...")); NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel; ulong TotalSizeSectors = 0; int PartitionCount = 0; ulong MainOSOldSectorCount = 0; ulong MainOSNewSectorCount = 0; ulong DataOldSectorCount = 0; ulong DataNewSectorCount = 0; ulong FirstMainOSSector = 0; bool GPTChanged = false; try { GPT GPT = Phone.ReadGPT(); using (FileStream FileStream = new FileStream(ArchivePath, FileMode.Open)) { using (ZipArchive Archive = new ZipArchive(FileStream, ZipArchiveMode.Read)) { foreach (ZipArchiveEntry Entry in Archive.Entries) { // Determine if there is a partition layout present ZipArchiveEntry PartitionEntry = Archive.GetEntry("Partitions.xml"); if (PartitionEntry == null) { GPT.MergePartitions(null, false, Archive); GPTChanged |= GPT.HasChanged; } else { using (Stream ZipStream = PartitionEntry.Open()) { using (StreamReader ZipReader = new StreamReader(ZipStream)) { string PartitionXml = ZipReader.ReadToEnd(); GPT.MergePartitions(PartitionXml, false, Archive); GPTChanged |= GPT.HasChanged; } } } // First determine if we need a new GPT! if (!Entry.FullName.Contains("/")) // No subfolders { string PartitionName = System.IO.Path.GetFileNameWithoutExtension(Entry.Name); int P = PartitionName.IndexOf('.'); if (P >= 0) { PartitionName = PartitionName.Substring(0, P); // Example: Data.bin.gz -> Data } Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, PartitionName, true) == 0).FirstOrDefault(); if (Partition != null) { DecompressedStream DecompressedStream = new DecompressedStream(Entry.Open()); ulong StreamLengthInSectors = (ulong)Entry.Length / 0x200; try { StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200; } catch { } TotalSizeSectors += StreamLengthInSectors; PartitionCount++; if (string.Compare(PartitionName, "MainOS", true) == 0) { MainOSOldSectorCount = Partition.SizeInSectors; MainOSNewSectorCount = StreamLengthInSectors; FirstMainOSSector = Partition.FirstSector; } else if (string.Compare(PartitionName, "Data", true) == 0) { DataOldSectorCount = Partition.SizeInSectors; DataNewSectorCount = StreamLengthInSectors; } else if (StreamLengthInSectors > Partition.SizeInSectors) { LogFile.Log("Flash failed! Size of partition '" + PartitionName + "' is too big."); ExitFailure("Flash failed!", "Size of partition '" + PartitionName + "' is too big."); return; } } } } if ((MainOSNewSectorCount > 0) && (DataNewSectorCount > 0)) { if ((MainOSNewSectorCount > MainOSOldSectorCount) || (DataNewSectorCount > DataOldSectorCount)) { UInt64 OSSpace = GPT.LastUsableSector - FirstMainOSSector + 1; if ((MainOSNewSectorCount + DataNewSectorCount) <= OSSpace) { // MainOS and Data partitions need to be re-aligned! Partition MainOSPartition = GPT.Partitions.Where(p => string.Compare(p.Name, "MainOS", true) == 0).Single(); Partition DataPartition = GPT.Partitions.Where(p => string.Compare(p.Name, "Data", true) == 0).Single(); MainOSPartition.LastSector = MainOSPartition.FirstSector + MainOSNewSectorCount - 1; DataPartition.FirstSector = MainOSPartition.LastSector + 1; DataPartition.LastSector = DataPartition.FirstSector + DataNewSectorCount - 1; GPTChanged = true; } else { LogFile.Log("Flash failed! Size of partitions 'MainOS' and 'Data' together are too big."); ExitFailure("Flash failed!", "Sizes of partitions 'MainOS' and 'Data' together are too big."); return; } } } else if ((MainOSNewSectorCount > 0) && (MainOSNewSectorCount > MainOSOldSectorCount)) { LogFile.Log("Flash failed! Size of partition 'MainOS' is too big."); ExitFailure("Flash failed!", "Size of partition 'MainOS' is too big."); return; } else if ((DataNewSectorCount > 0) && (DataNewSectorCount > DataOldSectorCount)) { LogFile.Log("Flash failed! Size of partition 'Data' is too big."); ExitFailure("Flash failed!", "Size of partition 'Data' is too big."); return; } if (GPTChanged) { Phone.WriteGPT(GPT); } if (PartitionCount > 0) { BusyViewModel Busy = new BusyViewModel("Flashing...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); ProgressUpdater Updater = Busy.ProgressUpdater; ActivateSubContext(Busy); int i = 0; foreach (ZipArchiveEntry Entry in Archive.Entries) { // "MainOS.bin.gz" => "MainOS" string PartitionName = Entry.Name; int Pos = PartitionName.IndexOf('.'); if (Pos >= 0) { PartitionName = PartitionName.Substring(0, Pos); } Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, PartitionName, true) == 0).FirstOrDefault(); if (Partition != null) { Stream DecompressedStream = new DecompressedStream(Entry.Open()); ulong StreamLengthInSectors = (ulong)Entry.Length / 0x200; try { StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200; } catch { } if (StreamLengthInSectors <= Partition.SizeInSectors) { i++; Busy.Message = "Flashing partition " + Partition.Name + " (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(DecompressedStream, Partition.Name, Updater); } DecompressedStream.Close(); } } } else { LogFile.Log("Flash failed! No valid partitions found in the archive."); ExitFailure("Flash failed!", "No valid partitions found in the archive"); return; } } } } catch (Exception Ex) { LogFile.LogException(Ex); if (Ex is WPinternalsException) { ExitFailure("Flash failed!", ((WPinternalsException)Ex).SubMessage); } else { ExitFailure("Flash failed!", null); } return; } ExitSuccess("Flash successful! Make sure you disable Windows Update on the phone!", null); }).Start(); }
internal void RestoreTask(string EFIESPPath, string MainOSPath, string DataPath) { new Thread(() => { bool Result = true; ActivateSubContext(new BusyViewModel("Initializing restore...")); ulong TotalSizeSectors = 0; int PartitionCount = 0; try { if (EFIESPPath != null) { TotalSizeSectors += (ulong)new FileInfo(EFIESPPath).Length / 0x200; PartitionCount++; } if (MainOSPath != null) { TotalSizeSectors += (ulong)new FileInfo(MainOSPath).Length / 0x200; PartitionCount++; } if (DataPath != null) { TotalSizeSectors += (ulong)new FileInfo(DataPath).Length / 0x200; PartitionCount++; } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel; BusyViewModel Busy = new BusyViewModel("Restoring...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); ProgressUpdater Updater = Busy.ProgressUpdater; ActivateSubContext(Busy); int i = 0; if (Result) { try { if (EFIESPPath != null) { i++; Busy.Message = "Restoring partition EFIESP (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(EFIESPPath, "EFIESP", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (MainOSPath != null) { i++; Busy.Message = "Restoring partition MainOS (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(EFIESPPath, "MainOS", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (DataPath != null) { i++; Busy.Message = "Restoring partition Data (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(EFIESPPath, "Data", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (!Result) { ActivateSubContext(new MessageViewModel("Failed to restore!", Exit)); return; } ActivateSubContext(new MessageViewModel("Successfully restored!", Exit)); }).Start(); }
internal void BackupTask(string EFIESPPath, string MainOSPath, string DataPath) { IsSwitchingInterface = false; new Thread(() => { bool Result = true; ActivateSubContext(new BusyViewModel("Initializing backup...")); ulong TotalSizeSectors = 0; int PartitionCount = 0; MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel; Phone.OpenVolume(false); byte[] GPTBuffer = Phone.ReadSectors(1, 33); GPT GPT = new WPinternals.GPT(GPTBuffer); Partition Partition; try { if (EFIESPPath != null) { Partition = GPT.Partitions.Where(p => p.Name == "EFIESP").First(); TotalSizeSectors += Partition.SizeInSectors; PartitionCount++; } if (MainOSPath != null) { Partition = GPT.Partitions.Where(p => p.Name == "MainOS").First(); TotalSizeSectors += Partition.SizeInSectors; PartitionCount++; } if (DataPath != null) { Partition = GPT.Partitions.Where(p => p.Name == "Data").First(); TotalSizeSectors += Partition.SizeInSectors; PartitionCount++; } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } BusyViewModel Busy = new BusyViewModel("Create backup...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); ProgressUpdater Updater = Busy.ProgressUpdater; ActivateSubContext(Busy); int i = 0; if (Result) { try { if (EFIESPPath != null) { i++; Busy.Message = "Create backup of partition EFIESP (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.BackupPartition("EFIESP", EFIESPPath, Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (MainOSPath != null) { i++; Busy.Message = "Create backup of partition MainOS (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.BackupPartition("MainOS", MainOSPath, Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (DataPath != null) { i++; Busy.Message = "Create backup of partition Data (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.BackupPartition("Data", DataPath, Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } Phone.CloseVolume(); if (!Result) { ActivateSubContext(new MessageViewModel("Failed to create backup!", Exit)); return; } ActivateSubContext(new MessageViewModel("Successfully created a backup!", Exit)); }).Start(); }
internal void BackupArchiveTask(string ArchivePath) { IsSwitchingInterface = false; new Thread(() => { bool Result = true; ActivateSubContext(new BusyViewModel("Initializing backup...")); ulong TotalSizeSectors = 0; int PartitionCount = 3; MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel; try { Phone.OpenVolume(false); byte[] GPTBuffer = Phone.ReadSectors(1, 33); GPT GPT = new WPinternals.GPT(GPTBuffer); Partition Partition; try { Partition = GPT.Partitions.Where(p => p.Name == "EFIESP").First(); TotalSizeSectors += Partition.SizeInSectors; Partition = GPT.Partitions.Where(p => p.Name == "MainOS").First(); TotalSizeSectors += Partition.SizeInSectors; Partition = GPT.Partitions.Where(p => p.Name == "Data").First(); TotalSizeSectors += Partition.SizeInSectors; } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } BusyViewModel Busy = new BusyViewModel("Create backup...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); ProgressUpdater Updater = Busy.ProgressUpdater; ActivateSubContext(Busy); ZipArchiveEntry Entry; Stream EntryStream = null; using (FileStream FileStream = new FileStream(ArchivePath, FileMode.Create)) { using (ZipArchive Archive = new ZipArchive(FileStream, ZipArchiveMode.Create)) { int i = 0; if (Result) { try { Entry = Archive.CreateEntry("EFIESP.bin", CompressionLevel.Optimal); EntryStream = Entry.Open(); i++; Busy.Message = "Create backup of partition EFIESP (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.BackupPartition("EFIESP", EntryStream, Updater); } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } finally { if (EntryStream != null) { EntryStream.Close(); } EntryStream = null; } } if (Result) { try { Entry = Archive.CreateEntry("MainOS.bin", CompressionLevel.Optimal); EntryStream = Entry.Open(); i++; Busy.Message = "Create backup of partition MainOS (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.BackupPartition("MainOS", EntryStream, Updater); } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } finally { if (EntryStream != null) { EntryStream.Close(); } EntryStream = null; } } if (Result) { try { Entry = Archive.CreateEntry("Data.bin", CompressionLevel.Optimal); EntryStream = Entry.Open(); i++; Busy.Message = "Create backup of partition Data (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.BackupPartition("Data", EntryStream, Updater); } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } finally { if (EntryStream != null) { EntryStream.Close(); } EntryStream = null; } } } } } catch { } finally { Phone.CloseVolume(); } if (!Result) { ActivateSubContext(new MessageViewModel("Failed to create backup!", Exit)); return; } ActivateSubContext(new MessageViewModel("Successfully created a backup!", Exit)); }).Start(); }
internal void DoDumpRom(string FFUPath, string EFIESPPath, bool CompressEFIESP, string MainOSPath, bool CompressMainOS, string DataPath, bool CompressData) { new Thread(() => { bool Result = true; ActivateSubContext(new BusyViewModel("Initializing ROM dump...")); ulong TotalSizeSectors = 0; int PartitionCount = 0; Partition Partition; FFU FFU = null; try { FFU = new FFU(FFUPath); if (EFIESPPath != null) { Partition = FFU.GPT.Partitions.Where(p => p.Name == "EFIESP").First(); TotalSizeSectors += Partition.SizeInSectors; PartitionCount++; } if (MainOSPath != null) { Partition = FFU.GPT.Partitions.Where(p => p.Name == "MainOS").First(); TotalSizeSectors += Partition.SizeInSectors; PartitionCount++; } if (DataPath != null) { Partition = FFU.GPT.Partitions.Where(p => p.Name == "Data").First(); TotalSizeSectors += Partition.SizeInSectors; PartitionCount++; } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } // We are on a worker thread! // So we must pass the SynchronizationContext of the UI thread BusyViewModel Busy = new BusyViewModel("Dumping ROM...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); ProgressUpdater Updater = Busy.ProgressUpdater; ActivateSubContext(Busy); int i = 0; if (Result) { try { if (EFIESPPath != null) { i++; Busy.Message = "Dumping partition EFIESP (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; FFU.WritePartition("EFIESP", EFIESPPath, Updater, CompressEFIESP); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (MainOSPath != null) { i++; Busy.Message = "Dumping partition MainOS (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; FFU.WritePartition("MainOS", MainOSPath, Updater, CompressMainOS); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (DataPath != null) { i++; Busy.Message = "Dumping partition Data (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; FFU.WritePartition("Data", DataPath, Updater, CompressData); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (!Result) { ActivateSubContext(new MessageViewModel("Failed to dump ROM partitions!", Restart)); return; } ActivateSubContext(new MessageViewModel("Successfully dumped ROM partitions!", Restart)); }).Start(); }