ThunderClap, Vol. 2, No. 2: COM+ Event Spy Program

Thunderclap, the Newsletter of Rolling Thunder Computing

Volume 2, Number 2 Winter 2000

In this issue:
About Thunderclap
Subscription Information
Feature Article: A Spy Program for the COM+ Event System
New Edition of The Essence of COM
Blatant Self Promotion: 
A New Word for the English Language: MINFU

Contest with Prizes: TLA? BFD! CCTs (Clever, Compound, TLAs) are here! 
Results of Last Contest: Computer Oxymorons


About Thunderclap

This is the sixth issue of my (more or less) quarterly newsletters. Each will bring you a technical article on COM or COM+ development, which I hope you will find useful. Each will also bring you a contest, allowing you to show off your intelligence and creativity to win prizes, which I hope you will find funny (although some readers have reported the reverse.) In between you will find my own blatant self promotional material, telling you about the latest ways I've come up with to separate you from your money. (I could have said "carefully selected products and services that we feel might interest you", or other mealy-mouthed horsepuckey. You want the truth or you want me to waste my time and yours dressing it up?)

I'd like to hear what you think about this newsletter and what types of articles you'd like to see in the future. Would you prefer technical programming articles, such as the one in this current issue? Future topics on this track might be, "What the Heck Is the Free-Threaded Marshaler, Anyway?" or "Our Friend, the Causality ID". Or would you prefer higher-level conceptual articles, like "With All the Fuss About COM+, What's In It For Me Today?" Send your e-mail comments to newsletter@rollthunder.com.

This newsletter may be freely redistributed, provided that it is sent in its entirety. If you enjoyed it, can I ask you to please forward it to a friend who might also enjoy it? The subscription roll has grown to over 1500 for this issue.


Subscription Information

Thunderclap is free, and is distributed via e-mail only. We never rent, sell or give away our mailing list. Subscription and unsubscription are handled by a human operator reading e-mail messages. To subscribe or unsubscribe, jump to the Rolling Thunder Web site and fill in the subscription form.


Feature Article: A Spy Program for the COM+ Event System

(This article requires a conceptual familiarity with the event subsystem in COM+)

One of my formative events in my early Windows days, back in the mists of antiquity when Ronald Reagan was president and I had more hair, was playing with the Windows Spy program. I found myself inexorably drawn to its icon, which was the white spy from Mad magazine's "Spy vs. Spy" column. (Most geeks I know grew up reading Mad, how do you think we got so warped? Microsoft used the spy icon until Mad's founder and publisher, the late Bill Gaines, threatened to sue Bill Gates if he didn't knock it off. You'll realize how long ago that was, and how much the world has changed, when you realize that Bill Gates backed down without a fight, instead of buying the entire publishing company for the rights to the Spy icon. Different world then, guys.) The realization that I could use an external tool to look into the workings of the operating system, or apps that I hadn't written, boggled my mind. I loved Spy, still do even now that they've added two plusses to its name, but I don't do much of the user interface programming anymore that it was designed for. 

 Last summer, when I went to teach for three weeks in Asia (Singapore, Malaysia, and Japan), I wanted a really knock-'em-dead demo, so I had to write something cool, something related to COM+. I decided that I would write a spy program that would display the workings on the COM+ event system. It didn't sound that hard to do, and in the end, it wasn't really. But it took me into lots of obscure corners of both COM+ and classic COM, and gave me something to do when the jet lag hit and my internal clock told me to get up at 2:30 AM.

To write my spy program, I needed to do the following things:

1. Look in the COM+ catalog to find all the registered event classes and interfaces. Offer a choice to the user.

2. When the user selects an event class and interface, create a dummy interface on which to receive calls. Enter a transient subscription into the COM+ catalog using this dummy interface.

3. When a publisher fires the event and the call comes in on the dummy interface, figure out which method in the VTBL the call came in on. Look in the event class's type library for the name of that method, then check the stack for the parameters that the type library says ought to be there. Write the name of the method and the parameter values in a window for the user to observe.

