A Complete Scriptable ActiveX Web Control Tutorial Using ATL

Introduction

ActiveX control is a term used to denote reusable software components that are based on the Microsoft Component Object Model (COM) that allows the developer to create objects or controls that can be used to "activate" content on the World Wide Web.

I have read lots of stuff over the Internet, but I have not found any complete guideline or example through which process I can build an ActiveX Control for the web using ATL with VC++ 6.0. I wrote this article because I couldn't find a unified description of this process anywhere on the web and also from my own hurdles. I am going to present you a complete example with the necessary details. I hope this will help you to understand how you can build a scriptable ActiveX control for the web, using ATL. Also, you will get a clear vision about ActiveX security details. It's written with as much detail as possible, but with the assumption that the reader basically knows his stuff.

In this article, I have tried to present an example of a Scriptable ActiveX Web Control using ATL; it will display a Label Control with the current Date and time on your Internet Explorer browser window. Also, you will be guided step by step through creating the control using Microsoft VC++ 6.0 as safe for the web.

Safety and Security

The security concerns associated with an ActiveX control are mainly due to the fact that ActiveX controls can do almost anything that a normal application can do. Therefore, both malware and useful ActiveX controls exist; thus, the threat level of an ActiveX control can be associated with how trusted its author is.

However, there is one famous case of an ActiveX control's safety concern: Internet Explorer. Internet Explorer has the ability to run ActiveX controls within a web page. This is both a blessing and a pain.

ActiveX controls, such as Adobe Reader, Adobe Flash Player, Apple QuickTime Player, Microsoft Windows Media Player, Real Networks RealPlayer, and Sun Java Virtual Machine are routinely used by Internet surfers every hour of the day all across the globe.

However, opening a web page that contains a harmful ActiveX control, and then allowing Internet Explorer to run that harmful control, would be same as running malware on the computer. Fortunately, Internet Explorer 6 and Windows Vista have taken actions to reduce such risks.

Requirements for Scriptable ActiveX Controls

Microsoft has published a document that describes all aspects of component object safety with regard to scripting ActiveX controls.

Before registering your control as safe for scripting, you must ensure that your control does not take any actions that may be unsafe when used by a scripting client. Unsafe actions include exposing information normally kept private, such as passwords and other sensitive information, executing files, and making dangerous system calls.

Another type of object safety concerns the use of parameters and properties with the control. When used with a scripting client, a safe control must ensure that the control can continue to function with any possible combination of properties defined by the user.

Designing a Scriptable ActiveX Control

A scriptable ActiveX control is a control that is constructed so that it is appropriate for use by scripting clients. Scriptable controls are designed to be safe when used in a Web browser, such as Internet Explorer, or by scripts written for the Windows Scripting Host (WSH). Scriptable controls also support mechanisms to simplify passing parameters to the control via a scripting language.

By default, ActiveX controls are not considered safe for scriptable clients. If you have an ActiveX control that could be useful to scripting clients, taking a few simple steps can expand the usefulness of your control. If you're using ATL, these changes typically take just a few minutes.

To be scriptable, an ActiveX control must meet the following requirements:

  • Be safe when executed by an arbitrary scripting client.
  • Be registered as "Safe for Scripting."
  • Support the IPersistPropertyBag interface. This is technically not a requirement, but it simplifies the task of passing parameters to the control.

Creating a Scriptable ActiveX Control

To create a Scriptable ActiveX control, use Microsoft Visual C++ 6.0 to perform the following steps:

  1. File->New->Projects.
  2. In the New Project dialog, as shown in Figure 1, select "ATL COM AppWizard".
  3. Figure 1: New Project Dialog

  4. Name the project ScriptableActiveX; for Location, enter the working folder for the project's source code, and then click the OK button.
  5. You will see a screen, as shown in Figure 2, that gives you several choices. The first choice is "Server Type." You are building a Server DLL, so make sure that the Server Type is set to "Dynamic Link Library."
  6. Figure 2: ATL COM AppWizard

  7. The other three checkboxes below do not concern you for this particular project, so you can ignore them. Press the finish button to have the Wizard generate the appropriate files for you.
  8. A "New Project Information" window, as shown in Figure 3, will appear to tell you what files are going to be created. Press the Ok button to accept this.
  9. Figure 3: New Project Information

