Tagged as

ATL/AUX Library

A set of VC++ helpers and patterns to help automate some routine coding tasks.

Introduction

ATL/AUX Library is a set of VC++ helpers and patterns I develop through my experience with COM/ATL. The project was started for my own needs almost two years ago. It helps me to automate some routine coding tasks and concentrate on the problem itself. The library is free and evolving, welcome to use it and hope you find it helpful. To be notified about library updates and ATL development tricks, subscribe to the ATL/AUX Billboard. I'd appreciate any technical feedback there; subscription isn't required to post.

What's new

ATL/AUX Library Manual

Under Construction

I still need to have done detailed description for each macro/API/class, but hopefully I covered the most interesting ATL/AUX topics, having revised old stuff and added new ones. Let me know your opinion on it.

I then click at the above line and automatically get to my source code line which caused the error:

_S( m_view->StartModel(img, sound, 0) );

The central part of error diagnostic is _HR(hr) macro. It takes an HRESULT value and traces all available error information as the above sample shows. The formatting is done in a way similar to compiler errors output, which Developer Studio understands and can open the affected source file and position the cursor at the place where the error occurred. Having traced the error information, _HR(hr) simply returns hr, that could be further analyzed. With Release Build, _HR(hr) simply expands as (hr). _HR macro may be used at any expression or statement wherever nice debug diagnostics is appropriate.

The common case in COM programming is the uniform HRESULT function return type. I built _S(hr) macro on top of _HR to check the passed HRESULT value and return it if error is indicated. I prefer this approach as an alternative to C++ exception handling as it produces faster and smaller code. For convenience, there also is _R, _R_OK, _R_FAILreturn macros:

Break into debugger in case of an error. Then you can walk the stack, etc.

_BP( foo->Foo() );

Structuring code this way provides simple linear flow control. What's more important, it possesses more safe and robust code as there is no more assumptions on one or another call to succeed. Automation errors (set with SetErrorInfo) bubble up through the call chain and are available to the caller. If we use Smart Pointers, Auto Pointers, and other C++ objects that live on the stack frame relying on automatic destructor invocation, we may not be bothered to release acquired resources. Check out CAuto class to see how to reclaim acquired resources automatically.

C++ Exception Handling

Here is the new AuxEH.h header, macros to handle C++ exception within COM interface method. C++ exceptions must not be thrown across a COM server method boundaries as the client doesn't expect to handle them. Rather, IErrorInfo might be set with SetErrorInfo and proper HRESULT should be returned.

The idea is to easily handle _com_error, AFX CException and all other possible (...) exceptions with a single statement and have full diagnostic similar to _S and _HR macros. Just put the code that may throw in try { ... } and append the block with either _CATCH_COM(), _CATCH_AFX(), _CATCH_ANY(), any combination of them or _CATCH_ALL(). Rich error information (IErrorInfo) will be preserved and propagated to the outer caller. AFX exceptions are translated into IErrorInfo within _CATCH_AFX() block. _CATCH_ALL() is defined to catch all possible exceptions and expanded as _CATCH_COM() _CATCH_AFX() _CATCH_ANY().

You may use _THROW to throw _com_error upon failed HRESULT. It will look for IErrorInfo set and take an ownership over it. From other hands, _SAFE may be used to catch a possible _com_error thrown by a #import-generated high level wrapper; IErrorInfo will be set (if any) and HRESULT will be returned to the caller of your method. _SAFE(exp) is a shorthand for try { exp; }_CATCH_COM();.

Dr. John F. Holliday proposed yet another useful macro: _ON_ERROR, to handle both HRESULT and exception-thrown errors with a single line, universally. Thanks John! I've modified it a bit by adding AFX support and $hr (the error code). As John noted, _ON_ERROR is a real time saver for finding subtle errors that only appear as exceptions; the downside is the amount of code that it generates. Examples:

One wonderful thing about AuxCreateObject is that it takes an optional pCtx parameter and passes it to the object during the construction. ATL prevents us from using non-default constructors (because there is derived CComObject-family wrapper). The only way to pass an initialization information is to provide our own SetVoid(void* pCtx) method, store passed pCtx pointer, then use it at the FinalConstruct call time. That's what AuxCreateObject takes the second parameter for. Here is an example of the object being initialized this way:

Note, if FinalConstruct() fails, the object is automatically destroyed and the failure code is returned by AuxCreateObject.

The nearest purely ATL solution is to use ATL CComCreator<>::CreateInstance method. This is not the same however; it returns the requested interface, not the object, and does AddRef. CComCreator is used by ATL class factories.

Note by the way, neither FinalConstruct nor SetVoid are virtual. ATL makes almost no use of virtual functions. It uses templates and C++ inheritance rules to get the job done. Look, basic FinalConstruct and SetVoid are defined at CComObjectRootBase from which our object derives. At our object, we override these methods (but they are not virtual!), so CComObject<> derives from ours and inherits our implementation. After all, CComCreator::CreateInstance calls SetVoid and FinalConstruct which happen to be ours.