4. When the user is finished with the spy program, remove the transient subscription.

Full source code for the spy program, along with a sample event publisher and subscriber, are on my Web site. Click here to download them. You will find a file called "instructions.txt" in the root directory that explains how to install it and run it. You may want to work the program while reading the description of how it works. 

The COM+ event system supports two types of  subscriptions, called persistent and transient. The persistent type is the one most people think of when they think of events. A persistent subscriber puts its CLSID or moniker in a persistent part of the COM+ catalog.  When a publisher creates an event object and fires an event, COM+ looks at all the persistent subscriptions, creates the objects to which they refer, calls the event method on each object, then releases the object. You use persistent subscriptions for subscribers that want to make sure they never miss an event, no matter what they are doing. 

A transient subscription is similar, except it does not use the automatic activation feature of the persistent subscription. A transient subscriber receives only events that are fired while the subscriber program is running. A transient subscriber doesn't put its CLSID into the catalog as does a persistent subscriber. Instead, it places a pointer to its event interface into a non-persistent location in the COM+ catalog. When a publisher fires an event, the event system calls the relevant method on this interface. The spy program uses this type of subscription, because I only want it to display events fired while the user is running it. . 

Both types of subscriptions require manipulation of the COM+ catalog, the hierarchical database inside the operating system in which COM+ administrative information is held. It contains an awful lot of stuff. If you think of the registry on steroids, you'll have the right mental model. To explore it in detail, I'd  suggest examining the sample explorer that comes with the platform SDK. I can't find it on Microsoft's site at the time of this writing, but it's in the platform SDK under \samples\Com\Administration\Explore.VB. Using this application, I determined that the layout of the relevant portion of the COM+ catalog looked like this:

Each double-outlined box below the top is a collection, which supports the ICatalogCollection interface. It contains methods for populating, iterating, selecting, and saving items within it. Each item within a collection, for example, each application in the "Applications" collection, supports the ICatalogObject interface. This contains methods for accessing the individual properties of each item. 

The first thing I had to do was to create the COM+  catalog and get its root collection. The COM+ Catalog manager is simply a system provided object, whose name is  "ComAdmin.ComAdminCatalog.1". To create an object of this class, and gain access to its interfaces, I needed to import its type library, which lives in the system DLL "comadmin.dll". The catalog's GetCollection( ) method provides access to the root collection. Thus:

#import "c:\\winnt\\system32\\com\\comadmin.dll"

COMAdmin::ICOMAdminCatalogPtr g_Catalog ;
COMAdmin::ICatalogCollectionPtr g_CatalogRoot ;

BOOL CRTEventSpyApp::InitInstance()
{

      < other initialization omitted >

/*
Create the COM+ catalog and open the root collection.
*/

      g_Catalog.CreateInstance (L"ComAdmin.ComAdminCatalog.1") ; 
      g_CatalogRoot = g_Catalog->GetCollection (_bstr_t("Root")) ;

      return TRUE;
}

When the user starts the spy program and selects "New Event" from the menu, the program shows the following dialog box, displaying all the event classes and interfaces currently in the COM+ catalog:

 

To fill the box, I needed to read the catalog.  I iterate through all the applications in the "Applications" collection. For each application, I iterate through its "Components" collection. A component has a property called "IsEventClass", which has the value TRUE if the component is an installed event class and FALSE if not.  For components that do, in fact, represent classes, I put there information in the list control for the user to select from. You'll note a couple of counterintuitive things in the sample code below. First, notice that when you get a collection, it's empty. You have to call its Populate( ) method first to read its properties out of the catalog database. Also, note that individual item properties, such as IsEventClass, do not have their own accessor functions on the interface. You have to fetch them explicitly using the GetValue( ) method.  I guess that was easier to write for Microsoft to write. Thus:

