forked from Snoooopy/MetroUnlocker
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9bb878121 | |||
| 0b4ad51c6b | |||
| 0daf0af6a4 | |||
| e974fbb666 | |||
| 6aae858b2d | |||
| 50ee3736a7 | |||
| c61739ad0f | |||
| b3468ad58f | |||
| 5543eabedc | |||
| 0747a1b804 | |||
| e391b89771 | |||
| fddf24c6f9 | |||
| 0d85c73817 | |||
|
|
590588c3bc | ||
|
|
fbb27f8ed0 | ||
|
|
b286f8aa41 | ||
|
|
845e783cfd | ||
|
|
d0d1683b0d | ||
|
|
f527acdf97 | ||
|
|
5ae6b4da9a | ||
|
|
f90695dfda | ||
|
|
ec55169d57 | ||
|
|
aa0c40def3 |
@@ -5,6 +5,11 @@ VisualStudioVersion = 12.0.40629.0
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetroUnlocker", "MetroUnlocker\MetroUnlocker.csproj", "{D27EB145-0B58-43AD-BB94-BE000D236D38}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetroUnlocker", "MetroUnlocker\MetroUnlocker.csproj", "{D27EB145-0B58-43AD-BB94-BE000D236D38}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C9C14067-F9A1-4D85-A1D2-162E91B71CC3}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
DependencyGraph.dgml = DependencyGraph.dgml
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|||||||
131
MetroUnlocker/App.Designer.cs
generated
131
MetroUnlocker/App.Designer.cs
generated
@@ -29,35 +29,17 @@
|
|||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(App));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(App));
|
||||||
this.temporaryButton = new System.Windows.Forms.Button();
|
|
||||||
this.developmentCheckbox = new System.Windows.Forms.CheckBox();
|
this.developmentCheckbox = new System.Windows.Forms.CheckBox();
|
||||||
this.signedCheckbox = new System.Windows.Forms.CheckBox();
|
this.signedCheckbox = new System.Windows.Forms.CheckBox();
|
||||||
this.allUsersCheckbox = new System.Windows.Forms.CheckBox();
|
this.allUsersCheckbox = new System.Windows.Forms.CheckBox();
|
||||||
this.statusTextLabel = new System.Windows.Forms.Label();
|
this.statusTextLabel = new System.Windows.Forms.Label();
|
||||||
this.statusLabel = new System.Windows.Forms.Label();
|
this.statusLabel = new System.Windows.Forms.Label();
|
||||||
this.LOBCheckBox = new System.Windows.Forms.CheckBox();
|
this.groupBox = new System.Windows.Forms.GroupBox();
|
||||||
this.SPPCheckBox = new System.Windows.Forms.CheckBox();
|
this.disableButton = new System.Windows.Forms.Button();
|
||||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
this.unlockButton = new System.Windows.Forms.Button();
|
||||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
this.groupBox.SuspendLayout();
|
||||||
this.Manual = new System.Windows.Forms.TabControl();
|
|
||||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
|
||||||
this.button1 = new System.Windows.Forms.Button();
|
|
||||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
|
||||||
this.button2 = new System.Windows.Forms.Button();
|
|
||||||
this.groupBox1.SuspendLayout();
|
|
||||||
this.groupBox2.SuspendLayout();
|
|
||||||
this.Manual.SuspendLayout();
|
|
||||||
this.tabPage1.SuspendLayout();
|
|
||||||
this.tabPage2.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// temporaryButton
|
|
||||||
//
|
|
||||||
resources.ApplyResources(this.temporaryButton, "temporaryButton");
|
|
||||||
this.temporaryButton.Name = "temporaryButton";
|
|
||||||
this.temporaryButton.UseVisualStyleBackColor = true;
|
|
||||||
this.temporaryButton.Click += new System.EventHandler(this.button1_Click);
|
|
||||||
//
|
|
||||||
// developmentCheckbox
|
// developmentCheckbox
|
||||||
//
|
//
|
||||||
resources.ApplyResources(this.developmentCheckbox, "developmentCheckbox");
|
resources.ApplyResources(this.developmentCheckbox, "developmentCheckbox");
|
||||||
@@ -89,79 +71,36 @@
|
|||||||
resources.ApplyResources(this.statusLabel, "statusLabel");
|
resources.ApplyResources(this.statusLabel, "statusLabel");
|
||||||
this.statusLabel.Name = "statusLabel";
|
this.statusLabel.Name = "statusLabel";
|
||||||
//
|
//
|
||||||
// LOBCheckBox
|
// groupBox
|
||||||
//
|
//
|
||||||
resources.ApplyResources(this.LOBCheckBox, "LOBCheckBox");
|
resources.ApplyResources(this.groupBox, "groupBox");
|
||||||
this.LOBCheckBox.Name = "LOBCheckBox";
|
this.groupBox.Controls.Add(this.signedCheckbox);
|
||||||
this.LOBCheckBox.UseVisualStyleBackColor = true;
|
this.groupBox.Controls.Add(this.allUsersCheckbox);
|
||||||
|
this.groupBox.Controls.Add(this.developmentCheckbox);
|
||||||
|
this.groupBox.Name = "groupBox";
|
||||||
|
this.groupBox.TabStop = false;
|
||||||
//
|
//
|
||||||
// SPPCheckBox
|
// disableButton
|
||||||
//
|
//
|
||||||
resources.ApplyResources(this.SPPCheckBox, "SPPCheckBox");
|
resources.ApplyResources(this.disableButton, "disableButton");
|
||||||
this.SPPCheckBox.Name = "SPPCheckBox";
|
this.disableButton.Name = "disableButton";
|
||||||
this.SPPCheckBox.UseVisualStyleBackColor = true;
|
this.disableButton.UseVisualStyleBackColor = true;
|
||||||
|
this.disableButton.Click += new System.EventHandler(this.Uninstall);
|
||||||
//
|
//
|
||||||
// groupBox1
|
// unlockButton
|
||||||
//
|
//
|
||||||
resources.ApplyResources(this.groupBox1, "groupBox1");
|
resources.ApplyResources(this.unlockButton, "unlockButton");
|
||||||
this.groupBox1.Controls.Add(this.signedCheckbox);
|
this.unlockButton.Name = "unlockButton";
|
||||||
this.groupBox1.Controls.Add(this.allUsersCheckbox);
|
this.unlockButton.UseVisualStyleBackColor = true;
|
||||||
this.groupBox1.Controls.Add(this.developmentCheckbox);
|
this.unlockButton.Click += new System.EventHandler(this.Jailbreak);
|
||||||
this.groupBox1.Name = "groupBox1";
|
|
||||||
this.groupBox1.TabStop = false;
|
|
||||||
//
|
|
||||||
// groupBox2
|
|
||||||
//
|
|
||||||
resources.ApplyResources(this.groupBox2, "groupBox2");
|
|
||||||
this.groupBox2.Controls.Add(this.LOBCheckBox);
|
|
||||||
this.groupBox2.Controls.Add(this.SPPCheckBox);
|
|
||||||
this.groupBox2.Controls.Add(this.temporaryButton);
|
|
||||||
this.groupBox2.Name = "groupBox2";
|
|
||||||
this.groupBox2.TabStop = false;
|
|
||||||
//
|
|
||||||
// Manual
|
|
||||||
//
|
|
||||||
resources.ApplyResources(this.Manual, "Manual");
|
|
||||||
this.Manual.Controls.Add(this.tabPage1);
|
|
||||||
this.Manual.Controls.Add(this.tabPage2);
|
|
||||||
this.Manual.Name = "Manual";
|
|
||||||
this.Manual.SelectedIndex = 0;
|
|
||||||
//
|
|
||||||
// tabPage1
|
|
||||||
//
|
|
||||||
this.tabPage1.Controls.Add(this.button2);
|
|
||||||
this.tabPage1.Controls.Add(this.button1);
|
|
||||||
resources.ApplyResources(this.tabPage1, "tabPage1");
|
|
||||||
this.tabPage1.Name = "tabPage1";
|
|
||||||
this.tabPage1.UseVisualStyleBackColor = true;
|
|
||||||
//
|
|
||||||
// button1
|
|
||||||
//
|
|
||||||
resources.ApplyResources(this.button1, "button1");
|
|
||||||
this.button1.Name = "button1";
|
|
||||||
this.button1.UseVisualStyleBackColor = true;
|
|
||||||
this.button1.Click += new System.EventHandler(this.JailbreakButton_Click);
|
|
||||||
//
|
|
||||||
// tabPage2
|
|
||||||
//
|
|
||||||
this.tabPage2.Controls.Add(this.groupBox2);
|
|
||||||
this.tabPage2.Controls.Add(this.groupBox1);
|
|
||||||
resources.ApplyResources(this.tabPage2, "tabPage2");
|
|
||||||
this.tabPage2.Name = "tabPage2";
|
|
||||||
this.tabPage2.UseVisualStyleBackColor = true;
|
|
||||||
//
|
|
||||||
// button2
|
|
||||||
//
|
|
||||||
resources.ApplyResources(this.button2, "button2");
|
|
||||||
this.button2.Name = "button2";
|
|
||||||
this.button2.UseVisualStyleBackColor = true;
|
|
||||||
this.button2.Click += new System.EventHandler(this.Uninstall);
|
|
||||||
//
|
//
|
||||||
// App
|
// App
|
||||||
//
|
//
|
||||||
resources.ApplyResources(this, "$this");
|
resources.ApplyResources(this, "$this");
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.Controls.Add(this.Manual);
|
this.Controls.Add(this.disableButton);
|
||||||
|
this.Controls.Add(this.groupBox);
|
||||||
|
this.Controls.Add(this.unlockButton);
|
||||||
this.Controls.Add(this.statusLabel);
|
this.Controls.Add(this.statusLabel);
|
||||||
this.Controls.Add(this.statusTextLabel);
|
this.Controls.Add(this.statusTextLabel);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
@@ -171,13 +110,8 @@
|
|||||||
this.ShowIcon = false;
|
this.ShowIcon = false;
|
||||||
this.ShowInTaskbar = false;
|
this.ShowInTaskbar = false;
|
||||||
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
||||||
this.groupBox1.ResumeLayout(false);
|
this.groupBox.ResumeLayout(false);
|
||||||
this.groupBox1.PerformLayout();
|
this.groupBox.PerformLayout();
|
||||||
this.groupBox2.ResumeLayout(false);
|
|
||||||
this.groupBox2.PerformLayout();
|
|
||||||
this.Manual.ResumeLayout(false);
|
|
||||||
this.tabPage1.ResumeLayout(false);
|
|
||||||
this.tabPage2.ResumeLayout(false);
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
|
|
||||||
@@ -185,21 +119,14 @@
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.Button temporaryButton;
|
|
||||||
private System.Windows.Forms.CheckBox developmentCheckbox;
|
private System.Windows.Forms.CheckBox developmentCheckbox;
|
||||||
private System.Windows.Forms.CheckBox signedCheckbox;
|
private System.Windows.Forms.CheckBox signedCheckbox;
|
||||||
private System.Windows.Forms.CheckBox allUsersCheckbox;
|
private System.Windows.Forms.CheckBox allUsersCheckbox;
|
||||||
private System.Windows.Forms.Label statusTextLabel;
|
private System.Windows.Forms.Label statusTextLabel;
|
||||||
private System.Windows.Forms.Label statusLabel;
|
private System.Windows.Forms.Label statusLabel;
|
||||||
private System.Windows.Forms.GroupBox groupBox2;
|
private System.Windows.Forms.GroupBox groupBox;
|
||||||
private System.Windows.Forms.CheckBox LOBCheckBox;
|
private System.Windows.Forms.Button unlockButton;
|
||||||
private System.Windows.Forms.CheckBox SPPCheckBox;
|
private System.Windows.Forms.Button disableButton;
|
||||||
private System.Windows.Forms.GroupBox groupBox1;
|
|
||||||
private System.Windows.Forms.TabControl Manual;
|
|
||||||
private System.Windows.Forms.TabPage tabPage1;
|
|
||||||
private System.Windows.Forms.Button button1;
|
|
||||||
private System.Windows.Forms.TabPage tabPage2;
|
|
||||||
private System.Windows.Forms.Button button2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Drawing;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
@@ -16,38 +17,38 @@ namespace MetroUnlocker
|
|||||||
{
|
{
|
||||||
public partial class App : Form
|
public partial class App : Form
|
||||||
{
|
{
|
||||||
public const string AppxKey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\Windows\\Appx";
|
public const string AppxRegistryKey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\Windows\\Appx";
|
||||||
|
|
||||||
string trustedAppsPolicyName = "AllowAllTrustedApps";
|
string TrustedAppsPolicyName = "AllowAllTrustedApps";
|
||||||
string developmentPolicyName = "AllowDevelopmentWithoutDevLicense";
|
string DevelopmentPolicyName = "AllowDevelopmentWithoutDevLicense";
|
||||||
string specialProfilesPolicyName = "AllowDeploymentInSpecialProfiles";
|
string SpecialProfilesPolicyName = "AllowDeploymentInSpecialProfiles";
|
||||||
|
|
||||||
public bool LOBEnabled
|
public bool LOBEnabled
|
||||||
{
|
{
|
||||||
get { return GetGroupPolicy(trustedAppsPolicyName); }
|
get { return GetGroupPolicy(TrustedAppsPolicyName); }
|
||||||
set { SetGroupPolicy(trustedAppsPolicyName, value); }
|
set { SetGroupPolicy(TrustedAppsPolicyName, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DevelopmentEnabled
|
public bool DevelopmentEnabled
|
||||||
{
|
{
|
||||||
get { return GetGroupPolicy(developmentPolicyName); }
|
get { return GetGroupPolicy(DevelopmentPolicyName); }
|
||||||
set { SetGroupPolicy(developmentPolicyName, value); }
|
set { SetGroupPolicy(DevelopmentPolicyName, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SpecialProfilesEnabled
|
public bool SpecialProfilesEnabled
|
||||||
{
|
{
|
||||||
get { return GetGroupPolicy(specialProfilesPolicyName); }
|
get { return GetGroupPolicy(SpecialProfilesPolicyName); }
|
||||||
set { SetGroupPolicy(specialProfilesPolicyName, value); }
|
set { SetGroupPolicy(SpecialProfilesPolicyName, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetGroupPolicy(string policyName, bool enabled)
|
public void SetGroupPolicy(string policyName, bool enabled)
|
||||||
{
|
{
|
||||||
Registry.SetValue(AppxKey, policyName, enabled ? 1 : 0, RegistryValueKind.DWord);
|
Registry.SetValue(AppxRegistryKey, policyName, enabled ? 1 : 0, RegistryValueKind.DWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetGroupPolicy(string policyName)
|
public bool GetGroupPolicy(string policyName)
|
||||||
{
|
{
|
||||||
object value = Registry.GetValue(AppxKey, policyName, 0);
|
object value = Registry.GetValue(AppxRegistryKey, policyName, 0);
|
||||||
return value is int ? (int)value == 1 : false;
|
return value is int ? (int)value == 1 : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,82 +61,36 @@ namespace MetroUnlocker
|
|||||||
|
|
||||||
public void UpdatePolicyState()
|
public void UpdatePolicyState()
|
||||||
{
|
{
|
||||||
var productPolicyEditor = new ProductPolicyEditor();
|
var productPolicyEditor = new ProductPolicyReader();
|
||||||
|
|
||||||
var policyState = productPolicyEditor.GetPolicyStateByName("WSLicensingService-LOBSideloadingActivated");
|
var policyState = productPolicyEditor.GetPolicyStateByName("WSLicensingService-LOBSideloadingActivated");
|
||||||
var isSideloadingKeyInstalled = LOBManager.IsSideloadingKeyInstalled();
|
var isSideloadingKeyInstalled = LOBManager.IsSideloadingKeyInstalled();
|
||||||
|
|
||||||
|
statusLabel.ForeColor = isSideloadingKeyInstalled ? Color.DarkGreen: Color.DarkOrange;
|
||||||
|
disableButton.Enabled = isSideloadingKeyInstalled;
|
||||||
|
|
||||||
switch (policyState)
|
switch (policyState)
|
||||||
{
|
{
|
||||||
case PolicyState.Disabled:
|
case PolicyState.Disabled:
|
||||||
statusLabel.Text = "Disabled";
|
|
||||||
statusLabel.ForeColor = Color.DarkRed;
|
|
||||||
break;
|
|
||||||
case PolicyState.Enabled:
|
|
||||||
if (isSideloadingKeyInstalled)
|
if (isSideloadingKeyInstalled)
|
||||||
{
|
statusLabel.Text = "Enabling...";
|
||||||
statusLabel.Text = "Sideloading enabled";
|
|
||||||
statusLabel.ForeColor = Color.DarkGreen;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
statusLabel.Text = "Sideloading will be disabled soon";
|
statusLabel.Text = "Disabled";
|
||||||
statusLabel.ForeColor = Color.DarkOrange;
|
statusLabel.ForeColor = Color.DarkRed;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PolicyState.Unknown:
|
case PolicyState.Enabled:
|
||||||
|
statusLabel.Text = isSideloadingKeyInstalled ? "Sideloading enabled" : "Disabling...";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
statusLabel.Text = "Unknown";
|
statusLabel.Text = "Unknown";
|
||||||
statusLabel.ForeColor = Color.Black;
|
statusLabel.ForeColor = Color.Black;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CombineArguments(params string[] arguments)
|
private void Jailbreak(object sender, EventArgs e)
|
||||||
{
|
|
||||||
return string.Join(" ", arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetSetupParameter(string key, object value, RegistryValueKind valueKind)
|
|
||||||
{
|
|
||||||
Registry.SetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\Setup", key, value, valueKind);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetSetupType(int type)
|
|
||||||
{
|
|
||||||
SetSetupParameter("SetupType", type, RegistryValueKind.DWord);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void button1_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
StartupArgument startupArgument;
|
|
||||||
|
|
||||||
if (LOBCheckBox.Checked && SPPCheckBox.Checked)
|
|
||||||
startupArgument = StartupArgument.EnableLOBAndEnableSPP;
|
|
||||||
else if (LOBCheckBox.Checked)
|
|
||||||
startupArgument = StartupArgument.EnableLOBAndDisableSPP;
|
|
||||||
else if (SPPCheckBox.Checked)
|
|
||||||
startupArgument = StartupArgument.DisableLOBAndEnableSPP;
|
|
||||||
else
|
|
||||||
startupArgument = StartupArgument.DisableLOBAndDisableSPP;
|
|
||||||
|
|
||||||
string commandLine = CombineArguments(new string[] { Application.ExecutablePath, StartupArguments.GetStartupArgumentString(startupArgument) });
|
|
||||||
|
|
||||||
SetSetupParameter("CmdLine", commandLine, RegistryValueKind.String);
|
|
||||||
SetSetupType(1);
|
|
||||||
DialogResult result = MessageBox.Show("Sideloading will be enabled after a reboot. Would you like to reboot now?", "Reboot?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
|
|
||||||
|
|
||||||
switch (result)
|
|
||||||
{
|
|
||||||
case DialogResult.Yes:
|
|
||||||
Rebooter.Reboot();
|
|
||||||
break;
|
|
||||||
case DialogResult.Cancel:
|
|
||||||
SetSetupType(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void JailbreakButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -145,12 +100,19 @@ namespace MetroUnlocker
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
LOBManager.ActivateZeroCID();
|
LOBManager.ActivateZeroCID();
|
||||||
|
|
||||||
|
LOBEnabled = true;
|
||||||
|
DevelopmentEnabled = true;
|
||||||
|
|
||||||
MessageBox.Show(this, "Sideloading activated!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
MessageBox.Show(this, "Sideloading activated!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
|
||||||
UpdatePolicyState();
|
UpdatePolicyState();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.Show(this, ex.Message, "Error while activating sideloading!", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
if (ex is COMException && ((uint)((COMException)ex).ErrorCode) == 0xC004F014)
|
||||||
|
MessageBox.Show(this, "You likely ran out of storage or something else caused your tokens.dat to get corrupted. SPPSVC will recreate it. Try rebooting to let Windows reactivate itself before trying again. Make sure you have at least 30MB free before using Sideloading Unlocker.", "The key was recognised but I can't activate it.", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
else MessageBox.Show(this, ex.Message, "Error while activating sideloading!", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,221 +117,59 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
|
||||||
<data name="temporaryButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
|
||||||
<value>Bottom, Left, Right</value>
|
|
||||||
</data>
|
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
|
||||||
<data name="temporaryButton.Location" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>6, 42</value>
|
|
||||||
</data>
|
|
||||||
<data name="temporaryButton.Size" type="System.Drawing.Size, System.Drawing">
|
|
||||||
<value>210, 23</value>
|
|
||||||
</data>
|
|
||||||
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
|
||||||
<data name="temporaryButton.TabIndex" type="System.Int32, mscorlib">
|
|
||||||
<value>0</value>
|
|
||||||
</data>
|
|
||||||
<data name="temporaryButton.Text" xml:space="preserve">
|
|
||||||
<value>Reboot to Apply</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>temporaryButton.Name" xml:space="preserve">
|
|
||||||
<value>temporaryButton</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>temporaryButton.Type" xml:space="preserve">
|
|
||||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>temporaryButton.Parent" xml:space="preserve">
|
|
||||||
<value>groupBox2</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>temporaryButton.ZOrder" xml:space="preserve">
|
|
||||||
<value>2</value>
|
|
||||||
</data>
|
|
||||||
<data name="developmentCheckbox.AccessibleDescription" xml:space="preserve">
|
<data name="developmentCheckbox.AccessibleDescription" xml:space="preserve">
|
||||||
<value>Allows sideloading of unpackaged apps.</value>
|
<value>Allows sideloading of unpackaged apps.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
<data name="developmentCheckbox.AutoSize" type="System.Boolean, mscorlib">
|
<data name="developmentCheckbox.AutoSize" type="System.Boolean, mscorlib">
|
||||||
<value>True</value>
|
<value>True</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<value>True</value>
|
<value>True</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
||||||
<value>6, 13</value>
|
<value>6, 13</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="$this.AutoSize" type="System.Boolean, mscorlib">
|
<data name="$this.AutoSize" type="System.Boolean, mscorlib">
|
||||||
<value>True</value>
|
<value>True</value>
|
||||||
</data>
|
</data>
|
||||||
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
<data name="$this.AutoSizeMode" type="System.Windows.Forms.AutoSizeMode, System.Windows.Forms">
|
<data name="$this.AutoSizeMode" type="System.Windows.Forms.AutoSizeMode, System.Windows.Forms">
|
||||||
<value>GrowAndShrink</value>
|
<value>GrowAndShrink</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>266, 215</value>
|
<value>252, 200</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Manual.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
<data name="disableButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||||
<value>Top, Bottom, Left, Right</value>
|
<value>Bottom, Left, Right</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="button2.Location" type="System.Drawing.Point, System.Drawing">
|
<data name="disableButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||||
<value>7, 123</value>
|
<value>12, 165</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="button2.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="disableButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>221, 23</value>
|
<value>228, 23</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="button2.TabIndex" type="System.Int32, mscorlib">
|
<data name="disableButton.TabIndex" type="System.Int32, mscorlib">
|
||||||
<value>1</value>
|
<value>1</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="button2.Text" xml:space="preserve">
|
<data name="disableButton.Text" xml:space="preserve">
|
||||||
<value>Disable Sideloading</value>
|
<value>Disable Sideloading</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>button2.Name" xml:space="preserve">
|
<data name=">>disableButton.Name" xml:space="preserve">
|
||||||
<value>button2</value>
|
<value>disableButton</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>button2.Type" xml:space="preserve">
|
<data name=">>disableButton.Type" xml:space="preserve">
|
||||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>button2.Parent" xml:space="preserve">
|
<data name=">>disableButton.Parent" xml:space="preserve">
|
||||||
<value>tabPage1</value>
|
<value>$this</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>button2.ZOrder" xml:space="preserve">
|
<data name=">>disableButton.ZOrder" xml:space="preserve">
|
||||||
<value>0</value>
|
<value>0</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="button1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
<data name="groupBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||||
<value>Top, Bottom, Left, Right</value>
|
<value>Bottom, Left, Right</value>
|
||||||
</data>
|
|
||||||
<data name="button1.Location" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>6, 6</value>
|
|
||||||
</data>
|
|
||||||
<data name="button1.Size" type="System.Drawing.Size, System.Drawing">
|
|
||||||
<value>222, 111</value>
|
|
||||||
</data>
|
|
||||||
<data name="button1.TabIndex" type="System.Int32, mscorlib">
|
|
||||||
<value>0</value>
|
|
||||||
</data>
|
|
||||||
<data name="button1.Text" xml:space="preserve">
|
|
||||||
<value>Unlock!</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>button1.Name" xml:space="preserve">
|
|
||||||
<value>button1</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>button1.Type" xml:space="preserve">
|
|
||||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>button1.Parent" xml:space="preserve">
|
|
||||||
<value>tabPage1</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>button1.ZOrder" xml:space="preserve">
|
|
||||||
<value>1</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage1.Location" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>4, 22</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage1.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
|
||||||
<value>3, 3, 3, 3</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage1.Size" type="System.Drawing.Size, System.Drawing">
|
|
||||||
<value>234, 152</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage1.TabIndex" type="System.Int32, mscorlib">
|
|
||||||
<value>0</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage1.Text" xml:space="preserve">
|
|
||||||
<value>Jailbreak</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>tabPage1.Name" xml:space="preserve">
|
|
||||||
<value>tabPage1</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>tabPage1.Type" xml:space="preserve">
|
|
||||||
<value>System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>tabPage1.Parent" xml:space="preserve">
|
|
||||||
<value>Manual</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>tabPage1.ZOrder" xml:space="preserve">
|
|
||||||
<value>0</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
|
||||||
<value>Top, Bottom, Left, Right</value>
|
|
||||||
</data>
|
|
||||||
<data name="LOBCheckBox.AutoSize" type="System.Boolean, mscorlib">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="LOBCheckBox.Location" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>6, 19</value>
|
|
||||||
</data>
|
|
||||||
<data name="LOBCheckBox.Size" type="System.Drawing.Size, System.Drawing">
|
|
||||||
<value>81, 17</value>
|
|
||||||
</data>
|
|
||||||
<data name="LOBCheckBox.TabIndex" type="System.Int32, mscorlib">
|
|
||||||
<value>1</value>
|
|
||||||
</data>
|
|
||||||
<data name="LOBCheckBox.Text" xml:space="preserve">
|
|
||||||
<value>Sideloading</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>LOBCheckBox.Name" xml:space="preserve">
|
|
||||||
<value>LOBCheckBox</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>LOBCheckBox.Type" xml:space="preserve">
|
|
||||||
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>LOBCheckBox.Parent" xml:space="preserve">
|
|
||||||
<value>groupBox2</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>LOBCheckBox.ZOrder" xml:space="preserve">
|
|
||||||
<value>0</value>
|
|
||||||
</data>
|
|
||||||
<data name="SPPCheckBox.AutoSize" type="System.Boolean, mscorlib">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="SPPCheckBox.Location" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>95, 19</value>
|
|
||||||
</data>
|
|
||||||
<data name="SPPCheckBox.Size" type="System.Drawing.Size, System.Drawing">
|
|
||||||
<value>119, 17</value>
|
|
||||||
</data>
|
|
||||||
<data name="SPPCheckBox.TabIndex" type="System.Int32, mscorlib">
|
|
||||||
<value>2</value>
|
|
||||||
</data>
|
|
||||||
<data name="SPPCheckBox.Text" xml:space="preserve">
|
|
||||||
<value>Software Protection</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>SPPCheckBox.Name" xml:space="preserve">
|
|
||||||
<value>SPPCheckBox</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>SPPCheckBox.Type" xml:space="preserve">
|
|
||||||
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>SPPCheckBox.Parent" xml:space="preserve">
|
|
||||||
<value>groupBox2</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>SPPCheckBox.ZOrder" xml:space="preserve">
|
|
||||||
<value>1</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.Location" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>6, 75</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.Size" type="System.Drawing.Size, System.Drawing">
|
|
||||||
<value>222, 71</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.TabIndex" type="System.Int32, mscorlib">
|
|
||||||
<value>8</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.Text" xml:space="preserve">
|
|
||||||
<value>Product Policy</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>groupBox2.Name" xml:space="preserve">
|
|
||||||
<value>groupBox2</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>groupBox2.Type" xml:space="preserve">
|
|
||||||
<value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>groupBox2.Parent" xml:space="preserve">
|
|
||||||
<value>tabPage2</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>groupBox2.ZOrder" xml:space="preserve">
|
|
||||||
<value>0</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
|
||||||
<value>Top, Left, Right</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="signedCheckbox.AccessibleDescription" xml:space="preserve">
|
<data name="signedCheckbox.AccessibleDescription" xml:space="preserve">
|
||||||
<value>Enables sideloading of signed apps.</value>
|
<value>Enables sideloading of signed apps.</value>
|
||||||
@@ -358,7 +196,7 @@
|
|||||||
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>signedCheckbox.Parent" xml:space="preserve">
|
<data name=">>signedCheckbox.Parent" xml:space="preserve">
|
||||||
<value>groupBox1</value>
|
<value>groupBox</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>signedCheckbox.ZOrder" xml:space="preserve">
|
<data name=">>signedCheckbox.ZOrder" xml:space="preserve">
|
||||||
<value>0</value>
|
<value>0</value>
|
||||||
@@ -373,7 +211,7 @@
|
|||||||
<value>True</value>
|
<value>True</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="allUsersCheckbox.Location" type="System.Drawing.Point, System.Drawing">
|
<data name="allUsersCheckbox.Location" type="System.Drawing.Point, System.Drawing">
|
||||||
<value>149, 19</value>
|
<value>155, 19</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="allUsersCheckbox.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="allUsersCheckbox.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>67, 17</value>
|
<value>67, 17</value>
|
||||||
@@ -391,88 +229,67 @@
|
|||||||
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>allUsersCheckbox.Parent" xml:space="preserve">
|
<data name=">>allUsersCheckbox.Parent" xml:space="preserve">
|
||||||
<value>groupBox1</value>
|
<value>groupBox</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>allUsersCheckbox.ZOrder" xml:space="preserve">
|
<data name=">>allUsersCheckbox.ZOrder" xml:space="preserve">
|
||||||
<value>1</value>
|
<value>1</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="groupBox1.Location" type="System.Drawing.Point, System.Drawing">
|
<data name="groupBox.Location" type="System.Drawing.Point, System.Drawing">
|
||||||
<value>6, 6</value>
|
<value>12, 96</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="groupBox1.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="groupBox.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>222, 63</value>
|
<value>228, 63</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="groupBox1.TabIndex" type="System.Int32, mscorlib">
|
<data name="groupBox.TabIndex" type="System.Int32, mscorlib">
|
||||||
<value>7</value>
|
<value>7</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="groupBox1.Text" xml:space="preserve">
|
<data name="groupBox.Text" xml:space="preserve">
|
||||||
<value>Group Policy</value>
|
<value>Group Policy</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>groupBox1.Name" xml:space="preserve">
|
<data name=">>groupBox.Name" xml:space="preserve">
|
||||||
<value>groupBox1</value>
|
<value>groupBox</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>groupBox1.Type" xml:space="preserve">
|
<data name=">>groupBox.Type" xml:space="preserve">
|
||||||
<value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>groupBox1.Parent" xml:space="preserve">
|
<data name=">>groupBox.Parent" xml:space="preserve">
|
||||||
<value>tabPage2</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>groupBox1.ZOrder" xml:space="preserve">
|
|
||||||
<value>1</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage2.Location" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>4, 22</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage2.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
|
||||||
<value>3, 3, 3, 3</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage2.Size" type="System.Drawing.Size, System.Drawing">
|
|
||||||
<value>234, 152</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage2.TabIndex" type="System.Int32, mscorlib">
|
|
||||||
<value>1</value>
|
|
||||||
</data>
|
|
||||||
<data name="tabPage2.Text" xml:space="preserve">
|
|
||||||
<value>Manual</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>tabPage2.Name" xml:space="preserve">
|
|
||||||
<value>tabPage2</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>tabPage2.Type" xml:space="preserve">
|
|
||||||
<value>System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>tabPage2.Parent" xml:space="preserve">
|
|
||||||
<value>Manual</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>tabPage2.ZOrder" xml:space="preserve">
|
|
||||||
<value>1</value>
|
|
||||||
</data>
|
|
||||||
<data name="Manual.Location" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>12, 25</value>
|
|
||||||
</data>
|
|
||||||
<data name="Manual.Size" type="System.Drawing.Size, System.Drawing">
|
|
||||||
<value>242, 178</value>
|
|
||||||
</data>
|
|
||||||
<data name="Manual.TabIndex" type="System.Int32, mscorlib">
|
|
||||||
<value>9</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>Manual.Name" xml:space="preserve">
|
|
||||||
<value>Manual</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>Manual.Type" xml:space="preserve">
|
|
||||||
<value>System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name=">>Manual.Parent" xml:space="preserve">
|
|
||||||
<value>$this</value>
|
<value>$this</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>Manual.ZOrder" xml:space="preserve">
|
<data name=">>groupBox.ZOrder" xml:space="preserve">
|
||||||
|
<value>1</value>
|
||||||
|
</data>
|
||||||
|
<data name="unlockButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||||
|
<value>Top, Bottom, Left, Right</value>
|
||||||
|
</data>
|
||||||
|
<data name="unlockButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||||
|
<value>12, 25</value>
|
||||||
|
</data>
|
||||||
|
<data name="unlockButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
|
<value>228, 65</value>
|
||||||
|
</data>
|
||||||
|
<data name="unlockButton.TabIndex" type="System.Int32, mscorlib">
|
||||||
<value>0</value>
|
<value>0</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="unlockButton.Text" xml:space="preserve">
|
||||||
|
<value>Unlock!</value>
|
||||||
|
</data>
|
||||||
|
<data name=">>unlockButton.Name" xml:space="preserve">
|
||||||
|
<value>unlockButton</value>
|
||||||
|
</data>
|
||||||
|
<data name=">>unlockButton.Type" xml:space="preserve">
|
||||||
|
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
|
<data name=">>unlockButton.Parent" xml:space="preserve">
|
||||||
|
<value>$this</value>
|
||||||
|
</data>
|
||||||
|
<data name=">>unlockButton.ZOrder" xml:space="preserve">
|
||||||
|
<value>2</value>
|
||||||
|
</data>
|
||||||
<data name="statusLabel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
<data name="statusLabel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||||
<value>Top, Right</value>
|
<value>Top, Right</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="statusLabel.Location" type="System.Drawing.Point, System.Drawing">
|
<data name="statusLabel.Location" type="System.Drawing.Point, System.Drawing">
|
||||||
<value>58, 9</value>
|
<value>44, 9</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="statusLabel.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="statusLabel.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>196, 13</value>
|
<value>196, 13</value>
|
||||||
@@ -496,7 +313,7 @@
|
|||||||
<value>$this</value>
|
<value>$this</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>statusLabel.ZOrder" xml:space="preserve">
|
<data name=">>statusLabel.ZOrder" xml:space="preserve">
|
||||||
<value>1</value>
|
<value>3</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="statusTextLabel.AutoSize" type="System.Boolean, mscorlib">
|
<data name="statusTextLabel.AutoSize" type="System.Boolean, mscorlib">
|
||||||
<value>True</value>
|
<value>True</value>
|
||||||
@@ -523,7 +340,7 @@
|
|||||||
<value>$this</value>
|
<value>$this</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>statusTextLabel.ZOrder" xml:space="preserve">
|
<data name=">>statusTextLabel.ZOrder" xml:space="preserve">
|
||||||
<value>2</value>
|
<value>4</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
|
<data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
|
||||||
<value>CenterScreen</value>
|
<value>CenterScreen</value>
|
||||||
@@ -556,7 +373,7 @@
|
|||||||
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>developmentCheckbox.Parent" xml:space="preserve">
|
<data name=">>developmentCheckbox.Parent" xml:space="preserve">
|
||||||
<value>groupBox1</value>
|
<value>groupBox</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>developmentCheckbox.ZOrder" xml:space="preserve">
|
<data name=">>developmentCheckbox.ZOrder" xml:space="preserve">
|
||||||
<value>2</value>
|
<value>2</value>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using MetroUnlocker.LibTSForge.SPP;
|
|||||||
// Common.cs
|
// Common.cs
|
||||||
namespace MetroUnlocker
|
namespace MetroUnlocker
|
||||||
{
|
{
|
||||||
public enum PSVersion
|
public enum PhysicalStoreVersion
|
||||||
{
|
{
|
||||||
Win8Early,
|
Win8Early,
|
||||||
Win8,
|
Win8,
|
||||||
@@ -33,7 +33,7 @@ namespace MetroUnlocker
|
|||||||
public static class Constants
|
public static class Constants
|
||||||
{
|
{
|
||||||
public static readonly string ZeroCID = new string('0', 48);
|
public static readonly string ZeroCID = new string('0', 48);
|
||||||
public static readonly byte[] UniversalHWIDBlock =
|
public static readonly byte[] UniversalHardwareIdBlock =
|
||||||
{
|
{
|
||||||
0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00,
|
0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
@@ -45,9 +45,6 @@ namespace MetroUnlocker
|
|||||||
|
|
||||||
public static class Utils
|
public static class Utils
|
||||||
{
|
{
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
public static extern uint GetSystemDefaultLCID();
|
|
||||||
|
|
||||||
public static string GetArchitecture()
|
public static string GetArchitecture()
|
||||||
{
|
{
|
||||||
string arch = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE", EnvironmentVariableTarget.Machine).ToUpperInvariant();
|
string arch = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE", EnvironmentVariableTarget.Machine).ToUpperInvariant();
|
||||||
@@ -146,8 +143,6 @@ namespace MetroUnlocker
|
|||||||
throw new InvalidOperationException("Unable to access sppsvc: " + ex.Message);
|
throw new InvalidOperationException("Unable to access sppsvc: " + ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Logger.WriteLine("Stopping sppsvc...");
|
|
||||||
|
|
||||||
bool stopped = false;
|
bool stopped = false;
|
||||||
|
|
||||||
for (int i = 0; stopped == false && i < 60; i++)
|
for (int i = 0; stopped == false && i < 60; i++)
|
||||||
@@ -174,19 +169,14 @@ namespace MetroUnlocker
|
|||||||
|
|
||||||
if (!stopped)
|
if (!stopped)
|
||||||
throw new System.TimeoutException("Failed to stop sppsvc");
|
throw new System.TimeoutException("Failed to stop sppsvc");
|
||||||
|
|
||||||
//Logger.WriteLine("sppsvc stopped successfully.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PSVersion DetectVersion()
|
public static PhysicalStoreVersion DetectVersion()
|
||||||
{
|
{
|
||||||
int build = Environment.OSVersion.Version.Build;
|
int build = Environment.OSVersion.Version.Build;
|
||||||
|
|
||||||
if (build >= 9600) return PSVersion.WinModern;
|
if (build >= 9600) return PhysicalStoreVersion.WinModern;
|
||||||
//if (build >= 6000 && build <= 6003) return PSVersion.Vista;
|
if (build == 9200) return PhysicalStoreVersion.Win8;
|
||||||
//if (build >= 7600 && build <= 7602) return PSVersion.Win7;
|
|
||||||
if (build == 9200) return PSVersion.Win8;
|
|
||||||
|
|
||||||
throw new NotSupportedException("This version of Windows is not supported. (build " + build + ")");
|
throw new NotSupportedException("This version of Windows is not supported. (build " + build + ")");
|
||||||
}
|
}
|
||||||
@@ -196,15 +186,9 @@ namespace MetroUnlocker
|
|||||||
SLApi.RefreshLicenseStatus();
|
SLApi.RefreshLicenseStatus();
|
||||||
|
|
||||||
using (RegistryKey wpaKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\WPA"))
|
using (RegistryKey wpaKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\WPA"))
|
||||||
{
|
|
||||||
foreach (string subKey in wpaKey.GetSubKeyNames())
|
foreach (string subKey in wpaKey.GetSubKeyNames())
|
||||||
{
|
|
||||||
if (subKey.StartsWith("8DEC0AF1") && subKey.EndsWith("-1"))
|
if (subKey.StartsWith("8DEC0AF1") && subKey.EndsWith("-1"))
|
||||||
{
|
|
||||||
return subKey.Contains("P");
|
return subKey.Contains("P");
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new FileNotFoundException("Failed to autodetect key type, specify physical store key with /prod or /test arguments.");
|
throw new FileNotFoundException("Failed to autodetect key type, specify physical store key with /prod or /test arguments.");
|
||||||
}
|
}
|
||||||
@@ -230,6 +214,10 @@ namespace MetroUnlocker
|
|||||||
public string Name;
|
public string Name;
|
||||||
public Dictionary<string, string> Data = new Dictionary<string, string>();
|
public Dictionary<string, string> Data = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
public TokenMeta() { }
|
||||||
|
public TokenMeta(string name) { Name = name; }
|
||||||
|
public TokenMeta(byte[] data) { Deserialize(data); }
|
||||||
|
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
{
|
{
|
||||||
BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
||||||
@@ -267,15 +255,5 @@ namespace MetroUnlocker
|
|||||||
Data[key] = value;
|
Data[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TokenMeta(byte[] data)
|
|
||||||
{
|
|
||||||
Deserialize(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TokenMeta()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,12 +5,11 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
using MetroUnlocker.ProductPolicy;
|
|
||||||
using MetroUnlocker;
|
using MetroUnlocker;
|
||||||
using MetroUnlocker.LibTSForge.PhysicalStore;
|
using MetroUnlocker.LibTSForge.SPP;
|
||||||
using MetroUnlocker.LibTSForge.Modifiers;
|
using MetroUnlocker.LibTSForge.Modifiers;
|
||||||
using MetroUnlocker.LibTSForge.TokenStore;
|
using MetroUnlocker.LibTSForge.TokenStore;
|
||||||
using MetroUnlocker.LibTSForge.SPP;
|
using MetroUnlocker.LibTSForge.PhysicalStore;
|
||||||
|
|
||||||
namespace MetroUnlocker
|
namespace MetroUnlocker
|
||||||
{
|
{
|
||||||
@@ -22,19 +21,25 @@ namespace MetroUnlocker
|
|||||||
|
|
||||||
public static void ActivateZeroCID()
|
public static void ActivateZeroCID()
|
||||||
{
|
{
|
||||||
PSVersion version = Utils.DetectVersion();
|
PhysicalStoreVersion version = Utils.DetectVersion();
|
||||||
bool production = Utils.DetectCurrentKey();
|
bool production = Utils.DetectCurrentKey();
|
||||||
|
|
||||||
if (Backup) BackupPhysicalStore();
|
if (Backup) BackupPhysicalStore();
|
||||||
|
|
||||||
GenPKeyInstall.InstallGenPKey(version, production, ActivationId);
|
ProductKeyInstaller.InstallGeneratedProductKey(version, production, ActivationId);
|
||||||
|
|
||||||
ZeroCID.Activate(version, production, ActivationId);
|
ZeroCID.Activate(version, production, ActivationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Guid GetInstalledSideloadingKeyId()
|
public static Guid GetInstalledSideloadingKeyId()
|
||||||
{
|
{
|
||||||
return SLApi.GetInstalledPkeyId(ActivationId);
|
return SLApi.GetInstalledProductKeyId(ActivationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsSideloadingKeyInstalled()
|
||||||
|
{
|
||||||
|
Guid sideloadingKeyId;
|
||||||
|
return IsSideloadingKeyInstalled(out sideloadingKeyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsSideloadingKeyInstalled(out Guid sideloadingKeyId)
|
public static bool IsSideloadingKeyInstalled(out Guid sideloadingKeyId)
|
||||||
@@ -80,28 +85,5 @@ namespace MetroUnlocker
|
|||||||
|
|
||||||
File.Copy(physicalStore, GetUniqueFileName(backupFileName), false);
|
File.Copy(physicalStore, GetUniqueFileName(backupFileName), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool SetPolicyState(PolicyState state)
|
|
||||||
{
|
|
||||||
ProductPolicyEditor policyEditor = new ProductPolicyEditor();
|
|
||||||
policyEditor.SetPolicyStateByName("WSLicensingService-LOBSideloadingActivated", state);
|
|
||||||
return policyEditor.Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Enable()
|
|
||||||
{
|
|
||||||
return SetPolicyState(PolicyState.Enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Disable()
|
|
||||||
{
|
|
||||||
return SetPolicyState(PolicyState.Disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsSideloadingKeyInstalled()
|
|
||||||
{
|
|
||||||
Guid sideloadingKeyId;
|
|
||||||
return IsSideloadingKeyInstalled(out sideloadingKeyId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ namespace MetroUnlocker.LibTSForge.Crypto
|
|||||||
{
|
{
|
||||||
public static class CryptoUtils
|
public static class CryptoUtils
|
||||||
{
|
{
|
||||||
public static byte[] GenerateRandomKey(int len)
|
public static byte[] GenerateRandomKey(int length)
|
||||||
{
|
{
|
||||||
byte[] rand = new byte[len];
|
byte[] randomKey = new byte[length];
|
||||||
Random r = new Random();
|
Random random = new Random();
|
||||||
r.NextBytes(rand);
|
random.NextBytes(randomKey);
|
||||||
|
|
||||||
return rand;
|
return randomKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] AESEncrypt(byte[] data, byte[] key)
|
public static byte[] AESEncrypt(byte[] data, byte[] key)
|
||||||
@@ -72,9 +72,7 @@ namespace MetroUnlocker.LibTSForge.Crypto
|
|||||||
|
|
||||||
byte[] hash;
|
byte[] hash;
|
||||||
using (SHA1 sha1 = SHA1.Create())
|
using (SHA1 sha1 = SHA1.Create())
|
||||||
{
|
|
||||||
hash = sha1.ComputeHash(data);
|
hash = sha1.ComputeHash(data);
|
||||||
}
|
|
||||||
|
|
||||||
return formatter.CreateSignature(hash);
|
return formatter.CreateSignature(hash);
|
||||||
}
|
}
|
||||||
@@ -90,9 +88,7 @@ namespace MetroUnlocker.LibTSForge.Crypto
|
|||||||
|
|
||||||
byte[] hash;
|
byte[] hash;
|
||||||
using (SHA1 sha1 = SHA1.Create())
|
using (SHA1 sha1 = SHA1.Create())
|
||||||
{
|
|
||||||
hash = sha1.ComputeHash(data);
|
hash = sha1.ComputeHash(data);
|
||||||
}
|
|
||||||
|
|
||||||
return deformatter.VerifySignature(hash, signature);
|
return deformatter.VerifySignature(hash, signature);
|
||||||
}
|
}
|
||||||
@@ -113,9 +109,7 @@ namespace MetroUnlocker.LibTSForge.Crypto
|
|||||||
public static byte[] SHA256Hash(byte[] data)
|
public static byte[] SHA256Hash(byte[] data)
|
||||||
{
|
{
|
||||||
using (SHA256 sha256 = SHA256.Create())
|
using (SHA256 sha256 = SHA256.Create())
|
||||||
{
|
|
||||||
return sha256.ComputeHash(data);
|
return sha256.ComputeHash(data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ namespace MetroUnlocker.LibTSForge.Crypto
|
|||||||
{
|
{
|
||||||
public static class Keys
|
public static class Keys
|
||||||
{
|
{
|
||||||
public static readonly byte[] PRODUCTION = {
|
public static readonly byte[] Production = {
|
||||||
0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
|
0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
|
||||||
0x01, 0x00, 0x01, 0x00, 0x29, 0x87, 0xBA, 0x3F, 0x52, 0x90, 0x57, 0xD8, 0x12, 0x26, 0x6B, 0x38,
|
0x01, 0x00, 0x01, 0x00, 0x29, 0x87, 0xBA, 0x3F, 0x52, 0x90, 0x57, 0xD8, 0x12, 0x26, 0x6B, 0x38,
|
||||||
0xB2, 0x3B, 0xF9, 0x67, 0x08, 0x4F, 0xDD, 0x8B, 0xF5, 0xE3, 0x11, 0xB8, 0x61, 0x3A, 0x33, 0x42,
|
0xB2, 0x3B, 0xF9, 0x67, 0x08, 0x4F, 0xDD, 0x8B, 0xF5, 0xE3, 0x11, 0xB8, 0x61, 0x3A, 0x33, 0x42,
|
||||||
@@ -43,7 +43,7 @@ namespace MetroUnlocker.LibTSForge.Crypto
|
|||||||
0x81, 0x44, 0x38, 0xBF
|
0x81, 0x44, 0x38, 0xBF
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly byte[] TEST = {
|
public static readonly byte[] Test = {
|
||||||
0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
|
0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
|
||||||
0x01, 0x00, 0x01, 0x00, 0x0F, 0xBE, 0x77, 0xB8, 0xDD, 0x54, 0x36, 0xDD, 0x67, 0xD4, 0x17, 0x66,
|
0x01, 0x00, 0x01, 0x00, 0x0F, 0xBE, 0x77, 0xB8, 0xDD, 0x54, 0x36, 0xDD, 0x67, 0xD4, 0x17, 0x66,
|
||||||
0xC4, 0x13, 0xD1, 0x3F, 0x1E, 0x16, 0x0C, 0x16, 0x35, 0xAB, 0x6D, 0x3D, 0x34, 0x51, 0xED, 0x3F,
|
0xC4, 0x13, 0xD1, 0x3F, 0x1E, 0x16, 0x0C, 0x16, 0x35, 0xAB, 0x6D, 0x3D, 0x34, 0x51, 0xED, 0x3F,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace MetroUnlocker.LibTSForge.Crypto
|
|||||||
{
|
{
|
||||||
public static byte[] DecryptPhysicalStore(byte[] data, bool production)
|
public static byte[] DecryptPhysicalStore(byte[] data, bool production)
|
||||||
{
|
{
|
||||||
byte[] rsaKey = production ? Keys.PRODUCTION : Keys.TEST;
|
byte[] rsaKey = production ? Keys.Production : Keys.Test;
|
||||||
BinaryReader br = new BinaryReader(new MemoryStream(data));
|
BinaryReader br = new BinaryReader(new MemoryStream(data));
|
||||||
br.BaseStream.Seek(0x10, SeekOrigin.Begin);
|
br.BaseStream.Seek(0x10, SeekOrigin.Begin);
|
||||||
byte[] aesKeySig = br.ReadBytes(0x80);
|
byte[] aesKeySig = br.ReadBytes(0x80);
|
||||||
@@ -33,33 +33,33 @@ namespace MetroUnlocker.LibTSForge.Crypto
|
|||||||
return psData;
|
return psData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] EncryptPhysicalStore(byte[] data, bool production, PSVersion version)
|
public static byte[] EncryptPhysicalStore(byte[] data, bool production, PhysicalStoreVersion version)
|
||||||
{
|
{
|
||||||
Dictionary<PSVersion, int> versionTable = new Dictionary<PSVersion, int>
|
Dictionary<PhysicalStoreVersion, int> versionTable = new Dictionary<PhysicalStoreVersion, int>
|
||||||
{
|
{
|
||||||
{PSVersion.Win8, 1},
|
{PhysicalStoreVersion.Win8, 1},
|
||||||
{PSVersion.WinBlue, 2},
|
{PhysicalStoreVersion.WinBlue, 2},
|
||||||
{PSVersion.WinModern, 3}
|
{PhysicalStoreVersion.WinModern, 3}
|
||||||
};
|
};
|
||||||
|
|
||||||
byte[] rsaKey = production ? Keys.PRODUCTION : Keys.TEST;
|
byte[] rsaKey = production ? Keys.Production : Keys.Test;
|
||||||
|
|
||||||
byte[] aesKey = Encoding.UTF8.GetBytes("Boop Foxyz nose!");
|
byte[] aesKey = Encoding.UTF8.GetBytes("Boop Foxyz nose!");
|
||||||
byte[] hmacKey = CryptoUtils.GenerateRandomKey(0x10);
|
byte[] hmacKey = CryptoUtils.GenerateRandomKey(0x10);
|
||||||
|
|
||||||
byte[] encAesKey = CryptoUtils.RSAEncrypt(rsaKey, aesKey);
|
byte[] encryptedAesKey = CryptoUtils.RSAEncrypt(rsaKey, aesKey);
|
||||||
byte[] aesKeySig = CryptoUtils.RSASign(rsaKey, encAesKey);
|
byte[] aesKeySignature = CryptoUtils.RSASign(rsaKey, encryptedAesKey);
|
||||||
byte[] hmacSig = CryptoUtils.HMACSign(hmacKey, data);
|
byte[] hmacSignature = CryptoUtils.HMACSign(hmacKey, data);
|
||||||
|
|
||||||
byte[] decData = new byte[] { };
|
byte[] decData = new byte[] { };
|
||||||
decData = decData.Concat(hmacKey).Concat(hmacSig).Concat(BitConverter.GetBytes(0)).Concat(data).ToArray();
|
decData = decData.Concat(hmacKey).Concat(hmacSignature).Concat(BitConverter.GetBytes(0)).Concat(data).ToArray();
|
||||||
byte[] encData = CryptoUtils.AESEncrypt(decData, aesKey);
|
byte[] encData = CryptoUtils.AESEncrypt(decData, aesKey);
|
||||||
|
|
||||||
BinaryWriter bw = new BinaryWriter(new MemoryStream());
|
BinaryWriter bw = new BinaryWriter(new MemoryStream());
|
||||||
bw.Write(versionTable[version]);
|
bw.Write(versionTable[version]);
|
||||||
bw.Write(Encoding.UTF8.GetBytes("UNTRUSTSTORE"));
|
bw.Write(Encoding.UTF8.GetBytes("UNTRUSTSTORE"));
|
||||||
bw.Write(aesKeySig);
|
bw.Write(aesKeySignature);
|
||||||
bw.Write(encAesKey);
|
bw.Write(encryptedAesKey);
|
||||||
bw.Write(encData);
|
bw.Write(encData);
|
||||||
|
|
||||||
return bw.GetBytes();
|
return bw.GetBytes();
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MetroUnlocker.LibTSForge.Modifiers
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using MetroUnlocker.LibTSForge.PhysicalStore;
|
|
||||||
using MetroUnlocker.LibTSForge.SPP;
|
|
||||||
using MetroUnlocker.LibTSForge.TokenStore;
|
|
||||||
|
|
||||||
public static class GenPKeyInstall
|
|
||||||
{
|
|
||||||
public static void InstallGenPKey(PSVersion version, bool production, Guid actId)
|
|
||||||
{
|
|
||||||
PKeyConfig pkc = new PKeyConfig();
|
|
||||||
|
|
||||||
pkc.LoadConfig(actId);
|
|
||||||
|
|
||||||
ProductConfig config;
|
|
||||||
pkc.Products.TryGetValue(actId, out config);
|
|
||||||
|
|
||||||
if (config == null) throw new ArgumentException("Activation ID " + actId + " not found in PKeyConfig.");
|
|
||||||
|
|
||||||
ProductKey pkey = config.GetRandomKey();
|
|
||||||
|
|
||||||
Guid instPkeyId = SLApi.GetInstalledPkeyId(actId);
|
|
||||||
if (instPkeyId != Guid.Empty) SLApi.UninstallProductKey(instPkeyId);
|
|
||||||
|
|
||||||
if (pkey.Algorithm != PKeyAlgorithm.PKEY2009)
|
|
||||||
throw new Exception("The key algorithm isn't 2009");
|
|
||||||
|
|
||||||
uint status = SLApi.InstallProductKey(pkey);
|
|
||||||
|
|
||||||
if (status != 0)
|
|
||||||
throw new ApplicationException("Failed to install generated product key.");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
36
MetroUnlocker/LibTSForge/Modifiers/ProductKeyInstaller.cs
Normal file
36
MetroUnlocker/LibTSForge/Modifiers/ProductKeyInstaller.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
using MetroUnlocker.LibTSForge.SPP;
|
||||||
|
|
||||||
|
namespace MetroUnlocker.LibTSForge.Modifiers
|
||||||
|
{
|
||||||
|
public static class ProductKeyInstaller
|
||||||
|
{
|
||||||
|
public static void InstallGeneratedProductKey(PhysicalStoreVersion version, bool production, Guid actId)
|
||||||
|
{
|
||||||
|
ProductKeyConfig keyConfig = new ProductKeyConfig();
|
||||||
|
|
||||||
|
keyConfig.LoadConfig(actId);
|
||||||
|
|
||||||
|
ProductConfig config;
|
||||||
|
keyConfig.Products.TryGetValue(actId, out config);
|
||||||
|
|
||||||
|
if (config == null) throw new ArgumentException("Activation ID " + actId + " not found in ProductKeyConfig.");
|
||||||
|
|
||||||
|
ProductKey pkey = config.GetRandomKey();
|
||||||
|
|
||||||
|
Guid instPkeyId = SLApi.GetInstalledProductKeyId(actId);
|
||||||
|
if (instPkeyId != Guid.Empty) SLApi.UninstallProductKey(instPkeyId);
|
||||||
|
|
||||||
|
if (pkey.Algorithm != ProductKeyAlgorithm.ProductKey2009)
|
||||||
|
throw new Exception("The key algorithm isn't 2009");
|
||||||
|
|
||||||
|
uint status = SLApi.InstallProductKey(pkey);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
throw new ApplicationException("Failed to install generated product key.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
MetroUnlocker/LibTSForge/PhysicalStore/BasicBlock.cs
Normal file
29
MetroUnlocker/LibTSForge/PhysicalStore/BasicBlock.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MetroUnlocker.LibTSForge.PhysicalStore
|
||||||
|
{
|
||||||
|
public class BasicBlock
|
||||||
|
{
|
||||||
|
public byte[] Key;
|
||||||
|
public string KeyAsString
|
||||||
|
{
|
||||||
|
get { return Utils.DecodeString(Key); }
|
||||||
|
set { Key = Utils.EncodeString(value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Value;
|
||||||
|
public string ValueAsString
|
||||||
|
{
|
||||||
|
get { return Utils.DecodeString(Value); }
|
||||||
|
set { Value = Utils.EncodeString(value); }
|
||||||
|
}
|
||||||
|
public uint ValueAsInteger
|
||||||
|
{
|
||||||
|
get { return BitConverter.ToUInt32(Value, 0); }
|
||||||
|
set { Value = BitConverter.GetBytes(value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,55 +1,42 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace MetroUnlocker.LibTSForge.PhysicalStore
|
namespace MetroUnlocker.LibTSForge.PhysicalStore
|
||||||
{
|
{
|
||||||
public enum CRCBlockType : uint
|
public enum CRCBlockType : uint
|
||||||
{
|
{
|
||||||
UINT = 1 << 0,
|
UInt = 1 << 0,
|
||||||
STRING = 1 << 1,
|
String = 1 << 1,
|
||||||
BINARY = 1 << 2
|
Binary = 1 << 2
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CRCBlock
|
public class CRCBlock : BasicBlock
|
||||||
{
|
{
|
||||||
public CRCBlockType DataType;
|
public CRCBlockType DataType;
|
||||||
public byte[] Key;
|
|
||||||
public string KeyAsStr
|
public CRCBlock() { }
|
||||||
|
|
||||||
|
public CRCBlock(BinaryReader reader)
|
||||||
{
|
{
|
||||||
get
|
uint crc = reader.ReadUInt32();
|
||||||
{
|
uint type = reader.ReadUInt32();
|
||||||
return Utils.DecodeString(Key);
|
uint lenName = reader.ReadUInt32();
|
||||||
}
|
uint lenVal = reader.ReadUInt32();
|
||||||
set
|
|
||||||
{
|
byte[] key = reader.ReadBytes((int)lenName);
|
||||||
Key = Utils.EncodeString(value);
|
|
||||||
}
|
reader.Align(8);
|
||||||
}
|
|
||||||
public byte[] Value;
|
byte[] value = reader.ReadBytes((int)lenVal);
|
||||||
public string ValueAsStr
|
reader.Align(8);
|
||||||
{
|
|
||||||
get
|
DataType = (CRCBlockType)type;
|
||||||
{
|
Key = key;
|
||||||
return Utils.DecodeString(Value);
|
Value = value;
|
||||||
}
|
|
||||||
set
|
if (CRC() != crc)
|
||||||
{
|
throw new InvalidDataException("Invalid CRC in variable bag.");
|
||||||
Value = Utils.EncodeString(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public uint ValueAsInt
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return BitConverter.ToUInt32(Value, 0);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Value = BitConverter.GetBytes(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Encode(BinaryWriter writer)
|
public void Encode(BinaryWriter writer)
|
||||||
@@ -67,45 +54,16 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
writer.Align(8);
|
writer.Align(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CRCBlock Decode(BinaryReader reader)
|
|
||||||
{
|
|
||||||
uint crc = reader.ReadUInt32();
|
|
||||||
uint type = reader.ReadUInt32();
|
|
||||||
uint lenName = reader.ReadUInt32();
|
|
||||||
uint lenVal = reader.ReadUInt32();
|
|
||||||
|
|
||||||
byte[] key = reader.ReadBytes((int)lenName);
|
|
||||||
|
|
||||||
reader.Align(8);
|
|
||||||
|
|
||||||
byte[] value = reader.ReadBytes((int)lenVal);
|
|
||||||
reader.Align(8);
|
|
||||||
|
|
||||||
CRCBlock block = new CRCBlock
|
|
||||||
{
|
|
||||||
DataType = (CRCBlockType)type,
|
|
||||||
Key = key,
|
|
||||||
Value = value,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (block.CRC() != crc)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid CRC in variable bag.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint CRC()
|
public uint CRC()
|
||||||
{
|
{
|
||||||
BinaryWriter wtemp = new BinaryWriter(new MemoryStream());
|
BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
||||||
wtemp.Write(0);
|
writer.Write(0);
|
||||||
wtemp.Write((uint)DataType);
|
writer.Write((uint)DataType);
|
||||||
wtemp.Write(Key.Length);
|
writer.Write(Key.Length);
|
||||||
wtemp.Write(Value.Length);
|
writer.Write(Value.Length);
|
||||||
wtemp.Write(Key);
|
writer.Write(Key);
|
||||||
wtemp.Write(Value);
|
writer.Write(Value);
|
||||||
return Utils.CRC32(((MemoryStream)wtemp.BaseStream).ToArray());
|
return Utils.CRC32(((MemoryStream)writer.BaseStream).ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,68 +6,41 @@ using System.IO;
|
|||||||
|
|
||||||
namespace MetroUnlocker.LibTSForge.PhysicalStore
|
namespace MetroUnlocker.LibTSForge.PhysicalStore
|
||||||
{
|
{
|
||||||
public class ModernBlock
|
public class ModernBlock : BasicBlock
|
||||||
{
|
{
|
||||||
public BlockType Type;
|
public BlockType Type;
|
||||||
public uint Flags;
|
public uint Flags;
|
||||||
public uint Unknown;
|
public uint Unknown;
|
||||||
public byte[] Key;
|
|
||||||
public string KeyAsStr
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Utils.DecodeString(Key);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Key = Utils.EncodeString(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public byte[] Value;
|
|
||||||
public string ValueAsStr
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Utils.DecodeString(Value);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Value = Utils.EncodeString(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public uint ValueAsInt
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return BitConverter.ToUInt32(Value, 0);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Value = BitConverter.GetBytes(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public byte[] Data;
|
public byte[] Data;
|
||||||
public string DataAsStr
|
public string DataAsString
|
||||||
{
|
{
|
||||||
get
|
get { return Utils.DecodeString(Data); }
|
||||||
{
|
set { Data = Utils.EncodeString(value); }
|
||||||
return Utils.DecodeString(Data);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Data = Utils.EncodeString(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint DataAsInt
|
public uint DataAsInt
|
||||||
{
|
{
|
||||||
get
|
get { return BitConverter.ToUInt32(Data, 0); }
|
||||||
{
|
set { Data = BitConverter.GetBytes(value); }
|
||||||
return BitConverter.ToUInt32(Data, 0);
|
}
|
||||||
}
|
|
||||||
set
|
public ModernBlock() { }
|
||||||
{
|
public ModernBlock(string key, string value, byte[] data, BlockType type = BlockType.NAMED, uint flags = 0)
|
||||||
Data = BitConverter.GetBytes(value);
|
{
|
||||||
}
|
Type = type;
|
||||||
|
Flags = flags;
|
||||||
|
KeyAsString = key;
|
||||||
|
ValueAsString = value;
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
public ModernBlock(ModernBlock block)
|
||||||
|
{
|
||||||
|
Type = block.Type;
|
||||||
|
Flags = block.Flags;
|
||||||
|
Unknown = block.Unknown;
|
||||||
|
Value = block.Value;
|
||||||
|
Data = block.Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Encode(BinaryWriter writer)
|
public void Encode(BinaryWriter writer)
|
||||||
@@ -81,7 +54,7 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
writer.Write(Data);
|
writer.Write(Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ModernBlock Decode(BinaryReader reader)
|
public ModernBlock(BinaryReader reader)
|
||||||
{
|
{
|
||||||
uint type = reader.ReadUInt32();
|
uint type = reader.ReadUInt32();
|
||||||
uint flags = reader.ReadUInt32();
|
uint flags = reader.ReadUInt32();
|
||||||
@@ -93,14 +66,11 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
byte[] value = reader.ReadBytes((int)valueLen);
|
byte[] value = reader.ReadBytes((int)valueLen);
|
||||||
byte[] data = reader.ReadBytes((int)dataLen);
|
byte[] data = reader.ReadBytes((int)dataLen);
|
||||||
|
|
||||||
return new ModernBlock
|
Type = (BlockType)type;
|
||||||
{
|
Flags = flags;
|
||||||
Type = (BlockType)type,
|
Unknown = unk3;
|
||||||
Flags = flags,
|
Value = value;
|
||||||
Unknown = unk3,
|
Data = data;
|
||||||
Value = value,
|
|
||||||
Data = data,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
private byte[] PreHeaderBytes = new byte[] { };
|
private byte[] PreHeaderBytes = new byte[] { };
|
||||||
private readonly Dictionary<string, List<ModernBlock>> Data = new Dictionary<string, List<ModernBlock>>();
|
private readonly Dictionary<string, List<ModernBlock>> Data = new Dictionary<string, List<ModernBlock>>();
|
||||||
private readonly FileStream TSFile;
|
private readonly FileStream TSFile;
|
||||||
private readonly PSVersion Version;
|
private readonly PhysicalStoreVersion Version;
|
||||||
private readonly bool Production;
|
private readonly bool Production;
|
||||||
|
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
@@ -66,7 +66,7 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
|
|
||||||
for (int j = 0; j < numValues; j++)
|
for (int j = 0; j < numValues; j++)
|
||||||
{
|
{
|
||||||
Data[keyName].Add(ModernBlock.Decode(reader));
|
Data[keyName].Add(new ModernBlock(reader));
|
||||||
reader.Align(4);
|
reader.Align(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,12 +75,10 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
|
|
||||||
public void AddBlock(ModernBlock block)
|
public void AddBlock(ModernBlock block)
|
||||||
{
|
{
|
||||||
if (!Data.ContainsKey(block.KeyAsStr))
|
if (!Data.ContainsKey(block.KeyAsString))
|
||||||
{
|
Data[block.KeyAsString] = new List<ModernBlock>();
|
||||||
Data[block.KeyAsStr] = new List<ModernBlock>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Data[block.KeyAsStr].Add(new ModernBlock
|
Data[block.KeyAsString].Add(new ModernBlock
|
||||||
{
|
{
|
||||||
Type = block.Type,
|
Type = block.Type,
|
||||||
Flags = block.Flags,
|
Flags = block.Flags,
|
||||||
@@ -92,92 +90,33 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
|
|
||||||
public void AddBlocks(IEnumerable<ModernBlock> blocks)
|
public void AddBlocks(IEnumerable<ModernBlock> blocks)
|
||||||
{
|
{
|
||||||
foreach (ModernBlock block in blocks)
|
foreach (ModernBlock block in blocks) AddBlock(block);
|
||||||
{
|
|
||||||
AddBlock(block);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModernBlock GetBlock(string key, string value)
|
public ModernBlock GetBlock(string key, string value)
|
||||||
{
|
{
|
||||||
List<ModernBlock> blocks = Data[key];
|
if (!Data.ContainsKey(key)) return null;
|
||||||
|
return Data[key].Find(block => block.ValueAsString == value);
|
||||||
foreach (ModernBlock block in blocks)
|
|
||||||
{
|
|
||||||
if (block.ValueAsStr == value)
|
|
||||||
{
|
|
||||||
return new ModernBlock
|
|
||||||
{
|
|
||||||
Type = block.Type,
|
|
||||||
Flags = block.Flags,
|
|
||||||
Key = Utils.EncodeString(key),
|
|
||||||
Value = block.Value,
|
|
||||||
Data = block.Data
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModernBlock GetBlock(string key, uint value)
|
public ModernBlock GetBlock(string key, uint value)
|
||||||
{
|
{
|
||||||
List<ModernBlock> blocks = Data[key];
|
if (!Data.ContainsKey(key)) return null;
|
||||||
|
return Data[key].Find(block => block.ValueAsInteger == value);
|
||||||
foreach (ModernBlock block in blocks)
|
|
||||||
{
|
|
||||||
if (block.ValueAsInt == value)
|
|
||||||
{
|
|
||||||
return new ModernBlock
|
|
||||||
{
|
|
||||||
Type = block.Type,
|
|
||||||
Flags = block.Flags,
|
|
||||||
Key = Utils.EncodeString(key),
|
|
||||||
Value = block.Value,
|
|
||||||
Data = block.Data
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlock(string key, string value, byte[] data)
|
public void SetBlock(string key, string value, byte[] data)
|
||||||
{
|
{
|
||||||
List<ModernBlock> blocks = Data[key];
|
if (!Data.ContainsKey(key)) return;
|
||||||
|
int index = Data[key].FindIndex(block => block.ValueAsString == value);
|
||||||
for (int i = 0; i < blocks.Count; i++)
|
Data[key][index].Data = data;
|
||||||
{
|
|
||||||
ModernBlock block = blocks[i];
|
|
||||||
|
|
||||||
if (block.ValueAsStr == value)
|
|
||||||
{
|
|
||||||
block.Data = data;
|
|
||||||
blocks[i] = block;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Data[key] = blocks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlock(string key, uint value, byte[] data)
|
public void SetBlock(string key, uint value, byte[] data)
|
||||||
{
|
{
|
||||||
List<ModernBlock> blocks = Data[key];
|
if (!Data.ContainsKey(key)) return;
|
||||||
|
int index = Data[key].FindIndex(block => block.ValueAsInteger == value);
|
||||||
for (int i = 0; i < blocks.Count; i++)
|
Data[key][index].Data = data;
|
||||||
{
|
|
||||||
ModernBlock block = blocks[i];
|
|
||||||
|
|
||||||
if (block.ValueAsInt == value)
|
|
||||||
{
|
|
||||||
block.Data = data;
|
|
||||||
blocks[i] = block;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Data[key] = blocks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlock(string key, string value, string data)
|
public void SetBlock(string key, string value, string data)
|
||||||
@@ -202,40 +141,12 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
|
|
||||||
public void DeleteBlock(string key, string value)
|
public void DeleteBlock(string key, string value)
|
||||||
{
|
{
|
||||||
if (Data.ContainsKey(key))
|
Data[key].Remove(GetBlock(key, value));
|
||||||
{
|
|
||||||
List<ModernBlock> blocks = Data[key];
|
|
||||||
|
|
||||||
foreach (ModernBlock block in blocks)
|
|
||||||
{
|
|
||||||
if (block.ValueAsStr == value)
|
|
||||||
{
|
|
||||||
blocks.Remove(block);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Data[key] = blocks;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteBlock(string key, uint value)
|
public void DeleteBlock(string key, uint value)
|
||||||
{
|
{
|
||||||
if (Data.ContainsKey(key))
|
Data[key].Remove(GetBlock(key, value));
|
||||||
{
|
|
||||||
List<ModernBlock> blocks = Data[key];
|
|
||||||
|
|
||||||
foreach (ModernBlock block in blocks)
|
|
||||||
{
|
|
||||||
if (block.ValueAsInt == value)
|
|
||||||
{
|
|
||||||
blocks.Remove(block);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Data[key] = blocks;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetPath()
|
public static string GetPath()
|
||||||
@@ -245,7 +156,7 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
return Path.Combine(Environment.ExpandEnvironmentVariables(sppRoot), "data.dat");
|
return Path.Combine(Environment.ExpandEnvironmentVariables(sppRoot), "data.dat");
|
||||||
}
|
}
|
||||||
|
|
||||||
public PhysicalStore(PSVersion version, bool production)
|
public PhysicalStore(PhysicalStoreVersion version, bool production)
|
||||||
{
|
{
|
||||||
Version = version;
|
Version = version;
|
||||||
Production = production;
|
Production = production;
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
public List<CRCBlock> Blocks = new List<CRCBlock>();
|
public List<CRCBlock> Blocks = new List<CRCBlock>();
|
||||||
|
|
||||||
public VariableBag() { }
|
public VariableBag() { }
|
||||||
public VariableBag(byte[] data)
|
public VariableBag(byte[] data) { Deserialize(data); }
|
||||||
{
|
|
||||||
Deserialize(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Deserialize(byte[] data)
|
public void Deserialize(byte[] data)
|
||||||
{
|
{
|
||||||
@@ -22,9 +19,7 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
BinaryReader reader = new BinaryReader(new MemoryStream(data));
|
BinaryReader reader = new BinaryReader(new MemoryStream(data));
|
||||||
|
|
||||||
while (reader.BaseStream.Position < len - 0x10)
|
while (reader.BaseStream.Position < len - 0x10)
|
||||||
{
|
Blocks.Add(new CRCBlock(reader));
|
||||||
Blocks.Add(CRCBlock.Decode(reader));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
@@ -39,40 +34,19 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
|
|||||||
|
|
||||||
public CRCBlock GetBlock(string key)
|
public CRCBlock GetBlock(string key)
|
||||||
{
|
{
|
||||||
foreach (CRCBlock block in Blocks)
|
return Blocks.Find(block => block.KeyAsString == key);
|
||||||
{
|
|
||||||
if (block.KeyAsStr == key)
|
|
||||||
{
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlock(string key, byte[] value)
|
public void SetBlock(string key, byte[] value)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Blocks.Count; i++)
|
int index = Blocks.FindIndex(block => block.KeyAsString == key);
|
||||||
{
|
if (index != -1) Blocks[index].Value = value;
|
||||||
CRCBlock block = Blocks[i];
|
|
||||||
|
|
||||||
if (block.KeyAsStr == key)
|
|
||||||
{
|
|
||||||
block.Value = value;
|
|
||||||
Blocks[i] = block;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteBlock(string key)
|
public void DeleteBlock(string key)
|
||||||
{
|
{
|
||||||
foreach (CRCBlock block in Blocks)
|
CRCBlock block = GetBlock(key);
|
||||||
if (block.KeyAsStr == key)
|
if (block != null) Blocks.Remove(block);
|
||||||
{
|
|
||||||
Blocks.Remove(block);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
91
MetroUnlocker/LibTSForge/SPP/NativeMethods.cs
Normal file
91
MetroUnlocker/LibTSForge/SPP/NativeMethods.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace MetroUnlocker.LibTSForge.SPP
|
||||||
|
{
|
||||||
|
public enum SLIDType
|
||||||
|
{
|
||||||
|
Application,
|
||||||
|
ProductSku,
|
||||||
|
LicenseFile,
|
||||||
|
License,
|
||||||
|
ProductKey,
|
||||||
|
AllLicenses,
|
||||||
|
AllLicenseFiles,
|
||||||
|
StoreToken,
|
||||||
|
Last
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SLDataType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
String,
|
||||||
|
DWord,
|
||||||
|
Binary,
|
||||||
|
MultiString,
|
||||||
|
Sum
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct SLLicensingStatus
|
||||||
|
{
|
||||||
|
public Guid SkuId;
|
||||||
|
public uint Status;
|
||||||
|
public uint GraceTimeDWord;
|
||||||
|
public uint TotalGraceDaysDWord;
|
||||||
|
public uint ReasonHResult;
|
||||||
|
public ulong ValidityExpiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NativeMethods
|
||||||
|
{
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
internal static extern uint GetSystemDefaultLCID();
|
||||||
|
|
||||||
|
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
||||||
|
internal static extern void SLOpen(out IntPtr hSLC);
|
||||||
|
|
||||||
|
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
||||||
|
internal static extern void SLClose(IntPtr hSLC);
|
||||||
|
|
||||||
|
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLInstallProofOfPurchase(IntPtr hSLC, string pwszPKeyAlgorithm, string pwszPKeyString, uint cbPKeySpecificData, byte[] pbPKeySpecificData, ref Guid PKeyId);
|
||||||
|
|
||||||
|
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLUninstallProofOfPurchase(IntPtr hSLC, ref Guid PKeyId);
|
||||||
|
|
||||||
|
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLGenerateOfflineInstallationId(IntPtr hSLC, ref Guid pProductSkuId, ref string ppwszInstallationId);
|
||||||
|
|
||||||
|
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLDepositOfflineConfirmationId(IntPtr hSLC, ref Guid pProductSkuId, string pwszInstallationId, string pwszConfirmationId);
|
||||||
|
|
||||||
|
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLGetSLIDList(IntPtr hSLC, SLIDType eQueryIdType, ref Guid pQueryId, SLIDType eReturnIdType, out uint pnReturnIds, out IntPtr ppReturnIds);
|
||||||
|
|
||||||
|
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLGetInstalledProductKeyIds(IntPtr hSLC, ref Guid pProductSkuId, out uint pnProductKeyIds, out IntPtr ppProductKeyIds);
|
||||||
|
|
||||||
|
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLConsumeWindowsRight(uint unknown);
|
||||||
|
|
||||||
|
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, out SLDataType peDataType, out uint pcbValue, out IntPtr ppbValue);
|
||||||
|
|
||||||
|
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, IntPtr peDataType, out uint pcbValue, out IntPtr ppbValue);
|
||||||
|
|
||||||
|
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLGetLicense(IntPtr hSLC, ref Guid pLicenseFileId, out uint pcbLicenseFile, out IntPtr ppbLicenseFile);
|
||||||
|
|
||||||
|
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLSetCurrentProductKey(IntPtr hSLC, ref Guid pProductSkuId, ref Guid pProductKeyId);
|
||||||
|
|
||||||
|
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern uint SLFireEvent(IntPtr hSLC, string pwszEventId, ref Guid pApplicationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
public int Serial;
|
public int Serial;
|
||||||
public ulong Security;
|
public ulong Security;
|
||||||
public bool Upgrade;
|
public bool Upgrade;
|
||||||
public PKeyAlgorithm Algorithm;
|
public ProductKeyAlgorithm Algorithm;
|
||||||
public string EulaType;
|
public string EulaType;
|
||||||
public string PartNumber;
|
public string PartNumber;
|
||||||
public string Edition;
|
public string Edition;
|
||||||
@@ -37,7 +37,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
get { return BitConverter.GetBytes(klow).Concat(BitConverter.GetBytes(khigh)).ToArray(); }
|
get { return BitConverter.GetBytes(klow).Concat(BitConverter.GetBytes(khigh)).ToArray(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductKey(int serial, ulong security, bool upgrade, PKeyAlgorithm algorithm, ProductConfig config, KeyRange range)
|
public ProductKey(int serial, ulong security, bool upgrade, ProductKeyAlgorithm algorithm, ProductConfig config, KeyRange range)
|
||||||
{
|
{
|
||||||
Group = config.GroupId;
|
Group = config.GroupId;
|
||||||
Serial = serial;
|
Serial = serial;
|
||||||
@@ -60,7 +60,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
|
|
||||||
public string GetAlgoUri()
|
public string GetAlgoUri()
|
||||||
{
|
{
|
||||||
return "msft:rm/algorithm/pkey/" + (Algorithm == PKeyAlgorithm.PKEY2005 ? "2005" : (Algorithm == PKeyAlgorithm.PKEY2009 ? "2009" : "Unknown"));
|
return "msft:rm/algorithm/pkey/" + (Algorithm == ProductKeyAlgorithm.ProductKey2005 ? "2005" : (Algorithm == ProductKeyAlgorithm.ProductKey2009 ? "2009" : "Unknown"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid GetPkeyId()
|
public Guid GetPkeyId()
|
||||||
@@ -70,21 +70,21 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
{
|
{
|
||||||
new CRCBlock
|
new CRCBlock
|
||||||
{
|
{
|
||||||
DataType = CRCBlockType.STRING,
|
DataType = CRCBlockType.String,
|
||||||
KeyAsStr = "SppPkeyBindingProductKey",
|
KeyAsString = "SppPkeyBindingProductKey",
|
||||||
ValueAsStr = ToString()
|
ValueAsString = ToString()
|
||||||
},
|
},
|
||||||
new CRCBlock
|
new CRCBlock
|
||||||
{
|
{
|
||||||
DataType = CRCBlockType.BINARY,
|
DataType = CRCBlockType.Binary,
|
||||||
KeyAsStr = "SppPkeyBindingMiscData",
|
KeyAsString = "SppPkeyBindingMiscData",
|
||||||
Value = new byte[] { }
|
Value = new byte[] { }
|
||||||
},
|
},
|
||||||
new CRCBlock
|
new CRCBlock
|
||||||
{
|
{
|
||||||
DataType = CRCBlockType.STRING,
|
DataType = CRCBlockType.String,
|
||||||
KeyAsStr = "SppPkeyBindingAlgorithm",
|
KeyAsString = "SppPkeyBindingAlgorithm",
|
||||||
ValueAsStr = GetAlgoUri()
|
ValueAsString = GetAlgoUri()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
|
|
||||||
pid2 = "";
|
pid2 = "";
|
||||||
|
|
||||||
if (Algorithm == PKeyAlgorithm.PKEY2005)
|
if (Algorithm == ProductKeyAlgorithm.ProductKey2005)
|
||||||
{
|
{
|
||||||
string mpc = GetMPC();
|
string mpc = GetMPC();
|
||||||
string serialHigh;
|
string serialHigh;
|
||||||
@@ -211,7 +211,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
int serialHigh = Serial / 1000000;
|
int serialHigh = Serial / 1000000;
|
||||||
int serialLow = Serial % 1000000;
|
int serialLow = Serial % 1000000;
|
||||||
int licenseType;
|
int licenseType;
|
||||||
uint lcid = Utils.GetSystemDefaultLCID();
|
uint lcid = NativeMethods.GetSystemDefaultLCID();
|
||||||
int build = Environment.OSVersion.Version.Build;
|
int build = Environment.OSVersion.Version.Build;
|
||||||
int dayOfYear = DateTime.Now.DayOfYear;
|
int dayOfYear = DateTime.Now.DayOfYear;
|
||||||
int year = DateTime.Now.Year;
|
int year = DateTime.Now.Year;
|
||||||
@@ -245,7 +245,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetPhoneData(PSVersion version)
|
public byte[] GetPhoneData(PhysicalStoreVersion version)
|
||||||
{
|
{
|
||||||
int serialHigh = Serial / 1000000;
|
int serialHigh = Serial / 1000000;
|
||||||
int serialLow = Serial % 1000000;
|
int serialLow = Serial % 1000000;
|
||||||
@@ -266,7 +266,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
string keyStr = "";
|
string keyStr = "";
|
||||||
Random rnd = new Random(Group * 1000000000 + Serial);
|
Random rnd = new Random(Group * 1000000000 + Serial);
|
||||||
|
|
||||||
if (Algorithm == PKeyAlgorithm.PKEY2005)
|
if (Algorithm == ProductKeyAlgorithm.ProductKey2005)
|
||||||
{
|
{
|
||||||
keyStr = "H4X3DH4X3DH4X3DH4X3D";
|
keyStr = "H4X3DH4X3DH4X3DH4X3D";
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
keyStr += ALPHABET[rnd.Next(24)];
|
keyStr += ALPHABET[rnd.Next(24)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Algorithm == PKeyAlgorithm.PKEY2009)
|
else if (Algorithm == ProductKeyAlgorithm.ProductKey2009)
|
||||||
{
|
{
|
||||||
int last = 0;
|
int last = 0;
|
||||||
byte[] bKey = KeyBytes;
|
byte[] bKey = KeyBytes;
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ using System.Xml;
|
|||||||
namespace MetroUnlocker.LibTSForge.SPP
|
namespace MetroUnlocker.LibTSForge.SPP
|
||||||
{
|
{
|
||||||
|
|
||||||
public enum PKeyAlgorithm
|
public enum ProductKeyAlgorithm
|
||||||
{
|
{
|
||||||
PKEY2005,
|
ProductKey2005,
|
||||||
PKEY2009
|
ProductKey2009
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KeyRange
|
public class KeyRange
|
||||||
@@ -23,10 +23,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
public string PartNumber;
|
public string PartNumber;
|
||||||
public bool Valid;
|
public bool Valid;
|
||||||
|
|
||||||
public bool Contains(int n)
|
public bool Contains(int n) { return Start <= n && End <= n; }
|
||||||
{
|
|
||||||
return Start <= n && End <= n;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ProductConfig
|
public class ProductConfig
|
||||||
@@ -36,70 +33,67 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
public string Description;
|
public string Description;
|
||||||
public string Channel;
|
public string Channel;
|
||||||
public bool Randomized;
|
public bool Randomized;
|
||||||
public PKeyAlgorithm Algorithm;
|
public ProductKeyAlgorithm Algorithm;
|
||||||
public List<KeyRange> Ranges;
|
public List<KeyRange> Ranges;
|
||||||
public Guid ActivationId;
|
public Guid ActivationId;
|
||||||
|
|
||||||
private List<KeyRange> GetPkeyRanges()
|
private List<KeyRange> GetProductKeyRanges()
|
||||||
{
|
{
|
||||||
if (Ranges.Count == 0)
|
if (Ranges.Count == 0)
|
||||||
{
|
|
||||||
throw new ArgumentException("No key ranges.");
|
throw new ArgumentException("No key ranges.");
|
||||||
}
|
|
||||||
|
|
||||||
if (Algorithm == PKeyAlgorithm.PKEY2005)
|
if (Algorithm == ProductKeyAlgorithm.ProductKey2005)
|
||||||
{
|
|
||||||
return Ranges;
|
return Ranges;
|
||||||
}
|
|
||||||
|
|
||||||
List<KeyRange> FilteredRanges = Ranges.Where(r => !r.EulaType.Contains("WAU")).ToList();
|
List<KeyRange> FilteredRanges = Ranges.FindAll(r => !r.EulaType.Contains("WAU"));
|
||||||
|
|
||||||
if (FilteredRanges.Count == 0)
|
if (FilteredRanges.Count == 0)
|
||||||
{
|
|
||||||
throw new NotSupportedException("Specified Activation ID is usable only for Windows Anytime Upgrade. Please use a non-WAU Activation ID instead.");
|
throw new NotSupportedException("Specified Activation ID is usable only for Windows Anytime Upgrade. Please use a non-WAU Activation ID instead.");
|
||||||
}
|
|
||||||
|
|
||||||
return FilteredRanges;
|
return FilteredRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductKey GetRandomKey()
|
public ProductKey GetRandomKey()
|
||||||
{
|
{
|
||||||
List<KeyRange> KeyRanges = GetPkeyRanges();
|
List<KeyRange> KeyRanges = GetProductKeyRanges();
|
||||||
Random rnd = new Random();
|
Random random = new Random();
|
||||||
|
|
||||||
KeyRange range = KeyRanges[rnd.Next(KeyRanges.Count)];
|
KeyRange range = KeyRanges[random.Next(KeyRanges.Count)];
|
||||||
int serial = rnd.Next(range.Start, range.End);
|
int serial = random.Next(range.Start, range.End);
|
||||||
|
|
||||||
return new ProductKey(serial, 0, false, Algorithm, this, range);
|
return new ProductKey(serial, 0, false, Algorithm, this, range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PKeyConfig
|
public class ProductKeyConfig
|
||||||
{
|
{
|
||||||
public Dictionary<Guid, ProductConfig> Products = new Dictionary<Guid, ProductConfig>();
|
public Dictionary<Guid, ProductConfig> Products = new Dictionary<Guid, ProductConfig>();
|
||||||
private List<Guid> loadedPkeyConfigs = new List<Guid>();
|
private List<Guid> _loadedProductKeyConfigs = new List<Guid>();
|
||||||
|
|
||||||
public void LoadConfig(Guid actId)
|
public void LoadConfig(Guid actId)
|
||||||
{
|
{
|
||||||
string pkcData;
|
string pkcData;
|
||||||
Guid pkcFileId = SLApi.GetPkeyConfigFileId(actId);
|
Guid configFileId = SLApi.GetProductKeyConfigFileId(actId);
|
||||||
|
|
||||||
if (loadedPkeyConfigs.Contains(pkcFileId)) return;
|
if (configFileId == Guid.Empty) throw new Exception("This edition of Windows does not support sideloading keys.");
|
||||||
|
|
||||||
string licConts = SLApi.GetLicenseContents(pkcFileId);
|
if (_loadedProductKeyConfigs.Contains(configFileId)) return;
|
||||||
|
|
||||||
using (TextReader tr = new StringReader(licConts))
|
string licenseContents = SLApi.GetLicenseContents(configFileId);
|
||||||
|
|
||||||
|
|
||||||
|
using (TextReader tr = new StringReader(licenseContents))
|
||||||
{
|
{
|
||||||
XmlDocument lic = new XmlDocument();
|
XmlDocument lic = new XmlDocument();
|
||||||
lic.Load(tr);
|
lic.Load(tr);
|
||||||
|
|
||||||
XmlNamespaceManager nsmgr = new XmlNamespaceManager(lic.NameTable);
|
XmlNamespaceManager nsmgr = new XmlNamespaceManager(lic.NameTable);
|
||||||
nsmgr.AddNamespace("rg", "urn:mpeg:mpeg21:2003:01-REL-R-NS");
|
nsmgr.AddNamespace("rg", "urn:mpeg:mpeg21:2003:01-REL-R-NS");
|
||||||
nsmgr.AddNamespace("r", "urn:mpeg:mpeg21:2003:01-REL-R-NS");
|
nsmgr.AddNamespace("random", "urn:mpeg:mpeg21:2003:01-REL-R-NS");
|
||||||
nsmgr.AddNamespace("tm", "http://www.microsoft.com/DRM/XrML2/TM/v2");
|
nsmgr.AddNamespace("tm", "http://www.microsoft.com/DRM/XrML2/TM/v2");
|
||||||
|
|
||||||
XmlNode root = lic.DocumentElement;
|
XmlNode root = lic.DocumentElement;
|
||||||
XmlNode pkcDataNode = root.SelectSingleNode("/rg:licenseGroup/r:license/r:otherInfo/tm:infoTables/tm:infoList/tm:infoBin[@name=\"pkeyConfigData\"]", nsmgr);
|
XmlNode pkcDataNode = root.SelectSingleNode("/rg:licenseGroup/random:license/random:otherInfo/tm:infoTables/tm:infoList/tm:infoBin[@name=\"pkeyConfigData\"]", nsmgr);
|
||||||
pkcData = Encoding.UTF8.GetString(Convert.FromBase64String(pkcDataNode.InnerText));
|
pkcData = Encoding.UTF8.GetString(Convert.FromBase64String(pkcDataNode.InnerText));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,13 +108,13 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
XmlNodeList rangeNodes = lic.SelectNodes("//p:ProductKeyConfiguration/p:KeyRanges/p:KeyRange", nsmgr);
|
XmlNodeList rangeNodes = lic.SelectNodes("//p:ProductKeyConfiguration/p:KeyRanges/p:KeyRange", nsmgr);
|
||||||
XmlNodeList pubKeyNodes = lic.SelectNodes("//p:ProductKeyConfiguration/p:PublicKeys/p:PublicKey", nsmgr);
|
XmlNodeList pubKeyNodes = lic.SelectNodes("//p:ProductKeyConfiguration/p:PublicKeys/p:PublicKey", nsmgr);
|
||||||
|
|
||||||
Dictionary<int, PKeyAlgorithm> algorithms = new Dictionary<int, PKeyAlgorithm>();
|
Dictionary<int, ProductKeyAlgorithm> algorithms = new Dictionary<int, ProductKeyAlgorithm>();
|
||||||
Dictionary<string, List<KeyRange>> ranges = new Dictionary<string, List<KeyRange>>();
|
Dictionary<string, List<KeyRange>> ranges = new Dictionary<string, List<KeyRange>>();
|
||||||
|
|
||||||
Dictionary<string, PKeyAlgorithm> algoConv = new Dictionary<string, PKeyAlgorithm>
|
Dictionary<string, ProductKeyAlgorithm> algoConv = new Dictionary<string, ProductKeyAlgorithm>
|
||||||
{
|
{
|
||||||
{ "msft:rm/algorithm/pkey/2005", PKeyAlgorithm.PKEY2005 },
|
{ "msft:rm/algorithm/pkey/2005", ProductKeyAlgorithm.ProductKey2005 },
|
||||||
{ "msft:rm/algorithm/pkey/2009", PKeyAlgorithm.PKEY2009 }
|
{ "msft:rm/algorithm/pkey/2009", ProductKeyAlgorithm.ProductKey2009 }
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (XmlNode pubKeyNode in pubKeyNodes)
|
foreach (XmlNode pubKeyNode in pubKeyNodes)
|
||||||
@@ -131,12 +125,10 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
|
|
||||||
foreach (XmlNode rangeNode in rangeNodes)
|
foreach (XmlNode rangeNode in rangeNodes)
|
||||||
{
|
{
|
||||||
string refActIdStr = rangeNode.SelectSingleNode("./p:RefActConfigId", nsmgr).InnerText;
|
string refActIdString = rangeNode.SelectSingleNode("./p:RefActConfigId", nsmgr).InnerText;
|
||||||
|
|
||||||
if (!ranges.ContainsKey(refActIdStr))
|
if (!ranges.ContainsKey(refActIdString))
|
||||||
{
|
ranges[refActIdString] = new List<KeyRange>();
|
||||||
ranges[refActIdStr] = new List<KeyRange>();
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyRange keyRange = new KeyRange();
|
KeyRange keyRange = new KeyRange();
|
||||||
keyRange.Start = int.Parse(rangeNode.SelectSingleNode("./p:Start", nsmgr).InnerText);
|
keyRange.Start = int.Parse(rangeNode.SelectSingleNode("./p:Start", nsmgr).InnerText);
|
||||||
@@ -145,15 +137,15 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
keyRange.PartNumber = rangeNode.SelectSingleNode("./p:PartNumber", nsmgr).InnerText;
|
keyRange.PartNumber = rangeNode.SelectSingleNode("./p:PartNumber", nsmgr).InnerText;
|
||||||
keyRange.Valid = rangeNode.SelectSingleNode("./p:IsValid", nsmgr).InnerText.ToLower() == "true";
|
keyRange.Valid = rangeNode.SelectSingleNode("./p:IsValid", nsmgr).InnerText.ToLower() == "true";
|
||||||
|
|
||||||
ranges[refActIdStr].Add(keyRange);
|
ranges[refActIdString].Add(keyRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (XmlNode configNode in configNodes)
|
foreach (XmlNode configNode in configNodes)
|
||||||
{
|
{
|
||||||
string refActIdStr = configNode.SelectSingleNode("./p:ActConfigId", nsmgr).InnerText;
|
string refActIdString = configNode.SelectSingleNode("./p:ActConfigId", nsmgr).InnerText;
|
||||||
Guid refActId = new Guid(refActIdStr);
|
Guid refActId = new Guid(refActIdString);
|
||||||
int group = int.Parse(configNode.SelectSingleNode("./p:RefGroupId", nsmgr).InnerText);
|
int group = int.Parse(configNode.SelectSingleNode("./p:RefGroupId", nsmgr).InnerText);
|
||||||
List<KeyRange> keyRanges = ranges[refActIdStr];
|
List<KeyRange> keyRanges = ranges[refActIdString];
|
||||||
|
|
||||||
if (keyRanges.Count > 0 && !Products.ContainsKey(refActId))
|
if (keyRanges.Count > 0 && !Products.ContainsKey(refActId))
|
||||||
{
|
{
|
||||||
@@ -172,31 +164,14 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadedPkeyConfigs.Add(pkcFileId);
|
_loadedProductKeyConfigs.Add(configFileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductConfig MatchParams(int group, int serial)
|
public ProductConfig MatchParams(int groupId, int serial)
|
||||||
{
|
{
|
||||||
foreach (ProductConfig config in Products.Values)
|
ProductConfig matchingConfig = Products.Values.FirstOrDefault(config => config.GroupId == groupId && config.Ranges.Any(range => range.Contains(serial)));
|
||||||
{
|
if (matchingConfig == null) throw new FileNotFoundException("Failed to find product matching supplied product key parameters.");
|
||||||
if (config.GroupId == group)
|
return matchingConfig;
|
||||||
{
|
|
||||||
foreach (KeyRange range in config.Ranges)
|
|
||||||
{
|
|
||||||
if (range.Contains(serial))
|
|
||||||
{
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new FileNotFoundException("Failed to find product matching supplied product key parameters.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public PKeyConfig()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,158 +3,56 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MetroUnlocker.LibTSForge.SPP
|
namespace MetroUnlocker.LibTSForge.SPP
|
||||||
{
|
{
|
||||||
public static class SLApi
|
public static class SLApi
|
||||||
{
|
{
|
||||||
private enum SLIDTYPE
|
|
||||||
{
|
|
||||||
SL_ID_APPLICATION,
|
|
||||||
SL_ID_PRODUCT_SKU,
|
|
||||||
SL_ID_LICENSE_FILE,
|
|
||||||
SL_ID_LICENSE,
|
|
||||||
SL_ID_PKEY,
|
|
||||||
SL_ID_ALL_LICENSES,
|
|
||||||
SL_ID_ALL_LICENSE_FILES,
|
|
||||||
SL_ID_STORE_TOKEN,
|
|
||||||
SL_ID_LAST
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum SLDATATYPE
|
|
||||||
{
|
|
||||||
SL_DATA_NONE,
|
|
||||||
SL_DATA_SZ,
|
|
||||||
SL_DATA_DWORD,
|
|
||||||
SL_DATA_BINARY,
|
|
||||||
SL_DATA_MULTI_SZ,
|
|
||||||
SL_DATA_SUM
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
private struct SL_LICENSING_STATUS
|
|
||||||
{
|
|
||||||
public Guid SkuId;
|
|
||||||
public uint eStatus;
|
|
||||||
public uint dwGraceTime;
|
|
||||||
public uint dwTotalGraceDays;
|
|
||||||
public uint hrReason;
|
|
||||||
public ulong qwValidityExpiration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly Guid WINDOWS_APP_ID = new Guid("55c92734-d682-4d71-983e-d6ec3f16059f");
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
|
||||||
private static extern void SLOpen(out IntPtr hSLC);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
|
||||||
private static extern void SLClose(IntPtr hSLC);
|
|
||||||
|
|
||||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLGetWindowsInformationDWORD(string ValueName, ref int Value);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLInstallProofOfPurchase(IntPtr hSLC, string pwszPKeyAlgorithm, string pwszPKeyString, uint cbPKeySpecificData, byte[] pbPKeySpecificData, ref Guid PKeyId);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLUninstallProofOfPurchase(IntPtr hSLC, ref Guid PKeyId);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLGetPKeyInformation(IntPtr hSLC, ref Guid pPKeyId, string pwszValueName, out SLDATATYPE peDataType, out uint pcbValue, out IntPtr ppbValue);
|
|
||||||
|
|
||||||
[DllImport("sppcext.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLActivateProduct(IntPtr hSLC, ref Guid pProductSkuId, byte[] cbAppSpecificData, byte[] pvAppSpecificData, byte[] pActivationInfo, string pwszProxyServer, ushort wProxyPort);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLGenerateOfflineInstallationId(IntPtr hSLC, ref Guid pProductSkuId, ref string ppwszInstallationId);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLDepositOfflineConfirmationId(IntPtr hSLC, ref Guid pProductSkuId, string pwszInstallationId, string pwszConfirmationId);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLGetSLIDList(IntPtr hSLC, SLIDTYPE eQueryIdType, ref Guid pQueryId, SLIDTYPE eReturnIdType, out uint pnReturnIds, out IntPtr ppReturnIds);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
|
||||||
private static extern void SLGetLicensingStatusInformation(IntPtr hSLC, ref Guid pAppID, IntPtr pProductSkuId, string pwszRightName, out uint pnStatusCount, out IntPtr ppLicensingStatus);
|
|
||||||
|
|
||||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLGetInstalledProductKeyIds(IntPtr hSLC, ref Guid pProductSkuId, out uint pnProductKeyIds, out IntPtr ppProductKeyIds);
|
|
||||||
|
|
||||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLConsumeWindowsRight(uint unknown);
|
|
||||||
|
|
||||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, out SLDATATYPE peDataType, out uint pcbValue, out IntPtr ppbValue);
|
|
||||||
|
|
||||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, IntPtr peDataType, out uint pcbValue, out IntPtr ppbValue);
|
|
||||||
|
|
||||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLGetLicense(IntPtr hSLC, ref Guid pLicenseFileId, out uint pcbLicenseFile, out IntPtr ppbLicenseFile);
|
|
||||||
|
|
||||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLSetCurrentProductKey(IntPtr hSLC, ref Guid pProductSkuId, ref Guid pProductKeyId);
|
|
||||||
|
|
||||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
|
||||||
private static extern uint SLFireEvent(IntPtr hSLC, string pwszEventId, ref Guid pApplicationId);
|
|
||||||
|
|
||||||
public class SLContext : IDisposable
|
public class SLContext : IDisposable
|
||||||
{
|
{
|
||||||
public readonly IntPtr Handle;
|
public readonly IntPtr Handle;
|
||||||
|
|
||||||
public SLContext()
|
public SLContext() { NativeMethods.SLOpen(out Handle); }
|
||||||
{
|
|
||||||
SLOpen(out Handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
SLClose(Handle);
|
NativeMethods.SLClose(Handle);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SLContext()
|
~SLContext() { Dispose(); }
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Guid GetPkeyConfigFileId(Guid actId)
|
public static Guid GetProductKeyConfigFileId(Guid activationId)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
SLDATATYPE type;
|
SLDataType type;
|
||||||
uint len;
|
uint length;
|
||||||
IntPtr ppReturnLics;
|
IntPtr fileIdPointer;
|
||||||
|
|
||||||
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "pkeyConfigLicenseId", out type, out len, out ppReturnLics);
|
uint status = NativeMethods.SLGetProductSkuInformation(sl.Handle, ref activationId, "pkeyConfigLicenseId", out type, out length, out fileIdPointer);
|
||||||
|
|
||||||
if (status != 0 || len == 0)
|
if (status != 0 || length == 0)
|
||||||
{
|
|
||||||
return Guid.Empty;
|
return Guid.Empty;
|
||||||
}
|
|
||||||
|
|
||||||
Guid pkcId = new Guid(Marshal.PtrToStringAuto(ppReturnLics));
|
Guid configLicenseId = new Guid(Marshal.PtrToStringAuto(fileIdPointer));
|
||||||
return GetLicenseFileId(pkcId);
|
return GetLicenseFileId(configLicenseId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Guid GetLicenseFileId(Guid licId)
|
public static Guid GetLicenseFileId(Guid licenseId)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
uint status;
|
uint status;
|
||||||
uint count;
|
uint count;
|
||||||
IntPtr ppReturnLics;
|
IntPtr returnLicenses;
|
||||||
|
|
||||||
status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_LICENSE, ref licId, SLIDTYPE.SL_ID_LICENSE_FILE, out count, out ppReturnLics);
|
status = NativeMethods.SLGetSLIDList(sl.Handle, SLIDType.License, ref licenseId, SLIDType.LicenseFile, out count, out returnLicenses);
|
||||||
|
|
||||||
return (status == 0 && count != 0) ? (Guid)Marshal.PtrToStructure(ppReturnLics, typeof(Guid)) : Guid.Empty;//new Guid(Marshal.PtrToStringAuto(ppReturnLics));
|
return (status == 0 && count != 0) ? (Guid)Marshal.PtrToStructure(returnLicenses, typeof(Guid)) : Guid.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,38 +62,34 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
|
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
uint dataLen;
|
uint length;
|
||||||
IntPtr dataPtr;
|
IntPtr dataPointer;
|
||||||
|
|
||||||
if (SLGetLicense(sl.Handle, ref fileId, out dataLen, out dataPtr) != 0)
|
if (NativeMethods.SLGetLicense(sl.Handle, ref fileId, out length, out dataPointer) != 0)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
byte[] data = new byte[dataLen];
|
byte[] data = new byte[length];
|
||||||
Marshal.Copy(dataPtr, data, 0, (int)dataLen);
|
Marshal.Copy(dataPointer, data, 0, (int)length);
|
||||||
|
|
||||||
data = data.Skip(Array.IndexOf(data, (byte)'<')).ToArray();
|
data = data.Skip(Array.IndexOf(data, (byte)'<')).ToArray();
|
||||||
return Encoding.UTF8.GetString(data);
|
return Encoding.UTF8.GetString(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetMetaStr(Guid actId, string value)
|
public static string GetMetaStr(Guid productSkuId, string value)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
uint len;
|
uint length;
|
||||||
SLDATATYPE type;
|
SLDataType type;
|
||||||
IntPtr ppbValue;
|
IntPtr binaryValue;
|
||||||
|
|
||||||
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, value, out type, out len, out ppbValue);
|
uint status = NativeMethods.SLGetProductSkuInformation(sl.Handle, ref productSkuId, value, out type, out length, out binaryValue);
|
||||||
|
|
||||||
if (status != 0 || len == 0 || type != SLDATATYPE.SL_DATA_SZ)
|
if (status != 0 || length == 0 || type != SLDataType.String)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
return Marshal.PtrToStringAuto(ppbValue);
|
return Marshal.PtrToStringAuto(binaryValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +98,7 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
string installationId = null;
|
string installationId = null;
|
||||||
var status = SLGenerateOfflineInstallationId(sl.Handle, ref actId, ref installationId);
|
var status = NativeMethods.SLGenerateOfflineInstallationId(sl.Handle, ref actId, ref installationId);
|
||||||
|
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
throw new Exception(string.Format("Failed to get installation ID: 0x{0}. Your data.dat is probably corrupt at the moment. Try again later.", status.ToString("X")));
|
throw new Exception(string.Format("Failed to get installation ID: 0x{0}. Your data.dat is probably corrupt at the moment. Try again later.", status.ToString("X")));
|
||||||
@@ -213,41 +107,40 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Guid GetInstalledPkeyId(Guid actId)
|
public static Guid GetInstalledProductKeyId(Guid actId)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
uint status;
|
uint status;
|
||||||
uint count;
|
uint count;
|
||||||
IntPtr pProductKeyIds;
|
IntPtr productKeyIds;
|
||||||
|
|
||||||
status = SLGetInstalledProductKeyIds(sl.Handle, ref actId, out count, out pProductKeyIds);
|
status = NativeMethods.SLGetInstalledProductKeyIds(sl.Handle, ref actId, out count, out productKeyIds);
|
||||||
|
|
||||||
//unsafe { return *(Guid*)pProductKeyIds; }
|
return (status == 0 && count != 0) ? (Guid)Marshal.PtrToStructure(productKeyIds, typeof(Guid)) : Guid.Empty;
|
||||||
return (status == 0 && count != 0) ? (Guid)Marshal.PtrToStructure(pProductKeyIds, typeof(Guid)) : Guid.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint DepositConfirmationId(Guid actId, string installationId, string confirmationId)
|
public static uint DepositConfirmationId(Guid actId, string installationId, string confirmationId)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
return SLDepositOfflineConfirmationId(sl.Handle, ref actId, installationId, confirmationId);
|
return NativeMethods.SLDepositOfflineConfirmationId(sl.Handle, ref actId, installationId, confirmationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RefreshLicenseStatus()
|
public static void RefreshLicenseStatus()
|
||||||
{
|
{
|
||||||
SLConsumeWindowsRight(0);
|
NativeMethods.SLConsumeWindowsRight(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool RefreshTrustedTime(Guid actId)
|
public static bool RefreshTrustedTime(Guid actId)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
SLDATATYPE type;
|
SLDataType type;
|
||||||
uint count;
|
uint count;
|
||||||
IntPtr ppbValue;
|
IntPtr ppbValue;
|
||||||
|
|
||||||
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "TrustedTime", out type, out count, out ppbValue);
|
uint status = NativeMethods.SLGetProductSkuInformation(sl.Handle, ref actId, "TrustedTime", out type, out count, out ppbValue);
|
||||||
return (int)status >= 0 && status != 0xC004F012;
|
return (int)status >= 0 && status != 0xC004F012;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,24 +148,22 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
public static void FireStateChangedEvent(Guid appId)
|
public static void FireStateChangedEvent(Guid appId)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
NativeMethods.SLFireEvent(sl.Handle, "msft:rm/event/licensingstatechanged", ref appId);
|
||||||
SLFireEvent(sl.Handle, "msft:rm/event/licensingstatechanged", ref appId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Guid GetAppId(Guid actId)
|
public static Guid GetAppId(Guid activationId)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
uint count;
|
uint count;
|
||||||
IntPtr pAppIds;
|
IntPtr appIdPointer;
|
||||||
|
|
||||||
uint status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_APPLICATION, out count, out pAppIds);
|
uint status = NativeMethods.SLGetSLIDList(sl.Handle, SLIDType.ProductSku, ref activationId, SLIDType.Application, out count, out appIdPointer);
|
||||||
|
|
||||||
if (status != 0 || count == 0)
|
if (status != 0 || count == 0)
|
||||||
return Guid.Empty;
|
return Guid.Empty;
|
||||||
|
|
||||||
return (Guid)Marshal.PtrToStructure(pAppIds, typeof(Guid));
|
return (Guid)Marshal.PtrToStructure(appIdPointer, typeof(Guid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,10 +172,10 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
uint count;
|
uint count;
|
||||||
SLDATATYPE type;
|
SLDataType type;
|
||||||
IntPtr ppbValue;
|
IntPtr ppbValue;
|
||||||
|
|
||||||
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "DependsOn", out type, out count, out ppbValue);
|
uint status = NativeMethods.SLGetProductSkuInformation(sl.Handle, ref actId, "DependsOn", out type, out count, out ppbValue);
|
||||||
return (int)status >= 0 && status != 0xC004F012;
|
return (int)status >= 0 && status != 0xC004F012;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,15 +184,15 @@ namespace MetroUnlocker.LibTSForge.SPP
|
|||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
{
|
{
|
||||||
Guid pkeyId = Guid.Empty;
|
Guid productKeyId = Guid.Empty;
|
||||||
return SLInstallProofOfPurchase(sl.Handle, pkey.GetAlgoUri(), pkey.ToString(), 0, null, ref pkeyId);
|
return NativeMethods.SLInstallProofOfPurchase(sl.Handle, pkey.GetAlgoUri(), pkey.ToString(), 0, null, ref productKeyId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint UninstallProductKey(Guid pkeyId)
|
public static uint UninstallProductKey(Guid productKeyId)
|
||||||
{
|
{
|
||||||
using (SLContext sl = new SLContext())
|
using (SLContext sl = new SLContext())
|
||||||
return SLUninstallProofOfPurchase(sl.Handle, ref pkeyId);
|
return NativeMethods.SLUninstallProofOfPurchase(sl.Handle, ref productKeyId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,18 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
{
|
{
|
||||||
public class TokenEntry
|
public class TokenEntry
|
||||||
{
|
{
|
||||||
public string Name;
|
public string Name { get; set; }
|
||||||
public string Extension;
|
public string Extension { get; set; }
|
||||||
public byte[] Data;
|
public byte[] Data { get; set; }
|
||||||
public bool Populated;
|
public bool Populated { get; set; }
|
||||||
|
|
||||||
|
public TokenEntry() : this("", "", new byte[] { }, false) {}
|
||||||
|
public TokenEntry(string name, string extension, byte[] data, bool populated = true)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Extension = extension;
|
||||||
|
Data = data;
|
||||||
|
Populated = populated;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,21 +10,21 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
|
|
||||||
public class TokenStore : IDisposable
|
public class TokenStore : IDisposable
|
||||||
{
|
{
|
||||||
private static readonly uint VERSION = 3;
|
private static readonly uint Version = 3;
|
||||||
private static readonly int ENTRY_SIZE = 0x9E;
|
private static readonly int EntrySize = 0x9E;
|
||||||
private static readonly int BLOCK_SIZE = 0x4020;
|
private static readonly int BlockSize = 0x4020;
|
||||||
private static readonly int ENTRIES_PER_BLOCK = BLOCK_SIZE / ENTRY_SIZE;
|
private static readonly int EntriesPerBlock = BlockSize / EntrySize;
|
||||||
private static readonly int BLOCK_PAD_SIZE = 0x66;
|
private static readonly int BlockPadSize = 0x66;
|
||||||
|
|
||||||
private static readonly byte[] CONTS_HEADER = Enumerable.Repeat((byte)0x55, 0x20).ToArray();
|
private static readonly byte[] Header = Enumerable.Repeat((byte)0x55, 0x20).ToArray();
|
||||||
private static readonly byte[] CONTS_FOOTER = Enumerable.Repeat((byte)0xAA, 0x20).ToArray();
|
private static readonly byte[] Footer = Enumerable.Repeat((byte)0xAA, 0x20).ToArray();
|
||||||
|
|
||||||
private List<TokenEntry> Entries = new List<TokenEntry>();
|
private List<TokenEntry> Entries = new List<TokenEntry>();
|
||||||
public FileStream TokensFile;
|
public FileStream TokensFile { get; set; }
|
||||||
|
|
||||||
public void Deserialize()
|
public void Deserialize()
|
||||||
{
|
{
|
||||||
if (TokensFile.Length < BLOCK_SIZE) return;
|
if (TokensFile.Length < BlockSize) return;
|
||||||
|
|
||||||
TokensFile.Seek(0x24, SeekOrigin.Begin);
|
TokensFile.Seek(0x24, SeekOrigin.Begin);
|
||||||
uint nextBlock = 0;
|
uint nextBlock = 0;
|
||||||
@@ -35,7 +35,7 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
uint curOffset = reader.ReadUInt32();
|
uint curOffset = reader.ReadUInt32();
|
||||||
nextBlock = reader.ReadUInt32();
|
nextBlock = reader.ReadUInt32();
|
||||||
|
|
||||||
for (int i = 0; i < ENTRIES_PER_BLOCK; i++)
|
for (int i = 0; i < EntriesPerBlock; i++)
|
||||||
{
|
{
|
||||||
curOffset = reader.ReadUInt32();
|
curOffset = reader.ReadUInt32();
|
||||||
bool populated = reader.ReadUInt32() == 1;
|
bool populated = reader.ReadUInt32() == 1;
|
||||||
@@ -50,9 +50,7 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
uint dataLength = reader.ReadUInt32();
|
uint dataLength = reader.ReadUInt32();
|
||||||
|
|
||||||
if (dataLength != contentLength)
|
if (dataLength != contentLength)
|
||||||
{
|
|
||||||
throw new FormatException("Data length in tokens content is inconsistent with entry.");
|
throw new FormatException("Data length in tokens content is inconsistent with entry.");
|
||||||
}
|
|
||||||
|
|
||||||
reader.ReadBytes(0x20);
|
reader.ReadBytes(0x20);
|
||||||
contentData = reader.ReadBytes((int)contentLength);
|
contentData = reader.ReadBytes((int)contentLength);
|
||||||
@@ -60,13 +58,7 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
|
|
||||||
reader.BaseStream.Seek(curOffset + 0x14, SeekOrigin.Begin);
|
reader.BaseStream.Seek(curOffset + 0x14, SeekOrigin.Begin);
|
||||||
|
|
||||||
Entries.Add(new TokenEntry
|
Entries.Add(new TokenEntry(reader.ReadNullTerminatedString(0x82), reader.ReadNullTerminatedString(0x8), contentData, populated));
|
||||||
{
|
|
||||||
Name = reader.ReadNullTerminatedString(0x82),
|
|
||||||
Extension = reader.ReadNullTerminatedString(0x8),
|
|
||||||
Data = contentData,
|
|
||||||
Populated = populated
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.BaseStream.Seek(nextBlock, SeekOrigin.Begin);
|
reader.BaseStream.Seek(nextBlock, SeekOrigin.Begin);
|
||||||
@@ -79,31 +71,16 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
|
|
||||||
using (BinaryWriter writer = new BinaryWriter(tokens))
|
using (BinaryWriter writer = new BinaryWriter(tokens))
|
||||||
{
|
{
|
||||||
writer.Write(VERSION);
|
writer.Write(Version);
|
||||||
writer.Write(CONTS_HEADER);
|
writer.Write(Header);
|
||||||
|
|
||||||
int curBlockOffset = (int)writer.BaseStream.Position;
|
int curBlockOffset = (int)writer.BaseStream.Position;
|
||||||
int curEntryOffset = curBlockOffset + 0x8;
|
int curEntryOffset = curBlockOffset + 0x8;
|
||||||
int curContsOffset = curBlockOffset + BLOCK_SIZE;
|
int curContsOffset = curBlockOffset + BlockSize;
|
||||||
|
|
||||||
for (int eIndex = 0; eIndex < ((Entries.Count / ENTRIES_PER_BLOCK) + 1) * ENTRIES_PER_BLOCK; eIndex++)
|
for (int eIndex = 0; eIndex < ((Entries.Count / EntriesPerBlock) + 1) * EntriesPerBlock; eIndex++)
|
||||||
{
|
{
|
||||||
TokenEntry entry;
|
TokenEntry entry = eIndex < Entries.Count ? entry = Entries[eIndex] : new TokenEntry();
|
||||||
|
|
||||||
if (eIndex < Entries.Count)
|
|
||||||
{
|
|
||||||
entry = Entries[eIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entry = new TokenEntry
|
|
||||||
{
|
|
||||||
Name = "",
|
|
||||||
Extension = "",
|
|
||||||
Populated = false,
|
|
||||||
Data = new byte[] { }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.BaseStream.Seek(curBlockOffset, SeekOrigin.Begin);
|
writer.BaseStream.Seek(curBlockOffset, SeekOrigin.Begin);
|
||||||
writer.Write(curBlockOffset);
|
writer.Write(curBlockOffset);
|
||||||
@@ -122,15 +99,15 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
if (entry.Populated)
|
if (entry.Populated)
|
||||||
{
|
{
|
||||||
writer.BaseStream.Seek(curContsOffset, SeekOrigin.Begin);
|
writer.BaseStream.Seek(curContsOffset, SeekOrigin.Begin);
|
||||||
writer.Write(CONTS_HEADER);
|
writer.Write(Header);
|
||||||
writer.Write(entry.Data.Length);
|
writer.Write(entry.Data.Length);
|
||||||
writer.Write(CryptoUtils.SHA256Hash(entry.Data));
|
writer.Write(CryptoUtils.SHA256Hash(entry.Data));
|
||||||
writer.Write(entry.Data);
|
writer.Write(entry.Data);
|
||||||
writer.Write(CONTS_FOOTER);
|
writer.Write(Footer);
|
||||||
curContsOffset = (int)writer.BaseStream.Position;
|
curContsOffset = (int)writer.BaseStream.Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((eIndex + 1) % ENTRIES_PER_BLOCK == 0 && eIndex != 0)
|
if ((eIndex + 1) % EntriesPerBlock == 0 && eIndex != 0)
|
||||||
{
|
{
|
||||||
if (eIndex < Entries.Count)
|
if (eIndex < Entries.Count)
|
||||||
{
|
{
|
||||||
@@ -139,21 +116,21 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
writer.BaseStream.Seek(curEntryOffset, SeekOrigin.Begin);
|
writer.BaseStream.Seek(curEntryOffset, SeekOrigin.Begin);
|
||||||
writer.WritePadding(BLOCK_PAD_SIZE);
|
writer.WritePadding(BlockPadSize);
|
||||||
|
|
||||||
writer.BaseStream.Seek(curBlockOffset, SeekOrigin.Begin);
|
writer.BaseStream.Seek(curBlockOffset, SeekOrigin.Begin);
|
||||||
byte[] blockHash;
|
byte[] blockHash;
|
||||||
byte[] blockData = new byte[BLOCK_SIZE - 0x20];
|
byte[] blockData = new byte[BlockSize - 0x20];
|
||||||
|
|
||||||
tokens.Read(blockData, 0, BLOCK_SIZE - 0x20);
|
tokens.Read(blockData, 0, BlockSize - 0x20);
|
||||||
blockHash = CryptoUtils.SHA256Hash(blockData);
|
blockHash = CryptoUtils.SHA256Hash(blockData);
|
||||||
|
|
||||||
writer.BaseStream.Seek(curBlockOffset + BLOCK_SIZE - 0x20, SeekOrigin.Begin);
|
writer.BaseStream.Seek(curBlockOffset + BlockSize - 0x20, SeekOrigin.Begin);
|
||||||
writer.Write(blockHash);
|
writer.Write(blockHash);
|
||||||
|
|
||||||
curBlockOffset = curContsOffset;
|
curBlockOffset = curContsOffset;
|
||||||
curEntryOffset = curBlockOffset + 0x8;
|
curEntryOffset = curBlockOffset + 0x8;
|
||||||
curContsOffset = curBlockOffset + BLOCK_SIZE;
|
curContsOffset = curBlockOffset + BlockSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,71 +167,41 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
public void DeleteEntry(string name, string ext)
|
public void DeleteEntry(string name, string ext)
|
||||||
{
|
{
|
||||||
foreach (TokenEntry entry in Entries)
|
foreach (TokenEntry entry in Entries)
|
||||||
{
|
|
||||||
if (entry.Name == name && entry.Extension == ext)
|
if (entry.Name == name && entry.Extension == ext)
|
||||||
{
|
{
|
||||||
Entries.Remove(entry);
|
Entries.Remove(entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteUnpopEntry(string name, string ext)
|
public void DeleteUnpopulatedEntry(string name, string extension)
|
||||||
{
|
{
|
||||||
List<TokenEntry> delEntries = new List<TokenEntry>();
|
Entries = Entries.FindAll(entry => entry.Name != name && entry.Extension != extension && entry.Populated);
|
||||||
foreach (TokenEntry entry in Entries)
|
|
||||||
{
|
|
||||||
if (entry.Name == name && entry.Extension == ext && !entry.Populated)
|
|
||||||
{
|
|
||||||
delEntries.Add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Entries = Entries.Except(delEntries).ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TokenEntry GetEntry(string name, string ext)
|
public TokenEntry GetEntry(string name, string ext)
|
||||||
{
|
{
|
||||||
foreach (TokenEntry entry in Entries)
|
foreach (TokenEntry entry in Entries)
|
||||||
{
|
|
||||||
if (entry.Name == name && entry.Extension == ext)
|
if (entry.Name == name && entry.Extension == ext)
|
||||||
{
|
if (entry.Populated) return entry;
|
||||||
if (!entry.Populated) continue;
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TokenMeta GetMetaEntry(string name)
|
public TokenMeta GetMetaEntry(string name)
|
||||||
{
|
{
|
||||||
DeleteUnpopEntry(name, "xml");
|
DeleteUnpopulatedEntry(name, "xml");
|
||||||
TokenEntry entry = GetEntry(name, "xml");
|
TokenEntry entry = GetEntry(name, "xml");
|
||||||
TokenMeta meta;
|
|
||||||
|
|
||||||
if (entry == null)
|
return entry == null ? new TokenMeta(name) : new TokenMeta(entry.Data);
|
||||||
{
|
|
||||||
meta = new TokenMeta
|
|
||||||
{
|
|
||||||
Name = name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
meta = new TokenMeta(entry.Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetEntry(string name, string ext, byte[] data)
|
public void SetEntry(string name, string extension, byte[] data)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Entries.Count; i++)
|
for (int i = 0; i < Entries.Count; i++)
|
||||||
{
|
{
|
||||||
TokenEntry entry = Entries[i];
|
TokenEntry entry = Entries[i];
|
||||||
|
|
||||||
if (entry.Name == name && entry.Extension == ext && entry.Populated)
|
if (entry.Name == name && entry.Extension == extension && entry.Populated)
|
||||||
{
|
{
|
||||||
entry.Data = data;
|
entry.Data = data;
|
||||||
Entries[i] = entry;
|
Entries[i] = entry;
|
||||||
@@ -262,13 +209,7 @@ namespace MetroUnlocker.LibTSForge.TokenStore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entries.Add(new TokenEntry
|
Entries.Add(new TokenEntry(name, extension, data));
|
||||||
{
|
|
||||||
Populated = true,
|
|
||||||
Name = name,
|
|
||||||
Extension = ext,
|
|
||||||
Data = data
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetPath()
|
public static string GetPath()
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.Win32;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
using MetroUnlocker.LibTSForge.SPP;
|
using MetroUnlocker.LibTSForge.SPP;
|
||||||
using MetroUnlocker.LibTSForge.PhysicalStore;
|
using MetroUnlocker.LibTSForge.PhysicalStore;
|
||||||
@@ -21,39 +22,37 @@ namespace MetroUnlocker
|
|||||||
uint status = SLApi.DepositConfirmationId(actId, instId, Constants.ZeroCID);
|
uint status = SLApi.DepositConfirmationId(actId, instId, Constants.ZeroCID);
|
||||||
|
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
throw new InvalidOperationException(string.Format("Failed to deposit fake CID. Status code: 0x{0}", status.ToString("X")));
|
throw new COMException(string.Format("Failed to deposit fake CID. Status code: 0x{0}", status.ToString("X")), (int)status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Activate(PSVersion version, bool production, Guid actId)
|
public static void Activate(PhysicalStoreVersion version, bool production, Guid activationId)
|
||||||
{
|
{
|
||||||
Guid appId = SLApi.GetAppId(actId);
|
Guid appId = SLApi.GetAppId(activationId);
|
||||||
|
|
||||||
string instId = SLApi.GetInstallationId(actId);
|
string instId = SLApi.GetInstallationId(activationId);
|
||||||
Guid pkeyId = SLApi.GetInstalledPkeyId(actId);
|
Guid pkeyId = SLApi.GetInstalledProductKeyId(activationId);
|
||||||
|
|
||||||
Utils.KillSPP();
|
Utils.KillSPP();
|
||||||
|
|
||||||
using (PhysicalStore store = new PhysicalStore(version, production))
|
using (PhysicalStore store = new PhysicalStore(version, production))
|
||||||
{
|
{
|
||||||
byte[] hwidBlock = Constants.UniversalHWIDBlock;
|
byte[] hwidBlock = Constants.UniversalHardwareIdBlock;
|
||||||
|
|
||||||
byte[] iidHash = CryptoUtils.SHA256Hash(Utils.EncodeString(instId + '\0' + Constants.ZeroCID));
|
byte[] iidHash = CryptoUtils.SHA256Hash(Utils.EncodeString(instId + '\0' + Constants.ZeroCID));
|
||||||
|
|
||||||
|
|
||||||
string key = string.Format("SPPSVC\\{0}\\{1}", appId, actId);
|
string key = string.Format("SPPSVC\\{0}\\{1}", appId, activationId);
|
||||||
ModernBlock keyBlock = store.GetBlock(key, pkeyId.ToString());
|
ModernBlock keyBlock = store.GetBlock(key, pkeyId.ToString());
|
||||||
|
|
||||||
if (keyBlock == null)
|
if (keyBlock == null)
|
||||||
{
|
throw new InvalidDataException("Failed to get product key data for activation ID: 0x" + activationId + ".");
|
||||||
throw new InvalidDataException("Failed to get product key data for activation ID: 0x" + actId + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
VariableBag pkb = new VariableBag(keyBlock.Data);
|
VariableBag keyBag = new VariableBag(keyBlock.Data);
|
||||||
|
|
||||||
byte[] pkeyData = pkb.GetBlock("SppPkeyPhoneActivationData").Value;
|
byte[] pkeyData = keyBag.GetBlock("SppPkeyPhoneActivationData").Value;
|
||||||
|
|
||||||
pkb.DeleteBlock("SppPkeyVirtual");
|
keyBag.DeleteBlock("SppPkeyVirtual");
|
||||||
store.SetBlock(key, pkeyId.ToString(), pkb.Serialize());
|
store.SetBlock(key, pkeyId.ToString(), keyBag.Serialize());
|
||||||
|
|
||||||
BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
||||||
writer.Write(0x20);
|
writer.Write(0x20);
|
||||||
@@ -69,27 +68,15 @@ namespace MetroUnlocker
|
|||||||
writer.Write(pkeyData);
|
writer.Write(pkeyData);
|
||||||
byte[] tsPkeyInfoData = Utils.GetBytes(writer);
|
byte[] tsPkeyInfoData = Utils.GetBytes(writer);
|
||||||
|
|
||||||
|
string path = "msft:Windows/7.0/Phone/Cached/";
|
||||||
|
|
||||||
store.AddBlocks(new ModernBlock[] {
|
store.AddBlocks(new ModernBlock[] {
|
||||||
new ModernBlock
|
new ModernBlock(key, path + "HwidBlock/" + pkeyId, tsHwidData),
|
||||||
{
|
new ModernBlock(key, path + "PKeyInfo/" + pkeyId, tsPkeyInfoData)
|
||||||
Type = BlockType.NAMED,
|
|
||||||
Flags = 0,
|
|
||||||
KeyAsStr = key,
|
|
||||||
ValueAsStr = "msft:Windows/7.0/Phone/Cached/HwidBlock/" + pkeyId,
|
|
||||||
Data = tsHwidData
|
|
||||||
},
|
|
||||||
new ModernBlock
|
|
||||||
{
|
|
||||||
Type = BlockType.NAMED,
|
|
||||||
Flags = 0,
|
|
||||||
KeyAsStr = key,
|
|
||||||
ValueAsStr = "msft:Windows/7.0/Phone/Cached/PKeyInfo/" + pkeyId,
|
|
||||||
Data = tsPkeyInfoData
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Deposit(actId, instId);
|
Deposit(activationId, instId);
|
||||||
|
|
||||||
SLApi.RefreshLicenseStatus();
|
SLApi.RefreshLicenseStatus();
|
||||||
SLApi.FireStateChangedEvent(appId);
|
SLApi.FireStateChangedEvent(appId);
|
||||||
|
|||||||
@@ -57,16 +57,18 @@
|
|||||||
<Compile Include="App.Designer.cs">
|
<Compile Include="App.Designer.cs">
|
||||||
<DependentUpon>App.cs</DependentUpon>
|
<DependentUpon>App.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="LibTSForge\Common.cs" />
|
<Compile Include="Common.cs" />
|
||||||
<Compile Include="LibTSForge\Crypto\CryptoUtils.cs" />
|
<Compile Include="LibTSForge\Crypto\CryptoUtils.cs" />
|
||||||
<Compile Include="LibTSForge\Crypto\Keys.cs" />
|
<Compile Include="LibTSForge\Crypto\Keys.cs" />
|
||||||
<Compile Include="LibTSForge\Crypto\PhysicalStoreCrypto.cs" />
|
<Compile Include="LibTSForge\Crypto\PhysicalStoreCrypto.cs" />
|
||||||
<Compile Include="LibTSForge\Modifiers\GenPKeyInstall.cs" />
|
<Compile Include="LibTSForge\Modifiers\ProductKeyInstaller.cs" />
|
||||||
|
<Compile Include="LibTSForge\PhysicalStore\BasicBlock.cs" />
|
||||||
<Compile Include="LibTSForge\PhysicalStore\CRCBlock.cs" />
|
<Compile Include="LibTSForge\PhysicalStore\CRCBlock.cs" />
|
||||||
<Compile Include="LibTSForge\PhysicalStore\ModernBlock.cs" />
|
<Compile Include="LibTSForge\PhysicalStore\ModernBlock.cs" />
|
||||||
<Compile Include="LibTSForge\PhysicalStore\PhysicalStore.cs" />
|
<Compile Include="LibTSForge\PhysicalStore\PhysicalStore.cs" />
|
||||||
<Compile Include="LibTSForge\PhysicalStore\VariableBag.cs" />
|
<Compile Include="LibTSForge\PhysicalStore\VariableBag.cs" />
|
||||||
<Compile Include="LibTSForge\SPP\PKeyConfig.cs" />
|
<Compile Include="LibTSForge\SPP\NativeMethods.cs" />
|
||||||
|
<Compile Include="LibTSForge\SPP\ProductKeyConfig.cs" />
|
||||||
<Compile Include="LibTSForge\SPP\ProductKey.cs" />
|
<Compile Include="LibTSForge\SPP\ProductKey.cs" />
|
||||||
<Compile Include="LibTSForge\SPP\SLApi.cs" />
|
<Compile Include="LibTSForge\SPP\SLApi.cs" />
|
||||||
<Compile Include="LibTSForge\TokenStore\TokenEntry.cs" />
|
<Compile Include="LibTSForge\TokenStore\TokenEntry.cs" />
|
||||||
@@ -74,13 +76,9 @@
|
|||||||
<Compile Include="LibTSForge\ZeroCID.cs" />
|
<Compile Include="LibTSForge\ZeroCID.cs" />
|
||||||
<Compile Include="LOBManager.cs" />
|
<Compile Include="LOBManager.cs" />
|
||||||
<Compile Include="ProductPolicy\ProductPolicy.cs" />
|
<Compile Include="ProductPolicy\ProductPolicy.cs" />
|
||||||
<Compile Include="ProductPolicy\ProductPolicyEditor.cs" />
|
<Compile Include="ProductPolicy\ProductPolicyReader.cs" />
|
||||||
<Compile Include="ProductPolicy\Tools.cs" />
|
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Rebooter.cs" />
|
|
||||||
<Compile Include="SPPManager.cs" />
|
|
||||||
<Compile Include="StartupArguments.cs" />
|
|
||||||
<EmbeddedResource Include="App.resx">
|
<EmbeddedResource Include="App.resx">
|
||||||
<DependentUpon>App.cs</DependentUpon>
|
<DependentUpon>App.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
@@ -93,7 +91,9 @@
|
|||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<None Include="app.manifest" />
|
<None Include="app.manifest">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</None>
|
||||||
<None Include="Properties\Settings.settings">
|
<None Include="Properties\Settings.settings">
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
|||||||
@@ -7,57 +7,20 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
|
||||||
namespace MetroUnlocker.ProductPolicy
|
namespace MetroUnlocker.ProductPolicy
|
||||||
{
|
{
|
||||||
//public struct ProductPolicyData
|
|
||||||
//{
|
|
||||||
// public string String;
|
|
||||||
// public byte[] Bytes;
|
|
||||||
// public uint DWord;
|
|
||||||
//};
|
|
||||||
class ProductPolicy
|
class ProductPolicy
|
||||||
{
|
{
|
||||||
public bool Modified { get; set; }
|
|
||||||
public ProductPolicyValue Header { get; set; }
|
public ProductPolicyValue Header { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
//private ProductPolicyData _data;
|
|
||||||
|
|
||||||
//public ProductPolicyData Data
|
|
||||||
//{
|
|
||||||
// get { return _data; }
|
|
||||||
// set { _data = value; }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public byte[] Bytes { get; set; }
|
public byte[] Bytes { get; set; }
|
||||||
public string StringValue
|
public string StringValue { get { return Encoding.Unicode.GetString(Bytes); } }
|
||||||
{
|
public uint DWordValue { get { return BitConverter.ToUInt32(Bytes, 0); } }
|
||||||
get
|
|
||||||
{
|
|
||||||
return Encoding.Unicode.GetString(Bytes);
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
Bytes = Encoding.Unicode.GetBytes(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public uint DWordValue
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return BitConverter.ToUInt32(Bytes, 0);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Bytes = BitConverter.GetBytes(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegistryValueKind Type
|
public RegistryValueKind Type
|
||||||
{
|
{
|
||||||
get
|
get { return (RegistryValueKind)Header.DataType; }
|
||||||
{
|
|
||||||
return (RegistryValueKind)Header.DataType;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NameFromBin(ref byte[] PolicyBlob, int offset)
|
private void NameFromBin(ref byte[] PolicyBlob, int offset)
|
||||||
@@ -74,12 +37,10 @@ namespace MetroUnlocker.ProductPolicy
|
|||||||
|
|
||||||
public void FromBin(ref byte[] PolicyBlob, int offset)
|
public void FromBin(ref byte[] PolicyBlob, int offset)
|
||||||
{
|
{
|
||||||
Header = Tools.BytesToStruct<ProductPolicyValue>(PolicyBlob, typeof(ProductPolicyValue), offset);
|
Header = ProductPolicyReader.BytesToStruct<ProductPolicyValue>(PolicyBlob, offset);
|
||||||
if ((Header.Data + Header.Name + Marshal.SizeOf(Header)) > Header.Size ||
|
if ((Header.Data + Header.Name + Marshal.SizeOf(Header)) > Header.Size || (offset + Header.Size) > PolicyBlob.Length)
|
||||||
(offset + Header.Size) > PolicyBlob.Length)
|
throw new Exception("Invalid data Header format");
|
||||||
{
|
|
||||||
throw new Exception("Invalid _data Header format");
|
|
||||||
}
|
|
||||||
NameFromBin(ref PolicyBlob, offset);
|
NameFromBin(ref PolicyBlob, offset);
|
||||||
ValFromBin(ref PolicyBlob, offset);
|
ValFromBin(ref PolicyBlob, offset);
|
||||||
}
|
}
|
||||||
@@ -97,57 +58,6 @@ namespace MetroUnlocker.ProductPolicy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Size()
|
public int Size() { return Bytes.Length; }
|
||||||
{
|
|
||||||
//switch (Type)
|
|
||||||
//{
|
|
||||||
// case RegistryValueKind.String:
|
|
||||||
// return StringValue.Length * 2;
|
|
||||||
// case RegistryValueKind.DWord:
|
|
||||||
// return 4;
|
|
||||||
// default:
|
|
||||||
// return Bytes.Length;
|
|
||||||
//}
|
|
||||||
return Bytes.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public byte[] ToBinary()
|
|
||||||
//{
|
|
||||||
// switch (Type)
|
|
||||||
// {
|
|
||||||
// case RegistryValueKind.String:
|
|
||||||
// return Encoding.Unicode.GetBytes(_data.String);
|
|
||||||
// case RegistryValueKind.DWord:
|
|
||||||
// return Tools.StructToBytes(DWordVq);
|
|
||||||
// default:
|
|
||||||
// return Bytes;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public byte[] ToBin()
|
|
||||||
{
|
|
||||||
ProductPolicyValue value = new ProductPolicyValue();
|
|
||||||
value.Name = (UInt16)(2 * Name.Length);
|
|
||||||
value.Data = (UInt16)Size();
|
|
||||||
int datablocksize = Marshal.SizeOf(Header) + value.Name + value.Data;
|
|
||||||
int suffixLength = 4 - (datablocksize % 4);
|
|
||||||
value.Size = (UInt16)(Marshal.SizeOf(Header) + value.Name + value.Data + suffixLength);
|
|
||||||
value.DataType = Header.DataType;
|
|
||||||
value.Unknown1 = Header.Unknown1;
|
|
||||||
value.Unknown2 = Header.Unknown2;
|
|
||||||
byte[] bytes = Tools.StructToBytes(value);
|
|
||||||
|
|
||||||
Tools.AppendBytes(ref bytes, Encoding.Unicode.GetBytes(Name));
|
|
||||||
Tools.AppendBytes(ref bytes, Bytes);
|
|
||||||
Tools.PaddingAppend(ref bytes, suffixLength);
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// I would like to not split the data into dword and string on parsing but on getting.
|
|
||||||
//public void SetDWordValue(uint value)
|
|
||||||
//{
|
|
||||||
// Data = new ProductPolicyData { DWord = value };
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace MetroUnlocker.ProductPolicy
|
|
||||||
{
|
|
||||||
public struct ProductPolicyHeader
|
|
||||||
{
|
|
||||||
public UInt32 Size, DataSize, EndMarker, Unknown1, Unknown2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct ProductPolicyValue
|
|
||||||
{
|
|
||||||
public UInt16 Size, Name, DataType, Data;
|
|
||||||
public UInt32 Unknown1, Unknown2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PolicyState : uint
|
|
||||||
{
|
|
||||||
Disabled = 0,
|
|
||||||
Enabled = 1,
|
|
||||||
Unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProductPolicyEditor
|
|
||||||
{
|
|
||||||
public List<ProductPolicy> PolicyValues { get; set; }
|
|
||||||
public ProductPolicyHeader Header;
|
|
||||||
private byte[] _policyBytes;
|
|
||||||
private byte[] _productPolicyBlobSuffix;
|
|
||||||
|
|
||||||
const string ProductOptionsKey = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions";
|
|
||||||
|
|
||||||
public ProductPolicyEditor()
|
|
||||||
{
|
|
||||||
_policyBytes = GetPolicyBlob();
|
|
||||||
PolicyValues = FromBinary();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Save()
|
|
||||||
{
|
|
||||||
return SetPolicyBlob(ToBin());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] GetPolicyBlob()
|
|
||||||
{
|
|
||||||
return (byte[])Registry.GetValue(ProductOptionsKey, "ProductPolicy", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool SetPolicyBlob(byte[] bytes)
|
|
||||||
{
|
|
||||||
Registry.SetValue(ProductOptionsKey, "ProductPolicy", bytes);
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
return Tools.ArraysEqual(GetPolicyBlob(), bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ProductPolicy> FromBinary()
|
|
||||||
{
|
|
||||||
return FromBinary(_policyBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ProductPolicy> FromBinary(byte[] policyBlob)
|
|
||||||
{
|
|
||||||
var header = Tools.BytesToStruct<ProductPolicyHeader>(policyBlob, typeof(ProductPolicyHeader));
|
|
||||||
|
|
||||||
if (header.Size < policyBlob.Length || (header.DataSize + Marshal.SizeOf(header) + header.EndMarker) != header.Size)
|
|
||||||
throw new Exception("Invalid Header format");
|
|
||||||
|
|
||||||
int pos = Marshal.SizeOf(header);
|
|
||||||
int pos_end = pos + (int)header.DataSize;
|
|
||||||
|
|
||||||
PolicyValues = new List<ProductPolicy>();
|
|
||||||
|
|
||||||
while (pos < pos_end)
|
|
||||||
{
|
|
||||||
ProductPolicy pv = new ProductPolicy();
|
|
||||||
pv.FromBin(ref policyBlob, pos);
|
|
||||||
PolicyValues.Add(pv);
|
|
||||||
|
|
||||||
pos += pv.Header.Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos < header.Size)
|
|
||||||
{
|
|
||||||
_productPolicyBlobSuffix = new byte[policyBlob.Length - pos];
|
|
||||||
Array.Copy(policyBlob, pos, _productPolicyBlobSuffix, 0, _productPolicyBlobSuffix.Length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_productPolicyBlobSuffix = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PolicyValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ToBin()
|
|
||||||
{
|
|
||||||
int headerSize = Marshal.SizeOf(Header);
|
|
||||||
byte[] policyBlob = new byte[headerSize];
|
|
||||||
|
|
||||||
foreach (ProductPolicy v in PolicyValues)
|
|
||||||
Tools.AppendBytes(ref policyBlob, v.ToBin());
|
|
||||||
|
|
||||||
Tools.AppendBytes(ref policyBlob, _productPolicyBlobSuffix);
|
|
||||||
|
|
||||||
Header.Size = (UInt32)policyBlob.Length;
|
|
||||||
Header.EndMarker = (UInt32)_productPolicyBlobSuffix.Length;
|
|
||||||
Header.DataSize = (UInt32)(Header.Size - Header.EndMarker - headerSize);
|
|
||||||
Array.Copy(Tools.StructToBytes(Header), 0, policyBlob, 0, headerSize);
|
|
||||||
|
|
||||||
return policyBlob;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProductPolicy GetPolicyWithName(string name)
|
|
||||||
{
|
|
||||||
return PolicyValues.Find(value => value.Name == name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PolicyState GetPolicyStateByName(string name)
|
|
||||||
{
|
|
||||||
ProductPolicy policy = GetPolicyWithName(name);
|
|
||||||
if (policy.Type == RegistryValueKind.DWord)
|
|
||||||
{
|
|
||||||
if (policy.DWordValue == 0)
|
|
||||||
return PolicyState.Disabled;
|
|
||||||
else if (policy.DWordValue == 1)
|
|
||||||
return PolicyState.Enabled;
|
|
||||||
}
|
|
||||||
return PolicyState.Unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SetPolicyStateByName(string name, PolicyState state)
|
|
||||||
{
|
|
||||||
ProductPolicy policy = GetPolicyWithName(name);
|
|
||||||
|
|
||||||
if (policy.Type == RegistryValueKind.DWord)
|
|
||||||
{
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case PolicyState.Disabled:
|
|
||||||
policy.DWordValue = 0;
|
|
||||||
break;
|
|
||||||
case PolicyState.Enabled:
|
|
||||||
policy.DWordValue = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
101
MetroUnlocker/ProductPolicy/ProductPolicyReader.cs
Normal file
101
MetroUnlocker/ProductPolicy/ProductPolicyReader.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace MetroUnlocker.ProductPolicy
|
||||||
|
{
|
||||||
|
public struct ProductPolicyHeader
|
||||||
|
{
|
||||||
|
public UInt32 Size, DataSize, EndMarker, Unknown1, Unknown2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ProductPolicyValue
|
||||||
|
{
|
||||||
|
public UInt16 Size, Name, DataType, Data;
|
||||||
|
public UInt32 Unknown1, Unknown2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PolicyState : uint
|
||||||
|
{
|
||||||
|
Disabled = 0,
|
||||||
|
Enabled = 1,
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProductPolicyReader
|
||||||
|
{
|
||||||
|
public List<ProductPolicy> PolicyValues { get; set; }
|
||||||
|
|
||||||
|
const string ProductOptionsKey = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions";
|
||||||
|
|
||||||
|
public ProductPolicyReader()
|
||||||
|
{
|
||||||
|
PolicyValues = FromBinary(GetPolicyBlob());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] GetPolicyBlob()
|
||||||
|
{
|
||||||
|
return (byte[])Registry.GetValue(ProductOptionsKey, "ProductPolicy", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public T BytesToStruct<T>(byte[] bytes, int offset = 0)
|
||||||
|
{
|
||||||
|
int size = Marshal.SizeOf(typeof(T));
|
||||||
|
IntPtr buffer = Marshal.AllocHGlobal(size);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Marshal.Copy(bytes, offset, buffer, size);
|
||||||
|
return (T)Marshal.PtrToStructure(buffer, typeof(T));
|
||||||
|
}
|
||||||
|
finally { Marshal.FreeHGlobal(buffer); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ProductPolicy> FromBinary(byte[] policyBlob)
|
||||||
|
{
|
||||||
|
var header = BytesToStruct<ProductPolicyHeader>(policyBlob);
|
||||||
|
|
||||||
|
if (header.Size < policyBlob.Length || (header.DataSize + Marshal.SizeOf(header) + header.EndMarker) != header.Size)
|
||||||
|
throw new Exception("Invalid Header format");
|
||||||
|
|
||||||
|
int position = Marshal.SizeOf(header);
|
||||||
|
int end = position + (int)header.DataSize;
|
||||||
|
|
||||||
|
PolicyValues = new List<ProductPolicy>();
|
||||||
|
|
||||||
|
while (position < end)
|
||||||
|
{
|
||||||
|
ProductPolicy policy = new ProductPolicy();
|
||||||
|
policy.FromBin(ref policyBlob, position);
|
||||||
|
PolicyValues.Add(policy);
|
||||||
|
|
||||||
|
position += policy.Header.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PolicyValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductPolicy GetPolicyWithName(string name)
|
||||||
|
{
|
||||||
|
return PolicyValues.Find(value => value.Name == name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolicyState GetPolicyStateByName(string name)
|
||||||
|
{
|
||||||
|
ProductPolicy policy = GetPolicyWithName(name);
|
||||||
|
if (policy.Type == RegistryValueKind.DWord)
|
||||||
|
{
|
||||||
|
if (policy.DWordValue == 0)
|
||||||
|
return PolicyState.Disabled;
|
||||||
|
else if (policy.DWordValue == 1)
|
||||||
|
return PolicyState.Enabled;
|
||||||
|
}
|
||||||
|
return PolicyState.Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace MetroUnlocker.ProductPolicy
|
|
||||||
{
|
|
||||||
class Tools
|
|
||||||
{
|
|
||||||
public static void AppendBytes(ref byte[] b1, byte[] b2)
|
|
||||||
{
|
|
||||||
int length = b1.Length;
|
|
||||||
Array.Resize(ref b1, length + b2.Length);
|
|
||||||
Array.Copy(b2, 0, b1, length, b2.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public T BytesToStruct<T>(byte[] bytes, Type type, int offset = 0)
|
|
||||||
{
|
|
||||||
int size = Marshal.SizeOf(type);
|
|
||||||
IntPtr buffer = Marshal.AllocHGlobal(size);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Marshal.Copy(bytes, offset, buffer, size);
|
|
||||||
return (T)Marshal.PtrToStructure(buffer, type);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public byte[] StructToBytes(object structObject)
|
|
||||||
{
|
|
||||||
int size = Marshal.SizeOf(structObject);
|
|
||||||
IntPtr buffer = Marshal.AllocHGlobal(size);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Marshal.StructureToPtr(structObject, buffer, false);
|
|
||||||
byte[] bytes = new byte[size];
|
|
||||||
Marshal.Copy(buffer, bytes, 0, size);
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void PaddingAppend(ref byte[] b1, int paddinglen)
|
|
||||||
{
|
|
||||||
if (paddinglen > 0)
|
|
||||||
{
|
|
||||||
int l = b1.Length;
|
|
||||||
Array.Resize(ref b1, b1.Length + paddinglen);
|
|
||||||
for (; l < b1.Length; l++)
|
|
||||||
b1[l] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public bool ArraysEqual(Array a1, Array a2)
|
|
||||||
{
|
|
||||||
if (a1 == a2)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (a1 == null || a2 == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (a1.Length != a2.Length)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
System.Collections.IList list1 = a1, list2 = a2; //error CS0305: Using the generic type 'System.Collections.Generic.IList<T>' requires '1' type arguments
|
|
||||||
for (int i = 0; i < a1.Length; i++)
|
|
||||||
{
|
|
||||||
if (!Object.Equals(list1[i], list2[i])) //error CS0021: Cannot apply indexing with [] to an expression of type 'IList'(x2)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
//using System.Runtime.InteropServices;
|
|
||||||
using System.Management;
|
|
||||||
|
|
||||||
namespace MetroUnlocker
|
|
||||||
{
|
|
||||||
public class Rebooter
|
|
||||||
{
|
|
||||||
public enum RebootMethod
|
|
||||||
{
|
|
||||||
LogOff = 0,
|
|
||||||
PowerOff = 8,
|
|
||||||
Reboot = 2,
|
|
||||||
ShutDown = 1,
|
|
||||||
Suspend = -1,
|
|
||||||
Hibernate = -2
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Reboot(RebootMethod method = RebootMethod.Reboot)
|
|
||||||
{
|
|
||||||
ManagementClass management = new ManagementClass("Win32_OperatingSystem");
|
|
||||||
management.Scope.Options.EnablePrivileges = true;
|
|
||||||
ManagementBaseObject mboShutdownParams = management.GetMethodParameters("Win32Shutdown");
|
|
||||||
mboShutdownParams["Flags"] = method;
|
|
||||||
mboShutdownParams["Reserved"] = 0;
|
|
||||||
management.GetInstances().OfType<ManagementObject>().First().InvokeMethod("Win32Shutdown", mboShutdownParams, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Management;
|
|
||||||
|
|
||||||
namespace MetroUnlocker
|
|
||||||
{
|
|
||||||
enum SPPStartupMode
|
|
||||||
{
|
|
||||||
Disabled,
|
|
||||||
Enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
class SPPManager
|
|
||||||
{
|
|
||||||
private static string LogFullName = "C:\\Temp\\W8Sideloader.log";
|
|
||||||
|
|
||||||
private static string RunCommand(string command, string arguments)
|
|
||||||
{
|
|
||||||
string output;
|
|
||||||
RunCommand(command, arguments, out output);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RunCommand(string command, string arguments, out string output)
|
|
||||||
{
|
|
||||||
Process process = Process.Start(new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = command,
|
|
||||||
Arguments = arguments,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true
|
|
||||||
});
|
|
||||||
|
|
||||||
output = process.StandardOutput.ReadToEnd();
|
|
||||||
string error = process.StandardError.ReadToEnd();
|
|
||||||
if (!string.IsNullOrWhiteSpace(error)) throw new Exception(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string SetStartupMode(SPPStartupMode startupMode)
|
|
||||||
{
|
|
||||||
string output;
|
|
||||||
bool enabled = startupMode == SPPStartupMode.Enabled;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
RunCommand("sc", "sdset sppsvc D:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPLOCRRC;;;IU)(A;;CCLCSWRPLOCRRC;;;SU)(A;;LCRP;;;AU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)", out output);
|
|
||||||
//RunCommand("sc", "config sppsvc start=" + (enabled ? "enabled" : "disabled"), out output);
|
|
||||||
using (var m = new ManagementObject("Win32_Service.Name=\"sppsvc\""))
|
|
||||||
m.InvokeMethod("ChangeStartMode", new object[] { enabled ? "Automatic" : "Disabledx" });
|
|
||||||
|
|
||||||
RunCommand("net", "stop sppsvc", out output);
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
DisableScheduledTask("SvcRestartTask");
|
|
||||||
DisableScheduledTask("SvcRestartTaskLogon");
|
|
||||||
DisableScheduledTask("SvcRestartTaskNetwork");
|
|
||||||
}
|
|
||||||
|
|
||||||
//MessageBox.Show(output + "\n----------------------\n", "sppsvc config change");
|
|
||||||
}
|
|
||||||
catch { throw; }
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DisableScheduledTask(string key)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
RunCommand("schtasks", "/change /disable /tn \"\\Microsoft\\Windows\\SoftwareProtectionPlatform\\" + key + "\"");
|
|
||||||
}
|
|
||||||
catch { throw; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Disable()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return SetStartupMode(SPPStartupMode.Disabled);
|
|
||||||
}
|
|
||||||
catch { throw; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Enable()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return SetStartupMode(SPPStartupMode.Enabled);
|
|
||||||
}
|
|
||||||
catch { throw; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MetroUnlocker
|
|
||||||
{
|
|
||||||
public enum StartupArgument
|
|
||||||
{
|
|
||||||
EnableLOBAndEnableSPP,
|
|
||||||
EnableLOBAndDisableSPP,
|
|
||||||
DisableLOBAndEnableSPP,
|
|
||||||
DisableLOBAndDisableSPP,
|
|
||||||
Other
|
|
||||||
}
|
|
||||||
|
|
||||||
public class StartupArguments
|
|
||||||
{
|
|
||||||
|
|
||||||
public static Dictionary<StartupArgument, string> KnownArguments = new Dictionary<StartupArgument, string>()
|
|
||||||
{
|
|
||||||
{StartupArgument.EnableLOBAndEnableSPP, "hi"},
|
|
||||||
{StartupArgument.EnableLOBAndDisableSPP, "mister"},
|
|
||||||
{StartupArgument.DisableLOBAndEnableSPP, "fox"},
|
|
||||||
{StartupArgument.DisableLOBAndDisableSPP, ":3"},
|
|
||||||
};
|
|
||||||
|
|
||||||
public static StartupArgument GetStartupArgument(string[] args)
|
|
||||||
{
|
|
||||||
return KnownArguments.ContainsValue(args[1]) ? KnownArguments.First(arg => arg.Value == args[1]).Key : StartupArgument.Other;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetStartupArgumentString(StartupArgument startupArgument)
|
|
||||||
{
|
|
||||||
return KnownArguments[startupArgument];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasStartupArgument(string[] args)
|
|
||||||
{
|
|
||||||
return args.Length > 1 && !HasOtherArgument(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasOtherArgument(string[] args)
|
|
||||||
{
|
|
||||||
return GetStartupArgument(args) == StartupArgument.Other;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
21
README.md
21
README.md
@@ -1,11 +1,22 @@
|
|||||||
|

|
||||||
|
|
||||||
# MetroUnlocker
|
RTUnlocker is a fork of MetroUnlocker that transforms it into a simple .bat file that lets you enable sideloading on Windows RT
|
||||||
|
|
||||||
Unlock signed sideloading on:
|
Credits to [Iemand005](https://github.com/Iemand005) for MetroUnlocker and [Snoooopy](https://git.snoooopy.online/Snoooopy) for mirroring MetroUnlocker.
|
||||||
|
|
||||||
- Windows 8.0 and up
|
# What you will need to do:
|
||||||
|
Download source code (in a .zip), and exctract its contains onto a USB drive. Then plug it in your Windows RT device, and run RTUnlocker.bat as a administrator.
|
||||||
|
Once it opens, hit 1 to enable sideloading. It should take a couple of seconds, after it has enabled it, it will notify you and if you want to, you can hit L to see logs. Hit E to exit.
|
||||||
|
If you have sideloading unlocked already and you want to get rid of it, hit 2.
|
||||||
|
If you are not sure should you do it, just hit E to exit.
|
||||||
|
(we suggest getting goldenkeys and yahallo with tegra jailbreak usb im not sure if it will work without it)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
Unlock development sideloading on:
|
If you went here by accident thinking this is for Windows 8, not RT, get regular MetroUnlocker here:
|
||||||
|
[Mirrored MetroUnlocker repo](https://git.snoooopy.online/Snoooopy/MetroUnlocker) |
|
||||||
|
[Original MetroUnlocker repo](https://github.com/Iemand005/MetroUnlocker)
|
||||||
|
|
||||||
- Windows 8.1 Pro and up
|
You can find other stuff here, like guides how to install Linux, Tegra Jailbreak USB and much more!:
|
||||||
|
[Windows RT Devices Gitbook](https://windows-rt-devices.gitbook.io/windows) |
|
||||||
|
[Open Surface RT](https://open-rt.gitbook.io/open-surfacert)
|
||||||
BIN
banner.jpg
Normal file
BIN
banner.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Reference in New Issue
Block a user