Willem's...

{rue if I mellow}

  Home  |   Contact  |   Syndication    |   Login
  25 Posts | 0 Stories | 120 Comments | 53 Trackbacks

News

Archives

Post Categories

Businessware Architects

XML-FX.COM

Following my prior post:

I have had many requests to provide the same code in unmanaged C++ - so here goes:

 

// KeyDecoder.h
#pragma once
#ifndef byte
typedef unsigned char byte;
#endif // byte
class KeyDecoder
{
public:
  enum Key { XP, Office10, Office11 };
  static int DecodeProductKey(KeyDecoder::Key key, char* pDecodedKey);
protected:
  static byte* GetRegistryDigitalProductId(KeyDecoder::Key key);
  static char* DecodeProductKey(byte* digitalProductId);
};

and:

 

// KeyDecoder.cpp
#include "StdAfx.h"
#include "keydecoder.h"
int KeyDecoder::DecodeProductKey(KeyDecoder::Key key, char* pKey)
{
  byte* pEncodedPID = GetRegistryDigitalProductId(key);
  int keyLen = 0;
  if(pEncodedPID)
  {
    char* pDecodedPID = DecodeProductKey(pEncodedPID);
    if(pDecodedPID)
    {
      keyLen = (int)::strlen(pDecodedPID);
      if(pKey)
      {
        ::strcpy(pKey, pDecodedPID);
      }
      delete[] pDecodedPID;
    }
  }
  return keyLen + 1;
}
char* KeyDecoder::DecodeProductKey(byte* digitalProductId)
{
  // Offset of first byte of encoded product key in 
  //  'DigitalProductIdxxx" REG_BINARY value. Offset = 34H.
  const int keyStartIndex = 52;
  // Offset of last byte of encoded product key in 
  //  'DigitalProductIdxxx" REG_BINARY value. Offset = 43H.
  const int keyEndIndex = keyStartIndex + 15;
  // Possible alpha-numeric characters in product key.
  char digits[] = 
  {
    'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R', 
    'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9',
  };
  // Length of decoded product key
  const int decodeLength = 29;
  // Length of decoded product key in byte-form.
  // Each byte represents 2 chars.
  const int decodeStringLength = 15;
  // Array of containing the decoded product key.
  char* pDecodedChars = new char[decodeLength + 1];
  ::memset(pDecodedChars, 0, decodeLength + 1); 
  // Extract byte 52 to 67 inclusive.
  byte hexPid[keyEndIndex - keyStartIndex + 1];
  for (int i = keyStartIndex; i <= keyEndIndex; i++)
  {
    hexPid[i - keyStartIndex] = digitalProductId[i];
  }
  for (int i = decodeLength - 1; i >= 0; i--)
  {
    // Every sixth char is a separator.
    if ((i + 1) % 6 == 0)
    {
      *(pDecodedChars + i) = '-';
    }
    else
    {
      // Do the actual decoding.
      int digitMapIndex = 0;
      for (int j = decodeStringLength - 1; j >= 0; j--)
      {
        int byteValue = (digitMapIndex << 8) | hexPid[j];
        hexPid[j] = (byte)(byteValue / 24);
        digitMapIndex = byteValue % 24;
        *(pDecodedChars + i) = digits[digitMapIndex];
      }
    }
  }
  return pDecodedChars;
}
byte* KeyDecoder::GetRegistryDigitalProductId(KeyDecoder::Key key)
{
  HKEY hKey = 0;
  LONG lResult = 0L;
  const char* pPIDName = "DigitalProductId";
  byte* pPID = 0;
  switch(key)
  {
    case KeyDecoder::Key::XP:
      lResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
        0, KEY_QUERY_VALUE, &hKey);
      break;
    case KeyDecoder::Key::Office10:
      break;
    case KeyDecoder::Key::Office11:
      break;
  }
  if(lResult == ERROR_SUCCESS)
  {
    DWORD cbData = 0;
    DWORD dwType = 0;
    lResult = ::RegQueryValueEx(hKey, pPIDName, 0, &dwType, 0, &cbData);
    if(lResult == ERROR_SUCCESS)
    {
      pPID = new byte[cbData];
      lResult = ::RegQueryValueEx(hKey, pPIDName, 0, &dwType, pPID, &cbData);
      if(lResult != ERROR_SUCCESS)
      {
        delete[] pPID;
        pPID = 0;
      }
    }
  }
  if(hKey)
  {
    ::RegCloseKey(hKey);
  }
  return pPID;
}

 

