Add partial support (zcid, rtmr, non-functional kms4k) for vista
Co-authored-by: InvoxiPlayGames <22731889+InvoxiPlayGames@users.noreply.github.com>
This commit is contained in:
@ -60,22 +60,22 @@ namespace LibTSforge.SPP
|
||||
|
||||
public Guid GetPkeyId()
|
||||
{
|
||||
VariableBag pkb = new VariableBag();
|
||||
pkb.Blocks.AddRange(new CRCBlock[]
|
||||
VariableBag pkb = new VariableBag(PSVersion.WinModern);
|
||||
pkb.Blocks.AddRange(new CRCBlockModern[]
|
||||
{
|
||||
new CRCBlock
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.STRING,
|
||||
KeyAsStr = "SppPkeyBindingProductKey",
|
||||
ValueAsStr = ToString()
|
||||
},
|
||||
new CRCBlock
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.BINARY,
|
||||
KeyAsStr = "SppPkeyBindingMiscData",
|
||||
Value = new byte[] { }
|
||||
},
|
||||
new CRCBlock
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.STRING,
|
||||
KeyAsStr = "SppPkeyBindingAlgorithm",
|
||||
|
@ -44,40 +44,40 @@ namespace LibTSforge.SPP
|
||||
|
||||
public static readonly Guid WINDOWS_APP_ID = new Guid("55c92734-d682-4d71-983e-d6ec3f16059f");
|
||||
|
||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
||||
[DllImport("slc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
||||
private static extern void SLOpen(out IntPtr hSLC);
|
||||
|
||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
||||
[DllImport("slc.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)]
|
||||
[DllImport("slc.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)]
|
||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint SLUninstallProofOfPurchase(IntPtr hSLC, ref Guid PKeyId);
|
||||
|
||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||
[DllImport("slc.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)]
|
||||
[DllImport("slcext.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)]
|
||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint SLGenerateOfflineInstallationId(IntPtr hSLC, ref Guid pProductSkuId, ref string ppwszInstallationId);
|
||||
|
||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint SLDepositOfflineConfirmationId(IntPtr hSLC, ref Guid pProductSkuId, string pwszInstallationId, string pwszConfirmationId);
|
||||
|
||||
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
|
||||
[DllImport("slc.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)]
|
||||
[DllImport("slc.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)]
|
||||
[DllImport("slc.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)]
|
||||
|
275
LibTSforge/SPP/SPPUtils.cs
Normal file
275
LibTSforge/SPP/SPPUtils.cs
Normal file
@ -0,0 +1,275 @@
|
||||
namespace LibTSforge.SPP
|
||||
{
|
||||
using LibTSforge.Crypto;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge.TokenStore;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.ServiceProcess;
|
||||
using System.Text;
|
||||
|
||||
public static class SPPUtils
|
||||
{
|
||||
public static void KillSPP(PSVersion version)
|
||||
{
|
||||
ServiceController sc;
|
||||
|
||||
string svcName = version == PSVersion.Vista ? "slsvc" : "sppsvc";
|
||||
|
||||
try
|
||||
{
|
||||
sc = new ServiceController(svcName);
|
||||
|
||||
if (sc.Status == ServiceControllerStatus.Stopped)
|
||||
return;
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Unable to access {0}: ", svcName) + ex.Message);
|
||||
}
|
||||
|
||||
Logger.WriteLine(string.Format("Stopping {0}...", svcName));
|
||||
|
||||
bool stopped = false;
|
||||
|
||||
for (int i = 0; stopped == false && i < 360; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sc.Status != ServiceControllerStatus.StopPending)
|
||||
sc.Stop();
|
||||
|
||||
sc.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(500));
|
||||
}
|
||||
catch (System.ServiceProcess.TimeoutException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
System.Threading.Thread.Sleep(500);
|
||||
continue;
|
||||
}
|
||||
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
if (!stopped)
|
||||
throw new System.TimeoutException(string.Format("Failed to stop {0}", svcName));
|
||||
|
||||
Logger.WriteLine(string.Format("{0} stopped successfully.", svcName));
|
||||
|
||||
if (version == PSVersion.Vista && SPSys.IsSpSysRunning())
|
||||
{
|
||||
Logger.WriteLine("Unloading spsys...");
|
||||
|
||||
int status = SPSys.ControlSpSys(false);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
throw new IOException("Failed to unload spsys");
|
||||
}
|
||||
|
||||
Logger.WriteLine("spsys unloaded successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void RestartSPP(PSVersion version)
|
||||
{
|
||||
if (version == PSVersion.Vista)
|
||||
{
|
||||
ServiceController sc;
|
||||
|
||||
try
|
||||
{
|
||||
sc = new ServiceController("slsvc");
|
||||
|
||||
if (sc.Status == ServiceControllerStatus.Running)
|
||||
return;
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
throw new InvalidOperationException("Unable to access slsvc: " + ex.Message);
|
||||
}
|
||||
|
||||
Logger.WriteLine("Starting slsvc...");
|
||||
|
||||
bool started = false;
|
||||
|
||||
for (int i = 0; started == false && i < 360; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sc.Status != ServiceControllerStatus.StartPending)
|
||||
sc.Start();
|
||||
|
||||
sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(500));
|
||||
}
|
||||
catch (System.ServiceProcess.TimeoutException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
System.Threading.Thread.Sleep(500);
|
||||
continue;
|
||||
}
|
||||
|
||||
started = true;
|
||||
}
|
||||
|
||||
if (!started)
|
||||
throw new System.TimeoutException("Failed to start slsvc");
|
||||
|
||||
Logger.WriteLine("slsvc started successfully.");
|
||||
}
|
||||
|
||||
SLApi.RefreshLicenseStatus();
|
||||
}
|
||||
|
||||
public static string GetPSPath(PSVersion version)
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case PSVersion.Vista:
|
||||
case PSVersion.Win7:
|
||||
return Directory.GetFiles(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.System),
|
||||
"7B296FB0-376B-497e-B012-9C450E1B7327-*.C7483456-A289-439d-8115-601632D005A0")
|
||||
.FirstOrDefault() ?? "";
|
||||
default:
|
||||
return Path.Combine(
|
||||
Environment.ExpandEnvironmentVariables(
|
||||
(string)Registry.GetValue(
|
||||
@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform",
|
||||
"TokenStore",
|
||||
string.Empty
|
||||
)
|
||||
),
|
||||
"data.dat"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetTokensPath(PSVersion version)
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case PSVersion.Vista:
|
||||
return Path.Combine(
|
||||
Environment.ExpandEnvironmentVariables("%WINDIR%"),
|
||||
@"ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SoftwareLicensing\tokens.dat"
|
||||
);
|
||||
case PSVersion.Win7:
|
||||
return Path.Combine(
|
||||
Environment.ExpandEnvironmentVariables("%WINDIR%"),
|
||||
@"ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SoftwareProtectionPlatform\tokens.dat"
|
||||
);
|
||||
default:
|
||||
return Path.Combine(
|
||||
Environment.ExpandEnvironmentVariables(
|
||||
(string)Registry.GetValue(
|
||||
@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform",
|
||||
"TokenStore",
|
||||
string.Empty
|
||||
)
|
||||
),
|
||||
"tokens.dat"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static IPhysicalStore GetStore(PSVersion version, bool production)
|
||||
{
|
||||
string psPath;
|
||||
|
||||
try
|
||||
{
|
||||
psPath = GetPSPath(version);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new FileNotFoundException("Failed to get path of physical store.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(psPath) || !File.Exists(psPath))
|
||||
{
|
||||
throw new FileNotFoundException(string.Format("Physical store not found at expected path {0}.", psPath));
|
||||
}
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case PSVersion.Vista:
|
||||
return new PhysicalStoreVista(psPath, production);
|
||||
case PSVersion.Win7:
|
||||
return new PhysicalStoreWin7(psPath, production);
|
||||
default:
|
||||
return new PhysicalStoreModern(psPath, production, version);
|
||||
}
|
||||
}
|
||||
|
||||
public static ITokenStore GetTokenStore(PSVersion version)
|
||||
{
|
||||
string tokPath;
|
||||
|
||||
try
|
||||
{
|
||||
tokPath = GetTokensPath(version);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new FileNotFoundException("Failed to get path of physical store.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tokPath) || !File.Exists(tokPath))
|
||||
{
|
||||
throw new FileNotFoundException(string.Format("Token store not found at expected path {0}.", tokPath));
|
||||
}
|
||||
|
||||
return new TokenStoreModern(tokPath);
|
||||
}
|
||||
|
||||
public static void DumpStore(PSVersion version, bool production, string filePath, string encrFilePath)
|
||||
{
|
||||
if (encrFilePath == null)
|
||||
{
|
||||
encrFilePath = GetPSPath(version);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(encrFilePath) || !File.Exists(encrFilePath))
|
||||
{
|
||||
throw new FileNotFoundException("Store does not exist at expected path '" + encrFilePath + "'.");
|
||||
}
|
||||
|
||||
KillSPP(version);
|
||||
|
||||
using (FileStream fs = File.Open(encrFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
byte[] encrData = fs.ReadAllBytes();
|
||||
File.WriteAllBytes(filePath, PhysStoreCrypto.DecryptPhysicalStore(encrData, production, version));
|
||||
}
|
||||
|
||||
Logger.WriteLine("Store dumped successfully to '" + filePath + "'.");
|
||||
}
|
||||
|
||||
public static void LoadStore(PSVersion version, bool production, string filePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
|
||||
{
|
||||
throw new FileNotFoundException("Store file '" + filePath + "' does not exist.");
|
||||
}
|
||||
|
||||
KillSPP(version);
|
||||
|
||||
using (IPhysicalStore store = GetStore(version, production))
|
||||
{
|
||||
store.WriteRaw(File.ReadAllBytes(filePath));
|
||||
}
|
||||
|
||||
Logger.WriteLine("Loaded store file succesfully.");
|
||||
}
|
||||
}
|
||||
}
|
47
LibTSforge/SPP/SPSys.cs
Normal file
47
LibTSforge/SPP/SPSys.cs
Normal file
@ -0,0 +1,47 @@
|
||||
namespace LibTSforge.SPP
|
||||
{
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
public class SPSys
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
|
||||
private static SafeFileHandle CreateFileSafe(string device)
|
||||
{
|
||||
return new SafeFileHandle(CreateFile(device, 0xC0000000, 0, IntPtr.Zero, 3, 0, IntPtr.Zero), true);
|
||||
}
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern bool DeviceIoControl([In] SafeFileHandle hDevice, [In] uint dwIoControlCode, [In] IntPtr lpInBuffer, [In] int nInBufferSize, [Out] IntPtr lpOutBuffer, [In] int nOutBufferSize, out int lpBytesReturned, [In] IntPtr lpOverlapped);
|
||||
|
||||
public static bool IsSpSysRunning()
|
||||
{
|
||||
SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice");
|
||||
IntPtr buffer = Marshal.AllocHGlobal(1);
|
||||
int bytesReturned = 0;
|
||||
DeviceIoControl(file, 0x80006008, IntPtr.Zero, 0, buffer, 1, out bytesReturned, IntPtr.Zero);
|
||||
bool running = Marshal.ReadByte(buffer) != 0;
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
file.Close();
|
||||
return running;
|
||||
}
|
||||
|
||||
public static int ControlSpSys(bool start)
|
||||
{
|
||||
SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice");
|
||||
IntPtr buffer = Marshal.AllocHGlobal(4);
|
||||
int bytesReturned = 0;
|
||||
DeviceIoControl(file, start ? 0x8000a000 : 0x8000a004, IntPtr.Zero, 0, buffer, 4, out bytesReturned, IntPtr.Zero);
|
||||
int result = Marshal.ReadInt32(buffer);
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
file.Close();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user