Packaging ActiveX Controls

This article introduces a data-compression technology and associated tool set that you can use to package your Microsoft ActiveX control for faster, more efficient downloading over the Internet or an intranet. (This same technology and tool set can be applied to Microsoft Win32 applications, Java classes, and Java libraries.)

  • Cabinet Files
    • Accessing Controls Stored in Cabinet Files
    • Signing Cabinet Files
    • Microsoft Cabinet Software Development Kit (SDK)
    • Packaging Strategies for Multiple Platforms
  • Packaging the Sample ActiveX Control
    • Installing the Cabinet Development Kit
    • Creating the .inf File
    • Building the .cab File
    • Signing the .cab File
  • Cabarc.exe
    • Creating New .cab Files (n Command)
    • Listing Contents of Existing Files
    • Extracting Files from Cabinet Files
  • INF Files
    • The [version] Section of the .inf File
    • The [Add.Code] Section of the .inf File
    • The [mfc42installer] Section of the .inf File

Cabinet Files

For a number of years, Microsoft used cabinet (.cab) files to compress software that was distributed on disks. Originally, these files were used to minimize the number of disks shipped with packaged product; today, .cab files are used to reduce the file size and the associated download time for Web content that is found on the Internet or corporate intranet servers.

The .cab file format is a nonproprietary compression format, also known as MSZIP, that is based on the Lempel-Ziv data-compression algorithm. (Other compression formats might also be supported later.)

Accessing Controls Stored in Cabinet Files

An ActiveX control is identified by the OBJECT object in an HTML file. If the control has been stored in a .cab file, OBJECT must include a CODEBASE attribute that specifies the URL for this .cab file. The following excerpt from a sample HTML file demonstrates how the OBJECT object and CODEBASE attribute are used.

<OBJECT CLASSID="clsid:dcf0768D-ba7a-101a-b57a-0000c0c3ed5f"
    CODEBASE="http://webserver/time.cab"
    ALIGN="CENTER" WIDTH=270 HEIGHT=26 ID="T1"><PARAM NAME="Interval" VALUE=1000>
    <PARAM NAME="Enabled" VALUE=1></OBJECT>

Microsoft Internet Explorer 4.0 or later versions handle the OBJECT object and the CODEBASE attribute in the following manner.

  1. Parses the OBJECT object and searches for the CODEBASE attribute. If the CODEBASE attribute is absent or is preceded by a URL-to-object index server in the CodeBaseSearchPath, this index is used to retrieve the file.
  2. Locates the .cab file identified by the CODEBASE attribute.
  3. Expands the files found in the .cab file.
  4. Copies the expanded files to the user's computer (the default directory is \windows\occache).
  5. Registers the objects and/or files that require registration.
  6. Calls the Component Object Model (COM) CoCreateInstance function to create an instance of the specified object.

Signing Cabinet Files

A .cab file can be digitally signed like an ActiveX control. A digital signature provides accountability for software developers: The signature associates a software vendor's name with a given file. A signature is applied to a .cab file (or control) using the Microsoft Authenticode technology.

The .cab tool set assists software developers in applying digital signatures to .cab files by allowing a developer to allocate space in the .cab file for the signature.

Microsoft Cabinet Software Development Kit (SDK)

The Cabinet Software Development Kit provides developers with the components needed to use the Microsoft .cab file technology, or build .cab file management tools.

One of the tools available in the Cabinet Software Development Kit is Cabarc.exe. This command-line application enables you to compress an ActiveX control and store it in a .cab file. In addition to creating .cab files, you can use Cabarc.exe to list the contents of or extract files from an existing .cab file.

For an example that demonstrates how you can use Cabarc.exe to package an ActiveX control, see Packaging the Sample ActiveX Control.

For more information about Cabarc.exe and its options, see Cabarc.exe.

Packaging Strategies for Multiple Platforms