This provides the same functionality as the C# code in the prior post.

XPKey is a standard Win32 console application that pops up a message box containing the decoded XP product key. It also copies the product key to the clipboard. You can download the executable here:

and the VC source-code and project file here:

The C++ application is provided for VS2003, but should convert without problems to VS2005. It uses only standard Win32 calls - no MFC/ATL/STL etc.

PLEASE NOTE: All code listed here is provided as-is, with no guarantees what so ever. Use of this code does not require a license and no copyright on the code exists or is implied. You are free to use the code as you see fit, for any commercial or non-commercial use.

posted on Wednesday, May 31, 2006 8:08 AM

Feedback

# re: Win32 XP Key Recovery Utility 7/12/2006 2:43 PM Dave Hope
Hello,

Thanks for this. I intend on writing a simple app to grab all the keys on our LAN so I can keep a track of our licensing situation.

I do have a quick question, what is the purpose of the first RegQueryValueEx? - it doesn't seem to do anything other than provide a return status. If it's not used, it doesn't seem to work so it's obviously got some purpose I just can't see what.

Thanks again!,

Dave

# re: Win32 XP Key Recovery Utility 7/14/2006 6:15 AM Willem
Dave, the first use is to determine the size of the registry value - the length is returned in cbData. This size is used to allocate the byte array, and the actual value is then read back using the second call.

# re: Win32 XP Key Recovery Utility 7/14/2006 7:20 AM Dave Hope
Thanks.

btw, you might also want to check for NULL in your DecodeProductKey function, NULL is a valid byte value :P - Can cause issues if you're checking for office installation status and they don't have it installed :)

Thanks,

Dave

# re: Win32 XP Key Recovery Utility 7/22/2006 11:38 PM Alex
This is a very fan tool. thx Alex

# re: Win32 XP Key Recovery Utility 9/30/2006 2:43 PM leonardo
eu quero entrar

# re: Win32 XP Key Recovery Utility 10/28/2006 11:38 PM Mike Cobain
How do I call the function to get the String showed into a Texbox in C# ?

Any clues.

# re: Win32 XP Key Recovery Utility 10/30/2006 9:30 AM Willem
Mike,

1. Create a WinForms application.
2. Add a text box control to the default form.
3. Add a reference to the C# (not C++) project containing the Key-decoder source-code.
4. In the form constructor after the 'InitializeComponent' method call, add the following line:

// Get the key and update the text-box
this.txtXPKey.Text = KeyDecoder.DecodeProductKey(
KeyDecoder.GetRegistryDigitalProductId(KeyDecoder.Key.XP));

where 'txtXPKey' is the text box control ID.

You can download the example code here via the link below. The WinXPKey.Net project has the code you're looking for.

http://www.bware.biz/DotNet/Tools/XPKey/XPKey+Apps.zip

# re: Win32 XP Key Recovery Utility 10/30/2006 10:15 PM Mike Cobain
You have solved my issue.


Thank you for answering my query. I appreciated that.

Cheers!



# re: Win32 XP Key Recovery Utility 5/18/2008 9:48 AM Steve
tried the xpkey.exe on my main Dell PC which has a product key installed and my second PC which has an OEM version of XP installed but is not activated yet and wanted to use this util to determine the product key for my second PC as I have lost the product key label and found that this utility and also magic beans always returns exactly the same product key on both systems, but this is not my XP product key :

XJM6Q-BQ8HW-T6DFB-Y934T-YD4YT

I mean did I miss something because people who dont know any better may think that this key returned is their actual key and may start using it, but it is not the key in fact I think it is the XP bulk (default) key and if the bulk key is always the same then surely the program should detect it is the bulk key and make this clear to the user.

# re: Win32 XP Key Recovery Utility 5/29/2009 3:27 AM Finch
Thanks, this is exactly what I was looking for!

Post Feedback

Title:
Name:
Email: (never displayed)
Url:
Comments: