You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
5.4 KiB
249 lines
5.4 KiB
/* File: \wacker\tdll\serialno.c
|
|
*
|
|
* Copyright 1995 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 8 $
|
|
* $Date: 7/12/02 12:18p $
|
|
*
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#pragma hdrstop
|
|
|
|
#include "features.h"
|
|
|
|
#ifdef INCL_NAG_SCREEN
|
|
|
|
#define INCL_WIN
|
|
#define INCL_DOS
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
|
|
#include "stdtyp.h"
|
|
#include "htchar.h"
|
|
#include "serialno.h"
|
|
|
|
// Function prototypes...
|
|
//
|
|
//static time_t CalcExpirationTime(const char * pszSerial);
|
|
static unsigned AsciiHEXToInt(TCHAR *sz);
|
|
static unsigned calc_crc(register unsigned crc, TCHAR *data, int cnt);
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* IsValidSerialNumber
|
|
*
|
|
* DESCRIPTION:
|
|
* Perform a crc test on the serial number passed in as a parameter
|
|
* to decide whether it is a valid serial number.
|
|
*
|
|
* ARGUMENTS:
|
|
* TCHAR *acSerialNo - pointer to a string conatining a serial number.
|
|
*
|
|
* RETURNS:
|
|
* TRUE if valid, FALSE otherwise, SERIALNO_EXPIRED if expired.
|
|
*
|
|
* AUTHOR: Jadwiga A. Carlson, 10:03:16am 05-10-95
|
|
*
|
|
*/
|
|
int IsValidSerialNumber(TCHAR *acSerialNo)
|
|
{
|
|
TCHAR acCRCPart[3];
|
|
TCHAR acBuffer[MAX_USER_SERIAL_NUMBER + sizeof(TCHAR)];
|
|
int len;
|
|
register unsigned crc1;
|
|
unsigned crc2;
|
|
|
|
TCHAR_Fill(acBuffer, TEXT('\0'), sizeof(acBuffer)/sizeof(TCHAR));
|
|
StrCharCopyN((TCHAR *)acBuffer, acSerialNo, sizeof(acBuffer)/sizeof(TCHAR));
|
|
|
|
// If the product code doesn't match, we're outta here! Note that
|
|
// the first character should be an "H".
|
|
//
|
|
if (acBuffer[0] != 'H')
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
len = StrCharGetStrLength(acBuffer); // whole serial number
|
|
if (len < APP_SERIALNO_MIN)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
acCRCPart[0] = acBuffer[len-2]; // everything but CRC
|
|
acCRCPart[1] = acBuffer[len-1];
|
|
acCRCPart[2] = '\0';
|
|
acBuffer[len-2] = '\0';
|
|
|
|
// Initialize these different so test will fail. mrw:8/25/95
|
|
//
|
|
crc1 = 1234;
|
|
crc2 = 0;
|
|
|
|
crc1 = calc_crc(0, acBuffer, (int)strlen(acBuffer));
|
|
crc2 = AsciiHEXToInt(acCRCPart);
|
|
|
|
if (crc2 != crc1)
|
|
return(FALSE);
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* calc_crc
|
|
*
|
|
* DESCRIPTION:
|
|
* Calucate crc check.
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
static unsigned calc_crc(register unsigned crc, TCHAR *data, int cnt)
|
|
{
|
|
unsigned int c;
|
|
register unsigned q;
|
|
|
|
while (cnt--)
|
|
{
|
|
c = *data++;
|
|
q = (crc ^ c) & 0x0f;
|
|
crc = (crc >> 4) ^ (q * 0x1081);
|
|
q = (crc ^ (c >> 4)) & 0x0f;
|
|
crc = (crc >> 4) ^ (q * 0x1081);
|
|
}
|
|
|
|
crc = crc & 0x0ff;
|
|
return (crc);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* AsciiHEXToInt
|
|
*
|
|
* DESCRIPTION:
|
|
* Convert Ascii representation of a HEX number into integer.
|
|
*
|
|
* ARGUMENTS:
|
|
* sz - character string.
|
|
*
|
|
* RETURNS:
|
|
* unsigned - the number.
|
|
*
|
|
* AUTHOR: Jadwiga A. Carlson, 11:34:32am 05-10-95
|
|
* (This function taken form HA/Win).
|
|
*/
|
|
static unsigned AsciiHEXToInt(TCHAR *sz)
|
|
{
|
|
unsigned i = 0;
|
|
|
|
while (*sz == ' ' || *sz == '\t')
|
|
sz++;
|
|
|
|
while (isdigit(*sz) || isxdigit(*sz))
|
|
{
|
|
if (isdigit(*sz))
|
|
i = (i * 16) + *sz++ - '0';
|
|
else
|
|
i = (i * 16) + (*sz++ - '0')-7;
|
|
}
|
|
|
|
return (i);
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* CalcExpirationTime
|
|
*
|
|
* DESCRIPTION:
|
|
* Simple little function that calculates the expiration time based
|
|
* on the given serial number. Currently, we expire a program on the
|
|
* 1st day of the 4 calendar month. Using the C time functions made
|
|
* this easy.
|
|
*
|
|
* For simplicity and to re-use the KopyKat code, the serial numbers
|
|
* may NOT use double-byte characters !
|
|
*
|
|
* ARGUMENTS:
|
|
* LPSTR acSerial
|
|
*
|
|
* RETURNS:
|
|
* time_t time which is defined by ANSI as the number of seconds from
|
|
* Jan 1, 1970 GMT. I suppose a correction for local time could be added
|
|
* but it just clutters up things when you think about it.
|
|
*
|
|
* Will return 0 if the serial number is not in valid format
|
|
*
|
|
*/
|
|
time_t CalcExpirationTime(const char *acSerial)
|
|
{
|
|
struct tm stSerial;
|
|
time_t tSerial;
|
|
int month;
|
|
|
|
// Beta serial number format is SDymxxxx
|
|
// where y = year since 1990, m = month (see below), and xxx = anything
|
|
|
|
// Validate the year -- it must be a digit
|
|
if ( ! isdigit(acSerial[3] ))
|
|
return 0;
|
|
|
|
// Month is represented by a single digit from 1 to 9 and A,B,C for
|
|
// Oct, Nov, Dec. If not a valid month, returns 0
|
|
switch (acSerial[4])
|
|
{
|
|
case 'A': month = 10;
|
|
break;
|
|
case 'B': month = 11;
|
|
break;
|
|
case 'C': month = 12;
|
|
break;
|
|
default:
|
|
if (isdigit(acSerial[4]))
|
|
month = acSerial[4] - '0';
|
|
else
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
|
|
// Build a partial time structure.
|
|
memset(&stSerial, 0, sizeof(struct tm));
|
|
stSerial.tm_mday = 1;
|
|
stSerial.tm_mon = month - 1; // tm counts from 0
|
|
stSerial.tm_year = 90 + (int)(acSerial[3] - '0'); // years since 1990
|
|
|
|
// Expiration date is 1st day of fourth calendar month from date
|
|
// of issue.
|
|
|
|
stSerial.tm_mon += 3;
|
|
|
|
// Check for end of year wrap around.
|
|
|
|
if (stSerial.tm_mon >= 12)
|
|
{
|
|
stSerial.tm_mon %= 12;
|
|
stSerial.tm_year += 1;
|
|
}
|
|
|
|
// Convert into time_t time.
|
|
|
|
if ((tSerial = mktime(&stSerial)) == -1)
|
|
return 0;
|
|
|
|
return tSerial;
|
|
}
|
|
|
|
#endif
|