Creating a New ATL Object

  1. From the Insert menu, select "New ATL Object" menu item. The "ATL Object Wizard" window, as shown in Figure 4, will appear.
  2. Figure 4: ATL Object Wizard

  3. Select Controls from the wizard's Category list box, and then select Full Control as the control type. Click Next to begin adding a ScriptableLabel control to the project.
  4. The "ATL Object Wizard Properties" dialog, as shown in Figure 5, will appear so that you can define your control's properties. For full controls, such as ScriptableLabel, the dialog box offers four tabs.
  5. Figure 5: ATL Object Wizard Properties

  6. All component types present a Names property page that contains naming attributes for ATL components. You only need to fill in the Short Name property for ScriptableLabel and the other fields are filled in automatically.
  7. The second tab, as shown in Figure 6, for most component types is the Attributes property page, which is used to collect information about the component. All these values are the default options, except "Support Connection Points" properties for the component. Connection points are used to supply events to a control's container.
  8. Figure 6: ATL Object Wizard Properties (Attributes)

  9. The third tab, as shown in Figure 7, is the Miscellaneous tab. It contains attributes specific to ActiveX controls.
  10. Figure 7: ATL Object Wizard Properties (Miscellaneous)

  11. The final tab, as shown in Figure 8, in the dialog box is Stock Properties. It contains a list of all stock properties that can be implemented by an ActiveX control.
  12. Figure 8: ATL Object Wizard Properties (Stock Properties)

  13. The ScriptableLabel control uses the following stock properties:
    • Background Color
    • Caption
    • Font
    • Foreground Color

After you select the stock properties listed here, click OK to close the dialog box. The ATL New Object Wizard then generates the necessary code and adds it to your project.

Modify Control Attributes

The default handler for OnCreate will superclass a default instance of the Windows CStatic class. Apply the following window styles changes to the OnCreate() member function to the ScriptableLabel control:

m_ctlStatic.Create( m_hWnd,
                    rc, 
                    _T("Static"),
                    WS_CHILD|WM_PAINT);

Retrieving Ambient Properties

When the control is loaded initially, it collects the current foreground color, background color, and font from its container. A good time to collect ambient properties is when the control and its container negotiate the client site. Add the following source code to the ScriptableLabel.cpp source file. This function overrides the base class implementation of SetClientSite() and stores the ambient values of these three properties.

STDMETHODIMP CScriptableLabel::SetClientSite(LPOLECLIENTSITE pSite)
{
   HRESULT hr = CComControlBase::IOleObject_SetClientSite(pSite);
   if(!m_pFont && pSite)
   {
      hr = GetAmbientFontDisp(&m_pFont);
   }
   GetAmbientBackColor(m_clrBackColor);
   GetAmbientForeColor(m_clrForeColor);
   return hr;
}

Add the following member function declaration to the CScriptableLabel class:

STDMETHOD(SetClientSite)(LPOLECLIENTSITE pSite);

Drawing the Control

The OnDraw() function is called by the ATL framework, passing in a structure that contains various bits of information needed to actually paint information on the screen. This implementation isn't much more complicated than it would be if you were simply displaying the current date and time. Add the following drawing code for the control to the ScriptableLabel.h header file.

void DrawString( HDC hdc, RECT* rc, BSTR caption )
{
   USES_CONVERSION;
   TCHAR* pCaption = OLE2T(caption);

   DrawText( hdc,
             pCaption,
             lstrlen( pCaption ),
             rc,
             DT_WORDBREAK );
}

