Well you might have heared of it a tool from a Russian programmer where you can validate your windows seven product key. Be careful!
The tool itself was written in Delphi and so it was easy to look at it a little deeper. Well from what I’ve found I can say it’s sending your windows product key to a server on the net!
However I found it interesting how the validating process is done. So again research on the net and with the mentioned Delphi tool I found out it uses the pidgenx.dll which resides inside your system folder.
The Function inside of the DLL (PidGenX or its ordinal value 118) which is used is undocumented and may change in further windows versions.
Function PidgenX ( param, param, param : PWideChar; Unknown : Integer; param, param, param : Pointer) HResult; stdcall;
Let me please describe the parameters:
Param1 = the Windows product key
Param2 = the pkeyconfig.xrm-ms file which is probably used for hashes.
Param3 = MCPID can be found in registry under:
Path: HKEY_Local_Machine\Software\Microsoft\Windows NT\CurrentVersion
Value: Productid (The first 5 digits are your MCPID)
Param4 = Unknown.
Param5 – 7 = Pointer which holds the data the PidgenX function returns after validating successfully your key.
If you don’t want to dive into the registry you can do it :
- Open System by clicking the Start button, clicking Control Panel, clicking System and Maintenance, and then clicking System.
Under Windows activation, you can view your activation status. You can also change your product key by clicking Change product key.
Btw. As you can see the function returns a HResult so when the function returns S_OK your key is valid otherwise not.
I should mention you might want to run the function call inside of a separate thread otherwise your GUI will freeze until the function call finished its work.
With my programmer fellow Remko Weijnen I could define the following structure for the PidgenX function.
First Block of Data:
Type TDigitalPidId4 = packed record cbSize: DWORD; Unknown1: DWORD; ExtendedPid: array [0 .. 63] of Char; Activationid: array [0 .. 71] of Char; Edition: array [0 .. 63] of Char; Unknown3: array [0 .. 399] of Byte; Unknown2: array [0 .. 79] of Byte; EditionId: array [0 .. 63] of Char; LicenseType: array [0 .. 63] of Char; LicenseChannel: array [0 .. 63] of Char; end; PDigitalPidId4 = ^TDigitalPidId4;
Second Block of Data:
TDigitalPidId = packed record cbSize: DWORD; Unknown: array [0 .. 27] of Byte; CryptoID: DWORD; Unknown2: array [0 .. 127] of Byte; end;
Third Block of Data:
TGeneratedPid = packed record case Byte of 0: (cbSize: DWORD); 1: (Pid: array [0 .. 24] of Char); end;
The most interesting record is probably the DigitalPidID4 for you, because it holds the most interesting data inside of it. With all of the above we now can start validating our product keys. So let’s call the PidgenX function dynamically:
var PidGenX_: function(WindowsKey, PkeyPath, MPCID: PWideChar; UnknownUsage: Integer; var GeneratedProductID: TGeneratedPid; var OldDigitalProductID: TDigitalPidId; var DigitalProductID: TDigitalPidId4): HRESULT; stdcall; Const // instead of hardcoding the pathes use system function to make it dynamic... DLLPath: String = 'C:\windows\system32\pidgenx.dll'; var hr: HRESULT; GenPID: TGeneratedPid; DigitialPid: TDigitalPidId; begin GetProcedureAddress(@PidGenX_, AnsiString(DLLPath), 'PidGenX'); ZeroMemory(@GenPID, sizeof(GenPID)); ZeroMemory(@DigitialPid, sizeof(DigitialPid)); ZeroMemory(DigitialPid4, sizeof(DigitialPid4^)); GenPID.cbsize := sizeof(GenPID); DigitialPid.cbsize := sizeof(DigitialPid); DigitialPid4^.cbsize := sizeof(DigitialPid4^); try hr := PidGenX_(PWideChar(szKey), 'C:\Windows\System32\spp\tokens\pkeyconfig\pkeyconfig.xrm-ms', MCPId, 0, GenPID, DigitialPid, DigitialPid4^); except RaiseLastOSError; end; case hr of S_OK: ShowMessageDlg('Your key is valid'); else ShowMessageDlg('Your key is invalid'); end; if Succeeded(hr) then begin // return your data here e.g. in a memo, label or whatever you like... // ValidationLog.Lines.Add(Format(‘Extended-Pid: %s’, [ DigitialPid4.ExtendedPID])); end else begin // display a nice error message here