BOOL CChooseEventClassDlg::OnInitDialog() 
{

/*
Get collection of applications from root. Populate collection. Iterate through applications.
*/

      COMAdmin::ICatalogCollectionPtr Apps ;

      Apps = g_CatalogRoot->GetCollection (_bstr_t("Applications"),
         _variant_t((long)0) ) ;
      Apps->Populate ( ) ;

      int i ;
      for (i = 0 ; i < Apps->Count  ; i++)
      {

/*
From each application, get collection of components. Populate collection. Iterate through components.
*/

            COMAdmin::ICatalogObjectPtr app ;
            app = Apps->GetItem (i) ;

            COMAdmin::ICatalogCollectionPtr Components ;
            Components = Apps->GetCollection (_bstr_t("Components"), 
               
app->GetKey( )) ;
            Components->Populate ( ) ;

            int j ;
            for (j = 0 ; j < Components->Count ; j++)
            {
                  COMAdmin::ICatalogObjectPtr comp ;
                  comp = Components->GetItem (j) ;
/*
If component represents an event class ...
*/

                  if (comp->GetValue(_bstr_t("IsEventClass")))
                  {
/*
Iterate through its interfaces. Add app name, component name, and interface name to list control.
*/

                       <omitted. Check sample code if you care>  
                  }
               }
           }
      }

      return TRUE;  
}

   
Once the user selects an event class, I need to add a transient subscription to that event.  I need to go to the TransientSubscriptions collection, call its Add( ) method to add a new subscription entry , set the properties of the new subscription, then save the changes. Thus: 

void CRTEventSpyApp::OnEventChooseevent() 
{
      CChooseEventClassDlg dlg ;
      if (dlg.DoModal ( ) == IDOK)
      {

/*
Create an object to subscribe to that interface.
*/

          CEventSpyDisp *pDisp = new CEventSpyDisp (dlg.m_iid, dlg.m_clsid);

/*
Spin off a new window to display calls to the specified interface. Give subscriber object a pointer to its window, and window a pointer to its object.
*/

            <omitted>

/*
Enter a transient subscription into the catalog.
First, get and populate collection of transient subscriptions.
*/

            COMAdmin::ICatalogCollectionPtr TranSubs ;
            TranSubs = g_CatalogRoot->GetCollection (
                _bstr_t("TransientSubscriptions"), _variant_t((long)0) ) ;
            TranSubs->Populate( ) ;

/*
Add a new transient subscription. Its properties are initially empty.
*/

            COMAdmin::ICatalogObjectPtr NewSub ;
            NewSub = TranSubs->Add( ) ;

/*
Set the properties of the new subscription. The most important is SubscriberInterface, the actual interface pointer to which calls will be made.
*/

            GUID SubID ; WCHAR *pOut ;  
            CoCreateGuid (&SubID) ;
            StringFromCLSID(SubID, &pOut) ;

            NewSub->PutValue (_bstr_t("SubscriberInterface"), 
                _variant_t (pDisp)) ; 
            NewSub->PutValue (_bstr_t("ID"), _variant_t (_bstr_t(pOut))) ; 
            NewSub->PutValue (_bstr_t("InterfaceID"), 
                _variant_t ((LPCTSTR)dlg.m_strIID)) ; 
            NewSub->PutValue (_bstr_t("Enabled"), _variant_t (true)) ; 
            NewSub->PutValue (_bstr_t("Name"), 
                _bstr_t ("Rolling Thunder Event Spy")) ;

/*
Save the changes into the COM+ catalog.
*/

            TranSubs->SaveChanges ( );
      }
}

The actual dummy interface that I roll on the fly is in the class CEventSpyDisp.  It does things like read the event class's type library to figure out the names of the methods, and the names and types of its parameters. When a call comes in, it figures out which method the event system has called and which parameters have been passed. The code is too painful to show here, but is in the free download available through the link at the start of this article. Just one thing, please, PLEASE don't judge me by the quality of that code. I was in a real, real hurry when I wrote it. I didn't check any error codes, I just hardwired reasonable sizes to arrays instead of figuring out their length dynamically, all kinds of things. I was after the learning experience and demonstration, not industrial strength. 

  So now, if you install the sample code according to its directions and run the client app, it will look like this:


 

