validating a product key in a vs

14
Validating a Product Key in a VS.NET Install The MSDN article Q253683 describes how to validate a serial number during an MSI install created with VSI 1.1. However, the architecture of the MSI has changed somewhat in VS.NET and the instructions given for creating the custom action DLL may be difficult to follow for developers who are not experienced C++ programmers. This article outlines how to adapt the procedure to an MSI created with VS.NET, and also gives detailed instructions on how to compile the custom action DLL. Background There are a wide variety of product registration strategies. On one end of the spectrum are the typical "try-and-buy" techniques used with relatively small Internet download applications. The simplest technique is creating two downloads, one for the trial and one for the purchased product. More sophisticated methods usually involve embedding the registration code within the application itself, and rely on registry entries to determine when the trial ends or if a license has been obtained. At the other end of the spectrum are shrink wrapped mass produced media that require a product key (PID) such as those Microsoft employs for its products. Neither of these cases require special packaging skills from the typical developer. In the first case, the registration is achieved by familiar techniques - simply programming the trial and registration code into the app itself. The latter case invariably is handled by a department that exists solely for deployment management, and the code developers are not part of the process. Occasionally, the developer themselves need to create media such as CDs for distribution without having the benefit of

Upload: rajchanchal

Post on 10-May-2015

2.281 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Validating A Product Key In A Vs

Validating a Product Key in a VS.NET Install

The MSDN article Q253683 describes how to validate a serial number during an MSI install created with VSI 1.1. However, the architecture of the MSI has changed somewhat in VS.NET and the instructions given for creating the custom action DLL may be difficult to follow for developers who are not experienced C++ programmers.

This article outlines how to adapt the procedure to an MSI created with VS.NET, and also gives detailed instructions on how to compile the custom action DLL.

Background

There are a wide variety of product registration strategies.

On one end of the spectrum are the typical "try-and-buy" techniques used with relatively small Internet download applications. The simplest technique is creating two downloads, one for the trial and one for the purchased product. More sophisticated methods usually involve embedding the registration code within the application itself, and rely on registry entries to determine when the trial ends or if a license has been obtained.

At the other end of the spectrum are shrink wrapped mass produced media that require a product key (PID) such as those Microsoft employs for its products.

Neither of these cases require special packaging skills from the typical developer. In the first case, the registration is achieved by familiar techniques - simply programming the trial and registration code into the app itself. The latter case invariably is handled by a department that exists solely for deployment management, and the code developers are not part of the process.

Occasionally, the developer themselves need to create media such as CDs for distribution without having the benefit of support from a dedicated group. This presents a problem for the app developer who generally does not have a lot of packaging expertise. This article is for the developer who needs to create a small number of media and wishes to require the user to enter a product key during the setup.

A simple technique that is manageable for a small number of deployment media is to create a product key file that uses some sort of encryption, and include it on the distribution media. The setup can then be modified to include a custom action that reads the product key file and validates the product key entered by the user.

This technique is outlined here.

Philosophy of licensing

Page 2: Validating A Product Key In A Vs

This is not a discussion of licensing strategies, however one concept merits discussion. Some developers spend an undue time and effort trying to ensure their product is not used without a valid license. This is a futile endeavor.

The simple try-and-buy strategies are used to encourage most people to simply buy a relatively inexpensive product rather than using it illegally. But anyone who has a good working knowledge of the registry and programming techniques can figure out how to circumvent a trial period restriction. The philosophy here is that most people do not have this expertise, and besides, how much effort is it worth to avoid paying $39.95 for a spyware utility?

On the other hand, there is real interest in protecting higher value products like those marketed by Microsoft. But it is simply not feasible! Obviously, if you require a product key, you must supply the key with the media, and there is no way to prevent people from simply making copies of the product. Well at least not unless you want to implement an XP type registration program!

So why do companies like MS invest the considerable resources required to create mass media with license keys? There are several reasons. The ROI comes not from the license key, but rather from the serial number! It is reasonable to assume that while many people who acquire legal software never actually register it, many do register. And that provides MS with valuable marketing information about how their products are acquired, because each time a product is registered, MS can look at the serial number and determine if the product was acquired as an OEM included with a new computer, a standalone shrink-wrapped app such as MS Word that was purchased from a vendor, or a shrink-wrapped suite of products like Office that was purchased from a vendor. All this information helps drive how they price, package, and distribute their products!