Internet Explorer 4.0 or later and ActiveX Controls can run on Macintosh and Intel x86 computers, as well as on any of several RISC machines. As a result, it's important that control developers create, test, and bundle their control's binaries for all platforms.

This section outlines three packaging strategies for supporting multiple platforms:

  • Multiple .cab files with the .inf saved in a separate .cab file
  • Multiple .cab files with the .inf and x86 binary bundled in a single .cab file
  • A single .cab file

Multiple .cab files with .inf in separate .cab

The first strategy requires that one .cab file contain a Windows 95 or later .inf file, the second contain the x86 binary, the third contain the Macintosh binary, and so on. Using this strategy, the CODEBASE attribute of the OBJECT object specifies the relative path for the .cab file that contains the Windows 95 or later .inf file.

The primary benefit of this strategy is reduced file size at download time—only the first .cab file containing the .inf file and a second .cab file with the appropriate binary for a given platform are downloaded.

The one drawback of this strategy is that two digital certificates will appear (one certificate per .cab file).

Multiple .cab files with .inf and x86 binary bundled in single .cab

The second strategy requires that one .cab file contain both the Windows 95 or later .inf file and the x86 binary. The remaining .cab files contain the Macintosh and RISC binaries (one binary per .cab file). Using this strategy, the CODEBASE attribute of the OBJECT object will specify the relative path for the .cab file that contains the Windows 95 or later .inf file and the x86 binary.

This strategy is most beneficial for controls that are primarily targeted at the x86 platform. Another benefit of this strategy is reduced file size at download time.

The one drawback of this strategy is that Macintosh or RISC users will have to wait for the x86 binaries to download.

Single .cab file

The third strategy requires that a single .cab file contain all binaries.

This strategy is most beneficial for small controls that have no dependent DLLs and that are primarily targeted at an intranet.

The drawbacks of this solution are that it does not optimize for dependent DLLs that might already be on the user's computer, and this solution might not be acceptable on some intranets.

Packaging the Sample ActiveX Control

This section describes how a single .cab file was created for the sample digital clock control. This .cab file contains a Windows 95 or later .inf file as well as the x86 binary for the control.

This example is based on the second packaging format described in the previous section of this article. However, the sample package is incomplete: a couple of final steps, which were omitted, require that a separate .cab file be created for the Macintosh binary as well as for each of the supported RISC platforms. In addition to creating the separate .cab files, the .inf file would need to be modified to point to these additional .cab files. These steps were omitted to simplify the example.

Installing the Cabinet Development Kit

To package an ActiveX control, it's necessary to install Cabarc.exe, a tool you download with the Cabinet Software Development Kit. When the Cabinet Software Development Kit is installed, you can begin using the tools it contains to build the necessary .cab files for your control.

Creating the .inf File

As previously stated, the sample .cab file bundles a Windows 95 or later .inf file with an x86 binary. The bundled .inf file contains information about the control, such as its name, its class identifier (CLSID), the name and location of required DLLs, whether the control requires registration, and so on. This .inf file has the following format.

[version]
    signature="$CHICAGO$"
    AdvancedINF=2.0
 [Add.Code]
    time.ocx=time.ocx
    msvcrt.dll=msvcrt.dll
    mfc42.dll=mfc42.dll
    olepro32.dll=olepro32.dll
 [time.ocx]
    file-win32-x86=thiscab
    clsid={DCF0768D-BA7A-101A-B57A-0000C0C3ED5F}
    FileVersion=1,0,0,0
    RegisterServer=yes
 [msvcrt.dll]
    FileVersion=4,20,0,6164
    hook=mfc42installer
 [mfc42.dll]
    FileVersion=4,2,0,6256
    hook=mfc42installer
 [olepro32.dll]
    FileVersion=4,2,0,6068
    hook=mfc42installer
 [mfc42installer]
    file-win32-x86=http://activex.microsoft.com/controls/vc/mfc42.cab
    run=%EXTRACT_DIR%\mfc42.exe

