ActiveX® controls frequently need to communicate with their containing object. For example, a control may want to QueryService for the cached InternetSecurityManager object to decide whether or not to take a particular action. Controls can obtain a pointer to their containing object (also called the object’s site) in one of at least two ways.
The typical scenario is Internet Explorer hosts the ActiveX® control inside of an object implemented in mshtml.dll. Controls that need to communicate with their container implement IOleObject and mshtml will call the SetClientSite method with a pointer to itself. Communication can now proceed by querying the given IOleClientSite pointer.
However, there is another scenario that authors of ActiveX® controls must consider. Controls can be dynamically created through script, e.g.:
oAX = new ActiveXObject(‘MyControl’);
In this case, the control is now being instantiated not by mshtml.dll, but by jscript.dll. Since jscript.dll does not implement any OLE containers, it does not set a client site pointer via IOleObject. It does, however, maintain an IServiceProvider chain to mshtml that can be accessed by an ActiveX® control. The control must implement IObjectWithSite. Now jscript will be able to call SetSite and the control can query the IUnknown pointer for services it requires from its container.
Astute readers may, at this point, notice something funny in the documentation. IObjectWithSite‘s documentation says, without elaboration: “This interface should only be used when IOleObject is not already in use.” This has to be read carefully. Notice the documentation uses the words “…in use,” not “…implemented.” You should keep track of the two different site pointers and prefer the one obtained from IOleObject. If, however, you find that site is NULL then IOleObject is not being used and it is acceptable to fallback to using the site obtained from IObjectWithSite.