Internet Component Download

DRAFT

January 1996

Microsoft Corporation

Download Microsoft Word (.DOC) format of this document (zipped, 28.6K).

Note: This document is an early release of the final specification. It is meant to specify and accompany software that is still in development. Some of the information in this documentation may be inaccurate or may not be an accurate representation of the functionality of the final specification or software. Microsoft assumes no responsibility for any damages that might occur either directly or indirectly from these inaccuracies. Microsoft may have trademarks, copyrights, patents or pending patent applications, or other intellectual property rights covering subject matter in this document. The furnishing of this document does not give you a license to these trademarks, copyrights, patents, or other intellectual property rights.

Contents

Overview
Executive Summary
Introduction
Packaging Component Code for Automatic Download
The Internet Component Download Interface
Storing/Caching Downloaded Code
Future Directions
Needs That Aren't Met by Internet Component Download
Appendix--Registry Details

Overview

This document provides a description of the mechanism for downloading and installing code for ActiveX™ objects (components) using the Microsoft® ActiveX technologies. This mechanism is used internally by the Microsoft Internet Explorer for downloading ActiveX controls inserted into HTML pages.

Executive Summary

Note: Internet Component Download as specified will not download anything other than ActiveX objects. This document does not list steps needed to download/certify other entities. For other code downloading information, see the documentation on the WinVerifyTrust API.

Introduction

Internet Component Download is a system service for downloading, certificate checking, and installing ActiveX component code from the Internet. This service is used by applications (such as Web browsers) to automatically download and install ActiveX objects from code repositories on the Internet. This document explains how code authors should prepare their components for automatic download. It then describes the interface for the component download mechanism, and finally provides some additional implementation details.

Internet Component Download is used within Microsoft Internet Explorer to automatically download ActiveX controls inserted into HTML pages using the <OBJECT> element in HTML. (In future releases, code for Document Object components will likewise be downloaded and installed automatically.) The mechanism for downloading components is exposed in an API that may be used in various other ActiveX containers. ActiveX control developers should follow the guidelines outlined below to package their controls so that they can be downloaded automatically by any container that uses the Internet Component Download mechanism.

Packaging Component Code for Automatic Download

Independent software vendors (ISVs) and authors of ActiveX objects for the Internet should package their implementations so that they may be downloaded automatically by Web browsers such as the Microsoft Internet Explorer. Such objects will be downloaded, for instance, when parsing the OBJECT tag in HTML. (The <OBJECT> tag used to be called the <INSERT> tag. This change was decided on by the World Wide Web Consortium [W3C] on 2/13.) For details, see the OBJECT tag specification. (See the ActiveX Development Kit, included in preliminary form on this Web site.)

Interpreting the "CODE" URL

The CODE attribute in an OBJECT tag contains a uniform resource locator (URL) pointing to the implementation of a given ActiveX object. This URL is of critical importance for component download, because it must specify all files necessary to implement a particular ActiveX object. HTML authors can author CODE URL to point to one of three file types. Component developers should choose one of the packaging schemes below for their ActiveX objects:

  1. A single PE (portable executable, such as an .OCX or a .DLL): This single executable file is downloaded, installed, and registered in one fell swoop. This is the simplest way to package a single-file ActiveX control, but it will not use file compression, and it will not be platform-independent except with HTTP.
  2. A .CAB (cabinet) file: This file contains one or more files, all of which are downloaded together in a compressed cabinet. (Care must be taken so that the cabinet file contains only those files that must necessarily be downloaded [such as the OCX executable itself]. Any additional helper DLLs [such as MFC] may have already been installed and, if so, should not be bundled into the cabinet.) Exactly one file in the cabinet is an .INF file providing further installation information. This .INF file may refer to files in the .CAB as well as to files at other URLs. This mechanism requires authoring of an .INF 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.
  3. A stand-alone .INF file: 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.

Including version number in the CODE URL

Besides the actual address of code, the CODE URL may also include an optional version number using the following syntax:

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

The Internet Component Download mechanism will download and install the file only if the specified version number is more recent than any existing version of the same file currently installed in the system (see the Appendix for more information). If a version number is not specified with a file, it is assumed that any version installed on the system is recent enough.

Platform independence and HTTP

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

The following multipurpose Internet mail extensions (MIME) types will be used to describe PEs (portable executables such as an .EXE, .DLL, or .OCX), cabinet files (.CAB), and setup scripts (.INF):

Note: The MIME scheme described here is temporary. Obviously this scheme results in too many MIME types. Eventually, MIME attributes will be used for the purpose of describing platform-dependent code (such as application/x-cabinet; os=win32 cpu=x86). Until more HTTP servers support such requests, the temporary scheme described above should suffice.

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

%opersys% and %cpu% above will specify the operating system and CPU for the desired platform on which the 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

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. (See the section below on platform independence in .INF files.)