Note also, by definition, the ATL object that relies on initialization information set with SetVoid cannot support the aggregation.

Of course, we always can split the initialization by two parts and provide separate method, say CHelper::Init(CParent* m_pParent), to carry out the initialization as a separate step.

Last note, all the above ways of construction may be too complex. For simple objects, we may use CUnkImpl<> class that allows non-default C++ constructors (because there is no object derived from ours).

FYI, Don Box discusses some aspects of COM object construction in his great column at Jul'97 MSJ.

The above would lead to linker conflicts, because CRT code for constructors/destructors invocation would be referenced. To overcome this, I've made AuxCrt.cpp, a small replacement of AtlImpl.cpp that provides required CRT functionality at the same cost (i.e., no extra overhead). Its use is simple:

Do not specify DllMain as Entry Point in the project Linker/Output Options tab (or specify _DllMainCRTStartup).

Replace AtlImpl.cppwith AuxCrt.cpp at the StdAfx.cpp file:

// stdafx.cpp : source file that includes just the standard includes
// stdafx.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include<spanclass="code-string">"stdafx.h"</span>
#ifdef _ATL_STATIC_REGISTRY
#include<spanclass="code-keyword"><statreg.h></span>#include<spanclass="code-keyword"><statreg.cpp></span>#endif#include<spanclass="code-keyword"><AuxCrt.cpp> // includes AtlImpl.cpp inside</span>

Dispinterface Event Sink Implementation: ISinkImpl<>

The idea is to handle source dispinterface events with properly laid out C++ virtual functions. I need to maintain some ATL2 projects, and have been working on ISinkImpl for a long time. ATL3 IDispEventImpl was a great help, still my approach is a bit different. I use an intermediate sink class that defines virtual functions to be overridden by a derived class. I believe it's more reusable, as in the long run, I have a collection of some favorite sinks. For example, here is the sink for default event sent of IE4 WebBrowser AX Control:

The best way to illustrate ISinkImpl<> is by example, of course. I've put full working client side sample, the IE4 Automation Controller. It creates an instance of Internet Explorer Application, navigates it to MS site, and logs all events that it fires. The sample is available here: IEClient.zip [64.6 Kb]. The project is located at \IEClientfolder of the ZIP; it should compile with both VC5 and VC6. All other ATL-related stuff is at \Shared folder. There, you might find another reusable class, CLogWindow (AuxLog.h), used to log IE4 events in a separate window.

IIDs/Smart Pointers Generator

I'm quite used to VC5+ __uuidof() extension (does anybody out there use COM/ATL with non-VC compiler? ). But I don't like to mix IID_<Name> and __uuidof(<Name>) styles. ATL is built the way it uses IID_* slyle; I use smart pointers intensively, which poses __uuidof(*). Having both IID_IUnknown and __uuidof(IUnknown) would place both the same GUIDs at the final binary.

Another issue is the naming convenience. I use my own IPtr<>, though you may be using standard CCom[QI]Ptr (atlbase.h) or _com_ptr_t (comdef.h). Whatever, it's boring to type IPtr<IMyLovelyIface> or even worse IPtr<IMyLovelyIface, &IID_IMyLovelyIface> each time. I prefer IMyLovelyIfacePtr instead. VC5 comdef.h (Compiler COM Support) file allows to define your own smart pointer class and provides smart pointer definitions like IUnknownPtr for majority of COM interfaces. More, #import directive can generate IMyLovelyIfacePtr for custom typelib, e.g.:

Look at the typical StdAfx.h file that uses ATL/AUX. This way, all IID_* get redefined as __uuidof(*) before any of them might get referenced by ATL. Note that you can include ax_id.hseveral times, as you add new MIDL-generated SDK headers.

