Creating Signed CAB Files for MFC and ATL Controls

Microsoft Corporation

If you plan to distribute Microsoft® Foundation Class (MFC) library and Active Template Library (ATL) controls via the Internet, you should package them as signed Cabinet (CAB) files. Signed files assure a user downloading your control that the code is safe. A CAB file contains a compressed version of your control plus information about how your control is to be installed, for example, what DLLs need to be installed along with the OCX.

The tools you need to create and sign CAB files are provided on the Visual C++® 5.0 CD in the CAB&SIGN directory. The utilities in the CAB&SIGN directory are not installed automatically when you install Visual C++, so you must copy the contents of the CAB&SIGN directory to your hard drive.

Before you can sign files, you need to get a Software Publisher Certificate. You must apply for your own certificate to a Certification Authority. With the tools in the CAB&SIGN directory you can create a test certificate for testing purposes, but this certificate cannot be used to sign code for distribution. See Step 1 for information about applying for a Software Publisher Certificate.

These are the steps to create a signed CAB file. Each step is discussed in separate section below:

  1. Get a Software Publisher Certificate (you only need to do this once).

  2. Create the CAB file.

  3. Sign your files.

  4. Embed the signed CAB file in a Web page (optional).

Step 1. Getting a Software Publisher Certificate

Before you can sign files, you need to obtain a Software Publisher Certificate (SPC). To do this, you must make a request to a Certification Authority. During the application process, you must generate a key pair and provide the Certification Authority with identification information, such as your name, address, and public key. You must also make a legally binding pledge that you cannot and will not distribute software you know or should have known contains viruses or will otherwise maliciously harm the user's machine or code.

To apply for a certificate, see "Digital Certificates for Authenticode" at http://msdn.microsoft.com/workshop/security/authcode/certs.asp. To create a test certificate to test signing your files, see the section below titled Making A Test Software Publisher Certificate.

The Certification Authority generates a Software Publisher Certificate that conforms to the industry standard X.509 certificate format with Version 3 extensions. The certificate identifies you and contains your public key. It is stored by the Certification Authority for reference and a copy is returned to you via electronic mail. After accepting the certificate, you should include a copy in all published software signed with the private key.

Making a test Software Publisher Certificate

You can use the MAKECERT and CERT2SPC utilities provided in the CAB&SIGN directory on the Visual C++ 5.0 CD to make a test Software Publisher Certificate. Note that this test SPC is not valid for software publishing, but can be used to test code signing.

To make a private key file called MYKEY.PVK and a company certificate called CERT.CER, run the MAKECERT utility with the following command:

  C:\CAB&SIGN\MAKECERT -u:MyKey -n:CN=MySoftwareCompany -k:MYKEY.PVK CERT.CER

MyKey is the name you give to your key and MySoftwareCompany is the name of your company. Note that the MAKECERT utility is case sensitive to command-line options, so you must use lowercase -u, -n, and -k. The value for the -n option must be an uppercase CN=.

To create a test Software Publisher Certificate (SPC) called CERT.SPC, run the CERT2SPC utility with the following command:

  C:\CAB&SIGN\CERT2SPC C:\CAB&SIGN\ROOT.CER CERT.CER CERT.SPC

Note that the CERT.SPC file is created from the CERT.CER file you created with MAKECERT and from the ROOT.CER file provided in the CAB&SIGN directory.

Step 2. Creating a CAB File

This section describes creating CAB files for distributing ATL and MFC controls over the Internet. If you need more information about CAB files, see the Cabinet File Reference in the Platform SDK documentation.

To create a CAB file:

  1. Create an INF file (see Creating an INF File below).

  2. Run the CABARC utility (available in the CAB&SIGN directory on the CD). For example:

    C:\CAB&SIGN\CABARC -s 6144 n MYCTL.CAB NEEDED1.DLL NEEDED2.DLL MYCTL.OCX MYCTL.INF

CABARC creates a CAB file called MYCTL.CAB.

You should run CABARC in the directory that contains your source files (the INF, OCX, and DLL files). The files archived in the CAB file should be listed on the command line in the same order they are listed in the INF file. In the example above, the INF file should list NEEDED1.DLL first, then NEEDED2.DLL, then MYCTL.OCX.

The -s option reserves space in the cabinet for code signing (Step 3). The n command specifies that you want to create a CAB file. For a list of CABARC commands and options, type CABARC alone on the command line:

C:\CAB&SIGN\CABARC 

Creating an INF file

The INF file is a text file that specifies the files (such as DLLs or other OCXs) that need to be present or downloaded for your control to run. An INF file allows you to bundle all the needed files in one compressed CAB file. By default, files with the same version numbers as existing files on the user's hard disk will not be downloaded. For more information about INF files and their options, including how to create platform-independent INF files, see the Platform SDK documentation.

As an example, the following INF will be used to create a CAB file for the ATL Polygon control. You can build POLYGON.DLL by downloading the ATL POLYGON sample files from the Visual C++ 5.0 CD and building a MinSize version. If you build a MinSize version of the Polygon control, you need one additional DLL, ATL.DLL. Since ATL.DLL needs to be registered before POLYGON.DLL, put ATL.DLL first in the INF.

