197 lines
6.2 KiB
C++
197 lines
6.2 KiB
C++
|
#include <windows.h>
|
||
|
#include "vblic.h"
|
||
|
|
||
|
#ifdef BETA_BOMB
|
||
|
#include "timebomb.h"
|
||
|
#endif //BETA_BOMB
|
||
|
|
||
|
// NOTE: The following strings must match exactly the content of the registry as specified in
|
||
|
// vbprolic.reg.
|
||
|
#define LICENSES_KEY "Licenses"
|
||
|
|
||
|
void CalcValue(char * pszLicenseKey, char * pszKeyValue, LPTSTR pszTempBuff);
|
||
|
BOOL ValidateValue(HKEY hLicenseSubKey, char* pszLicenseKey, char* pKeyValue);
|
||
|
|
||
|
#define MAX_KEY_LENGTH 200
|
||
|
|
||
|
//=-------------------------------------------------------------------------=
|
||
|
// CompareLicenseStringsW [Helper for comparing license keys]
|
||
|
//=-------------------------------------------------------------------------=
|
||
|
// Compares two null terminated wide strings and returns TRUE if the strings
|
||
|
// are equal.
|
||
|
//
|
||
|
BOOL CompareLicenseStringsW(LPWSTR pwszKey1, LPWSTR pwszKey2)
|
||
|
{
|
||
|
int i = 0;
|
||
|
|
||
|
#ifdef BETA_BOMB
|
||
|
// Check for expired control (BETA)
|
||
|
if (!CheckExpired()) return FALSE;
|
||
|
#endif //BETA_BOMB
|
||
|
|
||
|
// Check to see if the pointers are equal
|
||
|
//
|
||
|
if (pwszKey1 == pwszKey2)
|
||
|
return TRUE;
|
||
|
|
||
|
// Since pointer comparison failed, if either pointer is NULL, bail out
|
||
|
//
|
||
|
if (!pwszKey1 || !pwszKey2)
|
||
|
return FALSE;
|
||
|
|
||
|
// Compare each character. Jump out when a character is not equal or the end of
|
||
|
// either string is reached.
|
||
|
//
|
||
|
while (pwszKey1[i] && pwszKey2[i])
|
||
|
{
|
||
|
if (pwszKey1[i] != pwszKey2[i])
|
||
|
break;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
return (pwszKey1[i] == pwszKey2[i]);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
// VBValidateControlsLicense - This routine validates that the proper lincesing
|
||
|
// keys have been placed in the registery. The list of potential keys are
|
||
|
// gathered from the resource file in the LICENSE_KEY_RESOURCE resource.
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
BOOL VBValidateControlsLicense(char *pszLicenseKey)
|
||
|
{
|
||
|
HKEY hPrimaryLicenseKey, hLicenseSubKey;
|
||
|
LONG lSize = MAX_KEY_LENGTH;
|
||
|
BOOL bFoundKey = FALSE;
|
||
|
char szKeyValue[MAX_KEY_LENGTH];
|
||
|
|
||
|
#ifdef BETA_BOMB
|
||
|
// Check for expired control (BETA)
|
||
|
if (!CheckExpired()) return FALSE;
|
||
|
#endif //BETA_BOMB
|
||
|
|
||
|
// Continue only if we were passed a non-NULL license string
|
||
|
// We return FALSE, if the string is NULL
|
||
|
//
|
||
|
if (pszLicenseKey)
|
||
|
{
|
||
|
DWORD dwFoundKey = RegOpenKey(HKEY_CLASSES_ROOT, LICENSES_KEY, &hPrimaryLicenseKey);
|
||
|
if (dwFoundKey == ERROR_SUCCESS)
|
||
|
{
|
||
|
// Now, loop through all the keys in the resource file trying to find
|
||
|
// a match in the registry.
|
||
|
if (!bFoundKey && *pszLicenseKey)
|
||
|
{
|
||
|
if (RegOpenKey(hPrimaryLicenseKey, pszLicenseKey, &hLicenseSubKey) == ERROR_SUCCESS)
|
||
|
{
|
||
|
if (ValidateValue(hLicenseSubKey, pszLicenseKey, szKeyValue))
|
||
|
bFoundKey = TRUE;
|
||
|
|
||
|
RegCloseKey(hLicenseSubKey);
|
||
|
}
|
||
|
} // END if(...)
|
||
|
|
||
|
RegCloseKey(hPrimaryLicenseKey);
|
||
|
} // END successfull RegOpenKey(HKEY_CLASSES_ROOT...)
|
||
|
}
|
||
|
|
||
|
|
||
|
return bFoundKey;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
// ValidateValue - Calls CalcValue to get the corresponding value for a
|
||
|
// key and compares it to the value in the registry.
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL ValidateValue(HKEY hLicenseSubKey, char * pszLicenseKey, char * pszResultValue)
|
||
|
{
|
||
|
BOOL bValidValue;
|
||
|
TCHAR szTempBuff[MAX_KEY_LENGTH];
|
||
|
|
||
|
// Reject a key that is too short. (Short keys could lead to easier decoding.)
|
||
|
long lSize = lstrlen(pszLicenseKey) + 1;
|
||
|
if (lSize < 9)
|
||
|
return FALSE;
|
||
|
|
||
|
// Calculate the expected value from the key.
|
||
|
CalcValue(pszLicenseKey, pszResultValue, szTempBuff);
|
||
|
|
||
|
// Now, get the value from the registry and compare.
|
||
|
if (RegQueryValue(hLicenseSubKey, NULL, szTempBuff, &lSize) == ERROR_SUCCESS)
|
||
|
{
|
||
|
if (!lstrcmp(szTempBuff, pszResultValue))
|
||
|
bValidValue = TRUE;
|
||
|
else
|
||
|
bValidValue = FALSE;
|
||
|
}
|
||
|
return bValidValue;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
// THIS SOURCE IS REPLICATED IN THE "DECODE.EXE" OR LICGEN SOURCE. (THIS PROGRAM WILL
|
||
|
// GENERATE VALUES FROM KEYS.) ANY CHANGES TO EITHER SOURCE MUST BE REPLICATED
|
||
|
// IN THE OTHER. DO NOT CHANGE THIS SOURCE OR YOU RISK BREAKING CONTROLS UNDER
|
||
|
// VB4.
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// CalcValue - This routine checks the value of the key with the key to
|
||
|
// ensure it is a valid value.
|
||
|
// The plan: First, XOR the string with itself in reverse.
|
||
|
// Convert the result to ascii by adding each nibble to
|
||
|
// 'a' + (checksum of the key result mod 26).
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
void CalcValue(char * pszLicenseKey, char * pszResultKey, LPTSTR pszTempResult)
|
||
|
{
|
||
|
BOOL bValid = FALSE;
|
||
|
TCHAR *pKey, *pEndKey, *pEndResult, *pResult;
|
||
|
unsigned int nCheckSum = 0;
|
||
|
|
||
|
// Make a reverse copy of the key.
|
||
|
|
||
|
// Find the end of the string
|
||
|
for (pKey = pszLicenseKey; *pKey; pKey++);
|
||
|
pKey--;
|
||
|
|
||
|
for (pResult = pszTempResult; pKey >= pszLicenseKey; pKey--, pResult++)
|
||
|
*pResult = *pKey;
|
||
|
|
||
|
*pResult = '\0';
|
||
|
|
||
|
// Find the end of the result string.
|
||
|
for (pEndResult = pszTempResult; *pEndResult; pEndResult++);
|
||
|
pEndResult--;
|
||
|
|
||
|
// Find the end of the source string.
|
||
|
for (pEndKey = (char *) pszLicenseKey; *pEndKey; pEndKey++);
|
||
|
pEndKey--;
|
||
|
|
||
|
// XOR each character with its corresponding character at the other
|
||
|
// end of the string.
|
||
|
for (pKey = (char *) pszLicenseKey, pResult = pszTempResult; pKey < pEndKey; pKey++, pResult++)
|
||
|
{
|
||
|
*pResult ^= *pKey;
|
||
|
nCheckSum += *pResult; // Calculate the checksum.
|
||
|
}
|
||
|
|
||
|
// Now find the middle (or about the middle).
|
||
|
for (pKey = pszTempResult, pResult = pEndResult; pKey < pResult; pKey++, pResult--);
|
||
|
pKey--;
|
||
|
pEndResult = pKey; // Save our new end.
|
||
|
|
||
|
// Set our base character to mod 10 of the checksum of our XOR.
|
||
|
TCHAR cBaseChar;
|
||
|
cBaseChar = 'a' + (nCheckSum % 10);
|
||
|
|
||
|
//Now convert to some ascii representation by adding each nibble to our base char.
|
||
|
for (pKey = pszResultKey, pResult = pszTempResult; pResult <= pEndResult; pKey++, pResult++)
|
||
|
{
|
||
|
*pKey = cBaseChar + (*pResult & 0x0F);
|
||
|
++pKey;
|
||
|
*pKey = cBaseChar + (*pResult >> 4);
|
||
|
}
|
||
|
*pKey = '\0';
|
||
|
}
|
||
|
|