October 25, 1999 fun

Still_Life_with_Aggregate

Still_Life_with_Aggregate

Still Life with Aggregate

Built using online Lite-Brite.

Jason Whittington
Private DevelopMentor Mailing List

October 6, 1999

Spirit of the IUnknown

(sung to the tune of “Spirit of the Radio” (Rush, “Permanent waves”))
Words (c) Jason Whittington, 1999

Begin the day with a simple call,
A function unobtrusive
Loads the module that’s so elusive
And a matching context means no marshal goo

Off on your way from the factory
Interfaces at your fingers
QueryInterface gets to you a new one
Just Release the pointer when your object’s through

Transactional objects crackle with life
While they Service SOAP calls from some ASP
Giving their feedback on the final outcome
Making a call to Abort or Set Complete

All this machinery so that you can use it
Is still quite closely guarded
CreateInstance will get you a new object from the factory
(yeah the factory)

One likes to believe that it’s easy to use it,
But the threading models and getting pointers marshaled
shatters the illusion of transparency

the CLSID to marshal was requested by the S-C-M…
F-T-M!
Cookies, From the GIT
For Safety! Ohhhh….For Safe-ty!

Jason Whittington
Private DevelopMentor Mailing List

July 30, 1999 fun

Computer synthesized song to liven up your day…

I just like the idea of a computer singing… If you’ve seen 2001, you’ll recognize the tune.

June 27, 1999 book

Windows Telephony Programming: A Developer’s Guide to TAPI

Windows Telephony Programming: A Developer’s Guide to TAPI

The Book

This page is dedicated to my book, Windows Telephony Programming: A Developer’s Guide to TAPI, from Addison-Wesley. If you’d like to order a copy, you can do so from Amazon.com .

The Table of Contents

  • Prologue: The Story of Windows Telephony
  • Windows Telephony Architecture (excerpted here)
  • Assisted Telephony
  • Making a Call
  • Telephony Framework
  • Answering a Call
  • Call Management
  • Telephony Service Providers
  • The Future of Telephony

The Source

This source code has been run and tested on Windows 98, Windows ME, Windows NT 4.0, Windows 2000 and Windows XP and supports TAPI versions 1.4 through 3.1. I have not touched this source code in years and can no longer support it unfortunately.

VS.NET Sample Source | VC6 Sample Source (previous version)

Here’s vc6mfc42.dll (zipped) if you need it.

TAPI Explorer

I built the TAPI Explorer (tExplorer) to allow me to understand the various capabilities of the telephony devices installed on my system when I was developing TAPI applications and writing my TAPI book. It grew into a utility for showing all line, address and phone capabilities as well as other TAPI settings, e.g. country codes, telephony locations, service providers, etc. If you’re running into TAPI errors that you don’t understand, TAPI Explorer will help you work through them.

This source code has been run and tested on Windows 98, Windows ME, Windows NT 4.0, Windows 2000 and Windows XP and supports TAPI versions 1.4 through 3.1. I have not touched this source code in years and can no longer support it unfortunately.

VS.NET tExplorer Source | VC6 tExplorer Source (previous version)

April 19, 1999 fun

Real Programmers…

Real Programmers…

Contributed by Liliya Yakupova:

Real programmers code in binary.
Tommy Riddle had this to say: “Actually, real programmers don’t need the enter key- they just type in 00001101.”
 
4/19/1999
April 16, 1999 fun

Signs that you have hired the wrong COM developer…

Signs that you have hired the wrong COM developer…
  • Keeps referring to interfaces as “Thingies”.
  • Insists that migrating to NT5.0 is a bad idea because the going rate for a rental-threaded apartment is $640.00 a month plus utilities.
  • Comes into work one morning dressed as a cowboy and claiming to be “The new marshaller in town”.
  • Wants to know how to tune his TV to the “RPC Channel”.
  • Stands up in design meetings, grabs his crotch, and proclaims “Yo! Marshall this! Am I right?”.
  • Names one of his interfaces “IKnown” and claims that any object that doesn’t implement it is doomed to eventually fall victim to a “COM Identity Crisis”.
  • Spends 2 hours in front of a whiteboard trying to prove that by taking the integral of the GUID generating function, one can discern the total surface area of the application’s UI in pixels.
  • Pronounces GUID as “gooeey dee”.

P.S.

Here’s a picture of the t-shirt that Microsoft produced for their 1999 Dallas TechEd that leverages Tony’s idea without giving him credit, asking him permission or even notifying him. You lawyers should be able to support you in your retirement with this one, Tony!

BTW, here’s one more sign that you’ve hired the wrong COM programmer (do you think CAT scans will become a normal part of the interview process?):

Anthony Toivonen
Fri 4/16/99 1:07 PM
DCOM Mailing List

