mirror of
https://github.com/UMSKT/xpmgr.git
synced 2026-11-05 14:47:54 +01:00
Windows 98 'support'
This commit is contained in:
1 parent
1738a31bde
commit
831504110d
8 files changed
+868
-262
No files matched your search
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user