Return to Glenn's tools page

ComWizard

Glenn Story
storyg@acm.org

Download file from here.

Note: Due to a lack of disk space, the documentation on this web site does not contain the screen shot graphics. If you download the above file it will contain documentation including graphics

Contents

Introduction
Walkthrough
Finding COM Data in the Registry
Connecting to the Server
Other Interfaces
AppIDs
Conclusion

Introduction

This document describes how to use ComWizard, a tool for understanding how COM (Component Object Model) and DCOM (Distributed COM) work.

I wrote ComWizard to help me learn about COM. I now use it as a diagnostic tool for DCOM trouble-shooting.

ComWizard Walkthrough

This section gives a walkthrough of a typical use of ComWizard.

To begin, click on the ComWizard icon, or type "comwizard.exe" from the Windows "Run" command. The opening screen looks like this:

Finding COM Data in the Registry

Select the "next" button" to see this screen:

COM locates objects via the system registry. On this ComWizard screen, you must make two choices regarding the registry search that ComWizard will make:

Having selected the local registry and "PROGID" as the registry parameters to use, select the "next" button to see a page like this:

If we had selected some other type of key, such as CLSID, this page would rquest that type of key. If we had selected a remote registry, this page would be preceded by a page to allow us to select the remote system.

If you already know the PROGID you want to use, you can simply type it into the edit box. (Or you can cut and paste it from a piece of source code or other document.)

If you don't know which PROGID to select, select the "browse" button to see a screen like this:

Of course, the actual list of PROGIDs on your system will differ from the above example.

Scroll down through the list and find and select "Excel.sheet". This is the PROGID for a Microsoft Excel spreadsheet. Once you have selected the entry from the list, select the "OK" button. (If you don't find "excel.sheet" it probably means you don't have Microsoft Excel installed; in that case, select another PROGID and click "OK".

This will take you back to the PROGID ID entry page. Now select "Next". This will cause ComWizard to look up the specified PROGID in the registry, and display the information it found, like this:

As you can see, the following information is displayed:

The next step in the COM process is to look up in the registry the CLSID associated with our PROGID. Click "next" to have ComWizard do that. You will then see the first page of registry information associated with the CLSID:

The registry information for the CLSID includes the following:

Note that several of the items on this screen have "look up" buttons after them. This is because those fields can be looked up in the registry. In fact, let's select the "Look up" button for the type library to see the following screen:

Select a version from the "Version" combo box to see additional information.

This screen shows the following information:

When you are done looking at the type library, click "Back" to return to the previous screen.

We are now back at the page displaying information from the registry about the CLSID. Click "Next" to see additional CLSID registry information:

This screen shows the list of servers that can instantiate objects of the class specified by the CLSID. Typically a given class will only be supported by one type of server. Frequently for out-of-proc servers there is an inproc handler that acts as a go-between to the server. In general, "In proc" means that the server is a .DLL that is loaded into the calling program's address space. "Out of proc" means that the server is a .EXE file that runs in its own address space.

Since ComWizard is a 32-bit application, it cannot use 16-bit in-proc handlers or servers, which is why those items don't have a radio button. However, it is permissible for a 32-bit application to use a 16-bit out-of-proc server and vice versa.

Sometimes the registry will specify a remote machine on which to run the server. In cases where it doesn't, but you would like to run the server remotely from ComWizard, (or in cases where you'd like to connect to a different machine than the one in the registry) you can type in the name of a remote server (or use the "browse" button to locate one).

ComWizard will select the "most local" server by default (just as COM would). However, you can override this default by clicking on a radio button to select any type of server that is available. In our case the "most local" server is the in-proc handler.

Notice that the file name of the in-proc handler is not fully qualified. ComWizard has followed the name with the path where the file was found--this information is not part of the registry entry. ComWizard will also report when a file (either fully qualified or not) is not present on the disk.

At this point COM (and ComWizard) have all the information they need to instantiate the COM object. Click "next" to see the screen that summarizes the information that COM has acquired from the registry:

We've seen all of this information before, with the exception of Treading model. This is used by COM to make servers thread safe.

Connecting to the Server

Now click "next" again and we'll be ready to actually connect to the server:

COM goes through the following steps to instantiate our COM object as indicated by the entries on this screen:

  1. Since this is an in-proc handler, COM attaches the corresponding DLL to the process address space by calling LoadLibrary. (In an out-of-proc server, COM would either locate a running process, or start a new process for the server.)
  2. COM calls the well-known entrypoint DllGetClassObject in the newly-loaded DLL to get an interface to a class object. This interface (called IClassFactory) contains the functions to actually create an object of the class we want. The call to DllGetClassObject returns an interface pointer to IClassFactory.
  3. COM now calls the function CreateInstance in the class IClassFactory to actually create the object. This (in our case) returns a pointer to an interface called IUnknown. From this initial interface we can call the function QueryInterface to get additional interfaces.
  4. At this point, because we are using an in-proc handler, we are connected to an object in the handler. To start the "real" server we need to get an interface called IRunnableObject. (For in-proc or out-of-proc servers the query of this interface will fail, which tells us we are already connected to the "real" object.)
  5. To start the "real" server we call the function Run in the IRunnableObject interface.
  6. Finally we call the function IsRunning in the IRunnableObject interface to see if starting the server succeeded.

Most of the functions described on this page return a coded result value called an HRESULT. These HRESULTs are displayed by ComWizard in both a symbolic form and in hexadecimal.

You can either click on the "Connect" button to perform all of the above-mentioned steps at once, or you can click on "Step" to do them one at a time.

You can click on "Release" to release the object once it has been created. The object will also be released automatically if you exit from ComWizard or if you select "Back" from this screen.

If you have not already done so, click "Connect" or repeatedly click "step" to connect to the server.

In my case, I got an error while calling the Run function:

This dialog box give details about the error. When I dismiss this dialog box I can see the complete results in the unerlying window:

Even if the "real" server is not running, the object in the handler is running and we can do some further work with it.

Other Interfaces

In order to do any real work with a COM object we need to do a QueryInterface on the interface we really want to use.

Click "Next" to go to the next screen where we see the results of doing QueryInterface on a number of common interfaces:

To see even more interface, you can click "Next" again. This will cause ComWizard to do an exaustive search of all interfaces in the registry against the object. (Caution: this takes a long time on a remote object or a remote registry.) Here is the result of this search:

If you select one of these interface, you can look up the IID information for that interface stored in the registry. Select an interface, and then click "Next". You'll see something like this:

For out-of-proc servers, the component must supply an in-proc library, called a proxy/stub library, to do "marshalling", i.e. packaging parameters so they can be sent from one process to another. The marshalling code for each interface has its own CLSID as shown on this page.

These marshalling CLSIDs as well as several other parameters on this page have their own registry entries, which you can look up by clicking the corresponding "Look up" button.

AppIDs

We have not been able to demonstrate the ComWizard display for AppIDs because I don't know what keys on your system have associated AppIDs. Let's look at an AppID on my system go give you an idea of what data is displayed:

You can get to this display either by selecting "AppID" when ComWizard is first started, or by clicking the "Lookup" button for "AppID" for its associated CLSID.

The AppID display contains the following information:

Conclusion

This concludes our walk-through of ComWizard. I suggest you now try various features of the program so see how it behaves.