Internet Component Download Using INFInternet Component Download Using INF*
*Contents  *Index  *Topic Contents
*Previous Topic: Microsoft Internet Component Download Overview
*Next Topic: Extending Internet Component Download Using OSD

Internet Component Download Using INF

Microsoft Internet Explorer 4.0 introduces the concept of a software package. The packaging mechanism for this software package is a cabinet (CAB) file referenced by the CODEBASE element. A software package typically describes the smallest installable component, an ActiveX™ control, or a Java class library. The software package is addressed by its unique name/identifier and a version number. Legacy CABs that contain an INF file referenced by a CODEBASE attribute in the OBJECT element are automatically treated as a software package, with the unique name or identifier being the same as the GUID in the CLASSID attribute—for example, CLASSID=clsid:{9dba....}.

Software packages are described in the Open Software Description (OSD) vocabulary at http://www.microsoft.com/standards/osd. A software package CAB typically contains an OSD file. For compatibility and ease of use, it is possible to have the OSD reference a Microsoft Internet Explorer 3.0-style code download INF file inside the same CAB.

Packaging Component Code for Automatic Download

Independent software vendors and authors of COM objects for the Internet should package their implementations so they can be downloaded automatically by Web browsers such as Microsoft Internet Explorer. Such objects will be downloaded, for instance, when parsing the OBJECT tag in HTML.

Starting with Internet Explorer 4.0, an Internet Component Download CAB can contain a software package that represents a Java class library to be submitted to the Microsoft Internet Explorer Java Package Manager. Java class libraries are referenced by HTML in the APPLET and OBJECT element with PARAM NAME="useslibrary". When Internet Component Download is handed a CODEBASE that happens to be a CAB file, the following happens:

Interpreting the CODEBASE URL

The CODEBASE attribute in an OBJECT element contains a URL pointing to the implementation of a given COM object. This URL is of critical importance for component download, because it must specify all files necessary to implement a particular COM object. HTML authors can author the CODEBASE URL to point to one of two file types in the general case, and a third file type in a special case. Component developers should choose one of the following packaging schemes for their COM objects:

Registry settings and self-extracting EXE files

It's best to use self-registering code for Internet Component Download. For OCX, DLL, and EXE files marked as "OleSelfRegister" in the version resource, Internet Component Download will try to run self-registration. For DLLs, this means loading the DLL library and calling the DllRegisterServer entry point, if available. For EXEs, this means running the EXE file with the run-time parameter of "/RegServer". This ensures that COM objects implemented as local servers (for example, Winword.exe) are registered correctly. If an object is not marked as "OleSelfRegister" but registration is necessary, or if it is necessary to override the "OleSelfRegister" flag, one can add the following to an INF file (see the INF setup-script format below):

[foo.ocx]
RegisterServer=no 	; don't register even if marked OleSelfRegister

or

[foo.ocx]
RegisterServer=yes 	; register this even if not marked OleSelfRegister.
				; This is the typical workaround for getting old
				; controls to register

Code that is downloaded through Internet Component Download can be a self-extracting EXE because Internet Component Download ignores the "OleSelfRegister" flag if the main URL for code download points directly to an EXE file. In this case it is assumed that this is a self-registering EXE, and this enables self-extracting EXEs to work correctly as long as they ignore the /regsvr command-line parameter. Supporting self-extracting EXEs enables very complex setup mechanisms to be launched automatically through Internet Component Download. For details on how to package your self-extracting EXE as a hook instead of pointing your CODEBASE at it, see the "When and How to Use Hooks" section. However, if a self-extracting EXE is called through this mechanism, any components it installs will not be automatically tracked by Internet Component Download. Such components are permanently installed and are not marked by Internet Component Download for future cleanup.

Including the version number in the CODEBASE URL

In addition to the actual code address, the CODEBASE URL can also include an optional version number by using the following syntax:

"CODEBASE=http://www.foo.com/bar.ocx#Version=a,b,c,d"

The Internet Component Download mechanism downloads and installs the file only if the specified version number is more recent than any existing version of the same file currently installed in the system. If a version number is not specified with a file, it is assumed that any version installed on the system is recent enough.

