cwinapi

"PIDGenX failed with error code: 80070057"


I'm working with the PIDGenX function from the ProductKeyUtilities.dll library, which is used to validate product keys in the context of Volume Activation Management Tool (VAMT). I am receiving the error code 80070057, which corresponds to "The parameter is incorrect". This occurs when I attempt to validate a Windows product key and configuration file.

The key and configuration file are both valid as they work within VAMT, but I am unable to successfully use them in my C++ application that interacts directly with PIDGenX. Error code: 80070057 ("The parameter is incorrect")

argv[1]: Product Key (e.g., W269N-WFGWX-YVC9B-4J6C9-T83GX)

argv[2]: Path to .xrm-ms file (e.g., pkconfig\pkconfig_win10.xrm-ms)

Code:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    CHAR m_productId2[24];
} DigitalProductId2;

typedef struct {
    DWORD m_length;
    WORD  m_versionMajor;
    WORD  m_versionMinor;
    BYTE  m_productId2[24];
    DWORD m_keyIdx;
    CHAR m_sku[16];
    BYTE  m_abCdKey[16];
    DWORD m_cloneStatus;
    DWORD m_time;
    DWORD m_random;
    DWORD m_lt;
    DWORD m_licenseData[2];
    CHAR m_oemId[8];
    DWORD m_bundleId;
    CHAR m_hardwareIdStatic[8];
    DWORD m_hardwareIdTypeStatic;
    DWORD m_biosChecksumStatic;
    DWORD m_volSerStatic;
    DWORD m_totalRamStatic;
    DWORD m_videoBiosChecksumStatic;
    CHAR m_hardwareIdDynamic[8];
    DWORD m_hardwareIdTypeDynamic;
    DWORD m_biosChecksumDynamic;
    DWORD m_volSerDynamic;
    DWORD m_totalRamDynamic;
    DWORD m_videoBiosChecksumDynamic;
    DWORD m_crc32;
} DigitalProductId3;

typedef struct {
    DWORD m_length;
    WORD  m_versionMajor;
    WORD  m_versionMinor;
    CHAR m_productId2Ex[64];
    CHAR m_sku[64];
    CHAR m_oemId[8];
    CHAR m_editionId[260];
    BYTE  m_isUpgrade;
    BYTE  m_reserved[7];
    BYTE  m_abCdKey[16];
    BYTE  m_abCdKeySHA256Hash[32];
    BYTE  m_abSHA256Hash[32];
    CHAR m_partNumber[64];
    CHAR m_productKeyType[64];
    CHAR m_eulaType[64];
} DigitalProductId4;

typedef DWORD (STDAPICALLTYPE *pPIDGenX)(LPWSTR pk, LPWSTR config, LPWSTR mpc, LPWSTR oemID, DigitalProductId2 *dpid2, DigitalProductId3 *dpid3, DigitalProductId4 *dpid4);

int wmain(int argc, wchar_t** argv) {
    if (argc != 3) {
        wprintf(L"Usage: %s [key] [file]\n", argv[0]);
        exit(1);
    }

    // Load the DLL
    HMODULE hMod = LoadLibraryA("ProductKeyUtilities.dll");
    if (!hMod) {
        printf("Failed to load DLL. Error code: %lu\n", GetLastError());
        exit(1);
    }

    // Get the PIDGenX function
    pPIDGenX PIDGenX = (pPIDGenX)GetProcAddress(hMod, "PidGenX");
    if (!PIDGenX) {
        printf("Failed to find PIDGenX function. Error code: %lu\n", GetLastError());
        FreeLibrary(hMod);
        exit(1);
    }

    // Initialize the structures
    DigitalProductId2 dpid2 = {0};
    DigitalProductId3 dpid3 = {0};
    DigitalProductId4 dpid4 = {0};

    // Set the lengths for dpid3 and dpid4
    dpid3.m_length = sizeof(dpid3);
    dpid4.m_length = sizeof(dpid4);

    // Set the OEM ID (can be empty or some value)
    WCHAR oemId[8] = L"OEMID"; // or L""

    // Call the function
    int res = PIDGenX(argv[1], argv[2], L"12345", oemId, &dpid2, &dpid3, &dpid4);

    // Check result
    if (res != 0) {
        printf("PIDGenX failed with error code: %x\n", res);
    } else {
        printf("PIDGenX succeeded. Product ID: %s\n", dpid4.m_productId2Ex);
    }

    FreeLibrary(hMod);
    return 0;
}