HRESULT OnDraw(ATL_DRAWINFO& di)
{
   RECT& rc  = *(RECT*)di.prcBounds;
   HDC   hdc = di.hdcDraw;

   COLORREF clrFore, clrBack;
   OleTranslateColor(m_clrForeColor, NULL, &clrFore);
   OleTranslateColor(m_clrBackColor, NULL, &clrBack);
   SetTextColor(hdc, m_clrForeColor);
   HBRUSH hbrBtn = CreateSolidBrush(m_clrBackColor);

   FillRect(hdc, &rc, hbrBtn);
   DrawString(hdc, &rc, m_bstrCaption);

   DeleteObject(hbrBtn);
   return 0;
}

Implementing IPersistPropertyBag

To simplify the use of ScriptableLabel in a scripting client, such as Internet Explorer, the control must support the IPersistPropertyBag interface. The ATL class library includes a class, IPersistPropertyBagImpl, that provides a default implementation of IPersistPropertyBag that is sufficient in most cases.

  1. Add the following line to your class derivation list:
  2. public IPersistPropertyBagImpl<CScriptableLabel>
  3. Add the following line to your COM_MAP:
  4. COM_INTERFACE_ENTRY(IPersistPropertyBag)

Marking the Control as Safe for Scriptable Clients

You easily can add support for marking the Control as Safe for Scriptable Clients by implementing the IObjectSafety interfaces. This is done by deriving your control from the default ATL implementation, IObjectSafetyImpl.

You can use two methods to mark a control as safe for scripting clients:

  • Make appropriate entries directly in the System Registry.
  • Implement the IObjectSafety interface.

Microsoft recommends that you use new controls to implement the IObjectSafety interface instead of making Registry entries. IObjectSafety enables the control to apply much finer-grained safety policies than possible when using the Registry.

ATL provides a default implementation of IObjectSafety that you easily can take advantage of by deriving your class from the IObjectSafetyImpl class.

  1. Add the following line to your class derivation list:
  2. public IObjectSafetyImpl<CScriptableLabel,
                            INTERFACESAFE_FOR_UNTRUSTED_CALLER |
                            INTERFACESAFE_FOR_UNTRUSTED_DATA>
    
  3. Two template arguments are passed to IObjectSafetyImpl:
    • The name of the class deriving from IObjectSafetyImpl.
    • The type of safety to be applied to the control.

    Two values may be passed for the safety options:

    • INTERFACESAFE_FOR_UNTRUSTED_CALLER specifies that your control can be used safely by a scripting client and does not violate any of Microsoft's security or safety guidelines.
    • INTERFACESAFE_FOR_UNTRUSTED_DATA specifies that your control will work (or at least degrade gracefully) in the presence of any possible set of par
  4. Add the following lines to your COM_MAP:
  5. COM_INTERFACE_ENTRY(IObjectSafety)

Compiling the Scriptable ActiveX Control

Compile the ScriptableActiveX project. The compiler will register your new DLL in the Registry so that other programs can use it. You can test the control in a variety of control containers, including Visual Basic and Visual C++. You will find lots of examples using Visual Basic and Visual C++. Even better, consider a web control.

Because the ScriptableLabel control is scriptable, you also can use the control on an HTML page with Internet Explorer. Try it out.

A Complete Scriptable ActiveX Web Control Tutorial Using ATL

Building a Signed ActiveX Control

To use your control on web pages, it is very convenient to distribute it as a .cab (cabinet file). This is a compressed archive—the classic use is to put the .cab file on a web server, and refer to it from web pages that host the control. Internet Explorer is smart enough to download and install the control if it is not already installed on the client machine, and to selectively update any files that are newer in the .cab file. Microsoft provides CABARC.EXE for creating and editing .cab files.

The Contents of a CAB File

