diff --git a/App.xaml.cs b/App.xaml.cs index eb6f4d7..34a5dd6 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -52,17 +52,21 @@ namespace WPinternals if (Environment.GetCommandLineArgs().Count() > 1) CommandLine.OpenConsole(); - if (!mutex.WaitOne(0, false)) + try { - if (Environment.GetCommandLineArgs().Count() > 1) + if (!mutex.WaitOne(0, false)) { - Console.WriteLine("Windows Phone Internals is already running"); - CommandLine.CloseConsole(); + if (Environment.GetCommandLineArgs().Count() > 1) + { + Console.WriteLine("Windows Phone Internals is already running"); + CommandLine.CloseConsole(); + } + else + MessageBox.Show("Windows Phone Internals is already running.", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation); + Environment.Exit(0); } - else - MessageBox.Show("Windows Phone Internals is already running.", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation); - Environment.Exit(0); } + catch (AbandonedMutexException) { }; Registration.CheckExpiration(); diff --git a/CommandLine.cs b/CommandLine.cs index 1061b71..b4b8176 100644 --- a/CommandLine.cs +++ b/CommandLine.cs @@ -465,7 +465,7 @@ namespace WPinternals if (FFUs.Count() > 0) ProfileFFU = new FFU(FFUs[0].Path); else - throw new WPinternalsException("Profile FFU missing"); + throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line."); } LogFile.Log("Profile FFU: " + ProfileFFU.Path); @@ -601,7 +601,7 @@ namespace WPinternals if (FFUs.Count() > 0) ProfileFFU = new FFU(FFUs[0].Path); else - throw new WPinternalsException("Profile FFU missing"); + throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line."); } LogFile.Log("Profile FFU: " + ProfileFFU.Path); @@ -611,7 +611,7 @@ namespace WPinternals if (FFUs.Count() > 0) SupportedFFU = new FFU(FFUs[0].Path); else - throw new WPinternalsException("No donor-FFU found with supported OS version"); + throw new WPinternalsException("No donor-FFU found with supported OS version", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process."); } await LumiaUnlockBootloaderViewModel.LumiaUnlockUEFI(Notifier, ProfileFFU.Path, null, SupportedFFU.Path); @@ -695,7 +695,7 @@ namespace WPinternals App.PatchEngine.TargetPath = Drive + "\\"; PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS"); if (!PatchResult) - throw new WPinternalsException("Patch failed"); + throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the MainOS partition of your phone. Make sure your phone runs a supported Operating System version."); LogFile.Log("Fixed bootloader", LogType.FileAndConsole); LogFile.Log("The phone is left in Mass Storage mode", LogType.FileAndConsole); LogFile.Log("Press and hold the power-button of the phone for at least 10 seconds to reset the phone", LogType.FileAndConsole); @@ -721,14 +721,14 @@ namespace WPinternals App.PatchEngine.TargetPath = Drive + "\\EFIESP\\"; PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP"); if (!PatchResult) - throw new WPinternalsException("Patch failed"); + throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the EFIESP partition of your phone. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported."); App.PatchEngine.TargetPath = Drive + "\\"; PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS"); if (!PatchResult) - throw new WPinternalsException("Patch failed"); + throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the MainOS partition of your phone. Make sure your phone runs a supported Operating System version."); PatchResult = App.PatchEngine.Patch("RootAccess-MainOS"); if (!PatchResult) - throw new WPinternalsException("Patch failed"); + throw new WPinternalsException("Patch failed", "An error occured while modifying Operating System files on the MainOS partition of your phone for Root Access. Make sure your phone runs a supported Operating System version."); LogFile.Log("Root Access enabled!", LogType.FileAndConsole); LogFile.Log("The phone is left in Mass Storage mode", LogType.FileAndConsole); LogFile.Log("Press and hold the power-button of the phone for at least 10 seconds to reset the phone", LogType.FileAndConsole); @@ -785,7 +785,7 @@ namespace WPinternals App.PatchEngine.TargetImage = UnlockedEFIESPFileSystem; PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP"); if (!PatchResult) - throw new WPinternalsException("Failed to patch bootloader"); + throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible."); // Edit BCD LogFile.Log("Edit BCD"); @@ -820,7 +820,7 @@ namespace WPinternals App.PatchEngine.TargetImage = UnlockedMainOsFileSystem; PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS"); if (!PatchResult) - throw new WPinternalsException("Failed to patch MainOS"); + throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version."); } } LogFile.Log("Bootloader unlocked on image", LogType.FileAndConsole); @@ -863,7 +863,7 @@ namespace WPinternals App.PatchEngine.TargetImage = UnlockedEFIESPFileSystem; PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP"); if (!PatchResult) - throw new WPinternalsException("Failed to patch bootloader"); + throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible."); // Edit BCD LogFile.Log("Edit BCD"); @@ -896,10 +896,10 @@ namespace WPinternals App.PatchEngine.TargetImage = UnlockedMainOsFileSystem; PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS"); if (!PatchResult) - throw new WPinternalsException("Failed to patch MainOS"); + throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version."); PatchResult = App.PatchEngine.Patch("RootAccess-MainOS"); if (!PatchResult) - throw new WPinternalsException("Failed to patch MainOS"); + throw new WPinternalsException("Failed to patch MainOS", "An error occured while modifying Operating System files on the MainOS partition you provided for Root Access. Make sure your phone runs a supported Operating System version."); } LogFile.Log("Root access enabled on image", LogType.FileAndConsole); break; @@ -942,7 +942,7 @@ namespace WPinternals App.PatchEngine.TargetPath = EfiEspImagePath; PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP"); if (!PatchResult) - throw new WPinternalsException("Failed to patch bootloader"); + throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible."); // Edit BCD LogFile.Log("Edit BCD"); @@ -972,7 +972,7 @@ namespace WPinternals App.PatchEngine.TargetPath = MainOsImagePath; PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS"); if (!PatchResult) - throw new WPinternalsException("Failed to patch MainOS"); + throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version."); } LogFile.Log("Bootloader unlocked on image", LogType.FileAndConsole); break; @@ -1010,7 +1010,7 @@ namespace WPinternals App.PatchEngine.TargetPath = EfiEspImagePath; PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP"); if (!PatchResult) - throw new WPinternalsException("Failed to patch bootloader"); + throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible."); // Edit BCD LogFile.Log("Edit BCD"); @@ -1038,10 +1038,10 @@ namespace WPinternals App.PatchEngine.TargetPath = MainOsImagePath; PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS"); if (!PatchResult) - throw new WPinternalsException("Failed to patch MainOS"); + throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version."); PatchResult = App.PatchEngine.Patch("RootAccess-MainOS"); if (!PatchResult) - throw new WPinternalsException("Failed to patch MainOS"); + throw new WPinternalsException("Failed to patch MainOS", "An error occured while modifying Operating System files on the MainOS partition you provided for Root Access. Make sure your phone runs a supported Operating System version."); LogFile.Log("Root access enabled on image", LogType.FileAndConsole); break; case "downloadffu": @@ -1362,7 +1362,7 @@ namespace WPinternals App.Config.AddFfuToRepository(FFUFilePath); if (App.Config.FFURepository.Where(e => App.PatchEngine.PatchDefinitions.Where(p => p.Name == "SecureBootHack-V2-EFIESP").First().TargetVersions.Any(v => v.Description == e.OSVersion)).Count() == 0) - throw new WPinternalsException("Unable to find compatible FFU"); + throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process."); } Notifier.Stop(); break; @@ -1443,7 +1443,7 @@ namespace WPinternals App.Config.AddFfuToRepository(FFUFilePath); if (App.Config.FFURepository.Where(e => App.PatchEngine.PatchDefinitions.Where(p => p.Name == "SecureBootHack-V2-EFIESP").First().TargetVersions.Any(v => v.Description == e.OSVersion)).Count() == 0) - throw new WPinternalsException("Unable to find compatible FFU"); + throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process."); } break; case "downloadallbyproductcode": @@ -1523,7 +1523,7 @@ namespace WPinternals App.Config.AddFfuToRepository(FFUFilePath); if (App.Config.FFURepository.Where(e => App.PatchEngine.PatchDefinitions.Where(p => p.Name == "SecureBootHack-V2-EFIESP").First().TargetVersions.Any(v => v.Description == e.OSVersion)).Count() == 0) - throw new WPinternalsException("Unable to find compatible FFU"); + throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process."); } break; case "downloadallbyoperatorcode": @@ -1605,7 +1605,7 @@ namespace WPinternals App.Config.AddFfuToRepository(FFUFilePath); if (App.Config.FFURepository.Where(e => App.PatchEngine.PatchDefinitions.Where(p => p.Name == "SecureBootHack-V2-EFIESP").First().TargetVersions.Any(v => v.Description == e.OSVersion)).Count() == 0) - throw new WPinternalsException("Unable to find compatible FFU"); + throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process."); } break; default: diff --git a/Models/GPT.cs b/Models/GPT.cs index 9cb6b5e..83f0270 100644 --- a/Models/GPT.cs +++ b/Models/GPT.cs @@ -53,7 +53,7 @@ namespace WPinternals this.GPTBuffer = GPTBuffer; UInt32? TempHeaderOffset = ByteOperations.FindAscii(GPTBuffer, "EFI PART"); if (TempHeaderOffset == null) - throw new WPinternalsException("Bad GPT"); + throw new WPinternalsException("Bad GPT", "The GPT read isn't valid. Couldn't find the text \"EFI PART\"."); HeaderOffset = (UInt32)TempHeaderOffset; HeaderSize = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x0C); TableOffset = HeaderOffset + 0x200; @@ -63,7 +63,7 @@ namespace WPinternals PartitionEntrySize = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x54); TableSize = MaxPartitions * PartitionEntrySize; if ((TableOffset + TableSize) > GPTBuffer.Length) - throw new WPinternalsException("Bad GPT"); + throw new WPinternalsException("Bad GPT", "The GPT read isn't valid. The sizes defined in the GPT header exceed the provided GPT size."); UInt32 PartitionOffset = TableOffset; @@ -100,7 +100,7 @@ namespace WPinternals Partition SBL2 = Partitions.Where(p => (p.Name == "SBL2")).FirstOrDefault(); if ((SBL1 == null) || (SBL2 == null)) - throw new WPinternalsException("Bad GPT"); + throw new WPinternalsException("Bad GPT", "Can't patch GPT for the Secure Boot hack for Spec A devices. The provided GPT does not include a SBL1 and/or SBL2 partition."); if (HackPartition == null) { @@ -133,7 +133,7 @@ namespace WPinternals Partition SBL2 = Partitions.Where(p => (p.Name == "SBL2")).FirstOrDefault(); if ((SBL1 == null) || (SBL2 == null)) - throw new WPinternalsException("Bad GPT"); + throw new WPinternalsException("Bad GPT", "Can't un-patch GPT for the Secure Boot hack for Spec A devices. The provided GPT does not include a SBL1 and/or SBL2 partition."); if (HackPartition != null) { @@ -224,7 +224,7 @@ namespace WPinternals if (NewPartition.LastSector == 0) { - throw new WPinternalsException("Unknown length for partition \"" + NewPartition.Name + "\""); + throw new WPinternalsException("Unknown length for partition \"" + NewPartition.Name + "\". The last sector property is set to 0 and the partition doesn't exist on the device currently."); } } else @@ -234,9 +234,9 @@ namespace WPinternals // If the location of the new partition is specified, it must be the same as the current partition. if ((NewPartition.FirstSector != 0) && (NewPartition.FirstSector != OldPartition.FirstSector)) - throw new WPinternalsException("Incorrect location for partition \"" + NewPartition.Name + "\""); + throw new WPinternalsException("Incorrect location for partition \"" + NewPartition.Name + "\". A partition defined in the xml file got its boundaries updated, but as the partition isn't provided in the archive, it is not possible to relocate it."); if ((NewPartition.LastSector != 0) && (NewPartition.LastSector != OldPartition.LastSector)) - throw new WPinternalsException("Incorrect length for partition \"" + NewPartition.Name + "\""); + throw new WPinternalsException("Incorrect length for partition \"" + NewPartition.Name + "\". A partition defined in the xml file got its boundaries updated, but as the partition isn't provided in the archive, it is not possible to relocate it."); NewPartition.FirstSector = OldPartition.FirstSector; NewPartition.LastSector = OldPartition.LastSector; @@ -264,7 +264,7 @@ namespace WPinternals else { if (NewPartition.SizeInSectors != StreamLengthInSectors) - throw new WPinternalsException("Inconsistent length specified for partition \"" + NewPartition.Name + "\""); + throw new WPinternalsException("Inconsistent length specified for partition \"" + NewPartition.Name + "\". The provided partition in the archive does not match the length specified in the xml file."); } } } @@ -283,7 +283,7 @@ namespace WPinternals if (NewPartition.LastSector == 0) { - throw new WPinternalsException("Unknown length for partition \"" + NewPartition.Name + "\""); + throw new WPinternalsException("Unknown length for partition \"" + NewPartition.Name + "\". The last sector property is set to 0 and the partition doesn't exist on the device currently."); } } else @@ -293,9 +293,9 @@ namespace WPinternals // If the location of the new partition is specified, it must be the same as the current partition. if ((NewPartition.FirstSector != 0) && (NewPartition.FirstSector != OldPartition.FirstSector)) - throw new WPinternalsException("Incorrect location for partition \"" + NewPartition.Name + "\""); + throw new WPinternalsException("Incorrect location for partition \"" + NewPartition.Name + "\". A partition defined in the xml file got its boundaries updated, but as the partition isn't provided in the archive, it is not possible to relocate it."); if ((NewPartition.LastSector != 0) && (NewPartition.LastSector != OldPartition.LastSector)) - throw new WPinternalsException("Incorrect length for partition \"" + NewPartition.Name + "\""); + throw new WPinternalsException("Incorrect length for partition \"" + NewPartition.Name + "\". A partition defined in the xml file got its boundaries updated, but as the partition isn't provided in the archive, it is not possible to relocate it."); NewPartition.FirstSector = OldPartition.FirstSector; NewPartition.LastSector = OldPartition.LastSector; @@ -348,7 +348,7 @@ namespace WPinternals // Sanity check if (NewPartition.FirstSector < LowestSector) - throw new WPinternalsException("Bad sector alignment for partition: " + NewPartition.Name); + throw new WPinternalsException("Bad sector alignment for partition: " + NewPartition.Name + ". The partition is located before DPP."); Partition CurrentPartition = this.GetPartition(NewPartition.Name); if (CurrentPartition == null) @@ -426,7 +426,7 @@ namespace WPinternals MaxPartitionSizeInSectors = NextPartition.FirstSector - OldPartition.FirstSector; if (StreamLengthInSectors > MaxPartitionSizeInSectors) { - throw new WPinternalsException("Incorrect length for partition \"" + OldPartition.Name + "\""); + throw new WPinternalsException("Incorrect length for partition \"" + OldPartition.Name + "\". The provided partition in the archive does not match the length specified in the xml file."); } if (OldPartition.SizeInSectors != StreamLengthInSectors) @@ -528,7 +528,7 @@ namespace WPinternals } if (RevisePartition.LastSector >= 0xF400) - throw new WPinternalsException("Unsupported partition layout!"); + throw new WPinternalsException("Unsupported partition layout!", "The last sector of one of the BACKUP partitions defined in GPT exceeds the maximum threshold expected in order to restore BACKUP partitions to the device."); } } diff --git a/Models/LumiaDownloadModel.cs b/Models/LumiaDownloadModel.cs index 3e150f3..2524af0 100644 --- a/Models/LumiaDownloadModel.cs +++ b/Models/LumiaDownloadModel.cs @@ -117,7 +117,7 @@ namespace WPinternals } if (Package == null) - throw new WPinternalsException("FFU not found"); + throw new WPinternalsException("FFU not found", "No FFU has been found in the remote software repository for the requested model."); FoundProductType = Package.manufacturerHardwareModel[0]; @@ -207,7 +207,7 @@ namespace WPinternals } if (Package == null) - throw new WPinternalsException("ENOSW package not found"); + throw new WPinternalsException("ENOSW package not found", "No ENOSW package has been found in the remote software repository for the requested model."); SoftwareFile FileInfo = Package.files.Where(f => f.fileName.EndsWith(".secwim", StringComparison.OrdinalIgnoreCase)).First(); @@ -230,7 +230,7 @@ namespace WPinternals } if (DPLUrl == "") - throw new WPinternalsException("DPL not found"); + throw new WPinternalsException("DPL not found", "No DPL has been found in the remote software repository for the requested model."); Task GetDPLStrTask = HttpClient.GetStringAsync(DPLUrl); GetDPLStrTask.Wait(); diff --git a/Models/MassStorage.cs b/Models/MassStorage.cs index b7e8b21..0be26b3 100644 --- a/Models/MassStorage.cs +++ b/Models/MassStorage.cs @@ -35,7 +35,7 @@ namespace WPinternals internal IntPtr hDrive = (IntPtr)(-1); private bool OpenWithWriteAccess; - private QualcommSerial Serial; + private string Serial; internal MassStorage(string DevicePath) : base(DevicePath) { @@ -77,10 +77,16 @@ namespace WPinternals { try { - Serial = new QualcommSerial(DevicePath); - Serial.EncodeCommands = false; + QualcommSerial SerialDevice = new QualcommSerial(DevicePath); + SerialDevice.Close(); + SerialDevice.Dispose(); + + Serial = DevicePath; + } + catch (Exception ex) + { + LogFile.Log(ex.Message); } - catch { } } internal bool DoesDeviceSupportReboot() @@ -95,11 +101,18 @@ namespace WPinternals try { + QualcommSerial SerialDevice = new QualcommSerial(Serial); + + SerialDevice.EncodeCommands = false; + // This will succeed on new models - Serial.SendData(new byte[] { 0x7, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0 }); + SerialDevice.SendData(new byte[] { 0x7, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0 }); // This will succeed on old models - Serial.SendData(new byte[] { 0x7E, 0xA, 0x0, 0x0, 0xB6, 0xB5, 0x7E }); + SerialDevice.SendData(new byte[] { 0x7E, 0xA, 0x0, 0x0, 0xB6, 0xB5, 0x7E }); + + SerialDevice.Close(); + SerialDevice.Dispose(); } catch { } } diff --git a/Models/NokiaFlashModel.cs b/Models/NokiaFlashModel.cs index ca81d42..c72238d 100644 --- a/Models/NokiaFlashModel.cs +++ b/Models/NokiaFlashModel.cs @@ -235,7 +235,7 @@ namespace WPinternals if (Response == null) throw new BadConnectionException(); if (Response.Length == 4) - throw new WPinternalsException("Flash protocol v2 not supported"); + throw new WPinternalsException("Flash protocol v2 not supported", "The device reported that the Flash protocol v2 was not supported while sending the FFU header."); int ResultCode = (Response[6] << 8) + Response[7]; if (ResultCode != 0) ThrowFlashError(ResultCode); @@ -345,7 +345,7 @@ namespace WPinternals ThrowFlashError(ResultCode); } else - throw new WPinternalsException("Specified partition cannot be backupped to RAM"); + throw new WPinternalsException("Specified partition cannot be backupped to RAM", "Partition name: \"" + PartitionName + "\"."); } public void LoadMmosBinary(UInt32 TotalLength, UInt32 Offset, bool SkipMmosSupportCheck, byte[] MmosPart) @@ -450,7 +450,7 @@ namespace WPinternals PhoneInfo Info = ReadPhoneInfo(); if ((Info.SecureFfuSupportedProtocolMask & ((ushort)FfuProtocol.ProtocolSyncV1 | (ushort)FfuProtocol.ProtocolSyncV2)) == 0) - throw new WPinternalsException("Flash failed!", "Protocols not supported"); + throw new WPinternalsException("Flash failed!", "Protocols not supported. The device reports that both Protocol Sync v1 and Protocol Sync v2 are not supported for FFU flashing. Is this an old device?"); UInt64 CombinedFFUHeaderSize = FFU.HeaderSize; byte[] FfuHeader = new byte[CombinedFFUHeaderSize]; @@ -518,7 +518,7 @@ namespace WPinternals PhoneInfo Info = ReadPhoneInfo(); if (!Info.MmosOverUsbSupported) - throw new WPinternalsException("Flash failed!", "Protocols not supported"); + throw new WPinternalsException("Flash failed!", "Protocols not supported. The device reports that loading Microsoft Manufacturing Operating System over USB is not supported."); FileInfo info = new FileInfo(MMOSPath); uint length = uint.Parse(info.Length.ToString()); @@ -986,7 +986,7 @@ namespace WPinternals if (Response == null) throw new BadConnectionException(); if (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKI") - throw new WPinternalsException("Bad response from phone!"); + throw new WPinternalsException("Bad response from phone!", "The phone did not answer properly to the Hello message sent."); } internal UInt16 ReadSecureFfuSupportedProtocolMask() @@ -1199,7 +1199,7 @@ namespace WPinternals LogFile.Log("Product code: " + ProductCode, Type); if (RKH != null) LogFile.Log("Root key hash: " + Converter.ConvertHexToString(RKH, ""), Type); - if (Firmware.Length > 0) + if (Firmware != null && Firmware.Length > 0) LogFile.Log("Firmware version: " + Firmware, Type); if (!(Type == LogType.ConsoleOnly) && (Imei != null)) LogFile.Log("IMEI: " + Imei, LogType.FileOnly); diff --git a/Models/PatchEngine.cs b/Models/PatchEngine.cs index 7c81d51..ac012d0 100644 --- a/Models/PatchEngine.cs +++ b/Models/PatchEngine.cs @@ -399,7 +399,7 @@ namespace WPinternals internal FilePatcher(string FilePath, Stream FileStream) { if (!FileStream.CanSeek || !FileStream.CanWrite) - throw new WPinternalsException("Incorrect filestream"); + throw new WPinternalsException("Incorrect filestream", "The provided file stream for patching does not support seeking and/or writing."); this.FilePath = FilePath; this.Stream = FileStream; diff --git a/Models/QualcommPartition.cs b/Models/QualcommPartition.cs index 221bbdf..8d07a89 100644 --- a/Models/QualcommPartition.cs +++ b/Models/QualcommPartition.cs @@ -88,7 +88,7 @@ namespace WPinternals HeaderOffset = ImageOffset + 8; } else - throw new WPinternalsException("Invalid programmer"); + throw new WPinternalsException("Invalid programmer", "The type of elf image could not be determined from the provided programmer."); } else if (ByteOperations.FindPattern(Binary, Offset, (uint)LongHeaderPattern.Length, LongHeaderPattern, LongHeaderMask, null) == null) { diff --git a/TestCode.cs b/TestCode.cs index bc028f0..b5d3cb5 100644 --- a/TestCode.cs +++ b/TestCode.cs @@ -55,7 +55,7 @@ namespace WPinternals Info.Log(LogType.ConsoleOnly); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Qualcomm_Download); if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download) - throw new WPinternalsException("Switching mode failed."); + throw new WPinternalsException("Switching mode failed.", "Could not switch the phone to Qualcomm Emergency 9008."); LogFile.Log("Phone is in emergency mode.", LogType.FileAndConsole); } diff --git a/ViewModels/LumiaInfoViewModel.cs b/ViewModels/LumiaInfoViewModel.cs index e7f7655..c521b6c 100644 --- a/ViewModels/LumiaInfoViewModel.cs +++ b/ViewModels/LumiaInfoViewModel.cs @@ -68,6 +68,7 @@ namespace WPinternals case null: case PhoneInterfaces.Lumia_Bootloader: ActivateSubContext(null); + //ActivateSubContext(new NokiaBootloaderViewModel((NokiaFlashModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted)); break; case PhoneInterfaces.Lumia_Normal: ActivateSubContext(new NokiaNormalViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback)); diff --git a/ViewModels/LumiaModeViewModel.cs b/ViewModels/LumiaModeViewModel.cs index 011807a..098f53a 100644 --- a/ViewModels/LumiaModeViewModel.cs +++ b/ViewModels/LumiaModeViewModel.cs @@ -78,7 +78,11 @@ namespace WPinternals switch (CurrentInterface) { case null: + ActivateSubContext(null); + break; case PhoneInterfaces.Lumia_Bootloader: + ActivateSubContext(null); + //ActivateSubContext(new NokiaModeBootloaderViewModel((NokiaFlashModel)CurrentModel, OnModeSwitchRequested)); break; case PhoneInterfaces.Lumia_Normal: ActivateSubContext(new NokiaModeNormalViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested)); diff --git a/ViewModels/LumiaUnlockBootViewModel.cs b/ViewModels/LumiaUnlockBootViewModel.cs index c595df2..6db207d 100644 --- a/ViewModels/LumiaUnlockBootViewModel.cs +++ b/ViewModels/LumiaUnlockBootViewModel.cs @@ -134,11 +134,14 @@ namespace WPinternals TestPos = 1; UefiSecurityStatusResponse SecurityStatus = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadSecurityStatus(); - IsBootLoaderUnlocked = (SecurityStatus.AuthenticationStatus || SecurityStatus.RdcStatus || !SecurityStatus.SecureFfuEfuseStatus); + if (SecurityStatus != null) + IsBootLoaderUnlocked = (SecurityStatus.AuthenticationStatus || SecurityStatus.RdcStatus || !SecurityStatus.SecureFfuEfuseStatus); TestPos = 2; PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(); + if (SecurityStatus == null) + IsBootLoaderUnlocked = (Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled); TestPos = 3; @@ -255,7 +258,7 @@ namespace WPinternals if (FFUs.Count() > 0) ProfileFFU = new FFU(FFUs[0].Path); else - throw new WPinternalsException("Profile FFU missing"); + throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line."); LogFile.Log("Profile FFU: " + ProfileFFU.Path); diff --git a/ViewModels/LumiaUnlockBootloaderViewModel.cs b/ViewModels/LumiaUnlockBootloaderViewModel.cs index 0e37abc..51c6851 100644 --- a/ViewModels/LumiaUnlockBootloaderViewModel.cs +++ b/ViewModels/LumiaUnlockBootloaderViewModel.cs @@ -262,7 +262,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); NewGPT = ((NokiaFlashModel)Notifier.CurrentModel).ReadGPT(); @@ -272,7 +272,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); } else { @@ -501,7 +501,7 @@ namespace WPinternals if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download) await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download) - throw new WPinternalsException("Phone failed to switch to DLOAD."); + throw new WPinternalsException("Phone failed to switch to emergency download mode."); } // Send loader @@ -512,7 +512,7 @@ namespace WPinternals if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash) await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash) - throw new WPinternalsException("Phone failed to switch to DLOAD."); + throw new WPinternalsException("Phone failed to switch to emergency flash mode."); } // Flash bootloader @@ -584,7 +584,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader && Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) { @@ -593,7 +593,7 @@ namespace WPinternals } else { - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash, download, or emergency flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); } SetWorkingStatus("Rebooting phone..."); @@ -603,7 +603,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader && Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); NokiaFlashModel FlashModel = (NokiaFlashModel)Notifier.CurrentModel; if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash && FlashModel.ReadParam("FS")[3] > 0) @@ -750,7 +750,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); NewGPT = ((NokiaFlashModel)Notifier.CurrentModel).ReadGPT(); @@ -760,7 +760,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); } else { @@ -1122,7 +1122,7 @@ namespace WPinternals if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download) await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download) - throw new WPinternalsException("Phone failed to switch to DLOAD."); + throw new WPinternalsException("Phone failed to switch to emergency download mode."); } // Send loader @@ -1133,7 +1133,7 @@ namespace WPinternals if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash) await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash) - throw new WPinternalsException("Phone failed to switch to DLOAD."); + throw new WPinternalsException("Phone failed to switch to emergency flash mode."); } // Flash bootloader @@ -1211,7 +1211,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader && Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) { @@ -1222,7 +1222,7 @@ namespace WPinternals } else { - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash, download or emergency flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); } await LumiaUnlockBootloaderViewModel.LumiaUnlockUEFI(Notifier, FFUPath, LoadersPath, SupportedFFUPath, SetWorkingStatus, UpdateWorkingStatus, null, (string Message, string SubMessage) => @@ -1346,7 +1346,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); } byte[] GPTChunk = GetGptChunk(((NokiaFlashModel)Notifier.CurrentModel), 0x20000); @@ -1368,7 +1368,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) - throw new WPinternalsException("Phone is in an unexpected mode."); + throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); } if (IsSpecB || IsUnlockedPartitionSBL3 != null) @@ -1794,7 +1794,7 @@ namespace WPinternals Partition EFIESPPartition = GPT.GetPartition("EFIESP"); if (EFIESPPartition == null) - throw new WPinternalsException("EFIESP partition not found!"); + throw new WPinternalsException("EFIESP partition not found!", "No EFIESP partition was found in the provided FFU's GPT."); if ((UInt64)UnlockedEFIESP.Length != (EFIESPPartition.SizeInSectors * 0x200)) throw new WPinternalsException("New EFIESP partition has wrong size. Size = 0x" + UnlockedEFIESP.Length.ToString("X8") + ". Expected size = 0x" + (EFIESPPartition.SizeInSectors * 0x200).ToString("X8")); @@ -1866,7 +1866,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)) - throw new WPinternalsException("Error: Phone is in wrong mode"); + throw new WPinternalsException("Error: Phone is in wrong mode", "The phone should have been detected in bootloader or flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); if (!IsSpecB && !SBL3Eng) { @@ -1994,7 +1994,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) - throw new WPinternalsException("Phone is in wrong mode"); + throw new WPinternalsException("Phone is in wrong mode", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); ((NokiaFlashModel)Notifier.CurrentModel).SwitchToFlashAppContext(); @@ -2140,7 +2140,7 @@ namespace WPinternals await Notifier.WaitForArrival(); if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) - throw new WPinternalsException("Phone is in wrong mode"); + throw new WPinternalsException("Phone is in wrong mode", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); } ((NokiaFlashModel)Notifier.CurrentModel).SwitchToFlashAppContext(); @@ -2356,7 +2356,7 @@ namespace WPinternals PatchResult = App.PatchEngine.Patch(PatchDefinition); if (!PatchResult) - throw new WPinternalsException("Failed to patch bootloader"); + throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible."); } LogFile.Log("Edit BCD"); diff --git a/ViewModels/LumiaV2UnlockBootViewModel.cs b/ViewModels/LumiaV2UnlockBootViewModel.cs index 653c4aa..491bb46 100644 --- a/ViewModels/LumiaV2UnlockBootViewModel.cs +++ b/ViewModels/LumiaV2UnlockBootViewModel.cs @@ -317,7 +317,7 @@ namespace WPinternals Partition TargetPartition = GPT.GetPartition(PartitionName); if (TargetPartition == null) - throw new WPinternalsException("Target partition not found!"); + throw new WPinternalsException("Target partition not found!", "Couldn't find \"" + PartitionName + "\" from the device GPT."); LogFile.Log("Target-partition found at sector: 0x" + TargetPartition.FirstSector.ToString("X8") + " - 0x" + TargetPartition.LastSector.ToString("X8"), LogType.FileAndConsole); bool IsUnlocked = false; @@ -498,7 +498,7 @@ namespace WPinternals FFU FFU = new FFU(FFUPath); UInt32 UpdateType = ByteOperations.ReadUInt32(FFU.StoreHeader, 0); if (UpdateType != 0) - throw new WPinternalsException("Only Full Flash images supported"); + throw new WPinternalsException("Only Full Flash images supported", "The provided FFU file reports that it doesn't support Full Flash updates, but may support something else such as Partial Flash updates. This is not supported."); if (FlashParts != null) { @@ -519,9 +519,9 @@ namespace WPinternals } if ((Info.SecureFfuSupportedProtocolMask & ((ushort)FfuProtocol.ProtocolSyncV2)) == 0) // Exploit needs protocol v2 -> This check is not conclusive, because old phones also report support for this protocol, although it is really not supported. - throw new WPinternalsException("Flash failed!", "Protocols not supported"); + throw new WPinternalsException("Flash failed!", "Protocols not supported. The phone reports that it does not support the Protocol Sync V2."); if (Info.FlashAppProtocolVersionMajor < 2) // Old phones do not support the hack. These phones have Flash protocol 1.x. - throw new WPinternalsException("Flash failed!", "Protocols not supported"); + throw new WPinternalsException("Flash failed!", "Protocols not supported. The phone reports that Flash App communication protocol is lower than 2. Reported version by the phone: " + Info.FlashAppProtocolVersionMajor + "."); UEFI UEFI = new UEFI(FFU.GetPartition("UEFI")); string BootMgrName = UEFI.EFIs.Where(efi => ((efi.Name != null) && (efi.Name.Contains("BootMgrApp")))).First().Name; UInt32 EstimatedSizeOfMemGap = (UInt32)UEFI.GetFile(BootMgrName).Length; @@ -689,7 +689,7 @@ namespace WPinternals #endregion if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader)) - throw new WPinternalsException("Phone is in wrong mode"); + throw new WPinternalsException("Phone is in wrong mode", "The phone should have been detected in bootloader or flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode."); Model = (NokiaFlashModel)Notifier.CurrentModel; UpdateWorkingStatus("Initializing flash...", null, null); } @@ -2076,7 +2076,7 @@ namespace WPinternals App.PatchEngine.TargetPath = ((MassStorage)Notifier.CurrentModel).Drive + "\\"; bool PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS"); if (!PatchResult) - throw new WPinternalsException("Patch failed"); + throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the MainOS partition of your phone. Make sure your phone runs a supported Operating System version."); LogFile.Log("Fixed bootloader", LogType.FileAndConsole); LogFile.Log("The phone is left in Mass Storage mode", LogType.FileAndConsole); LogFile.Log("Press and hold the power-button of the phone for at least 10 seconds to reset the phone", LogType.FileAndConsole); diff --git a/ViewModels/NokiaBootloaderViewModel.cs b/ViewModels/NokiaBootloaderViewModel.cs new file mode 100644 index 0000000..3dd8d06 --- /dev/null +++ b/ViewModels/NokiaBootloaderViewModel.cs @@ -0,0 +1,76 @@ +// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Threading; + +namespace WPinternals +{ + // Create this class on the UI thread, after the main-window of the application is initialized. + // It is necessary to create the object on the UI thread, because notification events to the View need to be fired on that thread. + // The Model for this ViewModel communicates over USB and for that it uses the hWnd of the main window. + // Therefore the main window must be created before the ViewModel is created. + + internal class NokiaBootloaderViewModel : ContextViewModel + { + private NokiaFlashModel CurrentModel; + private Action RequestModeSwitch; + internal Action SwitchToGettingStarted; + private object LockDeviceInfo = new object(); + + internal NokiaBootloaderViewModel(NokiaPhoneModel CurrentModel, Action RequestModeSwitch, Action SwitchToGettingStarted) + : base() + { + this.CurrentModel = (NokiaFlashModel)CurrentModel; + this.RequestModeSwitch = RequestModeSwitch; + this.SwitchToGettingStarted = SwitchToGettingStarted; + } + + // Device info should be loaded only one time and only when the ViewModel is active + internal override void EvaluateViewState() + { + if (IsActive) + new Thread(() => StartLoadDeviceInfo()).Start(); + } + + private void StartLoadDeviceInfo() + { + + } + + internal void RebootTo(string Mode) + { + switch (Mode) + { + case "Normal": + RequestModeSwitch(PhoneInterfaces.Lumia_Normal); + break; + case "Label": + RequestModeSwitch(PhoneInterfaces.Lumia_Label); + break; + case "MassStorage": + RequestModeSwitch(PhoneInterfaces.Lumia_MassStorage); + break; + default: + return; + } + } + } +} diff --git a/ViewModels/NokiaFlashViewModel.cs b/ViewModels/NokiaFlashViewModel.cs index 98f7457..15401c0 100644 --- a/ViewModels/NokiaFlashViewModel.cs +++ b/ViewModels/NokiaFlashViewModel.cs @@ -125,6 +125,11 @@ namespace WPinternals Array.Copy(RawPublicID, 4, PublicID, 0, RawPublicID.Length - 4); LogFile.Log("Public ID: " + Converter.ConvertHexToString(PublicID, " ")); } + else + { + PublicID = new byte[20]; + LogFile.Log("Public ID: " + Converter.ConvertHexToString(PublicID, " ")); + } RootKeyHash = CurrentModel.ReadParam("RRKH"); if (RootKeyHash != null) LogFile.Log("Root Key Hash: " + Converter.ConvertHexToString(RootKeyHash, " ")); @@ -153,50 +158,66 @@ namespace WPinternals byte[] CID = CurrentModel.ReadParam("CID"); byte[] EMS = CurrentModel.ReadParam("EMS"); - UInt16 MID = (UInt16)(((UInt16)CID[0] << 8) + CID[1]); - UInt64 MemSize = (UInt64)(((UInt32)EMS[0] << 24) + ((UInt32)EMS[1] << 16) + ((UInt32)EMS[2] << 8) + EMS[3]) * 0x200; - double MemSizeDouble = (double)MemSize / 1024 / 1024 / 1024; - MemSizeDouble = (double)(int)(MemSizeDouble * 10) / 10; - string Manufacturer = null; - switch (MID) + if (CID != null && EMS != null) { - case 0x0002: - case 0x0045: - Manufacturer = "SanDisk"; - break; - case 0x0011: - Manufacturer = "Toshiba"; - break; - case 0x0013: - Manufacturer = "Micron"; - break; - case 0x0015: - Manufacturer = "Samsung"; - break; - case 0x0090: - Manufacturer = "Hynix"; - break; - case 0x0070: - Manufacturer = "Kingston"; - break; - case 0x00EC: - Manufacturer = "GigaDevice"; - break; + UInt16 MID = (UInt16)(((UInt16)CID[0] << 8) + CID[1]); + UInt64 MemSize = (UInt64)(((UInt32)EMS[0] << 24) + ((UInt32)EMS[1] << 16) + ((UInt32)EMS[2] << 8) + EMS[3]) * 0x200; + double MemSizeDouble = (double)MemSize / 1024 / 1024 / 1024; + MemSizeDouble = (double)(int)(MemSizeDouble * 10) / 10; + string Manufacturer = null; + switch (MID) + { + case 0x0002: + case 0x0045: + Manufacturer = "SanDisk"; + break; + case 0x0011: + Manufacturer = "Toshiba"; + break; + case 0x0013: + Manufacturer = "Micron"; + break; + case 0x0015: + Manufacturer = "Samsung"; + break; + case 0x0090: + Manufacturer = "Hynix"; + break; + case 0x0070: + Manufacturer = "Kingston"; + break; + case 0x00EC: + Manufacturer = "GigaDevice"; + break; + } + if (Manufacturer == null) + eMMC = MemSizeDouble.ToString() + " GB"; + else + eMMC = Manufacturer + " " + MemSizeDouble.ToString() + " GB"; + SamsungWarningVisible = (MID == 0x0015); } - if (Manufacturer == null) - eMMC = MemSizeDouble.ToString() + " GB"; else - eMMC = Manufacturer + " " + MemSizeDouble.ToString() + " GB"; - SamsungWarningVisible = (MID == 0x0015); + { + eMMC = "Unknown"; + SamsungWarningVisible = true; + } - int chargecurrent = CurrentModel.ReadCurrentChargeCurrent().Value; + int? chargecurrent = CurrentModel.ReadCurrentChargeCurrent(); - if (chargecurrent < 0) - ChargingStatus = CurrentModel.ReadCurrentChargeLevel() + "% - " + ((-1) * CurrentModel.ReadCurrentChargeCurrent()) + " mA (discharging)"; + if (chargecurrent.HasValue) + { + if (chargecurrent < 0) + ChargingStatus = CurrentModel.ReadCurrentChargeLevel() + "% - " + ((-1) * CurrentModel.ReadCurrentChargeCurrent()) + " mA (discharging)"; + else + ChargingStatus = CurrentModel.ReadCurrentChargeLevel() + "% - " + CurrentModel.ReadCurrentChargeCurrent() + " mA (charging)"; + + LogFile.Log("Charging status: " + ChargingStatus); + } else - ChargingStatus = CurrentModel.ReadCurrentChargeLevel() + "% - " + CurrentModel.ReadCurrentChargeCurrent() + " mA (charging)"; - - LogFile.Log("Charging status: " + ChargingStatus); + { + ChargingStatus = "Unknown"; + LogFile.Log("Charging status: " + ChargingStatus); + } PhoneInfo Info = CurrentModel.ReadPhoneInfo(true); if (Info.FlashAppProtocolVersionMajor < 2) @@ -210,6 +231,53 @@ namespace WPinternals ProductType = Info.Type; LogFile.Log("ProductType: " + ProductType); + + if (RootKeyHash == null) + { + LogFile.Log("Root Key Hash was null. Gathering information from an alternative source."); + + RootKeyHash = Info.RKH; + + if (RootKeyHash != null) + LogFile.Log("Root Key Hash: " + Converter.ConvertHexToString(RootKeyHash, " ")); + else + { + RootKeyHash = new byte[32]; + LogFile.Log("Root Key Hash: " + Converter.ConvertHexToString(RootKeyHash, " ")); + } + } + + if (PlatformName == null) + { + LogFile.Log("Platform Name was null. Gathering information from an alternative source."); + + PlatformName = Info.PlatformID; + LogFile.Log("Platform Name: " + PlatformName); + } + + if (SecurityStatus == null) + { + LogFile.Log("Security Status was null. Gathering information from an alternative source."); + + PlatformSecureBootStatus = Info.PlatformSecureBootEnabled; + LogFile.Log("Platform Secure Boot Status: " + PlatformSecureBootStatus.ToString()); + UefiSecureBootStatus = Info.UefiSecureBootEnabled; + LogFile.Log("Uefi Secure Boot Status: " + UefiSecureBootStatus.ToString()); + EffectiveSecureBootStatus = Info.PlatformSecureBootEnabled && Info.UefiSecureBootEnabled; + LogFile.Log("Effective Secure Boot Status: " + EffectiveSecureBootStatus.ToString()); + + BootloaderSecurityQfuseStatus = Info.SecureFfuEnabled; + LogFile.Log("Bootloader Security Qfuse Status: " + BootloaderSecurityQfuseStatus.ToString()); + BootloaderSecurityAuthenticationStatus = Info.Authenticated; + LogFile.Log("Bootloader Security Authentication Status: " + BootloaderSecurityAuthenticationStatus.ToString()); + BootloaderSecurityRdcStatus = Info.RdcPresent; + LogFile.Log("Bootloader Security Rdc Status: " + BootloaderSecurityRdcStatus.ToString()); + EffectiveBootloaderSecurityStatus = Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent; + LogFile.Log("Effective Bootloader Security Status: " + EffectiveBootloaderSecurityStatus.ToString()); + + NativeDebugStatus = !Info.JtagDisabled; + LogFile.Log("Native Debug Status: " + NativeDebugStatus.ToString()); + } } catch { diff --git a/ViewModels/NokiaModeBootloaderViewModel.cs b/ViewModels/NokiaModeBootloaderViewModel.cs new file mode 100644 index 0000000..cff353f --- /dev/null +++ b/ViewModels/NokiaModeBootloaderViewModel.cs @@ -0,0 +1,119 @@ +// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Threading; + +namespace WPinternals +{ + internal class NokiaModeBootloaderViewModel : ContextViewModel + { + private NokiaFlashModel CurrentModel; + Action RequestModeSwitch; + private object LockDeviceInfo = new object(); + bool DeviceInfoLoaded = false; + + internal NokiaModeBootloaderViewModel(NokiaPhoneModel CurrentModel, Action RequestModeSwitch) + : base() + { + this.CurrentModel = (NokiaFlashModel)CurrentModel; + this.RequestModeSwitch = RequestModeSwitch; + } + + internal override void EvaluateViewState() + { + if (IsActive) + new Thread(() => StartLoadDeviceInfo()).Start(); + } + + private bool? _EffectiveBootloaderSecurityStatus = null; + public bool? EffectiveBootloaderSecurityStatus + { + get + { + return _EffectiveBootloaderSecurityStatus; + } + set + { + _EffectiveBootloaderSecurityStatus = value; + OnPropertyChanged("EffectiveBootloaderSecurityStatus"); + } + } + + internal void StartLoadDeviceInfo() + { + lock (LockDeviceInfo) + { + if (!DeviceInfoLoaded) + { + try + { + PhoneInfo Info = CurrentModel.ReadPhoneInfo(); + + if (Info.FlashAppProtocolVersionMajor < 2) + { + UefiSecurityStatusResponse SecurityStatus = CurrentModel.ReadSecurityStatus(); + + if (SecurityStatus != null) + { + EffectiveBootloaderSecurityStatus = SecurityStatus.SecureFfuEfuseStatus && !SecurityStatus.AuthenticationStatus && !SecurityStatus.RdcStatus; + } + } + else + { + EffectiveBootloaderSecurityStatus = Info.UefiSecureBootEnabled; + } + + LogFile.Log("Effective Bootloader Security Status: " + EffectiveBootloaderSecurityStatus.ToString()); + } + catch + { + LogFile.Log("Reading status from Flash interface was aborted."); + } + DeviceInfoLoaded = true; + } + } + } + + internal void RebootTo(string Mode) + { + switch (Mode) + { + case "Normal": + RequestModeSwitch(PhoneInterfaces.Lumia_Normal); + break; + case "Flash": + RequestModeSwitch(PhoneInterfaces.Lumia_Flash); + break; + case "Label": + RequestModeSwitch(PhoneInterfaces.Lumia_Label); + break; + case "MassStorage": + RequestModeSwitch(PhoneInterfaces.Lumia_MassStorage); + break; + case "Shutdown": + RequestModeSwitch(null); + break; + default: + return; + } + } + } +} diff --git a/ViewModels/NokiaModeFlashViewModel.cs b/ViewModels/NokiaModeFlashViewModel.cs index 8730240..52a04ec 100644 --- a/ViewModels/NokiaModeFlashViewModel.cs +++ b/ViewModels/NokiaModeFlashViewModel.cs @@ -75,6 +75,10 @@ namespace WPinternals { EffectiveBootloaderSecurityStatus = SecurityStatus.SecureFfuEfuseStatus && !SecurityStatus.AuthenticationStatus && !SecurityStatus.RdcStatus; } + else + { + EffectiveBootloaderSecurityStatus = Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent; + } } else { diff --git a/ViewModels/NokiaModeMassStorageViewModel.cs b/ViewModels/NokiaModeMassStorageViewModel.cs index 6c3c8aa..114f88b 100644 --- a/ViewModels/NokiaModeMassStorageViewModel.cs +++ b/ViewModels/NokiaModeMassStorageViewModel.cs @@ -67,6 +67,9 @@ namespace WPinternals case "Flash": RequestModeSwitch(PhoneInterfaces.Lumia_Flash); break; + case "Shutdown": + RequestModeSwitch(null); + break; default: return; } diff --git a/ViewModels/PhoneNotifierViewModel.cs b/ViewModels/PhoneNotifierViewModel.cs index 563f8a9..455e470 100644 --- a/ViewModels/PhoneNotifierViewModel.cs +++ b/ViewModels/PhoneNotifierViewModel.cs @@ -165,8 +165,8 @@ namespace WPinternals NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel)); } else if ((e.DevicePath.IndexOf("VID_0421&PID_0661", StringComparison.OrdinalIgnoreCase) >= 0) || - (e.DevicePath.IndexOf("VID_0421&PID_06FC", StringComparison.OrdinalIgnoreCase) >= 0) || // VID_0421&PID_06FC is for Lumia 930 - (e.DevicePath.IndexOf("vid_045e&pid_0a00", StringComparison.OrdinalIgnoreCase) >= 0)) // vid_045e & pid_0a00 & mi_03 = Lumia 950 XL normal mode + (e.DevicePath.IndexOf("VID_0421&PID_06FC", StringComparison.OrdinalIgnoreCase) >= 0) || // VID_0421&PID_06FC is for Lumia 930 + (e.DevicePath.IndexOf("VID_045E&PID_0A00", StringComparison.OrdinalIgnoreCase) >= 0)) // vid_045e & pid_0a00 & mi_03 = Lumia 950 XL normal mode { if (((USBNotifier)sender).Guid == OldCombiInterfaceGuid) { @@ -215,18 +215,16 @@ namespace WPinternals } } else if ((e.DevicePath.IndexOf("VID_0421&PID_066E", StringComparison.OrdinalIgnoreCase) >= 0) || - (e.DevicePath.IndexOf("VID_0421&PID_0714", StringComparison.OrdinalIgnoreCase) >= 0) || // VID_0421&PID_0714 is for Lumia 930 - (e.DevicePath.IndexOf("VID_045E&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0)) // VID_045E&PID_0A02 is for Lumia 950 + (e.DevicePath.IndexOf("VID_0421&PID_0714", StringComparison.OrdinalIgnoreCase) >= 0) || // VID_0421&PID_0714 is for Lumia 930 + (e.DevicePath.IndexOf("VID_045E&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0)) // VID_045E&PID_0A02 is for Lumia 950 { CurrentModel = new NokiaFlashModel(e.DevicePath); ((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged; - // Attempt to request a param. - // When it succeeds we have full Flash mode. - // When it fails we are in a limited Flash mode, like Bootmanager or Hardreset-screen. - // Limited Flash mode only supports boot-commands; not querying info. - byte[] QueryResult = ((NokiaFlashModel)CurrentModel).ReadParam("SS"); - if (QueryResult == null) + FlashAppType type = ((NokiaFlashModel)CurrentModel).GetFlashAppType(); + LogFile.Log("Flash App Type: " + type.ToString(), LogType.FileOnly); + + if (type == FlashAppType.BootManager) { CurrentInterface = PhoneInterfaces.Lumia_Bootloader; LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly); @@ -235,6 +233,15 @@ namespace WPinternals LogFile.Log("Mode: Bootloader", LogType.FileAndConsole); NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel)); } + else if (type == FlashAppType.PhoneInfoApp) + { + CurrentInterface = PhoneInterfaces.Lumia_Bootloader; + LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly); + LogFile.Log("Device path: " + e.DevicePath, LogType.FileOnly); + LogFile.Log("Connected device: Lumia", LogType.FileAndConsole); + LogFile.Log("Mode: Bootloader (Phone Info)", LogType.FileAndConsole); + NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel)); + } else { ((NokiaFlashModel)CurrentModel).DisableRebootTimeOut(); @@ -246,8 +253,8 @@ namespace WPinternals NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel)); } } - else if ((e.DevicePath.IndexOf(@"disk&ven_qualcomm&prod_mmc_storage", StringComparison.OrdinalIgnoreCase) >= 0) || - (e.DevicePath.IndexOf(@"DISK&VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.OrdinalIgnoreCase) >= 0)) + else if ((e.DevicePath.IndexOf(@"DISK&VEN_QUALCOMM&PROD_MMC_STORAGE", StringComparison.OrdinalIgnoreCase) >= 0) || + (e.DevicePath.IndexOf(@"DISK&VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.OrdinalIgnoreCase) >= 0)) { #if DEBUG LogFile.Log("Mass storage arrived: " + e.DevicePath, LogType.FileOnly); @@ -266,11 +273,14 @@ namespace WPinternals { MassStorage NewModel = new MassStorage(e.DevicePath); - if (!string.IsNullOrEmpty(Qcom9006DevicePath)) - NewModel.AttachQualcommSerial(Qcom9006DevicePath); - if (NewModel.Drive != null) // When logical drive is already known, we use this model. Or else we wait for the logical drive to arrive. { + if (!string.IsNullOrEmpty(Qcom9006DevicePath)) + { + LogFile.Log("Found 9006 device previously on: " + Qcom9006DevicePath, LogType.FileOnly); + LogFile.Log("Attaching 9006 device", LogType.FileOnly); + NewModel.AttachQualcommSerial(Qcom9006DevicePath); + } CurrentInterface = PhoneInterfaces.Lumia_MassStorage; CurrentModel = NewModel; LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly); @@ -301,11 +311,14 @@ namespace WPinternals { MassStorage NewModel = new MassStorage(e.DevicePath); - if (!string.IsNullOrEmpty(Qcom9006DevicePath)) - NewModel.AttachQualcommSerial(Qcom9006DevicePath); - if (NewModel.Drive != null) // When logical drive is already known, we use this model. Or else we wait for the logical drive to arrive. { + if (!string.IsNullOrEmpty(Qcom9006DevicePath)) + { + LogFile.Log("Found 9006 device previously on: " + Qcom9006DevicePath, LogType.FileOnly); + LogFile.Log("Attaching 9006 device", LogType.FileOnly); + NewModel.AttachQualcommSerial(Qcom9006DevicePath); + } CurrentInterface = PhoneInterfaces.Lumia_MassStorage; CurrentModel = NewModel; LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly); @@ -355,12 +368,28 @@ namespace WPinternals // It is a slightly different version of the Qualcomm Emergency interface, which is implemented in SBL3. // One important difference is that the base address for sending a loader is not 0x2A000000, but it is 0x82F00000. + Qcom9006DevicePath = e.DevicePath; + LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly); - LogFile.Log("Device path: " + e.DevicePath, LogType.FileOnly); + LogFile.Log("Device path: " + Qcom9006DevicePath, LogType.FileOnly); LogFile.Log("Connected device: Lumia", LogType.FileAndConsole); LogFile.Log("Mode: Qualcomm Emergency 9006", LogType.FileAndConsole); - Qcom9006DevicePath = e.DevicePath; + if (CurrentModel is MassStorage) + { + LogFile.Log("Found Mass Storage device previously", LogType.FileOnly); + LogFile.Log("Attaching 9006 device", LogType.FileOnly); + ((MassStorage)CurrentModel).AttachQualcommSerial(Qcom9006DevicePath); + } + } + else if (e.DevicePath.IndexOf("VID_05C6&PID_F006", StringComparison.OrdinalIgnoreCase) >= 0) + { + // This is part of the charging inteface. + + LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly); + LogFile.Log("Device path: " + e.DevicePath, LogType.FileOnly); + LogFile.Log("Connected device: Lumia", LogType.FileAndConsole); + LogFile.Log("Mode: Qualcomm Emergency Charging F006", LogType.FileAndConsole); } } catch (Exception Ex) @@ -386,14 +415,15 @@ namespace WPinternals if ( (e.DevicePath.IndexOf("VID_0421&PID_0660&MI_04", StringComparison.OrdinalIgnoreCase) >= 0) || (e.DevicePath.IndexOf("VID_0421&PID_0713&MI_04", StringComparison.OrdinalIgnoreCase) >= 0) || + (e.DevicePath.IndexOf("VID_045E&PID_0A01&MI_04", StringComparison.OrdinalIgnoreCase) >= 0) || (e.DevicePath.IndexOf("VID_0421&PID_0661", StringComparison.OrdinalIgnoreCase) >= 0) || (e.DevicePath.IndexOf("VID_0421&PID_06FC", StringComparison.OrdinalIgnoreCase) >= 0) || (e.DevicePath.IndexOf("VID_0421&PID_066E", StringComparison.OrdinalIgnoreCase) >= 0) || (e.DevicePath.IndexOf("VID_0421&PID_0714", StringComparison.OrdinalIgnoreCase) >= 0) || - (e.DevicePath.IndexOf("vid_045e&pid_0a00", StringComparison.OrdinalIgnoreCase) >= 0) || + (e.DevicePath.IndexOf("VID_045E&PID_0A00", StringComparison.OrdinalIgnoreCase) >= 0) || (e.DevicePath.IndexOf("VID_045E&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0) || (e.DevicePath.IndexOf("VID_05C6&PID_9008", StringComparison.OrdinalIgnoreCase) >= 0) || - (e.DevicePath.IndexOf(@"disk&ven_qualcomm&prod_mmc_storage", StringComparison.OrdinalIgnoreCase) >= 0) || + (e.DevicePath.IndexOf(@"DISK&VEN_QUALCOMM&PROD_MMC_STORAGE", StringComparison.OrdinalIgnoreCase) >= 0) || (e.DevicePath.IndexOf(@"DISK&VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.OrdinalIgnoreCase) >= 0) ) { diff --git a/ViewModels/SwitchModeViewModel.cs b/ViewModels/SwitchModeViewModel.cs index b322e97..f2d7c54 100644 --- a/ViewModels/SwitchModeViewModel.cs +++ b/ViewModels/SwitchModeViewModel.cs @@ -347,6 +347,12 @@ namespace WPinternals ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null); LogFile.Log("Rebooting phone to Flash mode...", LogType.FileAndConsole); break; + case null: + ((MassStorage)CurrentModel).Reboot(); + PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode; + ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null); + LogFile.Log("First rebooting phone to Bootloader mode...", LogType.FileAndConsole); + break; default: return; } @@ -389,6 +395,9 @@ namespace WPinternals case PhoneInterfaces.Lumia_Normal: ModeSwitchErrorWrapper("Failed to switch to Normal mode"); break; + case null: + ModeSwitchSuccessWrapper(); + break; } } }); @@ -406,6 +415,9 @@ namespace WPinternals case PhoneInterfaces.Lumia_Normal: ModeSwitchErrorWrapper("Failed to switch to Normal mode"); break; + case null: + ModeSwitchErrorWrapper("Failed to shutdown"); + break; } } } diff --git a/Views/Empty.xaml b/Views/Empty.xaml index d05ed51..54e76c6 100644 --- a/Views/Empty.xaml +++ b/Views/Empty.xaml @@ -30,18 +30,19 @@ DEALINGS IN THE SOFTWARE. d:DesignWidth="700" > + - + + + + - - - - Getting started diff --git a/Views/Empty.xaml.cs b/Views/Empty.xaml.cs index 75eacc8..43954df 100644 --- a/Views/Empty.xaml.cs +++ b/Views/Empty.xaml.cs @@ -19,6 +19,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; @@ -32,12 +33,39 @@ namespace WPinternals /// public partial class Empty : UserControl { + static PhoneNotifierViewModel PhoneNotifier; + static SynchronizationContext UIContext; + // Dependency injection is not possible here, because this ViewModel is used in a Style. public Empty() { InitializeComponent(); InterruptBoot = App.InterruptBoot; + UIContext = SynchronizationContext.Current; + + // Setting these properties in XAML results in an error. Why? + GifImage.GifSource = @"/aerobusy.gif"; + GifImage.AutoStart = true; + + Loaded += Empty_Loaded; + Unloaded += Empty_Unloaded; + } + + private void Empty_Unloaded(object sender, RoutedEventArgs e) + { + PhoneNotifier.NewDeviceArrived -= PhoneNotifier_NewDeviceArrived; + } + + private void Empty_Loaded(object sender, RoutedEventArgs e) + { + // Find the phone notifier + DependencyObject obj = (DependencyObject)sender; + while (!(obj is MainWindow)) + obj = VisualTreeHelper.GetParent(obj); + PhoneNotifier = ((MainViewModel)(((MainWindow)obj).DataContext)).PhoneNotifier; + + PhoneNotifier.NewDeviceArrived += PhoneNotifier_NewDeviceArrived; } private void HandleHyperlinkClick(object sender, RoutedEventArgs args) @@ -81,12 +109,6 @@ namespace WPinternals if ((bool)e.NewValue) { - // Find the phone notifier - DependencyObject obj = d; - while (!(obj is MainWindow)) - obj = VisualTreeHelper.GetParent(obj); - PhoneNotifierViewModel PhoneNotifier = ((MainViewModel)(((MainWindow)obj).DataContext)).PhoneNotifier; - if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) { App.InterruptBoot = false; @@ -95,5 +117,30 @@ namespace WPinternals } } } + + internal void PhoneNotifier_NewDeviceArrived(ArrivalEventArgs Args) + { + if (App.InterruptBoot && Args.NewInterface == PhoneInterfaces.Lumia_Bootloader) + { + App.InterruptBoot = false; + LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode."); + Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash)); + } + + UIContext.Send(s => + { + if (!App.InterruptBoot && Args.NewInterface == PhoneInterfaces.Lumia_Bootloader) + { + StatusText.Content = "Phone is booting..."; + GifImage.Visibility = Visibility.Visible; + } + + if (!App.InterruptBoot && Args.NewInterface != PhoneInterfaces.Lumia_Bootloader) + { + StatusText.Content = "Waiting for connection with phone..."; + GifImage.Visibility = Visibility.Collapsed; + } + }, null); + } } } diff --git a/Views/MainWindow.xaml b/Views/MainWindow.xaml index f5aa697..0f4effb 100644 --- a/Views/MainWindow.xaml +++ b/Views/MainWindow.xaml @@ -34,6 +34,9 @@ DEALINGS IN THE SOFTWARE. + + + @@ -52,6 +55,9 @@ DEALINGS IN THE SOFTWARE. + + + diff --git a/Views/NokiaBootloaderView.xaml b/Views/NokiaBootloaderView.xaml new file mode 100644 index 0000000..558015e --- /dev/null +++ b/Views/NokiaBootloaderView.xaml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Getting started + + + + + + + + + + Normal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Views/NokiaBootloaderView.xaml.cs b/Views/NokiaBootloaderView.xaml.cs new file mode 100644 index 0000000..270c949 --- /dev/null +++ b/Views/NokiaBootloaderView.xaml.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; + +namespace WPinternals +{ + /// + /// Interaction logic for NokiaBootloaderView.xaml + /// + public partial class NokiaBootloaderView : UserControl + { + public NokiaBootloaderView() + { + InitializeComponent(); + + // Setting these properties in XAML results in an error. Why? + GifImage.GifSource = @"/aerobusy.gif"; + GifImage.AutoStart = true; + } + + private void HandleHyperlinkClick(object sender, RoutedEventArgs args) + { + Hyperlink link = args.Source as Hyperlink; + if ((link != null) && (link.NavigateUri != null)) + { + if (link.NavigateUri.ToString() == "GettingStarted") + (this.DataContext as NokiaBootloaderViewModel).SwitchToGettingStarted(); + + (this.DataContext as NokiaBootloaderViewModel).RebootTo(link.NavigateUri.ToString()); + } + } + + private void Document_Loaded(object sender, RoutedEventArgs e) + { + (sender as FlowDocument).AddHandler(Hyperlink.ClickEvent, new RoutedEventHandler(HandleHyperlinkClick)); + } + } +} diff --git a/Views/NokiaModeBootloaderView.xaml b/Views/NokiaModeBootloaderView.xaml new file mode 100644 index 0000000..c6b6b55 --- /dev/null +++ b/Views/NokiaModeBootloaderView.xaml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Switch to Normal-mode + + + + + Switch to Label-mode + + + + + Switch to Mass-Storage-mode + + + + + + + Shutdown the phone + + + + + + + + + + + + + + + + + + + diff --git a/Views/NokiaModeBootloaderView.xaml.cs b/Views/NokiaModeBootloaderView.xaml.cs new file mode 100644 index 0000000..0bd5d25 --- /dev/null +++ b/Views/NokiaModeBootloaderView.xaml.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; + +namespace WPinternals +{ + /// + /// Interaction logic for NokiaModeBootloaderView.xaml + /// + public partial class NokiaModeBootloaderView : UserControl + { + public NokiaModeBootloaderView() + { + InitializeComponent(); + } + + private void HandleHyperlinkClick(object sender, RoutedEventArgs args) + { + Hyperlink link = args.Source as Hyperlink; + if (link != null) + { + (this.DataContext as NokiaModeBootloaderViewModel).RebootTo(link.NavigateUri.ToString()); + } + } + + private void Document_Loaded(object sender, RoutedEventArgs e) + { + (sender as FlowDocument).AddHandler(Hyperlink.ClickEvent, new RoutedEventHandler(HandleHyperlinkClick)); + } + } +} diff --git a/Views/NokiaModeMassStorageView.xaml b/Views/NokiaModeMassStorageView.xaml index 23fa112..cd4503d 100644 --- a/Views/NokiaModeMassStorageView.xaml +++ b/Views/NokiaModeMassStorageView.xaml @@ -90,6 +90,27 @@ DEALINGS IN THE SOFTWARE. Switch to Flash-mode + + + Shutdown the phone + + + + + + + + + + + + + + + + + + diff --git a/WPinternals.csproj b/WPinternals.csproj index 58e5679..1bc1457 100644 --- a/WPinternals.csproj +++ b/WPinternals.csproj @@ -928,6 +928,8 @@ + + @@ -966,6 +968,12 @@ DisclaimerAndNdaView.xaml + + NokiaBootloaderView.xaml + + + NokiaModeBootloaderView.xaml + RegistrationView.xaml @@ -1089,6 +1097,14 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + MSBuild:Compile Designer