; Sample INF file for POLYGON.DLL
[version] 
; version signature (same for both NT and Win95) do not remove
signature="$CHICAGO$"
AdvancedINF=2.0  
[Add.Code]
polygon.dll=polygon.dll
atl.dll=atl.dll
; needed DLL
[atl.dll]
file-win32-x86=thiscab
FileVersion=2,00,0,7024
DestDir=11
RegisterServer=yes 
[polygon.dll]
file-win32-x86=thiscab
clsid={4CBBC676-507F-11D0-B98B-000000000000} 
FileVersion=1,0,0,1 
RegisterServer=yes  
; end of INF file

This INF specifies that ATL.DLL with the given version needs to be installed on the system. If ATL.DLL doesn't exist already on the system, it will be downloaded from the CAB file created with this INF. "thiscab" is a keyword meaning the CAB containing this INF. You can also download a needed DLL from an HTTP location by specifying an absolute or relative path, for example:

file-win32-x86=http://www.mysite.com/mydir/NEEDED.DLL 

The keyword "file-win32-x86" identifies the platform as x86-specific.

You can get the version number of a file by clicking the right mouse button on the file in Windows NT® or Windows 95® Explorer. Select Properties from the list that appears, then select the Version tab on the dialog box that appears. You will sometimes need to insert an extra 0 in the file version. For example, the version number for the ATL.DLL is shown as 2.00.7024 in the dialog box. This becomes 2, 00, 0, 7024 in the INF file.

The "DestDir" is the directory where the file will be loaded: 11 specifies the system directory WINDOWS/SYSTEM or WINNT/SYSTEM32; 10 specifies the windows directory, WINDOWS or WINNT. If no DestDir is specified (typical case), code is installed in the fixed OCCACHE directory.

The "clsid" is the CLSID of the control to be installed.

Once you have created an INF file, run the CABARC utility (available in the CAB&SIGN directory on the Visual C++ 5.0 CD) to create the CAB file. You should run CABARC in the directory that contains your source files. Put the source files in the order they appear in the INF and the INF file last. For example, to make a CAB file for the Polygon control from the INF above, use the following command:

     C:\CAB&SIGN\CABARC -s 6144 POLYGON.CAB ATL.DLL POLYGON.DLL POLYGON.INF

This CAB file contains a compressed version of ATL.DLL and POLYGON.DLL along with the information needed to extract them in the POLYGON.INF file.

Step 3. Signing a CAB File

To sign a CAB file using the Code Signing Wizard:

  1. Run the SIGNCODE utility (available in the CAB&SIGN directory on the Visual C++ 5.0 CD) to launch the Code Signing Wizard.
    \CAB&SIGN\SIGNCODE
    
  2. In the Code Signing Wizard dialog box, click Next to advance to the next page.

  3. In the Which program would you like to sign? edit box, enter the name of the CAB file you want to sign.

  4. In the What would you like to call this program? edit box, enter the name as you want it to appear on the certificate.

  5. Click Next to advance to the next page.

  6. In the Under which Software Publishing Credentials would you like to sign this program? edit box, enter the name of the Software Publisher Certificate (SPC) file.

  7. In the Where can you find the secret, private key that goes with these credentials? edit box, enter the name of the private key (PVK) file.

  8. Click Next twice to advance to the last page.

  9. Click Sign to sign the CAB file. Your file will be digitally signed.

You can sign your DLLs and OCXs directly, without using a CAB file. The advantages of a CAB file are compression and, if used with an INF file, the bundling of all necessary code together.

Step 4. Embedding a Signed CAB File on a Web Page

ATL and MFC controls are embedded in Web pages using the <OBJECT> tag. Within the <OBJECT> tag, you need to specify three attributes for the control:

As an example, the following Web page displays the ATL Polygon control archived in the CAB file created in the Creating an INF File section above. The address http://www.mysite.com/mydir/polygon.cab should be replaced with the actual HTTP address of the CAB file:

<HTML>
<HEAD>
<TITLE>ATL 2.0 test page for object PolyCtl</TITLE>
</HEAD>
<BODY>
<OBJECT ID="PolyCtl" 
CLASSID="CLSID:4CBBC676-507F-11D0-B98B-000000000000"
CODEBASE="http://www.mysite.com/mydir/polygon.cab">
</OBJECT>
<SCRIPT LANGUAGE="VBScript">
<!--
Sub PolyCtl_ClickIn(x, y)
PolyCtl.Sides = PolyCtl.Sides + 1
End Sub
Sub PolyCtl_ClickOut(x, y)
PolyCtl.Sides = PolyCtl.Sides - 1
End Sub
-->
</SCRIPT>
</BODY>
</HTML>

CODEBASE can point directly to an OCX or DLL file:

CODEBASE="http://www.mysite.com/mydir/polygon.dll#version=1,0,0,1"

Since this causes only the DLL or OCX file to be downloaded and installed, any necessary supporting DLLs must already be on the client machine.

If you include the optional version number with a CAB file, the version number should refer to the control being downloaded. For example, since POLYGON.DLL has a version number of 1, 0, 0, 1, the version for the CAB is also 1, 0, 0, 1:

CODEBASE="http://www.mysite.com/mydir/polygon.cab#version=1,0,0,1"

If you do not include the version number, older versions of the same control will not be replaced if they are found on the client machine.