If you're bundling the .inf file and your control's x86 binary in a single .cab file, and if your control was written with Microsoft Foundation Classes (MFC) 4.2, you can use the previous example after you replace all occurrences of the sample control name (time.ocx) with the name of your control and replace the sample control's CLSID with the CLSID for your control.

If you're organizing your files differently, or if your control requires DLLs other than the Microsoft Visual C++; 4.2 DLLs, you'll need to modify the .inf file to accommodate your unique requirements. Note that if your control requires that a DLL be registered before the control, its corresponding entry in the .inf file must precede the control's entry in the file. Also note that the order of the source files in the command line that is passed to Cabarc.exe must match the order of the file references in the .inf file.

For more information about .inf files and the section tags found within them, see INF Files.

Building the .cab File

After you've installed Cabarc.exe and built the .inf file for your package, you can build the .cab file. In the case of the sample .cab file, this entailed running Cabarc.exe with the following arguments.

cabarc.exe -s 6144 N time.cab time.ocx time.inf

This command created a .cab file named Time.cab, which contains a compressed x86 binary for the sample control as well as a compressed version of the corresponding .inf file. The -s 6144 switch specifies that Cabarc.exe should allocate 6144 bytes for a digital certificate. (Code signing with digital certificates is described briefly in the next section).

For more information about Cabarc.exe and its use, see Cabarc.exe.

Signing the .cab File

When Internet Explorer 4.0 or later versions are running at the default security level, any object identified by the OBJECT object on an HTML page must be digitally signed. Digital signatures are created using Authenticode technology. A digital signature associates a software vendor's name and a unique public key with a file that contains an ActiveX object (ensuring some sort of accountability on the part of the object's developer).

Before you purchase a certificate for your control's .cab file from a vendor, you can use the test certificate provided by Microsoft for verification purposes. The following steps were required to add the software development kit (SDK) test certificate to the sample control's .cab file.

  1. Use Setreg.exe, which is one of the tools you download with Authenticode technology, to validate the test root in the trust hierarchy.

    setreg 1 true
    

    Setreg.exe replaces the Wvtston.reg and Wvtstoff.reg files that were shipped as part of the ActiveX SDK. Validation of the test root means that Internet Explorer 4.0 or later will treat a .cab file signed under the test root as though it included credentials.

  2. Use the Makecert.exe utility, which is another one of the tools you download with Authenticode technology, to create a key pair (the pair consists of a public and a private key).

    makecert -u:mykey -n:CN=mysoftwarecompany cert.cer
    

    In addition to creating the key pair, Makecert.exe associates the key pair with an X.500 distinguished name and creates an X.509 certificate that is signed by the root key (and that binds your name to the public part of the new key pair).

  3. Use the Cert2SPC.exe utility, another one of the tools you download with Authenticode technology, to generate a software publishing certificate (.spc file).

    cert2spc root.cer cert.cer cert.spc
    
  4. Use the Signcode.exe utility (and accompanying wizard), which also comes with Authenticode technology, to sign the .cab file.

    signcode -prog mycab.cab -spc cert.spc -pvk mykey
    

    If Signcode.exe is successful, it will have embedded a PKCS #7 certificate in the .cab file.

If you package your control in one or more .cab files, each file must be digitally signed.

For information about X.500 distinguished names, X.509 certificates, software publishing certificates, or PKCS #7 certificates, see Signing and Checking Code with Authenticode.

Cabarc.exe

Cabarc.exe is a utility that creates, lists, and extracts the contents of cabinet (.cab) files. Cabarc uses a command-line interface similar to that of popular archiving tools. Cabarc supports wildcards and recursive directory searches.

Cabarc is used as follows:

cabarc [<options>] <command> [<file list>]

Three commands are currently supported:

  • n (create a new .cab file)
  • l (list contents of an existing .cab file)
  • x (extract files from a .cab file)