.CAB format

The .CAB format used for Internet Component Download is a non-proprietary format based on Lempel-Ziv compression. The Microsoft Internet SDK includes a free tool called DIANTZ.EXE that will package cabinet files into this non-proprietary format. There no specification of this .CAB format publicly available, although such a specification will be distributed as soon as possible.

Use of the DIANTZ.EXE tool for creating .CAB cabinet files

The DIANTZ.EXE tool uses a .DDF "directive file" that specifies which files to combine into a cabinet. The syntax for using this tool from a command line is:

DIANTZ.EXE /f <directive file.ddf>

The example directive file below, CIRC3Z.DDF, would be used for creating a cabinet file containing two files: CIRC3.INF and CIRC3.OCX. It should be a straightforward process 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

.INF setup script format

Here is a sample .INF file that demonstrates the syntax understood by the Internet Component Download service. Only the .INF syntax below may be used to write setup scripts for Internet Component Download.

;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 doesn't exist already, can be downloaded from the given location (a .CAB)
file=http://www.code.com/circ3/circ3.cab
clsid={9DBAFCCF-592F-101B-85CE-00608CEC297B}
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
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 specified (typical case), code is installed in the fixed 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 will use a scheme similar to the one described above under Platform independence and HTTP. Specifically, a sample platform-independent .INF file would include a 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 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=file://products/release/circ3/macppc/circ3.cab

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 Interface

The Internet Component Download service is exposed via a single function, CoGetClassObjectFromURL(). This system function is called by an application that wishes to download, verify, and install code for an ActiveX component. The function is used in the implementation of Microsoft® Internet Explorer. The implementation uses URL monikers to asynchronously download code, and it uses the WinVerifyTrust service to verify validity of the code.

Related Documents:

Architecture

The diagram below shows the implementation architecture for the Internet Component Download mechanism and its relation to other system services:

[COD2086B  3982 bytes ]

Technical Details

This section describes technical details of the Internet Component Download API used by applications (such as Web browsers) to download and install ActiveX object code.

CoGetClassObjectFromURL


STDAPI CoGetClassObjectFromURL ( [in] REFCLSID rclsid, [in] LPCWSTR szCodeURL,
   [in] DWORD dwFileVersionMS, [in] DWORD dwFileVersionLS, 
   [in] LPCWSTR szContentTYPE, [in] LPBINDCTX pBindCtx, 
   [in] DWORD dwClsContext, [in] LPVOID pvReserved, [in] REFIID riid,
   [out] VOID **ppv );

This function will return a factory object for a given rclsid. If no CLSID is specified (CLSID_NULL), this function will choose 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.

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

  1. Download the necessary file(s) (.CAB, .INF, or executable) using URL moniker(s).
  2. Call WinVerifyTrust to ensure that all downloaded files are safe to install.
  3. Complete self-registration of all ActiveX components. (Internet Component Download accomplishes self-registration using the /regserver command-line argument for .EXE files, and DLLRegisterServer() for other executables [such as .DLL and .OCX].)
  4. Add registry entries to keep track of downloaded code (see the Appendix).
  5. Call CoGetClassObject for the desired rclsid.
CoGetClassObjectFromURL accepts the following arguments:

