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 attributefor 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:
- The CAB is inspected to see if it contains an OSD file first. OSD files are basically Extensible Markup Language (XML) files with OSD vocabulary. The OSD specification is located at http://www.microsoft.com/standards/osd/; details on usage of OSD to install Java packages with the Microsoft Java Virtual Machine Package Manager or installing simple ActiveX Controls with OSD syntax can be found in the Extending Internet Component Download Using OSD article.
- If the CAB contains an OSD, it is processed for native code or Java packages to be installed as part of this software package. An OSD can also point to an INF file in the same CAB file.
- If the CAB does not contain an OSD file, a search is made for an INF file. If found, it is processed with the Component Download INF grammar detailed in INF setup-script format.
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:
- A single PE (portable executable, for example, an .ocx, a .dll, or an .exe file): This single executable is downloaded, installed, and registered in one step. This is the simplest way to package a single-file OLE control, but it will not use file compression, and it will not be platform independent except with HTTP.
- A CAB (cabinet) file: This file contains one or more files, all of which are downloaded together in a compressed cabinet. Exactly one file in the cabinet is an INF file providing further installation information. This INF file can refer to files in the CAB as well as to files at other URLs. This mechanism requires authoring of an INF file and packaging of a CAB file, but in return it provides file compression. It will not be platform independent, however, except with HTTP format negotiation.
- (Special case) A stand-alone INF file: The stand-alone INF can be used only when browser security is set to low or medium. This will not work in high browser security because a flat INF file cannot be signed, thus making it incompatible with Authenticode. This file specifies various files that need to be downloaded and set up for the OCX to run. The syntax of the INF file allows URLs pointing to files to download, and platform independence (by enumerating files for various platforms). This mechanism provides platform independence for non-HTTP servers.
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 OleSelfRegisteror
[foo.ocx] RegisterServer=yes ; register this even if not marked OleSelfRegister. ; This is the typical workaround for getting old ; controls to registerCode 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-x86The 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.OCXNote 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=2048If 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:
- It is now possible to include powerful INF files inside a trusted cabinet.
- By signing an entire cabinet, the time for verifying digital certificates can be accelerated due to the cabinet compression.
INF setup-script format
INF syntax understood by Internet Component Download
All URLs in the INF are to be encoded for handling of special charactersfor 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-name2Each 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=value2The 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=value2It 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-name5Just 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.0The 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,143Platform 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,143Thus 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:
- Download the necessary file(s) (.cab, .inf, or .exe) using URL Moniker(s).
- Call WinVerifyTrust to ensure that all downloaded files are safe to install.
- Complete self-registration of all COM components.
- Add registry entries to keep track of downloaded code (see Appendix on Registry Details).
- 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=mimetypeAll 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:
- If CLSID is provided with no version number, the most recent object matching the CLSID will be returned. If the CLSID is provided with a Version, the object matching the CLSID and with the largest version number greater than or equal to Version will be provided. If no object is available that matches the CLSID with a large enough version number, the 404 error will be returned. MIMETYPE will be ignored when CLSID is provided.
- If no CLSID is provided but MIMETYPE is provided, the first object found in the database that matches the MIMETYPE will be returned. Version, if provided, is treated exactly as above. If neither CLSID or MIMETYPE is provided, the error return code 400 Bad Request will be returned.
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:
- Object store servers at the beginning of the path will be asked for code before checking the location specified in the szCodeURL parameter for CoGetClassObjectFromURL. Servers at the beginning of the search path will thus be checked before trying the location specified in the CODEBASE attribute of an <OBJECT> tag. This is a useful feature for corporate intranets, because it allows intranet administrators to set up a local object store that is used to serve code for download by employees. In fact, it is possible to disable the CODEBASE attribute for <OBJECT> tags by removing the CODEBASE keyword from the search path.
- Object store servers at the end of the search path will be asked for code after trying the location specified in the szCodeURL parameter for CoGetClassObjectFromURL, and thus after trying the location specified in the CODEBASE attribute. This allows registration of default object store locations on the World Wide Web, where browsers can find code when no CODEBASE location is explicitly specified.
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:
- a - major version
- b - minor version
- c - custom number
- d - build number
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:
- If the file in question has an associated CLSID (either by the CLASSID attribute in the OBJECT tag for the main object to be instantiated, or specified by the clsid= key in the INF file), the following key is looked for on the client registry:
HKEY_CLASSES_ROOT:\\CLSID\{... clsid ...}\Installed version\The default value of this key if of the format a,b,c,d (as described in the previous section) is assumed to be the available local version of the clsid. This support is for extending version support to non-PE files such as Java class files. To make the version check more robust, the code downloader will also look for an optional named value "path" under the Installed Version key, which if present is validated to be present on the file system on the local computer. This is to ensure that a download takes place when the registry information is intact, but the actual file that implements the classid has been removed from the hard disk.
- The file version number is retrieved from the version resource and checked for sufficiency. If the file version cannot be retrieved, the version of the file is deemed insufficient and a download is initiated for that file. A trick to always download a non-PE file is to mark its FileVersion=1,0,0,0 or some non-zero version in the INF section.
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:
- 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.
- 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.0When 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:
- 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.
- 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.0When 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".
Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.