If the version number specified in the CODEBASE attribute is "-1,-1,-1,-1", Internet Component Download will always try to download the latest version of the desired component. Note that this can be a costly effort involving many network transactions, especially if the Internet search path is searched for the newest version of an object. Note also that because of the Internet search path, it is possible for the Component Download service to try to download code in the absence of a CODEBASE attribute. In fact, if the CODEBASE attribute is the URL fragment "#Version=-1,-1,-1,-1", there is no specific location to download code from, but the Internet search path will still be searched to find the latest version of an object.

Platform independence and HTTP

When code to be downloaded is on an HTTP server, the HTTP Accept header MIME request type can be used to specify which platform the code is to run on, thus allowing platform independence of the CODEBASE URL.

The following MIME types are used to describe PE files (.exe, .dll, .ocx), cabinet files (.cab), and setup scripts (.inf).
File description MIME type
PE (portable executable) - .exe, .dll, .ocx application/x-pe-%opersys%-%cpu%
Cabinet files - .cab application/x-cabinet-%opersys%-%cpu%
Setup scripts - .inf (platform independent) application/x-setupscript
Macintosh® Binhex files application/mac-binhex-40

%opersys% and %cpu% specify the operating system and CPU for the platform on which downloaded components will be executed. For example, the MIME type for a Win32® cabinet file running on an Intel® x86-architecture processor would be:

application/x-cabinet-win32-x86

The following are valid values for %opersys% and %cpu%.
Valid values for %opersys% Meaning
win32 32-bit Windows® operating systems (Windows 95 or Windows NT®)
mac Macintosh® operating system
<other> will be defined as necessary
Valid values for %cpu% Meaning
x86 Intel® x86 family of processors
ppc Motorola® PowerPC architecture
mips MIPS® architecture processors
alpha DEC® Alpha architecture
68k Motorola® 68k CPU

When the code is on a non-HTTP server (for example, at a local LAN location), an INF file can be used to achieve platform independence by specifying different URLs for files to be downloaded for different platforms.

CAB format

The CAB format used for Internet Component Download is a nonproprietary format based on Lempel-Ziv compression. The Microsoft Internet Client SDK includes a free tool called DIAMOND.EXE that will package cabinet files into this nonproprietary format.

Using the DIAMOND.EXE tool for creating CAB files

The DIAMOND.EXE tool takes a DDF "directive file" specifying which files to combine into a cabinet. The syntax for using this tool from the command line is:

DIAMOND.EXE /f <directive file.ddf>

The following example directive file, Circ3z.dff, would be used for creating a cabinet file containing two files: Circ3.inf and Circ3.ocx. It should be straightforward to add to this list of files.

; DIAMOND directive file for CIRC3.OCX+CIRC3.INF
.OPTION EXPLICIT				; Generate errors on variable typos
.Set CabinetNameTemplate=CIRC3Z.CAB 
;** The files specified below are stored, compressed, in cabinet files
.Set Cabinet=on
.Set Compress=on
circ3.INF
circ3.OCX

Note It is possible to use the "code-signing" utilities to sign entire cabinet files using a digital certificate. However, to do this, it is necessary to add the following lines to the DDF file before the list of files for inclusion in the cabinet.

;Reserve space for PKS#7 Code Signature
.Set ReservePerCabinetSize=2048

If a cabinet file is signed, it is assumed that every file inside the cabinet is trusted, including .inf and .ini files. This has two advantages:

INF setup-script format

INF syntax understood by Internet Component Download

All URLs in the INF are to be encoded for handling of special characters—for example, 'space' should be encoded as "http://foo/foo%20bar.ocx". Friendly file names are created using the decoded base names of these URLs. URLs, if relative, are based of the context of the main CODEBASE=<url>, unless redirected by the object index, in which case the context is set to that of the redirected URL.

Code downloader-understood main sections

The code downloader looks for and understands the [Add.Code] and [Setup Hooks] sections in the INF file. If both these sections are missing, the INF is assumed to be a standard Win32 INF without code downloader extensions, and a hook is created to have the system process the INF's DefaultInstall section.

The Add.Code section lists all the files to be installed, including optional files.

[Add.Code]
filename1=section-name1
filename2=section-name2

Each file section is identified by the section name in brackets, followed by all the key values, as in an .ini file.

[section-name1]
key1=value1
key2=value2