Also, having a standard process for generation of license keys and media makes it much simpler to prosecute bootlegged illegal products, but in practical terms this is much less of a consideration than acquiring marketing demographics.

Realistically, requiring a user to have a valid license key using the technique described in this article does very little to keep unlicensed copies from being made. So why bother? In my opinion, the reason is mainly if you create media for distribution of your product, users tend to expect a license key. Including this is mostly about creating a professional, high quality presentation for your product deployment. But you should understand that in terms of preventing unlicensed use of your product, the big boys have never been able to accomplish this and neither will you! Sorry, but that is the way it is!

What You'll Need

This procedure requires you to manually edit the msi file created by VS.NET manually using the Orca tool.  Download the Microsoft Windows Installer SDK if you do not already have Orca installed.

Page 3: Validating A Product Key In A Vs

There was a time when you could just download a Windows Installer SDK from Microsoft.   However, the brain tank at Redmond, in their mysterious "wisdom", decided to make this unavailable.  Now you have to download the 250MB Platform SDK just to get Orca???

You can still get the ancient Version 1 MSI tools, and luckily, the original version of Orca will allow you to open the version 2.0 msi created by VS.NET.  (I don't know about 2005, but VS 2002 and VS 2003 create version 2.0 installers).

Get it here, while you still can!

Version 1 Windows Installer SDK

Then find and run the Orca install.  

You will also need a C++ compiler.  VS.NET C++ and Visual Studio 6 C++ are both adequate.  The article describes the procedure using VS.NET C++.  The setup project and the dll were both created with VS 2002 but should be applicable to VS 2003 as well.

About the Download

The project and the source code for creating the custom DLL in VS.NET C++ is   included in the Sample Code Download, along with a sample MSI that has been modified to perform PID validation is also included so that you can examine the MSI of a typical modified package in Orca.

Procedures - Creating the Custom Action DLL

First we'll create the Custom Action DLL.

1)  Create the Custom Action Dll Project

Start Visual Studio NET.

Create a new VC++ Project.  Select Win32 Project as the type, and name the project PIDCheckDll. 

The Win32 Application Wizard will start.  Select the Application Settings option.  Select the following project settings:

Application Type:  Dll

Additional Options: Empty Project

Click the Finish button to create the project.

Page 4: Validating A Product Key In A Vs

2)  Configure the Dll Project

From the IDE main menu select Build, Configuration Manager.  The Config Manager dialog will be displayed.  Set Active Solution Configuration to Release and click Close.

Locate the \include folder where you installed the MS Platform SDK, typically C:\Program Files\Microsoft SDK\include.

Select Project, Properties and the Properties dialog will be displayed.  Verify that the active configuration is Release.  In the Configuration tree select C\C++ > General.   In the listview select Additional Include Directories and click the browse button.  The Additional Include Directories dialog will appear.  Click the New Folder button, and a folder dialog will appear. Browse to the Microsoft SDK\include folder.  Click Open to select the folder.  Click OK to dismiss the Additional Include Directories dialog.

The Properties page should now look like the figure below.

Next, in the Configuration tree select Linker > Input.    In the listview select Additional Dependencies and type msi.lib.  

Page 5: Validating A Product Key In A Vs

The Properties page should now look like the figure below.

Click Apply, then OK to close the Properties dialog.  The project is now configured properly.

About the Code

This is not a C++ tutorial, so I will only briefly describe what the code does. 

The dll exports a custom validation function, VerifyPID, which the setup will call to validate the serial number (PID) entered during the setup.  

VerifyPID calls a MSI API function to determine the location where the MSI is running.   This value is typically needed to locate a subfolder on the install media where you have placed an encrypted file that contains the specific PID that unlocks the install.  Since we can determine the run location during the setup, you do not need to worry about whether the CD is in D or E drive, etc.  You simply find the key file relative to the main msi path and perform your de-encryption algorithm to return the specific PID key value required by the setup. 