A CAB file contains at least two files in the archive: an ActiveX component file (.EXE, .DLL, or .OCX file), and an .INF file.

  • Component File (.EXE, .DLL, or .OCX): The type of ActiveX component you create determines the file extension of the file included here. All ActiveX controls have a .OCX extension. Other ActiveX components are either .EXEs or .DLLs. This file is your ActiveX component being installed.
  • .INF: This Information file contains information about what other files your ActiveX component depends on (dependency files), where to get copies of those files, and how to install those files.

Creating a CAB File

This section describes creating CAB files for distributing ATL and MFC controls over the Internet.

To create a CAB file:

  1. Create an INF file.
  2. Run the CABARC utility.
1. Creating an INF File

The INF file is a text file that specifies the files (such as DLLs or other OCXs) that need to be present or downloaded for your control to run. An INF file allows you to bundle all the needed files in one compressed CAB file. By default, files with the same version numbers as existing files on the user's hard disk will not be downloaded.

As an example, the following INF file will be used to create a CAB file for the ScriptableActiveX control.

; Sample INF file for SCRIPTABLEACTIVEX.DLL
[version] 
; version signature (same for both NT and Win95) do not remove
signature="$CHICAGO$"
AdvancedINF=2.0  

[Add.Code]
ScriptableActiveX.dll=ScriptableActiveX.dll
ScriptableActiveX.inf=ScriptableActiveX.inf

[ScriptableActiveX.dll]
file-win32-x86=thiscab
clsid={B8748B60-E34D-42AA-9309-8012CA4964AC}
FileVersion=1,0,0,1
RegisterServer=yes

[ScriptableActiveX.inf]
file=thiscab
; end of INF file

The clsid is the CLSID of the control to be installed.

2. Running the CABARC Utility

Once you have created an INF file, run the CABARC utility to create the CAB file. You should run CABARC in the directory that contains your source files. On the command line, put the source files in the order they appear in the INF and the INF file last. For example, to make a CAB file for the Polygon control from the INF above, use the following command:

CABARC -s 6144 n ScriptableActiveX.cab ScriptableActiveX.dll
                 ScriptableActiveX.inf

The -s option reserves space in the cabinet for code signing. The n command specifies that you want to create a CAB file.

Code Signing Tools

Microsoft provides code signing tools as part of the "Microsoft .NET Framework software development kit (SDK) 1.1." To download the SDK, visit the following Microsoft Web site: .NET Framework SDK Version 1.1. After you install the SDK, you will be able to find the code signing files in the following location on your PC: "\Program Files\Microsoft.NET\SDK\v1.1\Bin". From the many files found in the above BIN directory, the following are of interest:

  • signcode.exe
  • makecert.exe
  • cert2spc.exe
  • chktrust.exe

Recently, with the introduction of "Studio 2005," Microsoft has released a new set of tools. The new set of tools is provided as part of "Visual Studio 2005" and in the "Platform SDK." To download the "Platform SDK," visit the following Microsoft Web site: Platform SDK Full Download. After you install the SDK, you will be able to find the code signing files in the following location on your PC: "\Program Files\Microsoft Platform SDK\Bin". From the many files found in the above BIN directory, the following are of interest:

  • signtool.exe
  • makecert.exe
  • cert2spc.exe

All the above-mentioned tools are actually small console programs that should be run from a command prompt. When run, each program expects command-line parameters in a special syntax. Now, see how to do it in this article.

Signing a CAB File

Security is becoming increasingly important for software and media developers. "Code Signing" enables end users of your software to verify that the code you provide comes from the rightful source and that it has not been maliciously altered or accidentally corrupted.

Code signing technology has been available for many years, but many software vendors refrained from using it because of the complexity involved in the process. However, since the release of "Windows XP Service Pack 2," code signing cannot be ignored any longer.

With XP SP2, when downloading an UN-SIGNED program with Internet Explorer and choosing to open it (or even if saved to a file and later opened via Windows Explorer), the browser will display the "Security Warning" dialog. But, when downloading a SIGNED program the browser does not result in annoying error messages complaining that it is an unsigned or unsafe control.

You have two options to sign your code:

