C/C++ ISV Application Development Guide
Overview Of License Enabling Activities
Defining Your License Management Policies
Example Of Single-User License Key
Check
Example Of Server License Key Check
(Professional Edition Only)
This document guides you through the specifics of the process of license-enabling your C/C++ product with EasyLicenser. It adds detail to the overview of the EasyLicenser C/C++ Run Time Library API that is presented in the EasyLicenser Concepts guide.
The activities encompass:
A (no pun intended) key decision you need to make at the onset is whether you wish to enforce locking your license keys to specific hardware and / or operating system. Although locking your key provides a high degree of protection, it is also a sales inhibitor, as it subjects your end-customer to onerous procedures both at the time you take their order and whenever customers want to relocate their product installation. The approach is also less portable across platforms. The next decision you need to make is what you want to lock your key to: proprietary hardware, or the logical operating system runtime environment. If the former, you will need to implement or obtain hardware and operating system specific code and plug it into the EasyLicenser runtime framework. If the latter, you can utilize EasyLicenser's built-in enforcement facilities.
When your product is licensed for time limited or metered use, you can decide on what you want to have happen when a license key check indicates an expiring or expired key. You can define thresholds for generating warnings on expiring keys and grace periods or quotas to suppress generating errors when a quota or expiration date is exceeded.
EasyLicenser has built-in license management models, types and parameters. If you have a specialized need for your own variation to the built-in policies, you can accomplish this by defining your own custom handler.
The specific mechanics of accomplishing these tasks are described below.
Four API calls are provided in ezLicenseInfo.h for checking a license key:
If your application does not require customized or highly secure license management, you can use either of the first two API’s according to whether your product is a user or server product. Otherwise, you will find it convenient to use one of the functionally complete APIs.
The specific details of the API are available in the form of in-context comments in the C/C++ header files located at the “cpp/include” directory. Some simple examples will be illustrated below that show how the API calls are used in typical application scenarios. Source and binary code for additional examples are available in the “cpp/demo” directory. In particular, the "src/C_Demo.c" application is a simple "Hello World" application that performs a simple check on a license key provided as an input parameter based on a specified user / host name. For details on the demo programs and how to run them, see the description of the directory structure in the Setup, Management And Deployment Guide.
Suppose you have a desktop application such as a file management utility program that you sell to end consumers.
Whenever a new customer visits your web site and downloads your application and pays by credit card for a perpetual license to use it, your web site defines a serial number or user id, which is also used as the EasyLicenser user name input to a key your web site programmatically generates and emails to your customer. The key that you generate is a User license model, of User license type. It is not time limited and does not have a quota limit defined on it.
At product installation time, your product asks the user for the key, which is then stored in the operating system registry. Subsequently, each time the user runs your product, it prompts your user for the user id authentication information. Your code can take that user name input, retrieve the license key from the registry, and perform the license key check as follows:
// includes
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <ezLicenseInfo.h>
// Get the user name with the appropriate UI widget:
char *username = uiWidget->getText();
// Check the license key that is already obtained from the registry
into a “config” class.
// First, allocate a license info context
void * ezLicInstance = allocLicenseInfo();
int errorCode =
checkSingleUserLicenseKeyBasic(
ezLicInstance,
config->getLicenseKey(),
0, // no grace period for expired keys
0, // not metered license: no quota used to date
0, // metered-license quota threshold N/A
0, // no grace period for expired keys
0, // not metered license: no quota grace
username // user name matching what’s in the key
);
// errorCode is 0 if success, > 0 if success-with-warning,
// < 0 if error. Analyze
it for specifics.
if (errorCode >= 0) {
// Extract some interesting license params if needed
char *customCookie = getCustomCookie(ezLicInstance);
// analyze custom cookie in application-specific way
analyzeCustomCookie(customCookie);
// Check for warning conditions eg. about-to-expire key
checkWarnings(errorCode);
} else
// check for error codes defined in ezlicStatusCodes.h
checkErrors(errorCode);
// Free license key context
freeLicenseInfo(ezLicInstance);
Suppose you have an application server product that you wish to license by the number of concurrent sessions on the application server. You wish to lock the user into a specific host machine, therefore you adopt an enforced host naming policy that requires your customer to provide you with the DNS host name for their server machine at the time of accepting an order and generating a key.
The key that you generate is of a Server license model, and Concurrent User license type. At the time of generating the key, you specify an upper limit on the number of concurrent users according to what your customer paid for. It is not time limited, and you do not define a quota limit on it. The host name that you specify is based on what your customer tells you. Your customer obtains this information through a "uname -a" shell command on the server machine targeted for deployment of your application.
Your server application is designed to load at startup time an application property text file that includes, among other items, the license key and the host name, similar to the following:
:
LicenseKey=tFy67+h=…
HostName=licensedHostName1
:
At run time, either periodically or in response to specific events such as session initiation, your product code can interrogate its environment to obtain the number of active sessions and the application properties and check the license:
// includes
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <ezLicenseInfo.h>
// First, get the host name and license key,
// and the active sessionCount
char *hostName = AppProperty.getProperty(“HostName”);
char *licenseKey = AppProperty.getProperty(“LicenseKey”);
long sessionCount =
App.getActiveSessionCount(); // the current value
// Check the license key
// First, allocate a license info context
void * ezLicInstance = allocLicenseInfo();
int errorCode =
checkMultiUserLicenseKeyBasic(
ezLicInstance,
licenseKey,
0, // no grace period for expired keys
0, // not metered license: no quota used to date
0, // metered-license quota threshold N/A
0, // no grace period for expired keys
0, // not metered license: no quota grace
hostName, // host name matching what’s in the key
sessionCount // current usage value
);
// errorCode is 0 if success, > 0 if success-with-warning,
// < 0 if error. Analyze
it for specifics.
if (errorCode >= 0) {
// Extract some interesting license params if needed
char *customCookie = getCustomCookie(ezLicInstance);
// analyze custom cookie in application-specific way
analyzeCustomCookie(customCookie);
// Check for warning conditions eg. about-to-expire key
checkWarnings(errorCode);
} else
// check for error codes defined in ezlicStatusCodes.h
checkErrors(errorCode);
// Free license key context
freeLicenseInfo(ezLicInstance);
The C/C++ run time library can be used in a multithreaded environment. However, the API calls are not all guaranteed to be multithreadsafe for all platforms. It is the responsibility of the application developer to serialize license key checks at the license-key-check API call level of granularity. The remaining API calls are threadsafe. To serialize calls to the license key checking APIs, you can utilize a mutex. Initialize your mutex at program or shared library initialization time. Acquire the mutex immediately prior to invoking the API, and release it immediately after. If you provide a custom key handler that operates on global variables, then any operations on the global variables should be performed immediately after the API call and before releasing the mutex.
Refer to the C/C++ header files located at the “cpp/include” directory for specific information on the EasyLicenser C/C++ API calls that you will use while writing your product’s license-enabling code.