Creating New .cab Files (n Command)

Cabinets are created by using the n command, followed by the name of the cabinet to create, followed by a file name list, as shown in this example:

cabarc n mycab.cab prog.c prog.h prog.exe readme.txt

This command creates the cabinet Mycab.cab, containing the files Prog.c, Prog.h, Prog.exe, and Readme.txt, in a single folder, using the default compression mode, MSZIP.

Cabarc supports wildcards in the file name list, as shown in the following example.

cabarc n mycab.cab prog.* readme.txt

Options (-p, -P, -r, -s, -i, -m, -l, +, @)

Path preservation (-p)

Directory names are not preserved in the cabinet (by default); only the file name component is stored. For example, the following command stores Prog.c in the cabinet.

cabarc n mycab.cab c:\source\myproj\prog.c

To preserve paths, use the -p option as shown in the following example.

cabarc -p n mycab.cab c:\mysource\myproj\prog.c

This command puts mysource\myproj\prog.c in the cabinet. Be aware that the c:\ prefix is still removed from the file name: Cabarc cannot store absolute paths in the cabinet nor extract such absolute paths.

Path stripping (-P)

The path stripping option, -P, is used for preserving part (but not all) of a path. The following example shows how this option can archive everything in the c:\mysource\myproj\ directory, but store only the myproj\ component of the path.

cabarc -p -P mysource\ n mycab.cab c:\mysource\myproj\prog.c 

The -P option strips any strings that begin with the provided string. Wildcards are not supported by the -P option; it is a simple text match. Absolute path prefixes, such as c:\ or \, are stripped before the comparison takes place. Do not include absolute path prefixes when using the -P option.

The -P option can be reused to strip out multiple paths. Cabarc builds a list of all paths to be stripped and applies only the first one that matches. Consider the following example.

cabarc -p -P mysrc\ -P yoursrc\ n mycab.cab c:\mysrc\myproj\*.* d:\yoursrc\yourproj\*.c

The trailing slash at the end of the path is important: Entering -P mysrc instead of -P mysrc\ adds files as \myproj\file name.

Recursive directory search (-r)

Cabarc has an option, -r, for a recursive directory search. Using this option archives files in a directory and all of its subdirectories. For example, the following command example archives all files ending in .h that are in c:\msdev\include\, c:\msdev\include\sys, and c:\msdev\include\gl (assuming these directories exist on your system).

cabarc -r -p n mycab.cab c:\msdev\include\*.h

The -p option is used here to preserve the path information when the files are added to the cabinet. Without this option, only the file names would be stored.

Reserving space for digital signatures (-s)

Cabarc can reserve space in the cabinet for a code signature. This is done with the -s option, which reserves a specified amount of empty space in the cabinet. For code signatures, reserve 6,144 bytes. Consider the following example for doing so.

cabarc -s 6144 n mycab.cab test.exe

The -s option does not actually write the code signature; it reserves space for it in the cabinet. Use the code signature utility to fill out the code signature.

Setting the cabinet ID (-i)

Cabinet files have a 16-bit cabinet identification field that is designed for application use. The default value of this field is zero; however, use the -i option of Cabarc to set this field to any 16-bit value, as shown in the following example.

cabarc -i 12345 n mycab.cab test.exe

Setting the compression type (-m)

Set the compression type with the -m option. The default compression type for a cabinet is MSZIP. Only MSZIP compression (-m MSZIP) and no compression (-m NONE) are supported. The following command stores files in the cabinet without compression.

cabarc -m NONE n mycab.c *.*

Creating a file list from a file (-l)

Cabarc can create a file list from a file. Cabarc compiles a list of file inputs from a text file (instead of from the command line), using the -l option, followed by the name of the file from which to take the inputs. Consider the following example.

cabarc -l filelist.txt n mycab.cab

