Activex Quick Tutorial

Web based School

Creating an ActiveX Control


Previous

Editing the System Registry


Chapter 21

Creating an ActiveX Control

In this chapter you will be exposed to some of the advanced features of COM and DCOM OLE programming. First, you should know just what those two words mean.

Until now, you have been learning how to use OLE features within programs, and to use controls written by other people. For example, you used the marquee control, but you did not create the marquee control. Programs such as of Visual Basic (the next version) and Visual C++ enable you to create class objects (objects that are derived from classes) and OCX controls that others can use in their own applications.

A survey of the technologies that go into creating an OLE control would fill a much larger volume than this one. However, for those of you who will go on to creating these controls, this chapter reviews some of the features of control creation and how they apply to ActiveX. You will learn

  • How and why to edit the system registry

  • Some of the features and requirements of a COM/DCOM control

  • OLE interface design for objects and classes

Editing the System Registry

The system registry is the location for all the system settings on an NT or Win95 machine. Actually, any system that supports OLE will need to have some sort of equivalent to the system registry. When Microsoft introduced it in Windows 3.0, it allowed third-party programmers to write applications for Windows, which allowed Microsoft to sell more Windows, and so on.

Windows 3.0

Windows 3.0 has two sections of the Win.INI to enable OLE-like features—[Embedding] and [Extensions]. These sections tell the OLE system what features are enabled and what file extensions are associated with those features, respectively.

The format for the [Extensions] section follows a standard keyname = value format. An example section would look like this:

[Extensions]

crd=cardfile.exe ^.crd
doc=C:\MSOFFICE\WINWORD\WINWORD.EXE ^.doc
MDB=C:\MSOFFICE\ACCESS\MSACCESS.EXE ^.MDB
mpp=C:\MSOFFICE\WINPROJ\winproj.exe ^.mpp



msg=C:\PROGRA~1\MICROS~1\exchng32.exe /f ^.msg
ppt=C:\MSOFFICE\POWERPNT\POWERPNT.EXE ^.ppt
qry=C:\WINDOWS\MSAPPS\MSQUERY\msquery.exe ^.qry
vbp=C:\VB\vb.exe ^.vbp
wri=write.exe ^.wri

The Win.INI [Extensions] Section
Extension = Application FilePath ^.Extension

The [Extensions] section of the Win.INI file defines the application that is automatically associated with a given file extension. The INI file itself takes precedence over any similar settings in the system registry.

    Example:


foo = C:\FooDir\FooApp.exe ^.foo
In this example, an entry is made that will cause the computer to use the FooApp.exe program to handle FOO files.

The format in the [Embedding] section of the Win.INI tells the system the name of the control, the name of the object, the path to the control, and the type of object. An example [Embedding] section would look like this:

[embedding]
Mplayer = Media Clip, Media Clip, mplayer.exe, picture
ComicChat.Room.1 = Comic Chat Room, Comic Chat Room, C:\MSN\CCHAT\CHAT.EXE, picture

The [Embedding] section of the Win.INI file defines the OLE servers that can manipulate a given object. This file is only used for backwards-compatibility with older Windows 3.0-style programs.

Example:
My Object = My Object, My Object, C:\MyAppDir\MyApp.exe, picture

In this example, an entry is made that tells the operating system about a new type of server object called, My Object [ServerObject].
Next it gives the creatable object two descriptions. The first is a general name for the object; the second is a more generally readable description for it that will appear in menus and dialogs that refer to the object.
It also tells the system where there is an OLE server that is capable of creating one of these server objects [OLE Server].
Finally, it says what kind of file the data file will be. This is almost always picture.

Windows 3.1

Windows 3.1 added speed and OLE features to the access of the system registry components. Instead of keeping the information in diverse sections of multiple files, it keeps the most important parts of the registry in few fast-access binary files. Also, in response to the glut of programs being written for the Windows brand of OLE, Microsoft pre-added entries for several third-party OLE applications to the distribution copies of Windows 3.1. This made the installation of OLE-capable programs go more easily.

Windows 95,98

In Windows 98, access to the registry files is sped up considerably. This is to allow for the network feature of having dynamic keys. These keys make it possible for counters and various other real-time and metered data to be kept close to the processing environment.