When you run the event spy view and click either button on the sample publisher, you'll see a subscriber pop up message boxes, and you'll also see the calls appear in the spy program, as shown below. Try it with your own events and see how it does, always keeping in mind the limitations of my particular hack job -- ATL dual interfaces only, integer and string parameters only. I'd be grateful if someone with some time (HA!) would actually fix these and extend the program. I'll post it with full credit to you if you do.

 
 

And that's how I wrote an event spy program. It worked out just about the way you'd think it ought to. Figuring out the stack frame was a little tricky; everything else was just tedious. Enjoy playing with it.  

Give me a call if I can help you out. And as Red Green  would say, until next time, "Keep your stick on the ice."


New Book: Understanding COM+

by David S. Platt, President of Rolling Thunder Computing

Published by Microsoft Press

ucompluscvr.jpg (8012 bytes)

It's been a long haul, but I finally finished my book on COM+. It's entitled Understanding COM+, published by Microsoft Press,  ISBN 0-73560-666-8. It's a different approach than my other books, more of a conceptual overview than a wealth of cut-and-paste code. I'm using the same format that David Chappell did in his very successful Understanding ActiveX and OLE, published by Microsoft Press in 1996.

The table of contents of Understanding COM+ is:

1. Introduction to COM+

2. COM+ Architecture

3. Transactions

4. Queued Components

5. Events

6. In-Memory Database

7. Load Balancing


Blatant Self Promotion

New In-House Training Class on COM+

Rolling Thunder Computing is pleased to announce its new in-house training class on COM+. This four day training class will cover all the portions of COM+, including that catalog, security, synchronization and threading, transactions, queued components, events, in-memory database, and load balancing. You can read all about it on Rolling Thunder Computing's web site, http://www.rollthunder.com.

COM+ Events in Boston in January

I'll be speaking at BACOM, the Boston Area COM user's group, on Thursday night Jan 20, on the topic of the "COM+ Event System." The timing hasn't been announced yet, but these meetings usually start with pizza at 6:00 PM, with the main speaker at 6:30. The meeting will be held at the offices of Cisco in Billerica MA. For more details or directions, see http://www.bacom.org/events.htm.

San Diego in February

I'll be teaching a half-day workshop entitled, "What the Heck is COM+, Anyway, and What's In It for Me," from 1:00 to 5:00 PM on Sunday Feb 27. The workshop is part of the e-Business Application Strategies Conference, presented by Giga Information Group, at the Hotel Del Coronado in San Diego. The complete syllabus can be found at http://www.gigaweb.com/marketing/events.stm

COM+ at Harvard beginning in February

I'll be teaching CSCI-E218, Programming COM and COM + at Harvard University Extension in the Spring 2000 term. The class is designed for practicing programmers and is open to the paying public. It meets Thursday nights at 7:35 PM, beginning on February 3 in Lecture Hall E (downstairs) at the Harvard Science Center. The class grants 4 units of graduate credit and costs $1200. The class description and syllabus can be found at http://www.rollthunder.com/harvard.htm. Anyone who thinks they might be interested is encouraged to come to the first class meeting to check it out.

XML in Pasadena in March

I'll be teaching XML in March at E-Z Data, as part of a training class on XMLife, sponsored by ACORD. The timing hasn't been set yet, but see http://www.acord.org for details. Open to ACORD participants only. 


A New Word for the English Language: MINFU