The following keys are valid in a file section:

File-%opersys%-%cpu%=[url | ignore | thiscab]
%opersys% can be one of [win32 | mac] currently. %cpu% can be one of [x86 | ppc | mips | alpha].

A URL can be specified to indicate the correct file for the target operating system and CPU, or the special value "ignore", which indicates the file is not required for the specified platform. This key is always looked for before the platform-independent description key File= as described below.

File=[url | thiscab]
The value of the file key indicates where the file can be downloaded from. It can be a URL or the special value "thiscab", which indicates that the file is located in the CAB file where the INF file came from. If no value is specified, component download fails if the file is not already installed on the user's computer. If this URL points to a non-HTTP protocol or to an HTTP server that does not support/understand the special Accept Types sent out by the code downloader as discussed in the Platform Independence and HTTP section above, you must use the file-%opersys%-%cpu%= key described in the previous paragraph.
FileVersion=a,b,c,d
The FileVersion key specifies the minimum required version of the file specified by the File key. If no value is specified, any version is acceptable.
Clsid={nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}
The value of the clsid key is the string representation of the component CLSID, enclosed in braces {}.
DestDir=[10 | 11]
DestDir can be set to 10 to place the file into the \windows directory or to 11 to place the file into the \windows\system directory. If no value is specified, the file is placed in the \cache directory.
RegisterServer=[yes | no]
This is an override to the policy on whether to try to self-register this file. Section "Registry settings and self-extracting .exes" above in this document contain details on the registration policy.
Hook=section-name3
This is the way to specify conditional hooks. If the clsid or file of at least the version specified in this section is not sufficient and no File= or File-%opersys%-%cpu%= values are specified, this key hook is looked for by the component downloader to look for a custom setup hook to install the required file or component. The Hook section looks like the following:
[section-name3]
key1=value1
key2=value2

It is valid for several different file section hooks to point to the same hook section. This is a way to have one hook install one or more components/files. The hook is executed only once if one or more pieces are missing.

with the following valid keys:

File-%opersys%-%cpu%=[url | ignore]
%opersys% can be one of [win32 | mac] currently. %cpu% can be one of [x86 | ppc | mips | alpha].

A URL can be specified to indicate the correct file for the target operating system and CPU, or the special value "ignore", which indicates the file is not required for the specified platform. This is identical to the way you would specify the location of a file name in a section describing the piece in [add.code] except that this has to point to a CAB file and the keyword 'thiscab' is not applicable with this key. This value if absent would cause us to set our context to the CAB that this INF file was located in. This key is always looked for before the platform independent description key File= as described below.

File=[url]
This is a URL to a CAB file that contains one or more files that are needed for the hook. The component download downloads the CAB file and expands it into a unique temporary directory and then executes the hook. This is identical to the way you would specify the location of a file name in a section describing the piece in [add.code], except that this has to point to a CAB file, and the keyword 'thiscab' is not applicable with this key. This value, if absent, would cause us to set our context to the CAB that this INF file was located in.
Run=[cmd-line]
This is the command line to be run in the temporary directory with the extracted files in the CAB file pointed to by the above File= key. The command line can contain some component downloader variables that are expanded before execution. It can also contain translations of Win32 INF syntax based on registry key values on the client. Look for examples and details in the Appendix. If this key is absent, the component downloader looks for InfFile= and InfSection= keys to run a Win32 INF hook.
InfFile=[name of win32 INF file inside the CAB]
This is an optional key that, if absent, sets it to the current INF (the main INF pointed to or found in the CAB pointed to by CODEBASE=). This is a way to use standard Win32 INF syntax for installation of a file or component. Please look for samples and syntax of Win32 INF in the Appendix.
InfSection=[section name in the InfFile mentioned in above key]
This is an optional key that, if absent, sets it to the DefaultInstall section of the INF file specified in the InfFile= key above.

The Setup Hooks section lists all unconditional hooks to be executed before setup of files in the Add.Code section.

[Setup Hooks]
hookname1=section-name4
hookname2=section-name5

Just as within a section describing a file to be installed listed in Add.Code section, you could execute a hook to install/set up that file with the hook= key, you can also list a set unconditional hooks to be always executed before setup of files in Add.Code. This is done by listing all the hooks in order of preferred execution in the Setup Hooks section.