Option 1: Using a Test Certificate

Option 2: Using a Public Certificate

Option 1: Using a Test Certificate

Before you start with the process, it is highly recommended that you create a "TEST certificate," and use it to sign your program as a test run.

A program signed by this certificate must not be distributed on the Internet.

Use the following steps to sign and validate the .cab file:

  1. Type the following at a command prompt to create a private key file, Mycert.pvk.
    makecert -sv "mycert.pvk" -n "CN=My Company" mycert.cer
    The file created in this step, Mycert.cer, is used to create an .spc file. Type the password in the dialog box.
  2. Create an .spc file from the certificate file with the correct password. To do so, type the following line at a command prompt:
    cert2spc mycert.cer mycert.spc
    Note that this step involves creating a test private key. Alternatively, valid certificates can be created through Microsoft Certificate Server for Intranet use or purchased from external vendors for Internet use.
  3. Create a Personal Information Exchange file. This step is optional. You will need it only if you select to sign your code using SIGNTOOL.EXE, as described above. The following command line may be used to create a "Personal Information Exchange" (PFX) file:
  4. pvk2pfx -pvk mycert.pvk -pi Pass1 -spc mycert.spc
            -pfx mycert.pfx -po Pass2 -f
    

PVK2PFX.EXE expects two passwords:

  • Pass1: Provides the same password you used when creating the Private and Public keys.
  • Pass2: Provides a new password to protect the PFX file.

Once signed, you can distribute the ActiveX component to any user, but the user must install a certificate chain. If you want users to install an ActiveX component without the Root and Intermediate certificates, buy a Public code-signing certificate.

Option 2: Using a Public Certificate

To be able to sign your code, you will need a certificate. Certificates are issued by special Internet organizations called CA (Certificate Authority). There are many such organizations; the most prominent ones are verisign.com and tawthe.com.

You can get a full list of CAs by going to: Microsoft Root Certificate Program Members.

However, acquiring a certificate is quite a tedious and time-consuming process, (The CA has to identify you or your organization before it can issue a certificate) and you should expect to pay a few hundred dollars for the certificate.

Finishing Touches

Now, use the key information to sign the .cab file:

signcode -v mycert.pvk -spc mycert.spc ScriptableActiveX.cab
         -t [Timestamp server URL] 

Or, the following commands may be used to sign your code using SIGNTOOL.EXE:

signtool sign /f mycert.pfx /p Pass2 /v
         ScriptableActiveX.cab /t [Timestamp server URL]

Pass2: Enter here the second password you used when creating the PFX file.

Note: Specify the timestamp server URL at this step. The timestamp server URL provides a place to enter or edit the location of a timestamp server. A timestamp server validates the date and time that the cabinet file was signed. Certificate files can expire after a certain period of time. Contact your certificate file provider (certificate authority) for the location of their timestamp server.

The URL of a time stamping service provided for free by verisign.com is http://timestamp.verisign.com/scripts/timstamp.dll.

Validate a CAB File

Follow this procedure to validate a .cab file:

Option A: Using CHKTRUST
  1. Type the following at a command prompt to run SETREG.EXE on the client system with the TRUE value so that the test certificates are recognized:
  2. setreg -q 1 TRUE
  3. Run CHECKTRUST.EXE to ensure that the CAB file is signing correctly:
  4. chktrust ScriptableActiveX.cab

Expected results:

ScriptableActiveX.cab: Succeeded
Option B: Using SIGNTOOL

Run SIGNTOOL.EXE to verify the signing:

signtool verify /v /a ScriptableActiveX.cab

Expected results:

ScriptableActiveX.cab: Succeeded
Option C: Using Properties

You also can use the following method to verify your digital signature:

  • Open Explorer.
  • Browse to the file you just signed.
  • Right-click the file name and select "Properties."

Explorer will present you with the properties dialog of the file. This properties dialog will include a new tab, "Digital Signatures." You now can read the details of the signature in this tab.

