Contents Index Topic Contents | ||
Previous Topic: Introduction to ActiveX Controls Next Topic: ActiveX Control Tutorial |
Building ActiveX Controls for Internet Explorer 4.0
This article covers features of Microsoft® Internet Explorer 4.0 that a developer writing ActiveX Controls should take into account when targeting Internet Explorer 4.0 as a container. Some of the material in this article discusses existing technologies that have increased relevance with Internet Explorer 4.0; other sections discuss new technologies and services that are only available to a control in Internet Explorer 4.0. For an in-depth description of these technologies and reference documentation, the Internet Client SDK is the best source of information. To get the most out of this article the reader should already be familiar ActiveX Controls and associated COM technologies.
Justification for Targeting Internet Explorer as an ActiveX Control Container
Authoring Controls for the Active Desktop
Appendix: Additional Guidelines and Version Differences
Justification for Targeting Internet Explorer as an ActiveX Control Container
Internet Explorer is built upon a foundation of reusable and extensible components; two of the main componentsthe WebBrowser Control (SHDOCVW) and the HTML parsing and rendering engine (MSHTML)are available for reuse as part of other applications. An increasing number of Microsoft and third-party applications will be using the same underlying control container; thus, if a control works well in Internet Explorer 4.0 it will also work well in future applications. Current examples of this component reuse in the Internet Explorer suite include the Active Desktop and Outlook Express. Both use the same HTML rendering engine as Internet Explorer.
Apartment-Model Awareness
Apartment-model awareness is not a new issue with Internet Explorer 4.0, but it is an important one because of architectural changes in the multithreaded nature of containers such as Internet Explorer, the Active Desktop, and Outlook Express. Multiple instances of these containers are now quite common, so ActiveX Controls should be developed to conform to apartment-model rules to ensure that they behave correctly.
If a control is not apartment-model aware, the control might not function correctly. At the very least, it will suffer from degraded performance because calls to the control will be marshaled. This is due to the creation of the control being handled differently by the system if the control marks itself as being apartment-model-aware. Internet Explorer 4.0 will also reject improper calls across thread boundaries.
There are two relatively simple steps involved in making a control apartment-model-aware:
- Protect global resources. When data that is shared among instances of the control is being accessed, it should be protected so that other instances of the control do not attempt to access it at the same time. For example:
::EnterCriticalSection(&g_cs); // Access global data // .... ::LeaveCriticalSection( &g_cs );- Mark the control in the registry as "Apartment". This indicates to the system that the control understands and conforms to apartment-model rules and causes COM to create the control in its own apartment.
For further details about OLE threading models, see article Q150777, "Descriptions and Workings of OLE Threading Models," in the Microsoft Knowledge Base.
OC96 and Windowless Controls
While the OC96 (or OLE Controls '96) specification is not new, full support is only now appearing in common containers such as Office 97 and Internet Explorer 4.0; thus, the specification deserves further attention. One of the primary driving forces behind this specification was to improve the performance of controls for use on the Internet. An additional key feature is support for windowless controls. Windowless controls not only provide better performance, but they also can participate in overlapping 2D layout, can maintain a specific z-order, and can exhibit transparency as well as irregular shapes. Visual Filter effects will only function on components that support the windowless control specification since traditional windowed controls don't provide the hooks required for filters to affect painting. All the enhancements are designed to be compatible with existing OLE Controls technology, so a control can leverage these new features while maintaining backward-compatibility with down-level containers.
Key features of OC96 include:
- Delayed activation.
- Delaying the activation of a control means that a page can instantiate and be ready for interaction with the user faster, particularly if there are multiple controls on the page. A new interface, IPointerInactive, allows a control to remain inactive but still interact minimally with the mouse and drag and drop. Although the control still activates, it does so only as the result of some interaction with the user.
- Windowless.
- By supporting the windowless control specification, a control can make efficient use of its container's window rather than having a window of its own. This results in using fewer system resources and improves performance through faster activation/deactivation. The new interfaces introduced to support windowless controls include IOleInPlaceObjectWindowless and IOleInPlaceSiteWindowless. When drawing itself, a control asks the container-provided IOleInPlaceSiteWindowless interface for a device context and returns the device context to the container after drawing into it. Providing windowless support not only provides transparency for interesting visual effects, but also further improves the performance of the control.
- Hit detection.
- Hit detection is provided so that a windowless control can have an irregular shape and to complete the visual benefits of transparency. If the container detects that the rectangular extent occupied by a windowless control has been hit, it calls IViewObjectEx::QueryHitPoint (another new interface for windowless controls). The control then determines if it has been hit and returns an indication to the container.
- Quick activation.
- A new, optional interface, IQuickActivate, has been introduced to further speed activation of a control. If a container such as Internet Explorer 4.0 determines that this interface is supported by a control it is instantiating, the container calls IQuickActivate, passing two structures, one that the container uses to provide ambient properties and interface pointers to the control and the other for data that the control returns to the container. Replacing multiple calls with a single call increases the efficiency of instantiating a control.
Accessing Dynamic HTML
Internet Explorer 4.0 allows components to access the Dynamic HTML object model of the document in which the control is hosted. All the capabilities of the object model are available to the control, allowing it to both read and modify the document content. If a control supports either the IObjectWithSite or IOleObject interface, accessing the object model is very simple and consists of the following two steps:
- Call IOleClientSite::GetContainer. This returns the IOleContainer interface of the host of the control.
- Call QueryInterface on the IOleContainer interface for the IHTMLDocument2 interface.
The IHTMLDocument2 interface provides access to the document in which the control is hosted. Given this interface, it is possible to traverse the entire HTML object model. The following bit of code, written using Active Template Library (ATL) 2.0 smart pointers, accesses the object model and sets the background color of the document to pink. In script this is equivalent to document.bgColor = "pink".
// Get the document CComPtr<IOleContainer> spContainer; m_spClientSite->GetContainer(&spContainer); CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spDoc(spContainer); if (spDoc) spDoc->put_bgColor(CComBSTR(_T("pink")));Controls can perform any of the manipulations available to script in Internet Explorer 4.0. They can also perform functions that aren't possible from script due to security restrictions that do not apply to ActiveX Controls. To aid in the development process, use script to prove a concept; then translate that script to interface-level manipulation.
Note Any of the new interfaces introduced with Internet Explorer 4.0 are subject to change until the product is officially released. It is recommended that you maintain a copy of the header files you used to develop your code. When you upgrade to a later build of Internet Explorer 4.0, upgrade to the corresponding build of the Internet Client SDK, and use a file comparison tool such as Windiff to compare headers. Windiff is a utility that ships with the Microsoft Platform SDK as well as Microsoft Visual C++®.
Multimedia Services
Internet Explorer 4.0 ships with a number of multimedia controls; however, the services these controls use are also available to third-party controls. These include pixel-level manipulation, soon-to-be-introduced DirectDraw® support, timer and synchronization services, and visual filters and transitions. The full specifications and samples are included in the Internet Client SDK.
Security
Any ActiveX control to be deployed and used with Internet Explorer should be conceived and designed with object safety in mind from the start. Object safety is a promise by the control author about the potential for the control to be used in a manner that might compromise security. There are two variations of object safety that usually, but not always, go together:
- Safe for untrusted data asserts that the control is safe for any possible arguments (<PARAM> tags of an <OBJECT>).
- Safe for scripting asserts that the control is safe for any possible use of its properties, methods, and events.
ActiveX Control Safety Checklist
Safety of the control is ultimately a subjective judgment, but as a general rule "safe" means that none of the following undesirable effects will result for any conceivable use of the control:
- Exposure of private information on the local computer or network
- Modification or destruction of information on the local computer or network
- Faulting of the control and the potential crashing of the browser
- Consumption of excessive time or resources such as memory
- Execution of potentially damaging system calls, including execution of files
- Use of the control in a deceptive manner and causing unexpected results
To help check these abstract requirements, here are some questions to consider carefully before marking a control as safe. The same questions apply to both untrusted data and scripting.
- What files can the control potentially access?
- The ability to create files can be used to put content into the trusted local computer file system, possibly overwriting valuable data.
- Any arguments that allow arbitrary file paths to be specified are particularly suspect as potentially allowing access to private information.
- Writing excessive amounts of data even to restricted sets of files can use up disk space.
- Is registry access possible?
- Access to even limited parts of the registry could reveal information that should be kept private.
- Writing large amounts of data to the registry could waste resources or possibly corrupt the system.
- What system calls can the control be made to do?
- Executing code or arbitrary shell commands (such as FORMAT) is particularly dangerous.
- Think about how any system calls might be used by a malicious page, especially those calls with arguments that can be influenced by an untrusted data (<PARAM>) or script invocation.
- Other issues:
- Since any control can be used by any page that happens to know its CLSID, think about how the control might be reused maliciously in a completely unrelated page. Would the user possibly be tricked by seeing the familiar control out of context?
- Be sure the control won't loop infinitely or crash when given bad data or arguments.
- Can the control be made to call other objects on the page, including Java applets? The Java virtual machine (VM) called from native code in the control could attribute greater permissions to the control than script on the page has. If the script can manipulate the control to call the Java VM for it, an indirect security attack is possible.
- Can the control tunnel out of the frame in which it is hosted and access content in another frame? The data accessed could potentially violate the privacy of the user.
Using ActiveX Controls Safely in an Enterprise Intranet Environment
Using Internet Explorer 4.0 Security Zones, it is possible to configure the browser to only download or run ActiveX Controls located with the enterprise, a.k.a. the intranet. When a control is downloaded and installed on the local system, however, the location of the original download is no longer available, and the control is available for use on any page that might reference its CLSID. Thus, take heed to the possibility that an Internet page might reference a control intended only for the intranet. There are several approaches to handling this issue. If the ActiveX Controls are safe for untrusted data and for scripting, supporting IObjectSafety and requiring only safe controls is the simplest solution. Controls that are truly safe should not be usable to break security, even by an untrusted Internet page. To prevent an ActiveX control from being used on pages other than the one on which it is intended, the control can check the context in which it is instantiated. That is, a control can get access to the DHTML object model as described previously to get the URL of the page instantiating it. The location properties of the document object return the URL of the page in which the control is embedded. For instance, an ActiveX control could be designed to run only in the "http://admin" intranet area. When the URL of the containing document begins with a different protocol and host name, it could run with reduced functionality or otherwise completely disable itself. Be aware that some important controls might be inherently unsafe for scripting. They include tools to aid system configuration or installation. To safely use these ActiveX Controls in the intranet environment, it is important to guarantee:
- That these controls be used only by intranet pages and cannot be reused by other untrusted security zones;
- That any intranet pages that use these controls do so in the intended manner and with appropriate safeguards.
The first restriction can be enforced because, by default, ActiveX Controls are not safe for scripting. A system administrator can configure a custom security policy to override object safety for a specific intranet zone. Controls that are not marked as safe will run only in pages from this zone. In fact, it is possible to restrict a control to run only in a designated secure zone by explicitly not marking the control as safe. Of course the Internet zone should never be set to override object safety.
Authoring Controls for the Active Desktop
Internet Explorer 4.0 introduces several key innovations to the user's browsing experience. Among these are offline browsing and the Active Desktop. The former uses a caching mechanism to allow the user to read content from the Web without requiring them to be connected to it. The latter turns the desktop into a Web page by enabling the user to add any content viewable in the browser as an item to the Active Desktop including ActiveX controls. Network-aware components should understand the issues involved in authoring components for the Active Desktop that behave well in the offline state. For more information see the article on Supporting Offline Browsing in Applications and Components.
Debugging
In Internet Explorer 4.0 Integrated Browser Mode, the Windows® shell and the Web browser run in the same process space. This poses a challenge to developers who are attempting to debug their controls. Testing controls in Integrated Browser Mode is recommended because it helps to reveal apartment-model issues. For specific information on debugging ActiveX Controls in Internet Explorer 4.0, see Q167715, "Debugging ActiveX Controls in IE 4.0 Integrated Browser," in the Microsoft Knowledge Base.
Deployment
When deploying controls, use cabinet (.cab) files, and sign your controls. Issues regarding security have received great attention recently. End users are not advised to download executable content unless it is signed. If you do not sign your control, you cannot expect users to download your product. Cabinet files also create a better end-user experience because only one certificate is presented to the user, and a single, compressed download brings multiple files to the client computer. Details of this technology are in the Internet Client SDK.
Don't assume that non-system DLLs are already installed on a client computer. Although some releases of Internet Explorer ship with certain DLLs, such as MFC and Ctl3d32, this is not a reasonable assumption for minimal installations as well as future versions of Internet Explorer. In circumstances where a control is dependent on such DLLs, the main cabinet file should reference additional cabinets that contain the dependencies so they will be downloaded if necessary.
Appendix: Additional Guidelines and Version Differences
This section presents additional guidelines for creating controls as well as known differences in Internet Explorer's control hosting behavior between version 3.0 and 4.0. Internet Explorer 3.0 hosted controls in a slightly more relaxed fashion than Internet Explorer 4.0; Internet Explorer 4.0 follows the control container specification more stringently. This allows control authors to better anticipate the behavior of Internet Explorer 4.0 as a control container; however, it also means that controls which made assumptions based on Internet Explorer 3.0 behavior might no longer function as desired in Internet Explorer 4.0. Here we present the caveats we have discovered to control authors.
- If a control fires an event from a thread that it creates, rather than from the thread in which it was created, the connection point interface through which the event is fired must be marshaled to the secondary thread. For more information, see Q157437, "FIREV.EXE Fires Events from a Second Thread," in the Microsoft Knowledge Base.
- Internet Explorer 4.0 calls FindConnectionPoint on a control to hook up events even if the control exposes no events. A control should be written to expect this call.
- As previously mentioned, controls should be authored to respect apartment-model rules.
- The VBScript engine no longer passes parameters to controls by value (ByVal); they are now passed by reference (ByRef). Controls should check the VARTYPE field of parameters of type VARIANT explicitly.
- Internet Explorer 3.0 sent DoVerb with the verbs OLEIVERB_SHOW and OLEIVERB_HIDE to controls in addition to the verb OLEIVERB_INPLACEACTIVATE and IOleInPlaceObject::InPlaceDeactivate. Internet Explorer 4.0 no longer sends the show and hide verbs. A control should rely only on receiving the OLEIVERB_INPLACEACTIVATE verb and the IOleInPlaceObject::InPlaceDeactivate call.
- Internet Explorer 3.0 activated all controls immediately upon initialization of the control. Internet Explorer 4.0 does not. Instead it implements an optimization, only activating a control when it is visible (OLEMISC_ACTIVATEWHENVISIBLE). If a control needs to process window messages at initialization, it should create a hidden window for that purpose.
- In Internet Explorer 4.0, if a control implements a ReadyState property (DISPID_READYSTATE), events will remain frozen until the control notifies the container that the ready state has changed to READYSTATE_COMPLETE. Internet Explorer expects this notification through its IPropertyNotifySink::OnChanged implementation. Internet Explorer 3.0 would unfreeze events even if the control never reached the completed state. All controls should implement a ReadyState property to communicate their initialization status to scripts.
- A control should listen to IOleControl::FreezeEvents calls from the container. If a control fires an event that is important when events are frozen, the event will not be received by scripts. While it is not typically harmful to fire an event when events are frozen, if events are critical, the control should maintain a freeze count and implement a queuing mechanism, firing those queued events when FreezeEvents is called with FALSE and the freeze count reaches 0.
- In Internet Explorer 3.0, controls were unloaded when the browser was closed. Internet Explorer 4.0 relies upon proper COM reference counting. When the last reference to a control is released, the control will unload. Likewise, when the last reference to Internet Explorer is released, the browser will unload. A control should take care when caching interface pointers such as those returned by IOleClientSite::GetContainer and IOleControlSite::GetExtendedObject.
- A control should use the WM_CONTEXTMENU message to trigger a context menu and not utilize the WM_RBUTTONUP message.
- A control should not forcefully UI activate itself, or assume itself to be UI active. This is an area in which the page author should be in control, and a control that needs the focus should have it set through script. In the case of multiple controls on a page, a UI activation battle could cause strange results. Take as another example a control at the bottom of a large page that forcefully scrolls into view were it to UI activate itself upon instantiation.
- A control should only bring up modal dialog boxes when requiring immediate response to some user interaction. On the contrary, a control asynchronously downloading data in the background should not display a modal dialog box if the link fails. Instead it should fire an error event that a script could handle in its own fashion. Always keep the user in mind, as well as the effect a control's behavior will have upon applications hosting your control directly or indirectly through Internet Explorer 4.0 components.
- Controls should take advantage of the Internet Explorer 4.0 implementation of the IBindHost interface when performing data download. IBindHost can be obtained from Internet Explorer through the IServiceProvider interface, which is available by querying the IOleClientSite interface. For details, see the ATL 2.0 implementation of IBindStatusCallback, specifically IBindStatusCallbackImpl::StartAsyncDownload.
- Internet Explorer 4.0 eliminates the four-page in-memory cache. In Internet Explorer 3.0, controls would remain alive even though the page in which they were embedded was no longer in view. Assuming proper reference counting, Internet Explorer 4.0 destroys all controls embedded on the page when the user navigates away from the page. To keep a control alive, consider implementing a FRAMESET and placing the OBJECT tag in the HEAD element of the page containing the FRAMESET. While this instance of the control is not visible, it could provide global data for use by other objects contained within other frames within the frameset.
- Internet Explorer 4.0 prints documents by instantiating a second instance of the document on a background thread, by restoring the state of the document, and by requesting that the document print itself. To provide proper support for printing in Internet Explorer 4.0, controls should support one of the persistence interfaces (IPersist*). In addition, controls should make no assumptions about the type of device context (DC) they receive: controls should provide device independent rendering support. Finally, since controls are not put into the UI Active state when printed in the background, they should not rely upon window handles (HWND).
Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.