You may remember that in the last issue of this newsletter, I used the new word "MINFU", which had I coined in an earlier column in Byte.Com. In in polite company it stands for MIcrosoft Nomenclature Foul-Up, inspired by military acronyms such as SNAFU and FUBAR which have crossed into general usage. The term "Visual Editing" (to distinguish it from tactile editing, I imagine, or perhaps olfactory editing) is a MINFU. Calling a Visual Java project file a "solution" instead of a project is a MINFU. Renaming COM to OLE (1994), then back to COM (1995), then ActiveX (1996), then back to COM again (1999) was and is one giant MINFU. 

I'm very proud of this creation (I mean, how many people get to make up words?), and want to immortalize it for the ages. That means getting it listed in the Oxford English Dictionary. The full version spans 20 volumes, takes four feet of shelf space, and weighs 150 pounds. You don't want to drop it on your foot, although their CD-ROM version lightens this considerably (look for it on-line, projected for March 2000). Their web site, http://www.oed.com, modestly admits that the OED is:

Because of the magnitude of its task, the OED has always depended on its readers to submit words to be contained therein and quotations illustrating their meaning, especially the first use of a word in publication. Perhaps their most famous correspondent was Dr William C. Minor, inmate of Broadmoor Asylum for the Criminally Insane, whose relationship with the OED was catalogued in The Professor and the Madman : A Tale of Murder, Insanity, and the Making of the Oxford English Dictionary, by Simon Winchester (Harper, 1999). 

I thought that was a cool idea, so I wrote to the OED suggesting MINFU as a word. I've used it in two of my columns in Byte.com, whose print predecessor the OED cites as the source of many household terms such as "personal computer". The Chief Editor of the OED, Mr. John Simpson was very nice and composed to me the following reply:

"Thank you for your message. I'll add the word to our files. But we will be looking for more general currency before we could consider including it in the OED. If you come across written evidence of its use by others, then please forward the information to us. There is no timescale to this, so it might be worth your checking the search engines, for example, every few months."

So now it's up to us, my fellow geeks. I'd really appreciate it if you would use the term wherever it fits in whatever writing you do, and then send me a reference to it. You don't have to credit me for it, though I wouldn't mind if you pointed your readers to this newsletter.  I can't be the first person to stand in awe at Microsoft's ability to get names completely wrong, then change them to something even worse, but I can be the first person to give a name to it. 


New Contest with Prizes: CCTs

Every geek knows what a TLA is, right? It's a Three-Letter Acronym, like DLL or SDK. TLA itself is a TLA. You can hardly form a complete sentence in computerese without one, often two or three, and occasionally more. ("Hey, Charlie, I need the RPC COM SDK from the PDC put on the VAX, PDQ. Oh, yeah? Well, BFD to you, too.")

The problem is that there are only 17,576 unique TLAs in the English alphabet (a few more in places like Iceland, where they add characters like Æ and Þ, but still not all that many), and by my calculations, we've already used up approximately 87% of them. With the accelerating pace of technology spurred by the Internet, we will exhaust the remainder before the end of 2000. This is a crisis of grave proportions.

One of my favorite ways to while away long plane trips is to wonder how we're going to cope when we run out of TLAs (OK, I'm a geek). As Intel came up with the God-awful kludge of segmented memory to solve the problem of exhausting 16-bit memory space (I thought their segmented memory architecture was an April Fool's joke when I first read about it. HA! If only.), so I've come up with a truly horrible solution to TLA exhaustion. I was surfing the Windows Developer's Forum (remember when it all fit in one forum?) on CompuServe (remember when they were a real on-line service?) one evening many years ago. One disgruntled user had posted some nasty message about a thing he called an SDE, which he said stood for SDK Documentation Error. I immediately realized that I was in the presence of a new class of construct, which I have named the CCT, which stands for Clever Compound TLA. It's a TLA in which one or more of the letters stands for another TLA. And of course, CCT itself is a CCT. With 17,576 possibilities in each position, there are 5.4 x 1012 potential first-level CCTs in the universe. That ought to hold us for a while. (Of course, that's what I said about Win32's 4 GB address space 5 years ago, and I now have clients bumping their heads on it.)

It gets even worse. I've identified a special type of CCT that I call the recursive CCT. That's a CCT in which one letter stands for the CCT itself. For example, the GNU operating system, which stands for "GNU's Not Unix". Or in the cartoon where Dilbert asks Wally to come work on the TTP project with him. When Wally asks what TTP means, Dilbert informs him that it stands for "The TTP Project". Every time you dereference it, the recursive CCT regenerates itself. There is also the saturated CCT. It's a CCT in which all three of the letters stand for TLAs. Like OSB, which might stand for OLE SDK BFD. Theory would predict that a saturated, recursive CCT ought to exist somewhere, but I haven't been able to find or create an example of one. 

Your mission is to come up with as many cool CCTs as possible, new or existing. Go wild. You're not even restricted to one level of indirection. That is, a letter of a CCT can stand for another CCT, which can contain yet another CCT, as deep as you can nest them. When I ran this contest many years ago, Carl Rosenblatt's winning entry went down four levels, and he didn't even make it up! It was a real term from one of his projects at the time. (Your tax dollars at work, but that's another story.) 