[Note: the following section was originally written for VC5. I'll update it for VC6 soon.] Besides standard interfaces, I use the Generator for my own IDL files. To automate the thing, I use it as part of the build process. To try this, select Settings for your IDL, then add at Custom Build:

System Resource Wrapper Template: CAuto<>

It's convenient to wrap an acquired system resource with a C++ class, much the same way COM interfaces are wrapped with Smart Pointers. Any resource like memory, KERNEL/USER/GDI object etc. may be efficiently wrapped with Auto<> class and not worry further about its reclamation, because C++ takes care to release the resource when the scope of its use is over. This poses more simpler, linear code structuring.

The methods of resource reclamation differs, so we need an easy way to customize the Auto<> class. Let's define 'abstract' templatized helper class for this, CAutoDtor:

Then you may pass the variable of CAuto<> type to wherever the original resource type could be passed. In the long run, it's possible to put a small library of custom wrappers to reuse them.

From the first glance, the use of a class like CAuto<> may seem to be complex and unneeded. This is not so; it's especially handy when being combined with automatic errors/exceptions handling, and allows to cut the source code size and complexity in about a half. Just compare these two sample implementations.

Win32 Callback Thunking (C++ Closures): CAuxThunk<>

We cannot pass a C++ non-static member address to Win32 API requiring the callback address. Obviously, this is because in order to invoke the method on the object, two addresses are required. In some cases, this is solvable. For example, EnumWindows API takes a reference value lParam that it passes later to EnumWindowsProc callback. We may use lParam to pass the object address. Unfortunately, many other APIs (e.g., SetWindowsHookEx/CBTProc) don't support the reference data. Thunks could be used to turn an object+method pair into the closure that could be passed as single address to such an API. It's a very suitable and efficient way to provide proper apartment threading and reentrancy support, and avoids heavy MFC-style techniques relying on Global Variables, Thread Local Storage, Critical Sections and Instance Maps.

How to post message without a window

Here is another important example. In the current COM implementation, all calls are synchronized. That is, a thread making a call into another apartment shall wait until the call returns (the exception is IAdviseSink, its proxy releases the caller). Often, especially in the case of event handling, there is a need to postpone the call processing to let the caller to complete its task. Because we have no control over the client message loop, the only way to achieve this is to create a window and post a message to it. When the next message loop iteration occurs, the message would get dispatched and handled (in apartment-threaded environment only, of course). The window could be quite a significant overhead, especially if we have a very simple object without any visuals. Fortunately, there is a solution: to use the familiar SetTimer API, TimerProc callback and CAuxThunk to get the same effect that PostMessage would produce. It's possible to set up a one-shot timer, with zero interval, then kill it by ID at the TimerProc callback - the exact effect of PostMessage, and no need to create a window (of course, the timer callback would be invoked on the same thread that called SetTimer). Without a thunk, it's not so easy to achieve this effect because TimerProc doesn't take a reference data.

WindowsX.h Message Crackers in ATL Msg Map

The use of Win32 Message Crackers is handy, because they track down message parameters for us. WindowsX.h defines proper cracker almost for each documented Win32 messages. Just look inside WindowsX.h for interesting messages and cut & paste the cracker into your code. Check out: Introduction to STRICT and Message Crackers. You can mix ATL MESSAGE_HANDLER and ATL/AUX MESSAGE_CRACKER entries at the same msg map:

The library main header file, AtlAux.h, consists of two parts: Self-dependent and ATL-dependent. The above sample StdAfx.h includes it twice: before and after ATL itself. Note, there is no name collision (_R) with VC++ STL. The workaround is shown above (I personally prefer the excellent SGI STL implementation: it's free, evolving, more debugged, C++ exception neutral and kept in sync with ANSI standard, with more features available).

The first pass (before ATL) is optional; all self-dependent stuff gets defined here. It may be used to provide smart pointer classes for all COM interfaces declared above in StdAfx.h. More details on this:

At first, ax_id.h header redefines all standard IIDs in the form of IID_<Name> to be __uuidof(<Name>), to eliminate a GUID duplication [otherwise, linker would place two physical chunks, for IID_IUnknown and __uuidof(IUnknown)]. Here is how ax_id.h looks like:

So, the ax_id.his absolutely self-dependent and optional. It may be skipped and at the same time may be included several times, as far as other standard MIDL-generated headers are added.

Then, AtlAux.h is included to define the IPtr Smart Pointer class as well as _COM_SMARTPTR_TYPEDEF macro. We do that to be sure that standard VC's comdef.h file (that may be included by chance later as a result of #import directive generated code) will use our own C++ exception neutral IPtr Smart Pointer class. If this is not what you need, you may include comdef.h instead of AtlAux.h to use _com_ptr_t, or simply skip both the current and the following steps at all.

At last, ax_sp.h is included. It consists of declarations of smart pointer wrappers for each standard interface, and looks like:

The above defines IUnknownPtr and IDispatchPtr smart pointer types. The ax_sp.h file is similar to ax_id.h by the rules it obeys to, i.e., it may be included several or zero times. Note however, if standard comdef.h is referenced in the same project, you must include ax_id.h because of difference between ax_sp.h's and comdef.h's declarations:

Hi Andrew,
I'm newer in programming and very interesting for your library version 1.10.0019, but all links are broken: http://www.geocities.com/~andien/ as http://www.nozillium.com/atlaux/
And can't find it with search engine any more.

You idea to post message without window from a sink direct to the same thread is great.
But i don't now how i integrate you code in my ATL-Exeserver.
You have a function named CSimple::Post(CONTEXT& context) -> where get i the value of context ? i know context only from COM+.

Please can you give me a thin complete sample how can i implement you idea in my Exeserver.

I have forgotten to say, that my Freethreaded Exeserver(A) has another Exeserver(B) as client. (A) has several differnet client-instance from (B). All of this one send (A) Messages over the sink-interface. To prevent (A) was blocked, I send a Message to the Mainthread of (A) with PostThreadMessage() in the Eventmethod of (A), with different Message-ID's for each client (B). Each client of (B) was handele in a separate WorkClass from a singelton factory. So I must find a way without global Parameters to notify the Workclasses without own HWND.