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 Internet Component Download service to use a code cache rather than a permanent store.

  • Why the Existing "SharedDLL" Mechanism is Inadequate
  • Tracking Usage of Shared Components
  • Registry settings and self-extracting EXE files

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 Internet Component Download, in which OCXs are used by multiple pages quite regularly and there is no way of knowing which OCXs need reference counts.

Tracking Usage of Shared Components

To do reference counting correctly, Internet 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:/isapi/gomscom.asp?TARGET=/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>

The following table lists and describes shared module keys.

Key name Description
<Fully Qualified Path&File Name> This is the full path of the shared module. This name must use "/" instead of "\" because "\" 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 exists on the system and this ModuleUsage key does not exist, the .Owner key should be set to "Unknown" and the DLL should not be removed on uninstall. The .Owner key should always also enlist itself as a client.
.File Version The version number for the shared module. This is not implemented by Internet 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 the 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.

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 .dll files, this means loading the .dll library and calling the DllRegisterServer entry point, if available. For .exe files, this means running the .exe file with the run-time parameter of "/RegServer". This ensures that Component Object Model (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, add the following to an INF file:

[sample.ocx]
RegisterServer=no   ; Don't register even if marked OleSelfRegister.

or

[example.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 directing your CODEBASE to reference it, see Using Hooks. 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 cleanup.