mirror of
https://github.com/Iemand005/MetroUnlocker.git
synced 2026-04-11 17:37:21 +10:00
Refactor and cleanup
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
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 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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user