A Complete Scriptable ActiveX Web Control Tutorial Using ATL

Embedding a Signed CAB File on a Web Page

ATL and MFC controls are embedded in Web pages using the <OBJECT> tag. Within the <OBJECT> tag, you need to specify three attributes for the control:

<OBJECT classid=B8748B60-E34D-42AA-9309-8012CA4964AC
        id=ScriptableLabelControl
        CODEBASE ="ScriptableActiveX.cab#version=1,0,0,1">
</OBJECT>

The ID parameter refers to the the control's name. The CLASSID parameter refers to the CLSID of the control. And, the CODEBASE parameter refers to the location from which to download the control. Note that CODEBASE can point at a number of different file types successfully.

If you include the optional version number with a CAB file, the version number should refer to the control being downloaded. For example, because ScriptableActiveX.dll has a version number of 1, 0, 0, 1, the version for the CAB is also 1, 0, 0, 1.

If you do not include the version number, older versions of the same control will not be replaced if they are found on the client machine.

Testing the Scriptable ActiveX Web Control

Adding controls by hand is not a simple process. The CLSID numbers are unwieldy to type, and it can be difficult to visualize the effects of the parameter settings on the control. To help with these difficulties, Microsoft created the ActiveX Control Pad, which can be obtained from their web site at Microsoft ActiveX Control Pad.

To test the Scriptable ActiveX Web Control with JavaScript, you may use ActiveX Control Pad to create it, or you may find it easier to lay out your page in your preferred HTML editor as the following HTML code:

<HTML>
<HEAD>
<TITLE>Scriptable ActiveX Web Control</TITLE>
<SCRIPT LANGUAGE="JavaScript">
   function NotifyActiveX(e)
   {
      if ( e.readyState != 4 ) return;
      window.setInterval("document.all.ScriptableLabelControl.
                         caption=(new Date()).toString()",1000);
   }
</SCRIPT>
<STYLE TYPE="text/css">
#ScriptableLabelControl {
   width: 250px;
   height: 25px;
   padding: 4px;
   border: thin solid #fc5;
   margin-left: 5em;
}
</STYLE>
</HEAD>

<BODY>
<OBJECT
   ID="ScriptableLabelControl"
   onReadyStateChange="NotifyActiveX(this)"
   CLASSID="CLSID:B8748B60-E34D-42AA-9309-8012CA4964AC"
   CODEBASE="ScriptableActiveX.cab">
</OBJECT>
</BODY>
</HTML>

Save this HTML code in your web server and browse it!

Internet Explorer will prompt the user before downloading and installing the ActiveX control. If Internet Explorer is attempting to install the Signed ActiveX control automatically, it shows the prompt, as shown in Figure 9.

[InstallActiveX.PNG]

Figure 9: The Signed ActiveX control's prompt

When prompted with a certificate, please accept it. When downloading and installation process are finished, the current date and time should appear, as shown in Figure 10.

[ScriptableControl.PNG]

Figure 10: Scriptable ActiveX Control

If you see the current date and time displayed properly in your browser, CONGRATULATIONS! ActiveX and scripting are working properly.

Notes:
  • If you see a date and time but it isn't the right time, your PC's clock is set wrong! Double-click the time in the system tray to correct it.
  • If you see a blank space, ActiveX is probably working properly, but not scripting.
  • If you see the message ActiveX is not supported, your browser doesn't recognize ActiveX at all. Netscape, Opera, or other browsers usually do not support ActiveX.
  • When you think you've corrected any problem you are having with this, simply refresh the page [press F5] to try again.

Conclusion

For a control to be scriptable, it must follow Microsoft's object safety guidelines and be marked as safe for scripting. In this article, you examined the IObjectSafety interface and learned how a control built using ATL can take advantage of IObjectSafety. An example of a safely scriptable ActiveX control helped you explore this topic.



Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

Most Popular Programming Stories

More for Developers

RSS Feeds