Example C++ source code
Previous Top Next

/*

This C++ sample must be packaged with Thinstall Studio 2.219 or higher.

setkey_sample.cpp : This application demonstrates the following:

- How to retreive information about the current license key

- How to set a new license key and determine if the operation was successful

- How to determine if a new license key has expired or is unauthorized

This program must be "linked" with Thinstall with License System 2 enabled.

Although this program is written in C++, the same operations can be easily performed by any language including:
VB, C#, Delphi, etc. The only 2 system calls of interest are

GetEnvironmentVariable - how to access information provided by Thinstall
SetEnvironmentVariable - how to tell Thinstall to change the current license key

This page describes Environment variables available to your program.

*/

#include "stdafx.h"
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>


// This structure is used to hold the license data for the current key
struct license_info
{
// Set of bit flags which will indicate which of the optional key elements are present
enum {
MAX_DAYS_SET=1,
MAX_RUNS_SET=2,
REQUIRED_MACHINE_ID_SET=4,
EXPIRE_DATE_SET=8,
LICENSE_INFO_SET=16,
MAX_VERSION_SET=32,
MIN_VERSION_SET=64
};

// this data may or may not be set depending on how the key is generated
int flags;
int max_days, max_runs;
char current_key[1024];
char current_version[30], max_version[30], min_version[30];
char required_machine_id[32];
char info[1024];
char expire_date[16];

// the following data is set no matter what key is used
int days_used, run_count;
char machine_id[32];
char first_run[16];
int expired;
};


// This function retreives information about the current license key and stores it in a convient structure
void get_current_process_license_info(license_info &l)
{
char buf[1024];
memset(&l, 0, sizeof(l));

GetEnvironmentVariable("TS_CURRENT_KEY", l.current_key, sizeof(l.current_key));

GetEnvironmentVariable("TS_DAYSUSED", buf, sizeof(buf));
l.days_used=atoi(buf);


if (GetEnvironmentVariable("TS_MAXDAYS", buf, sizeof(buf)))
{
l.flags|=license_info::MAX_DAYS_SET;
l.max_days=atoi(buf);
}

GetEnvironmentVariable("TS_RUNON", buf, sizeof(buf));
l.run_count=atoi(buf);

if (GetEnvironmentVariable("TS_LICINFO", l.info, sizeof(l.info)))
l.flags|=license_info::LICENSE_INFO_SET;

if (GetEnvironmentVariable("TS_MAXRUNS", buf, sizeof(buf)))
{
l.flags|=license_info::MAX_RUNS_SET;
l.max_runs=atoi(buf);
}

if (GetEnvironmentVariable("TS_MACID_REQ", buf, sizeof(buf)))
{
l.flags|=license_info::REQUIRED_MACHINE_ID_SET;
strcpy(l.required_machine_id, buf);
}

GetEnvironmentVariable("TS_CURRENT_VER", l.current_version, sizeof(l.current_version));

if (GetEnvironmentVariable("TS_MIN_VER", buf, sizeof(buf)))
{
l.flags|=license_info::MIN_VERSION_SET;
strcpy(l.min_version, buf);
}



if (GetEnvironmentVariable("TS_MAX_VER", buf, sizeof(buf)))
{
l.flags|=license_info::MAX_VERSION_SET;
strcpy(l.max_version, buf);
}

GetEnvironmentVariable("TS_MACID", buf, sizeof(buf));
strcpy(l.machine_id, buf);


if (GetEnvironmentVariable("TS_EXPDATE", l.expire_date, sizeof(l.expire_date)))
l.flags|=license_info::EXPIRE_DATE_SET;

GetEnvironmentVariable("TS_FIRSTRUN", buf, sizeof(buf));
strcpy(l.first_run, buf);


if (GetEnvironmentVariable("TS_EXPIRED", buf, sizeof(buf)))
l.expired=1;
}

// This function prints to the console information inside a license_info structure
void show_license_info(const license_info &l)
{
printf("License Information about the current Key:\n"
" - Current Key Name = %s\n"
" - First Used = %s\n"
" - Number of days since first run = %d\n"
" - Program Execution Count = %d\n"
" - Software release version = %s\n"
" - Current Machine ID = %s\n"
" - Key has expired = %d\n",
l.current_key,
l.first_run,
l.days_used,
l.run_count,
l.current_version,
l.machine_id,
l.expired);

if (l.flags & license_info::MAX_DAYS_SET)
printf(" - Maximum Days Allowed = %d\n", l.max_days);

if (l.flags & license_info::MAX_RUNS_SET)
printf(" - Maximum Runs Allowed = %d\n", l.max_runs);

if (l.flags & license_info::REQUIRED_MACHINE_ID_SET)
printf(" - Locked to Machine ID %s\n", l.required_machine_id);

if (l.flags & license_info::EXPIRE_DATE_SET)
printf(" - Expires on date %s\n", l.expire_date);

if (l.flags & license_info::MAX_VERSION_SET)
printf(" - Maximum software release version allowed = %s\n", l.max_version);

if (l.flags & license_info::MIN_VERSION_SET)
printf(" - Minimum software release version allowed = %s\n", l.min_version);

if (l.flags & license_info::LICENSE_INFO_SET)
printf(" - Contains license info string '%s'\n", l.info);
}


