Geoff Chappell - Software Analyst
Windows has long had a scheme of associating file extensions, program IDs, class IDs, etc, in the registry, mostly under HKEY_CLASSES_ROOT. Programmers are left to find their way through an assortment of relevant settings which are mostly documented, though not as a single collection. At least for the shell’s purposes of examining associations, the shell itself nowadays has a formal notion of an association element which models all the registry settings for a particular association.
Every type of association element has a CLSID. The original way to create an association element was to pass the CLSID to the documented AssocCreate function. For Windows Vista, this function’s undocumented support for these CLSIDs was moved to SHELL32, so that an assocation element is now created by passing the undocumented CLSID to the undocumented SHELL32 function AssocCreateElement.
The following types of association element are supported:
Element Type | CLSID Symbol | CLSID Value | Applicable Versions |
---|---|---|---|
application | CLSID_AssocApplicationElement | {0C2BF91B-8746-4FB1-B4D7-7C03F890B168} | |
client | CLSID_AssocClientElement | {3C81E7FA-1F3B-464A-A350-114A25BEB2A2} | |
CLSID | CLSID_AssocClsidElement | {57AEA081-5EE9-4C27-B218-C4B702964C54} | |
extension | CLSID_AssocExtensionElement | {039A5DEA-159C-48B8-9DD3-56413A78FDE2} | SHELL32 only |
folder | CLSID_AssocFolderElement | {7566DF7A-42CC-475D-A025-1205DDF4911F} | |
perceived | CLSID_AssocPerceivedElement | {0DC5FB21-B93D-4E3D-BB2F-CE4E36A70601} | |
ProgID | CLSID_AssocProgidElement | {9016D0DD-7C41-46CC-A664-BF22F7CB186A} | |
ignore-unknown ProgID | CLSID_AssocProgidElementIgnoreUnknown | {503167C9-0060-471D-9DEA-C1E3306EC347} | SHELL32 only |
shell | CLSID_AssocShellElement | {C461837F-EA59-494A-B7C6-CD040E37185E} | |
star | CLSID_AssocStarElement | {0633B720-6926-404C-B6B3-923B1A501743} | |
system | CLSID_AssocSystemElement | {A6C4BAAD-4AF5-4191-8685-C2C8953A148C} | |
unknown ProgID | CLSID_AssocUnknownProgidElement | {E337427C-C96D-4183-9C00-B7B8671DF7B5} | SHELL32 only |
Each association element implements the following interfaces:
The AssocCreateElement function obtains an interface pointer to a newly created association element, which is only minimally constructed. All association elements expect initialisation in one of two ways. The aim in both is to provide the element with a query source, i.e., an IQuerySource implementation, which then supports the IAssociationElement methods.
One initialisation technique is to specify the query source explicitly, by passing the address of its IQuerySource interface to the element’s SetSource method. The other, arguably the preferred, way to initialise an assocation element is to let the element create its own query source from an initialisation string that is supplied to the SetString method. Different types of association elements interpret the initialisation string differently, mostly to decide the appropriate registry key to access as a query source.
All elements have SetString fail if an initialisation string has already been accepted. All elements have SetSource fail if a query source has already been accepted, including if created because of an earlier call to SetString. However, all elements allow SetString to override a query source that was already accepted through SetSource. This last scenario seems not to have been anticipated: the previous query source is merely forgotten, rather than released.
The GetString method produces a copy of the element’s initialisation string. The GetSource method obtains a desired interface to the element’s query source. The GetClassID method produces a copy of the element’s CLSID.
The IAssociationElement methods all query the query source for association settings. Without a query source, all these methods fail. Various well-known association settings are represented by values in the ASSOCQUERY enumeration, which is given as the first argument for all the methods. A second argument supplies an additional string to qualify the setting. Except for the QueryExists method, a third argument is an address at which to receive the data for the setting.