Registry Components

The system registry is made up of information from three files. These files contain user-specific, computer-specific, and system-specific information. It would be difficult to show just what these files look like. They are not very human-readable, but they still contain the binary representation of a whole data structure. You have to use a tool like the RegEdit utility to read and manipulate the registry database.

System.DAT

The System.DAT file contains the system-specific information for the system, such as what type of monitor is installed, and how many keys are on your keyboard.

Reg.DAT

The Reg.DAT file is the computer-specific registration database of information for the system. It is through this database that changes to the registry are made. It is where support for OLE happens in Windows 95. Drag and Drop, OLE, and Compound Documents all refer to this database to perform their operations.

User.DAT

The User.DAT file contains the user-specific information about the user profile. This magic little feature of Windows 95 enables each user of a machine to have a Desktop customized to his/her own taste.

The information for each user's particular setup is contained in the policy settings portion of this file. User profiles make it possible for Mom to access her newsgroups that are pointed to her favorites, and Dad's are still pointed to his when he logs on to the system. They can also manage the ratings for Junior. One computer, multiple configurations.

The last registries file to be loaded during boot-up is the Policy.POL (System Policies) file. It can be edited with the System Policy Editor (distributed with the Windows 95 Resource Kit). The settings in the system policy override all other policies. It is usually loaded from the network so that all the systems can be managed in one way.

Editing the Registry Database

There are several good utilities that come with the Windows 3.1, 95,98, and NT systems that can assist you in editing the registry settings.

RegEdit