Note When using hooks, it is important to add the following lines to your INF file for compatibility.

[Version]
Signature="$CHICAGO$"
AdvancedINF=2.0

The following is a sample INF file that demonstrates the syntax understood by the Component Download service.

;Sample INF file for CIRC3.OCX
[Add.Code]
circ3.ocx=circ3.ocx
random.dll=random.dll
mfc40.dll=mfc40.dll
foo.ocx=foo.ocx

[circ3.ocx]
; Lines below specify that the specified circ3.ocx (clsid, version) needs to be
; installed on the system. If it doesn't exist already, it can be downloaded from
; the given location (a .CAB).
; Note: if "thiscab" is specified instead of the file location, it is assumed that 
; the desired file is present in the same .CAB cabinet that the INF originated from.
; Otherwise, if the location pointed to is a different .CAB, the new cabinet
; is also downloaded and unpacked in order to extract the desired file.
file=http://www.code.com/circ3/circ3.cab
clsid={9DBAFCCF-592F-101B-85CE-00608CEC297B}
; Note that the {}s are required when entering a CLSID in the INF file.
; This is slightly different from the HTML
; syntax for inserting CLSIDs in an <OBJECT> tag.
FileVersion=1,0,0,143

[random.dll]
; Lines below specify that the random.dll needs to be installed in the system.
; If this doesn't exist already, it can be downloaded from the given location.
file=http:// www.code.com/circ3/random.dll
; Note that the FileVersion is optional, and it can also be left empty,
; meaning that any version is ok.
FileVersion=
DestDir=10


; DestDir can be set to 10 or 11 ( LDID_WIN or LDID_SYS by INF convention).
; This places files in \windows or \windows\system, respectively.
; If no dest dir is specified (typical case), code is installed in the occache
; directory.

[mfc40.dll]
; Leaving the file location empty specifies that the installation
; needs mfc40 (version 4,0,0,5), but it should not be downloaded.
; If this file is not already present on the client machine, component download fails.
file=
FileVersion=4,0,0,5

[foo.ocx]
; Leaving the file location empty specifies that the installation
; needs the specified foo.ocx (clsid, version), but it should not be downloaded.
; If this file is not already present on the client machine, component download fails.
file=
clsid={DEADBEEF-592F-101B-85CE-00608CEC297B}
FileVersion=1,0,0,143

Platform independence in .INF files

It is possible to create platform-independent setup scripts that pull files from different locations depending on the desired platform. Internet Component Download INF files use a scheme similar to the one described under "Platform Independence and HTTP" earlier in this section. Specifically, a sample platform-independent INF file would include text such as the following:

[circ3.ocx]
; Lines below specify that the specified circ3.ocx (clsid, version) needs to be
; installed on the system. If it doesn't exist already, can be downloaded from
; the given location (a .CAB).
file-win32-x86=file://products/release/circ3/x86/circ3.cab
file-win32-mips=file://products/release/circ3/mips/circ3.cab
file-mac-ppc=ignore
; The 'ignore' keyword means that this file is not needed for this platform. 

clsid={9DBAFCCF-592F-101B-85CE-00608CEC297B}
FileVersion=1,0,0,143

Thus the "file=" syntax used in the INF file is expanded to "file-%opersys%-%cpu =", allowing the INF file to specify multiple locations where various platform-dependent modules can be found and downloaded. See the section above for valid values for %opersys% and %cpu%.

The Internet Component Download Service

The Internet Component Download service is exposed through a single function, CoGetClassObjectFromURL. This system function is called by an application to download, verify, and install code for an OLE component. The function is used in the implementation of Microsoft Internet Explorer.

The CoGetClassObjectFromURL function returns a factory object for a given rclsid. If no CLSID is specified (CLSID_NULL), this function chooses the appropriate CLSID for interpreting the Internet MIME type specified in szContentType. If the desired object is installed on the system, it is instantiated. Otherwise, the necessary code is downloaded and installed from the location specified in szCodeURL or from an object store on the Internet search path (see below).