Page 6: Validating A Product Key In A Vs

VerifyPID next calls the MSI API to obtain the value the user entered for the PID.  The PID entered is compared to the PID extracted from the encrypted key file included on your media.  The VerifyPID then sets the PIDCHECK property in the msi to either true or false depending on the comparison results.

The format for your PID can be virtually anything.  We will see how to control the fields displayed by the setup later.  The important thing to keep in mind is that the PID format configured in the setup must match your actual PID string exactly, including any spaces and dashes.  The comparison succeeds only if the two strings match exactly, character for character.

For sake of example, the code shown here simply returns a string literal, and does not use a key file or encryption.  You can easily modify the code shown to add this functionality.  The sample code also includes minimal error checking for simplicity.

3) Add the Code to the Dll Project

Select Project, Add New Item.  In the dialog select C++ file and name the file PIDCheck.  Click Open.

Add the code in the sample PIDCheck.cpp file included in this download to the cpp file just created.

Save all, and then build the solution. The compiled dll will be created in the Release subfolder of the project.

Procedures - Configure the MSI To Validate a PID with the Custom Action

All modifications will be performed manually using Orca after the .msi is built.  I assume that you already know how to build an msi setup using Visual Studio NET.  Create your setup in the usual fashion.  Make sure you add the Customer Information dialog to the user interface sequence.   Finally, build the release version of your setup.

Adding PID validation to an msi requires the use of Microsoft's msi editing tool Orca.   First we will add the custom dll to the msi package.  The dll is embedded in the msi file and does not need to be distributed separately.  Next we will configure a custom action that instructs the msi on how to call the dll functions when the setup is run.  We will configure the property values required by the custom action to retrieve the PID value and return a boolean result indicating the validation outcome.   Finally, we will add the statements that control the setup dialog behavior for the dialog that collects the PID input from the user.

1) Add the Dll to the MSI

Page 7: Validating A Product Key In A Vs

Launch Orca.exe, and open the release version of your setup .msi file.  Orca is a database editor.  Tables are displayed in the list on the left, and fields in a selected table are displayed in the listview on the right.

Select the Binary table.    Double click on an empty row, or select Tables, Add Row from the Orca menu, and a dialog will be displayed.  In the Name field enter PIDCheckDll.  Click on the Data field, and a browse button will appear.  Browse to the compiled dll file and select it.  Click OK and the dll will be embedded in the msi as a binary stream.

2) Define the Custom Action

Now select the CustomAction table.  Add a new row, and enter the following values in the dialog.

Action:     CheckPID

Type:        1

Source:    PIDCheckDll

Target:     _VerifyPID@4

The Action field identifies the custom action.  The Type field is set to integer 1 which instructs the Windows Installer that the custom action uses a dll embedded as a binary field.  The Source field identifies the binary stream (which we included in the first step).  The Target field instructs the Windows Installer how to call the dll - in this case _VerifyPID@4 is the C style target function call exported by the compiled dll.

2) Configure Property Values

Next we need to configure the property values required by the PID validation.  First we will add a new property - PIDCHECK - that the dll will set to TRUE or FALSE based on the validation outcome.

Select the Property table.  Add a new row, and enter the following values in the dialog.

Property:    PIDCHECK

Value:         FALSE

This creates the custom property required by the dll and initializes it to a starting value of FALSE.  If the validation succeeds, the dll will set the property value to TRUE which will be used as a condition to continue the installation.

Now we will makes sure the PID entry fields are formatted correctly by setting the PIDTemplate property.  The Windows Installer automatically configures text input boxes in the CustomerInfo dialog to conform to the template specified.  See the SDK docs for

Page 8: Validating A Product Key In A Vs

more details on how to format input templates - it works essentially as a masked textbox, and the dialog will enforce field level key validation based on the mask.   In this example we have specified a PID value of 123 - 4567890.  The corresponding template is <### - #######>.

Select the existing PIDTemplate property and change the value is to:

<### - #######>

When the setup is run you will see that the dialog appears with two input boxes, separated by a space, dash, space.  The first box will accept three numeric digits, the second will accept seven numeric digits.

