Archived
1
1

Refactor and cleanup

This commit is contained in:
Mona Lassa
2025-05-22 02:52:38 +02:00
parent f90695dfda
commit 5ae6b4da9a
12 changed files with 215 additions and 333 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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)

View File

@@ -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();

View File

@@ -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);

View File

@@ -90,92 +90,33 @@ namespace MetroUnlocker.LibTSForge.PhysicalStore
public void AddBlocks(IEnumerable<ModernBlock> blocks)
{
foreach (ModernBlock block in blocks)
{
AddBlock(block);
}
foreach (ModernBlock block in blocks) AddBlock(block);
}
public ModernBlock GetBlock(string key, string value)
{
List<ModernBlock> 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<ModernBlock> 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<ModernBlock> 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<ModernBlock> 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<ModernBlock> 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<ModernBlock> 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()

View 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);
}
}

View File

@@ -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;

View File

@@ -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<KeyRange> Ranges;
public Guid ActivationId;
private List<KeyRange> GetPkeyRanges()
private List<KeyRange> GetProductKeyRanges()
{
if (Ranges.Count == 0)
{
throw new ArgumentException("No key ranges.");
}
if (Algorithm == PKeyAlgorithm.PKEY2005)
{
if (Algorithm == ProductKeyAlgorithm.ProductKey2005)
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)
{
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<KeyRange> KeyRanges = GetPkeyRanges();
Random rnd = new Random();
List<KeyRange> 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<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)
{
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<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, 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/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<KeyRange>();
}
if (!ranges.ContainsKey(refActIdString))
ranges[refActIdString] = new List<KeyRange>();
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<KeyRange> keyRanges = ranges[refActIdStr];
List<KeyRange> 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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -67,7 +67,8 @@
<Compile Include="LibTSForge\PhysicalStore\ModernBlock.cs" />
<Compile Include="LibTSForge\PhysicalStore\PhysicalStore.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\SLApi.cs" />
<Compile Include="LibTSForge\TokenStore\TokenEntry.cs" />