This "download and install" process involves the following steps:

  1. Download the necessary file(s) (.cab, .inf, or .exe) using URL Moniker(s).
  2. Call WinVerifyTrust to ensure that all downloaded files are safe to install.
  3. Complete self-registration of all COM components.
  4. Add registry entries to keep track of downloaded code (see Appendix on Registry Details).
  5. Call CoGetClassObject for the desired rclsid.

In the common Web-browser scenario, the values for parameters passed to this function are read directly from an HTML OBJECT element. For example, the szCodeURL, dwFileVersionMS, and dwFileVersionLS parameters are specified inside an <OBJECT> tag as "CODEBASE=http://www.foo.com/bar.ocx#Version=a,b,c,d", where szCodeURL is "http://www.foo.com/bar.ocx", dwFileVersionMS is MAKELONG(b, a), and dwFileVersionLS is MAKELONG(d, c).

Because downloading and installation of code occurs asynchronously, CoGetClassObjectFromURL often returns immediately with a return value of E_PENDING. At this point, the IBindStatusCallBack interface is used to communicate the status of the download operation to the client. To participate in this communication, the client must implement IBindStatusCallback and register this interface in the pBindCtx parameter passed into CoGetClassObjectFromURL using RegisterBindStatusCallback. The client can expect to be called with callback notifications for IBindStatusCallback::OnStartBinding (providing an IBinding for controlling the download), IBindStatusCallback::OnProgress (reporting progress), IBindStatusCallback::OnObjectAvailable (which returns the desired object interface pointer), and IBindStatusCallback::OnStopBinding (which returns error codes in case of an error).

Storing/Caching Downloaded Code

Component Download installs most new code in a permanent store in windows\occache. The cache location can be overridden by a registry setting of HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ActiveXCache. Some components (helper DLLs that need to be on the system PATH but currently are not) will also be installed in \windows and \windows\system. All downloaded code is registered using a new "Module Usage" registry section that keeps track of such code. Downloaded code is not removed automatically, but it is possible in the future to add a user interface to the Control Panel (or elsewhere) allowing a user to clean up this directory.

Internet Search Path

When Internet Component Download is called to download code, it traverses the Internet search path to look for the desired component. This path is a list of object store servers that will be queried every time components are downloaded using CoGetClassObjectFromURL. This way, even if an <OBJECT> tag in an HTML document does not specify a CODEBASE location to download code for an embedded OLE control, the Internet Component Download will still use the Internet search path to find the necessary code.

Internet search path syntax

The search path is specified in a string in the registry, under the key HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet Settings\CodeBaseSearchPath. The value for this key is a string in the following format:
CodeBaseSearchPath = <URL1>; <URL2>; ... <URLm>; CODEBASE; <URLm+1>;
    ... <URLn-1>; <URLn>

In this format, each of URL1 through URLn is an absolute URL pointing to HTTP servers acting as "object stores". When processing a call to CoGetClassObjectFromURL, the Internet Component Download service will first try downloading the desired code from the locations URL1 through URLm, then try the location specified in the szCodeURL parameter (corresponding to the CODEBASE attribute in the <OBJECT> tag), and will finally try the locations specified in locations URLm+1 through URLn.

Note that if the CODEBASE keyword is not included in the CodeBaseSearchPath key, calls to CoGetClassObjectFromURL will never check the szCodeURL location for downloading code. By removing the CODEBASE keyword from the CodeBaseSearchPath key, corporate intranet administrators can effectively disable Internet Component Download for corporate users.

Object stores

An object store on the Internet search path is an HTTP server that services requests for downloadable code. During a call to CoGetClassObjectFromURL, Internet Component Download will try to download code from the various object stores on the search path. Specifically, an object store will receive an HTTP POST request with data in the following format:

CLSID={class id}
Version=a,b,c,d
MIMETYPE=mimetype

All the values above are optional, although one of CLSID or MIMETYPE must be present. The object store should parse this information, check an internal database, and either fail the call or redirect the HTTP request to the downloadable code cabinet file (.cab), setup script (.inf), or portable executable (.exe, .dll, .ocx).

The POST parameters should be processed by the object store as follows:

In addition to the POST data described above, queries to object stores will also include HTTP headers for Accept (MIME type) and Accept-Language, thus specifying the desired platforms (see above for Platform Independence and HTTP) and language-localized implementation for a component. Note that these HTTP headers are added to all HTTP requests made by Internet Component Download. This allows object stores to serve different code implementations for differing platforms or even different languages.