Argument Type Description
rclsid REFCLSID CLSID of the ActiveX object that needs to be installed. If value is CLSID_NULL, then szContentType is used to determine the CLSID.
szCodeURL LPCWSTR URL pointing to the code for the ActiveX object. This may point to an executable, to an .INF file, or to a .CAB file (see below for details).
dwFileVersionMS DWORD Major version number for the object that needs to be installed.
dwFileVersionLS DWORD Minor version number for the object that needs to be installed.
szContentType LPCWSTR MIME type that needs to be understood by the installed ActiveX object. If rclsid is CLSID_NULL, this string is used to determine the CLSID of the object that must be installed.
pBindCtx LPBINDCTX A bind context to use for downloading/installing component code. The client should register its
IBindStatusCallback in this bind context to receive callbacks during the download and installation process. (See the Asynchronous Monikers specification for details: It's included in the ActiveX Development Kit, available in preliminary form on this Web site. )

dwClsContext DWORD Values taken from the CLSCTX enumeration specifying the execution context for the class object.
pvReserved LPVOID Reserved value, must be set to NULL.
riid REFIID The interface to obtain on the factory object (typically IClassFactory).
ppv VOID ** Pointer in which to store the interface pointer upon return if the call is synchronous.
Returns S_OK Success. The ppv contains the requested interface pointer.
  E_PENDING Component code will be downloaded and installed asynchronously. The client will receive notifications through the IBIndStatusCallback interface it has registered on pBindCtx.
  E_NOINTERFACE The desired interface pointer is not available. Other
CoGetClassObject error return values are also possible here.

In the common Web-browser scenario, the values for parameters passed to this function are read directly from an HTML OBJECT tag. For example, the szCodeURL, dwFileVersionMS, and dwFileVersionLS are specified inside an <OBJECT> tag as:

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

where: szCodeURL is HTTP://WWW.FOO.COM/BAR.OCX, dwFileVersionMS is MAKEDWORD(A, B), and dwFileVersionLS is MAKEDWORD(C, D).

Because the downloading and installation of code occurs asynchronously, CoGetClassObjectFromURL will often return immediately with a return value of E_PENDING. At this point, the IBindStatusCallBack mechanism is used to communicate the status of the download operation to the client. (See the Asynchronous Monikers specification for details: It's included in the ActiveX Development Kit, available in preliminary form on this Web site. ) To participate in this communication, the client must implement IBindStatusCallback and register this interface in the pBindCtx passed into CoGetClassObjectFromURL using RegisterBindStatusCallback. The client can expect to be called with callback notifications for OnStartBinding (providing an IBinding for controlling the download), OnProgress (reporting progress), OnObjectAvailable (which returns the desired object interface pointer), and OnStopBinding (which returns error codes in case of an error). For further negotiations, the client must also implement ICodeInstall as described below.

Note: The initial (beta) implementation of CoGetClassObjectFromURL will not handle system-wide simultaneous downloads of the same code. Similarly, it will not handle cases where different simultaneous downloads refer to the same piece of dependent code.

IBindStatusCallback::OnProgress

The client of CoGetClassObjectFromURL will receive notification about the download/install process via the provided IBindStatusCallback interface. During the download process, the following additional values (from the BINDSTATUS enumeration) may be passed back as the
ulStatusCode parameter for IBindStatusCallback::OnProgress.

Value Description
BINDSTATUS_BEGINDOWNLOADCOMPONENTS The download operation has begun downloading code for ActiveX components that will be installed before the object may be instantiated. The szStatusText accompanying
IBindStatusCallback::OnProgress() provides the display name of the component being downloaded.

BINDSTATUS_INSTALLINGCOMPONENTS The download operation has downloaded code and is installing it. The szStatusText accompanying IBindStatusCallback::OnProgress() provides the display name of the component being installed.
BINDSTATUS_ENDDOWNLOADCOMPONENTS The download operation has finished downloading and installing all necessary code. The szStatusText accompanying OnProgress() provides the display name of the newly installed component.

ICodeInstall

A code installation operation requires additional services from the client in order to complete the negotiation necessary for a download operation. Such services are requested using
IBindStatusCallback::QueryInterface. The specific interface requested in IBindStatusCallback::QueryInterface is ICodeInstall. This interface must be implemented by a client of Internet Component Download.

interface ICodeInstall : IUnknown {
   HRESULT   NeedVerificationUI( [out] HWND* phwnd);
   HRESULT   OnCodeInstallProblem( [in] ULONG ulStatusCode, 
                                   [in] LPCWSTR szDestination,
                                   [in] LPCWSTR szSource,
                                   [in] DWORD dwReserved); 
      };

ICodeInstall::NeedVerificationUI

This function is called when Internet Component Download needs to display a user interface (UI) message for verification of downloaded code. (Actually, this UI is displayed by the WinVerifyTrust mechanism that is used within Component Download.) When a client is called with this function, it has the opportunity to clear the message queue of its parent window before allowing a UI message to be displayed. If the client does not wish to display the UI message, code verification may continue, but components may fail to be installed.

Argument Type Description
phwnd HWND * Client-provided HWND of the parent window for displaying code verification UI. If this parameter is NULL, the desktop window is used. If the value is INVALID_HANDLE_VALUE, then no code verification UI will be displayed, and certain necessary components may not be installed.
Returns S_OK Success.
  E_INVALIDARG The argument is invalid.

ICodeInstall::OnCodeInstallProblem

This function is called when there is a problem with code installation. This notification gives the client a chance to resolve the problem, often by displaying a UI message, or by aborting the code installation process. If the client does not understand the problem, it should return E_ABORT by default to abort the code installation process, because returning S_OK would imply retrying the operation.

Argument Type Description
ulStatusCode ULONG Status code describing what problem occurred. A member of CIP_STATUS.
szDestination LPCWSTR The name of the existing file that was causing a problem. This may be the name of an existing file that needs to be overwritten, the name of a directory causing access problems, or the name of a drive that is full.
szSource LPCWSTR Name of the new file to replace the existing file (if applicable).
dwReserved DWORD Reserved for future use.
Returns S_OK Continue the installation process. If there was an "access denied" or full-disk problem, retry the installation. If there was an existing file (newer or older version), overwrite it.
  S_FALSE Skip this particular file, but continue with the rest of the code installation process. Note that this is the typical response for the CIP_NEWER_VERSION_EXISTS case.
  E_ABORT Abort the code installation process.
  E_INVALIDARG The given arguments are invalid.

The ulStatusCode parameter above is one of the following values:

      typedef enum {
         CIP_DISK_FULL,
         CIP_ACCESS_DENIED,
         CIP_OLDER_VERSION_EXISTS,
         CIP_NEWER_VERSION_EXISTS,
         CIP_NAME_CONFLICT,
         CIP_TRUST_VERIFICATION_COMPONENT_MISSING
      } CIP_STATUS;

Value Description
CIP_DRIVE_FULL The drive specified in szDestination is full.
CIP_ACCESS_DENIED Access to the file specified in szDestination is denied.
CIP_OLDER_VERSION_EXISTS An existing file (older version) specified in szDestination needs to be overwritten by the file specified in szSource.
CIP_NEWER_VERSION_EXISTS A file exists (specified in szDestination) that is a newer version of a file to be installed (specified in szSource).
CIP_NAME_CONFLICT A file exists (specified in szDestination) that has a naming conflict with a file to be installed (specified in szSource). The existing file is neither a newer nor an older version of the new filebethey are mismatched but have the same filename.
CIP_TRUST_VERIFICATION_COMPONENT_MISSING The code installation process cannot find the necessary component (WinVerifyTrust) for verifying trust in downloaded code. szSource specifies the name of the file that cannot be certified. The client should display a UI message asking the user whether or not to install the untrusted code, and should then return E_ABORT to abort the download, S_OK to continue anyway, or S_FALSE to skip this file but continue (usually dangerous).

Storing/Caching Downloaded Code

The Code Download installs most new code in a permanent store in windows\system\occache. (This directory location is hard-coded for initial releases. In future releases users may use a registry setting or a Control Panel applet to choose this directory. Component code will be installed in this directory unless a previous version exist. In such cases, the Component Download mechanism will attempt to replace the previous version and invoke ICodeInstall::OnCodeInstallProblem.) 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 Registry "Module Usage" section that keeps track of such code. Downloaded code is not removed automatically, but it is possible in the future to add a UI message to the Control Panel (or elsewhere) allowing a user to clean up this directory.

For future releases, it is also possible to convert this "permanent store" into a code cache that retains only popular downloaded code and deletes old unused code automatically. This migration plan justifies use of a permanent store for the first version. See the Appendix for information on how downloaded code is listed in the Registry and how a code cache could function in future releases.

Future Directions

Internet search path

The Internet Component Download service will provide for an Internet "search path" stored in the Registry. This path is a list of Web 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 location to download code for an embedded ActiveX control, the Internet Component Download will still use the Internet "search path" to find the necessary component.

Further specification of the Internet search path is still under development.

"Pluggable" setup-script handlers

Although Internet Component Download currently supports a limited .INF setup-script syntax, future releases will take into consideration the need to support "hooks" that allow custom setup handlers to interact with the component download and installation process. No further details are available at this time.

Needs That Aren't Met by Internet Component Download

There are situations in which code needs to be downloaded with trust verification but the code is not an ActiveX object. Such cases are not addressed by the current specification of the Internet Component Download mechanism. Solutions for these cases need to use the WinVerifyTrust mechanism directly, as detailed below:

Appendix--Registry Details

The Internet Component Download service will keep Registry entries for every new downloaded component. These Registry entries will be useful for writing a utility for cleaning up the code storage, or migrating the Internet Component Download service to use a code cache rather than a permanent store. (Either of these would be intelligent about uninstalling and de-registering component code using its existing self-registration mechanism.)

Why the existing SharedDLL mechanism is inadequate

To do correct code caching, the existing SharedDLL 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 most certainly fail for the Code Download, in which OCXes are used by multiple pages quite regularly, and there is no way of knowing which OCXes need reference counts.

The new ModuleUsage mechanism in the registry for tracking usage of shared components

To do reference counting correctly, Internet Component Download will maintain 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 would use the following syntax:

[ModuleUsage]
   [Fully Qualified Path&File Name]
      FileVersion=a,b,c,d
      Owner = Friendly Name/ID of Owner
      [Clients]
         ID of Client1 = <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 = MSCodeDownloaderID
      [Clients}
         MSCodeDownloaderID= <any info, or default>
         AnotherAppID= <any info, or default>

Key name Description
Fully Qualified Path&Filename 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 an 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 uninstallation. The owner should also enlist itself as a client.

File Version The version number for the shared module.
Clients IDs of various clients who are using the shared module.

Every client of this module is expected to increment and decrement the existing SharedDLL section in the Registry as well (a client only increments this value once when it adds itself as a client under ModuleUsage). This allows a migration path for apps currently implementing onlya SharedDLL scheme.

This Registry information complements the reference counts in the SharedDLL section by tracking 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.


Return to the Code Signing home page

© 1996 Microsoft Corporation