The -l option can be reused to retrieve file lists from multiple files. Cabarc does not check for duplicate files. If the same physical file appears in multiple file lists, it gets added to the cabinet multiple times.

The -l option can be combined with file names on the command line. The files from the -l option are added first. Consider the following example.

cabarc -l filelist1.txt -l filelist2.txt n mycab.cab *.c *.h

Beginning new folders (+)

All files are put in one folder in the cabinet (by default). It is possible to instruct Cabarc to begin a new folder by using the plus sign (+) for the file to be added, as shown in the following example.

cabarc n mycab.cab test.c main.c + test.exe *.obj

This command creates the cabinet Mycab.cab with one folder containing Test.c and Main.c, and a second folder containing Test.exe and all files matching *.obj.

Generating a file listing from an existing file list (@)

Cabarc can input its list of files from a text file, instead of from the command line, by using @files ("at files"). This is done by using the @ symbol to prefix the name of the file that contains the file list. For example:

cabarc n mycab.cab @filelist.txt

The text file must list the physical file names of the files to be added, one per line. As is the case when specifying file names on the command line, the plus sign can be used as a file name to specify the beginning of a new folder. If a file name contains any embedded spaces, it must be enclosed in quotes, as shown here:

test.c
myapp.exe
"output file.exe"

The reason for requiring quotes is that each physical file name might be followed on the same line by an optional logical file name, which specifies the name under which the file will be stored in the cabinet.

test.c myapp.c
myapp.exe
"output file.exe" example.exe

If the logical file name contains spaces, it must also be enclosed in quotes. Note that the logical file name overrides the -p (preserve path names) and -P (strip path name) options—the file will be added to the cabinet exactly as indicated. Wildcards are allowed in the physical file name, but in this situation a logical file name is not allowed.

The @ feature can be used multiple times to retrieve file lists from multiple files. Cabarc does not check for the presence of duplicate files, so if the same physical file appears in multiple file lists, it will be added to the cabinet multiple times.

The @ feature can be combined with file names on the command line. Files are added in the order in which they are parsed on the command line. For example:

cabarc n mycab.cab @filelist1.txt *.c @filelist2.txt *.h

The @ feature is available only when creating cabinets, not when extracting or listing cabinets

Listing Contents of Existing Files

The list cabinet contents command, l, makes it possible to view the contents of a cabinet. Consider the following example.

cabarc l mycab.cab

Cabarc displays the Set ID in the cabinet (see the -s option for cabinet creation). Cabarc also displays the following file information: size, date, time, and attributes.

Extracting Files from Cabinet Files

The extracting cabinets command, x, extracts files from a cabinet. The simplest use of the x command is shown in the following example, which extracts all files from the cabinet.

cabarc x mycab.cab

Alternatively, it is possible to selectively extract files by providing a list of file names or a list of file names and wildcards. Consider the following example.

cabarc x mycab.cab readme.txt *.exe *.c

Full paths (if they are present in the cabinet), by default, are not preserved upon extraction. For example, if mysrc\myproj\test.c is in the cabinet, the command cabarc x mycab.cab causes Test.c to be extracted into the current directory. To preserve file names upon extraction, the -p option must be used. This option causes any required directories to be created, if necessary.

By default, the extracted files are stored in the current directory (and its subdirectories, if -p is used). However, it is possible to specify a destination directory for the extracted files. This is accomplished by appending a directory name to the command line. The directory name must end in a backslash ( \ ). For example:

cabarc x mycab.cab c:\somedir\
cabarc x mycab.cab *.exe c:\somedir\

The extracting cabinets option considers only the file name component in the matching process; the path name is ignored. For example, cabarc x mycab.cab test.c causes mysrc\myproj\test.c to be extracted to the current directory as Test.c, as will cabarc x mycab.cab *.c (which also extracts any other files matching *.c).

INF Files

An .inf file contains data that Windows 95 or later and Microsoft Windows NT 4.0 or later use to load and register a bundled control (as well as any files required by that control). The following topics describe each section of the .inf file.

