The Internet Component Download service will keep registry entries for every new downloaded component. These registry entries will be useful for (a) writing a utility for cleaning up the code storage, or (b) migrating the Component Download service to use a code cache rather than a permanent store(14).
To do correct code caching, the existing shared DLL ref. counting scheme will not suffice, because ref. counts are easily inflated. Specifically, any application that is re-installed increases the ref. count on a shared DLL even though that DLL already has a ref. count belonging to the particular application. (this is already broken for current ref. counting, but it will especially fail for Code Download, in which OCXs are used by multiple pages quite regularly, and there is no way of knowing which OCXs need reference counts.
To do ref. counting correctly, Component Download will maintain a ModuleUsage section in the registry which 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 <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 = Microsoft Internet Code Downloader Microsoft Internet Code Downloader= <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 char 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 then and this Module Usage key did not exist then 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. |
<Client ID> | ID 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 "Microsoft Internet Code Downloader", and the client-specific information is a number which serves as a reference count. 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 apps currently implementing only 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.
Footnotes
(1) Note: Internet Component Download as specified will not download anything other than OLE Objects. This document does not list steps needed to download/certify other entities. For other code-download needs see documentation for WinVerifyTrust.
(2) In future releases code for Document Object components will likewise be downloaded and installed automatically.
(3) Note: The <OBJECT> tag used to be called the <INSERT> tag. This change was decided on by the W3C on 2/13.
(4) Care must be taken so that the cabinet file contains only those files that must necessarily be downloaded (e.g. the OCX executable itself). Any additional helper DLLs (e.g. MFC) may have already been installed and if so should not be bundled into the cabinet.
(5) Note that Internet Component Download makes the assumption that a newer version of an object with the same ClassID is always backwards compatible with previous versions. A newer version of an object may be used to replace older versions without worry of losing functionality. If a newer version of an object is not backwards compatible with previous versions, it is advised to assign a new ClassID to the incompatible implementations in order to avoid one overwriting the other resulting in loss of functionality.
(6) If Internet Search Path is used to find the latest version of an object, Component Download will search the path, querying servers, and it will use the first matching component that is a newer version than the existing version installed on the system (if any). For more details see the below documentation on Internet Search Path.
(7) 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 (e.g. application/x-cabinet; os=win32 cpu=x86). Until more HTTP servers support such requests, the temporary scheme described above should suffice.
(8) Internet Component Download accomplishes self-registration using the /regserver command-line argument for .EXE files, and DLLRegisterServer() for other executables (.DLL, .OCX)
(9) See the specification for further details.
(10) Actually, this UI is displayed by the WinVerifyTrust mechanism that is used within Component Download.
(11) 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.
(12) Currently Object Stores must be HTTP servers that can serve content dynamically, for instance via ISAPI. In future versions a mechanism will be introduced allowing non-HTTP Object Stores.
(13) Note: an HTTP POST request is used, not a GET request. This is because the number of parameters involved is large enough that a GET request may exceed the maximum URL length of 1024 characters.
(14) Either of these would be intelligent about un-installing and un-registering component code using its existing self-registration mechanism.