Initial commit

Co-authored-by: neko <109633131+nekoppai@users.noreply.github.com>
Co-authored-by: Lyssa <75037904+thecatontheceiling@users.noreply.github.com>
Co-authored-by: abbodi1406 <33669284+abbodi1406@users.noreply.github.com>
This commit is contained in:
2025-02-13 09:49:35 -05:00
commit 0d59561bee
36 changed files with 5712 additions and 0 deletions

View File

@ -0,0 +1,215 @@
namespace LibTSforge.SPP
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
public enum PKeyAlgorithm
{
PKEY2005,
PKEY2009
}
public class KeyRange
{
public int Start;
public int End;
public string EulaType;
public string PartNumber;
public bool Valid;
public bool Contains(int n)
{
return Start <= n && End <= n;
}
}
public class ProductConfig
{
public int GroupId;
public string Edition;
public string Description;
public string Channel;
public bool Randomized;
public PKeyAlgorithm Algorithm;
public List<KeyRange> Ranges;
public Guid ActivationId;
private List<KeyRange> GetPkeyRanges()
{
if (Ranges.Count == 0)
{
throw new ArgumentException("No key ranges.");
}
if (Algorithm == PKeyAlgorithm.PKEY2005)
{
return Ranges;
}
List<KeyRange> FilteredRanges = Ranges.Where(r => !r.EulaType.Contains("WAU")).ToList();
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();
KeyRange range = KeyRanges[rnd.Next(KeyRanges.Count)];
int serial = rnd.Next(range.Start, range.End);
return new ProductKey(serial, 0, false, Algorithm, this, range);
}
}
public class PKeyConfig
{
public Dictionary<Guid, ProductConfig> Products = new Dictionary<Guid, ProductConfig>();
private List<Guid> loadedPkeyConfigs = new List<Guid>();
public void LoadConfig(Guid actId)
{
string pkcData;
Guid pkcFileId = SLApi.GetPkeyConfigFileId(actId);
if (loadedPkeyConfigs.Contains(pkcFileId)) return;
string licConts = SLApi.GetLicenseContents(pkcFileId);
using (TextReader tr = new StringReader(licConts))
{
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("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);
pkcData = Encoding.UTF8.GetString(Convert.FromBase64String(pkcDataNode.InnerText));
}
using (TextReader tr = new StringReader(pkcData))
{
XmlDocument lic = new XmlDocument();
lic.Load(tr);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(lic.NameTable);
nsmgr.AddNamespace("p", "http://www.microsoft.com/DRM/PKEY/Configuration/2.0");
XmlNodeList configNodes = lic.SelectNodes("//p:ProductKeyConfiguration/p:Configurations/p:Configuration", nsmgr);
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<string, List<KeyRange>> ranges = new Dictionary<string, List<KeyRange>>();
Dictionary<string, PKeyAlgorithm> algoConv = new Dictionary<string, PKeyAlgorithm>
{
{ "msft:rm/algorithm/pkey/2005", PKeyAlgorithm.PKEY2005 },
{ "msft:rm/algorithm/pkey/2009", PKeyAlgorithm.PKEY2009 }
};
foreach (XmlNode pubKeyNode in pubKeyNodes)
{
int group = int.Parse(pubKeyNode.SelectSingleNode("./p:GroupId", nsmgr).InnerText);
algorithms[group] = algoConv[pubKeyNode.SelectSingleNode("./p:AlgorithmId", nsmgr).InnerText];
}
foreach (XmlNode rangeNode in rangeNodes)
{
string refActIdStr = rangeNode.SelectSingleNode("./p:RefActConfigId", nsmgr).InnerText;
if (!ranges.ContainsKey(refActIdStr))
{
ranges[refActIdStr] = new List<KeyRange>();
}
KeyRange keyRange = new KeyRange();
keyRange.Start = int.Parse(rangeNode.SelectSingleNode("./p:Start", nsmgr).InnerText);
keyRange.End = int.Parse(rangeNode.SelectSingleNode("./p:End", nsmgr).InnerText);
keyRange.EulaType = rangeNode.SelectSingleNode("./p:EulaType", nsmgr).InnerText;
keyRange.PartNumber = rangeNode.SelectSingleNode("./p:PartNumber", nsmgr).InnerText;
keyRange.Valid = rangeNode.SelectSingleNode("./p:IsValid", nsmgr).InnerText.ToLower() == "true";
ranges[refActIdStr].Add(keyRange);
}
foreach (XmlNode configNode in configNodes)
{
string refActIdStr = configNode.SelectSingleNode("./p:ActConfigId", nsmgr).InnerText;
Guid refActId = new Guid(refActIdStr);
int group = int.Parse(configNode.SelectSingleNode("./p:RefGroupId", nsmgr).InnerText);
List<KeyRange> keyRanges = ranges[refActIdStr];
if (keyRanges.Count > 0 && !Products.ContainsKey(refActId))
{
ProductConfig productConfig = new ProductConfig();
productConfig.GroupId = group;
productConfig.Edition = configNode.SelectSingleNode("./p:EditionId", nsmgr).InnerText;
productConfig.Description = configNode.SelectSingleNode("./p:ProductDescription", nsmgr).InnerText;
productConfig.Channel = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText;
productConfig.Randomized = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText.ToLower() == "true";
productConfig.Algorithm = algorithms[group];
productConfig.Ranges = keyRanges;
productConfig.ActivationId = refActId;
Products[refActId] = productConfig;
}
}
}
loadedPkeyConfigs.Add(pkcFileId);
}
public ProductConfig MatchParams(int group, 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 void LoadAllConfigs(Guid appId)
{
foreach (Guid actId in SLApi.GetActivationIds(appId))
{
try
{
LoadConfig(actId);
}
catch (ArgumentException)
{
}
}
}
public PKeyConfig()
{
}
}
}

View File

@ -0,0 +1,313 @@
namespace LibTSforge.SPP
{
using System;
using System.IO;
using System.Linq;
using LibTSforge.Crypto;
using LibTSforge.PhysicalStore;
public class ProductKey
{
private static readonly string ALPHABET = "BCDFGHJKMPQRTVWXY2346789";
private readonly ulong klow;
private readonly ulong khigh;
public int Group;
public int Serial;
public ulong Security;
public bool Upgrade;
public PKeyAlgorithm Algorithm;
public string EulaType;
public string PartNumber;
public string Edition;
public string Channel;
public Guid ActivationId;
private string mpc;
private string pid2;
public byte[] KeyBytes
{
get { return BitConverter.GetBytes(klow).Concat(BitConverter.GetBytes(khigh)).ToArray(); }
}
public ProductKey(int serial, ulong security, bool upgrade, PKeyAlgorithm algorithm, ProductConfig config, KeyRange range)
{
Group = config.GroupId;
Serial = serial;
Security = security;
Upgrade = upgrade;
Algorithm = algorithm;
EulaType = range.EulaType;
PartNumber = range.PartNumber.Split(':', ';')[0];
Edition = config.Edition;
Channel = config.Channel;
ActivationId = config.ActivationId;
klow = ((security & 0x3fff) << 50 | ((ulong)serial & 0x3fffffff) << 20 | ((ulong)Group & 0xfffff));
khigh = ((upgrade ? (ulong)1 : 0) << 49 | ((security >> 14) & 0x7fffffffff));
uint checksum = Utils.CRC32(KeyBytes) & 0x3ff;
khigh |= ((ulong)checksum << 39);
}
public string GetAlgoUri()
{
return "msft:rm/algorithm/pkey/" + (Algorithm == PKeyAlgorithm.PKEY2005 ? "2005" : (Algorithm == PKeyAlgorithm.PKEY2009 ? "2009" : "Unknown"));
}
public Guid GetPkeyId()
{
VariableBag pkb = new VariableBag();
pkb.Blocks.AddRange(new CRCBlock[]
{
new CRCBlock
{
DataType = CRCBlockType.STRING,
KeyAsStr = "SppPkeyBindingProductKey",
ValueAsStr = ToString()
},
new CRCBlock
{
DataType = CRCBlockType.BINARY,
KeyAsStr = "SppPkeyBindingMiscData",
Value = new byte[] { }
},
new CRCBlock
{
DataType = CRCBlockType.STRING,
KeyAsStr = "SppPkeyBindingAlgorithm",
ValueAsStr = GetAlgoUri()
}
});
return new Guid(CryptoUtils.SHA256Hash(pkb.Serialize()).Take(16).ToArray());
}
public string GetDefaultMPC()
{
int build = Environment.OSVersion.Version.Build;
string defaultMPC = build >= 10240 ? "03612" :
build >= 9600 ? "06401" :
build >= 9200 ? "05426" :
"55041";
return defaultMPC;
}
public string GetMPC()
{
if (mpc != null)
{
return mpc;
}
mpc = GetDefaultMPC();
// setup.cfg doesn't exist in Windows 8+
string setupcfg = string.Format("{0}\\oobe\\{1}", Environment.SystemDirectory, "setup.cfg");
if (!File.Exists(setupcfg) || Edition.Contains(";"))
{
return mpc;
}
string mpcKey = string.Format("{0}.{1}=", Utils.GetArchitecture(), Edition);
string localMPC = File.ReadAllLines(setupcfg).FirstOrDefault(line => line.Contains(mpcKey));
if (localMPC != null)
{
mpc = localMPC.Split('=')[1].Trim();
}
return mpc;
}
public string GetPid2()
{
if (pid2 != null)
{
return pid2;
}
pid2 = "";
if (Algorithm == PKeyAlgorithm.PKEY2005)
{
string mpc = GetMPC();
string serialHigh;
int serialLow;
int lastPart;
if (EulaType == "OEM")
{
serialHigh = "OEM";
serialLow = ((Group / 2) % 100) * 10000 + (Serial / 100000);
lastPart = Serial % 100000;
}
else
{
serialHigh = (Serial / 1000000).ToString("D3");
serialLow = Serial % 1000000;
lastPart = ((Group / 2) % 100) * 1000 + new Random().Next(1000);
}
int checksum = 0;
foreach (char c in serialLow.ToString())
{
checksum += int.Parse(c.ToString());
}
checksum = 7 - (checksum % 7);
pid2 = string.Format("{0}-{1}-{2:D6}{3}-{4:D5}", mpc, serialHigh, serialLow, checksum, lastPart);
}
return pid2;
}
public byte[] GetPid3()
{
BinaryWriter writer = new BinaryWriter(new MemoryStream());
writer.Write(0xA4);
writer.Write(0x3);
writer.WriteFixedString(GetPid2(), 24);
writer.Write(Group);
writer.WriteFixedString(PartNumber, 16);
writer.WritePadding(0x6C);
byte[] data = writer.GetBytes();
byte[] crc = BitConverter.GetBytes(~Utils.CRC32(data.Reverse().ToArray())).Reverse().ToArray();
writer.Write(crc);
return writer.GetBytes();
}
public byte[] GetPid4()
{
BinaryWriter writer = new BinaryWriter(new MemoryStream());
writer.Write(0x4F8);
writer.Write(0x4);
writer.WriteFixedString16(GetExtendedPid(), 0x80);
writer.WriteFixedString16(ActivationId.ToString(), 0x80);
writer.WritePadding(0x10);
writer.WriteFixedString16(Edition, 0x208);
writer.Write(Upgrade ? (ulong)1 : 0);
writer.WritePadding(0x50);
writer.WriteFixedString16(PartNumber, 0x80);
writer.WriteFixedString16(Channel, 0x80);
writer.WriteFixedString16(EulaType, 0x80);
return writer.GetBytes();
}
public string GetExtendedPid()
{
string mpc = GetMPC();
int serialHigh = Serial / 1000000;
int serialLow = Serial % 1000000;
int licenseType;
uint lcid = Utils.GetSystemDefaultLCID();
int build = Environment.OSVersion.Version.Build;
int dayOfYear = DateTime.Now.DayOfYear;
int year = DateTime.Now.Year;
switch (EulaType)
{
case "OEM":
licenseType = 2;
break;
case "Volume":
licenseType = 3;
break;
default:
licenseType = 0;
break;
}
return string.Format(
"{0}-{1:D5}-{2:D3}-{3:D6}-{4:D2}-{5:D4}-{6:D4}.0000-{7:D3}{8:D4}",
mpc,
Group,
serialHigh,
serialLow,
licenseType,
lcid,
build,
dayOfYear,
year
);
}
public byte[] GetPhoneData(PSVersion version)
{
if (version == PSVersion.Win7)
{
Random rnd = new Random(Group * 1000000000 + Serial);
byte[] data = new byte[8];
rnd.NextBytes(data);
return data;
}
int serialHigh = Serial / 1000000;
int serialLow = Serial % 1000000;
BinaryWriter writer = new BinaryWriter(new MemoryStream());
writer.Write(new Guid("B8731595-A2F6-430B-A799-FBFFB81A8D73").ToByteArray());
writer.Write(Group);
writer.Write(serialHigh);
writer.Write(serialLow);
writer.Write(Upgrade ? 1 : 0);
writer.Write(Security);
return writer.GetBytes();
}
public override string ToString()
{
string keyStr = "";
Random rnd = new Random(Group * 1000000000 + Serial);
if (Algorithm == PKeyAlgorithm.PKEY2005)
{
keyStr = "H4X3DH4X3DH4X3DH4X3D";
for (int i = 0; i < 5; i++)
{
keyStr += ALPHABET[rnd.Next(24)];
}
}
else if (Algorithm == PKeyAlgorithm.PKEY2009)
{
int last = 0;
byte[] bKey = KeyBytes;
for (int i = 24; i >= 0; i--)
{
int current = 0;
for (int j = 14; j >= 0; j--)
{
current *= 0x100;
current += bKey[j];
bKey[j] = (byte)(current / 24);
current %= 24;
last = current;
}
keyStr = ALPHABET[current] + keyStr;
}
keyStr = keyStr.Substring(1, last) + "N" + keyStr.Substring(last + 1, keyStr.Length - last - 1);
}
for (int i = 5; i < keyStr.Length; i += 6)
{
keyStr = keyStr.Insert(i, "-");
}
return keyStr;
}
}
}

417
LibTSforge/SPP/SLAPI.cs Normal file
View File

@ -0,0 +1,417 @@
namespace LibTSforge.SPP
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
public static class SLApi
{
private enum SLIDTYPE
{
SL_ID_APPLICATION,
SL_ID_PRODUCT_SKU,
SL_ID_LICENSE_FILE,
SL_ID_LICENSE,
SL_ID_PKEY,
SL_ID_ALL_LICENSES,
SL_ID_ALL_LICENSE_FILES,
SL_ID_STORE_TOKEN,
SL_ID_LAST
}
private enum SLDATATYPE
{
SL_DATA_NONE,
SL_DATA_SZ,
SL_DATA_DWORD,
SL_DATA_BINARY,
SL_DATA_MULTI_SZ,
SL_DATA_SUM
}
[StructLayout(LayoutKind.Sequential)]
private struct SL_LICENSING_STATUS
{
public Guid SkuId;
public uint eStatus;
public uint dwGraceTime;
public uint dwTotalGraceDays;
public uint hrReason;
public ulong qwValidityExpiration;
}
public static readonly Guid WINDOWS_APP_ID = new Guid("55c92734-d682-4d71-983e-d6ec3f16059f");
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void SLOpen(out IntPtr hSLC);
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void SLClose(IntPtr hSLC);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetWindowsInformationDWORD(string ValueName, ref int Value);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLInstallProofOfPurchase(IntPtr hSLC, string pwszPKeyAlgorithm, string pwszPKeyString, uint cbPKeySpecificData, byte[] pbPKeySpecificData, ref Guid PKeyId);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLUninstallProofOfPurchase(IntPtr hSLC, ref Guid PKeyId);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetPKeyInformation(IntPtr hSLC, ref Guid pPKeyId, string pwszValueName, out SLDATATYPE peDataType, out uint pcbValue, out IntPtr ppbValue);
[DllImport("sppcext.dll", CharSet = CharSet.Unicode)]
private static extern uint SLActivateProduct(IntPtr hSLC, ref Guid pProductSkuId, byte[] cbAppSpecificData, byte[] pvAppSpecificData, byte[] pActivationInfo, string pwszProxyServer, ushort wProxyPort);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGenerateOfflineInstallationId(IntPtr hSLC, ref Guid pProductSkuId, ref string ppwszInstallationId);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLDepositOfflineConfirmationId(IntPtr hSLC, ref Guid pProductSkuId, string pwszInstallationId, string pwszConfirmationId);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetSLIDList(IntPtr hSLC, SLIDTYPE eQueryIdType, ref Guid pQueryId, SLIDTYPE eReturnIdType, out uint pnReturnIds, out IntPtr ppReturnIds);
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void SLGetLicensingStatusInformation(IntPtr hSLC, ref Guid pAppID, IntPtr pProductSkuId, string pwszRightName, out uint pnStatusCount, out IntPtr ppLicensingStatus);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetInstalledProductKeyIds(IntPtr hSLC, ref Guid pProductSkuId, out uint pnProductKeyIds, out IntPtr ppProductKeyIds);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLConsumeWindowsRight(uint unknown);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, out SLDATATYPE peDataType, out uint pcbValue, out IntPtr ppbValue);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, IntPtr peDataType, out uint pcbValue, out IntPtr ppbValue);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetLicense(IntPtr hSLC, ref Guid pLicenseFileId, out uint pcbLicenseFile, out IntPtr ppbLicenseFile);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLSetCurrentProductKey(IntPtr hSLC, ref Guid pProductSkuId, ref Guid pProductKeyId);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLFireEvent(IntPtr hSLC, string pwszEventId, ref Guid pApplicationId);
public class SLContext : IDisposable
{
public readonly IntPtr Handle;
public SLContext()
{
SLOpen(out Handle);
}
public void Dispose()
{
SLClose(Handle);
GC.SuppressFinalize(this);
}
~SLContext()
{
Dispose();
}
}
public static Guid GetDefaultActivationID(Guid appId, bool includeActivated)
{
using (SLContext sl = new SLContext())
{
uint count;
IntPtr pLicStat;
SLGetLicensingStatusInformation(sl.Handle, ref appId, IntPtr.Zero, null, out count, out pLicStat);
unsafe
{
SL_LICENSING_STATUS* licensingStatuses = (SL_LICENSING_STATUS*)pLicStat;
for (int i = 0; i < count; i++)
{
SL_LICENSING_STATUS slStatus = licensingStatuses[i];
Guid actId = slStatus.SkuId;
if (GetInstalledPkeyID(actId) == Guid.Empty) continue;
if (IsAddon(actId)) continue;
if (!includeActivated && (slStatus.eStatus == 1)) continue;
return actId;
}
}
return Guid.Empty;
}
}
public static string GetInstallationID(Guid actId)
{
using (SLContext sl = new SLContext())
{
string installationId = null;
return SLGenerateOfflineInstallationId(sl.Handle, ref actId, ref installationId) == 0 ? installationId : null;
}
}
public static Guid GetInstalledPkeyID(Guid actId)
{
using (SLContext sl = new SLContext())
{
uint status;
uint count;
IntPtr pProductKeyIds;
status = SLGetInstalledProductKeyIds(sl.Handle, ref actId, out count, out pProductKeyIds);
if (status != 0 || count == 0)
{
return Guid.Empty;
}
unsafe { return *(Guid*)pProductKeyIds; }
}
}
public static uint DepositConfirmationID(Guid actId, string installationId, string confirmationId)
{
using (SLContext sl = new SLContext())
{
return SLDepositOfflineConfirmationId(sl.Handle, ref actId, installationId, confirmationId);
}
}
public static void RefreshLicenseStatus()
{
SLConsumeWindowsRight(0);
}
public static bool RefreshTrustedTime(Guid actId)
{
using (SLContext sl = new SLContext())
{
SLDATATYPE type;
uint count;
IntPtr ppbValue;
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "TrustedTime", out type, out count, out ppbValue);
return (int)status >= 0 && status != 0xC004F012;
}
}
public static void FireStateChangedEvent(Guid appId)
{
using (SLContext sl = new SLContext())
{
SLFireEvent(sl.Handle, "msft:rm/event/licensingstatechanged", ref appId);
}
}
public static Guid GetAppId(Guid actId)
{
using (SLContext sl = new SLContext())
{
uint status;
uint count;
IntPtr pAppIds;
status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_APPLICATION, out count, out pAppIds);
if (status != 0 || count == 0)
{
return Guid.Empty;
}
unsafe { return *(Guid*)pAppIds; }
}
}
public static bool IsAddon(Guid actId)
{
using (SLContext sl = new SLContext())
{
uint count;
SLDATATYPE type;
IntPtr ppbValue;
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "DependsOn", out type, out count, out ppbValue);
return (int)status >= 0 && status != 0xC004F012;
}
}
public static Guid GetLicenseFileId(Guid licId)
{
using (SLContext sl = new SLContext())
{
uint status;
uint count;
IntPtr ppReturnLics;
status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_LICENSE, ref licId, SLIDTYPE.SL_ID_LICENSE_FILE, out count, out ppReturnLics);
if (status != 0 || count == 0)
{
return Guid.Empty;
}
unsafe { return *(Guid*)ppReturnLics; }
}
}
public static Guid GetPkeyConfigFileId(Guid actId)
{
using (SLContext sl = new SLContext())
{
SLDATATYPE type;
uint len;
IntPtr ppReturnLics;
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "pkeyConfigLicenseId", out type, out len, out ppReturnLics);
if (status != 0 || len == 0)
{
return Guid.Empty;
}
Guid pkcId = new Guid(Marshal.PtrToStringAuto(ppReturnLics));
return GetLicenseFileId(pkcId);
}
}
public static string GetLicenseContents(Guid fileId)
{
if (fileId == Guid.Empty) throw new ArgumentException("License contents could not be retrieved.");
using (SLContext sl = new SLContext())
{
uint dataLen;
IntPtr dataPtr;
if (SLGetLicense(sl.Handle, ref fileId, out dataLen, out dataPtr) != 0)
{
return null;
}
byte[] data = new byte[dataLen];
Marshal.Copy(dataPtr, data, 0, (int)dataLen);
data = data.Skip(Array.IndexOf(data, (byte)'<')).ToArray();
return Encoding.UTF8.GetString(data);
}
}
public static bool IsPhoneActivatable(Guid actId)
{
using (SLContext sl = new SLContext())
{
uint count;
SLDATATYPE type;
IntPtr ppbValue;
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "msft:sl/EUL/PHONE/PUBLIC", out type, out count, out ppbValue);
return status >= 0 && status != 0xC004F012;
}
}
public static string GetPKeyChannel(Guid pkeyId)
{
using (SLContext sl = new SLContext())
{
SLDATATYPE type;
uint len;
IntPtr ppbValue;
uint status = SLGetPKeyInformation(sl.Handle, ref pkeyId, "Channel", out type, out len, out ppbValue);
if (status != 0 || len == 0)
{
return null;
}
return Marshal.PtrToStringAuto(ppbValue);
}
}
public static string GetMetaStr(Guid actId, string value)
{
using (SLContext sl = new SLContext())
{
uint len;
SLDATATYPE type;
IntPtr ppbValue;
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, value, out type, out len, out ppbValue);
if (status != 0 || len == 0 || type != SLDATATYPE.SL_DATA_SZ)
{
return null;
}
return Marshal.PtrToStringAuto(ppbValue);
}
}
public static List<Guid> GetActivationIds(Guid appId)
{
using (SLContext sl = new SLContext())
{
uint count;
IntPtr pLicStat;
SLGetLicensingStatusInformation(sl.Handle, ref appId, IntPtr.Zero, null, out count, out pLicStat);
List<Guid> result = new List<Guid>();
unsafe
{
SL_LICENSING_STATUS* licensingStatuses = (SL_LICENSING_STATUS*)pLicStat;
for (int i = 0; i < count; i++)
{
result.Add(licensingStatuses[i].SkuId);
}
}
return result;
}
}
public static uint SetCurrentProductKey(Guid actId, Guid pkeyId)
{
using (SLContext sl = new SLContext())
{
return SLSetCurrentProductKey(sl.Handle, ref actId, ref pkeyId);
}
}
public static uint InstallProductKey(ProductKey pkey)
{
using (SLContext sl = new SLContext())
{
Guid pkeyId = Guid.Empty;
return SLInstallProofOfPurchase(sl.Handle, pkey.GetAlgoUri(), pkey.ToString(), 0, null, ref pkeyId);
}
}
public static uint UninstallProductKey(Guid pkeyId)
{
using (SLContext sl = new SLContext())
{
return SLUninstallProofOfPurchase(sl.Handle, ref pkeyId);
}
}
public static void UninstallAllProductKeys(Guid appId)
{
foreach (Guid actId in GetActivationIds(appId))
{
Guid pkeyId = GetInstalledPkeyID(actId);
if (pkeyId == Guid.Empty) continue;
if (IsAddon(actId)) continue;
UninstallProductKey(pkeyId);
}
}
}
}