Note Internet Component Download uses the first successful response from a server on the Internet search path. Component Download will not continue searching for newer versions of components.

Uses for the Internet search path

The Internet search path can be used in two ways:

Registry Details

The Internet Component Download service keeps registry entries for every new downloaded component. These registry entries will be useful for writing a utility for cleaning up the code storage, or for migrating the Component Download service to use a code cache rather than a permanent store.

Why the existing "SharedDLL" mechanism is inadequate

To do correct code caching, the existing shared DLL reference counting scheme will not suffice, because reference counts are easily inflated. Specifically, any application that is reinstalled increases the reference count on a shared DLL even though that DLL already has a reference count belonging to the particular application. This is already broken for current reference counting, but it will especially fail for code download, in which OCXes are used by multiple pages quite regularly and there is no way of knowing which OCXes need reference counts.

New "ModuleUsage" registry mechanism for tracking usage of shared components

To do ref. counting correctly, Component Download maintains a ModuleUsage section in the registry that holds a list of "owners" and "clients" for each shared module. Thus the registry can keep track of who is using a shared module, not just how many clients that module has. The registry entries use the following syntax:

[ModuleUsage]
	[<Fully Qualified Path&File Name>]
		.FileVersion=a,b,c,d
		.Owner = Friendly Name/ID of Owner
		<Client ID > = <info peculiar to this client>
		<Client ID > = <info peculiar to this client>

A ModuleUsage section in a sample registry would look something like the following:

Under My Computer\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion:


[ModuleUsage]
	[c:/windows/system/mfc40.dll]
		.FileVersion=0,4,0,0
		.Owner ={CLSID of main object rclsid passed to CoGetClassObjectFromURL}
		{CLSID of main object rclsid passed to CoGetClassObjectFromURL}= <any info,
		    or default>
		AnotherAppID= <any info, or default>
Key name Description
<Fully Qualified Path&File Name> This is the full path of the shared module. This name has to use "/"s instead of "\"s because the "\" is an invalid character in a key name.
.Owner The application that installs the shared module and creates the original ModuleUsage section will put some identifier in the Owner key section. If the DLL already existed on the system and this Module Usage key did not exist, the .Owner key should be set to "Unknown" and the DLL should not be removed on uninstall. The owner should always also enlist itself as a client.
.File Version The version number for the shared module. This is unimplemented by Component Download at this time.
<Client ID> Identifier of a client who is using the shared module. The value corresponding to each client key contains client-specific information. When the client is Internet Component Download, the <Client ID> is {CLSID of main object rclsid passed to CoGetClassObjectFromURL}. For other clients, the client-specific information should be the full path of the client, so that if the client is accidentally deleted it is possible to do garbage collection.

Every client of this module is expected to increment and decrement the existing SharedDLLs section in the registry as well (a client only increments this value once when it adds itself as a client under [ModuleUsage]). This is to allow a migration path for applications currently implementing only a SharedDLLs scheme.

This registry information complements the reference counts in the SharedDLLs section by remembering which clients are actually using a shared module. This counting scheme will work correctly and allow caching of downloaded code. Furthermore, when downloading files, Internet Component Download can use this registry information as an efficient shortcut for verifying whether a file needs to be overwritten because it is an out-of-date version.

Win32 INF Syntax and Variable Substitutions

EXTRACT_DIR
Expands to the directory that the files in the CAB pointed to by the hook section were extracted to. For example, the following line in the Hook section will run the command mysetup.exe in the extracted directory.
run=%EXTRACT_DIR%/mysetup.exe 
OBJECT_DIR
Expands to the default destination directory for controls. In Internet Explorer 4.0, this is the Downloaded Program Files folder under the \windows directory. If there is a file name conflict with a previously existing file in this directory, CONFLICT.<n> folders are created under the default destination directory, when n is a monotonically increasing number. OBJECT_DIR reflects the final destination directory including such name conflict resolutions.

Version Number Format and Other Details

Version is a 64-bit number that you could break up as a,b,c,d, with most significant to least significant left to right. Typically the printed version numbers are represented as a.b.d (skipping c = 0), where:

For example, 4.1.6130 is really 4,1,0,6130.