The [version] Section of the .inf File

The first section in the .inf file is the [version] section. In the sample .inf, this section has the following format.

[version]
    signature="$CHICAGO$"
    AdvancedINF=2.0

The signature= tag specifies that the .inf version is compatible with Windows 95 or later and Microsoft Windows NT 4.0 or later.

The AdvancedINF= tag identifies the version of Advpack.dll that Internet Explorer 4.0 or later must load in order to parse this .inf file. In this case, version 2.0 is required.

The [Add.Code] Section of the .inf File

The second section of the .inf file is the largest section. In addition to the section immediately following the [Add.Code] tag, this section includes the subsections that are identified by the [time.ocx], [msvcrt.dll], [mfc42.dll], and [olepro32.dll] tags.

The [Add.Code] section maps files required by a given .ocx file to subsections in the .inf file. In the sample .inf file, this section has the following format.

[Add.Code]
    time.ocx=time.ocx
    msvcrt.dll=msvcrt.dll
    mfc42.dll=mfc42.dll
    olepro32.dll=olepro32.dll

The first line in this section maps Time.ocx (the file that contains the sample control) to a subsection of the same name. The second, third, and fourth lines map DLLs that the control requires to corresponding subsections in the .inf file. (The names of the .inf subsections are not restricted to the mapped file name; these names were chosen strictly for convenience in the sample.)

Because the sample control was created with MFC 4.2, the three named DLLs are required on a user's computer before the control will successfully run.

The [time.ocx] subsection of the [Add.Code] section

The [time.ocx] subsection has the following format.

[time.ocx]
    file-win32-x86=thiscab
    clsid={DCF0768D-BA7A-101A-B57A-0000C0C3ED5F}
    FileVersion=1,0,0,0
    RegisterServer=yes
  • The first line in this subsection specifies that the x86 binary is found in the same .cab file as the .inf file.
  • The second line specifies the control's CLSID.
  • The third line specifies the control's version.
  • The fourth line specifies that Internet Explorer 4.0 or later should register the control (using the specified CLSID and version number).

The [msvcrt.dll] subsection of the [Add.Code] section

The [msvcrt.dll] subsection has the following format.

[msvcrt.dll]
    FileVersion=4,20,0,6164
    hook=mfc42installer

The first line specifies the file version from the fixedfileinfo section of the DLL's version resource.

Note that the Properties dialog box in Windows Explorer only shows a portion of the version number. For example, in the case of Msvcrt.dll, the Properties dialog box will return 4.20.6164 as the version number (ignoring the third section [0] in the 4,20,0,6164 series).

The second line in this subsection, hook=mfc42installer, identifies a section in the .inf file that points to a .cab file that contains the required DLL (Msvcrt.dll).

The [mfc42.dll] subsection of the [Add.Code] section

The [mfc42.dll] subsection has the following format.

[mfc42.dll]
    FileVersion=4,2,0,6256
    hook=mfc42installer

For more information about these entries, see The [msvcrt.dll] subsection of the [Add.Code] section.

The [olepro32] subsection of the [Add.Code] section

The [olepro32.dll] subsection has the following format.

[olepro32.dll]
    FileVersion=4,2,0,6068
    hook=mfc42installer

For more information about these entries, see The [msvcrt.dll] subsection of the [Add.Code] section.

The [mfc42installer] Section of the .inf File

The final section in the .inf file is the [mfc42installer] section. In the sample .inf file, this section has the following format.

[mfc42installer]
    file-win32-x86=http://activex.microsoft.com/controls/vc/mfc42.cab
    run=%EXTRACT_DIR%\mfc42.exe

The file-win32-x86= tag specifies that the .cab file containing the MFC 4.2 DLLs is located at the specified site.

The run= tag specifies that the .cab file contains a self-extracting executable named Mfc42.exe.