Geeks With Blogs
Willem's... {rue if I mellow}

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 C++ Hard'n'Fast | Back to top


Comments on this post: Win32 XP Key Recovery Utility

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
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
Left by Dave Hope on Jul 12, 2006 2:43 PM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
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.
Left by Willem on Jul 14, 2006 6:15 AM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
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
Left by Dave Hope on Jul 14, 2006 7:20 AM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
This is a very fan tool. thx Alex
Left by Alex on Jul 22, 2006 11:38 PM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
How do I call the function to get the String showed into a Texbox in C# ?

Any clues.
Left by Mike Cobain on Oct 28, 2006 11:38 PM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
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
Left by Willem on Oct 30, 2006 9:30 AM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
You have solved my issue.


Thank you for answering my query. I appreciated that.

Cheers!

Left by Mike Cobain on Oct 30, 2006 10:15 PM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
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.
Left by Steve on May 18, 2008 9:48 AM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
Thanks, this is exactly what I was looking for!
Left by Finch on May 29, 2009 3:27 AM

# re: Win32 XP Key Recovery Utility
Requesting Gravatar...
my
new key?
my last key (xjm6q-bq8hw-t6dfb-y934t-yd4yt)
Left by siroos.shirazi far on Jun 19, 2010 1:51 PM

Your comment:
 (will show your gravatar)


Copyright © Willem Fourie | Powered by: GeeksWithBlogs.net | Join free