Windows 98 'support'

This commit is contained in:
thepwrtank18 committed 2026-10-24 22:39:55 -04:00
1 parent 1738a31bde
commit 831504110d
8 files changed
+868 -262

No files matched your search

+166 -99
View File
@@ -2,53 +2,95 @@
typedef struct IUnknown IUnknown;
#include <windows.h>
#include <iostream>
#include <string>
#include <algorithm>
#include "xpmgr.h"
#include "xpmgr_util.h"
// Command line handling
struct CommandLineArgs {
static const char* getCmdOption(char** begin, char** end, const std::string& option) {
const char* opt = option.c_str();
char** itr = std::find_if(begin, end, [opt](const char* arg) { return strcmp(arg, opt) == 0; });
if (itr != end && ++itr != end) {
return *itr;
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 nullptr;
}
static bool cmdOptionExists(char** begin, char** end, const std::string& option) {
const char* opt = option.c_str();
return std::find_if(begin, end, [opt](const char* arg) { return strcmp(arg, opt) == 0; }) != end;
}
static std::string readFromStdin() {
std::string input;
if (!std::cin.eof() && std::getline(std::cin, input)) {
// Remove any trailing whitespace, newlines or carriage returns
input.erase(std::find_if(input.rbegin(), input.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), input.end());
return input;
}
return "";
}
};
// Helper function to convert char* to wchar_t*
wchar_t* convertCharArrayToLPCWSTR(const char* charArray) {
auto* wString = new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
return wString;
return 0;
}
// Helper function to convert wchar_t* to char*
char* convertWCharToChar(const wchar_t* wcharArray) {
const int size = WideCharToMultiByte(CP_UTF8, 0, wcharArray, -1, nullptr, 0, nullptr, nullptr);
auto* charStr = new char[size];
WideCharToMultiByte(CP_UTF8, 0, wcharArray, -1, charStr, size, nullptr, nullptr);
return charStr;
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[]) {
@@ -63,111 +105,136 @@ int main(int argc, char* argv[]) {
"/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 (CommandLineArgs::cmdOptionExists(argv, argv + argc, "--GetUsage")) {
std::cout << USAGE_TEXT;
if (option_exists(argc, argv, "/?")) {
xpmgr_write(USAGE_TEXT);
return 0;
}
// Check Windows version
OSVERSIONINFOEX info = {};
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&info));
if (info.dwMajorVersion != 5) {
std::cout << "An error occurred: Windows management only works on Windows NT 5.1 and 5.2.";
if (info.dwMajorVersion > 5) {
std::cout << " Use slmgr instead: https://learn.microsoft.com/en-us/windows-server/get-started/activation-slmgr-vbs-options";
return 3;
}
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.dwMinorVersion != 1 && info.dwMinorVersion != 2) {
std::cout << "An error occurred: Windows management only works on Windows NT 5.1 and 5.2.";
if (info.dwMinorVersion == 0) {
std::cout << " You should be fine anyways, since Windows 2000 doesn't use Product Activation.";
return 4;
}
return 5;
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;
}
// Check architecture
#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;
GetNativeSystemInfo(&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) {
std::cout << "An error occurred: Incorrect version of xpmgr. You need to download the x64 version.";
xpmgr_write("An error occurred: Incorrect version of xpmgr. You need to download the x64 version.");
return 1;
}
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
std::cout << "An error occurred: Windows Product Activation does not exist on this platform.";
xpmgr_write("An error occurred: Windows Product Activation does not exist on this platform.");
return 1;
}
std::cout << "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!";
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
// Initialize the library
XPMGR_Initialize();
// Handle commands
const wchar_t* result = nullptr;
if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/dti")) {
if (option_exists(argc, argv, "/dti")) {
result = XPMGR_GetInstallationID();
}
else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/atp")) {
const char* confirmationId = CommandLineArgs::getCmdOption(argv, argv + argc, "/atp");
else if (option_exists(argc, argv, "/atp")) {
const char* confirmationId = option_value(argc, argv, "/atp");
char* piped = NULL;
if (!confirmationId) {
std::string pipedInput = CommandLineArgs::readFromStdin();
if (!pipedInput.empty()) {
result = XPMGR_SetConfirmationID(convertCharArrayToLPCWSTR(pipedInput.c_str()));
} else {
std::cout << "An error occurred: No confirmation ID provided via argument or pipe\n\n" << USAGE_TEXT;
XPMGR_Cleanup();
return 7;
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 {
result = XPMGR_SetConfirmationID(convertCharArrayToLPCWSTR(confirmationId));
wide = xpmgr_widen(confirmationId);
}
if (!wide) {
xpmgr_write("An error occurred: Out of memory\n");
return finish(7);
}
result = XPMGR_SetConfirmationID(wide);
}
else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/xpr")) {
else if (option_exists(argc, argv, "/xpr")) {
result = XPMGR_GetWPALeft();
}
else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/xpr-eval")) {
else if (option_exists(argc, argv, "/xpr-eval")) {
result = XPMGR_GetEvalLeft();
}
else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/ipk")) {
const char* productKey = CommandLineArgs::getCmdOption(argv, argv + argc, "/ipk");
else if (option_exists(argc, argv, "/ipk")) {
const char* productKey = option_value(argc, argv, "/ipk");
char* piped = NULL;
if (!productKey) {
std::string pipedInput = CommandLineArgs::readFromStdin();
if (!pipedInput.empty()) {
result = XPMGR_SetProductKey(convertCharArrayToLPCWSTR(pipedInput.c_str()));
} else {
std::cout << "An error occurred: No product key provided via argument or pipe\n\n" << USAGE_TEXT;
XPMGR_Cleanup();
return 7;
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 {
result = XPMGR_SetProductKey(convertCharArrayToLPCWSTR(productKey));
wide = xpmgr_widen(productKey);
}
if (!wide) {
xpmgr_write("An error occurred: Out of memory\n");
return finish(7);
}
result = XPMGR_SetProductKey(wide);
}
else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/dli")) {
else if (option_exists(argc, argv, "/dli")) {
result = XPMGR_GetProductID();
}
else {
std::cout << "An error occurred: No arguments listed\n\n" << USAGE_TEXT;
XPMGR_Cleanup();
return 7;
xpmgr_write("An error occurred: No arguments listed\n\n");
xpmgr_write(USAGE_TEXT);
return finish(7);
}
if (result) {
char* output = convertWCharToChar(result);
std::cout << output;
delete[] output;
char* output = xpmgr_narrow(result);
xpmgr_write(output);
xpmgr_free(output);
}
xpmgr_free(wide);
XPMGR_Cleanup();
return 0;