Determining the local version number of a file

If a recent enough version of a file listed in either the CODEBASE attribute in the OBJECT tag or in the FileVersion= key in the section of the INF file is already available on the local computer, no download happens. When deciding if the version of an available local file is good enough, the following algorithm is applied:

Order of Processing and Execution of INF

The [Add.Code] section is processed in the order listed, but the files are installed and set up in reverse order. This means that typically you would list the main OCX file first in the INF file, followed by dependent DLLs. The dependent DLLs are guaranteed to be installed and available at registration time of the main OCX.

Unconditional hooks, those hooks in the [Setup Hooks] section in the INF file, are executed in the order listed in that section (Hook1 executed before hook2). Conditional hooks, those hooks in the file sections referenced by file names in the [Add.Code] section, are executed in the order of the [Add.Code] section. Between conditional hooks and file section installation/setup, conditional hooks always get executed before file section installations/setups in the same CAB. Between two file section installations/setups, the order of file installation and setup is the reverse of the listing in the [Add.Code] section. Between two conditional hooks, the order is the same as that listed in the [Add.Code] section. Note this different ordering rule between conditional hooks and file section installation and setup.

When and How to Use Hooks

A hook is a way to override or customize the installation process of one or more pieces required for a component. There are two types of hooks, unconditional and conditional.

Unconditional hooks are hooks that always get executed. These are hooks mentioned in the [Setup Hooks] section of the Internet Component Download INF file. A good example of an unconditional hook is a setup program. The following is an example of a case using a custom setup program to install the component. Its packaging is as follows:

  1. CODEBASE= points to a foo.cab that contains a foosetup.exe, foo.ocx, and foo.inf file. foosetup.exe, when run with the /q parameter, will install foo.ocx silently in the windows\occache directory.
  2. foo.inf has:
    [Setup Hooks]
    	hook1=hook1
    
    	[hook1]
    	run=%EXTRACT_DIR%\foosetup.exe /q
    
    	[Version]
    	; This section is required for compatibility on both Windows 95 and Windows NT.
    	Signature="$CHICAGO$"
    	AdvancedInf=2.0
    

When the Code Downloader pulls down foo.cab, it trust verifies the cabinet and then processes the INF. Seeing that it has no [Add.Code], it processes the [Setup Hooks] section. It extracts all the files in foo.cab in a unique temporary directory and then runs the command line listed in the run= key. All the files left in the temporary directory after the completion of foosetup.exe including foosetup.exe are discarded. See section on "Component Downloader Variables" for details on the use of %EXTRACT_DIR% variable in the run= key.

Conditional hooks are run only when a certain condition evaluates as TRUE. This is typically when the [Add.Code] section points to a certain piece, and that piece is not available on the client's computer. The above example of foo.ocx could be rewritten using conditional hooks as follows:

  1. CODEBASE= points to a foo.cab that contains a foosetup.exe, foo.ocx, and foo.inf file. foosetup.exe, when run with the /q parameter, will install foo.ocx silently in the windows\occache directory.
  2. foo.inf has:
    [Add.Code]
    	foo.ocx=foo.ocx
    
    	[foo.ocx]
    	Clsid={...}
    	hook=hook1
    
    	[hook1]
    	run=%EXTRACT_DIR%\foosetup.exe /q
    
    	[Version]
    	; This section is required for compatibility on both Windows 95 and Windows NT.
    	Signature="$CHICAGO$"
    	AdvancedInf=2.0
    

    When the Code Downloader sees the above INF, it processes the [Add.Code] section. When processing the foo.ocx section, it sees that the clsid (foo.ocx) is not registered/available on the client computer and so proceeds to execute the hook mentioned in the hook= key when it is hook1. Execution of hook1 is identical to the previous description of the hook as an unconditional hook. When only one component is in question, it doesn't make any difference whether marked conditional or unconditional as the whole code download was triggered because the CLASSID attribute in the OBJECT tag could not be found on the client computer. However, when installing a component that relies on some dependency that is separately installable by itself (such as MFC DLLs), it is good to use conditional hooks to install them.

    When mixing hooks and regular code download setups, read the section on "Order of processing and execution of INF".


    Up Top of Page
    © 1997 Microsoft Corporation. All rights reserved. Terms of Use.