diff --git a/MetroUnlocker.sln b/MetroUnlocker.sln index c0b7115..27f4dae 100644 --- a/MetroUnlocker.sln +++ b/MetroUnlocker.sln @@ -5,6 +5,11 @@ VisualStudioVersion = 12.0.40629.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetroUnlocker", "MetroUnlocker\MetroUnlocker.csproj", "{D27EB145-0B58-43AD-BB94-BE000D236D38}" 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 GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/MetroUnlocker/App.cs b/MetroUnlocker/App.cs index 341dcb3..e2ffcda 100644 --- a/MetroUnlocker/App.cs +++ b/MetroUnlocker/App.cs @@ -17,38 +17,38 @@ namespace MetroUnlocker { 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 developmentPolicyName = "AllowDevelopmentWithoutDevLicense"; - string specialProfilesPolicyName = "AllowDeploymentInSpecialProfiles"; + string TrustedAppsPolicyName = "AllowAllTrustedApps"; + string DevelopmentPolicyName = "AllowDevelopmentWithoutDevLicense"; + string SpecialProfilesPolicyName = "AllowDeploymentInSpecialProfiles"; public bool LOBEnabled { - get { return GetGroupPolicy(trustedAppsPolicyName); } - set { SetGroupPolicy(trustedAppsPolicyName, value); } + get { return GetGroupPolicy(TrustedAppsPolicyName); } + set { SetGroupPolicy(TrustedAppsPolicyName, value); } } public bool DevelopmentEnabled { - get { return GetGroupPolicy(developmentPolicyName); } - set { SetGroupPolicy(developmentPolicyName, value); } + get { return GetGroupPolicy(DevelopmentPolicyName); } + set { SetGroupPolicy(DevelopmentPolicyName, value); } } public bool SpecialProfilesEnabled { - get { return GetGroupPolicy(specialProfilesPolicyName); } - set { SetGroupPolicy(specialProfilesPolicyName, value); } + get { return GetGroupPolicy(SpecialProfilesPolicyName); } + set { SetGroupPolicy(SpecialProfilesPolicyName, value); } } 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) { - object value = Registry.GetValue(AppxKey, policyName, 0); + object value = Registry.GetValue(AppxRegistryKey, policyName, 0); return value is int ? (int)value == 1 : false; } diff --git a/MetroUnlocker/Common.cs b/MetroUnlocker/Common.cs index b506ecb..6f47853 100644 --- a/MetroUnlocker/Common.cs +++ b/MetroUnlocker/Common.cs @@ -45,9 +45,6 @@ namespace MetroUnlocker public static class Utils { - [DllImport("kernel32.dll")] - public static extern uint GetSystemDefaultLCID(); - public static string GetArchitecture() { string arch = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE", EnvironmentVariableTarget.Machine).ToUpperInvariant(); diff --git a/MetroUnlocker/LibTSForge/Crypto/CryptoUtils.cs b/MetroUnlocker/LibTSForge/Crypto/CryptoUtils.cs index 0615aa9..693c378 100644 --- a/MetroUnlocker/LibTSForge/Crypto/CryptoUtils.cs +++ b/MetroUnlocker/LibTSForge/Crypto/CryptoUtils.cs @@ -6,13 +6,13 @@ namespace MetroUnlocker.LibTSForge.Crypto { public static class CryptoUtils { - public static byte[] GenerateRandomKey(int len) + public static byte[] GenerateRandomKey(int length) { - byte[] rand = new byte[len]; - Random r = new Random(); - r.NextBytes(rand); + byte[] randomKey = new byte[length]; + Random random = new Random(); + random.NextBytes(randomKey); - return rand; + return randomKey; } public static byte[] AESEncrypt(byte[] data, byte[] key) diff --git a/MetroUnlocker/LibTSForge/Crypto/PhysicalStoreCrypto.cs b/MetroUnlocker/LibTSForge/Crypto/PhysicalStoreCrypto.cs index 523ca38..fcfc151 100644 --- a/MetroUnlocker/LibTSForge/Crypto/PhysicalStoreCrypto.cs +++ b/MetroUnlocker/LibTSForge/Crypto/PhysicalStoreCrypto.cs @@ -47,19 +47,19 @@ namespace MetroUnlocker.LibTSForge.Crypto byte[] aesKey = Encoding.UTF8.GetBytes("Boop Foxyz nose!"); byte[] hmacKey = CryptoUtils.GenerateRandomKey(0x10); - byte[] encAesKey = CryptoUtils.RSAEncrypt(rsaKey, aesKey); - byte[] aesKeySig = CryptoUtils.RSASign(rsaKey, encAesKey); - byte[] hmacSig = CryptoUtils.HMACSign(hmacKey, data); + byte[] encryptedAesKey = CryptoUtils.RSAEncrypt(rsaKey, aesKey); + byte[] aesKeySignature = CryptoUtils.RSASign(rsaKey, encryptedAesKey); + byte[] hmacSignature = CryptoUtils.HMACSign(hmacKey, data); 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); BinaryWriter bw = new BinaryWriter(new MemoryStream()); bw.Write(versionTable[version]); bw.Write(Encoding.UTF8.GetBytes("UNTRUSTSTORE")); - bw.Write(aesKeySig); - bw.Write(encAesKey); + bw.Write(aesKeySignature); + bw.Write(encryptedAesKey); bw.Write(encData); return bw.GetBytes(); diff --git a/MetroUnlocker/LibTSForge/Modifiers/ProductKeyInstaller.cs b/MetroUnlocker/LibTSForge/Modifiers/ProductKeyInstaller.cs index 859f04b..771b595 100644 --- a/MetroUnlocker/LibTSForge/Modifiers/ProductKeyInstaller.cs +++ b/MetroUnlocker/LibTSForge/Modifiers/ProductKeyInstaller.cs @@ -22,7 +22,7 @@ namespace MetroUnlocker.LibTSForge.Modifiers Guid instPkeyId = SLApi.GetInstalledProductKeyId(actId); if (instPkeyId != Guid.Empty) SLApi.UninstallProductKey(instPkeyId); - if (pkey.Algorithm != PKeyAlgorithm.PKEY2009) + if (pkey.Algorithm != ProductKeyAlgorithm.ProductKey2009) throw new Exception("The key algorithm isn't 2009"); uint status = SLApi.InstallProductKey(pkey); diff --git a/MetroUnlocker/LibTSForge/PhysicalStore/PhysicalStore.cs b/MetroUnlocker/LibTSForge/PhysicalStore/PhysicalStore.cs index eb053bb..e861902 100644 --- a/MetroUnlocker/LibTSForge/PhysicalStore/PhysicalStore.cs +++ b/MetroUnlocker/LibTSForge/PhysicalStore/PhysicalStore.cs @@ -90,92 +90,33 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore public void AddBlocks(IEnumerable blocks) { - foreach (ModernBlock block in blocks) - { - AddBlock(block); - } + foreach (ModernBlock block in blocks) AddBlock(block); } public ModernBlock GetBlock(string key, string value) { - List blocks = Data[key]; - - foreach (ModernBlock block in blocks) - { - if (block.ValueAsString == value) - { - return new ModernBlock - { - Type = block.Type, - Flags = block.Flags, - Key = Utils.EncodeString(key), - Value = block.Value, - Data = block.Data - }; - } - } - - return null; + if (!Data.ContainsKey(key)) return null; + return Data[key].Find(block => block.ValueAsString == value); } public ModernBlock GetBlock(string key, uint value) { - List blocks = Data[key]; - - foreach (ModernBlock block in blocks) - { - if (block.ValueAsInteger == value) - { - return new ModernBlock - { - Type = block.Type, - Flags = block.Flags, - Key = Utils.EncodeString(key), - Value = block.Value, - Data = block.Data - }; - } - } - - return null; + if (!Data.ContainsKey(key)) return null; + return Data[key].Find(block => block.ValueAsInteger == value); } public void SetBlock(string key, string value, byte[] data) { - List blocks = Data[key]; - - for (int i = 0; i < blocks.Count; i++) - { - ModernBlock block = blocks[i]; - - if (block.ValueAsString == value) - { - block.Data = data; - blocks[i] = block; - break; - } - } - - Data[key] = blocks; + if (!Data.ContainsKey(key)) return; + int index = Data[key].FindIndex(block => block.ValueAsString == value); + Data[key][index].Data = data; } public void SetBlock(string key, uint value, byte[] data) { - List blocks = Data[key]; - - for (int i = 0; i < blocks.Count; i++) - { - ModernBlock block = blocks[i]; - - if (block.ValueAsInteger == value) - { - block.Data = data; - blocks[i] = block; - break; - } - } - - Data[key] = blocks; + if (!Data.ContainsKey(key)) return; + int index = Data[key].FindIndex(block => block.ValueAsInteger == value); + Data[key][index].Data = data; } public void SetBlock(string key, string value, string data) @@ -200,40 +141,12 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore public void DeleteBlock(string key, string value) { - if (Data.ContainsKey(key)) - { - List blocks = Data[key]; - - foreach (ModernBlock block in blocks) - { - if (block.ValueAsString == value) - { - blocks.Remove(block); - break; - } - } - - Data[key] = blocks; - } + Data[key].Remove(GetBlock(key, value)); } public void DeleteBlock(string key, uint value) { - if (Data.ContainsKey(key)) - { - List blocks = Data[key]; - - foreach (ModernBlock block in blocks) - { - if (block.ValueAsInteger == value) - { - blocks.Remove(block); - break; - } - } - - Data[key] = blocks; - } + Data[key].Remove(GetBlock(key, value)); } public static string GetPath() diff --git a/MetroUnlocker/LibTSForge/SPP/NativeMethods.cs b/MetroUnlocker/LibTSForge/SPP/NativeMethods.cs new file mode 100644 index 0000000..f96144f --- /dev/null +++ b/MetroUnlocker/LibTSForge/SPP/NativeMethods.cs @@ -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); + } +} diff --git a/MetroUnlocker/LibTSForge/SPP/ProductKey.cs b/MetroUnlocker/LibTSForge/SPP/ProductKey.cs index efb8bd1..8aab2af 100644 --- a/MetroUnlocker/LibTSForge/SPP/ProductKey.cs +++ b/MetroUnlocker/LibTSForge/SPP/ProductKey.cs @@ -22,7 +22,7 @@ namespace MetroUnlocker.LibTSForge.SPP public int Serial; public ulong Security; public bool Upgrade; - public PKeyAlgorithm Algorithm; + public ProductKeyAlgorithm Algorithm; public string EulaType; public string PartNumber; public string Edition; @@ -37,7 +37,7 @@ namespace MetroUnlocker.LibTSForge.SPP 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; Serial = serial; @@ -60,7 +60,7 @@ namespace MetroUnlocker.LibTSForge.SPP 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() @@ -137,7 +137,7 @@ namespace MetroUnlocker.LibTSForge.SPP pid2 = ""; - if (Algorithm == PKeyAlgorithm.PKEY2005) + if (Algorithm == ProductKeyAlgorithm.ProductKey2005) { string mpc = GetMPC(); string serialHigh; @@ -211,7 +211,7 @@ namespace MetroUnlocker.LibTSForge.SPP int serialHigh = Serial / 1000000; int serialLow = Serial % 1000000; int licenseType; - uint lcid = Utils.GetSystemDefaultLCID(); + uint lcid = NativeMethods.GetSystemDefaultLCID(); int build = Environment.OSVersion.Version.Build; int dayOfYear = DateTime.Now.DayOfYear; int year = DateTime.Now.Year; @@ -266,7 +266,7 @@ namespace MetroUnlocker.LibTSForge.SPP string keyStr = ""; Random rnd = new Random(Group * 1000000000 + Serial); - if (Algorithm == PKeyAlgorithm.PKEY2005) + if (Algorithm == ProductKeyAlgorithm.ProductKey2005) { keyStr = "H4X3DH4X3DH4X3DH4X3D"; @@ -275,7 +275,7 @@ namespace MetroUnlocker.LibTSForge.SPP keyStr += ALPHABET[rnd.Next(24)]; } } - else if (Algorithm == PKeyAlgorithm.PKEY2009) + else if (Algorithm == ProductKeyAlgorithm.ProductKey2009) { int last = 0; byte[] bKey = KeyBytes; diff --git a/MetroUnlocker/LibTSForge/SPP/PKeyConfig.cs b/MetroUnlocker/LibTSForge/SPP/ProductKeyConfig.cs similarity index 65% rename from MetroUnlocker/LibTSForge/SPP/PKeyConfig.cs rename to MetroUnlocker/LibTSForge/SPP/ProductKeyConfig.cs index 1f56655..25ceb5b 100644 --- a/MetroUnlocker/LibTSForge/SPP/PKeyConfig.cs +++ b/MetroUnlocker/LibTSForge/SPP/ProductKeyConfig.cs @@ -9,10 +9,10 @@ using System.Xml; namespace MetroUnlocker.LibTSForge.SPP { - public enum PKeyAlgorithm + public enum ProductKeyAlgorithm { - PKEY2005, - PKEY2009 + ProductKey2005, + ProductKey2009 } public class KeyRange @@ -23,10 +23,7 @@ namespace MetroUnlocker.LibTSForge.SPP public string PartNumber; public bool Valid; - public bool Contains(int n) - { - return Start <= n && End <= n; - } + public bool Contains(int n) { return Start <= n && End <= n; } } public class ProductConfig @@ -36,39 +33,33 @@ namespace MetroUnlocker.LibTSForge.SPP public string Description; public string Channel; public bool Randomized; - public PKeyAlgorithm Algorithm; + public ProductKeyAlgorithm Algorithm; public List Ranges; public Guid ActivationId; - private List GetPkeyRanges() + private List GetProductKeyRanges() { if (Ranges.Count == 0) - { throw new ArgumentException("No key ranges."); - } - if (Algorithm == PKeyAlgorithm.PKEY2005) - { + if (Algorithm == ProductKeyAlgorithm.ProductKey2005) return Ranges; - } - List FilteredRanges = Ranges.Where(r => !r.EulaType.Contains("WAU")).ToList(); + List FilteredRanges = Ranges.FindAll(r => !r.EulaType.Contains("WAU")); 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."); - } - + return FilteredRanges; } public ProductKey GetRandomKey() { - List KeyRanges = GetPkeyRanges(); - Random rnd = new Random(); + List KeyRanges = GetProductKeyRanges(); + Random random = new Random(); - KeyRange range = KeyRanges[rnd.Next(KeyRanges.Count)]; - int serial = rnd.Next(range.Start, range.End); + KeyRange range = KeyRanges[random.Next(KeyRanges.Count)]; + int serial = random.Next(range.Start, range.End); return new ProductKey(serial, 0, false, Algorithm, this, range); } @@ -77,29 +68,32 @@ namespace MetroUnlocker.LibTSForge.SPP public class ProductKeyConfig { public Dictionary Products = new Dictionary(); - private List loadedPkeyConfigs = new List(); + private List _loadedProductKeyConfigs = new List(); public void LoadConfig(Guid actId) { 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(); lic.Load(tr); XmlNamespaceManager nsmgr = new XmlNamespaceManager(lic.NameTable); 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"); 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)); } @@ -114,13 +108,13 @@ namespace MetroUnlocker.LibTSForge.SPP XmlNodeList rangeNodes = lic.SelectNodes("//p:ProductKeyConfiguration/p:KeyRanges/p:KeyRange", nsmgr); XmlNodeList pubKeyNodes = lic.SelectNodes("//p:ProductKeyConfiguration/p:PublicKeys/p:PublicKey", nsmgr); - Dictionary algorithms = new Dictionary(); + Dictionary algorithms = new Dictionary(); Dictionary> ranges = new Dictionary>(); - Dictionary algoConv = new Dictionary + Dictionary algoConv = new Dictionary { - { "msft:rm/algorithm/pkey/2005", PKeyAlgorithm.PKEY2005 }, - { "msft:rm/algorithm/pkey/2009", PKeyAlgorithm.PKEY2009 } + { "msft:rm/algorithm/pkey/2005", ProductKeyAlgorithm.ProductKey2005 }, + { "msft:rm/algorithm/pkey/2009", ProductKeyAlgorithm.ProductKey2009 } }; foreach (XmlNode pubKeyNode in pubKeyNodes) @@ -131,12 +125,10 @@ namespace MetroUnlocker.LibTSForge.SPP 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)) - { - ranges[refActIdStr] = new List(); - } + if (!ranges.ContainsKey(refActIdString)) + ranges[refActIdString] = new List(); KeyRange keyRange = new KeyRange(); 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.Valid = rangeNode.SelectSingleNode("./p:IsValid", nsmgr).InnerText.ToLower() == "true"; - ranges[refActIdStr].Add(keyRange); + ranges[refActIdString].Add(keyRange); } foreach (XmlNode configNode in configNodes) { - string refActIdStr = configNode.SelectSingleNode("./p:ActConfigId", nsmgr).InnerText; - Guid refActId = new Guid(refActIdStr); + string refActIdString = configNode.SelectSingleNode("./p:ActConfigId", nsmgr).InnerText; + Guid refActId = new Guid(refActIdString); int group = int.Parse(configNode.SelectSingleNode("./p:RefGroupId", nsmgr).InnerText); - List keyRanges = ranges[refActIdStr]; + List keyRanges = ranges[refActIdString]; 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) - { - if (config.GroupId == group) - { - 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 ProductKeyConfig() - { - + 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."); + return matchingConfig; } } } diff --git a/MetroUnlocker/LibTSForge/SPP/SLAPI.cs b/MetroUnlocker/LibTSForge/SPP/SLAPI.cs index fb404ba..1e2be58 100644 --- a/MetroUnlocker/LibTSForge/SPP/SLAPI.cs +++ b/MetroUnlocker/LibTSForge/SPP/SLAPI.cs @@ -3,142 +3,42 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; -using System.Text; namespace MetroUnlocker.LibTSForge.SPP { public static class SLApi { - private enum SLIDType - { - SLIDApplication, - SLIDProductSku, - SLIDLicenseFile, - SLIDLicense, - 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 SLLicensingStatus - { - public Guid SkuId; - public uint eStatus; - public uint dwGraceTime; - public uint dwTotalGraceDays; - public uint hrReason; - public ulong qwValidityExpiration; - } - - [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 readonly IntPtr Handle; - public SLContext() - { - SLOpen(out Handle); - } + public SLContext() { NativeMethods.SLOpen(out Handle); } public void Dispose() { - SLClose(Handle); + NativeMethods.SLClose(Handle); GC.SuppressFinalize(this); } - ~SLContext() - { - Dispose(); - } + ~SLContext() { Dispose(); } } - public static Guid GetPkeyConfigFileId(Guid actId) + public static Guid GetProductKeyConfigFileId(Guid activationId) { using (SLContext sl = new SLContext()) { SLDataType type; - uint len; - IntPtr ppReturnLics; + uint length; + 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; - } - Guid pkcId = new Guid(Marshal.PtrToStringAuto(ppReturnLics)); - return GetLicenseFileId(pkcId); + Guid configLicenseId = new Guid(Marshal.PtrToStringAuto(fileIdPointer)); + return GetLicenseFileId(configLicenseId); } } @@ -150,9 +50,9 @@ namespace MetroUnlocker.LibTSForge.SPP uint count; IntPtr returnLicenses; - status = SLGetSLIDList(sl.Handle, SLIDType.SLIDLicense, ref licenseId, SLIDType.SLIDLicenseFile, out count, out returnLicenses); + status = NativeMethods.SLGetSLIDList(sl.Handle, SLIDType.License, ref licenseId, SLIDType.LicenseFile, out count, out returnLicenses); - return (status == 0 && count != 0) ? (Guid)Marshal.PtrToStructure(returnLicenses, typeof(Guid)) : Guid.Empty;//new Guid(Marshal.PtrToStringAuto(returnLicenses)); + return (status == 0 && count != 0) ? (Guid)Marshal.PtrToStructure(returnLicenses, typeof(Guid)) : Guid.Empty; } } @@ -162,14 +62,14 @@ namespace MetroUnlocker.LibTSForge.SPP using (SLContext sl = new SLContext()) { - uint dataLen; - IntPtr dataPtr; + uint length; + 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; - byte[] data = new byte[dataLen]; - Marshal.Copy(dataPtr, data, 0, (int)dataLen); + byte[] data = new byte[length]; + Marshal.Copy(dataPointer, data, 0, (int)length); data = data.Skip(Array.IndexOf(data, (byte)'<')).ToArray(); return Encoding.UTF8.GetString(data); @@ -184,9 +84,9 @@ namespace MetroUnlocker.LibTSForge.SPP SLDataType type; IntPtr binaryValue; - uint status = SLGetProductSkuInformation(sl.Handle, ref productSkuId, value, out type, out length, out binaryValue); + uint status = NativeMethods.SLGetProductSkuInformation(sl.Handle, ref productSkuId, value, out type, out length, out binaryValue); - if (status != 0 || length == 0 || type != SLDataType.SL_DATA_SZ) + if (status != 0 || length == 0 || type != SLDataType.String) return null; return Marshal.PtrToStringAuto(binaryValue); @@ -198,7 +98,7 @@ namespace MetroUnlocker.LibTSForge.SPP using (SLContext sl = new SLContext()) { 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) 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"))); @@ -215,7 +115,7 @@ namespace MetroUnlocker.LibTSForge.SPP uint count; IntPtr productKeyIds; - status = SLGetInstalledProductKeyIds(sl.Handle, ref actId, out count, out productKeyIds); + status = NativeMethods.SLGetInstalledProductKeyIds(sl.Handle, ref actId, out count, out productKeyIds); return (status == 0 && count != 0) ? (Guid)Marshal.PtrToStructure(productKeyIds, typeof(Guid)) : Guid.Empty; } @@ -224,12 +124,12 @@ namespace MetroUnlocker.LibTSForge.SPP public static uint DepositConfirmationId(Guid actId, string installationId, string confirmationId) { 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() { - SLConsumeWindowsRight(0); + NativeMethods.SLConsumeWindowsRight(0); } public static bool RefreshTrustedTime(Guid actId) @@ -240,7 +140,7 @@ namespace MetroUnlocker.LibTSForge.SPP uint count; 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; } } @@ -248,22 +148,22 @@ namespace MetroUnlocker.LibTSForge.SPP public static void FireStateChangedEvent(Guid appId) { using (SLContext sl = new SLContext()) - SLFireEvent(sl.Handle, "msft:rm/event/licensingstatechanged", ref appId); + NativeMethods.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()) { uint count; - IntPtr pAppIds; + IntPtr appIdPointer; - uint status = SLGetSLIDList(sl.Handle, SLIDType.SLIDProductSku, ref actId, SLIDType.SLIDApplication, 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) return Guid.Empty; - return (Guid)Marshal.PtrToStructure(pAppIds, typeof(Guid)); + return (Guid)Marshal.PtrToStructure(appIdPointer, typeof(Guid)); } } @@ -275,7 +175,7 @@ namespace MetroUnlocker.LibTSForge.SPP SLDataType type; 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; } } @@ -284,15 +184,15 @@ namespace MetroUnlocker.LibTSForge.SPP { using (SLContext sl = new SLContext()) { - Guid pkeyId = Guid.Empty; - return SLInstallProofOfPurchase(sl.Handle, pkey.GetAlgoUri(), pkey.ToString(), 0, null, ref pkeyId); + Guid productKeyId = Guid.Empty; + 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()) - return SLUninstallProofOfPurchase(sl.Handle, ref pkeyId); + return NativeMethods.SLUninstallProofOfPurchase(sl.Handle, ref productKeyId); } } } diff --git a/MetroUnlocker/MetroUnlocker.csproj b/MetroUnlocker/MetroUnlocker.csproj index 6f3d686..d413817 100644 --- a/MetroUnlocker/MetroUnlocker.csproj +++ b/MetroUnlocker/MetroUnlocker.csproj @@ -67,7 +67,8 @@ - + +