April 15, 1999 fun

The Official Guide to COM Culture

If the things on this page haven’t been enough for you, check out Mr. Bunny’s Guide to ActiveX.

April 17, 1998

Handling Name Collision Using Forwarding Shims

One of the problems with MI is that of name collisions. Imagine the following interfaces:

interface ICowboy : IUnknown {
    HRESULT Draw();
};

interface IArtist : IUnknown {
    HRESULT Draw();
};

Because both Draw methods have the same signature, using straight MI requires a single shared implementation:

// Ace Powell was a cowboy/artist who lived in the
// western US from 1912 to his death in 1978. I’d
// like to thank Tim Ewald for this fabulous example,
// which I have used to death for years.

class CAcePowell :
    public CComObjectRootEx<CComSingleThreadModel>,
    public ICowboy,
    public IArtist {

public:

BEGIN_COM_MAP(CAcePowell)
    COM_INTERFACE_ENTRY(ICowboy)
    COM_INTERFACE_ENTRY(IArtist)
    END_COM_MAP()

…

    HRESULT Draw()
    { /* Act as a cowboy or an artist? */ }

};

Since the implied meaning of Draw is very different for an artist than it is for a cowboy, we’d like to be able to provide two Draw implementations. For that, we a technique long known to the C++ community that I’ll call “forwarding shims.”

The problem is that C++ has no syntax to be able to distinguish methods with the same signature from different bases in the derived class. For example, the following is not legal C++:

class CAcePowell :
    public CComObjectRootEx<CComSingleThreadModel>,
    public ICowboy,
    public IArtist {

public:

BEGIN_COM_MAP(CAcePowell)
    COM_INTERFACE_ENTRY(ICowboy)
    COM_INTERFACE_ENTRY(IArtist)
END_COM_MAP()

…

    HRESULT IArtist::Draw(); // error
    HRESULT ICowboy::Draw(); // error

};

However, we can certainly distinguish the methods in individual base classes, e.g.

struct _IArtist : public IArtist {
    STDMETHODIMP Draw() { return ArtistDraw(); }
    STDMETHOD(ArtistDraw)() =0;
};

struct _ICowboy : public ICowboy {
    STDMETHODIMP Draw() { return CowboyDraw(); }
    STDMETHOD(CowboyDraw)() =0;
};

Both _IArtist and _ICowboy are shim classes that implement the method with the conflicting name and forward to another pure virtual member function with a unique name. Since both shims derive from the interface in question, they interfaces IArtist and ICowboy can still appear in the interface map without difficulty:

class CAcePowell :
    public CComObjectRootEx<CComSingleThreadModel>,
    public _ICowboy,
    public _IArtist {

public:

BEGIN_COM_MAP(CAcePowell)
   COM_INTERFACE_ENTRY(ICowboy)
    COM_INTERFACE_ENTRY(IArtist)

END_COM_MAP()

…

    HRESULT ArtistDraw();
    HRESULT CowboyDraw();

};

This trick fills the vtables for IArtist and ICowboy with _IArtist::Draw and _ICowboy::Draw. These functions, in turn, forward to the more derived class’s implementation of the ArtistDraw and CowboyDraw. The forwarding shims remove our name conflict at the cost of an extra vtable per shim class, an extra entry per method per vtable and an extra virtual function invocation per call. If this extra cost bothers you, remove it using the standard ATL tricks:

template <typename Deriving>
struct ATL_NO_VTABLE _IArtist : public IArtist {
  STDMETHODIMP Draw() {
    return
      static_cast<Deriving*>(this)->ArtistDraw();
  }
};

template <typename Deriving>
struct ATL_NO_VTABLE _ICowboy : public ICowboy {
  STDMETHODIMP Draw() {
    return
      static_cast<Deriving*>(this)->CowboyDraw();
  }
};

class ATL_NO_VTABLE CAcePowell :
    public CComObjectRootEx<CComSingleThreadModel>,
    public _ICowboy<CAcePowell>,
    public _IArtist<CAcePowell> {

public:

BEGIN_COM_MAP(CAcePowell)
    COM_INTERFACE_ENTRY(ICowboy)
    COM_INTERFACE_ENTRY(IArtist)
END_COM_MAP()

…

    HRESULT ArtistDraw();
    HRESULT CowboyDraw();

};

Credit

Tim Ewald showed me this trick years ago. Jim Springfield showed me how it could be used with ATL. Don Box recommended the ATL_NO_VTABLE optimization.

Copyright

This web page is adapted from the book ATL Internals by Brent Rector and Chris Sells. Copyright � 1998 by Addison Wesley Longman, Inc. All rights reserved.


← Newer Entries Older Entries →