From 696162e9165c29be270a607e363c3609134ca453 Mon Sep 17 00:00:00 2001 From: TheTank20 Date: Wed, 23 Jul 2025 02:18:27 -0500 Subject: [PATCH 1/3] rewrite --- xpmgr.cpp | 828 +++++++++++++++++++++++++++--------------------------- 1 file changed, 411 insertions(+), 417 deletions(-) diff --git a/xpmgr.cpp b/xpmgr.cpp index 48fa987..339dcca 100644 --- a/xpmgr.cpp +++ b/xpmgr.cpp @@ -6,6 +6,7 @@ typedef struct IUnknown IUnknown; #include #include #include +#include // Check windows #if _WIN32 || _WIN64 @@ -16,6 +17,11 @@ typedef struct IUnknown IUnknown; #endif #endif +// Forward declarations of helper functions +BSTR FormatErrorMessage(const char* context, HRESULT status, ULONG returnCode = 0); +std::string ConvertToStdString(BSTR bstr); +BSTR ConvertCharToBSTR(const char* charString); + const char* specifiedProduct = nullptr; // This is a really weird way of making a GUID. In short, this becomes ACADF079-CBCD-4032-83F2-FA47C4DB096F. Ignore the 0x and it makes sense. @@ -100,44 +106,31 @@ DECLARE_INTERFACE_(ICOMLicenseAgent, IDispatch) static BOOL XP_ComInitialized = FALSE; static ICOMLicenseAgent* XP_LicenseAgent = nullptr; -static BOOL XP_LoadLicenseManager() -{ - if (!XP_ComInitialized) { - const HRESULT status = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - if (FAILED(status)) { - const char* errorString = "An error occurred at CoInitializeEx:"; - const int bufferSize = snprintf(nullptr, 0, "%s 0x%08X\n", errorString, static_cast(status)); - char* result = new char[bufferSize + 1]; - snprintf(result, bufferSize + 1, "%s 0x%08X\n", errorString, static_cast(status)); - std::cout << result; - return FALSE; - } - XP_ComInitialized = TRUE; - } - if (!XP_LicenseAgent) { - HRESULT status = CoCreateInstance(XP_CLSID, nullptr, CLSCTX_INPROC_SERVER, XP_IID, reinterpret_cast(&XP_LicenseAgent)); - int good = 0; - if (SUCCEEDED(status)) { - ULONG dwRetCode; - status = XP_LicenseAgent->Initialize(0xC475 /* This needs to be changed, I believe it's causing the crashing.*/ , 3, nullptr, &dwRetCode); - if (SUCCEEDED(status) && dwRetCode == 0) { - good = 1; - } - else { - XP_LicenseAgent->Release(); - XP_LicenseAgent = nullptr; - } - } - if (!good) { - const char* errorString = "An error occurred at CoCreateInstance:"; - const int bufferSize = snprintf(nullptr, 0, "%s 0x%08X\n", errorString, static_cast(status)); - char* result = new char[bufferSize + 1]; - snprintf(result, bufferSize + 1, "%s 0x%08X\n", errorString, static_cast(status)); - std::cout << result; - return FALSE; - } - } - return TRUE; +static BOOL XP_LoadLicenseManager() { + if (!XP_ComInitialized) { + const HRESULT status = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (FAILED(status)) { + std::cout << ConvertToStdString(FormatErrorMessage("CoInitializeEx", status)); + return FALSE; + } + XP_ComInitialized = TRUE; + } + + if (!XP_LicenseAgent) { + HRESULT status = CoCreateInstance(XP_CLSID, nullptr, CLSCTX_INPROC_SERVER, XP_IID, reinterpret_cast(&XP_LicenseAgent)); + if (SUCCEEDED(status)) { + ULONG dwRetCode; + status = XP_LicenseAgent->Initialize(0xC475, 3, nullptr, &dwRetCode); + if (SUCCEEDED(status) && dwRetCode == 0) { + return TRUE; + } + XP_LicenseAgent->Release(); + XP_LicenseAgent = nullptr; + } + std::cout << ConvertToStdString(FormatErrorMessage("CoCreateInstance", status)); + return FALSE; + } + return TRUE; } #pragma region Internals @@ -205,33 +198,6 @@ OLECHAR SizeToOLECHAR(size_t value) return oChar; } -BSTR ConvertToBSTR(const std::string& str) { - const int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); - // ReSharper disable once CppLocalVariableMayBeConst - BSTR bstr = SysAllocStringLen(nullptr, size - 1); - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, bstr, size); - return bstr; -} - -std::string ConvertToStdString(BSTR bstr) { - const int size = WideCharToMultiByte(CP_UTF8, 0, bstr, -1, nullptr, 0, nullptr, nullptr); - const auto buffer = new char[size]; - WideCharToMultiByte(CP_UTF8, 0, bstr, -1, buffer, size, nullptr, nullptr); - - std::string result(buffer); - delete[] buffer; - - return result; -} - -BSTR ConvertCharToBSTR(const char* charString) { - const int size = MultiByteToWideChar(CP_UTF8, 0, charString, -1, nullptr, 0); - // ReSharper disable once CppLocalVariableMayBeConst - BSTR bstr = SysAllocStringLen(nullptr, size - 1); - MultiByteToWideChar(CP_UTF8, 0, charString, -1, bstr, size); - return bstr; -} - #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" void safeStrncat(char* destination, const char* source, size_t size) { @@ -248,417 +214,445 @@ void safeStrncat(char* destination, const char* source, size_t size) { } #pragma clang diagnostic pop -bool IsProcessRunning(const wchar_t* processName) -{ - // ReSharper disable once CppLocalVariableMayBeConst - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (snapshot == INVALID_HANDLE_VALUE) - { - std::cout << "An error occurred at IsProcessRunning: Failed to create process snapshot." << std::endl; - return false; - } +#pragma region Process Management - PROCESSENTRY32W processEntry{}; - processEntry.dwSize = sizeof(PROCESSENTRY32W); - if (!Process32FirstW(snapshot, &processEntry)) - { - CloseHandle(snapshot); - std::cout << "An error occurred at IsProcessRunning: Failed to retrieve process information." << std::endl; - return false; - } +struct ProcessHandle { + HANDLE handle; + explicit ProcessHandle(HANDLE h) : handle(h) {} + ~ProcessHandle() { if (handle != INVALID_HANDLE_VALUE) CloseHandle(handle); } + operator HANDLE() const { return handle; } +}; - while (Process32NextW(snapshot, &processEntry)) - { - if (wcscmp(processEntry.szExeFile, processName) == 0) - { - CloseHandle(snapshot); - return true; // Process found - } - } +bool IsProcessRunning(const wchar_t* processName) { + ProcessHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + if (snapshot == INVALID_HANDLE_VALUE) { + std::cout << "Failed to create process snapshot: " << GetLastError() << std::endl; + return false; + } - CloseHandle(snapshot); - return false; // Process not found -} + PROCESSENTRY32W processEntry{}; + processEntry.dwSize = sizeof(PROCESSENTRY32W); + + if (!Process32FirstW(snapshot, &processEntry)) { + std::cout << "Failed to retrieve process information: " << GetLastError() << std::endl; + return false; + } -bool TerminateProcessByName(const wchar_t* processName) -{ - // ReSharper disable once CppLocalVariableMayBeConst - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (snapshot == INVALID_HANDLE_VALUE) - { - return false; - } + do { + if (wcscmp(processEntry.szExeFile, processName) == 0) { + return true; + } + } while (Process32NextW(snapshot, &processEntry)); - PROCESSENTRY32W processEntry{}; - processEntry.dwSize = sizeof(PROCESSENTRY32W); - if (!Process32FirstW(snapshot, &processEntry)) - { - CloseHandle(snapshot); - return false; - } + return false; +} - while (Process32NextW(snapshot, &processEntry)) - { - if (wcscmp(processEntry.szExeFile, processName) == 0) - { - // ReSharper disable once CppLocalVariableMayBeConst - HANDLE processHandle = OpenProcess(PROCESS_TERMINATE, FALSE, processEntry.th32ProcessID); - if (processHandle != nullptr) - { - if (TerminateProcess(processHandle, 0)) - { - CloseHandle(processHandle); - CloseHandle(snapshot); - return true; // Process terminated successfully - } - else - { - CloseHandle(processHandle); - CloseHandle(snapshot); - return false; // Failed to terminate the process - } - } - else - { - CloseHandle(snapshot); - return false; // Failed to open process handle - } - } - } +bool TerminateProcessByName(const wchar_t* processName) { + ProcessHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + if (snapshot == INVALID_HANDLE_VALUE) { + std::cout << "Failed to create process snapshot: " << GetLastError() << std::endl; + return false; + } - CloseHandle(snapshot); - return false; // Process not found + PROCESSENTRY32W processEntry{}; + processEntry.dwSize = sizeof(PROCESSENTRY32W); + + if (!Process32FirstW(snapshot, &processEntry)) { + std::cout << "Failed to retrieve process information: " << GetLastError() << std::endl; + return false; + } + + do { + if (wcscmp(processEntry.szExeFile, processName) == 0) { + ProcessHandle processHandle(OpenProcess(PROCESS_TERMINATE, FALSE, processEntry.th32ProcessID)); + if (processHandle == nullptr) { + std::cout << "Failed to open process: " << GetLastError() << std::endl; + return false; + } + + if (!TerminateProcess(processHandle, 0)) { + std::cout << "Failed to terminate process: " << GetLastError() << std::endl; + return false; + } + + return true; + } + } while (Process32NextW(snapshot, &processEntry)); + + std::cout << "Process not found: " << ConvertToStdString(ConvertCharToBSTR(reinterpret_cast(processName))) << std::endl; + return false; } #pragma endregion +#pragma region Helper Functions + +BSTR ConvertCharToBSTR(const char* charString) { + if (!charString) return nullptr; + const int size = MultiByteToWideChar(CP_UTF8, 0, charString, -1, nullptr, 0); + BSTR bstr = SysAllocStringLen(nullptr, size - 1); + MultiByteToWideChar(CP_UTF8, 0, charString, -1, bstr, size); + return bstr; +} + +std::string ConvertToStdString(BSTR bstr) { + if (!bstr) return ""; + const int size = WideCharToMultiByte(CP_UTF8, 0, bstr, -1, nullptr, 0, nullptr, nullptr); + std::string result(size - 1, '\0'); + WideCharToMultiByte(CP_UTF8, 0, bstr, -1, &result[0], size, nullptr, nullptr); + return result; +} + +BSTR FormatErrorMessage(const char* context, HRESULT status, ULONG returnCode) { + std::string errorMsg = "An error occurred at " + std::string(context) + ": "; + char statusBuffer[32]; + snprintf(statusBuffer, sizeof(statusBuffer), "0x%08X", static_cast(status)); + errorMsg += statusBuffer; + + if (returnCode != 0) { + char returnCodeBuffer[32]; + snprintf(returnCodeBuffer, sizeof(returnCodeBuffer), " %lu", returnCode); + errorMsg += returnCodeBuffer; + } + + return ConvertCharToBSTR(errorMsg.c_str()); +} + #pragma region Windows XP static BSTR XP_GetWPALeft() { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } + if (!XP_LoadLicenseManager()) { + return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); + } - ULONG dwWPALeft = 0, dwEvalLeft = 0; - const HRESULT status = XP_LicenseAgent->GetExpirationInfo(&dwWPALeft, &dwEvalLeft); - if (FAILED(status)) { - XP_LicenseAgent->Release(); - XP_LicenseAgent = nullptr; - const char* errorString = "An error occurred at CoInitializeEx:"; - const int bufferSize = snprintf(nullptr, 0, "%s 0x%08X", errorString, static_cast(status)); - char* result = new char[bufferSize + 1]; - snprintf(result, bufferSize + 1, "%s 0x%08X", errorString, static_cast(status)); - const int wideCharSize = MultiByteToWideChar(CP_UTF8, 0, result, -1, nullptr, 0); - auto* wideResult = new OLECHAR[wideCharSize]; - MultiByteToWideChar(CP_UTF8, 0, result, -1, wideResult, wideCharSize); - return SysAllocString(wideResult); - } - if (dwWPALeft == 0x7FFFFFFF) { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } + ULONG dwWPALeft = 0, dwEvalLeft = 0; + const HRESULT status = XP_LicenseAgent->GetExpirationInfo(&dwWPALeft, &dwEvalLeft); + if (FAILED(status)) { + XP_LicenseAgent->Release(); + XP_LicenseAgent = nullptr; + return FormatErrorMessage("GetExpirationInfo", status); + } + if (dwWPALeft == 0x7FFFFFFF) { + return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); + } wchar_t buffer[16]; swprintf(buffer, L"%lu", dwWPALeft); - return SysAllocString(buffer); + return SysAllocString(buffer); } static BSTR XP_GetEvalLeft() { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } + if (!XP_LoadLicenseManager()) { + return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); + } - ULONG dwWPALeft = 0, dwEvalLeft = 0; - const HRESULT status = XP_LicenseAgent->GetExpirationInfo(&dwWPALeft, &dwEvalLeft); - if (FAILED(status)) { - XP_LicenseAgent->Release(); - XP_LicenseAgent = nullptr; - const char* errorString = "An error occurred at GetExpirationInfo:"; - const int bufferSize = snprintf(nullptr, 0, "%s 0x%08X", errorString, static_cast(status)); - char* result = new char[bufferSize + 1]; - snprintf(result, bufferSize + 1, "%s 0x%08X", errorString, static_cast(status)); - const int wideCharSize = MultiByteToWideChar(CP_UTF8, 0, result, -1, nullptr, 0); - auto* wideResult = new OLECHAR[wideCharSize]; - MultiByteToWideChar(CP_UTF8, 0, result, -1, wideResult, wideCharSize); - return SysAllocString(wideResult); - } - if (dwEvalLeft == 0x7FFFFFFF) { - return SysAllocString(L"An error occurred at GetEvalLeft: Not an evaluation copy"); - } - wchar_t buffer[16]; - swprintf(buffer, L"%lu", dwWPALeft); - return SysAllocString(buffer); + ULONG dwWPALeft = 0, dwEvalLeft = 0; + const HRESULT status = XP_LicenseAgent->GetExpirationInfo(&dwWPALeft, &dwEvalLeft); + if (FAILED(status)) { + XP_LicenseAgent->Release(); + XP_LicenseAgent = nullptr; + return FormatErrorMessage("GetExpirationInfo", status); + } + if (dwEvalLeft == 0x7FFFFFFF) { + return SysAllocString(L"An error occurred at GetEvalLeft: Not an evaluation copy"); + } + wchar_t buffer[16]; + swprintf(buffer, L"%lu", dwEvalLeft); + return SysAllocString(buffer); +} + +#pragma region Windows XP Activation + +enum class VerificationResult { + Success, + InvalidFormat, + VerificationFailed, + AlreadyActivated, + LoadError +}; + +static VerificationResult VerifyConfirmationIDChunk(const std::string& chunk) { + if (chunk.length() != 6) { + return VerificationResult::InvalidFormat; + } + + LONG pbValue; + const HRESULT status = XP_LicenseAgent->VerifyCheckDigits(ConvertCharToBSTR(chunk.c_str()), &pbValue); + return (SUCCEEDED(status) && pbValue) ? VerificationResult::Success : VerificationResult::VerificationFailed; } static BSTR XP_VerifyCheckDigits(BSTR cidChunk) { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } + if (!XP_LoadLicenseManager()) { + return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); + } - if (0 == wcscmp(XP_GetWPALeft(), L"An error occurred at GetWPALeft: Windows is activated")) { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } + const std::string activationCheck = ConvertToStdString(XP_GetWPALeft()); + if (activationCheck == "An error occurred at GetWPALeft: Windows is activated") { + return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); + } - LONG pbValue; - const HRESULT status = XP_LicenseAgent->VerifyCheckDigits(cidChunk, &pbValue); - if (FAILED(status) || !pbValue) { - char errorMessage[70] = "An error occurred at XP_VerifyCheckDigits:"; - char pbValueChar[20]; - snprintf(errorMessage, sizeof(errorMessage), "%ld", pbValue); - safeStrncat(errorMessage, pbValueChar, sizeof(errorMessage)); - const int len = MultiByteToWideChar(CP_UTF8, 0, errorMessage, -1, nullptr, 0); - auto* oleCharString = new OLECHAR[len]; - MultiByteToWideChar(CP_UTF8, 0, errorMessage, -1, oleCharString, len); - return SysAllocString(oleCharString); - } - return SysAllocString(L"Successfully verified CID chunk"); + LONG pbValue; + const HRESULT status = XP_LicenseAgent->VerifyCheckDigits(cidChunk, &pbValue); + return SUCCEEDED(status) && pbValue + ? SysAllocString(L"Successfully verified CID chunk") + : FormatErrorMessage("XP_VerifyCheckDigits", status); } static BSTR XP_SetConfirmationID(BSTR confirmationID) { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } + if (!XP_LoadLicenseManager()) { + return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); + } - if (0 == wcscmp(XP_GetWPALeft(), L"An error occurred at GetWPALeft: Windows is activated")) { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } + const std::string activationCheck = ConvertToStdString(XP_GetWPALeft()); + if (activationCheck == "An error occurred at GetWPALeft: Windows is activated") { + return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); + } - const int length = static_cast(SysStringLen(confirmationID)); - char* str = new char[length + 1]; - WideCharToMultiByte(CP_UTF8, 0, confirmationID, length, str, length, nullptr, nullptr); - str[length] = '\0'; - - std::string inputString(str); - inputString.erase(std::remove(inputString.begin(), inputString.end(), '-'), inputString.end()); // remove -'s - for (size_t i = 0; i < inputString.length(); i += 6) { - std::string substring = inputString.substr(i, 6); - const char* cstr = substring.c_str(); - if (0 != wcscmp(XP_VerifyCheckDigits(ConvertCharToBSTR(cstr)), L"Successfully verified CID chunk")) { - return SysAllocString(L"An error occurred at XP_VerifyCheckDigits: Check for misspelling"); - } - } + // Convert and clean up the confirmation ID + std::string cidStr = ConvertToStdString(confirmationID); + cidStr.erase(std::remove(cidStr.begin(), cidStr.end(), '-'), cidStr.end()); + + // Verify each 6-character chunk + for (size_t i = 0; i < cidStr.length(); i += 6) { + const std::string chunk = cidStr.substr(i, 6); + const auto result = VerifyConfirmationIDChunk(chunk); + + switch (result) { + case VerificationResult::InvalidFormat: + return SysAllocString(L"An error occurred: Invalid confirmation ID format"); + case VerificationResult::VerificationFailed: + return SysAllocString(L"An error occurred: Confirmation ID verification failed"); + case VerificationResult::Success: + continue; + default: + return SysAllocString(L"An error occurred: Unexpected verification result"); + } + } - ULONG dwRetCode; - const HRESULT status = XP_LicenseAgent->DepositConfirmationId(confirmationID, &dwRetCode); - if (FAILED(status) || dwRetCode) { - const char* errorString = "An error occurred at DepositConfirmationId:"; - const int bufferSize = snprintf(nullptr, 0, "%s 0x%08X %lu", errorString, static_cast(status), dwRetCode); - char* result = new char[bufferSize + 1]; - snprintf(result, bufferSize + 1, "%s 0x%08X %lu", errorString, static_cast(status), dwRetCode); - - const int wideCharSize = MultiByteToWideChar(CP_UTF8, 0, result, -1, nullptr, 0); - auto* wideResult = new OLECHAR[wideCharSize]; - MultiByteToWideChar(CP_UTF8, 0, result, -1, wideResult, wideCharSize); - return SysAllocString(wideResult); - } + // Deposit the full confirmation ID + ULONG dwRetCode; + const HRESULT status = XP_LicenseAgent->DepositConfirmationId(confirmationID, &dwRetCode); + if (FAILED(status) || dwRetCode) { + return FormatErrorMessage("DepositConfirmationId", status, dwRetCode); + } - system("rundll32 setupapi,InstallHinfSection DEL_OOBE_ACTIVATE 132 syssetup.inf"); // remove activation shortcuts + // Handle WPA notifier process + if (IsProcessRunning(L"wpabaln.exe")) { + if (!TerminateProcessByName(L"wpabaln.exe")) { + std::cout << "Warning: Failed to terminate WPA notifier process" << std::endl; + } + } - if (IsProcessRunning(L"wpabaln.exe")) { // end WPA notifier process if there - TerminateProcessByName(L"wpabaln.exe"); - } + // Clean up activation files + HMODULE hMod = LoadLibraryW(L"setupapi.dll"); + if (hMod) { + using InstallHinfSectionFunc = BOOL (WINAPI*)(HWND, HINSTANCE, PCWSTR, INT); + if (auto installHinfSection = reinterpret_cast(GetProcAddress(hMod, "InstallHinfSectionW"))) { + SetLastError(0); + const BOOL result = installHinfSection(nullptr, nullptr, L"DEL_OOBE_ACTIVATE 132 syssetup.inf", 132); + const DWORD error = GetLastError(); + + if (!result && error != 0 && error != 6) { // Ignore error 6 (ERROR_INVALID_HANDLE) as it indicates success + std::cout << "Warning: Failed to remove activation reminders. Error: " << error << std::endl; + std::cout << "You can try to run the following command yourself: " << std::endl; + std::cout << "rundll32 setupapi,InstallHinfSection DEL_OOBE_ACTIVATE 132 syssetup.inf" << std::endl; + } + } + FreeLibrary(hMod); + } - return SysAllocString(L"Successfully set confirmation ID"); + return SysAllocString(L"Successfully set confirmation ID"); } static BSTR XP_GetInstallationID() { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } - if (0 == wcscmp(XP_GetWPALeft(), L"An error occurred at GetWPALeft: Windows is activated")) { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } + if (!XP_LoadLicenseManager()) { + return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); + } + if (0 == wcscmp(XP_GetWPALeft(), L"An error occurred at GetWPALeft: Windows is activated")) { + return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); + } - BSTR installationID = nullptr; - const HRESULT status = XP_LicenseAgent->GenerateInstallationId(&installationID); - if (FAILED(status) || !installationID) { - const char* errorString = "An error occurred at GenerateInstallationId:"; - const int bufferSize = snprintf(nullptr, 0, "%s 0x%08X", errorString, static_cast(status)); - char* result = new char[bufferSize + 1]; - snprintf(result, bufferSize + 1, "%s 0x%08X", errorString, static_cast(status)); - const int wideCharSize = MultiByteToWideChar(CP_UTF8, 0, result, -1, nullptr, 0); - auto* wideResult = new OLECHAR[wideCharSize]; - MultiByteToWideChar(CP_UTF8, 0, result, -1, wideResult, wideCharSize); - return SysAllocString(wideResult); - } - else { - return installationID; - } + BSTR installationID = nullptr; + const HRESULT status = XP_LicenseAgent->GenerateInstallationId(&installationID); + if (FAILED(status) || !installationID) { + return FormatErrorMessage("GenerateInstallationId", status); + } + return installationID; } static BSTR XP_SetProductKey(LPWSTR productKey) { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } + if (!XP_LoadLicenseManager()) { + return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); + } - std::wstring ws(productKey); - const std::string productKeyToRegex = std::string(ws.begin(), ws.end()); - const std::regex pattern("[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}"); + if (0 == wcscmp(XP_GetWPALeft(), L"An error occurred at GetWPALeft: Windows is activated")) { + return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); + } - if (!std::regex_match(productKeyToRegex, pattern)) { - return SysAllocString(L"An error occurred at regex_match: Product key is invalid"); - } + // Validate product key format + std::wstring ws(productKey); + const std::string productKeyToRegex = std::string(ws.begin(), ws.end()); + const std::regex pattern("[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}"); - if (0 == wcscmp(XP_GetWPALeft(), L"An error occurred at GetWPALeft: Windows is activated")) { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } + if (!std::regex_match(productKeyToRegex, pattern)) { + return SysAllocString(L"An error occurred at regex_match: Product key is invalid"); + } - const HRESULT status = XP_LicenseAgent->SetProductKey(productKey); - if (FAILED(status)) { - const char* errorString = "An error occurred at SetProductKey:"; - const int bufferSize = snprintf(nullptr, 0, "%s 0x%08X", errorString, static_cast(status)); - char* result = new char[bufferSize + 1]; - snprintf(result, bufferSize + 1, "%s 0x%08X", errorString, static_cast(status)); - const int wideCharSize = MultiByteToWideChar(CP_UTF8, 0, result, -1, nullptr, 0); - auto* wideResult = new OLECHAR[wideCharSize]; - MultiByteToWideChar(CP_UTF8, 0, result, -1, wideResult, wideCharSize); - return SysAllocString(wideResult); - } - else { - return SysAllocString(L"Successfully set product key"); - } + const HRESULT status = XP_LicenseAgent->SetProductKey(productKey); + if (FAILED(status)) { + return FormatErrorMessage("SetProductKey", status); + } + return SysAllocString(L"Successfully set product key"); } static BSTR XP_GetProductID() { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } + if (!XP_LoadLicenseManager()) { + return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); + } - BSTR productID = nullptr; - - const HRESULT status = XP_LicenseAgent->GetProductID(&productID); - if (FAILED(status)) { - const char* errorString = "An error occurred at GetProductID:"; - const int bufferSize = snprintf(nullptr, 0, "%s 0x%08X", errorString, static_cast(status)); - char* result = new char[bufferSize + 1]; - snprintf(result, bufferSize + 1, "%s 0x%08X", errorString, static_cast(status)); - const int wideCharSize = MultiByteToWideChar(CP_UTF8, 0, result, -1, nullptr, 0); - auto* wideResult = new OLECHAR[wideCharSize]; - MultiByteToWideChar(CP_UTF8, 0, result, -1, wideResult, wideCharSize); - return SysAllocString(wideResult); - } - else { - return productID; - } + BSTR productID = nullptr; + const HRESULT status = XP_LicenseAgent->GetProductID(&productID); + if (FAILED(status)) { + return FormatErrorMessage("GetProductID", status); + } + return productID; } #pragma endregion +#pragma region Command Line Handling + +struct CommandLineArgs { + static const char* getCmdOption(char** begin, char** end, const std::string& option) { + char** itr = std::find(begin, end, option); + if (itr != end && ++itr != end) { + return *itr; + } + return nullptr; + } + + static bool cmdOptionExists(char** begin, char** end, const std::string& option) { + return std::find(begin, end, option) != end; + } + + static std::string readFromStdin() { + std::string input; + if (!std::cin.eof() && std::getline(std::cin, input)) { + input.erase(std::find_if(input.rbegin(), input.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), input.end()); + return input; + } + return ""; + } +}; + +#pragma endregion + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -int main(int argc, char* argv[]) -{ - const char* 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"; - - if (cmdOptionExists(argv, argv + argc, "--GetUsage")) { - std::cout << text; - return 0; - } +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"; + + if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "--GetUsage")) { + std::cout << USAGE_TEXT; + return 0; + } + + // Check Windows version + OSVERSIONINFOEX info = {}; + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + GetVersionEx(reinterpret_cast(&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; + } + return 2; + } - specifiedProduct = "WindowsNT5x"; + 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 (std::strcmp(specifiedProduct, "WindowsNT5x") == 0) { - SYSTEM_INFO systemInfo; - GetNativeSystemInfo(&systemInfo); + // Check architecture #ifdef ENVIRONMENT32 - if (systemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) { // running under WOW64 - if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { // is AMD64 - std::cout << "An error occurred at systemInfo: Incorrect version of xpmgr. You need to download the x64 version."; - } - else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) { // is IA64 - std::cout << "An error occurred at systemInfo: Windows Product Activation does not exist on this platform."; - } - else { // is PPC, megafart 386, whatever else - std::cout << "An error occurred at systemInfo: 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; - } + SYSTEM_INFO systemInfo; + GetNativeSystemInfo(&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."; + return 1; + } + if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) { + std::cout << "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!"; + return 1; + } #endif - OSVERSIONINFOEX info = {}; - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - GetVersionEx(reinterpret_cast(&info)); - - if (info.dwMajorVersion != 5) { - std::cout << "An error occurred at OSVERSIONINFOEX: 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; - } - return 2; - } - else { - if (info.dwMinorVersion != 1 && info.dwMinorVersion != 2) { - std::cout << "An error occurred at OSVERSIONINFOEX: 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 (cmdOptionExists(argv, argv + argc, "/dti")) { - std::cout << ConvertToStdString(XP_GetInstallationID()); - return 0; - } - else if (cmdOptionExists(argv, argv + argc, "/atp")) { - const char* confirmationId = getCmdOption(argv, argv + argc, "/atp"); - if (!confirmationId) { - // No argument provided, try reading from stdin - std::string pipedInput = readFromStdin(); - if (!pipedInput.empty()) { - std::cout << ConvertToStdString(XP_SetConfirmationID(ConvertCharToBSTR(pipedInput.c_str()))); - } else { - std::cout << "An error occurred at main: No confirmation ID provided via argument or pipe\n\n"; - std::cout << text; - return 7; - } - } else { - std::cout << ConvertToStdString(XP_SetConfirmationID(ConvertCharToBSTR(confirmationId))); - } - return 0; - } - else if (cmdOptionExists(argv, argv + argc, "/xpr")) { - std::cout << ConvertToStdString(XP_GetWPALeft()); - return 0; - } - else if (cmdOptionExists(argv, argv + argc, "/xpr-eval")) { - std::cout << ConvertToStdString(XP_GetEvalLeft()); - return 0; - } + // Handle commands + if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/dti")) { + std::cout << ConvertToStdString(XP_GetInstallationID()); + } + else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/atp")) { + const char* confirmationId = CommandLineArgs::getCmdOption(argv, argv + argc, "/atp"); + if (!confirmationId) { + std::string pipedInput = CommandLineArgs::readFromStdin(); + if (!pipedInput.empty()) { + std::cout << ConvertToStdString(XP_SetConfirmationID(ConvertCharToBSTR(pipedInput.c_str()))); + } else { + std::cout << "An error occurred: No confirmation ID provided via argument or pipe\n\n" << USAGE_TEXT; + return 7; + } + } else { + std::cout << ConvertToStdString(XP_SetConfirmationID(ConvertCharToBSTR(confirmationId))); + } + } + else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/xpr")) { + std::cout << ConvertToStdString(XP_GetWPALeft()); + } + else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/xpr-eval")) { + std::cout << ConvertToStdString(XP_GetEvalLeft()); + } + else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/ipk")) { + const char* productKey = CommandLineArgs::getCmdOption(argv, argv + argc, "/ipk"); + if (!productKey) { + std::string pipedInput = CommandLineArgs::readFromStdin(); + if (!pipedInput.empty()) { + std::cout << ConvertToStdString(XP_SetProductKey(convertCharArrayToLPCWSTR(pipedInput.c_str()))); + } else { + std::cout << "An error occurred: No product key provided via argument or pipe\n\n" << USAGE_TEXT; + return 7; + } + } else { + std::cout << ConvertToStdString(XP_SetProductKey(convertCharArrayToLPCWSTR(productKey))); + } + } + else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/dli")) { + std::cout << ConvertToStdString(XP_GetProductID()); + } + else { + std::cout << "An error occurred: No arguments listed\n\n" << USAGE_TEXT; + return 7; + } - else if (cmdOptionExists(argv, argv + argc, "/ipk")) { - const char* productKey = getCmdOption(argv, argv + argc, "/ipk"); - if (!productKey) { - // No argument provided, try reading from stdin - std::string pipedInput = readFromStdin(); - if (!pipedInput.empty()) { - std::cout << ConvertToStdString(XP_SetProductKey(convertCharArrayToLPCWSTR(pipedInput.c_str()))); - } else { - std::cout << "An error occurred at main: No product key provided via argument or pipe\n\n"; - std::cout << text; - return 7; - } - } else { - std::cout << ConvertToStdString(XP_SetProductKey(convertCharArrayToLPCWSTR(productKey))); - } - return 0; - } - else if (cmdOptionExists(argv, argv + argc, "/dli")) { - std::cout << ConvertToStdString(XP_GetProductID()); - return 0; - } - else { - std::cout << "An error occurred at main: No arguments listed\n\n"; - std::cout << text; - return 7; - } + return 0; } #pragma clang diagnostic pop From ab8d15c6e38b05c648746f5db8940ae6a615b050 Mon Sep 17 00:00:00 2001 From: TheTank20 Date: Wed, 23 Jul 2025 02:37:07 -0500 Subject: [PATCH 2/3] library --- CMakeLists.txt | 28 ++- xpmgr.cpp | 572 ++++--------------------------------------------- xpmgr.h | 24 +++ xpmgr_lib.cpp | 389 +++++++++++++++++++++++++++++++++ 4 files changed, 481 insertions(+), 532 deletions(-) create mode 100644 xpmgr.h create mode 100644 xpmgr_lib.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 41dd7db..a061e31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,15 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(SOURCES xpmgr.cpp) +set(LIB_SOURCES xpmgr_lib.cpp) # ==== x86 build ==== + +# Static library for x86 +add_library(xpmgr_static_x86 STATIC ${LIB_SOURCES}) +target_compile_options(xpmgr_static_x86 PRIVATE -m32) +target_link_libraries(xpmgr_static_x86 PRIVATE ole32 oleaut32 uuid) + set(RES_X86 ${CMAKE_BINARY_DIR}/icon_x86.res) # Create a custom target for the x86 resource compilation @@ -26,11 +33,17 @@ add_dependencies(xpmgr_x86 xpmgr_x86_res) target_compile_options(xpmgr_x86 PRIVATE -m32) target_link_options(xpmgr_x86 PRIVATE -m32) -# Link .res file as a resource -target_link_libraries(xpmgr_x86 PRIVATE ole32 oleaut32 uuid) +# Link .res file and static library +target_link_libraries(xpmgr_x86 PRIVATE ole32 oleaut32 uuid xpmgr_static_x86) target_link_options(xpmgr_x86 PRIVATE -Wl,--subsystem,console ${RES_X86}) # ==== x64 build ==== + +# Static library for x64 +add_library(xpmgr_static_x64 STATIC ${LIB_SOURCES}) +target_compile_options(xpmgr_static_x64 PRIVATE -m64) +target_link_libraries(xpmgr_static_x64 PRIVATE ole32 oleaut32 uuid) + set(RES_X64 ${CMAKE_BINARY_DIR}/icon_x64.res) # Create a custom target for the x64 resource compilation @@ -50,6 +63,13 @@ add_dependencies(xpmgr_x64 xpmgr_x64_res) target_compile_options(xpmgr_x64 PRIVATE -m64) target_link_options(xpmgr_x64 PRIVATE -m64) -# Link .res file as a resource -target_link_libraries(xpmgr_x64 PRIVATE ole32 oleaut32 uuid) +# Link .res file and static library +target_link_libraries(xpmgr_x64 PRIVATE ole32 oleaut32 uuid xpmgr_static_x64) target_link_options(xpmgr_x64 PRIVATE -Wl,--subsystem,console ${RES_X64}) + +# Install targets +install(TARGETS xpmgr_static_x86 xpmgr_static_x64 + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + +install(FILES xpmgr.h DESTINATION include) diff --git a/xpmgr.cpp b/xpmgr.cpp index 339dcca..fa9a0b8 100644 --- a/xpmgr.cpp +++ b/xpmgr.cpp @@ -3,525 +3,15 @@ typedef struct IUnknown IUnknown; #include #include -#include -#include -#include #include +#include +#include "xpmgr.h" -// Check windows -#if _WIN32 || _WIN64 -#if _WIN64 -#define ENVIRONMENT64 -#else -#define ENVIRONMENT32 -#endif -#endif - -// Forward declarations of helper functions -BSTR FormatErrorMessage(const char* context, HRESULT status, ULONG returnCode = 0); -std::string ConvertToStdString(BSTR bstr); -BSTR ConvertCharToBSTR(const char* charString); - -const char* specifiedProduct = nullptr; - -// This is a really weird way of making a GUID. In short, this becomes ACADF079-CBCD-4032-83F2-FA47C4DB096F. Ignore the 0x and it makes sense. -static CLSID XP_CLSID = { 0xACADF079, 0xCBCD, 0x4032, {0x83, 0xF2, 0xFA, 0x47, 0xC4, 0xDB, 0x09, 0x6F} }; -static IID XP_IID = { 0xB8CBAD79, 0x3F1F, 0x481A, { 0xBB, 0x0C, 0xE7, 0xBB, 0xD7, 0x7B, 0xDD, 0xD1 } }; - -#undef XP_INTERFACE -#define XP_INTERFACE ICOMLicenseAgent -DECLARE_INTERFACE_(ICOMLicenseAgent, IDispatch) -{ -protected: - ~ICOMLicenseAgent() = default; - -public: - - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; - STDMETHOD_(ULONG, AddRef)() PURE; - STDMETHOD_(ULONG, Release)() PURE; - - /*** IDispatch methods ***/ - STDMETHOD(GetTypeInfoCount)(THIS_ UINT FAR * pctinfo) PURE; - STDMETHOD(GetTypeInfo)(THIS_ UINT itinfo, LCID lcid, ITypeInfo FAR * FAR * pptinfo) PURE; - STDMETHOD(GetIDsOfNames)(THIS_ REFIID riid, OLECHAR FAR * FAR * rgszNames, UINT cNames, LCID lcid, DISPID FAR * rgdispid) PURE; - STDMETHOD(Invoke)(THIS_ DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR * pdispparams, VARIANT FAR * pvarResult, EXCEPINFO FAR * pexcepinfo, UINT FAR * puArgErr) PURE; - - /*** ICOMLicenseAgent methods ***/ - STDMETHOD(Initialize)(THIS_ ULONG dwBPC, ULONG dwMode, BSTR bstrLicSource, ULONG * pdwRetCode) PURE; - STDMETHOD(GetFirstName)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetFirstName)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetLastName)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetLastName)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetOrgName)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetOrgName)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetEmail)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetEmail)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetPhone)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetPhone)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetAddress1)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetAddress1)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetCity)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetCity)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetState)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetState)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetCountryCode)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetCountryCode)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetCountryDesc)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetCountryDesc)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetZip)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetZip)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetIsoLanguage)(THIS_ ULONG * pdwVal) PURE; - STDMETHOD(SetIsoLanguage)(THIS_ ULONG dwNewVal) PURE; - STDMETHOD(GetMSUpdate)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetMSUpdate)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetMSOffer)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetMSOffer)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetOtherOffer)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetOtherOffer)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(GetAddress2)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(SetAddress2)(THIS_ BSTR bstrNewVal) PURE; - STDMETHOD(AsyncProcessHandshakeRequest)(THIS_ LONG bReviseCustInfo) PURE; - STDMETHOD(AsyncProcessNewLicenseRequest)() PURE; - STDMETHOD(AsyncProcessReissueLicenseRequest)() PURE; - STDMETHOD(AsyncProcessReviseCustInfoRequest)() PURE; - STDMETHOD(GetAsyncProcessReturnCode)(THIS_ ULONG * pdwRetCode) PURE; - STDMETHOD(AsyncProcessDroppedLicenseRequest)() PURE; - STDMETHOD(GenerateInstallationId)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(DepositConfirmationId)(THIS_ BSTR bstrVal, ULONG * pdwRetCode) PURE; - STDMETHOD(GetExpirationInfo)(THIS_ ULONG * pdwWPALeft, ULONG * pdwEvalLeft) PURE; - STDMETHOD(AsyncProcessRegistrationRequest)() PURE; - STDMETHOD(ProcessHandshakeRequest)(THIS_ LONG bReviseCustInfo) PURE; - STDMETHOD(ProcessNewLicenseRequest)() PURE; - STDMETHOD(ProcessDroppedLicenseRequest)() PURE; - STDMETHOD(ProcessReissueLicenseRequest)() PURE; - STDMETHOD(ProcessReviseCustInfoRequest)() PURE; - STDMETHOD(EnsureInternetConnection)() PURE; - STDMETHOD(SetProductKey)(THIS_ LPWSTR pszNewProductKey) PURE; - STDMETHOD(GetProductID)(THIS_ BSTR * pbstrVal) PURE; - STDMETHOD(VerifyCheckDigits)(THIS_ BSTR bstrCIDIID, LONG * pbValue) PURE; -}; - -static BOOL XP_ComInitialized = FALSE; -static ICOMLicenseAgent* XP_LicenseAgent = nullptr; - -static BOOL XP_LoadLicenseManager() { - if (!XP_ComInitialized) { - const HRESULT status = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - if (FAILED(status)) { - std::cout << ConvertToStdString(FormatErrorMessage("CoInitializeEx", status)); - return FALSE; - } - XP_ComInitialized = TRUE; - } - - if (!XP_LicenseAgent) { - HRESULT status = CoCreateInstance(XP_CLSID, nullptr, CLSCTX_INPROC_SERVER, XP_IID, reinterpret_cast(&XP_LicenseAgent)); - if (SUCCEEDED(status)) { - ULONG dwRetCode; - status = XP_LicenseAgent->Initialize(0xC475, 3, nullptr, &dwRetCode); - if (SUCCEEDED(status) && dwRetCode == 0) { - return TRUE; - } - XP_LicenseAgent->Release(); - XP_LicenseAgent = nullptr; - } - std::cout << ConvertToStdString(FormatErrorMessage("CoCreateInstance", status)); - return FALSE; - } - return TRUE; -} - -#pragma region Internals - -// Add function to read from stdin -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 ""; -} - -wchar_t* convertCharArrayToLPCWSTR(const char* charArray) -{ - auto* wString = new wchar_t[4096]; - MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096); - return wString; -} - -char* getCmdOption(char** begin, char** end, const std::string& option) -{ - char** itr = std::find(begin, end, option); - if (itr != end && ++itr != end) - { - return *itr; - } - return nullptr; -} - -bool cmdOptionExists(char** begin, char** end, const std::string& option) -{ - return std::find(begin, end, option) != end; -} - -char* BstrToChar(BSTR bstr) -{ - const int len = static_cast(::SysStringLen(bstr)); - const int bufSize = ::WideCharToMultiByte(CP_UTF8, 0, bstr, len, nullptr, 0, nullptr, nullptr); - const auto buffer = new char[bufSize + 1]; - ::WideCharToMultiByte(CP_UTF8, 0, bstr, len, buffer, bufSize, nullptr, nullptr); - buffer[bufSize] = '\0'; - return buffer; -} - -ULONG ConvertToULONG(const char* str) -{ - char* end; - const ULONG value = std::strtoul(str, &end, 10); - return value; -} - -OLECHAR SizeToOLECHAR(size_t value) -{ - // Convert size_t to wstring - const std::wstring wideString = std::to_wstring(value); - - // Retrieve the first character from the wide string - const OLECHAR oChar = wideString[0]; - - return oChar; -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -void safeStrncat(char* destination, const char* source, size_t size) { - const size_t destLen = strlen(destination); - const size_t srcLen = strlen(source); - - if (destLen + srcLen < size) { - // fuck off Microsoft - strncat(destination, source, size - destLen - 1); // -1 for the null terminator - } else { - // Handle buffer overflow error - std::cout << "An error occurred at safeStrncat: Buffer overflow during strncat operation." << std::endl; - } -} -#pragma clang diagnostic pop - -#pragma region Process Management - -struct ProcessHandle { - HANDLE handle; - explicit ProcessHandle(HANDLE h) : handle(h) {} - ~ProcessHandle() { if (handle != INVALID_HANDLE_VALUE) CloseHandle(handle); } - operator HANDLE() const { return handle; } -}; - -bool IsProcessRunning(const wchar_t* processName) { - ProcessHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); - if (snapshot == INVALID_HANDLE_VALUE) { - std::cout << "Failed to create process snapshot: " << GetLastError() << std::endl; - return false; - } - - PROCESSENTRY32W processEntry{}; - processEntry.dwSize = sizeof(PROCESSENTRY32W); - - if (!Process32FirstW(snapshot, &processEntry)) { - std::cout << "Failed to retrieve process information: " << GetLastError() << std::endl; - return false; - } - - do { - if (wcscmp(processEntry.szExeFile, processName) == 0) { - return true; - } - } while (Process32NextW(snapshot, &processEntry)); - - return false; -} - -bool TerminateProcessByName(const wchar_t* processName) { - ProcessHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); - if (snapshot == INVALID_HANDLE_VALUE) { - std::cout << "Failed to create process snapshot: " << GetLastError() << std::endl; - return false; - } - - PROCESSENTRY32W processEntry{}; - processEntry.dwSize = sizeof(PROCESSENTRY32W); - - if (!Process32FirstW(snapshot, &processEntry)) { - std::cout << "Failed to retrieve process information: " << GetLastError() << std::endl; - return false; - } - - do { - if (wcscmp(processEntry.szExeFile, processName) == 0) { - ProcessHandle processHandle(OpenProcess(PROCESS_TERMINATE, FALSE, processEntry.th32ProcessID)); - if (processHandle == nullptr) { - std::cout << "Failed to open process: " << GetLastError() << std::endl; - return false; - } - - if (!TerminateProcess(processHandle, 0)) { - std::cout << "Failed to terminate process: " << GetLastError() << std::endl; - return false; - } - - return true; - } - } while (Process32NextW(snapshot, &processEntry)); - - std::cout << "Process not found: " << ConvertToStdString(ConvertCharToBSTR(reinterpret_cast(processName))) << std::endl; - return false; -} - -#pragma endregion - -#pragma region Helper Functions - -BSTR ConvertCharToBSTR(const char* charString) { - if (!charString) return nullptr; - const int size = MultiByteToWideChar(CP_UTF8, 0, charString, -1, nullptr, 0); - BSTR bstr = SysAllocStringLen(nullptr, size - 1); - MultiByteToWideChar(CP_UTF8, 0, charString, -1, bstr, size); - return bstr; -} - -std::string ConvertToStdString(BSTR bstr) { - if (!bstr) return ""; - const int size = WideCharToMultiByte(CP_UTF8, 0, bstr, -1, nullptr, 0, nullptr, nullptr); - std::string result(size - 1, '\0'); - WideCharToMultiByte(CP_UTF8, 0, bstr, -1, &result[0], size, nullptr, nullptr); - return result; -} - -BSTR FormatErrorMessage(const char* context, HRESULT status, ULONG returnCode) { - std::string errorMsg = "An error occurred at " + std::string(context) + ": "; - char statusBuffer[32]; - snprintf(statusBuffer, sizeof(statusBuffer), "0x%08X", static_cast(status)); - errorMsg += statusBuffer; - - if (returnCode != 0) { - char returnCodeBuffer[32]; - snprintf(returnCodeBuffer, sizeof(returnCodeBuffer), " %lu", returnCode); - errorMsg += returnCodeBuffer; - } - - return ConvertCharToBSTR(errorMsg.c_str()); -} - -#pragma region Windows XP -static BSTR XP_GetWPALeft() { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } - - ULONG dwWPALeft = 0, dwEvalLeft = 0; - const HRESULT status = XP_LicenseAgent->GetExpirationInfo(&dwWPALeft, &dwEvalLeft); - if (FAILED(status)) { - XP_LicenseAgent->Release(); - XP_LicenseAgent = nullptr; - return FormatErrorMessage("GetExpirationInfo", status); - } - if (dwWPALeft == 0x7FFFFFFF) { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } - wchar_t buffer[16]; - swprintf(buffer, L"%lu", dwWPALeft); - return SysAllocString(buffer); -} - -static BSTR XP_GetEvalLeft() { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } - - ULONG dwWPALeft = 0, dwEvalLeft = 0; - const HRESULT status = XP_LicenseAgent->GetExpirationInfo(&dwWPALeft, &dwEvalLeft); - if (FAILED(status)) { - XP_LicenseAgent->Release(); - XP_LicenseAgent = nullptr; - return FormatErrorMessage("GetExpirationInfo", status); - } - if (dwEvalLeft == 0x7FFFFFFF) { - return SysAllocString(L"An error occurred at GetEvalLeft: Not an evaluation copy"); - } - wchar_t buffer[16]; - swprintf(buffer, L"%lu", dwEvalLeft); - return SysAllocString(buffer); -} - -#pragma region Windows XP Activation - -enum class VerificationResult { - Success, - InvalidFormat, - VerificationFailed, - AlreadyActivated, - LoadError -}; - -static VerificationResult VerifyConfirmationIDChunk(const std::string& chunk) { - if (chunk.length() != 6) { - return VerificationResult::InvalidFormat; - } - - LONG pbValue; - const HRESULT status = XP_LicenseAgent->VerifyCheckDigits(ConvertCharToBSTR(chunk.c_str()), &pbValue); - return (SUCCEEDED(status) && pbValue) ? VerificationResult::Success : VerificationResult::VerificationFailed; -} - -static BSTR XP_VerifyCheckDigits(BSTR cidChunk) { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } - - const std::string activationCheck = ConvertToStdString(XP_GetWPALeft()); - if (activationCheck == "An error occurred at GetWPALeft: Windows is activated") { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } - - LONG pbValue; - const HRESULT status = XP_LicenseAgent->VerifyCheckDigits(cidChunk, &pbValue); - return SUCCEEDED(status) && pbValue - ? SysAllocString(L"Successfully verified CID chunk") - : FormatErrorMessage("XP_VerifyCheckDigits", status); -} - -static BSTR XP_SetConfirmationID(BSTR confirmationID) { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } - - const std::string activationCheck = ConvertToStdString(XP_GetWPALeft()); - if (activationCheck == "An error occurred at GetWPALeft: Windows is activated") { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } - - // Convert and clean up the confirmation ID - std::string cidStr = ConvertToStdString(confirmationID); - cidStr.erase(std::remove(cidStr.begin(), cidStr.end(), '-'), cidStr.end()); - - // Verify each 6-character chunk - for (size_t i = 0; i < cidStr.length(); i += 6) { - const std::string chunk = cidStr.substr(i, 6); - const auto result = VerifyConfirmationIDChunk(chunk); - - switch (result) { - case VerificationResult::InvalidFormat: - return SysAllocString(L"An error occurred: Invalid confirmation ID format"); - case VerificationResult::VerificationFailed: - return SysAllocString(L"An error occurred: Confirmation ID verification failed"); - case VerificationResult::Success: - continue; - default: - return SysAllocString(L"An error occurred: Unexpected verification result"); - } - } - - // Deposit the full confirmation ID - ULONG dwRetCode; - const HRESULT status = XP_LicenseAgent->DepositConfirmationId(confirmationID, &dwRetCode); - if (FAILED(status) || dwRetCode) { - return FormatErrorMessage("DepositConfirmationId", status, dwRetCode); - } - - // Handle WPA notifier process - if (IsProcessRunning(L"wpabaln.exe")) { - if (!TerminateProcessByName(L"wpabaln.exe")) { - std::cout << "Warning: Failed to terminate WPA notifier process" << std::endl; - } - } - - // Clean up activation files - HMODULE hMod = LoadLibraryW(L"setupapi.dll"); - if (hMod) { - using InstallHinfSectionFunc = BOOL (WINAPI*)(HWND, HINSTANCE, PCWSTR, INT); - if (auto installHinfSection = reinterpret_cast(GetProcAddress(hMod, "InstallHinfSectionW"))) { - SetLastError(0); - const BOOL result = installHinfSection(nullptr, nullptr, L"DEL_OOBE_ACTIVATE 132 syssetup.inf", 132); - const DWORD error = GetLastError(); - - if (!result && error != 0 && error != 6) { // Ignore error 6 (ERROR_INVALID_HANDLE) as it indicates success - std::cout << "Warning: Failed to remove activation reminders. Error: " << error << std::endl; - std::cout << "You can try to run the following command yourself: " << std::endl; - std::cout << "rundll32 setupapi,InstallHinfSection DEL_OOBE_ACTIVATE 132 syssetup.inf" << std::endl; - } - } - FreeLibrary(hMod); - } - - return SysAllocString(L"Successfully set confirmation ID"); -} - -static BSTR XP_GetInstallationID() { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } - if (0 == wcscmp(XP_GetWPALeft(), L"An error occurred at GetWPALeft: Windows is activated")) { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } - - BSTR installationID = nullptr; - const HRESULT status = XP_LicenseAgent->GenerateInstallationId(&installationID); - if (FAILED(status) || !installationID) { - return FormatErrorMessage("GenerateInstallationId", status); - } - return installationID; -} - -static BSTR XP_SetProductKey(LPWSTR productKey) { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } - - if (0 == wcscmp(XP_GetWPALeft(), L"An error occurred at GetWPALeft: Windows is activated")) { - return SysAllocString(L"An error occurred at GetWPALeft: Windows is activated"); - } - - // Validate product key format - std::wstring ws(productKey); - const std::string productKeyToRegex = std::string(ws.begin(), ws.end()); - const std::regex pattern("[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}"); - - if (!std::regex_match(productKeyToRegex, pattern)) { - return SysAllocString(L"An error occurred at regex_match: Product key is invalid"); - } - - const HRESULT status = XP_LicenseAgent->SetProductKey(productKey); - if (FAILED(status)) { - return FormatErrorMessage("SetProductKey", status); - } - return SysAllocString(L"Successfully set product key"); -} - -static BSTR XP_GetProductID() { - if (!XP_LoadLicenseManager()) { - return SysAllocString(L"An error occurred at XP_LoadLicenseManager: Failed to load"); - } - - BSTR productID = nullptr; - const HRESULT status = XP_LicenseAgent->GetProductID(&productID); - if (FAILED(status)) { - return FormatErrorMessage("GetProductID", status); - } - return productID; -} -#pragma endregion - -#pragma region Command Line Handling - +// Command line handling struct CommandLineArgs { static const char* getCmdOption(char** begin, char** end, const std::string& option) { - char** itr = std::find(begin, end, 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; } @@ -529,12 +19,14 @@ struct CommandLineArgs { } static bool cmdOptionExists(char** begin, char** end, const std::string& option) { - return std::find(begin, end, option) != end; + 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()); @@ -544,10 +36,21 @@ struct CommandLineArgs { } }; -#pragma endregion +// 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; +} + +// 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; +} -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" int main(int argc, char* argv[]) { const char* USAGE_TEXT = "xpmgr - Windows XP License Manager (compiled on " __DATE__ " " __TIME__ ")\n" @@ -607,52 +110,65 @@ int main(int argc, char* argv[]) { } #endif + // Initialize the library + XPMGR_Initialize(); + // Handle commands + const wchar_t* result = nullptr; if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/dti")) { - std::cout << ConvertToStdString(XP_GetInstallationID()); + result = XPMGR_GetInstallationID(); } else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/atp")) { const char* confirmationId = CommandLineArgs::getCmdOption(argv, argv + argc, "/atp"); if (!confirmationId) { std::string pipedInput = CommandLineArgs::readFromStdin(); if (!pipedInput.empty()) { - std::cout << ConvertToStdString(XP_SetConfirmationID(ConvertCharToBSTR(pipedInput.c_str()))); + 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; } } else { - std::cout << ConvertToStdString(XP_SetConfirmationID(ConvertCharToBSTR(confirmationId))); + result = XPMGR_SetConfirmationID(convertCharArrayToLPCWSTR(confirmationId)); } } else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/xpr")) { - std::cout << ConvertToStdString(XP_GetWPALeft()); + result = XPMGR_GetWPALeft(); } else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/xpr-eval")) { - std::cout << ConvertToStdString(XP_GetEvalLeft()); + result = XPMGR_GetEvalLeft(); } else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/ipk")) { const char* productKey = CommandLineArgs::getCmdOption(argv, argv + argc, "/ipk"); if (!productKey) { std::string pipedInput = CommandLineArgs::readFromStdin(); if (!pipedInput.empty()) { - std::cout << ConvertToStdString(XP_SetProductKey(convertCharArrayToLPCWSTR(pipedInput.c_str()))); + 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; } } else { - std::cout << ConvertToStdString(XP_SetProductKey(convertCharArrayToLPCWSTR(productKey))); + result = XPMGR_SetProductKey(convertCharArrayToLPCWSTR(productKey)); } } else if (CommandLineArgs::cmdOptionExists(argv, argv + argc, "/dli")) { - std::cout << ConvertToStdString(XP_GetProductID()); + result = XPMGR_GetProductID(); } else { std::cout << "An error occurred: No arguments listed\n\n" << USAGE_TEXT; + XPMGR_Cleanup(); return 7; } + if (result) { + char* output = convertWCharToChar(result); + std::cout << output; + delete[] output; + } + + XPMGR_Cleanup(); return 0; } -#pragma clang diagnostic pop diff --git a/xpmgr.h b/xpmgr.h new file mode 100644 index 0000000..df55e2d --- /dev/null +++ b/xpmgr.h @@ -0,0 +1,24 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +// Core functions that match command line options +const wchar_t* XPMGR_GetInstallationID(); // /dti +const wchar_t* XPMGR_SetConfirmationID(const wchar_t* confirmationId); // /atp +const wchar_t* XPMGR_GetWPALeft(); // /xpr +const wchar_t* XPMGR_GetEvalLeft(); // /xpr-eval +const wchar_t* XPMGR_SetProductKey(const wchar_t* productKey); // /ipk +const wchar_t* XPMGR_GetProductID(); // /dli + +// Additional utility functions +const wchar_t* XPMGR_GetLastError(); +void XPMGR_Initialize(); +void XPMGR_Cleanup(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/xpmgr_lib.cpp b/xpmgr_lib.cpp new file mode 100644 index 0000000..12ba57a --- /dev/null +++ b/xpmgr_lib.cpp @@ -0,0 +1,389 @@ +#include "xpmgr.h" +#include +#include +#include +#include +#include +#include +#include +#include + +// CLSID and IID definitions +static CLSID XP_CLSID = { 0xACADF079, 0xCBCD, 0x4032, {0x83, 0xF2, 0xFA, 0x47, 0xC4, 0xDB, 0x09, 0x6F} }; +static IID XP_IID = { 0xB8CBAD79, 0x3F1F, 0x481A, { 0xBB, 0x0C, 0xE7, 0xBB, 0xD7, 0x7B, 0xDD, 0xD1 } }; + +// Interface definition +DECLARE_INTERFACE_(ICOMLicenseAgent, IDispatch) +{ +protected: + ~ICOMLicenseAgent() = default; + +public: + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID* ppvObj) PURE; + STDMETHOD_(ULONG, AddRef)() PURE; + STDMETHOD_(ULONG, Release)() PURE; + + /*** IDispatch methods ***/ + STDMETHOD(GetTypeInfoCount)(THIS_ UINT FAR* pctinfo) PURE; + STDMETHOD(GetTypeInfo)(THIS_ UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo) PURE; + STDMETHOD(GetIDsOfNames)(THIS_ REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames, LCID lcid, DISPID FAR* rgdispid) PURE; + STDMETHOD(Invoke)(THIS_ DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr) PURE; + + /*** ICOMLicenseAgent methods ***/ + STDMETHOD(Initialize)(THIS_ ULONG dwBPC, ULONG dwMode, BSTR bstrLicSource, ULONG* pdwRetCode) PURE; + STDMETHOD(GetFirstName)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetFirstName)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetLastName)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetLastName)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetOrgName)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetOrgName)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetEmail)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetEmail)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetPhone)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetPhone)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetAddress1)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetAddress1)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetCity)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetCity)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetState)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetState)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetCountryCode)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetCountryCode)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetCountryDesc)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetCountryDesc)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetZip)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetZip)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetIsoLanguage)(THIS_ ULONG* pdwVal) PURE; + STDMETHOD(SetIsoLanguage)(THIS_ ULONG dwNewVal) PURE; + STDMETHOD(GetMSUpdate)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetMSUpdate)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetMSOffer)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetMSOffer)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetOtherOffer)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetOtherOffer)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(GetAddress2)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(SetAddress2)(THIS_ BSTR bstrNewVal) PURE; + STDMETHOD(AsyncProcessHandshakeRequest)(THIS_ LONG bReviseCustInfo) PURE; + STDMETHOD(AsyncProcessNewLicenseRequest)() PURE; + STDMETHOD(AsyncProcessReissueLicenseRequest)() PURE; + STDMETHOD(AsyncProcessReviseCustInfoRequest)() PURE; + STDMETHOD(GetAsyncProcessReturnCode)(THIS_ ULONG* pdwRetCode) PURE; + STDMETHOD(AsyncProcessDroppedLicenseRequest)() PURE; + STDMETHOD(GenerateInstallationId)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(DepositConfirmationId)(THIS_ BSTR bstrVal, ULONG* pdwRetCode) PURE; + STDMETHOD(GetExpirationInfo)(THIS_ ULONG* pdwWPALeft, ULONG* pdwEvalLeft) PURE; + STDMETHOD(AsyncProcessRegistrationRequest)() PURE; + STDMETHOD(ProcessHandshakeRequest)(THIS_ LONG bReviseCustInfo) PURE; + STDMETHOD(ProcessNewLicenseRequest)() PURE; + STDMETHOD(ProcessDroppedLicenseRequest)() PURE; + STDMETHOD(ProcessReissueLicenseRequest)() PURE; + STDMETHOD(ProcessReviseCustInfoRequest)() PURE; + STDMETHOD(EnsureInternetConnection)() PURE; + STDMETHOD(SetProductKey)(THIS_ LPWSTR pszNewProductKey) PURE; + STDMETHOD(GetProductID)(THIS_ BSTR* pbstrVal) PURE; + STDMETHOD(VerifyCheckDigits)(THIS_ BSTR bstrCIDIID, LONG* pbValue) PURE; +}; + +// Static variables +static BOOL XP_ComInitialized = FALSE; +static ICOMLicenseAgent* XP_LicenseAgent = nullptr; +static wchar_t LastErrorMessage[1024] = L""; + +// Helper functions +static void SetLastErrorMessage(const wchar_t* message) { + wcscpy(LastErrorMessage, message); +} + +static BOOL XP_LoadLicenseManager() { + if (!XP_ComInitialized) { + const HRESULT status = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (FAILED(status)) { + SetLastErrorMessage(L"Failed to initialize COM"); + return FALSE; + } + XP_ComInitialized = TRUE; + } + + if (!XP_LicenseAgent) { + HRESULT status = CoCreateInstance(XP_CLSID, nullptr, CLSCTX_INPROC_SERVER, XP_IID, reinterpret_cast(&XP_LicenseAgent)); + if (SUCCEEDED(status)) { + ULONG dwRetCode; + status = XP_LicenseAgent->Initialize(0xC475, 3, nullptr, &dwRetCode); + if (SUCCEEDED(status) && dwRetCode == 0) { + return TRUE; + } + XP_LicenseAgent->Release(); + XP_LicenseAgent = nullptr; + } + SetLastErrorMessage(L"Failed to create license manager instance"); + return FALSE; + } + return TRUE; +} + +// Helper function to verify a confirmation ID chunk +static bool VerifyConfirmationIDChunk(ICOMLicenseAgent* agent, const wchar_t* chunk) { + LONG pbValue = 0; + BSTR bstrChunk = SysAllocString(chunk); + HRESULT status = agent->VerifyCheckDigits(bstrChunk, &pbValue); + SysFreeString(bstrChunk); + return SUCCEEDED(status) && pbValue != 0; +} + +struct ProcessHandle { + HANDLE handle; + explicit ProcessHandle(HANDLE h) : handle(h) {} + ~ProcessHandle() { if (handle != INVALID_HANDLE_VALUE) CloseHandle(handle); } + operator HANDLE() const { return handle; } +}; + +bool IsProcessRunning(const wchar_t* processName) { + ProcessHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + if (snapshot == INVALID_HANDLE_VALUE) { + std::cout << "Failed to create process snapshot: " << GetLastError() << std::endl; + return false; + } + + PROCESSENTRY32W processEntry{}; + processEntry.dwSize = sizeof(PROCESSENTRY32W); + + if (!Process32FirstW(snapshot, &processEntry)) { + std::cout << "Failed to retrieve process information: " << GetLastError() << std::endl; + return false; + } + + do { + if (wcscmp(processEntry.szExeFile, processName) == 0) { + return true; + } + } while (Process32NextW(snapshot, &processEntry)); + + return false; +} + +bool TerminateProcessByName(const wchar_t* processName) { + ProcessHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + if (snapshot == INVALID_HANDLE_VALUE) { + std::cout << "Failed to create process snapshot: " << GetLastError() << std::endl; + return false; + } + + PROCESSENTRY32W processEntry{}; + processEntry.dwSize = sizeof(PROCESSENTRY32W); + + if (!Process32FirstW(snapshot, &processEntry)) { + std::cout << "Failed to retrieve process information: " << GetLastError() << std::endl; + return false; + } + + do { + if (wcscmp(processEntry.szExeFile, processName) == 0) { + ProcessHandle processHandle(OpenProcess(PROCESS_TERMINATE, FALSE, processEntry.th32ProcessID)); + if (processHandle == nullptr) { + std::cout << "Failed to open process: " << GetLastError() << std::endl; + return false; + } + + if (!TerminateProcess(processHandle, 0)) { + std::cout << "Failed to terminate process: " << GetLastError() << std::endl; + return false; + } + + return true; + } + } while (Process32NextW(snapshot, &processEntry)); + + std::cout << "Process not found: " << processName << std::endl; + return false; +} + +// Exported functions implementation +extern "C" { + +void XPMGR_Initialize() { + XP_LoadLicenseManager(); +} + +void XPMGR_Cleanup() { + if (XP_LicenseAgent) { + XP_LicenseAgent->Release(); + XP_LicenseAgent = nullptr; + } + if (XP_ComInitialized) { + CoUninitialize(); + XP_ComInitialized = FALSE; + } +} + +const wchar_t* XPMGR_GetLastError() { + return LastErrorMessage; +} + +const wchar_t* XPMGR_GetInstallationID() { + if (!XP_LoadLicenseManager()) { + return XPMGR_GetLastError(); + } + + BSTR installationID = nullptr; + const HRESULT status = XP_LicenseAgent->GenerateInstallationId(&installationID); + if (FAILED(status) || !installationID) { + SetLastErrorMessage(L"Failed to generate installation ID"); + return XPMGR_GetLastError(); + } + + static wchar_t result[256]; + wcscpy(result, installationID); + SysFreeString(installationID); + return result; +} + +const wchar_t* XPMGR_SetConfirmationID(const wchar_t* confirmationId) { + if (!XP_LoadLicenseManager()) { + return XPMGR_GetLastError(); + } + + // Create a working copy and remove dashes + wchar_t cleanCid[256] = {0}; + const wchar_t* src = confirmationId; + wchar_t* dst = cleanCid; + while (*src) { + if (*src != L'-') { + *dst++ = *src; + } + src++; + } + *dst = 0; + + // Verify each 6-character chunk + size_t len = wcslen(cleanCid); + for (size_t i = 0; i < len; i += 6) { + wchar_t chunk[7] = {0}; + wcsncpy(chunk, cleanCid + i, 6); + if (!VerifyConfirmationIDChunk(XP_LicenseAgent, chunk)) { + SetLastErrorMessage(L"Invalid confirmation ID - verification failed"); + return XPMGR_GetLastError(); + } + } + + // Pass the original confirmation ID (with dashes if present) to the API + BSTR bstrConfirmationId = SysAllocString(confirmationId); + ULONG dwRetCode; + const HRESULT status = XP_LicenseAgent->DepositConfirmationId(bstrConfirmationId, &dwRetCode); + SysFreeString(bstrConfirmationId); + + if (FAILED(status) || dwRetCode) { + SetLastErrorMessage(L"Failed to deposit confirmation ID"); + return XPMGR_GetLastError(); + } + + // Handle WPA notifier process + if (IsProcessRunning(L"wpabaln.exe")) { + if (!TerminateProcessByName(L"wpabaln.exe")) { + std::cout << "Warning: Failed to terminate WPA notifier process." << std::endl; + } + } + + // Clean up activation files + HMODULE hMod = LoadLibraryW(L"setupapi.dll"); + if (hMod) { + using InstallHinfSectionFunc = BOOL (WINAPI*)(HWND, HINSTANCE, PCWSTR, INT); + if (auto installHinfSection = reinterpret_cast(GetProcAddress(hMod, "InstallHinfSectionW"))) { + SetLastError(0); + const BOOL result = installHinfSection(nullptr, nullptr, L"DEL_OOBE_ACTIVATE 132 syssetup.inf", 132); + const DWORD error = GetLastError(); + + if (!result && error != 0 && error != 6) { // Ignore error 6 (ERROR_INVALID_HANDLE) as it indicates success + std::cout << "Warning: Failed to remove activation reminders. Error: " << error << std::endl; + std::cout << "You can try to run the following command yourself: " << std::endl; + std::cout << "rundll32 setupapi,InstallHinfSection DEL_OOBE_ACTIVATE 132 syssetup.inf" << std::endl; + } + } + FreeLibrary(hMod); + } + + return L"Successfully set confirmation ID"; +} + +const wchar_t* XPMGR_GetWPALeft() { + if (!XP_LoadLicenseManager()) { + return XPMGR_GetLastError(); + } + + ULONG dwWPALeft = 0, dwEvalLeft = 0; + const HRESULT status = XP_LicenseAgent->GetExpirationInfo(&dwWPALeft, &dwEvalLeft); + if (FAILED(status)) { + SetLastErrorMessage(L"Failed to get expiration info"); + return XPMGR_GetLastError(); + } + + if (dwWPALeft == 0x7FFFFFFF) { + return L"Windows is activated"; + } + + static wchar_t result[16]; + _ultow(dwWPALeft, result, 10); + return result; +} + +const wchar_t* XPMGR_GetEvalLeft() { + if (!XP_LoadLicenseManager()) { + return XPMGR_GetLastError(); + } + + ULONG dwWPALeft = 0, dwEvalLeft = 0; + const HRESULT status = XP_LicenseAgent->GetExpirationInfo(&dwWPALeft, &dwEvalLeft); + if (FAILED(status)) { + SetLastErrorMessage(L"Failed to get expiration info"); + return XPMGR_GetLastError(); + } + + if (dwEvalLeft == 0x7FFFFFFF) { + return L"Not an evaluation copy"; + } + + static wchar_t result[16]; + _ultow(dwEvalLeft, result, 10); + return result; +} + +const wchar_t* XPMGR_SetProductKey(const wchar_t* productKey) { + if (!XP_LoadLicenseManager()) { + return XPMGR_GetLastError(); + } + + // Validate product key format + std::wregex pattern(L"[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}-[2346789BCDFGHJKMPQRTVWXY]{5}"); + if (!std::regex_match(productKey, pattern)) { + SetLastErrorMessage(L"Invalid product key format"); + return XPMGR_GetLastError(); + } + + const HRESULT status = XP_LicenseAgent->SetProductKey(const_cast(productKey)); + if (FAILED(status)) { + SetLastErrorMessage(L"Failed to set product key"); + return XPMGR_GetLastError(); + } + + return L"Successfully set product key"; +} + +const wchar_t* XPMGR_GetProductID() { + if (!XP_LoadLicenseManager()) { + return XPMGR_GetLastError(); + } + + BSTR productID = nullptr; + const HRESULT status = XP_LicenseAgent->GetProductID(&productID); + if (FAILED(status) || !productID) { + SetLastErrorMessage(L"Failed to get product ID"); + return XPMGR_GetLastError(); + } + + static wchar_t result[256]; + wcscpy(result, productID); + SysFreeString(productID); + return result; +} + +} \ No newline at end of file From ee066856af47e5273e692362d51afd05a5b96e8a Mon Sep 17 00:00:00 2001 From: TheTank20 Date: Wed, 23 Jul 2025 02:38:54 -0500 Subject: [PATCH 3/3] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ae4ce50..faaa8bf 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ If you have an Itanium version of Windows XP or Server 2003, Windows Product Act `/ipk` and `/dti` also support reading from stdin via a pipe. So, you could do something like `echo FCKGW-RHQQ2-YXRKT-8TG6W-2B7Q8 | xpmgr_x86 /ipk` or `echo 253286028742154311079061239762245184619981623171292574 | xpmgr_x86 /atp` (replace echo with your own program). +This can also be used as a library; see the xpmgr.h file for details. + ## Releases https://github.com/UMSKT/xpmgr/releases