mirror of
https://github.com/UMSKT/xpmgr.git
synced 2026-11-05 14:47:54 +01:00
242 lines
7.9 KiB
C++
242 lines
7.9 KiB
C++
// ReSharper disable CppEnforceOverridingFunctionStyle
|
|
typedef struct IUnknown IUnknown;
|
|
|
|
#include <windows.h>
|
|
#include "xpmgr.h"
|
|
#include "xpmgr_util.h"
|
|
|
|
static int option_exists(int argc, char** argv, const char* option) {
|
|
for (int index = 1; index < argc; index++) {
|
|
if (xpmgr_streq(argv[index], option)) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static const char* option_value(int argc, char** argv, const char* option) {
|
|
for (int index = 1; index < argc - 1; index++) {
|
|
if (xpmgr_streq(argv[index], option)) {
|
|
return argv[index + 1];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static char* read_stdin_line(void) {
|
|
HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
|
|
char* buffer;
|
|
int count = 0;
|
|
const int cap = 4096;
|
|
if (input == NULL || input == INVALID_HANDLE_VALUE) {
|
|
return NULL;
|
|
}
|
|
buffer = (char*)HeapAlloc(GetProcessHeap(), 0, cap);
|
|
if (!buffer) {
|
|
return NULL;
|
|
}
|
|
while (count < cap - 1) {
|
|
char ch;
|
|
DWORD got = 0;
|
|
if (!ReadFile(input, &ch, 1, &got, NULL) || got == 0) {
|
|
break;
|
|
}
|
|
if (ch == '\n') {
|
|
break;
|
|
}
|
|
buffer[count++] = ch;
|
|
}
|
|
while (count > 0) {
|
|
char ch = buffer[count - 1];
|
|
if (ch != ' ' && ch != '\t' && ch != '\r') {
|
|
break;
|
|
}
|
|
count--;
|
|
}
|
|
buffer[count] = 0;
|
|
return buffer;
|
|
}
|
|
|
|
static int finish(int code) {
|
|
XPMGR_Cleanup();
|
|
return code;
|
|
}
|
|
|
|
static int windows_command_selected(int argc, char** argv) {
|
|
return option_exists(argc, argv, "/dti")
|
|
|| option_exists(argc, argv, "/atp")
|
|
|| option_exists(argc, argv, "/xpr")
|
|
|| option_exists(argc, argv, "/xpr-eval")
|
|
|| option_exists(argc, argv, "/ipk")
|
|
|| option_exists(argc, argv, "/dli");
|
|
}
|
|
|
|
/* Windows product activation is XP/2003 only. Office hosts must still reach command dispatch. */
|
|
static int windows_host_error(const OSVERSIONINFOA* info) {
|
|
if (info->dwPlatformId == VER_PLATFORM_WIN32_NT
|
|
&& info->dwMajorVersion == 5
|
|
&& (info->dwMinorVersion == 1 || info->dwMinorVersion == 2)) {
|
|
return 0;
|
|
}
|
|
xpmgr_write("An error occurred: Windows management only works on Windows NT 5.1 and 5.2.");
|
|
if (info->dwPlatformId == VER_PLATFORM_WIN32_NT && info->dwMajorVersion > 5) {
|
|
xpmgr_write(" Use slmgr instead: https://learn.microsoft.com/en-us/windows-server/get-started/activation-slmgr-vbs-options");
|
|
return 3;
|
|
}
|
|
if (info->dwPlatformId == VER_PLATFORM_WIN32_NT && info->dwMajorVersion == 5 && info->dwMinorVersion == 0) {
|
|
xpmgr_write(" You should be fine anyways, since Windows 2000 doesn't use Product Activation.");
|
|
return 4;
|
|
}
|
|
if (info->dwPlatformId == VER_PLATFORM_WIN32_NT && info->dwMajorVersion == 5) {
|
|
return 5;
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
const char* USAGE_TEXT =
|
|
"xpmgr - Windows XP License Manager (compiled on " __DATE__ " " __TIME__ ")\n"
|
|
"\n"
|
|
"Usage: \n"
|
|
"/dti: Gets the Installation ID\n"
|
|
"/atp [cid]: Sets Confirmation ID (If successful, activates Windows/Office) (can also read from stdin)\n"
|
|
"/xpr: Gets the days before activation is required (Grace period)\n"
|
|
"/xpr-eval: Gets the days before the evaluation period expires (Eval. copies only)\n"
|
|
"/ipk [pkey]: Sets/changes product key (can also read from stdin)\n"
|
|
"/dli: Gets the product ID of Windows\n"
|
|
"/?: Displays this message";
|
|
const wchar_t* result = NULL;
|
|
wchar_t* wide = NULL;
|
|
|
|
if (option_exists(argc, argv, "/?")) {
|
|
xpmgr_write(USAGE_TEXT);
|
|
return 0;
|
|
}
|
|
|
|
OSVERSIONINFOA info = {};
|
|
int hostError;
|
|
info.dwOSVersionInfoSize = sizeof(info);
|
|
if (!GetVersionExA(&info)) {
|
|
xpmgr_write("An error occurred: Could not read the operating system version.\n");
|
|
return 2;
|
|
}
|
|
|
|
if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && info.dwMinorVersion == 0) {
|
|
xpmgr_write("An error occurred: This program requires Windows 98 or later.\n");
|
|
return 2;
|
|
}
|
|
|
|
if (!windows_command_selected(argc, argv)) {
|
|
xpmgr_write("An error occurred: No arguments listed\n\n");
|
|
xpmgr_write(USAGE_TEXT);
|
|
return 7;
|
|
}
|
|
|
|
hostError = windows_host_error(&info);
|
|
if (hostError) {
|
|
return hostError;
|
|
}
|
|
|
|
#ifdef ENVIRONMENT32
|
|
/* XP x64 WPA lives in the 64-bit process. Office is 32-bit, so this stays on the Windows path. */
|
|
SYSTEM_INFO systemInfo;
|
|
typedef void (WINAPI *GetNativeSystemInfoFn)(LPSYSTEM_INFO);
|
|
HMODULE kernel = GetModuleHandleA("kernel32.dll");
|
|
GetNativeSystemInfoFn nativeInfo = NULL;
|
|
if (kernel) {
|
|
nativeInfo = (GetNativeSystemInfoFn)GetProcAddress(kernel, "GetNativeSystemInfo");
|
|
}
|
|
if (nativeInfo) {
|
|
nativeInfo(&systemInfo);
|
|
} else {
|
|
GetSystemInfo(&systemInfo);
|
|
}
|
|
if (systemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) {
|
|
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
|
|
xpmgr_write("An error occurred: Incorrect version of xpmgr. You need to download the x64 version.");
|
|
return 1;
|
|
}
|
|
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
|
|
xpmgr_write("An error occurred: Windows Product Activation does not exist on this platform.");
|
|
return 1;
|
|
}
|
|
xpmgr_write("An error occurred: Incorrect version of xpmgr. Send an issue at https://github.com/UMSKT/xpmgr/issues if you want to help us make a version for your platform!");
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
XPMGR_Initialize();
|
|
|
|
if (option_exists(argc, argv, "/dti")) {
|
|
result = XPMGR_GetInstallationID();
|
|
}
|
|
else if (option_exists(argc, argv, "/atp")) {
|
|
const char* confirmationId = option_value(argc, argv, "/atp");
|
|
char* piped = NULL;
|
|
if (!confirmationId) {
|
|
piped = read_stdin_line();
|
|
if (!piped || !piped[0]) {
|
|
xpmgr_write("An error occurred: No confirmation ID provided via argument or pipe\n\n");
|
|
xpmgr_write(USAGE_TEXT);
|
|
xpmgr_free(piped);
|
|
return finish(7);
|
|
}
|
|
wide = xpmgr_widen(piped);
|
|
xpmgr_free(piped);
|
|
} else {
|
|
wide = xpmgr_widen(confirmationId);
|
|
}
|
|
if (!wide) {
|
|
xpmgr_write("An error occurred: Out of memory\n");
|
|
return finish(7);
|
|
}
|
|
result = XPMGR_SetConfirmationID(wide);
|
|
}
|
|
else if (option_exists(argc, argv, "/xpr")) {
|
|
result = XPMGR_GetWPALeft();
|
|
}
|
|
else if (option_exists(argc, argv, "/xpr-eval")) {
|
|
result = XPMGR_GetEvalLeft();
|
|
}
|
|
else if (option_exists(argc, argv, "/ipk")) {
|
|
const char* productKey = option_value(argc, argv, "/ipk");
|
|
char* piped = NULL;
|
|
if (!productKey) {
|
|
piped = read_stdin_line();
|
|
if (!piped || !piped[0]) {
|
|
xpmgr_write("An error occurred: No product key provided via argument or pipe\n\n");
|
|
xpmgr_write(USAGE_TEXT);
|
|
xpmgr_free(piped);
|
|
return finish(7);
|
|
}
|
|
wide = xpmgr_widen(piped);
|
|
xpmgr_free(piped);
|
|
} else {
|
|
wide = xpmgr_widen(productKey);
|
|
}
|
|
if (!wide) {
|
|
xpmgr_write("An error occurred: Out of memory\n");
|
|
return finish(7);
|
|
}
|
|
result = XPMGR_SetProductKey(wide);
|
|
}
|
|
else if (option_exists(argc, argv, "/dli")) {
|
|
result = XPMGR_GetProductID();
|
|
}
|
|
else {
|
|
xpmgr_write("An error occurred: No arguments listed\n\n");
|
|
xpmgr_write(USAGE_TEXT);
|
|
return finish(7);
|
|
}
|
|
|
|
if (result) {
|
|
char* output = xpmgr_narrow(result);
|
|
xpmgr_write(output);
|
|
xpmgr_free(output);
|
|
}
|
|
xpmgr_free(wide);
|
|
|
|
XPMGR_Cleanup();
|
|
return 0;
|
|
}
|