Solution

  • I discovered IonBazan/pidgenx when search for PidGenX examples in GitHub, and noticed some major differences:

    After that, only typedef definitions are updated (basically the structures are C):

    typedef struct {
        WCHAR m_productId2[24];
    } DigitalProductId2;
    
    typedef struct {
        DWORD m_length;
        WORD  m_versionMajor;
        WORD  m_versionMinor;
        BYTE  m_productId2[24];
        DWORD m_keyIdx;
        CHAR m_sku[16];
        BYTE  m_abCdKey[16];
        DWORD m_cloneStatus;
        DWORD m_time;
        DWORD m_random;
        DWORD m_lt;
        DWORD m_licenseData[2];
        CHAR m_oemId[8];
        DWORD m_bundleId;
        CHAR m_hardwareIdStatic[8];
        DWORD m_hardwareIdTypeStatic;
        DWORD m_biosChecksumStatic;
        DWORD m_volSerStatic;
        DWORD m_totalRamStatic;
        DWORD m_videoBiosChecksumStatic;
        CHAR m_hardwareIdDynamic[8];
        DWORD m_hardwareIdTypeDynamic;
        DWORD m_biosChecksumDynamic;
        DWORD m_volSerDynamic;
        DWORD m_totalRamDynamic;
        DWORD m_videoBiosChecksumDynamic;
        DWORD m_crc32;
    } DigitalProductId3;
    
    typedef struct {
        DWORD m_length;
        WORD  m_versionMajor;
        WORD  m_versionMinor;
        WCHAR m_productId2Ex[64];
        WCHAR m_sku[64];
        WCHAR m_oemId[8];
        WCHAR m_editionId[260];
        BYTE  m_isUpgrade;
        BYTE  m_reserved[7];
        BYTE  m_abCdKey[16];
        BYTE  m_abCdKeySHA256Hash[32];
        BYTE  m_abSHA256Hash[32];
        WCHAR m_partNumber[64];
        WCHAR m_productKeyType[64];
        WCHAR m_eulaType[64];
    } DigitalProductId4;
    

    As DigitalProductId4.m_productId2Ex is WCHAR[24] and printf only prints ASCII formatted string, we need to update to wprintf:

        // Check result
        if (res != 0) {
            printf("PIDGenX failed with error code: %x\n", res);
        } else {
            wprintf(L"PIDGenX succeeded. Product ID: %s\n", dpid4.m_productId2Ex);
        }
    

    Test result:

    C:\Users\winapiadmin\Downloads\pkeychecker\PKCONFIG>verify.exe W269N-WFGWX-YVC9B-4J6C9-T83GX pkconfig\pkconfig_win10.xrm-ms
    PIDGenX succeeded. Product ID: 12345-03311-000-000001-03-1033-9200.0000-0782025
    
    C:\Users\winapiadmin\Downloads\pkeychecker\PKCONFIG>verify.exe W269N-WFGWX-YVC9B-4J6C9-T83GX pkconfig\pkconfig_winNext.xrm-ms
    PIDGenX succeeded. Product ID: 12345-03311-000-000001-03-1033-9200.0000-0782025
    
    C:\Users\winapiadmin\Downloads\pkeychecker\PKCONFIG>verify.exe W269N-WFGWX-YVC9B-4J6C9-T83GX pkconfig\pkconfig_win8.1.xrm-ms
    PIDGenX failed with error code: 8a010001