Your entries must be computer-related and original. This isn't a family newsletter, so they don't have to be clean or politically correct. Submitting more than one increases your chances of winning, although submitters of only one will win if it's the best one. First prize is $100, second prize $50. Winners will be announced in the next issue of Thunderclap, and the judge's decision (mine) is final. In the event of duplicate or similar entries, the earliest wins. All entries become property of Rolling Thunder Computing.  All authors will be identified by first and last names, but not by company. Authors names will be withheld if you so request. Submit your entries via e-mail to contest@rollthunder.com.

Results of Last Contest: Computer Oxymorons

Here are the results of the last contest, in which you were asked to provide computer-related oxymorons:

First Prize, $100 to Igor Firkusny. No one submitted entries bashing Visual Basic, so this is the next best thing:

Mac OS (inspired by a recent and somewhat unfortunate exposure to same...)

Second Prize, $50 to Christopher E. McLendon. Anyone who's tried to get supposedly universal, cross-platform, write once, run everywhere Java code to run on both Netscape version 3 and version 4 on Windows will sympathize with:

Java Standard

And Honorable Mention To All:

Freeware
    -- Michael A. Jones

biztalk.ORG
Microsoft Open Architecture
Microsoft Certified Solution Provider
Al Gore, Father of the Internet
The Bill Gates Foundation
    -- David Hostler

IT Executive
Intelligence Magazine ... it's a computer magazine here in South Africa.
Microsoft ... its a very big company.
Hardware ... try accidentally dropping your PC.
Compact Disks ... get a Microsoft Select agreement and they send everything they ever made in every single language of the world.
    -- Gregory Hunter

DCOM for Dummies
    -- Christopher E. McLendon

MCSD - Microsoft Certified Solution Developer
Systems Programmer
Techie
Information Technology Specialist
    -- Stephane Frechette

Microsoft Intellisense
    -- George Kandalaft

COM for Dummies (book title)
Lightweight Active Directory (Microsoft documentation)
    -- Rolando Jiménez Salgado

Internet Specialist
User Friendly
    -- Bryan Beecham

Project Schedule
    -- Doug Reese


Legal Notices

Thunderclap does not accept advertising; nor do we sell, rent, or give away our subscriber list. We will make every effort to keep the names of subscribers private; however, if served with a court order, we will sing like a whole flock of canaries. If this bothers you, don't subscribe.

Source code and binaries supplied via this newsletter are provided "as-is", with no warranty of functionality, reliability or suitability for any purpose.

This newsletter is Copyright © 1999 by Rolling Thunder Computing, Inc., Ipswich MA. It may be freely redistributed provided that it is redistributed in its entirety, and that absolutely no changes are made in any way, including the removal of these legal notices.

Thunderclap is a registered trademark ® of Rolling Thunder Computing, Inc., Ipswich MA. All other trademarks are owned by their respective companies.