// display_license_violations : prints a list of reasons why the current license key cannot be used
void display_license_violations()
{
license_info l;
get_current_process_license_info(l);

// does this key only permit execution on one machine?
if (l.flags & license_info::REQUIRED_MACHINE_ID_SET)
if (stricmp(l.required_machine_id, l.machine_id)!=0) // do the machine IDs match?
printf("The key supplied does not permit execution on this computer\n");

if (l.flags & license_info::MAX_RUNS_SET) // does this key limit how many executions can take place?
if (l.run_count >= l.max_runs)
printf("The key supplied only permits %d executions, but you have already used %d\n",
l.max_runs, l.run_count);

if (l.flags & license_info::MAX_DAYS_SET) // does this key limit how many days from first use?
if (l.days_used >= l.max_days )
printf("The key supplied only permits %d days of use, but you have already used %d\n",
l.max_days, l.days_used );

// convert version numbers from X.X.X.X 16bit format to a FILETIME (64bit number)
FILETIME max_ver, min_ver, cur_ver;
cur_ver.dwHighDateTime=(atoi(l.current_version)<<16) | atoi(l.current_version+7);
cur_ver.dwLowDateTime=(atoi(l.current_version+14)<<16) | atoi(l.current_version+21);

if (l.flags & license_info::MAX_VERSION_SET)
{
max_ver.dwHighDateTime=(atoi(l.max_version)<<16) | atoi(l.max_version+7);
max_ver.dwLowDateTime=(atoi(l.max_version+14)<<16) | atoi(l.max_version+21);

if (CompareFileTime(&cur_ver, &max_ver)>0)
printf("Only execution on release versions <= %s permited\n"
" but the current software release version = %s\n", l.max_version, l.current_version);
}


if (l.flags & license_info::MIN_VERSION_SET)
{
min_ver.dwHighDateTime=(atoi(l.min_version)<<16) | atoi(l.min_version+7);
min_ver.dwLowDateTime=(atoi(l.min_version+14)<<16) | atoi(l.min_version+21);


if (CompareFileTime(&cur_ver, &min_ver)<0)
printf("Only execution on release versions >= %s permited\n"
" but the current software release version = %s\n", l.min_version, l.current_version);


}
}


// int verify_license_key_ok()
// returns 1 if the license key does not have any conditions that would permit its use
// returns 0 if the license key should not be allowed use
int verify_license_key_ok()
{
license_info l;
get_current_process_license_info(l);
return l.expired==0;
}


void set_new_license_key(const char *key)
{
license_info original;
int restore_original=0;
get_current_process_license_info(original);


// When running under Thinstall with License System 2 enabled, the line below will
// be treated as a special API command. Normally SetEnvironmentVariable would always
// returns 1, but in this case it returns 0 if the license key supplied is bad (cannot be decoded).
// Further, Thinstall preform the following actions if the key is valid:
// 1. Reset all of the environment variables associated with this key
// 2. Store this as the 'current key' for the computer. The next time your applicaiton runs it
// will start with this key as the 'current key'.

BOOL result=SetEnvironmentVariable("TS_CURRENT_KEY", key);

if (result!=0)
{
printf("Successfully decoded and set currrent key to '%s'\n", key);

// Just because the key was decoded & set successfully, does not mean it is authorized
// Now we should check to see if any of the license conditions are not satisified
if (!verify_license_key_ok())
{
printf("The supplied key %s cannot be used because:\n", key);

display_license_violations();

SetEnvironmentVariable("TS_CURRENT_KEY", original.current_key);
}
else
{
printf("License Key is valid for this time, place, and date\n");

license_info new_license_info;
get_current_process_license_info(new_license_info);
show_license_info(new_license_info);
}
}
else
printf("Could not decode key '%s' - Current license key setting are maintained!\n", key);

printf("\n");
}


int main(int argc, char* argv[])
{
char buf[256];

// This variable is always set by Thinstall - so if it is not set
// this program is not running under Thinstall
if (!GetEnvironmentVariable("TS_MACID", buf, sizeof(buf)))
{
printf("This program is not running under the Thinstall Operating System\n"
"Please package it using Thinstall and License System 2 enabled\n");
}
else
{
license_info li;
get_current_process_license_info(li);
show_license_info(li);

if (!verify_license_key_ok())
{
printf("The current license key is not valid!\n");
display_license_violations();
}

printf("\nPlease Enter a new license key: ");
scanf("%s", buf);

set_new_license_key(buf); // try to set the license key provided by the user
}

return 0;
}