Next we need to enable the serial number input.   By default, setups built with VS.NET disable this field.  Find the property named CustomerInfoForm_ShowSerial and you will notice the value is set to 0 (false0.  Change this property value to 1 (true) to enable the mask input boxes.

The last piece of the puzzle is the PIDKEY property that the dll retrieves to determine what the user has entered for the PID value.  This is one of the many intrinsic properties (like TARGETDIR) supplied by the Windows Installer.  We do not need to add this property, it always exists, is always initialized to null, and is set automatically to the string entered by the user.  The setup will take care of concatenating input values that span multiple text box fields, etc.

3) Configure Dialog Controls

At this point, we have the basic elements in place for the validation.   We've added our dll that performs the string validation, instructed the Windows Installer how to call the dll, and configured the input and return properties required to allow the dll to read the user input and return a boolean outcome.

First we have to enable the serial number controls. 

Open the Control table.  Find the series of rows for the CustomerInfoForm dialog.  Each represents a control on the PID entry dialog.  Find the row entry for Control named SerialEdit, and set the Attribute column value to 3 to enable this control.   Repeat this operation for the controls named SerialLabel, and SerialBodyText.

4) Configure Dialog Conditions

The last step is to configure the dialog to call the dll validation   function at the correct time in the install, and configure the dialog controls to either prevent or allow the user to continue the installation base don the PID validation outcome.

Page 9: Validating A Product Key In A Vs

This is the most confusing part of the process.  Like everything else in an msi, instructions are in the form of database entries.  The Windows Installer reads table values and creates an installation script accordingly.  Dialog actions are no different, and we have a ControlEvents table that instructs the installation how to respond to user interface events like button clicks.  Although the format is a little different, the basic concept is not different from programming a conventional GUI.

In this case, the actions we need to take are simple and intuitive.   When the user clicks the Next button on the dialog that accepts the PID, we need to call our custom validation function.  We also need to either prevent or allow   navigation to the next dialog triggered by the Next button click based on the outcome of the validation.  The main difference when working with an msi is that instead of writing the appropriate code in a single button click event handler, we have to work with a database format.

Select the ControlEvent table in Orca.  You will see numerous entries - for each dialog and each control on each dialog.  Find the section where the Dialog field is CustomerInfoForm.  These are the control events entries for the PID dialog.  

Take care to make sure you enter the following changes exactly as shown, to the exact table row described or the sequence will be corrupted!

Find the row where the Control value is NextButton and the Event value is ValidateProductID. 

Change the value of the Event column from ValidateProductID to DoAction.  Change the value of the Argument column from {} to CheckPID.  This instructs the installation to run our dll custom validation when the user clicks the Next button on the PID dialog.

Next, find the row where the Control value is NextButton and the Event value is NewDialog.  This controls navigation.  Delete the existing entry in the Condition column.  Then enter the new conditional arguments that use our PIDCHECK property:

(PIDCHECK="TRUE") AND CustomerInfoForm_NextArgs<>"" AND CustomerInfoForm_ShowSerial<>""

This basically requires our PIDCHECK value to be TRUE (the other arguments are used internally by the msi).  If PIDCHECK is FALSE, the validatiuon failed and the user will not be able to advance to the next dialog, effectively halting the installation sequence.

5) Finishing Up

Now save the msi.  You must also close it in Orca before it will run.  Launch the setup and verify that it works as advertised.

Comments

Page 10: Validating A Product Key In A Vs

If you've followed this process correctly, by now you have probably realized something.  MSI is an open platform.  Anyone who has an editor tool like Orca and the knowledge can open your MSI, see where you require conditions to continue the install, and edit your setup to circumvent the validation.  But then again, there is not much to stop anyone who has a licensed copy of your software from giving the setup and the license key to anyone else.  As I stated before, licensing is about deterrents and mostly about maintaining a professional looking software distribution system.  People who really want to will be able to circumvent any licensing system.  That's life on the mean streets!

This page was last modified on:  October 25, 2005

This page was originally created on:  October 25, 2005

All Content Copyright 2005 Robert Graham  All Rights Reserved.