Windows 3.1 and 98 come with RegEdit.exe (see Figure 21.1, usually in the \Windows\ directory. In Windows 3.1 you had the command line option of /v to toggle between normal and advanced mode. In Windows 95 there is just one mode: Power User.


Warning

For you diagnosticians out there, when you trace a problem with a client machine to a "mysterious" registry problem, try to find out if they did not go running around lose in the RegEdit program. It's a good place for someone who does not know what they are doing to really hurt themselves.


Figure 21.1. The Windows 95 Registration Editor.

The RegEdit utility is handy for editing the way OLE is carried out on a system. The functions that can be customized through RegEdit include Open, Close, Delete, Print, Edit, and other functions you might find on the File menu of an application.

When you have an OLE application on your system, you will want to make sure that it's registered in the registration database. Ideally, the software author included processes to automatically register and unregister their OLE server.

If the author did not include this process, or if the program somehow becomes unregistered on your system, there should be a REG file somewhere. These files are associated with the RegEdit utility to register the software component. This can also be done from the RegEdit Merge-Registration Info menu.

Here is a sample REG file for the Windows Media Player (also see Figure 21.2:
REGEDIT
HKEY_CLASSES_ROOT\mplayer = Media Clip
HKEY_CLASSES_ROOT\mplayer\protocol\StdExecute\server = mplayer.exe
HKEY_CLASSES_ROOT\mplayer\protocol\StdFileEditing\Handler = mciole.dll
HKEY_CLASSES_ROOT\mplayer\protocol\StdFileEditing\server = mplayer.exe
HKEY_CLASSES_ROOT\mplayer\protocol\StdFileEditing\PackageObjects =
HKEY_CLASSES_ROOT\mplayer\protocol\StdFileEditing\verb\1 = &Edit
HKEY_CLASSES_ROOT\mplayer\protocol\StdFileEditing\verb\0 = &Play
HKEY_CLASSES_ROOT\mplayer\shell\open\command = mplayer.exe /play /close %1
;OLE2 Compatibility entries.
HKEY_CLASSES_ROOT\MPlayer\CLSID = {0003000E-0000-0000-C000-000000000046}
HKEY_CLASSES_ROOT\CLSID\
{0003000E-0000-0000-C000-000000000046} = Media Clip
HKEY_CLASSES_ROOT\CLSID\
{0003000E-0000-0000-C000-000000000046} \InprocHandler = mciole.dll
HKEY_CLASSES_ROOT\CLSID\
{0003000E-0000-0000-C000-000000000046}\ProgID = MPlayer
HKEY_CLASSES_ROOT\CLSID\
{0003000E-0000-0000-C000-000000000046} \Ole1Class = MPlayer
HKEY_CLASSES_ROOT\.avi = mplayer
HKEY_CLASSES_ROOT\.mmm = mplayer
HKEY_CLASSES_ROOT\.mid = mplayer
HKEY_CLASSES_ROOT\.rmi = mplayer

Figure 21.2. The registry entries for MPLAYER from the MPlayer registry file .

For the truly advanced or daring administrator, the RegEdit utility includes a menu option, Add | File Type, which enables you to manually add the OLE registration information that should have been in the REG file—or to modify it to your own preferences. It is very similar to Windows 95's Menu, View | Options | File Types.

RegSvr32

You may have seen the RegSvr32.exe utility being distributed in the setup disks for different programs. This is the command line utility to register the OLE server features of an OCX or DLL file.

By typing RegSvr32 and the filename of an OLE Server, you can register that item in the system registry. This registration process will make its features available to all the other OLE-capable programs on your system.


The RegSvr32 Utility


RegSvr32.exe [/u] [/s] [/c] [OLE Server]


The 32-bit server registration utility is used to register and unregister OLE servers (such as OCX and DLL files) in the system registry.

    Example:

RegSvr32.exe /c MyServer.DLL


This will register the OLE server MyServer.DLL and output the results to the console (monitor).


RegSvr32.exe /u /s MyServer.OCX


This will unregister the OLE server MyServer.OCX and will do it in silent mode (no output to the console).


RegClean

The RegClean utility (See figure 21.3) is available from Microsoft's Software Library (ftp://ftp.microsoft.com/SoftLib/MSLFiles). It includes a Registry Cleanup utility that, among other things, will remove entries in your system registry for components or OCX files that are no longer available to your system.

Figure 21.3. Microsoft's Registry Cleaning Wizard.

ActiveX and the System Registry

There are many OLE controls out there that work just fine as they are, ActiveX environment or not. To attain the title ActiveX Control, your OCX or DLL file must support certain features—which the following sections introduce.


Note
This following sections introduce you to the APIs and SDKs involved in creating an ActiveX control . There are a variety of these tools that you may wish to use (such as security and versioning). Each can be quite complex and are included here for the truly daring programmer.
Microsoft makes their Internet APIs and SDKs publicly available on its Web site. Also, most of the documentation files on these tools were installed on your computer by the ActiveX SDK in the \IntDev\ directory.


Self-Registering and Versioning

An ActiveX Control's API must support the standard calls for registering and unregistering a control.

The DLL Register Server Standard API feature (STDAPI DLLRegisterServer()) loads all the .CLASS information (from the DLL or OCX file) into the system registry.

The DLL UnRegister Server Standard API feature (STDAPI DLLUnRegister Server()) removes all the previously loaded .CLASS information from the System Registry.

Ver.DLL

Ver.DLL contains the Windows versioning features. It supports three important functions:

  • GetFileVersionInfoSize Returns the size (in bytes) of the versioning information. This is useful to the programmer for reserving an appropriate buffer into which he should retrieve this data. For instance, if you were working in Visual Basic and retrieved this data into a string value (for whatever reason), you could reserve a three-character string variable instead of a memory-hogging variant.

  • GetFileVersionInfo Whether or not you make use of the size of the versioning information, you can retrieve the data itself with this function.

  • VerQueryValue After you have retrieved the versioning information, you use this function to retrieve VersionInfo that contains, among other things, FileVersion, ProductVersion and two additional blocks of data. These two blocks work together to identify the self-registering properties of the control.

  • VarFileInfo Contains a pointer to the location of the OLESelfRegister key within StringFileInfo.

Remote Procedure Calls (RPCs)

RPCs provide the programmer with a series of functions to access the Win32 registry. At this level, network functions such as SNMP procedures can be used. The client machine would need to have the Microsoft RPC service installed (from the \Admin\NetTools\ directory of the Windows 95 CD-ROM). Use of this feature is not required for ActiveX Controls, but it sure is powerful.

Programmers add utility for users whose machines are running the RPC service. If the user with whom you wish to interact is running the Windows RPC service (included with the Windows 95 CD-ROM in \Admin\NetTools) this allows programmatic access to the OLE procedure calls within Windows API. This is how features such as SNMP can be accessed.

Base Security Layer SDK

Another feature which programmers can make use of is the Base Security Layer of Windows. You were introduced to various parts of this feature in earlier chapters. What should be made clear here is that much of the information that is read from, and written to, ActiveX objects, is stored in the system registry. This goes for all ActiveX security features such as code signing, ratings, trust verification, and user locator services.

ActiveX Control Features

In order for a control to be truly ActiveX/OLE-enabled, it must support the central features of OLE—aggregation, marshaling, and reference counting—and support IUnknown interfaces. Briefly, these can be defined as follows:

  • Aggregation This feature enables one control to incorporate the features of another into itself. Without aggregation, the control code must be recompiled for each instance of the object (in other words, one object—one control). With aggregation, you only need one control to manage any number of instances of an object. This is an overly simplified definition, since there are all kinds of different things that must go on in order to perform this function.

Note
The Java Virtual Machine (VM) uses a Garbage Collector rather than reference counting to determine if it is being used and how many times.
Microsoft's implementation of the Java Virtual Machine combines OLE Reference Counting with the Java Garbage Collector. This relieves the programmer of the burden of coding when a reference to a control should be added or deleted, and of when a control needs to be loaded or unloaded. Also Java allows for exception handling, whereas COM does not. These are perfect examples of how Java makes OLE programming a lot easier!


  • Marshaling Marshaling is the process in which select features from one object are used within another object.

  • Reference counting This feature helps to manage memory use. When a COM object is loaded, it can be used to manipulate any number of instances of that object. By keeping count of how many different ways it is being used, the object can be unloaded when all other instances are cleared from use. (For you C++ programmers, that means you must use the AddRef and Release member functions when instantiating your controls.)

  • IUnknown All COM interfaces are based on this basic interface. It is through these interfaces that OLE applications talk with each other. The three primary interfaces implemented through IUnknown are QueryInterface, AddRef, and Release.

To actually compile your control for use, you need to use an OLE-aware programming environment such as Visual C++, Visual Basic, or Visual Java++.

Visual J++ (Jakarta)

Visual J++ (which Microsoft codenamed "Jakarta") is the first full-blown IDE to make Internet programming fully available to OLE developers. (Refer to Figure 21.4 for a view of the Jakarta IDE.) This programming language is based on the Java language developed by Sun Microsystems and integrates the features of OLE.

In this marriage, COM objects are exposed to Java as Java objects, and a public Java class is exposed to OLE as COM objects. Although you can program COM objects in a variety of languages, you still must use a Java compiler to create Java objects. This, however, may not be true for other Java compilers besides Jakarta, since this one is based on the Microsoft Java VM.

One security feature for running Java applets in ActiveX browsers is that they are hobbled. Hobbling restricts the control from calling code or classes that cannot be verified by the Java byte code verifier. Also, any interface that cannot be defined in a type library (TLB file) will be hobbled.

You can find more information about Visual J++ at Microsoft's Web site, http://www.microsoft.com/visualj.

Figure 21.4. Microsoft's Visual JAVA++ IDE.

Visual Basic

Visual Basic (Figure 21.5) supports various levels of OLE connectivity with COM objects, depending on the version of VB you are using. Even Visual Basic 4 enables you to program against a previously registered object.

A powerful feature of Visual Basic is its capability to make API calls to OLE servers. This feature enables 16-bit VB applications to make calls to 32-bit OLE out-of-process servers, and 32-bit VB applications to make calls to 16-bit OLE out-of-process servers. When using in-process servers, you still must consider bitness.

Figure 21.5. Microsoft's Visual Basic IDE.

You can find out more about Visual Basic at Microsoft's Web site, http://www.microsoft.com/vbasic.


Warning

When making API calls over a distributed network (such as with the Microsoft RPC Service API), performance is slowed considerably as remote connections are established and disconnected.


VB is wonderful for using OLE servers. On the enclosed CD-ROM, you should find a sample VB application, MyServer, for creating an OLE server in VB4. It does not do anything, but if you view the source code with Notepad, you will see that each contains nothing but comments about what should be done in a particular part.

Visual C++

Visual C++ has always (until now, anyway) been the language of choice for OLE programmers. Versions 4 and later enable you to program with foundation classes (predefined OLE classes) or templates (programming language-specific code snippets). Each has its own features for accessing COM.

Microsoft Foundation Classes (MFCs)

C programmers do most of their OLE programming with the classes supported in Microsoft's Foundation Classes Library. You must be sure to include the dependent files with your distribution disks. These include

  • MFC40.DLL May be different depending on your MFC version

  • MSVCRT.DLL Visual C++ RunTime libraries

  • OLEPro32.DLL Required for OLE
ActiveX Template Library (ATL)

The ATL is distributed by Microsoft to enable programmers to use API calls instead of relying on foundation classes. The most current version can be found at http://www.microsoft.com/visualc/v42/atl/default.asp.

This thing is a set of Visual C++ templates that enable quick and easy programmatic access to the ActiveX OLE features. This library is not at all a comprehensive library of functions, but it will enable you to create redistributable functioning COM Class objects.

Dual Interfaces

The ATL enables you to add support for dual interfaces to your C++ program. This makes possible access to features by way of both the IDispatch interface and vtable entries. This enables interaction through third-party features such as scripting.

Tear-Off Interfaces

This library also allows for support of Tear-Off Interfaces. This means that an object can be enumerated (defined) within the system with an IEnum... interface BUT you do not have to worry about the resource demand on your OLE connection. The OLE connection is not actually instantiated (loaded) until it is used. It can be used many times after that, and will stay loaded. When all the objects that were using it report that they are no longer using it (that is, the reference count hits 0), it is unloaded (uninstantiated).

IUnknown—The Center of ActiveX OLE

When you create an OLE interface for an object, there is one standard, IUnknown , with which most of your calls will work. (For a graphical representation of how IUnknown is used as an interface, refer to figure 21.6.) Determining the number of references (current implementations of this interface) and querying the interface (asking about a specific implementation) is determined by the processes that occur through this interface.

The basic model of the IUnknown interface would support the QueryInterface, AddRef, and Release methods:

Interface IUnknown {
Virtual HResult QueryInterface(REFID, VOID FAR *) = 0;
Virtual ULong AddRef()=0;
Virtual ULong Release()=0;
};

An example of C++ code that would implement a DragDrop function by way of the IUnknown interface would look like this:

Interface IDropTarget:IUnknown {
Virtual HResult DragDrop()=0;
Virtual HResult DragEnter()=0;
Virtual HResult DragLeave()=0;
Virtual HResult DragOver()=0;
};


Note
Make sure your program makes AddRef and Release calls as necessary. This will inform the system when it is using an object and when it's not. Then the system can load and unload it as necessary. If you keep opening interfaces and not closing them, you could easily run out of memory and hang your system.


Every interface, IUnknown or not, implements three methods:

  • AddRef When an object is instantiated, it calls the AddRef method to let COM increase the use count.

  • QueryInterface Returns data based on a query from the Interface Identification (IID) specified in a parameter.

  • Release Informs COM that the object is no longer needed and to decrease the use count for that interface. If the count is 0, the interface will be uninstantiated altogether.

Figure 21.6. Graphical representation of how programmers and their programs interact with COM.


OLE Definitions
OLE is a component technology (a theory).
COM is a convention for referring to computer objects.
A class is the definition of how one object behaves. The object it defines does not exist until it is instantiated. Each has a 128-bit Uniform Unique Identifier property (UUID).
An interface is any class based on the IUnknown class. This class will be the contract under which any objects created with it will operate.
The IUnknown class provides the details of a user-defined object, but it can not be loaded itself. It only provides the definitions by which other objects are loaded.
An ActiveX IDE (Integrated Design Environment) is a program that enables interaction with COM objects.
A language is the syntax and vocabulary used in an IDE to reference objects and procedures.
An object is the instantiation of an interface. It is usually contained in an EXE or a DLL file, but can be on a remote machine altogether (using RPC) .


Summary

Taken as a whole, these features are a bit much to swallow in one gulp. However, whether you are a control programmer who uses controls or a control programmer who creates them, it is important to have an exposure to the design considerations in ActiveX Controls.

Your ActiveX Controls will be working closely with your system registry, and you may have to use a utility such as RegEdit or RegClean to fix something. Also, if other programmers' controls are running rampant in your registry, you may find it necessary to remove or edit them manually.

If you do design ActiveX Controls, you have a wide choice of programming languages with which to work. Microsoft makes Visual Basic, Visual C++, and Visual J++ with control creation features.

Also, you will need to include certain interfaces, based on the IUnknown interface. They will need to be self-registering, using the API calls for DLLRegisterServer and DLLUnRegisterServer. The controls will also need to support versioning through API calls to Ver.DLL. Several additional, optional interfaces can be added to the control to enable enhanced features such as RPCs (Remote Procedure Calls) and code signing.

Q&A

  • Q What's the difference between a class, a control, and an object?

  • A A class is a description of how an OLE object works (a contract).
    A control is the code, usually compiled into a DLL or an OCX file, that contains the machine-level instructions (in other words, Mac-, PC-, or UNIX-specific) on how an object interacts with the system (a transaction manager).
    An object is created when a program tells a control to create one, following the rules defined in a class.

  • Q Can I change the system registry by editing the [Embedding] and [Extensions] sections of my Win.INI file?

  • A No. Only older programs that cannot use OLE reference those sections. They expose a default Open process.

  • Q Can I assign two or more programs to one file extension in the [Extensions] section?

  • A No. You can use the FileTypes tab from Explorer to do this, but not the Win.INI file. An example would be that you cannot assign both Notepad and Write to open a text file.

  • Q Can I assign two or more file extensions to one program in the [Extensions] section?

  • A Yes. One program may be capable of opening up a variety of files. An example would be that you can use Word to open DOC files as well as RTF, TXT, and even HTML files.

  • Q How can I back up my system registry alone?

  • A Archive the three registry files—Reg.DAT, User.DAT, and System.DAT— to a safe place. You might also want to include your Autoexec.BAT and your Config.SYS as well as your Win.INI and System.INI while you are at it, since they affect how your system registry will react.

  • Q How does automatic registration work for the user?

  • A When a program, such as the Setup utility, installs its controls, it should make an API call to the DLL and OCX files to tell them to register themselves. This can also be done manually in one of two ways:
    Using the RegSvr32.exe utility, included with Windows, run RegSvr32 [Filename] and the control, if it supports self-registration, should be added to your system registry.
    If the control author did not include self-registration interfaces in the control, it will need to have a REG file with it. This file should have the information necessary to add the OLE Server to the system registry. The filename for this can be used as a command-line parameter for the RegEdit.exe utility (for example, RegEdit [Filename]).
    If the control is not self-registering, and does not have a REG file, other programs will only be able to access it while it is running.

  • Q What, exactly, will RegClean.exe do to my system?

  • A Fix it. You can select options to allow or disallow such features as the following:

    • Validation of unrecognized or obsolete entries

    • Validation of optional keys

    • Check for empty keys

    • Validation of type libraries

    • Validation of cross-references

    • Check OLE servers

    • Check ProgIDs ClassIDs, and Handlers

    • Check OLE conversions

    • Check remote automation

Workshop

Create an OLE server that supports self-registering and versioning using any or all the following IDEs:

  • Visual C++ w/MFC

  • Visual C++ w/ATL

  • Visual Basic

  • Visual J++

Quiz

  1. What section of the Win.INI file identifies OLE objects?

  2. Which file, used by the system registry, identifies the hardware that is installed on a local machine?

  3. Which utility is used to remove invalid and obsolete entries from the system registry?

  4. What two interfaces must a control support to be considered self-registering?

  5. What DLL file supports the API calls used in versioning?

  6. Which programs will create both Java and COM objects?

  7. What dependent files must be installed on a user's machine to use an ActiveX control that is based on MFCs (Microsoft Foundation Classes)?

  8. What COM interfaces are derived from IUnknown?

  9. What three methods must be supported by any interface based on IUnknown?

  10. An object is an _____________ of an interface.



Previous