# ftsItem_content

c0Title: I have a need. A need for speed!
c2File: Performance Tests.doc
c1Code:
As Tom Cruse said in Top Gun. "I have a need. A need for speed".
 
SCADA being in the real time domain has a need for speed. This starts with the architecture, design and coding. Attached is a document which may be of use when designing and coding you speedy applications.
 
Martin


c0Title: Locating, Analyzing, and Repairing Memory Problems
c1Code:
March 2000

http://www.devx.com/premier/mgznarch/vcdj/2000/03mar00/cp0300/cp0300.asp
No coding problem is harder to locate, analyze, or repair than problems involving memory allocation and leaks. By studying this example, you'll learn general techniques you can apply to your own applications. 

by Chris Pappas and William Murray 
This article is adapted from Debugging C++: Troubleshooting for Programmers by Chris Pappas and William Murray (ISBN: 0-07-212519-5; $39.95). Copyright 2000, by Osborne/McGraw-Hill. Reproduced by permission. All rights reserved.

     A computer's memory, or lack thereof, has always been a limiting factor in program development. Computers seem to cry out for more and more RAM memory. In early computers, 16K of memory handled most applications. Now, it seems as if 256MB or 512MB is just sufficient. Windows uses complex memory managers to help control and optimize memory use�and this includes disk caching. A serious problem occurs when an application mismanages, over-allocates, or leaks memory. Most MFC applications allow Windows to manage memory allocation for resources, so this is not usually a problem area. However, memory allocation for program components that are not handled by the system and memory leaks are another problem. 
Memory allocation and leaks are often considered the same problem. A memory leak occurs when memory is allocated on the heap and is never deallocated. That means that the memory will never be freed for reuse. This type of problem is difficult to detect because most applications with this type of problem will appear to initially work well. Knowing an application has this type of problem is only the tip of the iceberg. The problem must then be located and analyzed before a solution can be achieved. In the following sections, we'll look at a problem initially brought to us by some senior students working on a MFC project. 

Code with a problem
A group of students were working on a MFC Windows project involving simple projectile motion. The following project, MLeak, retains the essence of the programming problem, without the overhead of the complete project. 

    
Figure 1 The window created by the initial run of the MLeak project. 
Click here.

 
The AppWizard will generate template code for the project. The only file that needs to be modified is the MLeakView.cpp file. 
Listing 1 shows all of the modifications to the AppWizard's code in a bold font. 

Create an executable for the project by selecting the Build | Rebuild All menu item. Run the application to see a window similar to that shown in Figure 1. 

Upon initial inspection, the program looks as if it ran correctly. A logical font was created, and the TextOut() function wrote text in the client area of the window. So where is the problem? Ah, it is a memory leak problem that cannot be detected at this point! Maybe if you just let the application run for a couple of minutes. No, it's not related to how long the program has been running. Grab a border of the application's window and resize the window between 50 and 100 times to discover what our students found. Figure 2 shows the same window after it has been resized a number of times. 

Something has gone wrong with the font. The TextOut() function is still printing to the window correctly, but the logical font is not being created properly. Our students' initial guess was that the problem centered around the font creation process within the OnDraw() method. In the next section, we'll see how they proceeded to locate and analyze the problem. 

    
Figure 2 The MLeak project window after being resized a number of times. Click here.

 
Locating and Analyzing
Our students had to locate and analyze the source of the memory problem in the MLeak project. Fortunately, they knew about several MFC classes and functions that could be used to find memory leaks. Properly placed, these classes and functions can provide a before and an after picture of the condition of memory. By proper analysis, it can then be determined if memory is being properly allocated and released or deallocated. The students added the code shown in Listing 2 to help them detect leakage problems to the MLeakView.cpp file. The added code is shown in a bold font. 

The OnCreate() method was added with the ClassWizard in order that statistics could be obtained on the heap when the application initializes the window. This is easy to do with just a call to oldMemState.Checkpoint(). 

Then, after all of the font work has been completed, the following code is executed in the OnDraw() method: 



#ifdef _DEBUG
    newMemState.Checkpoint();
    if(diffMemState.Difference(oldMemState, newMemState))  {
        TRACE("Difference between first and now!\n\n");
        diffMemState.DumpStatistics();
    }
#endif

The call to newMemState.Checkpoint() snaps a new picture of the heap, and a call to diffMemState.Difference() returns information when a difference between the initial and current values occurs . Statistics are dumped by calling diffMemState.DumpStatistics(). Since this information is contained within the OnDraw() method, and since the OnDraw() method responds to screen resizing via WM_PAINT messages, statistics will be printed each time the screen is resized. This is where we encountered problems initially. 

The next listing is an abbreviated output from this program while running in the Debugger: 



Difference between first and now!
0 bytes in 0 Free Blocks.
-36 bytes in 0 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 9 bytes.
Total allocations: 87 bytes.

Difference between first and now!
0 bytes in 0 Free Blocks.
-36 bytes in 0 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 9 bytes.
Total allocations: 132 bytes.
     .
     .
     .
Difference between first and now!
0 bytes in 0 Free Blocks.
-36 bytes in 0 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 9 bytes.
Total allocations: 14307 bytes.

Difference between first and now!
0 bytes in 0 Free Blocks.
-36 bytes in 0 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 9 bytes.
Total allocations: 14352 bytes.

If you study the listing carefully, you'll notice that only one line really changes from dump to dump. Yes, the total allocations line seems to be increasing with each screen resizing. More specifically, it increases by 45 bytes. It doesn't sound like a very big leak when you consider the overall system memory, but look at the last number in the dump, 14,352 bytes. That number was reported after resizing the screen just a few times! Also, remember the dramatic effect this little leak is having on the application�it kills the logical font. 

The students were sure, because the leak was so small, that it was because they forgot to allocate memory for the logical font structure, so they went back and inserted this bold piece of code into the OnDraw() method: 



    LOGFONT lf;
    CFont NFont;
    CFont* pOFont;

    memset(&lf,0,sizeof(LOGFONT));

    lf.lfHeight = 50;
    lf.lfWeight=FW_NORMAL;
    lf.lfEscapement=0;       
         .      
         .
         .

This is the kind of logic that makes a professor proud of his or her students. The students realized the difference between dumps was 45 bytes and that the logical font structure could be about this size. However, as good of a guess as this was, it wasn't the solution to the problem. The total allocated memory kept incrementing upward! 

Desperate times and deadlines require desperate measures. Were the students really thinking of increasing the size of the virtual memory swapping file with the hope that the old professor wouldn't catch the problem? Probably not, so the next line of reasoning went as follows. Maybe something is happening with the font creation process that is leaking a little memory each time the screen is resized. Solution�remove the font creation process from within OnDraw() and move it to OnCreate(). That way, the logical font resource will be created when the window is created, not each time the OnDraw() method responds to a WM_PAINT message. Now this was a worthy idea, and it is in the tradition of the best form of programming�don't keep allocating and deallocating the same resources. However, this approach didn't turn out to be the whole solution. The total allocated memory kept incrementing upward! 

The students had taken the diagnostic tools about as far as they could when one student suggested getting rid of the logical font altogether and seeing what happened using just the default system font. So the OnDraw() method was modified once again as follows: 



void CMLeakView::OnDraw(CDC* pDC)
{
    CMLeakDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
 
    pDC->TextOut(20, 200, "This program has memory problems");
 
#ifdef _DEBUG
    newMemState.Checkpoint();
    if(diffMemState.Difference(oldMemState, newMemState))  {
        TRACE("Difference between first and now!\n\n");
        diffMemState.DumpStatistics();
    }
#endif 
}

What do you think happened when the program was tested? Here is a portion of the dump statistics for you to examine: 



Difference between first and now!
0 bytes in 0 Free Blocks.
-36 bytes in 0 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 9 bytes.
Total allocations: 87 bytes.

Difference between first and now!
0 bytes in 0 Free Blocks.
-36 bytes in 0 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 9 bytes.
Total allocations: 132 bytes.
     .
     .
     .
Difference between first and now!

0 bytes in 0 Free Blocks.
-36 bytes in 0 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 9 bytes.
Total allocations: 5352 bytes.

Difference between first and now!
0 bytes in 0 Free Blocks.
-36 bytes in 0 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 9 bytes.
Total allocations: 5397 bytes.

Well, nothing changed. There is still a difference of 45 bytes between each dump's total memory allocation. So where is the problem? Of course, we know now�it's the only code left in the OnDraw() method. 



    pDC->TextOut(20, 200, "This program has memory problems");

Comment out this line of code, recompile, and run the diagnostics once again. You'll see that the total memory allocations remain constant from one dump to another. As a matter of fact, replace all of the logical font code, and the memory allocations still remain constant from one dump to another. 

The problem is that the memory being allocated to the string is being reallocated each time the screen is redrawn. The obvious solution is to get that string out of the OnDraw() method just as the students did by moving the creation of the logical font resources. We'll show you how they finally solved the problem a little later in this article. 

Parameters for Memory Diagnostics
In order to use the memory diagnostics facilities, diagnostic tracing must be enabled. These values are enabled within the Debugger. However, to enable or disable memory diagnostics, Microsoft suggests a call the global function AfxEnableMemoryTracking(). This function enables or disables the diagnostic memory allocator. The Debugger automatically turns this feature on, so use this function as a switch to turn the feature off. In so doing, the program's execution speed increases, and there is an overall reduction in the amount of diagnostic information. 

Altering the MFC global variable afxMemDF can make specific memory diagnostic features available. This variable can use any of the values shown in Table 1. 

The values, shown in Table 1, can be combined with a logical OR operation, when needed. 

Locating a Memory Leak
Microsoft has provided an outline that can be followed in the search for memory leaks. We've modified the outline slightly to make it more compatible with the work we are doing on this project. Follow these steps: 

Implement a CMemoryState object. Call the Checkpoint() method, before entering the code in question, to get an initial picture of memory usage. 
Implement another CMemoryState object and call the Checkpoint() method, after completing the code in question, to get a final picture of memory usage. 
Now, if needed, implement another CMemoryState object and call the Difference() member function. When this function is called, use the two previous CMemoryState objects as arguments. The value returned will be nonzero when there is a difference in memory allocation. This is an indication that at least some memory blocks have not been released or deallocated. 
Here is a portion of code that uses three CMemoryState objects: 



// Declaration of CMemoryState variables
#ifdef _DEBUG
    CMemoryState oldMemState, newMemState, diffMemState;
    oldMemState.Checkpoint();
#endif
     .
     .
     .
     (Code to be tested placed here)
     .
     .
     .
#ifdef _DEBUG
    newMemState.Checkpoint();
    if(diffMemState.Difference(oldMemState, newMemState))
    {
        TRACE("Memory Leaked Here:\n\n" );
    }
#endif

Bracket this code with #ifdef _DEBUG and #endif to insure that this code is compiled only in Win32 Debug versions of the project. 

Table 2 lists additional CMemoryState operations, including brief descriptions. The additional operations can be used when the difference between two CMemoryState objects does not disclose enough information. 

Dumping Memory Statistics
The CMemoryState() member function can be used to dump the current statistics or the difference between two memory state objects. Either technique can be used to help locate problems dealing with the deallocation of heap memory. 

The following code uses the information obtained in the previous 24x7 code to determine the current memory statistics: 



TRACE("Current Memory Picture:\n\n" );
NewMemState.DumpStatistics();

The difference between the original and new memory pictures is just as easy to obtain: 



if( diffMemState.Difference(oldMemState,newMemState))
{
    TRACE( "Memory Leaked Here:\n\n");
    diffMemState.DumpStatistics();
}

A sample output from a diffMemState.DumpStatistics() call could take this form: 



0 bytes in 0 Free Blocks
2 bytes in 1 Object Blocks
50 bytes in 5 Non-Object Blocks
Largest number used: 76 bytes
Total allocations: 304 bytes

The first line in this listing indicates the number of blocks whose release or deallocation was delayed. This occurs when the afxMemDF variable was set to delayFreeMemDF (see Table 1). The second line is used to indicate how many objects still remain allocated on the heap. The third line is used to indicate how many nonobject blocks (items allocated with new) were allocated and not released or deallocated on the heap. The fourth line is used to indicate the maximum memory used by the application at any given time. The last line indicates the total amount of memory used by the project. Problems in any of these areas indicate a memory leak. 

Repairing the Project
The students that worked on this project put the Debugger and techniques for detecting memory leaks to good use. While their initial line of reasoning led them down the wrong path, they quickly regrouped, got on the right path, and located and analyzed the problem correctly. 

The key to solving this problem involves getting the string that is to be printed to the screen out of the OnDraw() method that is called each time the screen is resized. While this probably could be done successfully in MLeakView.cpp, the AppWizard created files specifically for this kind of storage and allocation. They are the MLeak\Doc.h and MLeakDoc.cpp project files. 

Here is a portion of the MLeakDoc.h file showing the declaration for the string to be used in this project: 



// MLeakDoc.h : interface of the CMLeakDoc class
//
//////////////////////////////////////////////////////////////

#if !defined \
(AFX_MLEAKDOC_H__7D597DAA_8B14_11D3_A7DE_0080AE000001__INCLUDED_)
#define \
AFX_MLEAKDOC_H__7D597DAA_8B14_11D3_A7DE_0080AE000001__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


class CMLeakDoc : public CDocument
{
protected: // create from serialization only
    CMLeakDoc();
    DECLARE_DYNCREATE(CMLeakDoc)

    CString myCString;
     .
     .
     .

The string itself can be found in a constructor in the MLeakDoc.cpp file, as shown in the next partial listing: 



// MLeakDoc.cpp : implementation of the CMLeakDoc class
//

#include "stdafx.h"
#include "MLeak.h"

#include "MLeakDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//////////////////////////////////////////////////////////////
// CMLeakDoc

IMPLEMENT_DYNCREATE(CMLeakDoc, CDocument)

BEGIN_MESSAGE_MAP(CMLeakDoc, CDocument)
    //{{AFX_MSG_MAP(CMLeakDoc)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////
// CMLeakDoc construction/destruction

CMLeakDoc::CMLeakDoc()
{
    myCString = "This program doesn't have a leak";
}

Finally, the repaired MLeakView.cpp code is listed as it would be used in a release version: 



// MLeakView.cpp : implementation of the CMLeakView class
//

#include "stdafx.h"
#include "MLeak.h"

#include "MLeakDoc.h"
#include "MLeakView.h"


CFont NFont;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//////////////////////////////////////////////////////////////
// CMLeakView

IMPLEMENT_DYNCREATE(CMLeakView, CView)

BEGIN_MESSAGE_MAP(CMLeakView, CView)
    //{{AFX_MSG_MAP(CMLeakView)
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////
// CMLeakView construction/destruction

CMLeakView::CMLeakView()
{
}

CMLeakView::~CMLeakView()
{
}

BOOL CMLeakView::PreCreateWindow(CREATESTRUCT& cs)
{
    return CView::PreCreateWindow(cs);
}

//////////////////////////////////////////////////////////////
// CMLeakView drawing

void CMLeakView::OnDraw(CDC* pDC)
{

    CMLeakDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    CFont* pOFont;

    pOFont = pDC->SelectObject(&NFont); 

    pDC->TextOut(20, 200, pDoc->myCString);
    
    DeleteObject(pOFont);

}

//////////////////////////////////////////////////////////////
// CMLeakView diagnostics

#ifdef _DEBUG
void CMLeakView::AssertValid() const
{
    CView::AssertValid();
}

void CMLeakView::Dump(CDumpContext& dc) const
{
    CView::Dump(dc);
}

CMLeakDoc* CMLeakView::GetDocument() // non-debug ver. inline
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMLeakDoc)));
    return (CMLeakDoc*)m_pDocument;
}
#endif //_DEBUG

int CMLeakView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    // TODO: Add your specialized creation code here

    LOGFONT lf;
    memset(&lf,0,sizeof(LOGFONT));

    lf.lfHeight = 50;
    lf.lfWeight=FW_NORMAL;
    lf.lfEscapement=0;       
    lf.lfOrientation=0;      
    lf.lfItalic=false;
    lf.lfUnderline = false;
    lf.lfStrikeOut = false;
    lf.lfCharSet=ANSI_CHARSET;
    lf.lfPitchAndFamily=34;  //Arial

    NFont.CreateFontIndirect(&lf);
 
    return 0;
}

To build this project, remember to make the previously shown changes to the MLeakDoc.h, MLeakDoc.cpp, and MLeakView.cpp files. 

If you have been down this road a couple of times, you'll soon start recognizing these memory traps in programming code. However, first encounters are difficult to locate and detect. This, of course, is what will make you so valuable to your employer�experience! 


Chris Pappas and William Murray are professors of computer science at the B.C.C campus of the S.U.N.Y system in Binghamton, NY. They have co-authored over four dozen books on such programming topics as assembly language, Visual Basic, C and C++, HTML, Visual J++, Java, JavaScript, Microsoft Foundation Class Library, OS/2, Standard Template Library, Windows 95, Windows 98, Windows NT, and more. Their books have been translated into more than 25 foreign languages. 
   Get the Code 
   Get the code for this issue here. 
  Join the Premier Club

 

C++ Zone Links
� Product Review of the Week 
BugTrapper 3.0

� Site of the Week
Bytamin-C

� Book Review of the Week
The Humane Interface: New Directions for Designing Interactive Systems

� Tip of the Day
Short-Circuiting String Comparison

� Download of the Week
BugTrapper 3.0 
 


c0Title: Make IDispatch Easier to Use
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/2000/09sep00/aa0009/aa0009.asp

ATL gives you several classes to create and use IDispatch-based interfaces. 

by Richard Grimes 


   Whenever you use COM, the odds are you'll use IDispatch. This interface is everywhere, because the components produced by most development languages implement it, and it's the interface that scripting languages call. So any COM C++ library must support IDispatch. In other words, if you want to make things happen in ATL, you've got to know how to use it to implement and access IDispatch. 
What you need:
Visual C++ 6.0 SP3  
 

I'll show you the facilities that ATL 3.0 provides, starting with a description of the class most obvious to an ATL developer: IDispatchImpl<>. As the name suggests, IDispatchImpl<> implements IDispatch for a dual interface, meaning your class has to implement only the custom part of the interface and doesn't have to provide code for IDispatch. ATL is flexible and easy to adapt, as is IDispatchImpl<>, because IDispatchImpl<> is built over a class called CComTypeInfoHolder. This class is a wrapper around an ITypeInfo pointer provided by COM and based on a type library. I'll then describe CComDispatchDriver, which wraps an IDispatch pointer for client access so you don't have to write the automation access code. 

When COM appeared as part of OLE2, back in those lazy, hazy days of 16-bit Windows 3.1, the only way you could create a new interface was to implement IDispatch to support your chosen methods and properties�in other words, you had to create a dispinterface. When Microsoft released the Microsoft Interface Definition Language (MIDL) compiler with support for COM interfaces, it looked like the end of IDispatch because developers could produce custom, vtable-based interfaces without IDispatch overhead. 

But IDispatch has endured. Part of the reason is the sheer bulk of Visual Basic code that was written when VB could access only dispinterfaces. Another part is the popularity of typeless scripting languages, such as VBScript and JavaScript, which know about only this single interface. With dispinterfaces, however, C++ developers have to fiddle with packaging parameters into DISPPARAMS, which makes implementing components more complex. For this reason, developers don't like dispinterfaces. You might think this lack of enthusiasm for dispinterfaces would have ghettoized C++, but it hasn't.    
Figure 1 A Simple Plan Click here.

 

The other reason IDispatch has hung around is another VBism: dual interfaces. As the name suggests, you can use a dual interface in two ways: as a vtable-based interface or dispinterface. An interface you declare in IDL as dual must derive from IDispatch, meaning any methods declared in the interface will appear after the three IUnknown methods and the four IDispatch methods in the vtable (see Figure 1). A client of the component that has the dual interface can query for the dual interface and access the methods through the vtable. If you access the component within the same COM/COM+ context as the client code, the client has direct access to the method. But if the component is in another context, COM ensures that marshaling will occur, so the marshaling layer will always lie between the client and component. 

However, any component implementing a dual interface will also implement IDispatch, so a client can query for this interface. Implementing IDispatch::Invoke() takes a DISPID that identifies the method requested and merely dispatches the call to the method on the dual interface. 

How ATL Implements Idispatch
Although ATL implements IDispatch, it delegates most of the labor to COM. Take a look at IDispatchImpl<> to see how this works (you'll find this in atlcom.h). Although you'll see only a few lines of code here, this is a scene of feverish activity: 

template <class T, const IID* piid, 
	const GUID* plibid =  
		&CComModule::m_libid, 
	WORD wMajor = 1, WORD wMinor = 0,
	class tihclass = 
		CComTypeInfoHolder>
class ATL_NO_VTABLE IDispatchImpl
First, look at the template parameters; the ATL Object Wizard typically generates values for just the first three and uses the default for the others. T is the dual interface you want to implement, and you pass its IID through the second parameter. To provide an interface description, you need the type library, and the ATL Object Wizard passes the LIBID of the first bound type library in the third parameter. The wizard usually ignores the rest of the parameters and relies on the default values. These values are the type library's version and a "type information holder" class, which is actually the heart of the dual interface implementation. I'll come back to this in a moment. 
When you create an object that uses a dual interface, Object Wizard generates code that uses IDispatchImpl<>. I find this code a little odd because it specifies the LIBID, but not the library's version. This is a mistake, because you need four pieces of information to identify a type library: its LIBID, the version, the locale, and the operating system the type library is designed for. The operating system will always be Win32, and the client will pass the locale as a parameter to each of the IDispatch methods; you're left with the LIBID and the library version. These are intimately connected, so if you specify the LIBID, you must also specify the required library version. 

Following the ATL Object Wizard's recommendations leaves you open to a nasty little bug. If you change the type library's major version in the IDL file, which you should do when you update a server to a new version, you must also specify this in IDispatchImpl<>; if you don't, the code won't be able to find the type library and get a description of the interface. Consequently, all methods will fail. This isn't the case if you merely increment the minor version. 

Incidentally, the plibid parameter has a default value�the LIBID of the first type library bound to the server. This type library is usually the one you'll want to use. But using this parameter's default means you'll use the default for its version which, again, leads to the version bug. I recommend you ignore the default values for the LIBID and version�always explicitly specify them. 

Returning to IDispatchImpl<>, it implements IDispatch by delegating all the methods to the "type information holder" class except GetTypeInfoCount(). The type information holder class has a static member, _tih, so your code must explicitly allocate storage. Code in atlcom.h can do this, which explains the declaration after the class. This might look complicated, but most of the declaration deals with the class member's type. 

The implementation of IDispatchImpl<>'s Invoke() is worth looking at. This method calls the same named method on the _tih member with the same parameters, except for the first one. The first parameter is the this pointer cast to IDispatch. The cast provides the vtable for the dual interface. This information is crucial: As you can see from Figure 1, you can obtain a pointer to the first non-IDispatch method of the dual interface from this IDispatch pointer by adding 28 bytes�4 bytes for each of the four functions in IDispatch and the three in IUnknown. 

Hold Type Information
CComTypeInfoHolder does most of the work of implementing IDispatch (you can also find this in atlcom.h). This class provides an implementation of the IDispatch methods through a type library using Invoke(): 

HRESULT Invoke(IDispatch* p, 
		DISPID dispidMember, REFIID,
		LCID lcid, WORD wFlags,
		DISPPARAMS* pdispparams, 
		VARIANT* pvarResult,
		EXCEPINFO* pexcepinfo, 
		UINT* puArgErr)
	{
		HRESULT hRes = EnsureTI(lcid);
		if (m_pInfo != NULL)
			hRes = m_pInfo->Invoke(p,
				dispidMember, wFlags, 
				pdispparams,   
				pvarResult, pexcepinfo, 
				puArgErr);
		return hRes;
	}
First, the code calls the EnsureTI() method, which checks whether the m_pInfo member�the ITypeInfo pointer�has a valid value. If not, the EnsureTI() method calls GetTI(), which loads the type library specified by the m_plibid, m_wMajor, and m_wMinor members, including both the LIBID and version. Remember: These three are intimately connected, and you always use them together. From the type library, GetTI() gets the type information for the dual interface using the IID specified by m_pguid. COM provides this implementation. 
The first three of the four IDispatch methods deal with type info. Once you have a valid ITypeInfo pointer, GetTypeInfoCount() and GetTypeInfo() are trivial. But the remaining two methods of IDispatch are interesting. GetIDsOfNames() maps a text name to a DISPID. This is precisely the information that a type library holds, so ITypeInfo features a method to do this. 

But what about Invoke()? Surely this is object-specific, so how can ITypeInfo implement it? Well, if you take a closer look at ITypeInfo::Invoke(), you'll see that it essentially has the same parameters as IDispatch::Invoke(), except it doesn't have RIID or LCID parameters and it has an additional VOID* parameter. You don't need the RIID because the type info is specific to the interface, and you don't need the LCID because the type information obtained from the type library is written for a specific locale. As mentioned, IDispatchImpl<>::Invoke() passes the IDispatch pointer on the component you use for the VOID* pointer. This means the ITypeInfo implementation can access the dual interface's vtable and the method's function pointer. ITypeInfo::Invoke() can access the interface's implementation, and the type library contains information that allows mapping between DISPID and vtable position, so the type library can access specific methods based on the DISPID passed. 

Scripting languages such as VBScript don't deal with code containing DISPIDs. Instead, they process scripts with text names of methods and properties. Script interpreters rely on an implementation of GetIDsOfNames() to convert the local-specific text name to a DISPID. As mentioned, the type library holds this information, and ITypeInfo has a method to do the conversion. If a script calls the same method several times, however, any scripting language could call GetIDsOfNames() multiple times to fetch the same information. CComTypeInfoHolder keeps a cache of the names to optimize this lookup. The type information holder class creates this cache when it calls GetTI(). This method calls LoadNameCache(), which gets the interface method's name. 

Now, when a client calls GetIDsOfNames(), the implementation first checks the cache to see if the name is there. If so, GetIDsOfNames() returns the DISPID associated with the name. If the name isn't in the cache, the type information holder delegates the request to the ITypeInfo pointer, which looks up the DISPID in the type library. The type information holder creates the name cache on the heap, so some code must eventually delete the name cache when it's no longer used. You could put this cleanup code in the destructor. A small problem�the CComTypeInfoHolder instance is a static member of IDispatchImpl<>. C++ creates such static objects before main() is called and destroys them after main() has exited. 

Don't Use the Destructor
But your ATL COM server doesn't have main(), and usually it doesn't support the C Runtime Library (defining _ATL_MIN_CRT turns off support for the CRT). So you can't use the CComTypeInfoHolder destructor. The ATL framework has solved the wider problem of static and global object construction and destruction. The CComModule class has two methods, Init() and Term(). The server calls Init() through the global _Module object when the code module first loads and Term() when the module is unloaded. 

Init() calls functions registered to be called when the module first loads, and Term() calls functions registered to be called when the module unloads. Every ATL class has an ObjectMain() method that _Module automatically calls in Init() and Term(), but any class can call CComModule::AddTermFunc() to add a termination function. CComTypeInfoHolder does this when GetTI() is first called. CComTypeInfoHolder registers a method called Cleanup() that deletes the name cache. This is essentially a static destructor. 

I find the implementation of CComTypeInfoHolder::GetIDsOfNames() rather odd because the Platform SDK documentation says, "When GetIDsOfNames() is called with more than one name, the first name (rgszNames[0]) corresponds to the member name, and subsequent names correspond to the names of the member's parameters." In other words, the first item in rgszNames is the method name and any other names are the parameters, so the scripting language can support the script using named parameters. 

But the ATL implementation checks the name cache for all the items in the rgszNames array, even though LoadNameCache() merely gets the method names on the interface. As a result, if the client passes the parameter names along with the method's name rather than optimizing the lookup, this implementation actually slows down the lookup. VBScript doesn't allow named parameters, but VBA does, so this could be an issue in VBA code if the component's interfaces are late-bound. 

The other restriction of GetIDsOfNames(), which affects the entire interface implementation, is that the type information holder constructs the name cache when you first use the interface. Then, for the component's lifetime, you use the same name cache. The problem with this is that the name cache is specific to a locale�so if a call comes into GetIDsOfNames() on the same component, but for a different locale, the call fails. In practice this isn't a problem, because you'll rarely use components across locale boundaries. 

Calling Idispatch
As mentioned, dispinterfaces are annoying because you can access the methods and properties only by calling IDispatch::Invoke(). This technique requires packaging the parameters into a DISPPARAMS structure to pass to the method. Old-timer, hardcore OLE2 developers can easily write such code, but we lily-livered, 32-bit COM developers, brought up on custom interfaces, view such code as unreadable and error-prone, and we try to avoid it whenever possible. 

ATL helps here with the CComDispatchDriver class, which you can find in atlcom.h. This is essentially a specialization of CComQIPtr<> that gives a friendlier face to IDispatch (see Table 1). The table mentions neither DISPPARAMS nor the DISPATCH_ flags. Instead, the client code passes method parameters through VARIANTs, and the class does the rest of the work. If you know the DISPID of the dispinterface method you want to call, you can use it; otherwise, you can pass the method's names and the class will obtain the DISPID for you. CComDispatchDriver does this by calling the member method GetIDOfNames(), which in turn calls IDispatch::GetIDsOfNames() with a locale of LOCALE_USER_DEFAULT (the locale of the caller). You must ensure the code always runs in the same locale as the strings you use. If you can't guarantee this, you should use DISPIDs. 

If the method you want to call has zero, one, or two parameters (with or without a return value), you can pass these parameters to Invoke0(), Invoke1(), or Invoke2(). If the method has more than two parameters, you should put them in an array and pass it to InvokeN(): 

CComPtr<IDispatch> pMyDisp;
pMyDisp.CoCreateInstance(
	L"MyServer.MyAutomationObj");
CComDispatchDriver disp(pMyPtr);

// looks like this in VBScript:
// id = obj.GetEmployeeID("Richard",
//	 "Grimes", 35)
CComVariant varArr[3] 
	= {L"Richard", L"Grimes", 35};
CComVariant varRet;
disp.InvokeN(DISPID_VALUE, varArr,
	sizeof(varArr), &varRet);
ATLTRACE("ID = %ld\n", varRet.lVal);
This class enables clients to access IDispatch more easily. The ATL control classes use it extensively, particularly when implementing property maps. 

Whatever you do in your COM code, you can't get away from IDispatch. You need to implement every dual interface and you can use a wealth of automation objects to do it. ATL provides classes to implement and access IDispatch, so it's easier to use. 

The download for this month's column contains a simple project that illustrates how to use IDispatchImpl<> and CComDispatchDriver. The object allows access to the environment variables by name and to the process's command line through properties and methods. This code has three clients: a VB6 client that creates the object and late-binds to it, a C++ client that accesses the object solely through IDispatch using CComDispatchDriver, and a VBScript client. 

Richard Grimes is the author of Professional ATL COM Programming and Beginning ATL COM Programming; both cover ATL 3.0 (Wrox Press). Richard's latest book, Visual C++ MTS Programming, was published by Wrox Press last fall. E-mail him at atl.dev@grimes.demon.co.uk. 
     
   Get the code for this issue here. 
   Get the code for this article here. 
  Join the Premier Club

 

  
  FEATURED SOFTWARE:
 
Create Killer Apps Without Writing Code
APEX Olectra Resizer 2.0
Download Now: $139
 

Slash Your Development Time�Download Now!
ReCrystallize.com Pro 3.0
Buy Now�DevX Price: $132
 

FEATURED BOOK:
Manage COM Objects
Professional Visual C++ 6 MTS Programming
DevX Price: $29.99�Save 40%
 

   
� Professional ATL COM Programming by Richard Grimes (Wrox Press, 1998, ISBN: 1861001401)
� ATL Internals by Brent Rector and Chris Sells (Addison Wesley, 1999, ISBN: 0201695898)  

 � Product Review of the Week 
BugTrapper 3.0

� Site of the Week
Bytamin-C

� Book Review of the Week
The Humane Interface: New Directions for Designing Interactive Systems

� Tip of the Day
Short-Circuiting String Comparison

� Download of the Week
BugTrapper 3.0

 
 



c0Title: Make the Most of the IDE
c1Code:
August 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/08aug00/fu0008/fu0008.asp
The Visual C++ IDE provides many tools to help you develop better code faster. 

by Bill Wagner 

 
   L ast month, I gave you the framework for starting applications using the Visual C++ AppWizard. This month, I'll show you Visual C++'s wide array of tools you can use that help you program more effectively. Some of them are personal preferences that let you work the way you want; others are productivity tools that save you quite a bit of work while adding features to a project. Still others make it simpler for you to work in a group setting. 
What you need:
Visual C++ 6.0  
 
I'll introduce you to VC++ wizards and tools that add features to your application, and help you navigate the source code in a large project. Many of these productivity features are built around the Microsoft Foundation Classes (MFC) and the Active Template Library (ATL). Learning the wizards will help you use these libraries while you become familiar with their contents. 

The initial project you create with AppWizard contains a minimum number of user interface features. Your users will expect more from a commercial application. In this month's column, you'll use VC++'s Component Gallery to add functionality to the sample application from last month.    
Figure 1 Add a Function to Your Class Click here.

 

Access the Component Gallery from the Add To Project item on the Project menu. From there, select the Components and Controls menu item to display a list of available components. Choose the Visual C++ Components item from the listbox, which presents you with various controls. All the Visual C++ components work in a similar fashion. When you select one of the controls, Visual C++ shows you a wizard dialog with a set of options. The status bar component, for example, provides an enhanced status bar that can display the system date and time. You normally wouldn't set this option because the date and time are visible from the Windows taskbar, but add it for this example. 

Add the Stretch Menu Prompt Pane option in the last page of the Status Bar Component wizard. This adds the code that stretches the status bar's first pane to display menu prompts fully. In this application, add the date prompt to the status bar as a template for a different feature. You can get the functionality in much less time by modifying a standard component. 

In your small editor, display the number of characters in the window. First, add a function to the view class that retrieves the number of words in the window. Right-click on the CSampleView class in the ClassView pane and select Add Member Function from the context menu to bring up the dialog (see Figure 1). After you enter the information for the new function, VC++ adds the declaration in the H file, and the blank definition in the CPP file. 

Next, double-click on the function name in the ClassView pane to add the function's definition. The body of the function is simple; CEditView has a function that returns the number of characters in the buffer. You now have a new version of the OnUpdateDate() function. Rename it to OnUpdateCharacters() for clarity, and you're done (see Listing A). In a production environment, you'd change the names of the functions and member variables to reflect their current uses. In this case, you have the opportunity to see what the component wizard created. 

The status bar is just one of more than 20 components you can add to your application. Working with any of the VC++ components will follow the same pattern. After you select the component, select the options you want from dialogs. Then the component adds the necessary code to your application. 

Search the Comments
All the code a component adds to a project is tagged with a comment, which always takes the same form. All comments begin with CG, for Component Gallery, and include the name of the component that generated the code. If you use the Find in Files command to search your project, you can find all the code blocks the same component inserted. For example, you can search for all the code the status bar component added with the comment CG.*'status bar'. Use the Regular Expression checkbox; otherwise, the search looks for the asterisk (*) character, instead of using it as a regular expression. Finally, you might prefer to leave all the components' comments in the application to ease finding the component code later when a project gets larger.  
Figure 2 Integrate Dialogs With Code Click here.

   

VC++ also contains tools that help tie together the various user interface (UI) elements (such as toolbars) and the code that implements the commands. Adding a find-text function to the editor demonstrates all these features. Create a search toolbar button for the user to click to execute the Find command, and create a dialog to let the user enter the text he or she is searching for. Finally, write the code that ties together these elements. 

Click on the ResourceView tab in the workspace window. Expand the resources folder if necessary, then expand the Toolbar folder. The application contains only one toolbar. Double-click to open the toolbar editor, which lets you edit the toolbar itself as well as each image it contains. Note that each image has its own properties. To add a new command to the toolbar, edit the blank image on its far-right edge. Once you do so, a new blank image will appear at the end of the toolbar. If you want to move the new image anywhere in the toolbar, drag the image to its new location. Also, to create a separator between two buttons in the toolbar, simply drag a button a bit to the right or left so you create a space between it and the two adjacent buttons. 

Similar to any resource type in the resource editor, press Alt-Enter to bring up the properties for the new toolbar button. Enter a new resource ID for the command, using this convention: Preface the command name with ID_ and use all capital letters. 

Then, add a prompt to the command. The first part is the prompt your application displays in the status bar when the user selects this new command. The part after the \n is the text displayed in the tool tip when the user selects the command. When you add a menu item using the resource editor, you include the same kind of prompt information. In fact, if there is already a menu item with the same resource ID as the toolbar button you're creating, or vice versa, the resource editor fills in the prompt after you set the resource ID. I've chosen ID_FIND for the find command ID. The prompt string is "Find\nSearch for text in the current document." 

Next, create a simple dialog to let the user enter the text to find. Right-click on the Dialog folder in the ResourceView tab and select Insert Dialog. Note that the dialog editor, which is easy to use, is also part of the resource editor. Just drag a control onto the dialog, and press Alt-Enter to change its properties. Select the entire dialog to change the dialog's title and ID. The My Find Text dialog has an edit box for the user to type the text, and the standard OK and Cancel buttons. The dialog editor also contains a variety of commands on the Layout menu to help you arrange the dialog controls exactly as you want. 

Create Code With ClassWizard
VC++ also offers tools that generate the code to work with the dialogs you create. Open the Search dialog in the resource editor and select the ClassWizard command on the View menu. Remember in last month's column, I said that ClassWizard files are not checked into the archive. This means the ClassWizard information can get out of sync if another developer creates a new class. To fix that, delete the CLW file from your disk and reopen ClassWizard, which asks you to rebuild the ClassWizard information database from your source files�you'll experience this if you download the files. Doing this brings ClassWizard up-to-date again. Note that the ClassWizard file is not included with the sample project. 

ClassWizard determines you're viewing a resource that doesn't yet have code associated with it by showing a dialog asking if you want to create a new class or use an existing one. You'll almost always want to create a new class. ClassWizard needs to know the name of the class and the base class; you can pick almost any MFC class for your base class. For dialogs, the base class will almost always be CDialog. But if you've derived a specialized dialog class from CDialog, you can choose it as your base class. After you click on OK, ClassWizard makes two new files: the include file containing the class definition, and the source file containing the definition of all the new class's member functions. ClassWizard automatically adds these files to the current project. 

After you add the new class, you'll see the ClassWizard main screen. You'll spend most of your time in the first two tabs of ClassWizard: Message Maps and Member Variables. Use the Message Maps tab to add functions that handle window messages, or override base class functionality; you won't use it as much with dialogs. Use the Member Variables tab to add variables that work with controls in dialogs (see Figure 2). You want to work with C++ classes that represent the values the user gives in the dialogs. Windows stores these values inside the dialog controls and provides APIs to access them. ClassWizard provides the means of coupling C++ class variables with dialog controls to make them easier to work with.    
Figure 3 Have Wizard Bar, Will Travel Click here.

 

Press the Member Variables tab's Add Variable button to add a variable to transfer text to and from the textbox that contains the search string. Then name the variable and select whether it's a control or a value. Use values to transfer the user's selection from the dialog controls, and controls to create MFC variables that let your program manipulate the other dialog controls. With values, the type column in the Member Variables tab lets you select the type of data to transfer. Windows Edit controls have the greatest possible types of variables that can handle transfer. Users can type strings, integers, and floating-point numbers. Your search text in this example is obviously a string. 

That's all you need to do to make the dialog work. You build more complicated dialogs the same way. MFC provides all the code to transfer data between dialogs and your class. ClassWizard helps you create the class that supports the transfer. You'll revisit the Message Maps tab in next month's column, which will discuss MFC in more detail. 

You must perform one last step to add the find capability to this application: Tie together all the UI elements created so far. Do this by adding a message handler to the CSampleView class: Right-click on the class name in ClassView and select Add Windows Message Handler. If the CLW file is missing, the Add Windows Message Handler item will not appear in the menu. If that happens, rebuild the CLW file. Select the ID_FIND command in the Class or Object to Handle list. The list of messages and events contains two items: UPDATE_COMMAND_UI and COMMAND. Select COMMAND. Then, click the Add and Edit button�this adds code to the CSampleView class to handle the message when the user selects the Find command. Next month, you'll see how MFC handles this routing. For now, just understand that the CSampleView class has code that handles the user interaction for the Find command (see Listing B). You could have performed this same function using ClassWizard. Both methods give the same result. 

Visual C++ features quite a few development group-productivity tools, which are a bit tougher to demonstrate in a small application. However, one is the Wizard bar, which makes it easy to find a particular class, a specific member function, or a variable inside a class (see Figure 3). The Wizard bar contains three combo boxes. The left-most combo box shows you the class; the middle combo box lets you display window message handlers, or all class members; the right-most combo box displays the current member function dynamically. You can also select a different class, filter, and member function to go to a specific source statement in the editor. 

IntelliSense editing, another feature that works well, gives you tool tips for both the names of member functions and their parameters. If you put comments above your function declarations or to the right of member variable declarations, the IntelliSense feature includes those comments when you hover the mouse over function names in the editor. This can be a great help in a large project when you're trying to find the right function. If you put a single-line comment above the name of each of your functions, other developers will get a quick tip about the function's usage when they're working with your class. For other VC++ features geared toward larger projects, see the sidebar, "Work With Large Projects". 

I have one final side note on building the sample project. I made the project with the default options to build the help file as part of the project. That option often causes problems because the help compiler doesn't examine the include path when it looks for files. So, projects that have the help file built as part of the project are not portable from machine to machine. With this in mind, I've turned off the help build step in the downloadable code. 

I've shown you just a small portion of the VC++ IDE. You can also write macros to automate common tasks, and use advanced editing features to replace spaces with tabs and format a section of code to match a style guide. There are features that find the opening or closing brace to a block of code. You can access many of these under the Advanced command on the Edit menu; others are listed in the Text Editor Reference on the MSDN CD. Look for the How Do I? portion of the text editor section of the Visual Studio documentation. 

I don't always use the wizards to edit code�often, I find it easier to work directly with the code. The Visual C++ IDE works quite well in both modes. I personally find that working with the navigation wizards helps the most in larger projects, where you end up spending more time searching for a particular piece of source code than modifying and fixing it. 

It's difficult to separate the IDE tools from the libraries they're designed to support, so next month I'll explain how this code functions internally, and how to work with MFC. 


Bill Wagner is the president/software architect for Midwest Seas Software Development Inc. Bill has several years of experience in Windows and C++ programming. He specializes in C++, Java, and COM-based enterprise-programming solutions. He has taught several classes for developers using C++, Visual C++ tools, and MFC. Reach him by e-mail at wwagner@midwestseas.com
 


c0Title: Manage vptr Overload With Tear-Off Interfaces
c1Code:
June 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/06jun00/ac0600/ac0600.asp

If your object is cluttered with too many interfaces, tear-offs can help clean up. 

by George Shepherd 


   Programmers write most COM objects using multiple-interface inheritance, a C++ technique. It adds one vptr to your class per interface. As long as your object's clients use all the interfaces on your object, this is a reasonable payment. However, there are times your object will have to make a set of interfaces available, even if clients don't use them frequently. In this case, the overhead the vptrs impose might be too much. In this article, I'll look at a way to reduce vptr overhead�using tear-off interfaces. 
What you need:
Visual C++ 6.0
Windows 2000  
 
COM differs from ordinary C++-style development in that it clearly separates an object's interface from its implementation. When creating a normal C++ object at run time using operator new, you get a pointer to the object's data and a set of functions scoped to that data. In short, the object's identity is the pointer to that data (the object's this pointer). When you create a new COM object, you get a pointer to an interface, rather than a pointer to the object's data. Because of this, COM allows you to manage an object's set of interfaces dynamically. Rather than implementing an object's interfaces within a single C++ class, you implement tear-offs using separate objects allocated on demand. 

To fully understand COM tear-off interfaces, you'll need to understand object identity first. For example, consider a normal C++ class. When you want an instance of a C++ class, you simply call on operator new to produce one for you. If operator new succeeds, you get back a pointer to the top of the object, after which the compiler lets you access any of the public-data members and functions. Notice in this example that operator new gives you a pointer to the entire object: 



class CSomeClass {
public:
   short x;
   void DoIt();
   void DoItAgain();
};

CSomeClass* pSomeClass = new CSomeClass;
pSomeClass->x = 42;
pSomeClass->DoIt();
pSomeClass->DoItAgain();

Here, pSomeClass represents the object's identity, meaning pSomeClass represents the whole object and nothing but the object. Recall that a COM object is just a piece of code (in other words, a component), so the internal workings are hidden from the client. The COM object distinguishes itself from random memory by implementing a COM interface (a vptr function table) named IUnknown. IUnknown includes three functions you can express in C++, like this: 



struct IUnknown {
   virtual HRESULT QueryInterface(REFIID riid, 
               void** ppv) = 0;
   virtual ULONG AddRef() = 0;
   virtual ULONG Release() = 0;
};

The key to grasping how IUnknown works is understanding that a COM object simply needs to implement these three functions, and that all the COM interfaces you'll ever encounter begin with these three functions. This means that IUnknown establishes a COM object's identity. Unlike normal C++, you never talk to an actual object in COM�you talk to one of the object's interfaces. For example, the equivalent COM-based example might look like this: 



struct ISomeInterface  : IUnknown {
   virtual void DoIt() = 0;
};

ISomeInterface* pSomeInterface;
CoCreateInstance(CLSID_CoSomeClass,
         NULL,
         CLSCTX_ALL,
         ISomeInterface,
         (void**)&pSomeInterface);
if(pSomeInterface) {
   pSomeInterface->DoIt();
   pSomeInterface->Release();
}

When the client code talks to pSomeInterface, the client isn't touching the actual instance of CoSomeClass�it's touching an interface attached to the CoSomeClass object. Imagine that CoSomeClass implements another interface named (appropriately) IAnotherInterface. Once the client obtains an interface, any interface, to the object, the client can try to widen its connection to the object arbitrarily, like this: 



struct IAnotherInterface : IUnknown {
   void DoItAgain();
}

void UseSomeInterface(ISomeInterface *pSomeInterface) {
   IAnotherInterface* pAnotherInterface = 0;
   pSomeInterface->QueryInterface(IID_IAnotherInterface, 
               (void**)&pAnotherInterface);
   if(pAnotherInterface) {
      pAnotherInterface->DoItAgain();
      pAnotherInterface->Release();
   }
}

The client can try to do this because QueryInterface(), a member of the IUnknown interface, is the first function of every COM interface you'll ever see. At this point, you're staring COM and object identity right in the face. Recall the lollipop diagrams that appear so often throughout COM literature. Each lollipop represents an interface, and the rounded rectangle represents the code implementing the interface (see Figure 1). 

   
Figure 1. In this classic diagram, lollipops represent... Click here.

 
COM's IUnknown interface allows objects to have multiple personalities. CoSomeObject understands how to implement both ISomeInterface and IAnotherInterface. A client can hold a pointer to ISomeInterface and a pointer to IAnotherInterface, and each pointer might be pointing to the same object. By permitting the mechanism to widen the connection to an object arbitrarily at run time, COM effectively extends objects arbitrarily, without breaking old clients. Older clients who understand the existing interfaces remain content, because the interfaces still exist. Clients who want to use the newer interfaces simply have to ask for the new interface. 

In COM, IUnknown represents a pointer to an object. That is, IUnknown denotes an object's identity. COM establishes some basic rules about COM identity. At first these rules seem unimportant, even pointless. However, by understanding these rules, you can leverage them and compose COM classes in many ways. 

Remembering COM's Identity Rules
A mnemonic device to help you remember COM's identity rules is the letters STR, which stand for symmetric, transitive, and reflexive. First, COM interfaces are symmetric. For example, if you're using the ISomeInterface pointer on CoSomeObject and call QueryInterface() to retrieve IAnotherInterface successfully, then you should be able to call QueryInterface() through IAnotherInterface to retrieve the ISomeInterface again successfully. 

Second, COM interfaces are transitive. Imagine you're using ISomeInterface on the CoSomeObject and call QueryInterface() to retrieve IAnotherInterface with success. Next, imagine you use IAnotherInterface to retrieve the IUnknown pointer. If that succeeds, then you should be able to call QueryInterface() through the ISomeInterface interface to retrieve the IUnknown interface (see Figure 2). Finally, COM interfaces are reflexive. If you're using the ISomeInterface pointer on CoSomeObject, you should be able to call QueryInterface() to retrieve ISomeInterface again. 

   
Figure 2. COM interfaces are symmetric, transitive... Click here.

 
The upshot of these rules is that the interfaces on a COM object are peers�you can get from one interface implemented by an object to any other interface implemented by an object. The symmetry, transitivity, and reflexivity rules mean COM client code need not worry about the order in which they acquire interfaces. If a COM object required interfaces to be acquired in a certain order, COM code that either didn't adhere to that order or changed the order of acquisition between versions would break. 

In addition to the rules of symmetry, transitivity, and reflexivity, COM imposes two other stipulations on interfaces. First, COM requires that a query for IUnknown always return the same actual pointer value, thereby allowing clients to compare two IUnknown pointers to determine whether they both point to the same object. However, it's okay for QueryInterface() to return different pointers whenever it's called to acquire other interface pointers. As you'll soon see, this lets you implement objects in several ways, including using tear-offs and aggregation, among other techniques. This requirement also supports the earlier statement about IUnknown establishing a COM object's identity. 

Second, COM requires that the set of interfaces accessible on an object through QueryInterface() remain static during the object instance's lifetime. That is, if you call QueryInterface() to retrieve ISomeInterface once during the object's lifetime, then you should be able to retrieve the ISomeInterface interface again, at any time during the object's lifetime. If a query for ISomeInterface through QueryInterface() fails once, the same query must fail for the object's lifetime, meaning it's illegal to implement QueryInterface() such that it succeeds only under certain conditions. 

The main reason to make the set of interfaces available to an object static during the object's lifetime is that COM doesn't guarantee all client QueryInterface() requests will be forwarded to the object when it's accessed remotely. Client-side proxies can take advantage of this and cache the results of QueryInterface(). By doing so, excessive client-object communications are avoided, which, in turn, reduces the number of round-trips and increases the object's network performance. 

To easily make sense of these STR rules, remember that all interfaces supported during an object's lifetime end up as peers. The interfaces form more of a landscape than a hierarchy. Knowing these identity rules is critical to understanding tear-off interfaces. 

Understanding Tear-Off Interfaces
The most common way to implement COM classes is to inherit a C++ class from some interfaces, then implement the union of the functions included in the interfaces. Classes implemented through multiple-interface inheritance follow the identity rules automatically. However, multiple inheritance isn't the only way to implement COM classes. You can also compose COM classes by implementing an interface using a tear-off interface. 

Imagine that your COM object has to conform to a higher-level protocol. Perhaps this protocol formally requires 15 interfaces, but you can get away with implementing only five because the other interfaces manage functionality you and your client aren't interested in. 

If you implement a COM class using multiple inheritance, the class is always going to lug around all 15 interfaces' extra vptr overhead. Tear-off interfaces help you write COM classes that create the resources necessary for implementing an interface on demand. In the CoSomeObject example I mentioned earlier, imagine that only the ISomeInterface interface needs to be fully implemented all the time, and that IAnotherInterface is optional. An independent C++ class implements IAnotherInterface. Calling QueryInterface() to retrieve the IAnotherInterface interface causes the CoSomeObject class to instantiate a new instance of the class implementing IAnotherInterface. 

Because the new tear-off class needs to implement IUnknown and preserve the object identity for the client, the new tear-off class gets a back pointer to the class with object identity (CoSomeObject, in this case). The new tear-off class can forward QueryInterface() calls back to CoSomeObject, and the client is happy because the COM object follows the rules of identity (see Figure 3). 

   
Figure 3. Here's COSomeObject implemented... Click here.

 
Tear-off interfaces are useful whenever you have many optional interfaces, and they're also useful for transient interfaces. However, using tear-off interfaces uses a lot of memory. The COM-related size overhead of CoSomeObject implemented using normal multiple inheritance of interfaces is 12 bytes: 4 bytes for each interface vptr (ISomeInterface and IAnotherInterface), and 4 more bytes for a reference counter. A multiple-inheritance COM class's size goes up by 4 bytes for every interface it implements. In comparison, the COM-related size of CoSomeObject using tear-off interfaces is 20 bytes when implemented using raw C++ and having all interfaces in use. This includes 4 bytes for the ISomeInterface vptr, 4 bytes for CoSomeObject's reference count, and 12 bytes for the tear-off class. 

Each tear-off class needs a back pointer to the managing object, 4 bytes for the vptr, and 4 more bytes for the reference counter. Each additional tear-off class takes up 12 bytes. The size of a COM class with tear-off interfaces goes up by 12 bytes for every interface it implements as a tear-off. As a result, the overhead of tear-off interfaces increases if the interfaces are queried for frequently. Now that you see how raw tear-off interfaces work, let's take a look at how the Active Template Library (ATL) handles tear-off interfaces. 

ATL supports two kinds of tear-off interfaces: plain, noncached tear-off interfaces and cached tear-off interfaces. ATL's classes for implementing tear-off interfaces include CComTearOffObjectBase<>, CComTearOffObject<>, and CComCachedTearOffObject<>. A COM class implementing an interface as a noncached tear-off creates a new instance of the subobject each time it requests the interface. The subobject implementing the tear-off interface stays alive as long as its reference count is greater than zero. A COM class implementing an interface as a cached tear-off creates a new instance of the subobject the first time it requests the interface, then caches the object, using the same subobject, every time it requests that interface. Let's take a look at noncached tear-offs first. 

ATL implements its tear-off interfaces in two phases. The CComTearOffObjectBase<> methods handle the reference count and QueryInterface(), while CComTearOffObject<> implements IUnknown. CComTearOffObject<> implements a tear-off interface as a separate object, instantiated only when that interface is queried for. The tear-off is deleted when its reference count becomes zero. 

As a developer, the only class you really need to concern yourself with is the CComTearOffObjectBase<> class because you need to derive your tear-off object from it. CComTearOffObjectBase<> takes template parameters for the threading model and the owner object, the class with object identity. Here's the definition of CComTearOffObjectBase<>: 



template <class Owner, class ThreadModel =       
   CComObjectThreadModel>
class CComTearOffObjectBase : public       
   CComObjectRootEx<ThreadModel>
{
public:
   typedef Owner _OwnerClass;
   CComObject<Owner>* m_pOwner;
   CComTearOffObjectBase() {m_pOwner = NULL;}
};

Notice how CComTearOffObjectBase<> includes a back pointer to the class with object identity, the data member m_pOwner. CComTearOffObjectBase<> uses this data member to maintain the COM identity laws�that is, to call QueryInterface() on the owner class. 

Implementing a tear-off interface using ATL is straightforward. Simply create a tear-off class using CComTearOff-ObjectBase<>, and create the main class (the one with object identity) the normal way. The tear-off magic happens within the interface map (see Listing 1). All you need to do is use the COM_INTERFACE_ENTRY_TEAR_OFF() macro in the interface map: 



#define COM_INTERFACE_ENTRY_TEAR_OFF(iid, x)\
   {&iid,\
   (DWORD)&_CComCreatorData<\
      CComInternalCreator< CComTearOffObject< x > >\
      >::data,\
   _Creator},

When a client calls QueryInterface() for the auxiliary interface, the COM_INTERFACE_ENTRY_TEAR_OFF() macro creates a new tear-off object using the normal ATL creation mechanism. You'll notice that the macro uses the CComTearOffObject<> class during the creation process. 

Implementing a cached tear-off interface in ATL is similar to implementing a noncached one. The only difference is you use COM_INTERFACE_ENTRY_CACHED_TEAR_OFF() in the interface map. This macro uses the CComCachedTearOffObject<> class when creating the tear-off interface. Here's the macro: 



#define COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(iid, x, punk)\
   {&iid,\
   (DWORD)&_CComCacheData<\
      CComCreator< CComCachedTearOffObject< x > >,\
      (DWORD)offsetof(_ComMapClass, punk)\
      >::data,\
   _Cache},

CComCachedTearOffObject<> implements IUnknown for a tear-off interface. CComCachedTearOffObject<> maintains its own reference count on its IUnknown and deletes itself once its reference count is zero. Querying for any of the subobject's interfaces increments the reference count of the owner object's IUnknown. 

When an interface implemented using ATL's cached tear-off interface mechanism is requested, the subobject is instantiated only once. Subsequent requests use the same tear-off object, as opposed to a tear-off interface implemented by a CComTearOffObject<>, which instantiates multiple tear-off objects. 

The caveat with cached interfaces is that the class with object identity must implement FinalRelease() and call Release() on the cached IUnknown for the CComCachedTearOffObject<>. This decrements the tear-off's reference count and causes the cached tear-off to delete itself. 

Living in the age of component-software development means programmers have to endure source code to arrive at their goal�a binary nirvana. If you've decided to use COM to create components, you'll often find yourself using C++. COM differs from C++ in its notion of object identity. In C++, an object's definition (what you see in the C++ header file) is usually synonymous with its identity. In C++, you never really talk to an object�you always talk to one of the object's interfaces. Through this indirection, and because every COM interface starts with the function QueryInterface(), a client can always expand its connection to an object at run time. 

As an object implementor, understanding COM identity rules gives you more options for creating COM classes. One useful way to implement COM classes employs tear-off interfaces, which compose classes instead of using implementation inheritance to create classes. Tear-off interfaces are helpful for creating COM classes whose interfaces aren't used by clients frequently or aren't used for very long. Fortunately, ATL provides good support for tear-off interfaces. 


George Shepherd develops software for Stingray Software and teaches seminars for DevelopMentor. In addition, George is the coauthor of MFC Internals (Addison Wesley Longman Inc.) and Programming Visual C++ (Microsoft Press). Reach him at 70023.1000@compuserve.com
 


c0Title: Monitor System State With SENS
c1Code:
June 2000

http://www.devx.com/premier/mgznarch/vcdj/2000/06jun00/jm0600/jm0600.asp
Learn how to hook an ATL application up to the System Event Notification Service (SENS). 

by Jim Beveridge 


   One of the more frustrating problems to solve under Windows is how to determine what is happening on the user's desktop. I've seen developers use all sorts of hacks to find out when a screen saver starts, when the user logs off, and other activities. Windows 2000 includes the System Event Notification Service (SENS) to try to solve this problem by notifying your application when interesting events happen. This article uses SENS to demonstrate the basics of subscribing to COM+ events by creating transient and persistent subscriptions. 
What you need:
Visual C++ 6.0 SP3
Platform SDK, September 1999 or later
Windows 2000  
 

There are two key questions to answer before moving forward: What is SENS? And why can't this problem be solved without COM+ events so that the solution works on older platforms? 

SENS provides a documented way for applications and services to find out about interesting things that are happening concerning battery management, network status, and desktop status. Without SENS, questions such as, "Does the user have the desktop locked?" and "Is the battery low?" are not only difficult to answer, but also require an application to poll Windows constantly to get the result. 

The difficulty of duplicating the functionality of SENS yourself should not be underestimated. If you use the DEPENDS utility (see Links) and look at SENS.DLL, you'll discover that the DLL is linked to almost 50 other DLLs, including ones that support PING, DHCP, and DNS, among others. SENS.DLL clearly contains more than a trivial API. 

When SENS determines that something interesting has happened, it needs to inform all interested parties. Historically, there has been no effective communications mechanism for this to happen. Window messages aren't viable because they require the target application to be running and they generally don't work for services. Connection points also require the target application to be running. 

The solution is to use COM+ events, another new feature in Windows 2000, which allow a sender (the "publisher") to call a function that is ultimately executed on one or more receivers (the "subscribers"). The publisher doesn't know who the receivers are, so the distribution of the information is separated and encapsulated from the publication. For our purposes, SENS is the publisher and your application indicates its interest in ("subscribes to") various things that SENS knows about. 

You should view this article as a demonstration of the mechanics of subscribing to COM+ events for a problem that would be difficult to solve through other means. If you want a more theoretical discussion, refer to Tom Armstrong's VCDJ article or Jeff Prosise's Middle Tier VCDJ columns (see Resources). For more details on the functionality of the COM+ Event System, see the Platform SDK (see Links). A complete publisher/subscriber example is presented in the Platform SDK in \Platform SDK\Samples\Com\Services\Events\EventMonitor. 

For those of you who make it to the end of this article, I have a new acronym for you to throw around casually with your lesser-informed colleagues. 

The Big Picture for a COM+ Event 
If you try to puzzle out COM+ Events from the reference pages, you're in for a tough ride. The basics of COM+ Events are easy, but you have to avoid getting bogged down in the details at the beginning. The key is that everything revolves around the event class ID. An event is defined when you take a GUID, call it an event class ID, and associate it in the event system with one or more Automation classes. 

To subscribe to an event, you implement your own version of those Automation classes in your program and tell COM+ to connect your implementation to that event class ID. Once the subscription is in place, COM+ calls your subscriber's copy of the Automation classes whenever the original Automation class is called. 

The cool part is that the notification process is completely transparent. Programs fire events by loading the Automation library and using it like any other Automation library. But, under the covers, whenever those programs call an interface in the Automation library, COM+ takes care of calling that same interface using the IDispatch interface on every single subscriber. 

SENS defines several event class IDs in Sens.h in the Platform SDK, but this article focuses on SENSGUID_EVENTCLASS_LOGON. The associated Automation interface is called "SENS Logon Events.1". The native interface is called ISensLogon. This interface has several methods, including DisplayLock() and Logoff(). You implement these methods in your subscriber and COM+ calls them when SENS fires an event. 

This arrangement is interesting for several reasons. First, multiple applications can subscribe to a single event class ID. All of them will be called by COM+ whenever the event is fired. However, the notification happens asynchronously and the program that fires the event doesn't have to wait for all clients to be called. Second, an event is really an asynchronous, multicast function call. By using the function call as the transmission mechanism instead of something simpler, such as Windows messages with a message number, a WPARAM, and an LPARAM, events can be expressed richly with multiple parameters and different data types that are fully type safe. Finally, the publisher doesn't have to know that it is firing events. As far as the publisher is concerned, firing an event is just like making any other function call. 

Now let's look at the mechanical details of creating all of these connections. You'll create an ATL object that subscribes to the SENS event. 

Create Your ATL Object
The ATL object required for this project is somewhat unusual because it has to implement an existing interface that is not predefined by ATL, and that interface has to be properly exposed in the object's type library. SENS has already defined the interface and this implementation of it has to match SENS's version both in the code and in the type library. This is easy in Visual Basic with the "implements" keyword, but it took me several false starts to find the proper combination of type library, C++ include files, and wizard-generated code that would actually work in ATL. 

To repeat what I did, create a new ATL project and call it SensDemo. I recommend creating an executable instead of a DLL because it's much easier to debug and experiment with. Insert a new ATL object that is a Simple object and call it LogonSubscriber. Don't change the default attributes. 

Go to CLogonSubscriber in the ClassView, right-click, and choose Implement Interface. Click on OK at the error dialog, then find SENS Events Type Library (1.0) in the type libraries list, check the checkbox next to it, and click on OK. In the Implement Interface dialog, check ISensLogon and click on OK. This generates all the correct C++ skeleton code. Unfortunately, it will not work yet because the Implement Interface Wizard does not update the IDL file. You need to modify the IDL file manually in order to have the right type-library support. 

The first change to the IDL file is to indicate that LogonSubscriber implements ISensLogon. You do this by adding "interface ILogonSubscriber;" under "coclass LogonSubscriber". That's the easy part. Now MIDL requires a definition for ILogonSubscriber. 

The straightforward approach is to add 'import "SensEvts.idl";' at the top of the file. Great idea, but it doesn't work. The MIDL compiler generates SensDemo.h, which includes SensEvts.h, whose contents conflict with the structure definitions created by the #import statement in LogonSubscriber.h. The correct solution is to restrict the scope and place the declaration in the section under "library SENSDEMOLib". The end of the IDL file now looks like Listing 1. 

To complete the skeleton, add these two lines to the list of include files in SemsDemo.cpp: 



#include "Sens.h"
#include "EventSys.h"

Create a Transient Subscription
Now that your object has a skeleton, you're ready to create a subscription for the object to receive events. There are three kinds of subscriptions: transient, persistent, and per-user. 

A transient subscription sets up an instance of a single object to receive events. The subscription only lasts the lifetime of the object. The object must exist to create a transient subscription, so transient subscriptions are only created for a running application. 

A persistent subscription sets up a class of objects to receive events. Persistent subscriptions last beyond the lifetime of any instance of an object and are saved through reboots. With a persistent subscription, an instance of the class is created when the event fires. Finally, a per-user subscription is a persistent subscription that will only be fired if a particular user is logged in. 

To create a transient subscription, you work with three separate COM objects: the Event System, the Event Subscription, and your object that implements the interface for the event. The Event System is the repository that keeps track of all subscriptions and each Event Subscription object represents a single entry in the Event System. There are numerous other objects related to events for publishers, filtering, and creating COM+ applications, but ignoring them for the moment allows us to focus on the basics. 

In this sample code, I initialized the subscription after initializing the class factor but before the message loop. The first step is to create an EventSubscription object. EventSubscription doesn't do much on its own; it merely acts as a container for the data that needs to be given to EventSystem: 



CComPtr<IEventSubscription>
          pIEventSubscription;
hr = CoCreateInstance(
      CLSID_CEventSubscription,
      NULL,
      CLSCTX_SERVER,
      IID_IEventSubscription,
      (void**)&pIEventSubscription);

Next, the EventSubscription object should be initialized to define your subscription. I've listed the minimum properties I recommend to define a transient subscription (see Table 1). You can use other ways to define events, which I'll talk about shortly, but the common theme is to uniquely identify the subscription, define which events you are interested in, and define where the events should be directed. 

The code to fill in the EventSubscription object for a transient subscription to SENS is shown in Listing 2. Error checking has been removed for brevity. Note that the code must create an instance of CLogonSubscriber because a transient subscription requires an existing IDispatch interface. 

Once the EventSubscription object is ready, obtain an interface to EventSystem and save the EventSubscription with the Store() function, as shown here: 



CComPtr<IEventSystem> pIEventSystem;
hr = CoCreateInstance(
      CLSID_CEventSystem,
      NULL,
      CLSCTX_SERVER,
      IID_IEventSystem,
      (void**)&pIEventSystem);
   CComBSTR eventsub(
      PROGID_EventSubscription);
   hr = pIEventSystem->Store(
      eventsub,
      pIEventSubscription);

The subscription is now active and will respond to events. In my sample application (download the code), I put "MessageBeep(-1)" in several of the implementation routines to prove the code was working. The simplest event to try is to lock the workstation by pressing Ctrl-Alt-Delete and clicking on Lock Workstation. You'll hear the application beep when the workstation is locked and when it's unlocked. 

Act on the Events
There are a variety of events generated by ISensLogon that your application can react to. These include: 

Logon/Logoff 
Display Lock/Unlock 
Screensaver Start/End 
Start Shell
The ability to be informed when the desktop is locked and when the screensaver is running allows your application to make knowledgeable decisions about how to behave. Applications such as backup programs can use a default setting if the user isn't available. Calendar and reminder programs can queue up notifications until the user is available. Programs idling in the background can increase their CPU priority. Utility programs can begin tasks such as harddisk cleanup and folder synchronization. 

Some events, such as Logon and Logoff, are probably more interesting if they can be delivered to objects that might not be part of a currently running application. The solution is to use a persistent subscription. 

I've described how to create a subscription using native calls to the Event System, but it's important to note that there are actually four ways to create a subscription: 

Native COM calls to the Event System 
Automation calls to the Event System 
Automation calls to the COM+ Catalog 
Through a user interface in the Component Services application (under Start/Programs/Administrative Tools)
You'll find examples of the other three as you look through the sample code and README files in the Platform SDK. The first example is the technique used to create the transient subscription I discussed earlier. To create a subscription to SENS, it appears that you have to talk to the event system instead of using the user interface (UI). The reason is that the UI in the Component Services application requires you to provide a type library and an implementation DLL when you define the event. The type library can be found in either SENS.DLL or ES.DLL, but I have been unable to find an implementation DLL that installs successfully in the Component Services application. Your mileage may vary. 

It would be useful to have the UI because you could use it to confirm that your API calls have worked correctly. Unfortunately, subscriptions created with IEventSystem aren't visible in Component Services. One workaround is that you can view registration information in the Registry in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EventSystem. 

Although an EXE server can be used to define a transient event, you must use an in-proc DLL server to define a persistent event. As I discovered, trying to use an EXE server does not generate any errors, but the events are never received. 

Creating an in-process server is almost identical to creating an EXE server, except that the location, within your code, of the persistent event registration changes. My solution was to place the event registration code in DllRegisterServer() after _Module.RegisterServer(TRUE). With this structure, the subscription is created whenever the DLL is registered. For the sake of completeness, you should also include code to remove the event in DllUnregisterServer(). 

A persistent subscription is defined by setting the SubscriberCLSID property in the EventSubscription object to the class ID of your object. The CLSID is generated when your IDL file is compiled and looks something like CLSID_LogonSubscriber. When you set SubscriberCLSID, you don't set SubscriberInterface. The Subscriber CLSID and SubscriberInterface properties are mutually exclusive. 

Implement Filtering
The COM+ Event System is quite flexible, and this flexibility is the root of the difficulty in making events work properly when you start using them. Until you get the publisher, the event, and the subscriber all defined correctly, the events don't work and there are no error messages. The good news is that once you have an event working, you can incrementally play with the properties in the EventSubscription object and observe the results. 

Many of the properties for IEventSubscription revolve around filtering. Filtering allows you to define the combination of publishers, events, interfaces, methods, and custom parameters that are actually fired to your event handlers. In a system with many events, this can be an important performance enhancement. In a distributed system, where publishers and subscribers are connected by slow links, using filtering can be vital to using the available bandwidth optimally. 

The highest level of filtering depends on whether you choose to subscribe to a particular event class, a publisher, or an event class published by a specific publisher. When I said earlier that everything revolves around the event class, I oversimplified somewhat. If your top-level filter is on the publisher, you get all events that the publisher defines for which you have written code to receive. If your top-level filter is on the event class, you'll receive events from any publisher that fires an event in that event class. 

Notice the part in the last paragraph about receiving events "for which you have written code to receive." All events are generated through IDispatch. Events aren't generated through native interfaces. The reason is that you only need to implement functions you actually need. This is a moot point in ATL, where your vtbl must be structured properly anywhere, but it's important in higher-level languages such as Java and Visual Basic. 

Obviously, if you've only defined one interface out of several, there is no reason the event system should go through the work of querying your type library on every single event, only to discover over and over again that your code doesn't implement that event. The two properties in IEventSubscription that control this problem are InterfaceID and MethodName. An event can encompass multiple interfaces. By setting InterfaceID, you can declare that you're only interested in a particular interface. Similarly, by setting MethodName, you can exclude all methods that don't have that name. This filtering saves the server from significant work and can reduce the load on your application if many events are being fired. 

A parting hint about working with SENS. Don't be fooled (as I was) by definitions in Sens.h, such as SENSGUID_PUBLISHER and SENSGUID_SUBSCRIBER_LCE. Although they seem to exactly match useful property names in IEventSubscription, they probably don't do what you think they do. For example, you can't use SENSGUID_PUBLISHER as the PublisherID to get all the SENS events. Instead, SENSGUID_PUBLISHER is used when you want events indicating that SENS events have changed. 

Finally, the new acronym. It took me quite a while to figure out what the LCE means in SENSGUID_SUBSCRIBER_LCE. Turns out that it stands for loosely coupled events. COM+ Events are loosely coupled because the publisher and subscriber don't need to know about each other. The opposite is TCE, or tightly coupled events, which is what you get with connection points. 

When I started to research this article, I intended to talk about ISensNetwork, which informs your application about network connectivity status. ISensNetwork is interesting because it's supported under all versions of Windows that have Internet Explorer 5 installed, even though it uses COM+ Events. The result is that you can see COM+ Events in action under Windows 95, Windows 98, or Windows NT 4.0. 

The problem is that I was never able to get ISensNetwork events to work. Under Windows 2000, the subscriber never received any events, and on Windows NT 4.0, the subscriber failed to install into IEventSystem. If you are able to make ISensNetwork function, I would be interested in hearing from you. E-mail me at jbeveridge@fawcette.com. 


Jim Beveridge is an independent consultant specializing in software architecture, design, and project management. He is the coauthor of Multithreading Applications in Win32 (Addison Wesley Longman Inc.) and a frequent speaker at the Visual C++ Developers Conferences. Reach him at jbeveridge@fawcette.com
 


c0Title: Multithreading in C++ and Java
c1Code:
May 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/05may00/dm0500/dm0500.asp


C++ and Java approach multithreading differently. You can achieve the same result with both languages, using different techniques. 

by Dianne M. Marsh 


     A good way to prevent your C ++ and Java programs from locking up is to use multithreading, which simply means you write a program that enables multiple execution streams to occur simultaneously within the same program. Each stream processes a different transaction or message. For multithreading to be useful, you must run a multithreaded program in a multitasking or multiprocessing environment, allowing multiple operations to take place. 
What you need:
Visual C++ 6.0
Java 2.0  
 
For example, if you've started a lengthy, single-threaded calculation with errant parameters, the only way to stop the calculation is to terminate the application entirely. The program can't respond to your input because it's busy performing some other operation. To prevent this problem, use multithreading. 

If you're new to multithreading, this article introduces you to key concepts and shows you a comparison between the constructs MFC and Java provide. If you're a seasoned MFC programmer, you'll be able to compare the constructs you already know to those Java provides, and vice versa if you're a Java multithreading programmer, although you're admittedly fewer in number! 

Specifically, in this article, I'll describe how to achieve a distributed solution with both C++ and Java. I use programming examples to demonstrate how to implement multithreading in both languages. 

You can benefit from multithreaded programming with single-processor and multiprocessor systems. On a single-processor system, only one task (thread) runs at a time. The CPU scheduler controls the switching between threads, making it appear the threads run simultaneously. In multiprocessor systems, you can spread thread execution across processors. For scalability reasons, if you write a multithreaded application now, you're able to take advantage of added processors later. 

Using synchronization ensures a consistent state between the threads. You must carefully implement synchronization to avoid deadlocking, which occurs when one object is waiting for another to release a lock, and that object is also waiting. If circular dependency occurs, then the waiting threads are never executed, and the program is stuck or "deadlocked." To prevent this, it's important not to hold a lock while waiting for another resource that also requires locking. 

   
Figure 1. Turn on Multithreaded Support. Click here.

 
Modern operating systems support multithreaded applications and can schedule individual threads for execution, providing a flexible operating environment. You can also write individual programs, called processes, which communicate among themselves, exchanging data and checking state. The operating system still schedules processes for execution, but processes don't share state. The operating system switches contexts when one program stops and another is scheduled to run. In addition, you must use interprocess communication mechanisms to exchange data between the executing processes. In a multithreaded program, individual threads can execute and interact as necessary without incurring expensive context-switching costs. Traditional languages, such as C and C++, use libraries to provide threading support. MFC has its own support for threads. Java was written with multithreading support. While it can't prevent deadlock entirely, its inherent mechanisms reduce the likelihood. No matter what approach you use, you'll have to properly use synchronization to avoid deadlock. 

Synchronizing Provides Integrity Within a Program
Threads share state, address space, and resources provided by the operating system, allowing multithreading to work with shared memory and making the CPU more efficient. However, one thread's state might impact another. Programmers use synchronization to prevent this. Thread synchronization doesn't mean the threads work together in lockstep like synchronized swimmers. Rather, the threads agree about data access and modification, so one thread doesn't corrupt data another thread is using. The CPU scheduler doesn't understand program flow and can't anticipate when one thread might be inopportunely interrupted. You'll need to specify explicitly such situations to prevent problems. 

It might be tempting to synchronize all of a class's methods to prevent problems with changing and accessing member data. The locking mechanism, however, is costly. It puts a brake on program flow until the lock is released�meanwhile, other threads check the lock to determine if they can continue. Use locking only in those methods that modify member data state accessed by other methods. 

The reader-writer program is a classic computer-science example demonstrating the need for synchronization. In a multithreaded application, one thread might be trying to read a data object (reader) while another is trying to update it (writer). This might happen if you implement a thread to wait for a socket read. Once the data is available to read on a socket, you can update the information in the corresponding object. If, however, another thread is using that information, unexpected behavior occurs. For example, a program might have one thread processing I/O and others handling the user interface code, background calculations, or any other necessary tasks. 

There are several constructs for synchronization, including mutexes, semaphores, and event objects. Mutexes are used for mutual exclusion. They describe a portion of code that must be treated as an atomic action to provide consistent results. A mutex is commonly used in a critical section, where only one executing thread at a time can enter a section of code. Semaphores count resources that can handle only a limited number of simultaneous threads, so you can make sure the resources aren't overloaded. Event objects indicate that a particular event has either happened (set) or hasn't happened yet (unset). Rather than protect a resource, event objects coordinate activity between threads. Both MFC and Java support these constructs, although in different ways. I'll explore the differences in the following sections. 

Neither C nor C++ include support for multithreaded programming as a language construct. Unix programmers rely on libraries provided with specific compilers or provided by third-party vendors. Win32 provides constructs for threading and synchronization, and MFC adds an object-oriented flavor to the constructs. While the concepts are the same, the C++ examples I've included in this article use MFC. To create a mul-tithreaded program in MFC, turn on multithreaded support under the Project Settings C/C++ tab, Code Generation Category (see Figure 1). 

MFC Discerns Between Threads
MFC distinguishes between user interface threads and worker threads. Appropriately enough, user interface threads handle user input and respond to user events, while worker threads perform background processing. For this reason, the user interface thread has its own message loop, independent of the main message loop, and a worker thread doesn't. To determine if you need to create a user interface thread or a worker thread, consider how you'll use the thread and, in particular, if it requires its own message loop. If the thread displays information to the user, then you should create a user interface thread. However, a worker thread is sufficient in most cases, and, thankfully, easier to implement. 

Java provides language support, including creating, managing, and synchronizing threads, through monitors for multithreading (see Resources). Monitors serve as locks for resources that require access one object at a time. Any object can serve as a monitor in Java and you specify that a resource requires a lock using the synchronized keyword. (I discuss the synchronized keyword in more detail later.) Locks are assigned automatically upon entering the synchronized block of code and released as necessary when the block is exited. This process differs significantly from MFC, where the programmer checks and releases all locks manually. Java handles critical sections directly, using the synchronized keyword, and you can implement semaphores easily, using a combination of an object with a counter and the synchronized keyword. I've provided a comparison of MFC and Java multithreading constructs and described their symmetry (see Table 1). 

In MFC, AfxBeginThread() defines threads. This method's parameters differ based on whether you're creating a worker thread or a user interface thread. To create a worker thread, use this form: 



CWinThread* AfxBeginThread( 
   AFX_THREADPROC    pfnThreadProc, 
   LPVOID pParam, 
   int nPriority =
         THREAD_PRIORITY_NORMAL, 
   UINT nStackSize = 0, 
   DWORD dwCreateFlags = 0, 
   LPSECURITY_ATTRIBUTES
      lpSecurityAttrs = NULL);

To create a user interface thread, use this form: 



CWinThread* AfxBeginThread( 
   CRuntimeClass* pThreadClass, 
   int nPriority    =    THREAD_PRIORITY_NORMAL, 
   UINT nStackSize = 0, 
   DWORD dwCreateFlags = 0,
   LPSECURITY_ATTRIBUTES 
      lpSecurityAttrs =NULL);

To create a user interface thread, derive a class from CWinThread and pass it into AfxBeginThread() (this parameter is used only in user interface threads, not in worker threads). Both forms of the AfxBeginThread() method take a pointer to a function that runs when the thread starts. Windows documentation describes this as the thread controlling function, but it's commonly referred to as the threadproc. You must define the thread-proc with this signature: UINT threadFunc(LPVOID param). 

Use the LPVOID Parameter
Use the LPVOID parameter to pass in any information the threadproc needs to execute. This parameter is used most commonly to pass "this" to the threadproc and to call a public member function from the threadproc. Here's how to create the thread and define the associated threadproc in Visual C++ 6.0: 



// declare a static member function 
// of the class MyClass 
static UINT 
MyClass::MyThreadProc(void *param)
{
   MyClass *ptr = (MyClass *)param;
   return param->ClassThreadProc();
}
UINT MyClass::ClassThreadProc()
{   
   // perform thread work here
}
CWinThread *pThread = 
   AfxBeginThread(&MyThreadProc,
      (LPVOID)this, 
      THREAD_PRIORITY_NORMAL);

In MFC, the nPriority parameter indicates the thread's priority. The operating system performs round-robin scheduling based on priority levels, so lower-level threads are only scheduled when higher-priority threads aren't available to run. Generally, you'll set this parameter to 0, indicating that the new thread should use the same priority as the thread that created it. Another interesting parameter is dwCreateFlags, which specifies whether the thread should start immediately after creation or whether it should start in a suspended state. You'll often start threads in a suspended state to make sure the thread creation succeeded, then call the ResumeThread() function on the newly created thread. You invoke the thread-proc either at thread creation or after ResumeThread() is called, if the thread was created in a suspended state. The new thread runs independently of the creating thread, if the program is multithreaded. 

Unlike MFC, Java doesn't distinguish between user interface and worker threads. You can either inherit from Thread or implement the Runnable interface. Each Java form has advantages. Inheriting from Thread provides a simple syntax. You merely specify a run method in the new class, then call its start method: 



class myClass extends Thread
{
   public void run() 
   {
      // body of the thread
   }
}

To define a thread by implementing the Runnable interface, use a form of the Thread constructor that takes an object of type Runnable: 



MyClass stuff1 = new MyClass();
stuff1.start();
class MyOtherClass implements Runnable
{
   public void run()
   {
      // body of the thread
   }
}

MyOtherClass stuff2 = 
   new MyOtherClass();
Thread aThread = 
   new Thread(stuff2);
aThread.start();

While it's more verbose, defining a thread by implementing the Runnable interface is generally better. From a purist's perspective, this specification is more object oriented, in that the new class implements an interface, rather than implying an Is-A relationship. This avoids multiple inheritance problems. Because Java doesn't support multiple inheritance, any class inheriting from Thread can't specify an inheritance relationship with any other class. Given a class might implement any number of interfaces but is limited to inheriting from a single class, it's cleaner to implement the Runnable interface than to inherit from Thread. 

Start the Thread
You start a thread by invoking its start() method, which in turn invokes its run() method. Don't directly invoke a thread's run() method by the application program; this executes the method within the currently executing thread�probably not what you intended. This is the same way you specify the threadproc (as I described for MFC) without imposing the static-member function. 

Java threads can be interrupted, can voluntarily yield the CPU, and can sleep. As of Java 2, however, they can no longer be suspended, resumed, or stopped directly to reduce the potential for deadlock. Instead, the wait() and notify() methods of Object handle the suspend and resume operations. To stop a thread, set a member variable when the necessary condition is met. Implement the run() method to check that variable periodically, then exit when it's appropriate. 

MFC provides several classes used specifically for synchronization, including CMutex, CCriticalSection, Csemaphore, and CEvent. You'll use mutexes, critical sections, and semaphores with a lock. Locking and unlocking objects isn't an integral part of the runtime environment, as it is in Java, so you must separately define the process. The synchronization object you choose defines how code behaves, while the lock enforces that behavior. In MFC, the programmer handles locking and unlocking objects. You must manipulate the locking mechanism atomically, which results in the complicated activity of associating locks with synchronization objects. MFC doesn't release a lock if a function terminates abnormally, if an exception occurs, or if you exit a function and forget to unlock an object. All these situations can cause deadlock, so be careful. 

Another locking form is based on event handling. An Event object is any synchronization object whose state can be changed with SetEvent. To synchronize threads based on an object's state, create an Event and call the WaitForSingleObject() or WaitForMultipleObjects() method to await notification that the state has changed. This might be useful when running a background process and periodically sending the status information back to the main thread. The main thread can set up an Event to wait for notification that processing is complete. 

Threads are terminated in MFC when their controlling function (threadproc) completes execution. You can call the AfxEndThread() function to prematurely terminate the thread. You can also use event notification to wait for another thread to terminate. A thread's lifetime depends on the parameters set during thread creation. By default, the CWinThread object lives only during the thread's execution. Once the threadproc exits, the CWinThread object also goes away. If you set CWinThread::m_bAutoDelete to false, the CWinThread object you created stays around until you delete it. This allows you to check the thread's exit code and to perform any necessary cleanup after it exits. 

Synchronized Keyword Specifies What to Lock
Java programmers don't manipulate locks manually. The synchronized keyword in Java specifies that a block of code requires locking. When the lock is used on a function, the Java runtime environment obtains the lock for the function's execution. When the lock is used on a code block, it's obtained during that block's execution only. A current object (this), which limits the synchronization to the critical code block, is a common object to use for locking. Execution can continue once the synchronized block of the method has completed, giving you more control over a method's composition than if you could specify synchronization only on function boundaries. The lock is released when the function (or code block) is exited; the release doesn't require you to intervene manually. To avoid deadlock, use caution when locking on an object other than the current object: 



synchronized void    methodThatRequiresLocking()
{
   // function is not entered until 
   // the lock is obtained.
   // lock is released upon exit 
   //   from this function
}
void someOtherMethod()
{
   // lock is not obtained until the 
   // synchronized keyword is 
   //   reached
   Vector vec = new Vector();
   vec.addElement(new Integer(5));
   // etc., etc.

   synchronized (this)
   {
      // lock is obtained for the
      // object in which this  
      // method is defined
      // do something here that 
      // requires sole access
      // lock is released upon exit
   }
   // do some other stuff here
   // assume that myString is 
   //   defined as a class member
   // variable
   synchronized (myString)
   {
      // lock is not obtained on the 
      //   entire object, just on 
      //   myString
      // do something here 
      //   (careful to avoid
      //   deadlock)
      
   }
}

In this code, a subsequent lock on myString (or on "this") can't be granted until the synchronized block of code exits. This results in deadlock if the code block requires a lock on "this." You can also specify a lock on a class, rather than an object, and handle synchronizing the class's static methods. 

In Java, the wait() and notify() methods support event notification. This works differently from MFC, where you wait on a particular event. In Java, you use wait() to put a thread to sleep until some event occurs and notify() or 
notifyAll() is called. When the thread wakes up, it should check the object's state, and if the desired event has occurred, proceed. If not, it should call wait() again. This is more efficient than using sleep(), because the thread doesn't have to poll for changes. It's also safer than sleep() and suspend(), because neither of those release the lock when they're called. 

Java 2 removed the suspend() and resume() methods because suspend() was deadlock-prone. Note that the Java scheduler runs independently of the threads. If a thread relinquishes the CPU or releases a lock, the thread can't control which waiting thread will gain control or obtain a lock. One running thread can't "hand off the baton" to another. Execution is always scheduled through the Java scheduler. In the same way, you can't specify which thread is notified when the notify() method is called. For this reason, use notifyAll(), rather than notify(), to ensure that all threads are aware of the state change. 

If you have to wait for a thread to die, use the join() method. Never directly invoke the stop() method. A thread's lifetime continues until the run() method terminates, effectively calling the stop() method. If the run method never terminates, then the thread continues to run, even after the program that initiated the thread exits. You need to be aware of this so you don't leave orphaned threads and consume resources. You should kill a thread performing background operations when the application exits. This type of thread is called a daemon thread. The Java interpreter exits if the daemon threads are the only ones running. Use the setDaemon() method to specify this behavior. You can also use thread groups to associate and control threads. 

Bank Account Synchronization
A bank account is a classic example demonstrating synchronization. A user might withdraw money at the same time that a deposit is made on the same account. If both are allowed to access the account simultaneously, the balance will be wrong at the end of the second transaction. However, the bank can't simply process one connection at a time�the other bank customers would likely be annoyed. You should implement the bank as a multithreaded object, but elements specific to a particular account should be accessed synchronously. This example uses a critical section (a mutual exclusion object) in MFC to indicate that only one thread can access the code associated with the lock: 



class AccountInfo 
{
private:
   float balance;
   string accountName;
   CCriticalSection balanceCode;
   CSingleLock *balanceLock;

public:
   AccountInfo(const string &name) : 
      balance(0.0), accountName(name)
   {
      balanceLock = new 
         CSingleLock(&balanceCode, 
         false);
   }

   ~AccountInfo() { 
   delete balanceLock;
   }

   void deposit(float amount) {
      
      balanceLock->Lock();
      balance +=   amount;
      balanceLock->Unlock();
   }

   void withdraw(float 
      amount) {
      balanceLock->Lock();
      balance -= amount;
      balanceLock->Unlock();
   }
   float getBalance() const {
      balanceLock->Lock();
      float val = balance;
      balanceLock->Unlock();
      return val;
   }
};

This works because the C++ program is well behaved; it checks for locks whenever accessing data that another thread might be modifying, and locks and unlocks appropriately. The synchronization constraints are defined in the class definition and used in the class implementation�a fact that is easily lost in the code. In particular, if a new function merely reads a variable (as does getBalance() in the example), it might not seem necessary to lock it, even if the programmer realizes that synchronization constraints have been imposed on the class. If the language had restricted access when another thread was granted a lock, the programmer wouldn't have this burden. Of course, language support doesn't substitute for good programming skills, but it's convenient when a programming language (rather than the programmer) handles mundane tasks, such as synchronization in multithreaded programs. 

Here's the bank example in Java to demonstrate synchronization techniques: 



public class AccountInfo
{
   private int balance;
   private String accountName;

   public AccountInfo(String name)
   {
      accountName = 
         new String(name);
   }

   synchronized public void    deposit(float amount)
   {
      balance += amount;
   }

   synchronized public void    withdraw(float amount)
   {
      balance -= amount;
   }

   synchronized public float    getBalance()
   {
      return balance;
   }
}

The synchronization constraints in both the bank examples I've provided aren't entirely complete. While you've ensured that a single account can't be corrupted by multiple simultaneous accesses, you haven't addressed the fact that synchronization is needed at the bank level as well. In particular, while the message is processed (perhaps by a socket call), you have to ensure another thread doesn't distort the socket's contents. In addition, if accounts are added or removed while balances are being obtained for all accounts in a different thread, unexpected results might occur. A complete application should address all these issues. 

The I/O Operation Example
A classic example of multithreaded programming is waiting for an I/O operation to complete. This happens when you use a socket connection for communication between client and server, but user interface elements must continue to update. I've included a demonstration of using thread-synchronization techniques (with both MFC and Java) to implement a more complete bank application. Download this code�an extension of the article's listings, covering necessary interactions in greater depth. 

In addition to implementing the MFC in the article, the online application uses sockets to make connections between the client and server. The Java implementation in the sample also uses sockets to connect between the client and server. See the sidebar, "A Multithreaded Application in C++ and Java," for details. 

Users expect a responsive user interface in modern programs, a benefit most often achieved by a multithreaded program. By understanding the issues involved in creating, managing, and synchronizing threads, you can better determine when to recommend multithreading. C++ and Java both create threads and synchronize access to data shared by those threads. In MFC, you manage all access to shared data, and every function checks for a lock before proceeding. In Java, the runtime environment enforces locking, so you need only specify which functions access the method data another function might read or write. 

MFC code is sprinkled with locking and unlocking mechanisms, and class definitions include the relevant synchronization object and associated lock. Java classes have inherent support for synchronization, should they choose to include it; if class-wide locking isn't necessary, you can lock on another object. 

The legacy code an application will be built around often determines which language you choose to use. This is why it's important you understand how to provide multithreaded support in both C++ and Java. 


Dianne Marsh is a professional software architect and cofounder of Midwest Seas Software Development Inc. Dianne has more than 10 years of software experience, designing and developing enterprise-wide systems. She has an M.S. in computer science and is a Sun Certified Programmer for the Java 2 Platform. Reach her at dmarsh@midwestseas.com or www.midwestseas.com
 


c0Title: Navigate Skillfully Through MFC
c1Code:
  September 2000

http://www.devx.com/premier/mgznarch/vcdj/2000/09sep00/fu0009/fu0009.asp

Learn to find the classes and tools you need to solve your programming problems. 

by Bill Wagner 

 
   I ended last month's installment promising to provide an MFC overview in this month's column, and here it is. This column does two things: It highlights the original design goals of MFC, and it gives you a quick roadmap of the MFC libraries. MFC is a large library. When I teach MFC, I split it into three areas, which is the way I've organized this column: the application framework, the Windows API tools, and the utility classes. After reading this column, you'll have a better understanding of how MFC is organized and be able to find the particular classes needed to solve your individual programming problems. Many of the tools you need are in MFC, and this roadmap will help you find them. 
What you need:
Visual C++ 6.0  
 
The first version of MFC shipped in 1992, when the programming world was quite different. C++ had not reached industry-wide acceptance, and there was no C++ standard. Developers were creating desktop applications�they weren't working with COM components, Web pages, or other ActiveX controls�and Windows was a 16-bit world. 

Visual C++ entered that world with one purpose: to make it easier for developers to create high-quality Windows applications. MFC was, and is, the primary tool that fulfills this goal. MFC is also tightly integrated with the Visual C++ wizards, which help you build Windows applications. 

Work With MFC's Application Framework
To work effectively with MFC, you must understand its application framework, which is loosely derived from Smalltalk's Model/View/Controller (MVC) framework. The Model reads, writes, and transforms the data in an application; the View displays the data in the model; and the Controller controls how the view interacts with the operating system. 

The MFC developers then changed the term "mode" to "document." The Controller is not necessary in MFC because MFC applications only ran on Windows. The Windows API substituted for the controller; there was only one. 

MFC's application model uses four main classes: the application, the frame window, the document, and the view window. The application class is derived from CWinApp, the frame window is derived from CFrameWnd, the document class is derived from CDocument, and the view class is derived from CView. You should put global methods and variables in the application class. Member variables and methods that work with the Win32 API go in the frame window. You put all methods and variables that define your data abstractions in the document, and all methods and variables that display or print data in the view. The document and the view have a one-to-many relationship: One document can be displayed in multiple formats. 

The frame window and the document also have a one-to-many relationship: a multiple document interface (MDI) application can display more than one document at once. Single document interface (SDI) applications work with only one document at a time; there is a one-to-one relationship between the document and the frame. MFC has many derived classes for each of the four main classes mentioned previously, but there is only one application class: CWinApp. CWinApp handles the appropriate abstraction for any application. 

There are five frame window classes you might use in your application; AppWizard picks the right one based on the options you select. For the main application window, SDI applications use CFrameWnd, which provides all the functionality needed for a main window. 

MDI applications use two frame window classes. Your main application window is a CMDIFrameWnd object. Each document window is contained inside a CMDIChildFrameWnd object. If you are using OLE Compound Document Storage, your application gets a COleIPFrameWnd object. The COleIPFrameWnd object handles the in-place activation of an OLE Compound Document Object server. 

CMiniFrameWnd is a different type of frame window. It creates a floating window that has a half-height title bar. MFC creates these for you if your application supports floating toolbars. You rarely add your own frame windows to your application because AppWizard typically creates the correct frame windows for you. In fact, AppWizard creates classes derived from the correct MFC classes so you can add any functionality to your own frame windows. 

MFC has different document classes for different purposes (see Table 1). I have included recordsets here, which are not actual document classes, but they work closely with CDocument to provide database access. The document class provides the abstraction for your data. MFC's CDocument class is an abstract base class; your application uses a document class derived from one of the MFC classes. CDocument provides the interface and a default implementation for common tasks. MFC knows nothing about the data or disk file format of your document structure, so you need to provide this information by adding data members and overriding the serialize functions in your application's document class. 

MFC also provides a way to override the reading and writing functionality in the CDocument class to use an existing file format. The rest of the CDocument functions provide an interface for MFC's framework to work with your derived document. You have functions that let you change the title of a document, specify the behavior when a document is loaded or saved, or determine how your documents are sent using e-mail. 

You'll find much greater variety in the types of views you can use as base classes for your application's view class (see Table 2). The view class draws your document's data in a window. MFC provides many more view classes because you can use a wide variety of Windows controls to draw your document's data in the format that provides the best user presentation. You can pick the best view class to draw your data. Then, all you need to do is override a few virtual functions to display your document's data and interact with the users. For most view classes, you'll override the OnDraw() function to draw your data. View classes derived from CCtrlView are capable of drawing themselves. You need to use the control's member functions to get your document's data into the control. 

Your application needs to receive input from the users. Before MFC, all user input went through the main window in the form of a window message, and all command messages went through in the form of WM_COMMAND messages. MFC's application framework introduces command routing, which enables an object to register its interest in a particular command message. The MFC command routing architecture provides an object-oriented framework on top of the Windows messaging architecture. In Windows, all user interaction gets to your program in the form of a Windows message sent to a window (see the sidebar, "Windows and MFC Messaging"). MFC's command routing means you can have each object respond only to those messages best handled in that object. 

MFC implements command routing in the class CCmdTarget. The application, frame window, document, and view window classes all derive from CCmdTarget, which contains a message map. MFC uses message map macros to call functions in an object when the users select a particular command. Use ClassWizard to add the macros and functions that build a message for you. 

You should take particular care when deciding which class in your application should handle a particular command. Anything that changes the document data should be part of the document class, and anything related to the document data's display or printing should be part of your view class. Note a subtle distinction between the application class and the frame window class. The application class should handle global commands; the frame window class should handle commands that affect the presentation of the main window. A good example comes directly from the default commands AppWizard creates. The application handles the File | Open command, which creates a new document/view pair for users to edit. The main frame window handles the View | Toolbar command, which shows or hides the toolbar window. The toolbar window is the main frame window's child. 

A common mistake, one made even in many MFC tutorials, is to place command handlers that belong in the document class in the view class. This practice often seems expedient because user interaction begins in the view window. But this makes it difficult to add different kinds of views in the future. Doing too much work in the view class leads you to provide public access to the document's data. You'll end up writing algorithms that modify your document in your first view class. As you add the next view class, you often need to copy those algorithms to the document class or your second view class. 

Another large section of MFC manages UI elements. MFC's application framework gets you started on creating your application. MFC applications use windows for all the UI elements, and MFC provides classes that work with Win32 UI elements. Use these classes to work with window controls, tooltips, GDI elements, and the Win32 common controls, such as dialogs, toolbars, and status bars. The classes include all the various window classes, device contexts, windows pens, brushes, and other GDI elements you need. 

This has always been a difficult concept to describe because of the overuse of the word "class." Windows describes types of windows as a window class. Examples are EDIT, LISTBOX, COMBOBOX, and BUTTON. C++ and MFC use "class" to describe a C++ class. The MFC corollaries to the preceding windows are CEdit, CListBox, CComboBox, and CButton. I will use "class" to refer to an MFC class, and "Windows class" to refer to the Windows class. These MFC classes are simple object wrappers around the existing Windows API. For example, this gets you the size of a window using the Win32 API: 

GetClientRect (hwnd, &rc);
hwnd is a window handle, and rc is a RECT structure. But you can do the same more simply in MFC: 
pWnd->GetClientRect (rc);
Here, pWnd is a pointer to a CWnd, and rc is a CRect class. 
The second form is more natural in the C++ language. CWnd hides the HWND and implements all the Win32 API functions concerning a window as a member function. 

These MFC classes are tricky only in how they are created and destroyed. This difficulty arises because the C++ object's lifetime might not be the same as the Windows handle's lifetime. MFC designers tried to link these two concepts. You use two common idioms with Windows. The first is when you create a CWnd object, then call its Create() member function to create the window. The C++ object is destroyed when the window is destroyed, and your pointer becomes invalid. 

The second idiom is used in dialogs, whenever the MFC framework creates a child window or the Windows OS creates a window before the C++ object exists: The operating system creates the window, and you attach a C++ object to the existing window. In those cases, you call Detach() before the operating system window�not the CWnd object�is destroyed. If you don't call Detach(), the CWnd destructor does it for you. 

Working with both idioms is actually quite easy. The sample application I created already uses the first idiom to create the main windows and the view windows. Even though view windows are child windows, use the first idiom to create them. The first idiom is also used for the status bar and toolbar in the main window. 

You can also use the second idiom to add a control variable to the search dialog. Use the ClassWizard to create a dialog member variable that represents the edit control. The edit control is attached to the existing window in the Search dialog's OnInitDialog, and Windows creates it when creating the dialog box. MFC creates the C++ object and attaches it to the existing Windows control in the search dialog's DoDataExchange. The C++ object is a CEdit object, and MFC has a different C++ object for each Win32 Window class. The CEdit class supports all the window messages that a CEdit object would support. 

MFC also has a set of utility classes that wrap Windows data structures: CRect, CPoint, and CSize. Use these classes to simplify programming with the corresponding Windows data structures. These are small and lightweight classes that provide you with a more object-oriented framework when working with existing Windows structures. These classes include a set of methods that manipulate the data inside the Windows data structures, and they internally call Win32 API functions that manipulate these structures. The structures are derived from the Windows data structures RECT, POINT, and SIZE, respectively. Notice that it is legal for C++ to derive a class from a C language struct. RECT is defined in wtypes.h like this: 

typedef struct  tagRECT
    {
    LONG left;
    LONG top;
    LONG right;
    LONG bottom;
    }   RECT; 
CRect is defined in afxwin.h as: 
class CRect : public tagRECT
{
public:
   // ...
};
The data members from the tagRECT struct (also known as a RECT) are public members of the CRect class, by virtue of inheritance. CRect simply adds a lengthy list of member functions that simplify working with this data structure. The same strategy applies to CPoint and CSize. 
MFC provides the application framework and a way to work easily with Windows UI elements, but you are still responsible for manipulating your application's data. MFC's utility classes make that easier. The last portion of MFC contains utility classes, which help you manipulate your app's data. They're not as powerful as the C++ standard library, but they're useful and easier to work with. These classes aren't specific to Windows GUI applications, and you can use them in console programs. First, consider CString, which is an abstract representation of a string of characters. Choosing between CString and the C++ standard library string has caused considerable debate, but you need to work with CString in MFC programs. 

The simplest approach is to use a string class�either CString or std::string�whenever you need to manipulate character data. These string classes handle all the dynamic memory management for you, and provide a large number of member functions to manipulate the character data. 

MFC also contains a number of classes that implement fundamental data structures. These collection classes come in two flavors: One creates reference-based collections that store pointers to objects derived from CObject; the other is a set of templates that provides the same familiar interface. Just like CString, the C++ standard library has its own collection classes provided by the STL. You can cite legitimate reasons to choose either collection class in your programs, but once again, the simplest way is to use one of the data structures already provided for you. The collection classes save you considerable development time, and are already debugged. 

MFC has kept pace with quite a few changes in the language, Windows, and object-oriented techniques. It started as a library for Windows 3.1 applications, using a compiler that didn't support many modern C++ features at a time when the vast majority of coders had little C++ experience. Since then, the compiler has moved forward and is close to standard C++ compliance, including exceptions and reasonable template support. The object-oriented design community has grown and matured. Over that time, many features have been added to the library. So it's worth your while to read through some of the references and become more familiar with MFC. You'll find large portions I didn't even mention�so I will return to MFC and devote an entire series to it. 


Bill Wagner is a founder of Midwest Seas Software Development Inc. Bill has several years of experience in Windows and C++ programming. He specializes in C++, Java, and COM-based enterprise-programming solutions. He has taught several classes for developers using C++, Visual C++ tools, and MFC, and has spoken at VCDC. E-mail him at wwagner@midwestseas.com
 


c0Title: Pragmas, Linker Options, and WTL
c1Code:
June 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/06jun00/ap0600/ap0600.asp

by Andy Harding 


   Q.Debugging Dilemma 
Can I debug a Win32 console application without debugging through the standard library functions, such as cout, printf, and so on? I just want to step through my code. 
What you need:
Visual C++ 6.0 
MS Platform SDK, 
January 2000 or later  
 
A. Yes. The problem you're experiencing happens when you link with the standard libraries' debug versions, instead of the release versions. To fix the situation, you have to change the libraries you link with. To do this, first determine which standard libraries you're using. With so many standard libraries included with Visual C++ 6.0, it's difficult to know (see Table 1). You must consider these items:



Are you linking to the static libraries or the DLL versions? 
Is your application multithreaded or single-threaded? 
Which version of cout are you using: the old I/O stream class or the newer version found in the Standard Template Library (STL)? 
Do you want the debug or the release versions? 
Fortunately, you know the answer to the last question already. To figure out the answers to the other questions, you need some code. This console-application code allows you to step into the functions from the standard libraries: 


#include "stdafx.h"
#include <iostream.h>

int main(int argc, char* argv[]) 
{
   printf("Hello World!\n");
   cout << "What a crazy place" <<
      endl;
   return 0;
}

By looking at #include <iostream.h>, you know you're using the old-style I/O stream classes. If you included <iostream>, you'd be using the newer standard C++ library. But you still have two unanswered questions on the list. You can find the information needed to answer the remaining in the Project Settings dialog, but an easier way to find out what you're linking to is to let the linker show you. 

   
Figure 1 Customize Linker Options Click here.

 

In the Project Settings dialog's Link tab, you'll see a Customize option in the drop-down listbox, along with the "Print progress messages" checkbox (see Figure 1). With this option selected, the linker keeps you informed every step of the way while it's linking. This is an excellent way to get to know the linker functions. A warning to squeamish readers: The output is long and verbose, so this feature might not be for you. For the preceding three-line app, the linker gave 654 lines of output. Here are the important lines showing what libraries are being linked to in the console app: 



Found _printf
      Referenced in testliblink.obj
      Loaded libcd.lib(printf.obj)

Found "class ostream_withassign cout"
      (?cout@@3Vostream_withassign@@A)
      Referenced in testliblink.obj
      Loaded libcid.lib(iostrini.obj)

From the linker's output, you can see that your Win32 console application uses the single-threaded static library (libcd.lib) for the printf function, and the old-style I/O stream classes (libcid.lib) for the cout class. To change the default general-linker settings so they're not linking in the debug versions, check the "Ignore all default libraries" checkbox. This doesn't mean you don't want to use the default libraries, rather that you prefer to list them yourself. After checking the checkbox, add the names of the libraries your application uses in the "Object/library modules" edit box. Now you can debug just your code, even if you hit the step-in key (F11) when you meant to step over (F10). 

Q.Linking in a Library 
Can I include libraries for linking in a library without changing the Project Settings dialog? At work, our build process uses makefiles. I'd like to use some Visual C++ features, but they require Developer Studio Project (DSP) files. Every time the application's configuration changes, I have to spend extra time updating my personal DSPs. 


A. You can if you're not afraid of using pragmas. The answer to your question involves linker comments, inserted into the source file using this: 



#pragma comment (opt �)


Linker comments are a great way of guaranteeing that your code links with the proper libraries. For example, look at a project with one EXE, myprog.exe, and one DLL, mylib.dll. To make these files link every time, place this linker comment in the source for myprog.exe: 


#pragma comment (lib, "mylib.lib")

This forces the linker to look at mylib.lib when attempting to resolve external references. You can also use a #pragma comment to insert linker options into your source code files: #pragma comment (linker, "/option"), where option represents an actual linker option. Use this code to turn on the linker's verbose option without modifying your project settings or your makefile: 


#pragma comment (linker, "/verbose")


This option allows you to be flexible when creating apps that build in different building environments. However, you need to solve certain implementation shortcomings when you use #pragma comment. For example, when you try to place the linker option /libpath:path into your object file, the linker option seems to work without any warnings (because the /libpath linker option is completely unsupported from the comment pragma), but it's actually not working. The MSDN and VC++ documentation imply that any linker command should work when placed in an object file this way. The documentation even provides a link to the full list of command-line linker options. But that idea never made it into the actual code for the linker: 


// This pragma does not work!!!
#pragma comment (linker, "/libpath:..\libdir")

While researching, I discovered some interesting history about the comment pragma linker option. Before the linker option was added to #pragma comment, programmers discovered a new technique allowing them to add linker options directly into the object code. In VC++ 2.x, extending the lib option gave the desired result: 


#pragma comment (lib, "mylib /verbose")


This was definitely a hack, but it worked. When the linker started to link, it spit out the progress information because the linker recognized the /verbose tag in the object file. When Microsoft introduced VC++ 4.x, the linker began giving an error stating it couldn't open "mylib /verbose." Microsoft then added the linker option, so now you can use this: 


#pragma comment (linker, "/verbose")

However, Microsoft stopped here. Although the company provided a workaround, it didn't fully design and test #pragma comment (linker, "/option") beyond a few simple linker options, nor did it provide an official list of what is supported. The only way to determine whether what you want to do will work is by trial and error. Maybe Microsoft will fix this problem in VC++'s next version. We can always hope. Until then, you need to update the additional library paths in the Project Settings dialog's Linker Input section. 

Q.ATL Add-Ons? 
Does Active Template Library (ATL) include any add-on components or classes, or any built-in support to implement CMenu-type features? 


A. Yes, ever since Microsoft's January 2000 Platform SDK came out. This is the first official release of Windows Template Library (WTL), an ATL add-on. WTL gives ATL decent GDI support, something it only had partially and unofficially until now. WTL's menu support isn't as neatly wrapped as the CMenu class, but it's more powerful. 

WTL, which follows the Windows CE model, gives you command bars through toolbars and rebars. Command bars are an excellent idea because you now can add items other than buttons and menus, such as drop-down lists where a plain old menu used to be. WTL gives you the look-and-feel of high-quality apps, without adding a ton of Win32 GDI calls. Note that WTL doesn't create a system-level class for the command bars as Windows CE does. 

Another excellent feature added in WTL is a new application type called Multiple Threaded SDI. This feature allows an SDI application to launch another window identical to the first, but with another document. When an application uses the Multiple Threaded SDI model, each window seems to be in a separate process, but it's actually one process with each window running on a separate thread. 

With the new stuff, documentation is sparse, and WTL is no exception. (See Resources for two exceptions.) WTL presents a new and powerful set of tools for ATL programmers. Look forward to hearing more about WTL in the future. 

Q.I Want My ATL! 
I am very excited about WTL. Where can I get it? 

A. WTL comes with Microsoft's Platform SDK, editions January 2000 and later (see Links). Installing the program requires the new Windows Installer 1.1, so you might have to upgrade that first before you can install the new platform. Another item worth mentioning: The entire platform is about 1.3 GB�a lot to download on a 56K modem. Some of Windows Installer's new features are great, but I had problems making it work. Still, WTL is worth the effort. 


Andy Harding is a software engineer at BSQUARE (NASDAQ: BSQR). He enjoys debugging legacy spaghetti code, working with unreasonable time frames, and the occasional game of Half-Life. Surprisingly, BSquare enjoys paying him to deal with it. He also likes answering questions, so if you have a good one, send it to him at andyh@bsquare.com
 


c0Title: Use interfaces in your C++ programs to simplify maintenance
c1Code:
November/December 1999
 
http://www.devx.com/premier/mgznarch/vcdj/1999/11nov99/mp1199/mp1199.asp
Program for Change 

by Michael L. Perry 


  The ultimate test of any programming technique is how well it supports change. Any software project of appreciable size or functionality undergoes many requirement, design, and implementation changes� even before its first release. Many programming techniques have been devised to help ease the impact of these changes, but you can achieve the most return for your time investment using interfaces. 
System notes

To replicate the steps described in this article, you will need:
  ++ Visual C++ 5.0 or 6.0  
 
Interfaces ease software development by supporting change. They enable you to package many services or interpretations of a single service, so you don't need to change the client code when you add new implementations. Interfaces also provide a superior alternative to function pointers by encapsulating context information, and they offer a simple and powerful way to query for a service. 

An interface is defined as a contract between an object and its clients that the object implements and the clients can invoke. The contract has three parts: It defines a set of operations, it defines a set of other interfaces, and it provides the object's identity. In this article, I'll walk you through how to use C++'s interfaces to mitigate the effect of changes in your projects; I'll also show you how to define an interface by demonstrating the C++ syntax for displaying an interface, and presenting several examples that illustrate how to use various techniques of interface use, each with a code sample and an explanation that covers how a given technique supports change. These techniques include multiple inheritance, callback interfaces, dynamic casts, and factoring. 

You can acquire a simple Single Document Interface (SDI) app called Intercpp that I created to illustrate the concepts discussed in this article here. I used Visual C++ 5.0's ClassWizard to generate an MFC app that lets you swap out the main frame window on-the-fly, enabling the app to exhibit browser-like behavior. The frame sports a button control bar that interacts with the active view. It also displays a column of bitmaps that becomes highlighted as the user moves and clicks the mouse, dims as the buttons become inactive, and responds to a click or an accelerator key with appropriate action. The button bitmaps use a rounded rectangle design�mainly because they're easy to draw. 

The techniques described here are useful when your project doesn't require reference counting, marshaling, or other COM services. They work directly in C++, don't take advantage of Interface Definition Language (IDL), don't require GUIDs, and don't use any COM interfaces such as IUnknown (see Table 1). However, the techniques do require that you adopt a specific approach to object design. Deciding whether to use C++ or COM interfaces usually boils down to a couple of easy-to-sort-through criteria. You should use C++ interfaces only in cases where the interfaces appear exclusively within your code and you're working solely in C++. The advantages of using interfaces might not be obvious because the payoff occurs later in the development cycle, most notably during maintenance, where programmers typically spend most of their development time. Yes, you spend some of this maintenance time fixing bugs, but you probably devote more time to adding those unplanned features the user simply can't live without. Minimizing the impact of these changes on the system as a whole enables you to avoid many hours of debugging and rewriting. 

Why you need interfaces
Let's begin by assuming you've written a system that doesn't use interfaces. Each object's client refers to that object by name and calls its methods directly. Now suppose your user asks for a new option. He or she wants to choose on-the-fly whether your object will work as originally planned or in some new and much more useful way. You want to accommodate your user, so you decide to implement a new object that shares a common base class with your original object to implement this specialized behavior. However, this means you must modify all the original object's clients to use the base class instead. It also means you must check out most of the source files, which prevents your teammates from finishing their work. You make massive code changes, only to realize you've introduced three new bugs into the process. 

Now assume you created the same system using interfaces. This means you've already hidden your object behind a thin wall, isolating the object's code. It also means you've packaged your object's services in such a way that only the essential messages pass in and out. Making the changes your client wants requires only that you add a new object that implements the same interface, then change only the code that creates the object. All other client code remains untouched, so you minimize the impact of your changes. In fact, your teammates can continue to develop using the original object, completely oblivious to your changes until they sync up their source code two weeks later. Everything works fine, even when they sync up, because their code made no assumptions about the object's implementation; their code simply used the established interface. 

You need look no further than COM for a good example of how well interfaces support change. COM evolved in a short period of time from a means of writing OLE compound documents to a foundation for creating enterprise-level solutions. It offered some basic services from the beginning, including reference counting, cross-thread and interprocess communication, and late binding. Now it offers such advanced features as network and Internet communication, transaction and resource management, and cross-language development. The source of its power derives from the fact that, at its core, COM is based on interfaces. Indeed, interfaces are so powerful, Java's designers incorporated them directly into the language. However, any language capable of polymorphism is also capable of interfaces in some form. 

An interface's first contract responsibility is to define a set of operations, possibly empty, that the class implements, and the client can invoke. The class accepts responsibility for implementing these operations. An interface's second responsibility, defining a set of other interfaces, relates to inheritance of other interfaces. Any type cast of an interface to a base interface is guaranteed to succeed (see the sidebar, "C++ Code Glossary"). Finally, an interface provides the object's identity. The identity gives the client control over the object itself, not just a copy. 

How C++ interfaces work
An interface takes the form of an abstract base class in C++. All methods are declared as pure virtual, with the exception of the destructor, if present (see the sidebar, "C++ Code Glossary"). The destructor is present only if the interface is intended for its owner, which is responsible for creating, managing, and deleting an object. A factory class is a good example of an interface intended for its owner (see Listing 1). 

The client invokes MakeThing to create an object on its behalf and manipulates the object through its IThing interface. The client doesn't know the particular class used to implement the interface, but it's still the owner and is responsible for the class's destruction. Therefore, the IThing interface has a virtual destructor with an empty implementation, which permits the client to use the delete operator. 

An interface class inherits only other interfaces; it has no members and no implementation, and it doesn't inherit members or implementation from its base classes. However, the C++ language doesn't enforce these rules, so you must be disciplined. For example, consider this code, which provides an interface for a button handler: 


class IButtonHandler
{
public:
   virtual bool IsActive() = 0;
   virtual void OnClick() = 0;
};
The code defines two methods: one that responds when the button is clicked on, and another that determines whether the button is active. This interface has no destructor because the holder (client) of this interface is not its owner. 

A class implements an interface through inheritance. The example class CViewWithOneButton implements the button handler interface, and the button control bar receives an interface pointer as implemented by an object of this class. The button control bar can then call its members, both to determine whether the button is active and to respond to a click or accelerator key: 


bool CViewWithOneButton::IsActive()
{
   // The button is always active.
   return true;
}

void CViewWithOneButton::OnClick()
{
   // Return to the main view.
   SwitchView(
      RUNTIME_CLASS(CIntercppView) );
}
This button view is quaint, but it is not particularly useful. A typical view would handle more buttons, although there is no practical limit to how many interfaces a class can implement. You create multiple buttons through multiple inheritance, a technique that makes good programmers cringe in most cases. However, multiple inheritance is perfectly acceptable with interface inheritance. Interfaces have no members or implementation, so there is no danger of inheriting two copies of a member or a method. Therefore, you have no need for virtual inheritance (see the sidebar, "C++ Code Glossary") when using this technique. If two interfaces define methods with the same signature, both have the same implementation. The only danger you face is that two signatures might be alike, except for their return values. You get a compiler error when a class that inherits both interfaces attempts to implement either method. 

However, it's possible to construct a class so it implements the same interface in different ways. Do this by defining an interpreter class for each different implementation of the interface the class provides. An interpreter is an intermediate class that works somewhat like an interface and somewhat like a class. It implements an interface by redirecting the method calls to other pure virtual methods. 

Put multiple inheritance to work
Now, put multiple inheritance and interpreters to work by defining a view that handles several buttons. First, write an interpreter for the Copy button: 


class IButtonHandlerCopy :
   public IButtonHandler
{
public:
   bool IsActive()
   {
      return IsActiveCopy();
   }
   void OnClick()
   {
      OnClickCopy();
   }
   virtual bool IsActiveCopy() = 0;
   
virtual void OnClickCopy() = 0;
};
Writing a class that handles several buttons requires that you create one interpreter class for each button, then use multiple inheritance to generate one class that implements them all. Use a macro to simplify creating the interpreters: 


#define DEFINE_BUTTON_HANDLER(s) \
class IButtonHandler##s : \
   public IButtonHandler \
{ \
public: \
   bool IsActive() \
   { \
      return IsActive##s(); \
   } \
   void OnClick() \
   { \
      OnClick##s(); \
   } \
   virtual bool IsActive##s() = 0; \
   virtual void OnClick##s() = 0; \
};
The example class "CViewWithManyButtons" defines an interpreter for each button the view handles, employing multiple inheritance to implement each one. The view class uses private inheritance to implement these interfaces because the view class itself distributes these interfaces. It is neither necessary nor desirable for other classes to cast a view object to one of the button interpreter base classes (see Listing 2). 

You are probably aware that you can use message maps to achieve similar results, as in MFC. However, there are at least two reasons why interface interpreters support change better. First, a message map is nothing more than an array of member function pointers, so each entry maps to just one function. The multiple inheritance example demonstrates how it's sometimes useful to group functions together in a cohesive set. Each menu item you add to your application requires only that you tell the wizard to generate one new interpreter, rather than both the ON_COMMAND and ON_UPDATE_COMMAND_UI macros. Second, you cannot create message map entries as objects themselves. The caller requires both the object pointer and the member pointer invoke an object method through a pointer. The client must know the object pointer type, so this limits the set of classes you can use to implement the behavior. However, the interface itself holds the identity of the object, so only the interface pointer is required. Additionally, any class can implement the interface. Your existing code can use new classes through interfaces as you add them to the system. 

Improve on function pointers
It also makes sense to implement callbacks�once the exclusive realm of function pointers�with interfaces. An object implements a set of methods that should only be called in response to a request. In this case, the object distributes its own interface pointer using private inheritance. The object passes the interface pointer to the client as an argument to a method call. The client uses the interface within the method, but doesn't store it. 

For example, you might have an interface that defines a pair of callbacks to collect the set of buttons the view handles: 


class IButtonHandlerSet
{

public:
   virtual void AddButton(
      UINT idImage, int nKeyCode,
      IButtonHandler *pButton) = 0;
   virtual void AddSeparator() = 0;
};
The class CViewWithManyButtons uses this interface within the GetButtons method. Note how it casts itself to each of the interpreter base classes before passing the pointer to the AddButton callback function: 


void CViewWithManyButtons::GetButtons(
   IButtonHandlerSet *pButtonSet)
{
   // Add buttons to the control bar.
   pButtonSet->AddButton(
      IDB_CUT,   'T',
      (IButtonHandlerCut   *)this );
   pButtonSet->AddButton(
      IDB_COPY,  'C',
      (IButtonHandlerCopy  *)this );
   pButtonSet->AddButton(
      IDB_PASTE, 'P',
      (IButtonHandlerPaste *)this );
   pButtonSet->AddSeparator();
   pButtonSet->AddButton(
      IDB_DONE,  'D',
      (IButtonHandlerDone  *)this );
}
Callback functions usually require some context information. Sometimes, programmers store this information in global variables when using function pointers. However, global variables cause many problems, including nonreentrancy, which prevents threading, and persistence of outdated information, which introduces avoidable bugs. Other times, programmers store the context information in a structure, the pointer to which is cast to void *. This is easier to maintain than its global counterpart, but you should eliminate unprotected type casts, if possible. 

The class that implements the callback interface in the example holds the context information. This class can be either the caller itself (as in the example) or a reusable class that many callers use. The class doesn't use global variables, so you can add thread support easily. Also, encapsulating the data means your app will destroy outdated information, introducing fewer bugs as the system grows. Therefore, interfaces support change better than function pointers do. 

This example also demonstrates that an interface can represent a set of cohesive callbacks. Accomplishing the same thing with function pointers requires the caller to pass multiple function pointers as parameters. Then, you have to coordinate the actions of two or more independent functions. Encapsulating these callbacks in one interface, which you implement using one class, documents the callbacks' intended cohesiveness and simplifies their coordination. 

Another excellent use of interfaces is to expose special services implemented by some objects. A client can query the object to determine whether it implements a particular service. You do this in COM using QueryInterface, but C++ doesn't provide you the luxury of IUnknown. You could create your own IUnknown, but today's compilers offer something that fits the bill much more nicely: the dynamic_cast operator. This operator performs a down-cast, which, unlike an up-cast, isn't guaranteed to yield an interface pointer. Fortunately, it fails in a predictable way. The dynamic_cast operator returns a pointer if the object inherits the requested class, and returns NULL otherwise. 

   
Figure 1 Project settings show the RTTI option. Click here.

 
Use RTTI with care
You must turn on run-time type information (RTTI) to use this operator (see Figure 1). This flag adds extra baggage to every class, so its default setting is off. However, enabling the compiler to check casts automatically at run time adds a simplicity and robustness that far outweighs the extra overhead. 

Some might argue that run-time type information violates one or more of the principles of object-oriented design. Many of RTTI's opponents are the same programmers who eschew multiple inheritance. RTTI is similar to multiple inheritance because it's possible to use the technique poorly, but most potential problems disappear when you use it with interfaces. 

One way to misuse RTTI is to determine what class is used to implement an interface and respond accordingly. For example, a view controller might use the typeid operator to determine the exact type of an object in the document, then create a user interface object specific to that type. A well-designed interface would make such knowledge unnecessary because the object itself, not the client, would implement any specialized behavior. Instead, the view controller could use the visitor pattern to send an interface to the object and to enable it to choose from several options (see Resources). The visitor interface grows as you add new document objects and their corresponding user interface objects to the system. The compiler verifies that all classes implementing the interface pick up any new methods. The RTTI solution doesn't enroll the compiler's support, so it doesn't support change as well as the visitor pattern. 

However, a client that uses RTTI to cast to an interface pointer dynamically queries for a service, not an implementation. New classes can come along and implement these services, and the client will work just as well with them. 

A view implements this interface to handle buttons: 


class IButtonView
{
public:
   virtual void GetButtons(
      IButtonHandlerSet *pButtonSet)=0;
};
Note that only views requiring a button bar implement this interface. 

I've mentioned that the main frame window swaps out views on-the-fly, giving the application a browser-like appearance. When it does so, it queries the new view object to determine whether the button interface is present. If it is, it passes the interface off to the button control bar that displays these buttons and interacts with the view when the user clicks on them. If the interface isn't present, the main frame window passes in a NULL pointer and hides the button control bar (see Listing 3). 

You might find yourself designing interfaces that offer two or more disparate services simply because you usually implement them with the same object. This is often dangerous because what you "usually" do tends to become something you "sometimes" or "rarely" do as a system matures. It's always best to take a few extra keystrokes and factor your interfaces as soon as you notice they're noncohesive. 

The Intercpp code example to which I referred earlier comes from a medical insurance application. The original incarnation of the button view interface incorporated methods that exposed patient information, which it displayed in a title control bar. This made the interface difficult to use on views that didn't need to expose patient information. Therefore, I split these methods off and formed a new interface for patient title information only. Now the button control bar and the title control bar use different interfaces. A View class can choose to implement one or both of these interfaces. It's possible I'll need different title information in the future, in which case I can add a second title control bar, and hide or show either control bar based on the presence or absence of their respective interfaces. Using interfaces makes such updates quick, easy, and relatively painless. 


Michael L. Perry is a software developer with six years of industry experience. As the founder of Mallard Software Designs Inc., Michael strives to make sound development practices more commonplace in the software community. For more information, please visit the Mallard Web site at www.mallardsoft.com. Reach Michael at mperry@mallardsoft.com
 


c0Title: Reformat Extracted ODBC Data
c1Code:
July 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/07jul00/bb0007/bb0007.asp
Learn to access ODBC data and format it into SQL INSERT statements. 

by Tom Creighton 


   In the first of this two-part series on creating an ODBC-based data-extraction utility, I described the actual utility program and the object hierarchy used to implement the extraction. In this second part, I'll show you how to extract the data and format it into SQL INSERT statements. In this simple program, all the work happens in a set of objects you can use in a variety of ways, not just in the extract utility. To refresh your memory, look at the object model in Figure 1 in last month's column (see Resources). 
What you need:
Visual C++ 6.0
ODBC 3.0  
 

Before we start, quickly review last month's code. The program's main() function collects command-line parameters, instantiates a CTETableDump object, loads the parametric data (Data Source Name, and so on) into the object, and calls the method CTETableDump::ExtractTo(), specifying stdout as the parameter. The ExtractTo() method connects to the database through CTETableExtract::Connect(), and issues the SQL statement through a call to CTETableExtract::Execute(). Then, for each record in the resultset, the ExtractTo() method calls CTESQLExtract::GetNextRecord(). The rest of this article describes what happens in GetNextRecord and in the methods it calls. 

You can use the classes CTETableExtract and CTESQLExtract to get data out of a relational database, then use the data however you want�you can create reports from it, for example. That's why the CTETableExtract's interface is at the database-field level, while CTESQLExtract's is at the SQL-statement level. In last month's column, I pointed out that you could use CTETableExtract to extract the data and reformat it into XML or CSV file format. Besides XML or CSV files, you could produce output reports based on CTETableExtractderived data. Here, though, you'll use the classes to produce SQL INSERT statements from the recordset returned from your query. 

Note the CTESQLExtract declaration in Listing 1. The method implementations for the properties are inline, and the rest are shown in Listing 2. Only the GetNextRecord() method does anything interesting in this class. You retrieve field data from the cursor established in the call to SQLExecDirect. After retrieving the field data, GetNextRecord() must format it into a SQL INSERT statement. GetNextRecord() declares one formal parameter, Record, a reference to a string. The method places the resulting SQL INSERT statement here: 


GetNextRecord (string & Record);
To retrieve a row's worth of data from the ODBC driver, GetNextRecord() calls CTETableExtract::FetchNextRecord(). FetchNextRecord() is a simple wrapper for the ODBC function SQLFetch(). It adds some error handling and reporting, but basically says, "Go get the next record." It might help you to remember an INSERT statement's general syntax: 


Insert Into <TableName>
(<Col1 Name>, <Col2 Name>, ... <ColN Name>)
Values (<Col1 Value>, <Col2 Value>, ... <ColN Value>)
Pseudocode for GetNextRecord() looks like this: 


RetCode = FetchNextRecord();
if (TE_OK == RetCode)
{
   for (int i = 1; i <= mcColumns; i++)
   {
      // For each column, try to retrieve a value.
      <Get the column's Name>
      <Get the column's Type>
      <Get the column's Value>
      <If the column's value is not null, add the name 
      to the column name list of the INSERT statement, 
      reformat the column's value to a string and
      decorate it according to SQL syntax rules 
      (quotes, etc.)>
   }
}
<Loop to get the next record until done>
If you look closely at the implementation code in Listing 2, and if you're familiar with ODBC programming, you'll notice I didn't write a bind call (SQLBindCol). Binding tells the database (in this case, ODBC tells the driver) what to do with each column value for each row retrieved with a call to SQLFetch(). Normally, you do this before the call to fetch a row, but I didn't code it that way for several reasons. 

First, I didn't want to explain binding in detail. Second, I don't know beforehand how the data will be used (speaking from the perspective of CTETableExtract), so it might be just as efficient to code generalized access to column data after the fetch, rather than binding ahead of time. Besides, binding makes more sense when I know at coding time what my record layout is. In this case, it can't be known. Finally, I'd have to handle null data differently. These factors led me to code calls to SQLGetData(), rather than SQLBindCol(). 

After retrieving a row of data from the database cursor into the ODBC driver buffers by calling SQLFetch() from within CTETableExtract::FetchNextRecord(), GetNextRecord() retrieves the data one field at a time through calls to SQLGetData(). Any column might have a null value for the current row, so you must handle that case as well. CTETableExtract::Execute() stores the column count in the private data member CTETableExtract::mp_cColumns. GetNextRecord() retrieves this value through the property mcColumns. For each column, GetNextRecord() inspects the column type and gets the column data. It does this in one step by calling CTETableExtract::GetColumnData(). (I'll examine GetColumnData() in more detail later.) This GetNextRecord() code snippet shows the call to GetColumnData inside a loop bound by mcColumns: 


if (TE_OK == RetCode)
{
   for (   int i = 1; 
            i <= mcColumns; i++)
   {
   // For each column, try to retrieve a value.

      RetCode = 
         GetColumnData(i, ColumnName, 
            ColType, ColumnValue);
      if (TE_OK == RetCode)
      {
      <Handle the different data types here. Produce column list and value list >
      }         
   }
...
In this code snippet, you handle each column with a valid return from GetColumnData(). One possible return value is TE_NULL_DATA. If that's returned, it means the current row has no data for the current field, so you simply leave out the column name and value from the lists. 

Adding the Column Name
Now that GetNextRecord() has a column's data back from GetColumnData(), it can add the column's name to the ColNamesClause variable and its value to the ValuesClause variable. Of course, if GetNextRecord() has already added one or more column values, it needs to first append a comma to each list. String types and timestamp types each have single quote marks around them in SQL. GetNextRecord() generates the leading quote for the column data if it's a string. 

Assuming that GetNextRecord() retrieves the column data without error (and that it wasn't null), it then formulates the INSERT statement. Look at the sample output to refresh your memory of the SQL INSERT statement (see Listing 3). The data extraction tool's output looks like this when run with the sample data shown in Table 1. In GetNextRecord(), you build the statement in three parts, each within its own string variable. The InsertClause variable holds the statement's INSERT portion, including the table name. The ValuesClause variable holds the part that lists the values, while the ColNamesClause variable holds the column names list. 

If a column's value is null, it's not included in the INSERT statement. You don't want to list its name in the names list with an empty string�simply leave it out. Also, this implementation is limited to supporting integer numbers, character strings, and timestamps, which combine the date and time. I limited the datatypes to make it easier to see what's going on. You should be able to easily extend the code to enable other types. 

The next snippet from GetNextRecord() shows how the two "accumulator" variables, ColNamesClause and ValuesClause, collect their values. Notice that the InsertClause variable combines the key phrase "Insert Into" and the target table's name: 


string InsertClause =
 "Insert into " + mDestTableName;
string ColNamesClause = "(";
string ValuesClause = "Values(";
      ...
if (cGeneratedFields > 0)
{
ColNamesClause         += ", ";
   ValuesClause      += ", ";
}
ColNamesClause   += ColumnName;
if (eDateTime == ColType)
// dates have the ts function
{
   ValuesClause   += "{ts ";
}
if (eDateTime == ColType ||
   eString == ColType)
// dates and strings have quotes
{
   ValuesClause   += "'";
}
// Append the actual value of the data
ValuesClause   += ColumnValue;   
if (eDateTime == ColType || 
    eString == ColType)
// dates and strings have quotes
{
   ValuesClause   += "'";
}
if (eDateTime == ColType)   
// dates have the ts function
{
   ValuesClause   += "}";
}
cGeneratedFields++;
ColNamesClause         += ")";
ValuesClause         += ")";
Record =   InsertClause   + "\n" +
         ColNamesClause   + "\n" +
         ValuesClause;

CTETableExtract::GetNextRecord(Record);
This snippet wraps up the INSERT statement construction. You append the three clauses together. The extra new-line characters between each clause make it easier to read, in case you need to read the SQL in the output file. Of course, from your class's perspective, the output might not be headed for a file, but in any case it's easier to read with the new-line characters. 

At the end of CTESQLExtract::GetNextRecord(), you'll notice a call to CTETableExtract::GetNextRecord(). I first designed CTETableExtract as an abstract base class, with GetNextRecord() as pure virtual. Then I realized that knowing how many rows had been processed at any given moment could be useful. I also realized that GetNextRecord() in the base class is a good place to record that information, independent of the derived classes' implementations of GetNextRecord(). About the only thing you'll see in CTETableExtract:: GetNextRecord() is the instruction mcRows += 1. Properties don't seem to get along with the postfix ++ operator, so I coded it with += instead (see the sidebar, "C++ Class Properties"). 

If GetNextRecord() detects a timestamp column type, it produces the appropriate formatting characters around the data. In this case, I chose to use ODBC's TimeStamp function (see the sidebar, "The Great Escape Sequence"). If you have more columns to retrieve, GetNextRecord goes back and handles the next one. 

Details, Details
Look under the covers of CTETableExtract::GetColumnData(). GetColumnData() gets the column's type from GetColumnType() (returned in the parameter ColumnType); the column's name from SQLGetColAttribute(); and the column's value converted to a string format from GetField() (see Listing 4). 

ODBC defines a set of manifest constants to indicate column types. I've defined a subset of those column types in an enumerated type called eColumnType. In the method GetColumnType(), treat the column type as the enumerated type eColumnType. Here's the declaration of eColumnType: 


typedef enum _eColumnType
{
   eDateTime,
   eInteger,
   eString
} eColumnType;
As you can see, I've created enumerations only for the datatypes I support. If you decide to add support for new datatypes, you have to extend this declaration. 

GetColumnType() is overloaded. I've declared two implementations: The first is public; the second, protected. Here are their prototypes: 


public:
virtual TERetType GetColumnType
   (   TEUShort          ColumnID, 
      eColumnType & ColType);
protected:
virtual TERetType GetColumnType
   (   TEUShort      ColumnID,
      TEShort & ColumnType);
I'll refer to the public version as GetColumnType1 and the protected as GetColumnType2, for convenience. As you can see from GetColumnType1's prototype, you use it to retrieve a given column's type in terms of the enumeration (see Listing 5). GetColumnType2 hides the details of retrieving the column's datatype from ODBC (see Listing 6). 

To retrieve either the column's name or type from ODBC, use the ODBC function SQLColAttribute(). You can retrieve much information about a column through this function. Using it can be a bit confusing, because you either get a character string or an integer returned, depending on the value passed in as the third parameter (the FieldIdentifier, in this case). Make sure you have the right kind of buffers ready to catch the data when it comes back. 

You'll notice that SQLColAttribute() is called only from GetColumnType2. GetColumnType2 retrieves the actual column type from the ODBC driver and verifies the returned type is the one you support. The type ID returned from SQLColAttribute is also returned from GetColumnType2. GetColumnType1 then maps that value into the appropriate enumeration. 

You can see another call to SQLColAttribute() in GetColumnData(). Notice that in this case, you're asking for the column's name, called FieldName in the code. The column might have no name, depending on how a driver handles things such as aggregation functions or calculated fields in absence of an alias. If the column has no name, the code simply gives up on it, and the column is skipped in the SQL generation code (see Listing 7). You can improve this by inventing a column name inside GetColumnData(). You might use the column identifier to create a name, such as "Colx," where x represents the column identifier. While that probably wouldn't work by itself at insert time, you could easily modify the resulting string in a text editor. 

Retrieve the Column Data
To retrieve the actual column data, GetColumnData() calls the GetField() method, passing a reference to the string variable that receives the column data. Notice that GetField() is overloaded for each datatype you support. Here's the prototype for each version of GetField: 


virtual TERetType GetField (
      TEUShort      ColumnID,
      int &      Field);
virtual TERetType GetField (
      TEUShort      ColumnID,
      string &      Field);
virtual TERetType GetField (
      TEUShort      ColumnID,
      CTEDateTime & Field);
Each version of GetField checks what the actual column datatype is, determines whether that matches the datatype it supports or whether there's a reasonable conversion to the datatype it supports, then gets and converts the data. Because each GetField() method calls GetColumnType(), and because the type has been determined by now in any event, it's more efficient to store the column type in a class variable and check there, rather than calling ODBC each time the type is needed. I leave you to implement that efficiency. 

GetColumnData() retrieves column data in string format. If you want to write code that extracts data in its native format, call the GetColumnType() and GetField() methods from your own derived class. For this data extraction utility, string-formatted data is exactly what you want. 

Let's look at a case where the requested data format doesn't match the type of data in the database. This happens whenever the extraction utility retrieves data that's stored in the database in a nonstring format such as integer or date. This code snippet shows how the string version of GetField(), or the second of the three prototypes listed earlier, handles requests for column data of integer type: 


case SQL_NUMERIC:
case SQL_DECIMAL:
case SQL_INTEGER:
case SQL_SMALLINT:
   RetCode = GetField(ColumnID, iData);   
// get it in 'native format'
   if (TE_OK == RetCode)
   {
      // Now convert it to a string.
      Field = itoa(iData, Number, 10);
   }
Notice that you first retrieve the data by calling GetField recursively, specifying a retrieval type that matches the column type. Then you perform a data conversion�by calling the system function itoa(), in this case. Be careful: You can write code requesting conversions that make no sense. For example, if you call GetField() to retrieve date/time data, but request the data in integer format, the result will be a return code of TE_UNSUPPORTED_TYPE_CONVERSION. 

When the string form of GetField() is called, if the column data is one of the string forms, no conversion is necessary, so GetField() retrieves the data and places it in the string reference passed in as the Field parameter (see Listing 8). Before actually retrieving the data through a call to ODBC's SQLGetData(), the string version of GetField() must first have a place for the data to be copied. Because SQLGetData() doesn't understand string references, GetField() must allocate a standard C-string. GetField() determines the size needed by calling SQLColAttribute() (yet another use of this function!) and allocates space for the data through a call to calloc(): 


/*   Find the column width and allocate 
   a buffer. */
SQLRetCode = SQLColAttribute(
            mhStmt,
            ColumnID,
            SQL_DESC_LENGTH,
            NULL,
            0,
            NULL,
            & ColWidth);
if (SQL_SUCCEEDED(SQLRetCode))
{
   char * pszData;
   pszData = (char *) 
            calloc(ColWidth + 1,
                  sizeof(SQLCHAR));
   if (pszData)
   {
      SQLINTEGER DataLenOrIndicator;
      // Now go and get the data.
      SQLRetCode = SQLGetData(
                  mhStmt,
                  ColumnID,
                  SQL_C_CHAR,
                  pszData,
                  ColWidth + 1,
                  &DataLenOrIndicator);
GetField() goes through the same process for dates, with just a bit more formatting to represent the date/time as a string (see Listing 9). 

SQLGetData() transfers the column data from the ODBC driver's internal buffer into the program's data space. The driver must support all types of data, so tell it what datatype your variable is�in other words, tell it what data transformation you want. This can be confusing, so I keep it simple and do other data conversions in my own code. In this example, the datatype ODBC knows about is a string (CHAR, VARCHAR, and so on). The SQL_C_CHAR manifest constant tells SQLGetData() you want the data as a null-terminated C-string. 

Notice the last parameter to SQLGetData(), which is a pointer to an integer variable: The formal parameter name is StrLen_or_IndPtr. SQLGetData() places either the length of the data retrieved into the integer variable, or the constant value SQL_NULL_DATA if the column has a null value. You can't indicate a null value simply by truncating the string, so you must inform the GetField() caller through the return code that the column's value is null. If the column data isn't a string, GetField() calls the form of GetField() corresponding to the actual column datatype. After retrieving the data in native format, the string version of GetField() converts it. 

Integers aren't particularly interesting, so let's just look at the Date/Time, or the timestamp version. If the column type is eDateTime, GetField() calls the timestamp version of GetField(). In the timestamp version of GetField(), notice that SQLGetData() retrieves the column data into a structure of type SQL_TIMESTAMP_STRUCT. I could've used this data structure throughout the code for holding date/time information, but I wanted to keep ODBC things strictly hidden within CTETableExtract. I wanted to pass date/time information back in forms other than strings, so I had to come up with my own binary format for the structure. The class CTEDateTime, declared in TEDataTypes.h, works great. I've used this little class for some time. It doesn't validate the dates or time values entered�well, it does a little�but it works well enough for this data-extraction utility. 

Once GetField() (the string version) retrieves the timestamp data as a CTEDateTime object, it must convert that into a string. I could've chosen any format for the date and time. I wanted to produce SQL from the result, so I formatted the date and time in order to create an INSERT statement from it easily. Code at the CTESQLExtract level could request the data by actual column type, then make its own data conversion and formatting, but this approach works here. 

Once GetField() has its data in the correct format, the data is copied into the string reference, returned to GetColumnData(), then ultimately returned back to CTE-SQLExtract::GetNextRecord(). GetNextRecord() runs around getting field data in string format, adding the extra characters needed for an INSERT statement, and appending to the emerging INSERT statement's various classes. When it's finished, the three clauses are appended together and passed back in the string reference. 

Create a Wish List
Naturally, when you finish an application, you think of improvements you can make. First, you could add datatypes. The application needs some kind of floating-point and currency support. Supporting various Binary Large Objects (BLOBs) is difficult, but necessary. Next, you could enhance the SQL handler. Often, you'd like to produce SQL syntax specific to a particular DBMS. As it now stands, CTE-SQLExtract generates INSERT statements with mostly generic syntax. You might want to enhance the SQL handler to enable use of the Oracle TO_DATE function, for example. 

You could also implement more output formats. CSV makes sense, in this context. And some efficiency changes throughout the code would be nice. I mentioned that each GetField() calls GetColumnType(). You could speed that up by caching the column type retrieved by a call to GetColumnType() and returning it upon a subsequent call. The trick: making sure to flush the cache at the right time! Finally, you could enable the proposed SQL= switch so you can use generic queries for extraction, and allow the user to specify a list of tables or queries to process. This move would let the user do several extracts without having to disconnect or reconnect to the DBMS each time. 

You now have a set of object classes that lets you retrieve data from ODBC databases and easily reformat it into any format that suits your needs. You also have some great examples of how to access data at the ODBC level�useful in itself. Finally, you have an example of how to use class derivation to refine access to data successively, and you can tailor that access to specific needs that extend the base classes. 

Tom Creighton, who has worked as a professional software engineer for more than 20 years, consults in database design and Public Key Infrastructure (PKI) development. Tom earned two computer science degrees: a B.S. from Brigham Young University and an M.S. from University of Southern California. Reach him at prohacker47@hotmail.com
 


c0Title: Rich Error Handling and Custom Error Codes
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/1999/octmag99/tipa1.asp  



By Michele Leroux Bustamante

System Notes 
To fully utilize this Tip, you will need: 
Visual C++ 6.0 
ATL 3.0 
 

The best way to present useful information to the clients of your component is to support rich error handling through a dual interface, and to provide custom error codes (or HRESULTs) that indicate the granularity of success or failure. 

COM provides several API functions (Create-ErrorInfo(), SetErrorInfo(), and GetErrorInfo()) and error handling interfaces (IsupportErrorInfo, IcreateErrorInfo, and IerrorInfo) that support COM error handling.

A component can generate a COM exception by creating an error object, associating that error object with the current thread, and then returning an HRESULT indicating an error has occurred. First, your component must implement the IsupportErrorInfo interface to support rich error handling. The CreateErrorInfo() function creates an error object that supports both the IcreateErrorInfo and IerrorInfo COM interfaces. This error object is passed to the SetErrorInfo() function, which associates the error object with the current thread of execution. Of course, for the error to be recognized, your component also must return an appropriate HRESULT indicating failure (discussed below). 

Upon return of one of your component's property or method functions, the client of your component will check the HRESULT and determine how to handle it. The client can then call GetErrorInfo(), which returns the error object set by your component. This only works if the client used VTBL binding (early binding) to connect to your component's interface. 

It is important to note that if a client of your component uses the IDispatch::Invoke() method to call your component's properties and methods, it will check the EXCEPINFO parameter for information about the generated error, in place of GetErrorInfo(). Regardless, your component can still use CreateErrorInfo() and SetErrorInfo() to provide error information through COM. 

Properties and methods supplied by your component should always return a suitable HRESULT to indicate success or failure. Winerror.h provides macros and constants to facilitate the use of HRESULTs.

The MAKE_HRESULT macro enables you to easily generate a custom HRESULT. This macro is defined as follows in winerror.h:

#define MAKE_HRESULT(sev,fac,code) 
	((HRESULT) (((unsigned long)(sev)<<31) |
		((unsigned long)(fac)<<16) 
	| ((unsigned long)(code))) )

 


The first parameter, sev, indicates the severity of the error, which can be one of the following constants:

#define SEVERITY_SUCCESS    0
#define SEVERITY_ERROR      1

 


The severity element of an HRESULT provides greater granularity for both success and failure. This is why clients of your component should always check the severity bit to determine if an HRESULT evaluates success or failure. This can be done using the SUCCEEDED(hr) and FAILED(hr) macros. 

The second parameter, fac, indicates the facility generating the error. For custom HRESULTs generated by any of your component interfaces, the constant FACILITY_ITF (which indicates that a COM interface generated the error) is recommended. This constant is defined in winerror.h (along with numerous other facilities) as follows:

#define FACILITY_ITF        4

 


The last parameter code defines the actual return code for the HRESULT. HRESULT codes can range from 0x0000 to 0xFFFF. HRESULTs within the range 0x0000 to 0x01FF have already been defined for FACILITY_ITF in winerror.h, so it is recommended that you use HRESULTs outside of this range. Note that this isn't absolutely necessary, since a given HRESULT need only be unique to the interface generating the result.

The following example uses the MAKE_HRESULT macro to generate failure and success codes for a custom object:

HRESULT OBJ_E_OFFLINE_NORECLAIM = 
	MAKE_HRESULT(SEVERITY_ERROR, 
			FACILITY_ITF, 1000);

HRESULT OBJ_OFFLINE_CANRECLAIM = 
	MAKE_HRESULT(SEVERITY_SUCCESS,
			FACILITY_ITF, 1001);

 


If an ATL component implements the IsupportErrorInfo interface and derives from CcomCoClass, it can use CComCoClass::Error() to generate a COM error. This method calls CreateErrorInfo() and SetErrorInfo as discussed earlier, and returns the HRESULT which can be returned to the client to indicate the result of the function called:

if (bReclaimAllowed)
	return Error(_T("This object can be 
		reclaimed."), IID_IMyObject, 
	OBJ_OFFLINE_CANRECLAIM);
else
	return Error(_T("This object cannot be
			reclaimed."),   
	IID_IMyObject, OBJ_E_OFFLINE_NORECLAIM);

 


This is a brief summary of the steps for a typical ATL implementation of rich error handling and custom HRESULTs. Of course, MFC provides alternative mechanisms for reporting errors for components and controls, leveraging these concepts. In addition, you should know that each client of your component can differ in how it responds to HRESULT values. For example, Visual Basic doesn't raise errors for HRESULTS with a severity of success.

 


c0Title: Save Time With Software Patterns
c1Code:
June 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/06jun00/mn0600/mn0600.asp

Use the Singleton pattern to implement a simple console application and an ATL COM object 

by Muaz Niazi 


   Programmers benefit from software patterns in many ways. Patterns help solve practical software problems by documenting existing expertise; this way, developers can benefit from the experience of seasoned pros. Patterns provide a shared vocabulary for problem solving and show more than just the solution to the problem at hand�they demonstrate potential solutions to other related problems as well. 
What you need:
Windows NT, 
95, or 98 
Visual C++ 5 or 6  
 
Patterns solve real problems. Like court decisions, patterns convey the various decisions regarding the design and analysis of object-oriented software. By using patterns, developers can talk in terms of interactions of patterns, instead of focusing on the tiny details of classes and objects. 

In this article, I'll explain what software patterns are, how they are structured, and how you use them. You'll learn to use a common software pattern, the Singleton pattern, to implement a simple console application and an ATL COM object. 

Writing a pattern isn't easy (see the sidebar, "What is a Pattern?"). A pattern author has to justify the pattern by giving examples of how to use it in different domains, usually at least two. For example, the abstract factory-design pattern is documented in InterViews and ET++, and the Singleton design pattern is documented in Smalltalk-80, as well as the InterViews UI Toolkit. The author must also provide any related patterns so developers can understand their differences. If developers use the patterns together in some scenarios, the author has to document this in the related-patterns section of the pattern documentation. 

Experts such as Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides categorize 23 design patterns (see Resources). According to these experts, patterns have three basic purposes: creational, structural, and behavioral. Creational patterns deal with creating objects, whereas structural patterns deal with composing classes or objects. And behavioral patterns characterize the ways in which classes or objects interact and distribute responsibility. 

A pattern's scope specifies whether you can apply a pattern primarily to classes or to objects. As the name implies, class patterns deal with classes and their subclasses. Object patterns deal with relationships at run time and are in essence, dynamic. Most of the patterns are dynamic, and so belong to the object pattern category. 

Considering both the purpose and scope of patterns, you can see that creational class patterns should be the ones that defer object creation to subclasses, while creational object patterns defer it to another object. Similarly, behavioral class patterns use inheritance mainly to depict algorithms and flow, whereas behavioral object patterns describe how a group of objects exhibits behavior that no single object can perform alone. UML comes to our aid by efficiently depicting the relationships between objects�which are dynamic. Finally, structural class patterns use inheritance to compose classes, while their object counterparts describe ways to assemble objects. 

Design patterns help programmers find appropriate objects by identifying less obvious abstractions. In addition, they can help designers decide on the level of object granularity required. They also specify the interface (exposed part) of the objects, as well as the implementation of the objects; put reuse mechanisms such as inheritance and composition to work; and can certainly help in relating runtime and static structures. Lastly, patterns make designs adaptable to change. 

Enter the Singleton Pattern
The Singleton pattern is an object-creational pattern that ensures a class has only one instance. For example, you might require classes to have a single instance if you have many printers on a system, but only one printer spooler. You can deal with this kind of problem by using global variables, which are easily accessible but don't force the class to have a single instance. The Singleton offers a better solution than global variables; it provides a global access point for the class. 

Use the Singleton when the class should have only one instance accessible from a single well-known access point. In addition, the sole instance should be extensible through subclassing, and clients should be able to use it or an extended instance without modifying the code (see Figure 1). The Singleton class has a static variable with a unique instance. 

   
Figure 1. The Singleton's Structure Click here.

 

The Singleton design pattern offers designers many benefits. It provides controlled access to the sole instance. As the class encapsulates the sole instance, you can control access as strictly as you want. Also, you have a reduced name space, which proves a better solution than global variables because it eliminates filling out the name space unnecessarily. The Singleton also permits you to refine operations and representation. You can subclass the Singleton and easily configure the application to use it, and even control the number of instances by changing the method of accessing the instance. 

The Singleton also permits a variable number of instances, making it easy to switch to more instances later, if you need them. Although you can do the same thing using static-member functions, the Singleton pattern is better and more flexible because in C++, static member functions are never virtual, making it difficult to change the design for multiple instances. 

   
Figure 2. Inspect the Program Output Click here.

 
To learn how to use the Singleton pattern with a simple console application, create an empty Win32 console project using the Visual C++ AppWizard. Add the source files Singleton.h, Singleton.cpp, and main.cpp (download these), then populate those files with these three code snippets: header file, source file, and driver program. If you compile and run the program from a command prompt, you'll get the console output (see Figure 2). To start, look at the header file for the Singleton pattern: 



//Singleton.h
#ifndef __SINGLETON_H__
#define __SINGLETON_H__
#include <windows.h>
class CSingleton
{
public:
   static   CSingleton* Instance();
   ULONG GetData();
   void SetData(const ULONG 
         a_unlData);
protected:
   CSingleton();
   ULONG m_unlSomeData;
private:
   static CSingleton* s_snglInstance;   
};

#endif //__SINGLETON_H__

I've included the standard windows.h header so you can use the standard Win32 datatypes in your program. This file contains the declaration of the CSingleton class, the class implementing the Singleton pattern. To illustrate that the class has no more than one instance, use the data variable m_unlSomeData. The GetData() and SetData() functions provide access to this data. The Instance() function gives access to the single instance, defined here as a static pointer to the class itself. Note that the sole constructor of the class isn't accessible from outside the class, ensuring that the only way to get the instance of the class is through the Instance() method. 

Next, implement the Singleton class in Singleton.cpp (see Listing 1). In this file, you initialize the static variable. In C++, static member variables aren't attached to a particular instance; instead, you can access them without creating an instance of the class. The CSingleton class's constructor initializes the data to zero. The two functions you need for the data are simple, and set or get the values, respectively. The implementation's most important part is the Instance() function, which actually creates the one instance and gives it to this class's clients. 

Finally, you get to the driver program containing the main function: 



//Main file
#include <conio.h>
#include <iostream.h>
#include "Singleton.h"

void main()
{
   CSingleton* psnglObject1,* 
         psnglObject2;
   psnglObject1 = 
         CSingleton::Instance();
   psnglObject2 = 
         CSingleton::Instance();
   psnglObject1->SetData(10);
   cout << "Singleton Object 1 has 
         data " << 
         psnglObject1->GetData() 
         << endl << flush;
   cout << "Singleton Object 2 has 
         data " << 
         psnglObject2->GetData() 
         << endl << flush;   
   getch();
}

As you can see, you declare two pointers to the CSingleton class. You can't directly call the CSingleton constructor. Instead, you call the Instance() method, the only way to gain access to the instance. Now, you use the accessor SetData() function to set the object's data. However, you have the same data for both pointers! So, regardless of the number of clients, the CSingleton class can hook them on to the same instance, illustrating that the class is true to its name (see Figure 2). 

Implement the Pattern in ATL 
Now that you know how to implement a Singleton in C++, implement the pattern in ATL and see how it handles the task. First, take a look at how ATL implements COM (see Figure 3). Of the classes ATL uses to implement COM, CComObject<>, CComAggObject<>, and CComPolyObject<> implement the three methods of IUnknown. CComObjectRootEx<> handles object-reference count management for both nonaggregated and aggregated objects. It holds the object reference count if your object isn't being aggregated, and it holds the pointer to the outer unknown if your object is being aggregated. 


   
Figure 3. How ATL Implements COM Click here.

 
For aggregated objects, you can use the CComObjectRootEx<> method to handle the failure of the inner object to construct, and you can use it to protect the outer object from deletion when inner interfaces are released or the inner object is deleted. CComObjectRootEx<> provides the default QueryInterface() mechanism based on COM map entries. It's essential for all ATL objects to have a single instance of CComObjectRoot<> or CComObjectRootEx<> in their inheritance. For ATL, CComObject<> and CComAggObject<> are the best way to deal with COM objects, without and with aggregation, respectively. However, if the macro DECLARE_POLY_AGGREGATABLE is defined, ATL uses CComPolyObject<> instead of the other two classes. 

This approach supports both aggregatable and non-aggregatable objects, but it might result in a slightly larger module size than expected. However, for a full control or an Internet Explorer control, the ATL Object Wizard automatically adds the macro. You derive from IDispatchImpl<> for a default implementation of IDispatch. If you want to report errors back to the client using IErrorInfo, your object must support ISupportErrorInfo. The ATL template class ISupportErrorInfoImpl<> provides an easy way to implement this, if you have a single error-generating interface. 

Now look at CComCoClass<>, used by ATL to define the default class factory and aggregation model for your object. ATL also uses the typedef mechanism to implement default behavior. For example, the DECLARE_AGGREGATABLE macro uses typedef to define a type called CreatorClass, referenced throughout ATL. CComCoClass<> specifies these two macros: DECLARE_CLASSFACTORY, which declares the class factory to be CComClassFactory<>, and DECLARE_AGGREGATABLE, which declares the object is aggregatable. Here's an actual code snippet from atlcom.h: 



template <class T, const CLSID* 
         pclsid = &CLSID_NULL>
class CComCoClass
{
public:
   DECLARE_CLASSFACTORY()
   DECLARE_AGGREGATABLE(T)
   . . .
};

To override any of these, you can use any other macro in your class definition. Returning to the Singleton pattern, to use the ATL's default implementation, you simply have to define the macro DECLARE_CLASSFACTORY_SINGLETON in your class, and it overrides the default behavior: 



class CMySingleClass : . . ., public 
      CComCoClass<...>
{
. . .
DECLARE_CLASSFACTORY_SINGLETON(CMySingleClass)
. . .
};

This means that ATL uses the class CComClassFactorySingleton<>, instead of CComCoClass<>, as the class factory. Here's the code for the DECLARE_ CLASSFACTORY_SINGLETON macro from atlcom.h: 



. . .
#define 
   DECLARE_CLASSFACTORY_SINGLETON(
   obj) 
   DECLARE_CLASSFACTORY_EX(
   CComClassFactorySingleton<obj>)
. . . 
To understand how ATL implements the Singleton pattern, look at the definition of CComClassFactorySingleton<>, again in your favorite atlcom.h (see Listing 2). The code reveals a number of things here. First, ATL has added a member of type CComObjectGlobal<> to the class CComClassFactorySingleton. Next, the default implementation of ATL ensures the Singletons aren't aggregatable. Below the comment, the debug version should give an ASSERT() failure if pUnkOuter is non-null. In general, the class doesn't support aggregation. What might not be obvious is that you'll have problems implementing Singletons in DLLs. (See Resources for a description and workaround.) 

Technically, this procedure meets the formal definition of a Singleton. Every client gets a reference to the same instance of the class through a well-known access point. One problem is that CreateInstance() behaves "unnaturally" according to COM, because it's supposed to give new instances each time. Considering the norm of COM programming, clients unaware of your implementation�and, in OOP, clients are supposed to be unaware of the implementation and focus instead on the class's interface�might be surprised if your implementation expects two different objects from the CreateInstance() method. 

CComObjectGlobal<> manages a reference count on the module containing your Base object. It ensures the object won't be deleted, as long as the module isn't released. The object will be removed only when the reference count on the entire module goes to zero. A single CComObjectGlobal<> object is being used�it has a member variable m_hResFinalConstruct, which has the HRESULT value from calling FinalConstruct(). ATL uses this object for the reference counting. 

Another way to use Singletons in COM: Implement your own custom interface and implement it the way you want. This implementation doesn't break COM programming norms: 



// Custom interface
// implemented by 
// class object
interface IMySingletonFactory : 
         IUnknown {
      HRESULT GetTheInstance([in] 
         REFIID riid,
         [out, iid_is(riid)] 
         void **ppv);
}
// Implementation of GetTheInstance
HRESULT 
   CMyClass::GetSingleInstance(REFIID 
   riid, void **ppvObject)
{
   static CMyClass s_myClass;
   return 
      s_myClass.QueryInterface(riid, 
      ppvObject);
}

In this code, you're designing a completely new interface, IMySingletonFactory, derived from IUnknown. This process doesn't limit you, as does ATL, by IClassfactory::CreateInstance(). Instead, you do things your own way. You get access to your single instance through your lone method, GetSingleInstance()�a much better way to implement Singletons than ATL's method. However, in both cases, you're forgetting one basic COM concept: COM objects are typically in separate apartments. So, you must marshal interface pointers between two apartments. If the class object returns the interface pointer directly, and you use the Singleton in multiple apartments in one process, the code violates the rules. 

This means that to use in-process Singletons, you should either mark the threading model in the registry as free or else leave out the ThreadingModel attribute altogether from the registry. The point is, Singletons have limited applicability to distributed computing unless you focus on a single state, rather than a single instance. When you need a single instance without going into distribution, the Singleton pattern works well. 

The pattern revolution made developers and analysts rethink their way of getting the job done. Patterns solve complex problems. In my opinion, the Singleton design pattern is a good way to start learning patterns. You can move on to more complex patterns involving multiple classes, or even multiple patterns, in the future. And as you start using even one pattern in your designs, you'll find yourself looking for other patterns as well. At the least, you'll start to observe what goes into a design�good or bad. 


Muaz Niazi is an electrical engineer with post-graduate training in software development and an MCSD certification. He is a software consultant (www.geocities.com/maqsoodi) and specializes in software engineering practices, as well as developing applications in C++, COM, ATL, and MFC. Reach him at muaz_niazi@yahoo.com
 


c0Title: Share Settings Across Programs
c1Code:
August 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/08aug00/bb0008/bb0008.asp
Use CdbSettings classes and a simple database to build a go-anywhere shared-settings implementation. 

by Tom Creighton 


Most programs need to read and/or store configuration information during the normal course of their operation. With Windows 95, Microsoft gave us a sophisticated mechanism for handling configuration information. I usually use the Windows API directly, but sometimes I use the ATL abstraction, and I've often wished I had a better abstraction of the Registry API. 
What you need:
Visual C++ 6.0
Microsoft Access 2000/Access 97  
 

While I've wished for a better abstraction of the Registry, several of my clients have needed a facility for sharing program settings across multiple, concurrent and distributed programs. Answering my clients' needs has typically involved creating one or more database tables to store such information. You can share settings data across multiple, distributed programs by using the Registry API to save and load hives. However, this approach requires that you lock the hive file while loading or saving�a process that can prove difficult and certainly reduce the concurrency level. 

In the approach I describe here, you use a simple database to share settings. You can implement the schema on a variety of DBMS platforms. I've included a sample implementation in Microsoft Access to show you the shared-settings implementation in action. Each DBMS platform requires its own procedures, but for the most part, my approach is platform-neutral. 

Get the sample program to work by creating an ODBC data source name (DSN) and pointing it to the sample program's MDB file. The sample program uses the DSN "dbSettings", so if you don't want to change the connect string in the program, you should use the same name for your DSN. 

I've implemented the shared-settings capability as a set of C++ classes; I created a simple dialog-based program to demonstrate the use of these classes (download the program and the implementation classes). I modeled this shared-settings implementation on the Registry functionality. A quick overview of the Registry will help you understand the way this non-Registry-based shared-settings implementation works; see my article, "Shared Settings Basics" (www.cplus-zone.com/morearticles.asp), for a demonstration of the same functionality in a Registry-based implementation. 

The Windows Registry is essentially a database of named value pairs organized into groups and subgroups. Each group or subgroup has a unique name within its containing group; group names are called keys. Each named value pair (called an item) has a unique name within the subgroup that contains it. The Registry predefines several base, or root-level groups; users can't create or delete these groups. To retrieve the named value pairs from a particular group, open that group by calling the RegOpenKey() function or one of its related functions. Each group has an optional, unnamed item typically referred to as the Default item. With that, you have the Registry "essentials" that directly relate to the shared-settings implementation. 

Database Schema Supports Collections
I created a database that supports groups and subgroups (that I call collections) as well as data items (see Figure 1). The database schema has only three entity classes (ECs), corresponding to three tables that I define to implement the database (see Figures 2, 3, and 4).     
Figure 1 How the Entity Classes Relate Click here.

 

A Collection instance can contain several subcollections, as modeled by the recursive relation class Contains and implemented by the foreign key ParentKeyID. This hierarchical implementation is fairly standard in a relational database. You can use any of several approaches to support multiple data items in each collection. For example, you can create a different table for each type of data item you want to support and have an optional relation class between Collection and each of the data item ECs. That approach makes both the model and the implementation a bit more complex, but it might be justified if the target DBMS does a poor job of handling null data. I wasn't concerned about null-data handling, though; my target DBMS is Oracle with a future implementation on SQL Server, so I don't need a different table for each type of data. 

    
Figure 2 Set the Collection Table Click here.

 

At this point, the program supports character string and integer item types. I've also partially implemented support for a private datatype I call opaque. You'll want to add your own datatypes as well. For example, the next one I plan to support is a date/time type. For each datatype you want to support, define a new attribute in the Item EC, and a corresponding field in the Item table. Be sure to allow these attributes to have null values. By definition, only one nonkey attribute of the Item EC can have a non-null value. 

You'll also notice that the Item EC has an attribute called ItemType. I've defined the range of values for this attribute to be 0, 1, and 2, indicating integer, string, and private (opaque) types, respectively. A more explicit model�and not a bad way to implement the database�would have another EC, called AllowedType, define a domain for the datatypes. If I used that model, I could use a foreign key class in Item to refer to that EC. In the current implementation, however, you have to remember the allowed values and what they mean. 

Get to the Heart of this Implementation
One of my goals with this project: to have a program settings capability that closely modeled the Windows Registry, but that was implemented in a DBMS. I wanted to create a demonstration program that worked with either the Registry or a DBMS with minimal change. I didn't quite meet that goal�but I got pretty close. 

    
Figure 3 Hold Item Name/Value Pairs Click here.

 

The program's primary class is CdbSettings, which derives from an abstract base class called CSettings (see Listing A). When I implemented the Registry-based version of the program, I derived from CSettings as well, but CSettings has subsequently undergone a few changes. You can see the declaration of CSettings online in the file settings.h. When you work with the Windows Registry, the database is always there, ready to be used. When you work with a real DBMS, you must first make a connection to the database. I kept all database stuff out of the abstract base class. 

If you inspect these two classes carefully, you'll notice that CdbSettings has diverged further than necessary from the base class. My next project is to go back and redefine the abstract base class so all non-database-specific functionality that represents the public interface to the classes is reflected in the base class. You can see most of the CdbSettings declaration, but I've left out some of the details such as property declaration (see Listing A, and the dbsettings.h file for the full listing). 

    
Figure 4 Manage Key Values Click here.

 

Using CdbSettings is fairly straightforward. You open a root key by calling OpenRootKey()�an action similar to opening one of the predefined keys in the Registry. If you choose root keys that have a syntax based on a network distinguished name, you should be able to avoid name conflicts with other programmers. In my example, I created root key names such as "AllUsers.lptg.com" and "v1.devgroup2.lptg.com". As when working with the Registry, when you open a key you can choose to have the key created, or you can have the system look for the named key. 

Call one of the GetItem() or SetItem() methods to retrieve or set data items. You'll notice that I've declared a number of other related methods in CdbSettings. I declared all of those as protected, and I intended for them to support the primary methods declared in the abstract base class, rather than to be called directly. 

In addition to the classes CSettings and CdbSettings, I've declared several other supporting classes. These classes let me have different datatypes for data items, and they provide for enumerating keys or data items. I'll cover the enumerations when I discuss implementation, but here, I need to mention CHexAscii and CSimpleComposite briefly. 

CHexAscii is an unfinished class I intend to use as a mechanism for loading structures (class data) into the database without creating new tables for each structure I want to support. This arrangement is similar to supporting remote procedure calls (RPCs) when marshaling data between processes or machines. I plan to build an ASCII representation of the structure that includes information to allow me to decode it correctly. I hesitated to include this unfinished class in the article, but I wanted to give you a feel for one way you could extend this system. 

The CSimpleComposite datatype, which I first introduced in August's Black Belt column on data extraction, is a simple variant implementation that I use in many situations. It's useful here because it eliminates the need for your program to specify a data item's type before it requests an item's value. You can simply ask for the data to be retrieved in the composite type and check what you received. 

Dig Into Implementation Details
All the methods you call to connect to a particular group (or key) call the protected method OpenKey() (see Listing B). Here's the prototype for OpenKey: 

int OpenKey (   
   KeyIDType ParentKeyID,
   const string & Key,
   SQLHSTMT hStmt,
   KeyIDType & KeyID,
   bool bCreate);
Each subkey is separated from its container by a single backslash character. OpenKey() parses the Key reference to find key segments. When OpenKey() finds a key segment, it queries the database for that name within the KeyID given in the ParentKeyID parameter. If that value is 0, OpenKey() looks for the name where the ParentKeyID is null. Here's the SQL template OpenKey() uses (you can find the definition online in dbsettings.h): 
Select KeyID, KeyName, DefaultItem, ParentKeyID
From Collection
Where ParentKeyID = %d  And KeyName = '%s'
If ParentKeyID is 0, the request is for a root key. In that case, the SQL is slightly different: 
Select KeyID, KeyName, DefaultItem, ParentKeyID
From Collection
Where ParentKeyID is null Or ParentKeyID = 0

Even though I allow you to use a 0 value in the database to represent the lack of a ParentKeyID, I prefer to leave it as a null value (admittedly, some DBMSs might not support null values well). 
I use a number of #define manifest constants in this implementation to define various SQL statements. To simplify things, I recommend you always retrieve all fields of a particular table, even if a single field could satisfy the query's purpose. By retrieving all the table's fields, you can use the same method to handle any query for each table. To handle key-table queries, for example, you use ReadKey(). Once you know which SQL statement to issue, call ReadKey() to issue the statement and retrieve the data: 

RetCode = ReadKey(sSQL, hStmt, ParentKeyID, KeyID, KeyName, DefaultItem);
If KeyName hasn't been fully processed at this point (in other words, if KeyRemainder isn't null), OpenKey() simply calls itself and passes in as ParentKeyID the KeyID returned from ReadKey() and the KeyRemainder as KeyName. Finally, the leaf of the tree is reached (or possibly created) and OpenKey() marks the KeyID as current. 
Reading in the subkeys within a key or the items within a subkey was fairly simple in the Registry-based version of this implementation. But the database implementation required a different approach. I wanted to be able to initiate an enumeration of keys or items and then retrieve each one in turn. I didn't want to process all the results at once, though, so I had to come up with a structure to maintain state between retrievals. An enumerator seemed to make sense. 

Enumerate Keys and Items
Each enumerator type derives from CSetEnumerator (you'll find online the virtual base class declared in settings.h and the two derived classes in dbsettings.h). This class defines only two methods: Reset() and GetNext(). CdbKeyEnumerator and CdbItemEnumerator provide access to lists of keys and items. To construct your retrieval, first prepare a SQL query using one of the templates I've defined in dbsettings.h. Then, pass the SQL along with a connection handle and environment handle to the appropriate enumerator's constructor. 

For example, here's what GetItem() does to retrieve the item data for a single item: 

char sSQL[256];
sprintf(   sSQL, 
      DB_QUERY_SPECIFIC_ITEM_WITHIN_KEY, 
      mp_CurrentKeyID, 
      Name.c_str());
CdbItemEnumerator * pEnum = 
   new CdbItemEnumerator(mhDBC, mhEnv, sSQL);
if (pEnum && pEnum_>mbReady)
{
   string Tmp;
   RetCode = pEnum_>GetNext(Tmp, Value);
}
The manifest constant DB_QUERY_SPECIF- IC_ITEM_WITHIN_KEY defines the SQL, which is: 
Select ItemID, ItemName, ItemType,
IntValue, StrValue, PriValue
From Item
Where KeyID = %d and ItemName = '%s'
GetNext() maps the data from each retrieved record into the composite Value. 
For a slightly more involved example, look at code in the sample application found in CDbSetDlg::FillList(), in the file dbSetDlg.cpp: 

CSetEnumerator * pEnum = NULL;
CSimpleComposite Value;
Result = (mp_pSettings->mbRKOpen
   ? mp_pSettings->
   GetSubKeyEnumerator(& pEnum)   
   : mp_pSettings->
   GetRootKeyEnumerator(& pEnum));
if (SE_OK == Result && pEnum)
{
   int i;
   for (i = 0, 
       Result = pEnum->GetNext(KeyName,
         Value); 
   SE_OK == Result;
   i++, 
   Result = pEnum->GetNext(KeyName,
            Value))
   {
      mp_pKeyList->AddString(
      KeyName.c_str());
   }
FillList() has the job of filling up a listbox with root key or subkey names. It first determines whether to enumerate root key or subkey records, then it instantiates an enumeration object for that record type. In the case of keys, I've hidden the SQL inside the helper method GetSubKeyEnumerator() and inside the constructor CRootKeyEnumerator(). That little trick makes it much simpler to get the enumerator constructed. CKeyEnumerator() calls CKeyEnumerator::Reset(), so by the time the constructor is finished executing, it has issued the appropriate SQL statement and created a cursor to use in retrieving recordsets. 
Then FillList() tests to see that the SQL executed correctly by calling the enumerator's IsReady() method. If all is ready, FillList() iterates over each record in the recordset by calling the enumerator's GetNext() method. Each GetNext() call brings back a key name that is added to the list. 

Did you notice that FillList() doesn't call the key enumerators' constructors directly? Instead, FillList() calls the helper methods CdbSettings:GetRootKeyEnumerator and CdbSettings::GetSubKeyEnumerator. That indirect calling method further simplifies the job of constructing enumerators. 

This CdbSettings class and the helper classes that come with it let you store program settings in a central location. These settings can be as detailed as you want. They can be startup configuration items�or even user-related items. You can access the database independently of the interface defined by CdbSettings, so you can use a variety of report writers to prepare custom reports. Even better, you can give cooperating programs that run on non-Windows machines the same access your Windows programs have (provided, of course, you port the classes to a non-Windows platform). 

Enumerators are useful for managing lists of data regardless of source, independent of the shared-settings environment. In fact, I use enumerators this way all the time. For example, you could create a file enumerator to provide access to data files within directories. 

While the shared settings system is useful, I'm sure you'll agree it needs to contain more datatypes. Adding a new datatype is relatively simple: Simply define a new column in the Item table and create GetItem() and SetItem() methods to support the datatype. By finishing the opaque datatype CHexAscii, you can readily extend support for any scalar or nonscalar datatype without making a schema change. 

Let me know some of the ways you end up using CdbSettings. 


Tom Creighton has worked as a professional software engineer for more than 20 years. He consults in database design and in Public Key Infrastructure (PKI) development. Tom earned two computer science degrees: a B.S. from Brigham Young University and an M.S. from University of Southern California. E-mail him at prohacker47@hotmail.com
 


c0Title: The Incredible Shrinking Executable
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/2000/09sep00/ap0009/ap0009.asp

by Andy Harding 


 Q. Optimization Options 
Trim the Fat From Your Apps 
How can I shrink the size of executables and ActiveX controls? Size is important to my company because we have many customers connecting with our networks over dial-up lines. 
What you need:
Visual C++ 5 or 6  
 
A. Visual C++ gives you a number of options for shrinking executables and ActiveX controls. First, consider using the �O and �G command-line compiler optimization options, because the default optimization compiler switch in Visual Studio optimizes speed, not size. /O1 and /O2 are the two main switches, and the /O1 switch is intended to provide smaller code size. /O2, the default optimization option for new projects in Visual Studio, provides the fastest code. You can change the optimization option settings in the Project Settings dialog on the C/C++ tab. Set the dialog's Category drop-down listbox to Optimizations, then select the Minimum Size option from the Optimizations drop-down list to place the /O1 switch in the Project Options. 

But how much smaller can the /O1 switch make your code? On smaller programs, the switch makes little or no difference. For example, it had no impact on the size of a couple sample applications I wrote for this column. A Win32 SDK app was 28,672 bytes when I compiled it with either the /O1 or the /O2 switch; I had the same results with a 20,480-byte bare-bones MFC application. 

One reason these switches aren't effective on small programs: Both options pad every function call with extra space. To avoid the extra padding�and we all need to avoid the extra padding�try these switches: /Og (global optimizations), /Os (favor small code), and /Oy (no frame pointers). You can also place this pragma in your stdafx.h or the header file of your choice: 

#pragma optimize("gsy",on)
Another tool for shrinking your applications is /FILEALIGN:xxx. To understand how this linker switch works, you need a basic understanding of how a linker assembles a binary file. Traditionally, the linker places several segments in a binary file; the segments we're concerned with here are .data (strings, heap variables, and so on), .rdata (read only data), .rsrc (resource data), .reloc (relocation information), and .text (your source code). The linker creates these segments with a default block size, so they almost always contain extra space. In VC6, the default block size is 4K; so if your resources are 4.1K compiled, your .rsrc segment will be 8K. In VC5, the default block size is 512 bytes. 
    
Figure 1 Process Viewer Reveals All Click here.

 
VC6 contains an undocumented linker switch that allows you to change the default block size; the switch is /FILEALIGN:xxx, where xxx is the size. The value passed with /FILEALIGN must be between 512 bytes and 64K, and it must be a power of 2. The linker places the /FILEALIGN value in the binary file's header section, in the file alignment value. Placing /FILEALIGN here helps keep the blocks closer to the size your binaries need. But remember that this is an undocumented feature. When you upgrade to VC7, /FILEALIGN might not work well, or it might stop working altogether. 

How about some other options? Microsoft Platform Builder 2.12, the Windows CE OS-generating product based on VC6, uses an interesting technique to condense binary files. It combines two of the file segments into one, merging the .rdata into the .data section. NOPcode.com provides a header file that goes several steps further to shrink file size, merging the .rdata, .text, and .reloc segments into the .data section (see Links). 

On average, the NOPcode.com merger saves about 6K per binary file. In my trial, a 33K control panel applet was just 3K after the NOPcode.com optimizations. If you're downloading ActiveX controls on a 56K baud modem, you'll appreciate this kind of size reduction. Our friends at NOPcode.com give us this warning, though: "Note that merging the .rdata section will result in LARGER exe's if you are using MFC (esp. static link)." 

  
Figure 2 The Process Viewer DLL Dossier. Click here.

   
I must add a final word of warning about optimizations in general: From my own experiences, these are great tools, but you should turn them off at times. I've spent many days tracking down problems that didn't exist in my code�only in the optimizations. If you start seeing strange behavior in your compiled code that seems to appear only in the release version, check the optimizations. 

Q. DLL Detection Made Easy 
Is there any way (commercial program, shareware, or something I can code myself) to detect the DLLs in use by any executable program? Running the VC++ debugger, I can see that each loaded DLL traces a message in the output window. I tried to find where this tracing originates, but it seems to come from API functions (CreateWindowEx(), for example). 


A. You can view DLLs in use through Process Viewer, which comes with VC++ 6 (see Figure 1). Make a selection in the Process list, then click on the Memory Detail button. In the Memory Details dialog, use the drop-down list to view all the DLLs loaded; they're listed by the selected process and memory they're using (see Figure 2). Make sure you select the process you want to check before hitting the Memory Detail button. You can find better DLL-checking tools, but you should already have this one. 

The messages that show up in the debugger's Debug window are sent using the API OutputDebugString(). The debugger uses OutputDebugString() to place the DLL load messages into the Debug window. Here's a code snippet that writes a string with the last error value: 

TCHAR szBuff[256];
	_stprintf(szBuff, _T("MyApp:	\ 
				  LastError = %d\n"), 
				  GetLastError());
	OutputDebugString(szBuff);
As a rule, you should use OutputDebugString() only in Debug Mode, not with Release Mode. OutputDebugString() can be a helpful debugging tool when you're working with lots of loops or iterations that are hard to step through. 
Q. Track Down File Dependencies 
I need to identify all DLLs/ActiveX controls that a given application needs in order to run. When I install the setup program, I get error messages saying the application is missing necessary components. Is there a tool that can help me figure out what the system is missing? 


A. There certainly is! The good folks at Microsoft thought we might need just such a tool, so they provided Dependency Walker (DEPENDS.EXE) for times you need a little extra support. DEPENDS is one of the standard tools that comes with Visual Studio 6. 

    
Figure 3 Just What Your Binary Needs. Click here.

 
After you select a binary file, DEPENDS analyzes the file's complete dependency tree and gives you the results in a nice GUI treeview (see Figure 3). At the bottom of the screen, DEPENDS presents a listview of the DLLs your binary file depends on, complete with version information. If you select a DLL entry in the treeview, the top-right pane lists all the functions the DLL links with; the bottom-right pane lists all the functions the DLL exports. Double-click on a list entry to get the Quick View of the DLL, with even more information about the binary. 

Although DEPENDS gets you well on your way to identifying all the files your setup program needs, it doesn't list the DLLs dynamically loaded by LoadLibrary(). You'll need to search for these dynamically loaded DLLs yourself. A good starting point for that search is Process Viewer (see previous question), another helpful tool from Microsoft that's already in your arsenal. 


Andy Harding is a software engineer at BSquare Corp. He is trying to find some spare time, but is becoming convinced it does not exist in the software market. Contact him at andyh@bsquare.com. 
 


c0Title: Use ATL Windows Features
c1Code:
August 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/08aug00/et0008/et0008.asp


Level: Intermediate 
in a Regular Win32 App 
You might find it challenging to use ATL in your Win32 apps, unless you know several little tricks. You need to include a few ATL header files and add a CComModule _Module variable to your project. You also need to call _Module.Init() and _Module.Term() in your WinMain procedure. 

First, here's what you need in your stdafx.h file: 

#define STRICT
#include <Windows.h>
#include <ATLBase.h>
extern CComModule _Module;
#include <ATLWin.h>
Next, declare the _Module instance in one of your CPP files: 
CComModule _Module;
Here's what you need in WinMain: 
int WINAPI WinMain (HINSTANCE hinstExe, 
	HINSTANCE, LPSTR lpszCmdLine, int nCmdShow)
{
	_Module.Init(NULL, hinstExe);

	/* your app code...*/
	_Module.Term();
	return 0;
}
Now you can use one of the ATL windowing classes�use ATL's CDialogImpl<> template base class to implement a dialog class, for this example. Your dialog proc becomes a class method instead of a module or global scope function if you use this base class. CDialogImpl<> also provides some handy methods for displaying and destroying your dialog, such as DoModal(), Create(), ShowWindow(), and DestroyWindow(). Declare your dialog class like this: 

class CYourDialog : public 
	CDialogImpl<CYourDialog>
{
public:
	BOOL ProcessWindowMessage(HWND, UINT, 
		WPARAM, LPARAM, LRESULT&, 
		DWORD dwMsgMapID = 0);
	enum {IDD = IDD_dlgTest};
...
};
ATL uses the IDD enumerated value to get your dialog's resource ID. The ProcessWindowMessage() class method is your dialog proc. 

To show the dialog, use this: 

CYourDialog dlg;
dlg.DoModal();
 


c0Title: Use COM Interfaces to Read Type Libraries
c1Code:
March 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/03mar00/fg0300/fg0300.asp
Type libraries give you the power to use objects, interfaces, and data structures with a COM server. 

by Jeff Ferguson 


     Developers need all the help they can get, which is why they love type libraries. Type libraries describe the objects, interfaces, and data structures you can use with a COM server, and make it easier for you to create accurate and fast code in a variety of situations. Visual Basic, for example, implements its IntelliSense and Object Browser features using the information it reads from a type library. And the Visual C++ #import feature uses type libraries to automatically generate the code that calls into COM servers. 
What you need:
Visual C++ 6.0
Windows 95, 
Windows 98, Windows 
NT 4.0, or Windows 2000
 
 
You don't access type libraries directly. They're saved in an undocumented binary format, which you read using the COM interfaces ITypeLib and ITypeInfo. Windows 95 through 2000 ship with implementations of these interfaces, so any developer can use them to read type library data. 

Various type library viewers ship with Microsoft Visual Studio products. Visual Basic's Object Browser is a type library viewer, as is the OLEVIEW application that ships with Visual C++. However, these tools provide only some of the information available in a type library. When you want to perform additional work with type libraries, you'll need to use the ITypeLib and ITypeInfo interfaces. As I mentioned, these COM interfaces enable you to read information from the type library and implement the code manually. In this article, you'll learn how to use ITypeLib and ITypeInfo to read information from type libraries. The first step in reading from a type library is to get a pointer to an ITypeLib interface for a type library. Begin by creating the IDL for the ITypeLib interface (see Listing 1). 

Once you have an ITypeLib interface pointer associated with a type library, you can use it to read the objects found there. The ITypeLib method GetType-InfoCount() returns the number of objects found in the type library. The ITypeLib methods GetTypeInfo() and GetTypeInfoType() return information about one of the objects in the type library. 

Both methods take two parameters. Both methods' first parameter is a zero-based index of the type library object whose information you want to retrieve. The GetTypeInfo() method's second parameter is an address of an ITypeInfo interface pointer. When the method returns, you can use the ITypeInfo interface pointer to get specific information about the object. The GetTypeInfo-Type() method's second parameter is the address of a variable of type TYPEKIND. The TYPEKIND datatype is an enumeration whose value describes the type of object found at the given index. The TYPEKIND enumeration can have a number of values (see Table 1). 

Access Generic Object Data
All type library objects share some basic attributes, regardless of their specific object type. You can access these basic attributes through calls on the object's ITypeInfo interface pointer. And you can get an object's name, documentation string, and help file information through a call into the type library's ITypeLib interface pointer. The ITypeLib::Get-Documentation() method returns the name of an object, its documentation string, and help file information. Type library viewers, such as Visual Basic's Object Browser, display these strings as a documentation aid. The method requires that the caller supply the index of the object whose information should be returned. This code snippet illustrates calling the ITypeLib::GetDocumenta- tion() method for each object in a type library: 



int nTypeInfoCount;
int nTypeInfoIndex;

nTypeInfoCount = 
	pITypeLib->GetTypeInfoCount();
for(nTypeInfoIndex = 0;
	nTypeInfoIndex < nTypeInfoCount;
	nTypeInfoIndex++)
{
	BSTR  bstrDocumentation;
	BSTR  bstrHelpFile;
	BSTR  bstrName;
	DWORD dwHelpContextID;

	pITypeLib->GetDocumentation(
		nTypeInfoIndex,
		&bstrName,
		&bstrDocumentation,
		&dwHelpContextID,
		&bstrHelpFile);

	// work with the information here

	::SysFreeString(bstrName);
	::SysFreeString(bstrDocumentation); 
	::SysFreeString(bstrHelpFile);
}

You might be wondering how you could obtain this information if the ITypeLib pointer has been released, and the only interface available is a specific object's ITypeInfo interface. The answer lies with the ITypeInfo interface method, GetContainingTypeLib(); it returns an ITypeLib interface pointer that manages the type library the ITypeInfo object came from. GetContainingTypeLib() also returns the zero-based index of the object in the type library. This code illustrates how to get the name, documentation, and help file information for an object using its ITypeInfo interface: 



BSTR		 bstrDocumentation;
BSTR		 bstrHelpFile;
BSTR		 bstrName;
DWORD		 dwHelpContextID;
Int		 nTypeInfoIndex;
ITypeLib * pITypeLib;

pITypeInfo->GetContainingTypeLib(
	&pITypeLib,
	&nTypeInfoIndex);
pITypeLib->GetDocumentation(
	nTypeInfoIndex,
	&bstrName,
	&bstrDocumentation,
	&dwHelpContextID,
	&bstrHelpFile);

// work with the information here

::SysFreeString(bstrName);
::SysFreeString(bstrDocumentation);
::SysFreeString(bstrHelpFile);
pITypeLib->Release();

You can access the remaining data available for all type library objects through a call to the ITypeInfo method GetTypeAttr(). It creates a TYPEATTR structure, fills it with data, and returns it to the caller (see Table 2). Now that you know how to get generic object data, take a look at each type of object to see how you can access its object-specific data through an ITypeInfo pointer. 

Access Enumeration Data
If GetTypeInfoType() returns TKIND_ ENUM for a given object index, then you can use the ITypeInfo interface pointer returned by GetTypeInfo() to access enumeration data. An enumeration is a set of one or more variables, each with a name and a specific value. The cVars member of the enumeration's TYPEATTR structure keeps track of the number of variables in an enumeration. A call to the ITypeInfo method GetVar-Desc() reads the information associated with each enumerated variable. This method takes two parameters: The zero-based index of the variable to be read, and the address of a VARDESC structure (see Table 3). Information about the enumeration variable fills the VARDESC structure. Once the structure is full, you must call ReleaseVarDesc(), another ITypeInfo method, to release the memory associated with the structure. A typical processing loop for enumerations might look like this: 



if(eTypeKind == TKIND_ENUM)
{
	int		 nEnumIndex;
	TYPEATTR * pTypeAttr;

	pTypeInfo->GetTypeAttr(&pTypeAttr);
	for(nEnumIndex = 0;
		nEnumIndex < pTypeAttr->cVars;
		nEnumIndex++)
	{
	  BSTR		bstrName;
		HRESULT		hResult;
		Unsigned int nLength;
		VARDESC * 	pVarDesc;

		hResult = 
			pTypeInfo->GetVarDesc(
			nEnumIndex,
			&pVarDesc);
		if(hResult == S_OK)
		{
			hResult = 
				pITypeInfo->GetNames( 
				pVarDesc->memid,
				&bstrName,
				1,
				&nLength);
			if(hResult == S_OK)
			{
				// the name is now in
				// "bstrName"
::SysFreeString(bstrName);

			}
			pTypeInfo->ReleaseVarDesc(
				&pVarDesc);
		}
	}
}

You retrieve the name of the enumeration value through a call to GetNames(). This ITypeInfo method takes four parameters. The first parameter is the member ID of the enumeration value whose name you want to retrieve. You'll find this value in the memid member of the enumeration's VARDESC structure. The second parameter is a pointer to an array of BSTRs that will hold the returned names. Generally, you'll get only one name at a time. Passing in the address of a single BSTR works well here. The third parameter is the number of names you want to retrieve, and the fourth parameter is the address of an integer that will contain the number of names actually retrieved. 

Armed with this knowledge, you can expand your enumeration sample to get the names of each enumeration value you find: 



if(eTypeKind == TKIND_ENUM)
{
	int		 nEnumIndex;
	TYPEATTR * pTypeAttr;

	pTypeInfo->GetTypeAttr(
		&pTypeAttr);
	for(nEnumIndex = 0;
		nEnumIndex < pTypeAttr->cVars;
		nEnumIndex++)
	{
	 BSTR		bstrName;
		HRESULT	hResult;
		Unsigned int nLength;
		VARDESC *	pVarDesc;

		hResult = 
			pTypeInfo->GetVarDesc( 
			nEnumIndex,
			&pVarDesc);
		if(hResult == S_OK)
		{
			hResult = 
				pITypeInfo->GetNames(

					pVarDesc->memid,
					&bstrName,
					1,
					&nLength);
				if(hResult == S_OK)
				{
					// the name is now in 
					// "bstrName"
::SysFreeString(bstrName);

			}
			pTypeInfo->ReleaseVarDesc(
					&pVarDesc);
		}
	}
}

You'll find the value of the enumeration through the lpvarValue member of the enumeration's VARDESC structure. This value is a pointer to a VARIANT and could theoretically hold any VARIANT-compatible datatype. In practice, however, you define enumerations as four-byte signed integers, so the VARIANTs will hold values of type VT_I4. 

Access Structure and Union Data
If GetTypeInfoType() returns TKIND_ RECORD for a given object index, you can use the ITypeInfo interface pointer returned by GetTypeInfo() for that same index to access structure data. You'll obtain structure information using the same ITypeInfo methods you use to read enumeration information. The number of data members in the structure is in the cVars member of the structure's TYPEATTR structure, and you'll use GetNames() to read these data members' names. You now need to figure out how to find the structure members' datatypes. You retrieve information about a structure data member the same way you retrieve information about enumeration values: through a call to GetVarDesc(). Recall that GetVarDesc() populates a VARDESC structure with information about a particular data member. One of the members of the VARDESC structure is called elemdescVar, which is an instance of another structure called ELEMDESC. The ELEMDESC structure contains information about the type of a specific variable. This means that the elemdescVar data member found in the VARDESC structure populated by the call to GetVarDesc() contains the datatype of the structure's data member. The ELEMDESC structure contains a data member called tdesc, of type TYPEDESC. The TYPEDESC type describes a specific datatype. It, too, is a structure, and one of its members is called vt. This data member is a VARTYPE variable and holds the actual datatype value, which is the same datatype you use in a VARIANT to describe a VARIANT datatype. It has values such as VT_BSTR, VT_I4, or VT_R8. A code example will make this clearer: 



	VARDESC *	pVarDesc;
	hResult = pTypeInfo->GetVarDesc(
		nEnumIndex,
		&pVarDesc);
	if(hResult == S_OK)
	{
		ELEMDESC * pElemDesc;
		TYPEDESC * pTypeDesc;
		VARTYPE    vt;

		pElemDesc = 
			&(pVarDesc->elemdescVar);
		pTypeDesc = 
			&(pElemDesc->tdesc);        
		vt = pTypeDesc->vt;
		// "vt" now holds the type of 
		// variable
	}

To sum up, you find a structure data member's datatype by calling Get-VarDesc() for a data member and finding the datatype in pVarDesc->elem- descVar.tdesc.vt. You access data for unions just as you access structure data. The only difference between structures and unions is that all the data members of a union have an offset of zero. This makes sense, given the definition of a union. 

Access Interface Data
If GetTypeInfoType() returns TKIND_ DISPATCH or TKIND_INTERFACE for a given object index, you can use the ITypeInfo interface pointer returned by GetTypeInfo() for that same index to access interface data. 

Unlike enumerations, structures, and unions, a COM interface doesn't carry any variables. Instead, it carries a set of methods. You'll find the number of methods on an interface in the cFuncs member of the structure's TYPEATTR structure, and you'll use the ITypeInfo method GetFuncDesc() to read a method's description. The method takes two parameters: The zero-based index of the method whose information you want to retrieve, and the address of a FUNCDESC structure that holds the method information. You need to call another method, ReleaseFuncDesc(), to free the memory used by the FUNCDESC structure when it's no longer needed. As you can see, processing method descriptions is similar to processing element descriptions: 



if((eTypeKind == TKIND_DISPATCH)
|| (eTypeKind == TKIND_INTERFACE))
{
	int		 nFuncIndex;
	TYPEATTR * pTypeAttr;
	pTypeInfo->GetTypeAttr(
		&pTypeAttr);
	for(nFuncIndex = 0;
		nFuncIndex <
			pTypeAttr->cFuncs;
		nFuncIndex++)
	{
		FUNCDESC * pFuncDesc;
		pTypeInfo->GetFuncDesc(
			nFuncIndex,
			&pFuncDesc);
		// work with FUNCDESC here
		pTypeInfo->ReleaseFuncDesc(
			&pFuncDesc);
	}
}

The FUNCDESC structure contains several pieces of information about the method. It contains data members describing the number of parameters that the method uses, the method's calling convention, and its member ID. Finding out other information about the method takes some digging. 

First, you need to find the name. As it turns out, one function call gives you not only the name of the method, but also the names of all the parameters used in a call. Use your old friend GetNames() for this, but this time, remember you'll get back a group of strings�one for the name of the function and one for each parameter. The cParams member of the FUNCDESC structure tells you how many parameters the function uses; and, because you'll also need to get back the name of the function itself, you'll need to create an array of BSTRs large enough to hold all of these strings: 



nNamesArraySize =
	pFuncDesc->cParams + 1; 
bstrNames = 
	new BSTR [nNamesArraySize]; 
_pITypeInfo->GetNames(
	_pFuncDesc->memid,
	bstrNames,
	nNamesArraySize,?
	&nReturnedNames);
	
At this point, the name of the function is in the zeroth element of the array, and the parameter names follow it. This rule has one important exception for methods that implement "property put" functionality. Property put methods have IDL signatures like these: 



[propput, id(1)] HRESULT 
	Size([in] long lSize); 
	
MIDL might or might not drop the parameter name during compilation. In this case, you'll get one less name back than you're expecting. Using the rule above, you should expect two names from your call to GetNames(): One for the function name ("Size") and one for the parameter ("lSize"). However, if MIDL felt like dropping the parameter name during compilation, you'll only get back the name of the function. This is why it's important to check the value of GetNames()'s fourth parameter to find out how many names were actually returned. This also explains why other type library tools, such as OLEVIEW, display a generic name like rhs for these parameters, regardless of what you specify in the original IDL. 

The same ELEMDESC structure you use to get element information for structures and unions describes each pa- rameter's datatype. The FUNCDESC structure contains a data member called lprgelemdescParam. This data member is a pointer to an array of ELEMDESC structures, and one ELEMDESC structure will be in the array for each parameter. The ELEMDESC structures will be in the same order as the names of the parameters returned by GetNames(). For example, the element information for the first parameter named by GetNames() will be in the zeroth element of the lprgelemdescParam array. 

Access CoClass Data 

If GetTypeInfoType() returns TKIND_ COCLASS for a given object index, you can use the ITypeInfo interface pointer returned by GetTypeInfo() for that same index to access component class data. From the type-library point of view, a COM coclass contains a collection of implemented interfaces. You'll find the number of implemented interfaces on a COM component in the cImplTypes member of the structure's TYPEATTR structure. 

The interesting part about getting the interface information for a COM class is that you do it though a call to the ITypeInfo methods GetRefTypeOf-ImplType() and GetRefTypeInfo(). The theory is that the interfaces you use on this object are defined elsewhere, either in the same type library or a different type library. These ITypeInfo methods work by specifying the location of the interface definition as a handle, which you can dereference to get back the description of the interface. This handle can ultimately resolve to a definition in the same type library or an external type library. The nice thing about the handle: You don't have to know details concerning what type library the interface is defined in or what index it's found on. 

The GetRefTypeOfImplType() method is called first. It takes two parameters. The first parameter is the zero-based index of the interface whose information you want to retrieve, and the second parameter is an address of the datatype HREFTYPE. This type is a handle to a type description, and a call to the GetRefTypeOfImplType() method fills in its value. A call to GetRefType-Info() dereferences the handle. GetRef-TypeInfo() takes the handle in and returns an ITypeInfo pointer pointing to the requested interface: 



HREFTYPE	hRefType;
ITypeInfo * pInterfaceITypeInfo;

_pITypeInfo->GetRefTypeOfImplType(
	nIndex,
	&hRefType);
_pITypeInfo->GetRefTypeInfo(
	hRefType,
	&pInterfaceITypeInfo);
	
The ITypeInfo interface retrieved from the call to GetRefTypeInfo() points to an interface type library object. In other words, its TYPEKIND value is either TKIND_DISPATCH or TKIND_ INTERFACE, and you work with it just like any other interface object. It carries the same information as interface information for interfaces defined in the type library. 

Although I've presented a lot of information on type libraries, you'll find even more in the source code for a type library viewer I created using Microsoft Foundation Class Library and Visual C++ 6.0. Download the source code from the VCDJ Web site to see how you can use your new knowledge in a Visual C++ application (see the Go Online box). You can use this code as a starting point for your own exploration of type library internals. Enjoy! 




Jeff Ferguson is a senior consultant for Magenic Technologies, a technology consulting company dedicated to solving clients' business problems using Microsoft tools and platforms. Jeff has been developing software with Microsoft C and C++ compilers for more than 10 years and fondly remembers the days when Microsoft C 5.1 shipped on 51/4" floppies. Reach him by e-mail at JeffF@magenic.com. 
   Links
� Microsoft�s COM Web site: (www.microsoft.com/com)  
Get the Code 
   Get the code for this issue here. 
   Premier Club members can download the code from each article individually. Get the code for this article here. 
  Join the Premier Club

 

C++ Zone Links
� Product Review of the Week 
BugTrapper 3.0

� Site of the Week
Bytamin-C

� Book Review of the Week
The Humane Interface: New Directions for Designing Interactive Systems

� Tip of the Day
Short-Circuiting String Comparison

� Download of the Week
BugTrapper 3.0 
 


c0Title: Using Registry Keys to Store User Program Information
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/1999/jun99/tip2.asp
By Brian Noyes 
An important part of making your program user friendly is having it remember user settings and preferences between sessions. Saving these settings in the registry is also a requirement for the Windows Logo program. 

The process to do so simply involves making sure your program is aware of where in the registry it is supposed to store this information, and then using some MFC functions to do the reading and the writing when necessary. The convention for persisting user preferences and settings between application sessions is to store these settings under the HKEY_CURRENT_USER\Software key in the registry. The convention also includes using sub-keys to the above with a hierarchy that starts with the name of the company who developed the software, followed by the application name the settings are for, and then any sub-keys and values you want to add for categorizing and saving your settings. For example, HKEY_CURRENT_USER\Software\DomeWorks\DeskShow holds the registry keys and values for my DeskShow program. 

The code to accomplish the above is simple. To set your company name, use the CWinApp::SetRegistryKey() function in your InitInstance() function. For example: 

BOOL MyApp::InitInstance()
{
SetRegistryKey(_T("DomeWorks"));
�
}

 

If you desire the next sub-key to be the name of the project, then nothing further is required prior to reading and writing values to the registry. MFC will set the project name as the profile name by default. However, if you want to modify it, perhaps because this project is a sub-project of the main application, simply follow the code above with code like this: 

free((void *)m_pszProfileName);
m_pszProfileName = _tcsdup(_T("DeskShow"));

 

Now all you have to do is use the CwinApp functions GetProfileString(), GetProfileInt(), GetProfileBinary(), WriteProfileString(), WriteProfileInt(), and WriteProfileBinary() wherever you need to to get and set values to the registry. For example: 

void MyClass::MyFunction() 
{
CString lastfilename = AfxGetApp()->GetProfileString(_T("Initialize"),_T("LoadFile"),_T(""));
AfxGetApp()->WriteProfileInt(_T("Epochs"), T("CurrentTime"), m_currtime);
�
}

 

The first call will retrieve the LoadFile value from registry key HKEY_CURRENT_USER\Software\DomeWorks\DeskShow\Initialize, and will return an empty string if the value is not found. The second will write the member variable m_currtime to the CurrentTime value under the Epochs sub-key to DeskShow. 

These features make using the registry for program settings a piece of cake. 


c0Title: Using Windows Hooks with MFC
c1Code:
http://www.devx.com/premier/mgznarch//vcdj/1999/aug99/hooks1.asp 
By Eduard Koller 

Introduction

System Notes 
To replicate the steps described in this article, you will need: 
Windows NT 4.0 or higher, Windows 95 or higher 
Visual C++ 5.0 or higher 
 
A Windows hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system for intercepting messages at various points along the message processing sequence. Such subroutines can process certain types of messages (e.g., mouse actions, keystrokes) before they reach the target window procedure. 

The subroutine can act on the messages and, in some cases, modify or discard them. The subroutines that receive the events are application-defined callback functions called hook procedures and are classified according to the type of event they intercept. For each type of hook, Windows maintains a separate hook chain, i.e., a list of pointers to some hook procedures. 

When a message occurs that is associated with a particular type of hook, the system passes the message to each hook procedure referenced in the hook chain, one after another, beginning at the end of the chain. This is known as "calling the hooks." Attaching one or more hook procedures to a hook is known as "setting the hook." 

The action a hook procedure can take depends on the type of hook involved. The hook procedures for some types of hooks can only monitor messages; others can modify messages or stop their progress through the chain, preventing them from reaching the next hook procedure or the destination window. 

Following are some of the more common hook types: 

WH_GETMESSAGE hook: Windows calls your hook function each time your application calls a GetMessage() or a PeekMessage() function to request a message from the application's message queue. The hook function can change or remove the message before the application processes it. 
WH_CALLWNDPROC hook: Windows calls your hook function immediately before the window procedure is called (as a result of a SendMessage function call) for every window in your application thread. The hook procedure can change or remove the message. However, this type of hook is extremely inefficient, because the hook function is called for every message. 
WH_KEYBOARD hook: Windows calls your hook function for each keystroke message (key up and key down) before the message is placed in the application's message queue. The hook function can change or discard keystrokes. 
WH_MOUSE hook: Windows calls your hook function for each mouse message before the message is placed in the application's message queue. The hook function can change or discard mouse messages. 
WH_MSGFILTER and WH_SYSMSGFILTER hooks: Windows calls your hook function for all messages meant for dialog boxes, message boxes, scroll bars, menus for an application, or for the system, respectively. The hook function can change or discard these messages. 
WH_SHELL hook: Windows calls your hook function when actions occur to top-level windows. For example, the hook procedure is called when a top-level window is created or is about to be destroyed. This is a notification-only hook, so the hook procedure cannot modify or discard the message. 
In addition, Windows 2000 offers two new hook types: WH_KEYBOARD_LL and WH_MOUSE_LL. They are lower level ("LL") versions of the traditional keyboard and mouse hooks, and are deployed for the Microsoft accessibility initiative, which makes Windows easier to use for people with physical disabilities. By seeing the mouse and keyboard actions earlier, and in a more raw form than normal hooks allow, programs can better anticipate or respond to the user. 

Hooks tend to slow down the system because they increase the amount of processing the system must perform for each message. For this reason, hooks are not supported under Windows CE. You should install a hook only when necessary, and remove it as soon as possible. 

A hook procedure can be global, monitoring messages for all threads in the system, or it can be thread specific, monitoring messages for an individual thread. Some hooks may be set with system scope only (e.g. WH_SYSMSGFILTER), but most hooks have either system or thread scope. If an application installs a hook procedure for one of its own threads, the hook procedure can be in either the same module as the rest of the application's code or in a DLL. If the application installs a hook procedure for a thread of a different application or a hook procedure with a system-wide scope, the procedure must be in a DLL, otherwise it can't be loaded in the address space of another process. 

There are many different scenarios in which hooks can be useful. Hooks may be used to: 

provide context-sensitive help by pressing the F1 key to menus, dialog boxes, and message boxes (WH_MSGFILTER); 
trap system-reserved key combinations (e.g. alt-tab, ctrl-esc) and, if necessary, discard them. (WH_SHELL); 
redirect all keyboard and mouse events to one window (WH_KEYBOARD and WH_MOUSE); 
implement ToolTip windows to provide extended functionality (WH_KEYBOARD and WH_MOUSE). 
To manage the hooks chain, applications use the following Win32 APIs: SetWindowsHookEx(), UnhookWindowsHookEx(), and CallNextHookEx(). 

Setting the hook 

SetWindowsHookEx() is used to set a hook procedure to a specific hook: 

HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod,
			 DWORD dwThreadId);

 

Its arguments have the following meaning: 

idHook An integer code describing the type of hook procedure to be installed (e.g. WH_MOUSE, or WH_SHELL). See the Platform SDK Help for a complete list of the hook types. 
lpfn The address of the hook procedure (in a dynamic-link library or in the code associated with the current process). 
hMod Handle to the DLL containing the hook procedure. This value must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and the hook procedure is within the code associated with the current process.  
dwThreadId The thread ID for which the hook procedure is to be associated. If this parameter is zero, the hook procedure has system scope and is associated with all existing threads in the system. An application can use the GetCurrentThreadId() function to obtain the thread handle for hooking the current thread. 

Releasing the hook 

UnhookWindowsHookEx() is used to remove a filter function from a hook's chain: 

BOOL UnhookWindowsHookEx(HHOOK hhk);

 

This function takes the hook handle returned from SetWindowsHookEx() and returns a value indicating whether the hook was removed (TRUE) or not (FALSE). To get extended error information, call GetLastError(). 

The hook procedure 

Hook procedures are functions that are attached to a hook. Because hook procedures are called by Windows and not by an application, they are sometimes referred to as callback functions. All hook procedures must have the following signature: 

LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);

 

HookProc is a placeholder for the actual hook procedure name. 

The nCode parameter is a code that the hook procedure uses to determine the action to perform. The value of the hook code depends on the type of the hook; each type has its own characteristic set of hook codes. If Windows sends a negative hook code to a hook procedure, the hook procedure must call CallNextHookEx() with the parameters Windows passed to the hook procedure. The hook procedure must also return the value returned by CallNextHookEx(). 

The values of the wParam and lParam parameters depend on the event that causes the hook to be called. For a complete list of arguments and their meanings for each hook type, see the corresponding documentation in the SDK. 

The standard way to process the information from a hook procedure is to send a WM_COPYDATA message to the client's main window. The WM_COPYDATA message is sent when an application passes data to another application. Its wParam and lParam have the following meaning: 

wParam = (WPARAM) (HWND) hwnd; 
lParam = (LPARAM) (PCOPYDATASTRUCT) pcds;

 

Here, hwnd is a handle to the window to which the data should be passed, and pcds is a pointer to a COPYDATASTRUCT structure that contains the data to be passed. See MSDN for more documentation about the WM_COPYDATA message and the COPYDATASTRUCT structure. 

Suppose you want to set a hook to spy all the messages passing through all the windows in the system, and then send to the client application the information about those messages (i.e. hwnd, lParam, wParam and, of course, the message ID). First, you define a data structure to contain the information you want to send: 

typedef struct
{
  WPARAM wParam;
  LPARAM lParam;
  DWORD  dwExtraData;
} CLIENTMSGDATA;

CLIENTMSGDATA MsgData;
COPYDATASTRUCT gcds = { 0, sizeof(CLIENTMSGDATA), &MsgData };

 

Next, you write the hook procedure. This procedure should be attached to a WH_GETMESSAGE hook, using the SetWindowsHookEx() function: 

LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam )
{
  MSG *pMsg = (MSG*)lParam;
  HWND hWnd = pMsg->hwnd;
  HWND hwndClient = FindWindow(CLIENTWINDOWCLASS, CLIENTWINDOWNAME);
	  
  if (nCode < 0 || hwndClient == NULL)
    return CallNextHookEx(NULL, hc, wParam, lParam);

  if (nCode == HC_ACTION)
  {
    MsgData.wParam = wParam;
    MsgData.lParam = lParam;
    gcds.dwData = uiMessage;

    SendMessage(hwndClient, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)&gcds);
    return 1;
  }

  return 0;
}

 

To preserve the clarity, I eliminated some parameter testing (e.g., it's a good idea to check if the spied window is not the client's window). 

 

Calling the next function in the hook chain 

When a hook is set, Windows calls the first function in the hook's filter function chain, and the responsibility of Windows ends. To ensure that the next function in the hook chain is called, the current hook procedure must call the CallNextHookEx() function, which passes the hook information to the next hook procedure in the current hook chain. A hook procedure can call this function either before or after doing its work: 

LRESULT CallNextHookEx(HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam);

 


The first parameter of CallNextHookEx() is the handle to the current hook. An application receives this handle as a result of a previous call to the SetWindowsHookEx() function. Windows currently ignores this value, so you can simply set it to NULL. The next three parameters are the parameters that Windows passes to the current hook procedure, specifying the hook code, wParam and lParam. 

Calling CallNextHookEx() is optional, but it is highly recommended. However, a hook procedure may not want to pass a message (e.g. if it has modified that message) to the other hook functions on the same chain. In particular, when a hook allows a hook procedure to discard a message (as I mentioned, not all hook types allow it) and the hook procedure decides to do so, the function must not call CallNextHookEx(). 

As I mentioned in the beginning of the article, in most cases the hook procedure must reside in a DLL, and it is usually exported from that DLL. As a result, there are some things to be considered when working with DLLs using MFC. 

Exporting a class from a DLL 

Let's go over some basic concepts about exporting C++ classes from DLLs. 

In an extension MFC DLL, you cannot simply add your own C++ classes to the project to export them. You must add the macro AFX_EXT_CLASS to the class declaration, as follows: 

class AFX_EXT_CLASS CMySpecialHook : public CObject 
{
...
}

 


This modification goes in the H file that's included in both the DLL project and the client project. 

In a pure Win32 DLL, the easiest way to export a function or a class from a DLL is to use the __declspec(dllexport) directive. After creating a new project using the Win32 Dynamic-Link Library project wizard and creating a new class (called, for example, CMySpecialHook), you'll need to change the class definition to look like the following: 

class __declspec(dllexport) CMySpecialHook
{
...
}

 


This modification goes in the header file included in the DLL project. Where the DLL had to export the class, the client application must import it by adding in the header file the expression __declspec(dllimport) in the class definition. If you want to use the same header to both DLL and client project, you should create a separate header file that looks like the following: 

#ifndef _HOOK_DECL_H
#define _HOOK_DECL_H

#ifdef _SpecialHook
#define HOOKDLL_API __declspec(dllexport)
#else
#define HOOKDLL_API __declspec(dllimport)
#endif

#endif // _HOOK_DECL_H

 


Then, you must include this header file before the class definition, which should look like this: 

class HOOKDLL_API CMySpecialHook;

 


In that way, the same class definition can be used for both the DLL and client project, under the assumption you have defined the symbol _Special_hook in your DLL project. (See also "MFC Extension DLL FAQs" by Scott Wingo and George Shepherd in the January 97 issue of VCDJ.)

Sharing data between processes 

If a 32-bit application installs a system-wide hook with the hook callback function in a DLL, this DLL is mapped into the address space of every application for which the hook event occurred. 

Under Win32, each process has its own virtual address space. That means the data owned by one process is completely invisible to the data owned by all other processes. From this point of view, the 32-bit model offers significant advantages. Making separate instances of a DLL invisible to each other prevents critical errors in one instance of the DLL from affecting the health of the other processes using it. 

However, under certain circumstances, hook callback functions need to share some data variables (such as HHOOK or a window handle) among all mappings of the DLL. This can be accomplished by using one of the many IPC mechanisms available (Read Davide Marcato's article covering IPCs in Win32 at http://www.vcdj.com/online/articles/mar98/ipc1.asp for detailed information). In this case I'll use the easiest of the group: shared data sections. 

Every 32-bit DLL (or EXE) is composed of a collection of sections. These sections can have the following attributes: READ, WRITE, SHARED, and EXECUTE. Using the #pragma pre-processor command in the DLL source file, you can create a shared data section, where you can place the data to be shared among different mappings. Note that the data must be initialized for this to work: 

// Create a named data section
// By convention, each section name begins with a period
// However, the period is not required

#pragma data_seg(".SHARDATA")

 HHOOK g_hHook           = NULL;  // Global hook handle 
 HWND  g_hWnd            = NULL;  // Handle of window to be monitored
 char  g_szClassName[20] = { 0 }; // Buffer for class name to be monitored

#pragma data_seg()

 


You must also tell the linker that the variables in the section you defined are to be shared. That is, you must specify the correct sharing attributes for your named section in the dynamic link library's .DEF file. To do this, add a SECTIONS statement to the DLL's .DEF file: 

SECTIONS
   .SHARDATA  Read Write Shared

 


Alternatively, you can accomplish the same job by setting the linker switch in your code. To do this, include the following lines in your code, preferably near the #pragma data_seg (".SHARDATA") line: 

// Set sharing attributes for the data section
  #pragma comment(linker, "/SECTION:.SHARDATA,RWS")

 


Now, all the variables defined in the .SHARDATA data section will be shared among all DLL's mappings into the address spaces of other applications. 

Callback thunking

 


As good C++ programmers, our intention is to provide a generic wrapper class to encapsulate all the windows hooks-related issues. In the optimal case, the programmer will only have to derive from my CHook class, and to override (if necessary) a member function, namely the hook procedure. Unfortunately, the hook procedures, as any callback functions, are prototyped as C functions, which do not associate data with operations on that data. Therefore, one cannot use as callback a normal member function, which needs the hidden "this" pointer. 

Sometimes, it is possible to handle callbacks with member functions, by keeping a pointer in a collection indexed by a return value or passing a pointer in a parameter for application-supplied data. (See Davide Marcato's article, "Encapsulating Windows Timers in MFC," in the January 98 issue of VCDJ.) However, these techniques are dependent on the particularities of the callback functions and not suitable for our case. 

The solution appears from a deeper observation of the ATL source code, which ships with VC++ 6.0. The ATL team used thunks to give WindowProc access to the this pointer of the CWindowImpl<> class (See also Richard Grimes' article, "ATL and Win32 Applications" in the February 99 issue of VCDJ.). Generally, a thunk is a stubroutine, in an overlay-programming environment, which loads and jumps to the correct overlay. 

In our case, we have to simulate the function call mechanism by putting the this value in the ECX CPU's register, and forcing a jump to the member function's code. As in the ATL code, I defined a helper class CThunk to "wrap" the method to be used as a callback. The difference between my example and the ATL code is in the CPU's instructions, which are completely different because we are using the thiscall calling convention, i.e. the this pointer is stored in ECX. 


Here is the complete code for the class, which has only two methods: 

#pragma pack(push, 1) // Force byte alignment 

template <class T> class HOOKDLL_API CHKThunk
{
  BYTE    m_mov;          // mov ecx, <0xB9>
  DWORD   m_this;         // pThis
  BYTE    m_jmp;          // jmp func     <0xE9>
  DWORD   m_relproc;      // jmp is relative
public:
  typedef void (T::*TMPFN)();
  void InitThunk(TMPFN method, const T* pThis)
  {
    union {
      DWORD func;
      TMPFN method;
    } addr;

    addr.method = method;
    m_mov = 0xB9;
    m_this = (DWORD)pThis;
    m_jmp = 0xE9;
    m_relproc = addr.func - (DWORD)(this+1);
    FlushInstructionCache(GetCurrentProcess(), this, sizeof(*this));
  }
  FARPROC GetThunk() const {
    _ASSERTE(m_mov == 0xB9);
    return (FARPROC)this; }
};

#pragma pack(pop) // CHKThunk

 


Now, we simply derive the hook class from CHKThunk. The SetWindowsHookEx() function expects a callback function as a second argument, which normally cannot be a member in any class. After initializing the thunk in CHook's constructor with the address of our HKHookProc() member function, we simply pass to SetWindowsHookEx() the pointer returned by GetThunk(). This pointer can be interpreted as the address of a piece of code, which finally calls the HKHookProc() member function: 

class HOOKDLL_API CHook: public CHKThunk<CHook>
{
public:
  HHOOK m_hhook;

  CHook(HHOOK hHook = NULL): m_hhook(hHook)
  {
    InitThunk((TMPFN)HKHookProc, this);
  }
  LRESULT HKHookProc(int nCode, WPARAM wParam, LPARAM lParam);
  BOOL Hook();
  BOOL UnHook();
};

 


Of course, this implementation is characteristic of the Intel X86 architecture, but the same technique can be used for any platform. For example, the window thunk used by ATL (see the file atlcom.h, which ships with VC++ 6.0) is implemented for both machines based on Intel and Alpha architectures. 

Examples 

For a better understanding of the hook-related issues, I'll present three examples: 

customizing the "Browse For Folder" dialog box (WH_CBT hook); 
providing context-sensitive help by pressing the F1 key (WH_MSGFILTER hook); 
redirecting all keyboard and mouse events to one window (WH_KEYBOARD and WH_MOUSE hooks). 
All the examples consist of two parts: a hook DLL, which implements the hook class and its methods, and a client application which installs the hook, receives messages from the hook procedure, and eventually releases the hook. Once a general hook class is defined, the differences between the three hook DLLs consist only of the first parameter being passed to SetWindowsHookEx() and the implementation of the hook procedure. For this reason, the DLL project is very similar to the three examples, while the client applications are, of course, completely different. 

Customizing the "Browse for Folder" dialog box 

For many applications, the familiar Browse for Folder dialog box shown in Figure 1 should be enough to enable the user to select a folder or a special location. 


Figure 1

But for many other applications, a customized dialog, like that shown in Figure 2, would be more appropriate. 


Figure 2

Unfortunately, there is no standard way to customize the Browse for Folder dialog box. You cannot get a handle to the dialog, move/resize its controls and/or add new ones because you cannot have the handle of the dialog before it is displayed. On the other hand, if we try to call FindWindow() until the dialog is created, we obtain the handle for the dialog too late, so the user will see the standard dialog before it is modified. 

A natural approach for this problem is to install a system-wide hook to be notified when the dialog is created, or just before it is activated and displayed. We have two options: a WH_SHELL hook, or a WH_CBT hook. If we try to use the WH_SHELL hook, we'll obtain the handle for the dialog during its creation process, which would be too early for our purpose. 

Trying to resize the dialog's window at this time won't help, because Windows will set the default values for the dialog's size and position after the creation process, i.e., after returning from our hook procedure. 

The second option is the correct one. The system calls a WH_CBT hook procedure before activating, creating, destroying, minimizing, maximizing, moving, or sizing a window. For our purpose, we are interested in activating the dialog box, which requires a value of HCBT_ACTIVATE for the hook code nCode, sent as a parameter to the hook procedure.


Creating the hook DLL for example 1. 

Using AppWizard, create a new MFC extension DLL project we'll call "HookDll." Leave all the other options on default, then press "Finish." 
Then, add a thunk class, as described in the section "Callback thunking." Name this class CHKThunk, then derive a hook class from it. Name this new class CHook. 
Implement for CHook class the constructor and the following methods: HKHookProc(), Hook(), UnHook(). If you want to derive later from CHook, make these functions virtual. Use #pragma to share the global hook object g_Hook and the module's instance g_hInst, and don't forget to #define HOOKDLL_EXPORTS in the DLL project. 
The code for the Hook() and UnHook() functions is very simple. The first function sets the hook, while the second one releases it. 

BOOL CHook::Hook() 
{
  if (m_hhook == NULL)
    m_hhook = SetWindowsHookEx(WH_CBT, (HOOKPROC)GetThunk(), 
                               g_hInst, NULL);
  return (BOOL)m_hhook;
}

BOOL CHook::UnHook()
{
  BOOL fOK = TRUE;
  // Only uninstall the hook if it was successfully installed.
  if (m_hhook != NULL)
  {
    fOK = UnhookWindowsHookEx(m_hhook);
    m_hhook = NULL;
  }
  return(fOK);
}

 


We need to send to the main application only the handle of the "Browse for folders" dialog, so we won't need a CLIENTMSGDATA structure to store any additional information. Thus, we'll simply set to NULL the last member of the COPYDATASTRUCT structure: 

COPYDATASTRUCT gcds = { 0, 0, NULL};

 


In the Hook procedure HKHookProc(), we'll find the main window of the client application, then we'll send them a WM_COPYDATA message. 

The wParam for the WM_COPYDATA message is intended for passing the handle of the window, which sent the message. Our DLL isn't associated with any particular window, so we'll set wParam to be the handle of the "Browse for Folders" dialog. 

SendMessage(hwndClient, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)&gcds);

 


Alternatively, we can store the same handle in the dwData member of COPYDATASTRUCT, which is sent as lParam with the same message: 

gcds.dwData = (DWORD)hwnd;

 


Here is the complete code for the hook function: 

LRESULT CHook::HKHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
  if ( nCode == HCBT_ACTIVATE) 
  {
    char szBuffer[256];
    HWND hwnd = (HWND)wParam;
    GetWindowText(hwnd, szBuffer, 256);
    
    if (strstr(szBuffer, "Browse"))
    {
  //  Since a system-wide hook considerably slows down the 
  //  system, is a good ideea to release the hook at this time
      UnhookWindowsHookEx(m_hhook);
      
      HWND hwndClient = FindWindow(NULL, "HKBrowse");	  
      if(hwndClient == NULL)
        return CallNextHookEx(m_hhook, nCode, wParam, lParam);

      gcds.dwData = (DWORD)hwnd; 
      SendMessage(hwndClient, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)&gcds);
    }
  }
  return CallNextHookEx(m_hhook, nCode, wParam, lParam);
}

 


Creating the client application for example 1. 

Using AppWizard, create a dialog-based MFC application we'll call "HKBrowse." Leave all the other options on default, then press "Finish." 
After resizing the application's main dialog (its default ID will be IDD_HKBROWSE_DIALOG), add a static text with the ID: IDC_FOLDER, to put the folder name in. Then add a push-button, to allow the user to open a "Browse for Folders" dialog. Name this button "Browse...", give it an ID: IDC_BROWSE, then use ClassWizard to add a message handler to it. Let's name this CHKBrowseDlg::OnBrowse(). Below is a sample implementation for it: CHKBrowseDlg::OnBrowse()
{
  BROWSEINFO bi;
  LPITEMIDLIST pidl;
  char szFolderName[MAX_PATH];

  bi.hwndOwner      = m_hWnd;
  bi.pidlRoot       = NULL;
  bi.pszDisplayName = szFolderName;
  bi.lpszTitle      = _T("Select a folder:");d
  bi.ulFlags        = BIF_RETURNONLYFSDIRS | BIF_EDITBOX ;
    //Use the BIF_EDITBOX flag only if you have the version 4.71 
    //or above of IE dll's, i.e. if you have IE4 or later
  bi.lpfn           = NULL;
  bi.lParam         = 0;
  bi.iImage         = 0;

  pidl = SHBrowseForFolder(&bi);
  if (pidl)
  {
    if (SUCCEEDED(::SHGetPathFromIDList(pidl, szFolderName)))
      SetDlgItemText(IDC_FOLDER, szFolderName);

    LPMALLOC pMalloc;
    //Retrieve a pointer to the shell's IMalloc interface
    if (SUCCEEDED(SHGetMalloc(&pMalloc)))
    {
      // free the PIDL that SHBrowseForFolder returned to us.
      pMalloc->Free(pidl);
      // release the shell's IMalloc interface
      pMalloc->Release();
    }
  }

 

Insert a new dialog box template with the ID: IDD_CHILDDLG, containing the controls you intend to add to the "Browse for folders" dialog. 
You must specify the WS_CHILD and WS_CLIPSIBLINGS styles and should specify the DS_3DLOOK and DS_CONTROL styles. The system requires the WS_CHILD style because your template defines a child dialog of the default dialog box, and WS_CLIPSIBLINGS style ensures that the child dialog box does not paint over any of the controls in the default dialog box. You also must specify the WS_VISIBLE style in the dialog-box template if the dialog box should appear when the parent window is created. Otherwise, you must call ShowWindow(). 

Use ClassWizard to attach to the template a CDialog-derived class. Let's name this CChildDlg. 
Use ClassWizard to attach to the controls in your dialog template data members and/or message-handler functions. 
Add to CHKBrowseDlg a member variable to keep a pointer to the CChildDlg object you'll use for customizing the "Browse for folders" dialog: class CHKBrowseDlg : public CDialog
{
// ...
  CChildDlg* m_pDlg;
// ...
}

 

Allocate memory for the pointer in the constructor of CHKBrowseDlg, and deallocate it in the destructor.

Now, prepare the application to use the hook class: 
Include the file HookDll.h, as created within the HookDll project 
Declare the global hook object, which is also declared in the HookDll project as being shared: HOOKDLL_API CHook  g_Hook = NULL;  // The one and only hook object

 

Add HookDll.lib to your project 
In the handler function CHKBrowseDlg::OnBrowse(), set the hook before calling SHBrowseForFolder(), and release it immediately after that: ...
g_Hook.Hook();
pidl = SHBrowseForFolder(&bi);
g_Hook.UnHook();
...

 

Finally, use ClassWizard to add to the main dialog class a message handler for the WM_COPYDATA message:

BOOL CHKBrowseDlg::OnCopyData(CWnd* pWnd, 
                              COPYDATASTRUCT* pCopyDataStruct) 
{

// pWnd is the pointer to the Browse for folders dialog, 
// as sent from the Hook procedure.
// you can obtain its handle from the dwData member of 
// pCopyDataStruct

  CRect rect;
  //  Expand the Browse for folders dialog, to show our controls...
  pWnd->GetWindowRect(&rect);
  rect.InflateRect(50, 0);
  pWnd->MoveWindow(&rect,TRUE);

  // ...and create the child dialog as child of pWnd
  m_pDlg->Create(CChildDlg::IDD, pWnd);

  return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}

 


Because the child dialog you created is a child of the "Browse for Folders" dialog, it is automatically destroyed when the parent window is destroyed. Thus, you will not have to call DestroyWindow() for it. However, be sure to eventually delete the memory you allocated for the pointer to the corresponding CDialog-derived object. 


Provide context-sensitive help by pressing the F1 key 

Applications written for Windows usually provide context-sensitive help, allowing the user to get help on a particular window, dialog box, command, or toolbar button. MFC makes it simple to add context-sensitive help to your application. 

Unfortunately, the Microsoft Foundation Classes assume a single help file per application. That help file must have the same name and path as the application (.EXE -> .HLP). That is not always desirable. On the other hand, you may want to make your application respond to F1 by launching other modules than Winhelp.exe. For example, you may want to use the new HTML help present in IE 4.0 or above, or you may want to use your custom help application. 

To provide custom F1 key processing, we'll install a WH_MSGFILTER hook. This kind of hook can be used to monitor messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar, but before the message generated by the input event is processed. 

Creating the hook DLL for example 2. Follow steps 1-3 from the preceding example to create the DLL project and insert the CHook class in this project. This time we don't need a system-wide hook but a thread-specific one. Thus, in the CHook::Hook() function, call SetWindowsHookEx() with a call to GetCurrentThreadId() as the last argument: 

m_hhook = SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)GetThunk(), 
                            g_hInst, GetCurrentThreadId());

 


As in the previous sample, our hook procedure will find the client's main window, then send a WM_COPYDATA message. For the same reasons as in the case of "Browse for Folders," we'll set to NULL the last member of the COPYDATASTRUCT structure, passing the handle to the dialog in the dwData member. After sending the WM_COPYDATA message to the application, we should return TRUE to indicate that this message was handled. 

We are interested in monitoring only messages generated as a result of an input event in a dialog box, which means a value of MSGF_DIALOGBOX for the hook code nCode, which is sent as a parameter to the hook procedure. Our hook procedure has to check whether the message (we get it in lParam) is an F1 keystroke; in this case, the hWnd argument will contain the HWND for the dialog control that the user wants help information on. 

Here is the complete code for the hook function: 

LRESULT CHook::HKHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
 // if (nCode < 0), return CallNextHookEx immediately !

 if (nCode >= 0)    
 {
  if (nCode == MSGF_DIALOGBOX)
  {
   MSG * ptrMsg = (MSG *)lParam;
 
   if ((ptrMsg->message == WM_KEYDOWN) && (ptrMsg->wParam == VK_F1 ))
   {
    HWND hwndClient = FindWindow(NULL, "Context F1");	  
    if(hwndClient == NULL)
      return CallNextHookEx(m_hhook, nCode, wParam, lParam);

    gcds.dwData = (DWORD)ptrMsg->hwnd; 
    SendMessage(hwndClient, WM_COPYDATA, (
                WPARAM)ptrMsg->hwnd, (LPARAM)&gcds);
    //  prevent the system from passing the message to the rest of 
    //  the hook chain or the target window procedure. 
    return 1L; 
   }
  }
 }
 return CallNextHookEx(m_hhook, nCode, wParam, lParam);
}

 


Creating the client application for example 2. This time we'll implement a simple dialog-based application, which illustrates how to implement F1-help for a message box. We'll set a hook before displaying the message box on the screen, and release it immediately after the user closes the message box. 

As in the preceding example, use AppWizard to create a dialog-based MFC application without support for ActiveX Controls. Name it "ContextF1." Since you intend to implement your custom F1-key processing, you do not need to select the Context-sensitive help check box in step 4, unless you also plan to use WinHelp in the application. 

Then, add support for the hook class to the application: 

Include the file HookDll.h, as created within the HookDll project; 
Declare the global hook object, which is also declared in the HookDll project as being shared: 
HOOKDLL_API CHook g_Hook = NULL; // The one and only hook object 
Add HookDll.lib to your project. 
Now, implement the code for displaying the message box. After resizing the application's main dialog (its default ID will be IDD_CONTEXTF1_DIALOG), add a push-button, to allow the user to pop-up a message box. Name this button "Msg Box," give it an ID: IDC_MSGBOX, then use ClassWizard to add a message handler to it. Let's name this CContextF1Dlg::OnMsgbox(). Below is a sample implementation for it: 

void CContextF1Dlg::OnMsgbox() 
{
  g_Hook.Hook();
  AfxMessageBox("Press F1 to get help on this MessageBox");
  g_Hook.UnHook();
}

 


Finally, use ClassWizard to add to the main dialog class a message handler for the WM_COPYDATA message: 

BOOL CContextF1Dlg::OnCopyData(CWnd* pWnd, 
             COPYDATASTRUCT* pCopyDataStruct) 
{
  HtmlHelp(NULL, "ContextF1.chm", HH_DISPLAY_TOPIC, 0);
  return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}

 


All that function does is call the HtmlHelp() function, or other custom help module. Of course, you can use the information from the COPYDATASTRUCT structure to determine in which window the F1 key was pressed. 

In order to use the HtmlHelp() support, you need to install the Microsoft HTML Help Workshop, which you can get for free fromhttp://www.microsoft.com/workshop/author/htmlhelp. As an alternative, if you don't have the HTML Help Workshop, you could open the chm file by calling the ShellExecute() function: 

ShellExecute(m_hWnd, NULL, "ContextF1.chm", NULL, 
             NULL, SW_SHOWNORMAL);

 


With this last approach you can't have complete control over the type, style, and position of the Help window, which is provided when using the HtmlHelp()API. 


Redirecting all keyboard and mouse events to a single window 

Sometimes it's desirable to redirect all the keyboard and mouse events to a one window (e.g., a dialog box). For example, the XWindows users may remember that every time you move or resize a window, a small label appears on the screen, displaying that window's coordinates. A function like SetCapture() works only for windows of the same process, but we need a small trick to capture events from all desktop windows. 

To do this you need to install Windows hooks that capture all keyboard and mouse messages at a system level. This will accomplish what you want but with some degradation to system performance. If performance isn't an issue, then this function works just fine. 

Creating the hook DLL for example 3. As in the first two examples, create the "HookDll" project, add to that project the thunk class CHKThunk and its derived class CHook. 

Implement for CHook class the constructor and the following methods: HKHookProc(), Hook(), UnHook(). Because we will derive from CHook two other classes (one for mouse, and one for keyboard hooks), ensure you declared the above member functions as virtual. 

Implement the UnHook() function in the same way as in the first example: 

BOOL CHook::UnHook() {
  BOOL fOK = TRUE;
  // Only uninstall the hook if it was successfully installed.
  if (m_hhook != NULL)
  {
    fOK = UnhookWindowsHookEx(m_hhook);
    m_hhook = NULL;
  }
  return(fOK);
}

 


You will override the HKHookProc() and Hook() functions in the derived classes, so that you can keep the implementation in this base class as simple as possible: 

BOOL CHook::Hook()
{
  return (BOOL)m_hhook;
}

LRESULT CHook::HKHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
  return CallNextHookEx(m_hhook, nCode, wParam, lParam);
}

 


Derive from CHook the specialized classes CKbHook and CMouseHook. Declare two global objects, one from each class, and use #pragma to share them: 

#pragma data_seg("Shared")
HOOKDLL_API CMouseHook  g_MouseHook = NULL;  // The Mouse hook object
HOOKDLL_API CKbHook     g_KbHook = NULL;     // The Keyboard hook object
#pragma data_seg()

 


Now, implement the Hook() member function for the two derived classes: 

BOOL CKbHook::Hook() 
{
  if (m_hhook == NULL)
    m_hhook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)GetThunk(),
             g_hInst, NULL);
  return (BOOL)m_hhook;
}

 


and 

BOOL CMouseHook::Hook()
{
  if (m_hhook == NULL)
    m_hhook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC)GetThunk(),
             g_hInst, NULL);
  return (BOOL)m_hhook;
}

 


respectively. 

Finally, let's implement the hook procedure HKHookProc() for the two derived classes. First, we'll do the hook procedure for the WH_MOUSE hook. To send to the main application all the information about the current mouse message, we'll use the following structure: 

typedef struct
{
  LONG    x;          //  x- coordinates of the cursor
  LONG    y;          //  y- coordinates of the cursor
  UINT    uMsg;       //  the identifier of the mouse message
  UINT    uExtraInfo; //  specifies the hit-test value
} MOUSEMSGDATA;

 


Then, we'll construct the COPYDATASTRUCT object as: 

COPYDATASTRUCT gcds = { 0, sizeof(MOUSEMSGDATA), &MsgData };

 


Before sending the WM_COPYDATA message to the main window of the client application, we have to fill in the structure members: 

  MOUSEHOOKSTRUCT*  lpStruct = (MOUSEHOOKSTRUCT*) lParam;
  HWND hWnd = lpStruct->hwnd; 

  MsgData.x = lpStruct->pt.x;
  MsgData.y = lpStruct->pt.y;
  MsgData.uMsg = wParam;
  MsgData.uExtraInfo = lpStruct->wHitTestCode;
  gcds.dwData = (DWORD)hWnd; 

 


The dwData member of gcds is the handle of the window that will receive the mouse message we just intercepted. 

Here is the code for the hook function: 

LRESULT CMouseHook::HKHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
  if (nCode < 0)
    return CallNextHookEx(m_hhook, nCode, wParam, lParam);

  MOUSEHOOKSTRUCT*  lpStruct = (MOUSEHOOKSTRUCT*) lParam;
  MOUSEMSGDATA MsgData;
  COPYDATASTRUCT gcds = { 0, sizeof(MOUSEMSGDATA), &MsgData };

  HWND hWnd = lpStruct->hwnd; 

  if ( nCode == HC_ACTION) 
  {
    HWND hwndClient = FindWindow(NULL, 
                "Redirecting the mouse and keyboard input");
    if(hwndClient == NULL)
      return CallNextHookEx(m_hhook, nCode, wParam, lParam);

    MsgData.x = lpStruct->pt.x;
    MsgData.y = lpStruct->pt.y;
    MsgData.uMsg = wParam;
    MsgData.uExtraInfo = lpStruct->wHitTestCode;
    gcds.dwData = (DWORD)hWnd; 

    SendMessage(hwndClient, WM_COPYDATA, (WPARAM)hWnd,
                (LPARAM)&gcds);
  }
  return CallNextHookEx(m_hhook, nCode, wParam, lParam);
}

 


Now, we'll implement the hook procedure for the WH_KEYBOARD hook. 

This time, we'll send to the main application only the virtual-key code of the key that generated the keystroke message, so we'll simply set to NULL the last member of the COPYDATASTRUCT structure: 

COPYDATASTRUCT gcds = { 0, 0, NULL};

 


Then, we'll initialize its dwData member with the virtual-key code: 

  UINT nKeyCode = wParam;
  gcds.dwData = (DWORD)nKeyCode; 

 


Finally, we notify the client application of the event: 

SendMessage(hwndClient, WM_COPYDATA, NULL, (LPARAM)&gcds);

 


Our DLL isn't associated with any window, so we can set wParam to NULL. 

Creating the client application for example 3. Let's create a simple application which will display the mouse and keyboard messages received from all the windows in the system. The application's main window may look like Figure 3. 


Figure 3.

As in the preceding example, use AppWizard to create a dialog-based MFC application named "HKRedirect." After resizing the main dialog, delete the "Cancel" button, and rename the "OK" button to "Close." Then, add another two buttons: "Hook" and "Unhook" and add message handlers for them. 

Make sure the dialog is always on top by inserting the following line in the CHKRedirectDlg:: OnInitDialog(), after calling the base class: 

SetWindowPos(&wndTopMost, 0,0,0,0, 
             SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW);

 

Now, put two static text controls into the dialog template, to display the messages from the mouse and from the keyboard, respectively. Then, use ClassWizard to add to the dialog class two CString data members corresponding to the static controls you just created. Name them m_csKeybMsg and m_csMouseMsg, respectively. 

As in the other two examples, prepare the application to set, unset and use the hook. 

Declare the two global hook objects (g_MouseHook and g_KbHook), which are also declared in the HookDll project as being shared: 

HOOKDLL_API CMouseHook g_MouseHook;  // The Mouse hook object
HOOKDLL_API CKbHook     g_KbHook;    // The Keyboard hook object

 

Add HookDll.lib to your project. Now, implement the message handlers OnHook() and OnUnhook() as follows: 

void CHKRedirectDlg::OnHook() 
{
  g_MouseHook.Hook();
  g_KbHook.Hook();	
}

void CHKRedirectDlg::OnUnhook() 
{
  g_MouseHook.UnHook();
  g_KbHook.UnHook();	
	
}

 

Finally, add to the main dialog class a handler for the WM_COPYDATA message: 

BOOL CHKRedirectDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) 
{
  if(pCopyDataStruct -> cbData == 0)
  {
    // Message comes from the keyboard hook
    m_csKeybMsg.Format(IDS_KEYB_MSG, pCopyDataStruct->dwData);
  }
  else
  {
    // Message comes from the mouse hook
    MOUSEMSGDATA* pMsgData = (MOUSEMSGDATA*)pCopyDataStruct->lpData;

    m_csMouseMsg.Format(IDS_MOUSE_MSG, pMsgData->uMsg, pMsgData->x, 
      pMsgData->y, pMsgData->uExtraInfo, pCopyDataStruct->dwData);
  }
  UpdateData(false);

  return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}

 

Remember that when we implemented the hook procedures for keyboard and mouse, we used the last two members of the COPYDATASTRUCT only for the CMouseHook:: HKHookProc() and we have set them to zero in the CKbHook::HKHookProc(). 

Thus, if the cbData member of that structure is nonzero, the WM_COPYDATA message we just received comes from the mouse hook procedure. Otherwise, it comes from the keyboard hook procedure. 

After building the m_csMouseMsg and m_csKeybMsg strings, we call the UpdateData (false) function to display the two strings in the corresponding static text controls. 

To make the messages more user-friendly, you can write two helper functions to translate the integer values of key codes, mouse messages and hit test codes into user-readable strings. Here is an example of translating the virtual-key codes into CStrings: 

CString GetKeyName(DWORD dwCode)
{
  CMap<DWORD, DWORD, CString*, CString*> keyMap;
  
  keyMap[VK_SPACE] = new CString("VK_SPACE");
  keyMap[VK_PRIOR] = new CString("VK_PRIOR");
  // ...
  keyMap[VK_END] = new CString("VK_END");
  keyMap[VK_HOME] = new CString("VK_HOME");

  CString * pcsValue;
  keyMap.Lookup(VK_SPACE, pcsValue);
  return * pcsValue;
}

 

Of course, you must modify the code in OnCopyData() accordingly: 

 m_csKeybMsg.Format(IDS_FRIEND_KEYB_MSG, 
                    GetKeyName(pCopyDataStruct->dwData));

 

The new string resource will be modified to use the string value, instead of the numeric one: 

IDS_FRIEND_KEYB_MSG "The  %s key was pressed."

 

This sample uses the hooks only to monitor the mouse and keyboard events, without modifying or discarding them. The keyboard hook can also "swallow" keystrokes by returning TRUE in the hook procedure. However, this will not work for system keyboard events such as CTRL+ALT+DEL, CTRL+ESC, and ALT+TAB. Disabling these key combinations is a bit tricky. 

For Windows NT version 5.0, you can install a low-level keyboard hook WH_KEYBOARD_LL that can detect these system keyboard events and "eat" all of them, except for CTRL+ALT+DEL. This exception is for security reasons. 

In Windows 95/98 you can make a call to SystemParametersInfo() to disable the system keyboard events, including CTRL+ALT+DEL. 

SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, lpvoid, 0)

 

Calling it again with the TRUE changed to FALSE will re-enable these key sequences. The technique involves tricking Windows 95 or Windows 98 into thinking that a screen saver is running. A side effect of this is that CTRL+ALT+DEL no longer has any effect. 

Conclusion 

Windows hooks offer programmers a way to process messages before they reach the target window procedure. Since MFC doesn't implement a CHook class, I've presented a way to write such a class, using a special technique called callback thunking. In addition, after providing coverage of the theory behind hooks, I developed three samples, which illustrate three ways to take advantage of using the Windows hooks.


c0Title: Visual Studio Editor Tips
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/1999/octmag99/tipa2.asp 
Tips and Tricks

By Glenn Carr

The Visual Studio editor is a powerful and flexible editor with a lot of hidden capabilities and features. Here are some helpful, but not so obvious, editor features that I use frequently now that I've discovered them. Most of these features are available from the menu structure, accelerator keys, or editor commands. Editor commands are shown in parentheses below where appropriate, and can be assigned to custom toolbar buttons, menus, or keystrokes by selecting Customize from the Tools menu.


To copy or cut a rectangular area in the editor, press the Alt key while selecting text with the mouse. Copy or cut the selection as usual. When you paste a rectangular selection, it will be pasted into the target document as a rectangular region. 
To display tab and space characters, select Advanced->View Whitespace from the Edit menu. To toggle it back off, just repeat the menu selection or use the accelerator key combination Ctrl-Shift-8 (ToggleViewWhitespace). 
Using the default editor emulation, incremental searches are available by selecting Advanced-> Incremental Search from the Edit menu, or by pressing Ctrl-I (SearchIncremental) or Ctrl-Shift-I (SearchIncrementalBack). If you are unfamiliar with incremental searches, they allow you to find text by entering the minimum number of characters necessary. As you type each character of the search string, your cursor becomes positioned on the first matched text and the matching text is selected. 


c0Title: Win32 API Handles
c1Code:
 http://www.devx.com/premier/mgznarch/vcdj/1999/octmag99/qa1.asp 
Short solutions
By Davide Marcato 
System Notes 
To replicate the steps described in this article, you will need: 
Visual C++ 5.0 or higher 
Windows NT 4.0 or higher 
 

What is a handle? Why do I have to call DuplicateHandle() if I want to pass a handle to a certain resource? Is it acceptable to simply copy it to the destination? 

The concept of a handle is important when dealing with the Win32 API, and handles are certainly one of the most frequent elements you will run across in your development efforts. But what, exactly, is a handle? 

Some background on Win32 will help put handles in context. Win32 is the abstract specification of a very extensive family of APIs. Different operating system implementers can decide to adhere to the Win32 specification and implement the numerous functions as outlined by the documentation. The main supplier of such implementations is, unsurprisingly, Microsoft itself, through its three subplatforms-Windows 95/98, Windows NT/2000 (which works on diverse CPU architectures), and the recently arrived Windows CE. So, the Win32 API is a hardware-independent specification, which means that, because system-level code may vary depending on the environment, it must abstract the logical operations carried out by the programmer from the actual low-level operations executed by the system-level code on the hardware devices. 

Through the very useful mechanism of dynamic linking of compiled modules (DLLs) and the well-defined standard for exporting and publishing C-style routines from dynamic modules, the decoupling between application logic and operating system plumbing is effectively separated at the functional level. 

However, Win32 is technically a procedural API in the sense that it is composed of global functions (although logically grouped into nearly independent families, the division is conceptual), but it works in an object-oriented fashion. However, the abstraction at the functional level isn't sufficient: system objects (the actual data or the objects' state if you're familiar with OOP terminology) must also be abstracted in some standard, generic, platform-independent way. 

Win32 answers this problem with handles. In addition to dictating the functions a compliant platform must expose, Win32 also defines a long set of system objects those functions act on, and which can be considered logical system resources. A Win32 handle is essentially a high-level reference that uniquely identifies each object, so the application developer doesn't have to tamper with the internal structure of the objects. A handle is an opaque pointer you can treat as a variable, pass as an argument to API calls, and take back as a return value, without any further direct access. Nearly every resource in Windows is accessed through handles: windows (HWND), files (HANDLE), GDI objects (HDC, HFONT, HBITMAP), menus (HMENU), and mutexes (HANDLE). Some resources correspond to a recognizable system-specific entity (such as files), while others play at a higher level of abstraction (like GDI objects). Some store the offsets in a table maintained by the operating system, while others work like real pointers and store a valid memory address. Handles are also used as a means to implement reference-counting mechanisms on the system object, while other objects support only one handle at a time. 

Under Windows NT the layer of abstraction represented by handles has another important advantage: the objects they refer to can be secured via the standard NT security model, based on access tokens and access control lists. This means that not every security principal can do everything on all objects. Obviously, if you can simply access the resources through a raw pointer, any security check is easily circumventable. 

Saying that a handle is a reference to a system object doesn't give the complete picture. A more precise definition would be that handles are process-specific references to system objects. If you pass a handle around within the bounds of the same process, everything will work fine. The only thing that could impede access to the underlying resource would be a security-related issue, i.e., a thread impersonating a user without the right to perform the requested operations on the object. 

However, when you cross the boundaries of the process, the opaque pointer doesn't refer to anything valid in the new context, even if the resource is system-wide and technically accessible from the second process. 

Therefore, to pass a handle to another process, you need to create a copy of it for the off-process context. You can do this through inheritance or duplication. 

Inheritance means that whenever a process (the parent process) spawns another process (the child process), all or some of the handles opened by the parent at that moment can be automatically opened by the child as well. Handle inheritance doesn't occur transparently. To make a handle inheritable, the code that creates it must specify this characteristic up front, typically by setting a flag in the parameters of the API. For example, the CreateFile() API has the following signature: 

HANDLE CreateFile(LPCTSTR lpFileName,
	DWORD dwDesiredAccess,
	DWORD dwShareMode,	
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile);

 


The fourth parameter is a pointer to a SECURITY_ATTRIBUTES structure, defined as: 

typedef struct _SECURITY_ATTRIBUTES
{
	DWORD  nLength; 
	LPVOID lpSecurityDescriptor;
	BOOL   bInheritHandle; 
} SECURITY_ATTRIBUTES;

 


For our purposes, the relevant field is bInheritHandle. To make the handle to a newly created file inheritable by child processes, you must explicitly provide security information and set the Boolean bInheritHandle to TRUE. If you simply pass NULL as the security-aware parameter to the API, you not only get the default security properties, you also prevent the handle from being inherited! 

This is not enough, however. When you create the second process, you must tell the operating system that you want all the open and inheritable handles to flow transparently to the first process. You do so by setting the bInheritHandles flag to TRUE in CreateProcess(): 

BOOL CreateProcess(LPCTSTR lpApplicationName,
	LPTSTR lpCommandLine,
	LPSECURITY_ATTRIBUTES lpProcessAttributes, 
	LPSECURITY_ATTRIBUTES lpThreadAttributes, 
	BOOL bInheritHandles,
	DWORD dwCreationFlags,
	LPVOID lpEnvironment,
	LPCTSTR lpCurrentDirectory,
	LPSTARTUPINFO lpStartupInfo,
	LPPROCESS_INFORMATION lpProcessInformation);

 


The inherited handles are equivalent to their ancestors: They have the same numeric value and share the same access privileges. 

What happens if you want to inherit a handle originally created as non-inheritable? And what about passing parameters among processes not linked by a parent-child relationship? The answer to both questions is duplication. The handles that can be inherited can also be duplicated by means of the DuplicateHandle() API, declared as follows: 

BOOL DuplicateHandle(
	HANDLE hSourceProcessHandle,
	HANDLE hSourceHandle,
	HANDLE hTargetProcessHandle,
	LPHANDLE lpTargetHandle,
	DWORD dwDesiredAccess,
	BOOL bInheritHandle,
	DWORD dwOptions);

 


The first and second parameters represent the process by which the handle has to be duplicated and the original handle itself. The third and fourth parameters represent the process by which the new handle is to be tailored and the address where the new handle will be put after the return of the function call. The dwDesiredAccess parameter specifies the access properties of the new handle (which may be different from the original); bInheritHandle dictates whether the duplicated handle will be inheritable or not, and the last parameters deal with less important options. 

See Table 1 for a complete list of the inheritable handles and the APIs that generate them. 

TABLE 1 List of the inheritable handles 
OBJECT NAME RETURNED BY... 
Access token CreateRestrictedToken(), DuplicateToken(), DuplicateTokenEx(), OpenProcessToken(), OpenThreadToken() 
Communications device CreateFile() 
Console input CreateFile(), GetStdHandle() 
Console screen buffer CreateFile(), GetStdHandle() 
Desktop GetThreadDesktop() 
Directory CreateDirectory() 
Event CreateEvent(), OpenEvent() 
File CreateFile() 
File Mapping CreateFileMapping() 
Job CreateJobObject() 
Mailslot CreateMailslot() 
Mutex CreateMutex(), OpenMutex() 
Pipe CreateNamedPipe(), CreateFile(), CreatePipe() 
Process CreateProcess, GetCurrentProcess, OpenProcess() 
Registry key RegCreateKey, RegCreateKeyEx, RegOpenKey, RegOpenKeyEx (Windows NT/2000 only) 
Semaphore CreateSemaphore(), OpenSemaphore() 
Socket socket(), accept() 
Thread CreateProcess(), CreateThread(), CreateRemoteThread(), GetCurrentThread() 
Timer CreateWaitableTimer(), OpenWaitableTimer() 
Window station GetProcessWindowStation() 


To convert a non-inheritable handle into an inheritable one (or vice versa), the programmer just duplicates the handle, remembering to set the bInheritHandle parameter to TRUE and to close the original handle by means of the CloseHandle() API: 

BOOL CloseHandle(HANDLE hObject);

 


Closing the handle is crucial to avoid resource leaks and to allow proper memory clean up, because, as stated earlier, some objects rely on the number of outstanding handles to implement reference-counting. If even one of the handles isn't closed after use, the resources of the system object will never be freed. 

 

The following sample program shows how the inheritable attribute can be infused into a file handle: 

#define WIN32_LEAN_AND_MEAN
#include 
#include 
#include 

BOOL MakeHandleInheritable(HANDLE origHandle, 
					LPHANDLE pNewHandle);

int main()
{
	HANDLE hFile, hNewFile;
	hFile = CreateFile(_T("c:\\HandleTest.vcdj"), 
						GENERIC_READ,
		FILE_SHARE_READ, NULL, CREATE_ALWAYS, 
				FILE_ATTRIBUTE_NORMAL, NULL);
	
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("Error opening the file\n");
	}
	else
	{
		if (!MakeHandleInheritable(hFile, 	
					&hNewFile))
		{
			printf("Operation failed\n");
		}
		else
		{
			printf("Operation succeeded\n");
			// Close the newly generated 
			// inheritable handle before exit
			CloseHandle(hNewFile);
		}
	}

	getchar();
	return 0;
}

BOOL MakeHandleInheritable(HANDLE origHandle, 
				LPHANDLE pNewHandle)
{
	// Input parameters check...
	if (!origHandle || !pNewHandle)
		return FALSE;

	HANDLE hThisProc = GetCurrentProcess();
	if (!DuplicateHandle(hThisProc, origHandle, 
				hThisProc, pNewHandle, 0,
		TRUE, DUPLICATE_SAME_ACCESS))
		return FALSE;

	// We want to end up with one handle only, 
	// so we close the original
	if (!CloseHandle(origHandle))
		return FALSE;
	
	return TRUE;
}

 


This sample code segment is also available at www.vcdj.com/magazine. 

The heart of this sample program is the MakeHandleInheritable() function. This routine duplicates the handle received as a parameter using the handle to the current process (a pseudo-handle retrievable through GetCurrentProcess()) to fill both the source process and the target process arguments in the invocation to the DuplicateHandle() API. Before returning to the caller, MakeInheritableHandle() frees the original input handle. The duplicated handle can thereafter be employed exactly as the former would be, because although their numeric values differ (if you remember, the value was the same when inheritance was involved), they refer to the same system object. The main procedure creates a file and retrieves its handle for testing purposes and prints a string on the console to inform the user of the outcome of the operation. 

The same principles can be applied to cross-process handle passing. However, you might need to employ some form of inter-process communication (IPC) to pass the handle of one process to the other. In addition, because the original handles are meaningful only within the source process, the duplicated handles are valid only within the destination process and cannot be used by the original (even though this process was probably the one in charge of performing the duplication). 

 
Davide Marcato is a freelance international consultant, writer and speaker specializing in Windows, Java and COM/MTS/COM+ development and system design. He is a member of the instructional staff at DevelopMentor and an independent consultant managing projects of all sizes. A Windows DNA expert and a Microsoft certified developer, Davide is also a prolific technical writer and conference speaker worldwide, regularly contributing to several magazines such as Visual C++ Developers Journal, Dr. Dobb's Journal, MIND and COM Developer. For VCDJ he serves as a technical editor and Q&A columnist, and sits in the editorial advisory board of both MSDN Journal and VCDJ. Contact him through his Web site at http://www.DavideMarcato.com or by email at marcato@programmers.net. 



c0Title: Working With the STL
c1Code:
June 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/06jun00/bw0600/bw0600.asp
Working With the STL 
STL programming is powerful, but it can take some time to learn. 

by Bill Wagner 


   In my last STL article, I described the design strategies behind the C++ Standard Template Library (STL). When you program with STL, you'll spend your time choosing the right container, working with iterators, and using, writing, and adapting algorithms. In this article, I'll describe when to use which kind of container, and how and when to use iterators and algorithms. 
The different STL containers all store a group of like objects. The main distinction between the containers is the performance of different operations based on how they store elements. STL containers come in two types: sequence containers and associative containers. 

Associative containers store keys always sorted in one particular order. You use these keys to retrieve the collection's elements. Associative containers include the set<> and map<> classes. A set<> is a collection of items you use to group like items, such as a set of valid item identifiers for a particular application. The set stores values of objects, and the value is the key on which the collection is sorted. A map<> is an ordered grouping of pairs of values, consisting of a key and the associated value. Maps are useful for implementing dictionary lookup types of collections. 

Sequence containers store a sequence of like elements. The STL containers include vector<> (arrays), deque<> (double-ended queues), and list<> (doubly linked lists). You can use these data structures in a many ways to handle and store data in your applications. Sequence containers are easier to understand and have more widespread application, so I'll explain them first and then get into the associative containers. 

Choosing a Sequence Container
The main difference between the sequence containers is how they perform in particular applications (see the sidebar, "STL Performance Specifications"). In fact, all the STL sequence containers use similar interfaces. This was by design. You should be able to replace the container in most instances with minimal effect on other code. In fact, if you use a typedef for all STL sequence container definitions in your code, you can experiment with different containers with minimal changes to your source code. Here's an example: 



// Use this:
typedef vector < Things > 
   ThingsContainer;
// ...
//
ThingsContainer   _LotsOfThings;

// Bad interface design, but you can 
// see the point:
ThingsContainer& getThings () 
{ 
   return _LotsOfThings; 
};

// Rather than this:
vector < things > _LotsOfThings;

// Bad interface design, but you can 
// see the point:
vector < things >& getThings () 
{ 
   return _LotsOfThings; 
};

Suppose you later decided to change from the vector to a deque. The first approach, using the typedef, requires only one code change. The second approach, declaring the template specification throughout the code, requires two changes in the preceding code snippet. As the code base increases, the number of changes increase greatly. 
Your first choice for a sequence container should be the vector<>, the fastest and most efficient STL container. Unless your needs meet one of the special cases discussed later, use vector<>. Internally, the structure of the STL vector<> matches a C array's semantics. However, the interface for the STL vector<> is more robust than the C array. You can write more compact and portable code by using the STL vector<> class instead of a C array. However, the internal performance should match that of the C array. 

The vector<> class has several advantages over the other containers. First, it accesses individual elements faster than other containers. In fact, the vector<> class includes operator[]() to retrieve any element by an integer index, just like a C array. The vector<> has the fastest traversal of any STL collection. The vector moves forward and backward in a collection using pointer arithmetic, rather than the more computationally expensive pointer manipulation. Vectors support random access, meaning that the expression (&Things [5] - &Things[2] == 3) is true for a vector<>. 

In other words, without worrying about the underlying storage scheme, you can treat the elements of a vector<> as if they were stored sequentially in memory. You can also move through a vector<> using nonsequential arithmetic expressions. Access to any element in a vector<> is a constant time 
operation�O(1) in Big O notation (see the sidebar, "STL Performance Specifications"). But, if vector<> has the best performance in these cases, why use anything else? Well, sometimes vector<> isn't the fastest. Adding elements to a vector<> at locations other than the back end can slow things down, because inserting elements in the middle of a vector<> means moving the elements that follow the inserted element to a new location. 

Next, I'll discuss the disadvantages of the vector<> topology. These disadvantages always revolve around inserting elements into a container at some location other than the end of the container. 

Reasons for Using a deque<> or list<>
The deque<>, or double-ended queue, improves the vector's performance with respect to insertions at the beginning and end of the container. Deques support both traditional data structure stacks or queues, although STL provides adapter templates to implement these data structures from any collection. I'll discuss these structures later. If your needs include inserting or deleting new elements at the beginning or end of a collection, consider using the deque<> instead of the vector<>. You implement the deque<> container as a circular array, which means that adding elements to either end of a deque<> takes constant time, or O(1). 

However, the deque<> slows things down. You implement the deque<> internally as a C array with additional space allocated at the beginning to support insertions. This introduces extra housekeeping and decreased performance. While both deque<> and vector<> provide constant time access to all elements, the vector<> is usually a bit faster, depending on the application and the frequency of insertion operations at the front of the collection. 

The access performance of deque<> is similar to vector<> and includes operator[]() support for indexed access to collection elements. The distance between elements is still a known arithmetic quantity. The deque<> is the right choice for containers needing to support insertion and deletion at the front and end of the container, and it supports these operations without slowing down other operations. 

The list<> container addresses the problem of insertions and deletions into a container at any location. However, this increased insertion-and-deletion capability slows down other operations. The STL list<> collection is stored internally as a doubly linked list. The elements aren't stored sequentially in memory because accessing list<> elements slows down the operation. Instead of pointer arithmetic, you use pointer dereferencing to get to the next element. Furthermore, you can directly access elements only at the beginning and end of the list. To access any other elements, you must start at one end and follow the list<> pointer elements to the list<> element being sought. You can't use arithmetic operations to compare the distance between two elements of the list<>. 

Use the list<> when you must frequently insert and delete elements at any location in the list<> container. The list<> is the right choice only when the insertion and deletion performance overrides access performance. Also, only use a list<> when access is mostly sequential. Finding elements in the middle of a list<> isn't a high-performance operation. 

Adapters
The STL supports two adapter templates that use other containers to provide specific limited operations on containers. Choose the adapters when you need a limited interface to a particular container. 

The stack<> template adapter takes some other container and presents a limited interface to model a stack's Last In, First Out (LIFO) behavior. You should almost always implement the stack<> using the vector<> template: 



typedef stack < vector < Thing > > 
   ThingStack;

The adapter exists to diminish the need for extra code. Using an adapter leverages other code already in the STL and reduces your application's code base. The similar queue<> template takes a container and limits the interface to a First In, First Out (FIFO) queue. You should almost always implement the queue<> template using a deque<> class: 



typedef queue < deque < Thing > > 
   ThingQueue;

The priority_queue<> adapter stores elements in a queue, where items in the queue are ordered based on an less() algorithm that can't be overridden. I'll cover algorithms later in the article. The first element out of the priority queue is the first element in of the highest priority. 

Sorted Associative Containers
Sorted associative containers are special-purpose containers for set-based actions. You'll use one of the sorted associative containers when all of these conditions are true: The collection must always be sorted, additions to the collection are rare, and access to collection elements is to search for a specific element, rather than to traverse the entire collection. 

For example, if you're implementing an English dictionary, the map < string, string > would be the right choice. All access to nodes is by searching, not traversing. Everyone looks up individual words in the dictionary, but no one reads the whole dictionary. Once the map data structure is created, insertions and deletions are rare. This means the cost of initially creating the map data structure isn't significant when compared to the amount of time spent searching the dictionary. All access is sorted, with only one meaningful sorted order. 

You'll find four different sorted associative containers. The set<> class is a mathematical set. One copy of each key value is present. Use it only when you need to test for the presence or absence of a single key. The multiset<> class differs from set<> in that it allows multiple copies of the same key. The map<> class stores key, value pairs. It only allows one copy of each key. Although you can use map<> as a sparse array, this isn't wise. Maps perform differently than vectors. Each access of a map<> element requires a tree traversal from the root node to the particular element sought. The access time for map<> elements is logarithmic, or O(ln n). Remember that vector has constant time access for elements. 

The multimap<> class differs from the map<> container in that it can store multiple copies of the same key. These multiple copies of the same key need not have the same value. 

Working With Iterators
The iterator pattern is described in the book Design Patterns (see Resources). Iterator is a big word for the simple concept of allowing access to the items in a collection. Iterartors access all the elements in a collection in a prescribed manner. Iterators act like pointers. In fact, they provide overloaded operators so you use them syntactically just like pointers: 



// defined elsewhere:
extern vector < Thing > v;
// initialized elsewhere ...
vector < Thing >::iterator iter = 
   v.begin();

// Just like a pointer...
Thing& s = *iter; 

// Use your imagination...
iter->ThingFunc (); 

From this brief example, you can see that accessing elements in a collection by an iterator uses the same semantics and the same syntax as a pointer. An iterator contains overloaded operator ++() and operator () functions, so you can access the next and previous elements: 



// defined elsewhere:
extern vector < Thing > v;
// initialized elsewhere ...

vector < Thing >::iterator iter = 
   v.begin();

while (iter != v.end ())
{
   // Just like a pointer...
   Thing& s = *iter; 
   // Use your imagination...
   iter->ThingFunc (); 
   // Get the next one:
   ++iter;
}

vector < Thing >::iterator iter2 = 
   v.end();

while (iter != v.begin ())
{
   // Get the previous one:
   // Do this first.  
   // end () points past the end.
   --iter;
   // Just like a pointer...
   Thing& s = *iter; 
   // Use your imagination...
   iter->ThingFunc (); 
}

From the preceding example, you can see that an iterator contains the current position in a collection. You can compare an iterator to a collection's beginning and end. As I stated earlier, using the iterator is similar to using a pointer, except that iterators are more powerful than pointers. The iterator template allows you to redefine the logical operations for traversing a collection. 

For example, consider the increment and decrement operators. As expected, these operators will increment and decrement the internal pointer in a vector<>. However, the list<> iterator implements these operations differently: 



// psuedocode for list.  
// The actual implementation 
// looks a bit different.
list::iterator& 
   list::iterator::operator++ ()
{
   ptr = ptr->next;
   return *this;
}

The internal implementation is different, but iterator::operator++() will always move the iterator forward one position in the collection. In general, an iterator provides a standard way to traverse a collection, so you can use the collection in many different ways, without writing specific code that depends on the collection topology. 

Iterators decouple a container's algorithms from the container's organization. Whether you use the STL generic algorithms or have your own application-specific algorithms, writing them to use iterators makes your algorithms more reusable. You can use the algorithm with any of the container types I've discussed. By using a typedef, you can easily change your collection types. However, if any of the algorithms that work with the collection use raw pointers, you'll need to rewrite those algorithms for the new collection style. If you're using iterators, the iterator template implements the abstraction of iterating over the collection. You can reuse those algorithms on different collection types and on partial ranges of a collection. For instance, this function is tied to the vector implementation: 



void vectFunc (vector < Things >& v)
{
   for (int i = 0; i<v.size (); i++)
      v[I].Func ();
}

However, if you rewrite the same function to take iterators, you can reuse it in many more places: 



template < class Iter > 
void callFunc (Iter start, Iter end)
{
   while (start != end)
   {
      start->Func ();
      ++start;
   }
}
// calling it:
callFunc (vect.start (), 
   vect.end ());

You can use the second example with a vector<>, a deque<>, a list<>, or any subrange of any of those containers. This simple example illustrates several important concepts. Notice that the STL version is a function template, not a regular function. Iterators aren't real classes�they're more accurately expressed as any object satisfying a set of functions. Although list<> iterators, vector<> iterators, deque<> iterators, or any other iterator have no inheritance relationship, they all share a common interface. The compiler creates a different template instantiation for any different version of the template function that you call. For example, you instantiate two different versions of the template function with a vector<> and a list<>. 

Using and Finding Algorithms
Using iterators, the STL decouples the containers from the generic algorithms. All the STL algorithms use iterators, rather than the container. As the preceding example shows, this means you can use the algorithms with more than one container. 

I'm often asked how to find algorithms in the STL. With so many, it's a daunting task to find what you need. The only answer: Become more familiar with the algorithms available. Two different header files, <algorithm> and <numeric>, contain the definitions of all the STL algorithms. The general-purpose algorithms are in <algorithm>, while <numeric> contains the numeric-processing functions. 

All the algorithms have a common style. The STL algorithm traverses, searches, or manipulates the collection. You'll write a special kind of class, called a function object, to manipulate or compare one particular object. As an example, look at the accumulate() algorithm. Suppose you wanted to add the numbers in an array of integers. You could use this code: 



extern vector < int > vars;
int sum = 0;
for (int I = 0; I < 20; I++)
{
   sum += vars[I];
};

This instance works fine, but it's limited. The STL version of the code looks like this: 



extern vector < int > vars;
int sum = accumulate (vars.begin (), 
   vars.end (), 0);

The accumulate() function follows a common signature for STL generic algorithms. The first two parameters define the function's range. Like all ranges in STL, the begin() parameter is in the range, the end() parameter is one past the end of the range, equivalent to a null character at the end of a string. The last parameter is the initial value for the accumulation. Examining the STL code shows you've cut the lines of code in half. In addition, you can use the same construct with another style of collection: 



// Sum another collection:
extern list < int > vars2;
sum = accumulate (vars2.begin (), 
   vars2.end(), sum);

The STL makes the code more robust to many different kinds of changes. The accumulate() function returns the "total" of all the values in the collection and lets you define exactly what that means for your type. 

I've written some tools to help artists create animations for games. Most of the time, several small animations play at once in different parts of the window. In most cases, I'm trying to limit the area that needs to be updated in each frame. To make these calculations, I put all the animation rectangles in a vector and use the STL algorithms to get the totals. The preceding example shows that the accumulate() algorithm is close to what I need. However, the accumulate() algorithm assumes that operator +() is defined for the type of elements in the collection. In this case, I'm not adding rectangles, but I do want to add up the area of all the rectangles. 

The second version of the accumulate function takes a function object that adds the values you want. The function object is a class that provides a way to tailor the algorithm's behavior to your needs. To perform the summation I want, I wrote a function object that adds the area of the rectangle to the existing sum. The accumulate function now adds the values returned by Rect_Area::operator () for each value in the vector: 



class Rect_Area 
{
public:
   int operator () (int sum, const CRect& r)
   {
      return sum + (r.bottom-r.top) *
         (r.right - r.left);
   }
};

extern vector < CRect > the_Rects;
int area = accumulate 
   (the_ Rects.begin (), 
   the_ Rects.end (), 0,
   Rect_Area ());

You'll use function objects throughout the STL to tailor the behavior of generic algorithms. In this case, the function object defines how to add the values from each of the objects in the collection. 

These two examples show the framework the STL algorithms use. The STL algorithm provides a common implementation that works on built-in types, as in my example with the vector of integers. The STL also provides a framework that lets you write specific function objects to adapt that behavior for your specific datatypes, as in my second example. In both cases, the STL provides the framework, so you write less code. You write the specific functions that work with your datatype. 

Summing Up
STL-style programming is different from programming with traditional data structures and algorithms. Where traditional programming idioms force you to write collection-traversal code for each possible operation you might perform on a collection or elements in a collection, the STL uses a different programming style. If you use STL algorithms and adapters, operations on a collection's element are divorced from the collection traversal, so you write less significantly less code. 

To pick which collection type to use, first consider the applicability of the STL sequential collections in this order: vector<>, deque<>, then list<>, based on your application. You should use the sorted associative containers only when the application matches their intended purpose. Keep in mind that each container has its own header file by the name of the collection, so you need to include only those collection types you intend to use. Use iterators whenever possible, rather than accessing the collection directly, so you can reuse your algorithms with any collection type. 

Algorithms provide standardized operations on collections, or elements in a collection. Algorithms use iterators to decouple the collection topology from the access methods for a collection. STL uses function objects to decouple a collection traversal from operations on elements carried out during that traversal. The algorithms all use iterators as parameters, rather than collections, so they work with all collection types. The algorithms provide function object parameters to allow you to customize how the algorithms behave. 


Bill Wagner, president and software architect for Midwest Seas Software Development Inc., has several years' experience in Windows and C++ programming. He specializes in C++, Java, and COM-based enterprise-programming solutions. Reach him at wwagner@midwestseas.com
 


c0Title: Write Thread-Safe Code With ATL
c1Code:
March 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/03mar00/at0300/at0300.asp

Master ATL wizards to get the most from COM. 

by Richard Grimes 


     The Component Object Model (COM) architecture first appeared on Windows 3.1, a 16-bit, single-threaded, cooperative multitasking operating system. No two clients could access a COM component concurrently; therefore, developers didn't need to synchronize access, and could write components without this capability. With 32-bit COM, Microsoft created apartments to group together components with similar concurrency requirements, ensuring you could execute code in a thread-safe way. The Active Template Library (ATL) wizards help you write components for all the COM apartment types�for components housed in both EXEs and in DLLs. This is a major step forward in creating safe code. 
What you need:
Visual C++ 6.0
Windows NT4, 95, 98, or 2000  
 
In this article, I'll explain how to get the most from the wizards, and I'll show you how to protect your code from multithreaded access. (See Resources for more information on COM apartments.) 

I'll begin with the ATL Object Wizard. Depending on the type of component you want to create, you might or might not see an Attributes page. If you do, you can choose the Single, Apartment, Both, or Free threading model. With some component types, certain threading models are disabled because they're irrelevant; and with other component types, you're unable to choose a threading model altogether. In the latter case, ATL chooses a threading model for you (see Table 1). The first five component types in Table 1 provide the Attributes page, but the last three don't, so I listed the threading model that ATL chooses for you. 

The Object Wizard will do one of two things, using the options you select. First, if the component is based in a DLL, the Wizard adds an appropriate ThreadingModel entry to the RGS registration file. Second, the Wizard adds synchronization code to the component that's appropriate to the apartment where the component is designed to run. 

Regarding the first point, it's important to remember that DLL servers don't call CoInitializeEx()�so they don't initialize apartments. In general, DLL servers shouldn't even create threads. You should register the component with the apartment type it prefers to run in. This way COM can ensure that if the calling code isn't running in an appropriate apartment, one will be created. However, it's only true for DLL-based components, because EXE servers do initialize apartments for the components to run. 

Therefore, if you want to create an EXE-based component, you have only two choices. You can either make the component single-threaded (in this case you can use either Single or Apartment) or you can make it free-threaded (in this case you can use either Both or Free). These options are available because EXE-based components don't have a ThreadingModel registry entry; synchronization is the only other applicable threading aspect of the Object Wizard. 

The Wizard-generated code applies the option you choose either by adding CComSingleThreadModel (Single and Apartment) or CComMultiThreadModel (Both and Free) as the template class parameter to CComObjectRootEx<>, the base class of every ATL COM class. This base class has these pertinent members: 



template 
class CComObjectRootEx : 
	public CComObjectRootBase
{
public:
 typedef ThreadModel _ThreadModel;
 typedef  
  _ThreadModel::AutoCriticalSection 
  _CritSec; 
 typedef 
  CComObjectLockT<_ThreadModel>    
  ObjectLock; 
 ULONG InternalAddRef();
 ULONG InternalRelease();
 void Lock()
 {m_critsec.Lock();}
 void Unlock()
 {m_critsec.Unlock();}
private:
 _CritSec m_critsec;
};

This code has several interesting aspects. First, notice that there is a data member called _CritSec of the type _ThreadModel::AutoCriticalSection, and this data member acts as a "lock." The two methods on it, Lock() and Unlock(), guard a section of code to ensure that only one thread runs the guarded code at a time. If the component is single-threaded, then the implementation of _CritSec will have empty methods, and if the component is multithreaded, a critical section is used. InternalAddRef() and InternalRelease() increment and decrement the component's reference count appropriate to the component's threading model. For a single-threaded component, this means using the C++ increment and decrement operators. 

The base class has a type called ObjectLock, based on CComObjectLockT<>. This class takes a pointer to an ATL class as a constructor parameter and calls Lock() on that pointer in its constructor and Unlock() in its destructor. When you create an instance of this class, it locks the object passed to the constructor to access a single thread. 

Default Threading Model
If you look into stdafx.h for a project, you'll see one of three symbols (see Table 2). Note that these symbols don't describe the threading model of the components in a DLL server. They define a default for the entire server used for accessing global data, and for components where you don't explicitly specify a threading model, such as enumerator objects based on CComEnum<>. 

In addition, if you have an EXE server, the symbol determines the apartment membership of the first thread in the server and the apartment where the class factories are created. This means if you have an EXE server and you define _ATL_APARTMENT_THREADED, the server will have one STA thread where all class factories are registered. Even if you created your ATL classes with the Object Wizard to have the free-threading model, those components will always be created in the single STA because their class factories live there. COM creates the DLL server class factories in the apartment the threading model specifies, so DLL servers aren't affected in this way. If you want to have a mixture of apartment and free-threaded components in an EXE, then define _ATL_FREE_THREADED and use an STA thread pool for the Apartment-threaded components. For an explanation of how to do this, refer to the ATL Advantage column in the January/February 2000 issue of VCDJ (see Resources). 

Thread-Sensitive Code
Some code should be accessed by one thread at a time. Consider this innocent line: 



m_ulData++;

Here, m_ulData is a data member of your class. If two threads can run this code at the same time, this data might be corrupted, because the ++ operator isn't atomic. Imagine that one thread runs this code, but it's suspended before completing the action, and the intermediate value is saved in some temporary storage. The second thread then runs and performs the entire action of incrementing the original value and saving it to the m_ulData variable. This means that when the first thread finally completes its work, it overwrites the previous value saved by the second thread, so m_ulData is increased by one, not by two. The solution is to make the action atomic. 

You can make the action atomic in two ways. For simple, un-signed 32-bit increment or decrement, use the Increment() and Decrement() methods of the _ThreadModel type of your class's CComObject-RootEx<> base class. This will be the CComSingleThreadModel or CComMultiThreadModel class, depending on the component's threading model. CComSingleThreadModel uses the C++ prefix increment and decrement operators (++ and --) for these methods, because they will only be called by a single thread. However, because methods in a multithreaded component can be accessed by several threads, CComMultiThreadModel implements Increment() and Decrement() using the Win32 API InterlockedIncrement() and InterlockedDecrement(): 



class CComMultiThreadModel
{
public:
 static ULONG WINAPI 
 Increment(LPLONG p) 
 {return InterlockedIncrement(p);}
 static ULONG WINAPI 
 Decrement(LPLONG p) 
 {return InterlockedDecrement(p);}
 typedef CComAutoCriticalSection 
		AutoCriticalSection;
 typedef CComCriticalSection 
		CriticalSection;
 typedef CComMultiThreadModelNoCS 
		ThreadModelNoCS;
 };

The Platform SDK says that under Windows 95, the return value of these functions doesn't necessarily result from the increment or decrement. So if you're targeting Windows 95, make sure you don't use the return value. Instead, access the variable directly: 



_ThreadModel::Increment(&m_ulData);
ulTwiceData = m_ulData * 2;

You only need to protect class members or global variables. If it's a nonstatic stack variable, you won't have a problem because each thread will have its own stack. Another way to protect thread-sensitive code is to use a critical section. 

Critical Sections
Most data you change won't be ULONGs, so you won't be able to use Increment() or Decrement(). You can also access functions in a library that isn't thread-safe, so you'll need some other mechanism to protect against multithreaded access. ATL provides code to do this based on a Win32 critical-section object to mark a section of code that should performed atomically. In other words, once a thread enters the guarded code, no other thread can run that code until the first thread has completed the guarded code. 

There are three ways you can use critical sections in ATL. The first way is to use the ObjectLock type mentioned earlier: 



HRESULT CMyObject::Method()
{
   // Lock() is called on
   // the next line
   ObjectLock obj(this);
   bool b = ThreadSensitiveCode();
   if (b)
   { 
		return S_OK;	
   } // Unlock() called
   OtherThreadSensitiveCode();
   return S_OK; // Unlock() called
}

This technique locks all code in the scope of the obj variable to a single thread, which is useful if an entire method is thread-sensitive. However, the technique does have a downside. The lock also prevents all other threads from executing any code protected by the class critical section, m_critsec. When you lock out other threads, you create a bottleneck that affects your component's performance. The second way to use critical sections is to use the Lock() and Unlock() methods inherited from CComObjectRootEx<>: 



HRESULT CMyObject::IncrementWeight()
{
   Lock();
   m_fWeight += 10.0;
   ProcessWeight(m_fWeight);
   Unlock();
   return S_OK;
}

This code ensures that when Lock() is called, no other thread can access any other code in the component guarded by Lock()/Unlock() because the critical-section object is a member of the class. This method applies the lock to a smaller amount of code than when you use ObjectLock. It's useful if you have another method that depends on m_fWeight. 

And the third way to use critical sections�if you'd prefer to lock just one section of code in a single method�is to use one of the typedef'd critical-section classes in your component's _ThreadModel. 

The CriticalSection class requires its Init() method to be called to initialize the Win32 critical section before Lock() can be called. Similarly, when you've finished with the critical-section object, call the Term() method to clear up the critical-section resources. The AutoCriticalSection class makes these calls in the object's constructor and destructor. Here's one way to use this class: 



HRESULT CMyObject::IncrementHeight()
{
   AutoCriticalSection cs;
   cs.Lock();
   m_fHeiht += 10.0;
   ProcessHeight(m_fHeight);
   cs.Unlock();
   return S_OK;
}

Because cs is local to IncrementHeight(), it ensures that other threads can access other methods on the component. If you have other code that uses m_fHeight, it's better to add an AutoCriticalSection object as a class data member so the other code can use it as a guard. You should use the AutoCriticalSection type, rather than CComAutoCriticalSection, because if the component is single-threaded, Lock() and Unlock() will be implemented as empty methods. In this case, locking isn't necessary. However, using AutoCriticalSection improves the resource usage and component performance, and if the component has a user interface, AutoCriticalSection also prevents the UI from "locking." 

Mastering the ATL wizards enables you to quickly take advantage of the benefits of COM and helps you protect your code from the threat of multithreaded access. 


Richard Grimes writes, talks, and advises extensively on COM and ATL. He's the author of Professional ATL COM Programming and ATL COM Programmer's Reference (both Wrox Press). Richard's latest book is Professional Visual C++ MTS Programming (Wrox Press). Reach him at atl.dev@grimes.demon.co.uk
 


c0Title: Create fully featured Win32 apps without using MFC.
c1Code:
April 2000

http://www.devx.com/premier/mgznarch/vcdj/2000/04apr00/at0400/at0400.asp
Write With WTL 

by Richard Grimes 


     The Windows Template Library (WTL) has been the subject of Internet mailing lists and newsgroups for well over a year now. Some people speculated it would become part of ATL 4.0; others thought it would replace MFC. Neither camp was correct. 
What you need:
Visual C++ 6.0
Service Pack 3
Windows 95, 98,
NT 4.0, or 2000
Microsoft Platform SDK,
January 2000  
 
WTL is a lightweight framework for writing Win32 applications. Although it lacks MFC's document-view features and OLE document support, WTL has been written from scratch with multithreading in mind, and has wrapper classes that simplify using Win32 and common controls. In this article, I'll provide a brief overview of WTL and show you the facilities it adds to ATL. I'll start by looking at the new WTL AppWizard and the application types you can choose from. Then I'll explain the view architecture and describe two view classes that add splitter and scrolling window support to your application. I've also included a Registry viewer application, which demonstrates how to use WTL (download the code here). 

You can find WTL in the Sources folder in the Platform SDK installer (see Links). To use WTL, you won't need to install anything else from the Platform SDK, because you'll already have ATL 3.0 installed as part of Visual C++ 6.0. 

    
Figure 1 The WTL App Wizard 
Click here.

 
A brief look through the WTL files reveals that they contain a few examples, the Visual C++ 6.0 AppWizard, and the WTL headers, but they don't contain documentation. Indeed, if you search MSDN or the Microsoft Web site, you won't find documents or code that uses WTL. It's totally undocumented and unsupported. This is a pity because it was written with ATL's ethos of being fully featured, extensible, and capable of producing small, efficient code. (And WTL is clearly worthy of commercial development.) 

WTL has an ATL AppWizard which, when installed, adds another item to the New Project dialog box. Figure 1 shows the application types you're able to produce; the type you choose depends on your application. 

An application that shows a single document will most likely use the single document interface (SDI) type, which has a single window with a menu, toolbar, and status bar. If your application needs to support more than one document (perhaps of different types), MDI�the classic multiple document interface�is a good choice (for example, Developer Studio is an MDI application). An intermediate solution is the Multiple Threads SDI option. It allows you to display only a single document type, but you can open multiple documents from the same application. This is like Internet Explorer in that there's only one instance of the application (iexplore.exe); when you try to create another instance, a new window is created instead. 

If your application will use Windows or ActiveX controls, make it dialog based. You can use the VC++ dialog editor to determine the control's position; this works best when the dialog has a fixed border. 

Finally, you can use any of the application types to host ActiveX controls or to be a COM object server. Select the options using the checkboxes at the bottom of the ATL/WTL AppWizard - Step 1 of 2 window. If you select a dialog-based project, a dialog template is added to your project's resources. This dialog is used as the application's user interface, and your code handles events and notifications from these controls. 

If you select one of the SDI project types or the MDI project type, the code is a little more complicated. The WTL approach is similar to the MFC architecture whereby you have a mainframe class and a view class. But WTL doesn't supply sophisticated message routing as MFC does. However, it's relatively easy to write code so a WTL view window can forward the message to its frame, or vice versa. 

The frame window class's command bar is comparable to the command bar window type CE developers are used to. WTL simulates the command bar by using a rebar control and attaching to it a toolbar. The rebar control (also known as the coolbar) was introduced in IE 3.0. In CE applications, menus are inserted into a command bar; WTL also simulates this action. In effect, it means that the CCommandBarCtrl class converts a menu described by a menu resource into a toolbar, thereby making it easy to associate the same command IDs and images for menu items and toolbar buttons. 

Although the frame window has a client area, this isn't the window you use to draw the user interface. Instead, the frame class has a member that's a view window. Listing 1 shows an edited form of the mainframe class. 

Mainframe Class Details
In Listing 1 , the instance of the wizard-generated CMyView class is created as the client window of the frame using the frame window as its parent window. The frame class's WM_SIZE handler ensures that the view window is resized to fill the client area of the frame window. It does this by taking the sizes of the command bar and status bar into account. 

The frame window class is derived from CMessageFilter and CIdleHandler, which are abstract base classes. This means your view class must implement a filter that weeds out messages before they are dispatched (for example, to change the way that key presses are handled), and an idle handler that is called when there aren't any messages in the queue. 

As you can see, the view class simply derives from CWindowImpl<>: 



class CMyView : public 
	CWindowImpl<CMyView>
{
public:
	DECLARE_WND_CLASS(NULL)
	BEGIN_MSG_MAP(CMyView)
		MESSAGE_HANDLER(
			WM_PAINT, OnPaint)
	END_MSG_MAP()
	LRESULT OnPaint(UINT, 
		WPARAM, LPARAM, 
		BOOL&)
	{
		return 0;
	}
};

You can use CWindowImpl<> to draw your user interface. WTL provides wrapper classes for common GDI objects such as pens and brushes, and for device contexts. However, they're thin wrappers that perform handle management and ensure the handle is valid in debug builds. These thin wrappers follow ATL's ethos, which is to provide an efficient�yet extensible�library. 

Table 1 lists WTL's new window and control classes. The two classes at the bottom of the table are particularly interesting. CSplitterWindow allows you to replace a single view window with two view windows. The splitter divides the client area of the frame window between the two views, based on the position of the splitter bar. CScrollWindowImpl<> adds to the existing view code, enabling you to show just a small portion of a larger document in your window. 

Split Your Views
To use a splitter window, make the client window in the frame, then create the view windows as the splitter's child windows. Finally, you need to add the view windows to the splitter with a call to SetSplitterPanes(). Listing 2 is a simple example of how to change the wizard-generated code to use a splitter window. 

Using scrolling windows is almost as simple as using splitting views. Notice that an Impl class provides the support to make views scroll. This implies that to make your views scroll, you'll need to derive your view from this class. Your class no longer needs a WM_PAINT handler because it uses the CScrollWindow Impl<> base class. Your view class gets access to the base class by chaining unhandled messages to the base with CHAIN_MSG_MAP. 

But your class must do some drawing, and it does this using the DoPaint() method, which is called byCScrollWindowImpl<>::On Paint(). In Listing 3 , I handle the WM_CREATE message so I can set the size of the document you can draw to and scroll around in. 

Listing 3 is a basic example of the CScrollingWindow<> class�which has other methods that allow you to specify how large page and line scrolling should be, as well as the position of the window over the document�but it demonstrates the class's basic uses. 

WTL has other facilities, but I don't have the space to ewxplore them in depth. Instead, here's a brief overview. WTL has wrapper classes for all of Windows' common dialog boxes, which you can use to show an Open or Save dialog box; the shell's browse folder dialog box; fonts; colors; the Find and Replace dialog boxes; and the Printer and Page Setup dialog boxes. The last two dialog boxes can be used in conjunction with the WTL printer DC and print preview classes to add printer support to your application. 

WTL also has MFC-style DDX and DDV support, which provides dynamic data exchange and validation. This way, when a dialog box is created, its controls are automatically initialized with the dialog class's data members. When the dialog box is dismissed, the data in the controls can be validated, then copied back to the class data members. 

However, there are a couple of differences between how you use DDX and DDV in WTL and how you use them in MFC. First, the data exchange and validation information is held in an ATL-style map (in MFC, these were present in DoDataExchange(), but the WTL map hides this method). Second, you have to explicitly call DoDataExchange() in the WM_INITDIALOG and IDOK handlers. WTL also provides message crackers. Instead of trying to decipher the LPARAM or WPARAM parameters of a particular message, you can use the cracker macros to call your method and pass it the appropriate parameters. 

Finally, WTL adds several utility classes, including a CString class, which is essentially a port of the MFC class with the same name. I've met many ATL developers who add MFC support to ATL projects merely for the string-handling CString provides. Now there's no need to do this! 

Despite the fact that WTL is an unsupported technology, I predict it will be popular with C++ programmers who want to produce efficient, fully featured applications. To demonstrate what you can do with WTL, I've ported the Registry viewer application I first presented in my VCDJ February/March 1999 column to WTL (see Resources and download the code). In addition, I've added a change-font facility that RegEdit lacks. This facility is a boon to people who give presentations because it allows them to show the Registry values in a font larger than the default System font. 

If you intend to write a Win32 application�with or without COM�I recommend you take a look at WTL. It provides you with an application framework; wrapper classes that allow you to use Win32, common controls, and printers; and splitter and scrolling windows. All of this without the bulk of MFC! 




Richard Grimes is the author of Professional ATL COM Programming (Wrox Press) and Beginning ATL COM Programming (Wrox Press); both cover ATL 3.0. Richard's latest book, Visual C++ MTS Programming, was published by Wrox Press last fall. Contact him at atl.dev@grimes.demon.co.uk
 


c0Title: How Simple is SMTP?
c1Code:
TechNet Home > TechNet Magazine > How IT Works: How Simple is SMTP?
How IT Works
R'ykandar Korra'ti


SMTP, the Simple Mail Transfer Protocol, carries the electronic mail of the world. While other message transferring systems exist�some more efficient, some better at specific tasks, some privately owned and some public�none have won the widespread public acceptance of the venerable SMTP, first defined in RFC 821, all the way back in 1982.

But how does SMTP work? The "Simple" part of the name is pure truth in advertising. A message can be moved from one SMTP server to another using one of the simplest TCP/IP protocols (line-oriented telnet) and just a few simple text commands. One SMTP server makes a telnet-like connection to TCP port 25 on the other; it then sends commands and data, receiving numeric responses.

This process can be simulated with any telnet client. In fact, in the early days of the grand network unification of ARPAnet, Bitnet, Edunet, and several other major networks, a lot of testing was done this way, with developers connecting to an SMTP server and typing commands at it, just to see what would happen. To do this yourself, run telnet from a command prompt and connect to an online SMTP mail server on TCP port 25. The server will send back a response that looks a lot like this: 

C:\> telnet newmoon.microsoft.net 25
Trying 127.0.0.1...
Connected to newmoon.microsoft.net.
Escape character is �^]�.
220 newmoon.microsoft.net Microsoft ESMTP MAIL Service, Version: 
6.0.3790.1830 ready at  Sun, 15 May 2005 22:56:26 �0700

As easily as that, the client machine is ready to talk to that SMTP server as if it were an SMTP peer. Type commands, and they�ll be processed and responded to with numeric response codes. 

These three-digit coded responses, in this case, 220, may look familiar to Webmasters. The first digit indicates success or failure. 1 indicates a success requiring confirmation, 2 indicates complete success, and 3 indicates success so far, but that more input is expected. 4, the first failure code, is used for failures that may be temporary, such as the mail account existing but being locked; 5 indicates that the failure condition is permanent, such as a syntax error in the command. The second and third digits provide further details, but at the top level, all that matters is that 1xx, 2xx, and 3xx are good, and 4xx and 5xx indicate problems. (For further information on mail response codes, read RFC 1893.)


Issuing Commands

EHLO (or HELO) identifies the server initiating the connection (see the sidebar "The Difference Between HELO and EHLO?" to understand the difference between the two). It also tells the receiving server to clear its slate. The format is: 

EHLO <network name of connecting machine>

The parameter is mandatory on all recent SMTP servers, despite the fact that all modern servers will also use DNS to identify your actual domain and machine name, if possible. It will also log the IP address before responding with another three-digit response code (250, in most cases), and a greeting message: 
250 newmoon.microsoft.net Hello [127.0.0.1]

The receiving machine has now identified the sending server and is ready to continue. 

The sending machine must next provide the mail�s individual sender�that might be the person on the From: line, but it often isn�t; it could, for example, be a mailing list software package, a redirector, or some other agent. This is envelope data, rather than header data: 

MAIL FROM: <email address>


The e-mail address must be in a valid format, and with any modern e-mail server, must indicate a valid domain. Invalid MAIL FROM: addresses will be rejected, thusly: 

MAIL FROM: sajkdflaef
553 5.5.4 sajkdflaef... Domain name required for sender address sajkdflaef
MAIL FROM: asfe@asefsad.asf
553 5.1.8 asfe@asefsad.asf... Domain of sender address asfe@asefsad.asf does not exist
MAIL FROM: sample@microsoft.net
250 2.1.0 sample@microsoft.net... Sender ok


Next, the address (or list of addresses) to receive the messages must be specified, as arguments to the RCPT TO: command: 

RCPT TO: <email address>

Only one e-mail address may be specified with this command, but the command may be repeated as many times as needed with different addresses as parameters: 
RCPT TO: sample@microsoft.net
250 2.1.5 sample@microsoft.net... Recipient ok
RCPT TO: test@microsoft.net
250 2.1.5 test@microsoft.net ... Recipient ok



Once all addresses have been specified, it�s time to send the actual mail! This includes the actual header as seen by the mail client, then a blank line, then the message body and any attachments. Describing all that is well beyond the scope of this column (see RFC 2822, for starters) but the command to tell the server that it�s time for the actual message isn�t. It�s one of the simplest SMTP commands: 

DATA

There are no parameters for this command. Barring error, the server will reply: 
354 Enter mail, end with "." on a line by itself

(Note a 3xx success code: "successful so far, more input expected.") Then the message header and body should be sent, followed by a period on a line by itself indicating message end. If all goes well, the server will respond to the standalone period with this response code: 
250 2.0.0 Message accepted for delivery

And the message is on its way! The connecting server can then start another message (with another MAIL FROM: command), send other SMTP commands, or end the session by sending a QUIT command on a line by itself: 
QUIT
221 2.0.0 microsoft.net closing connection

QUIT must prompt a success error code and connection drop by the server. And that�s all you need to move a piece of mail. 

However, there are several other standard commands available: NOOP, RSET, VRFY, and EXPN. These are neither optional nor obsolete, though they are of somewhat limited use in the modern corporate environment. For a complete list of all commands, including obsolete verbs, see RFC 2821, RFC 1123, and RFC 821, available via MSN� Search. Remember that later RFCs supersede earlier ones, and that some commands have been made obsolete, like the TURN, SEND, SOML, and SAML commands described in RFC 821. The simplest of these commands is NOOP, useful mostly in testing to avoid timeouts; it does nothing and can generate only a successful response, with no change in state, as shown here: 

NOOP
250 2.0.0 OK


RSET clears the MAIL FROM: and RCPT TO: address stacks, throwing out any message delivery in progress, and resetting the connection back to the state it was in just after HELO or EHLO. The command should never cause the server to disconnect or require a new EHLO/HELO exchange. It takes no parameters: 

RSET
250 2.0.0 Reset state


The Difference Between HELO and EHLO
EHLO indicates that the client supports at least one of several possible extensions that are not part of the basic SMTP specification. HELO indicates that it does not, and that only the minimum SMTP set will be used when talking to this server. Many of these extensions are common and standardized; others may be local to the particular SMTP host only, in which case, the extended commands must begin with the letter X. All extended commands the server supports must be listed as part of the server�s response to EHLO, one per line, each line prefixed with code 250. Typical uses of extended commands are to transfer binary information in non-encoded form, and to tunnel another protocol through SMTP.

The command VRFY allows clients to validate individual e-mail addresses. Many postmasters disabled this command early in the spam wars, since some spammers began using it to clean their mailing lists. Support in some form, however, is still required by the SMTP specification. For servers supporting it as described in the RFC, the format is: 

VRFY <email address>


VRFY submitted with a valid address returns a canonical expansion of the e-mail address given, complete with friendly name. An invalid address, by contrast, triggers an error code 550: 

VRFY dara@microsoft.net
250 2.1.5 Dara Korra�ti <dara@microsoft.net>

VRFY bogus-address@microsoft.net
550 5.1.1 bogus-address@microsoft.net ... User unknown


Finally, EXPN historically provided a way to expand a mailing list into its component members. This allowed e-mail clients and servers to identify all the members of such a list. As can be easily imagined, this command, too, was an early casualty of the spam wars. Independently of that, it also became less and less useful as mailing list management software changed, and became less integrated with the MTA (or Message Transfer Agent). Many third-party mailing list management software packages do not provide mail servers with ways of supporting EXPN correctly at all. However, servers that do support it as intended should return all the e-mail addresses of the list members, each prefixed with a success code, or a 550 failure if the list name doesn�t exist: 

EXPN mylist
250 2.1.5 sample1@microsoft.net
250 2.1.5 sample2@microsoft.net
250 2.1.5 sample3@microsoft.net

EXPN bogus-list
550 5.1.1 bogus-list ... User unknown

Collectively, these commands complete the minimum required set for SMTP servers. Simple, isn�t it? 



--------------------------------------------------------------------------------
R'ykandar Korra'ti, postmaster for a small co-op ISP, lives near Seattle with her partner Anna. Having previously shipped mail products at Microsoft, she is now looking at grad school in a CS-related field so esoteric it doesn�t really have a name. Potential faculty advisors can reach her at darako@murkworks.net.

--------------------------------------------------------------------------------
From the November � December 2005 issue of TechNet Magazine.
We welcome your comments. Please feel free to send us feedback. 
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
� 2005 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.


c0Title: Mail FAQ
c1Code:
Archive-name: sending-mail-from-code-with-microsoft
Last-modified: 2000/jan/05
Version: 1.0.8
 
 FAQ: Sending Mail From Code with Microsoft Systems
 
 Author: Daniel J. Mitchell <djmitchella@yahoo.com> 
 Date: 2000/jan/05
 
 This document attempts to cover some of the more frequently asked 
questions about sending mail using the Microsoft mail APIs.
  ______________________________________________________________________
 
  Table of Contents:
 
  1.  Welcome
  1.1  Disclaimer
  1.2  Copyright
  1.3  What's New?
  1.4  Where can I find this FAQ?
  1.5  What's with all the KB article numbers?
  2.  Introduction.
  2.1 Which ways are there to send mail from my application?
  2.1.1 Simple MAPI.
  2.1.2 CMC.
  2.1.3 MAPI ActiveX control.
  2.1.4 Extended MAPI.
  2.1.5 CDO. (Active Messaging/OLE Messaging).
  2.1.6 Outlook Automation.
  2.2 Which should I use?
  3. Questions
  4. General version issues.
  4.0 What exactly is MAPI, anyway?
  4.1 Can I use MAPI/CDO with Outlook Express?
  4.2 How do I install Windows Messaging?
  4.3 Where can I get CDO?
  4.4 How do I use CDO from C++?  
  4.5 How do I use CDO from Java?
  4.6 Which mail programs support CDO?
  4.7 How do I get the CDO HTML rendering library to run? I've installed
      Outlook, but still no joy.
  5. Outlook.
  5.1 How do I use Outlook from my C++ code?
  5.2 Can I run two Outlooks at the same time pointing at different 
      mailboxes?
  5.3 When my Outlook code is finished, Outlook doesn't unload. Why?
  5.4 How can I send mail containing RTF from Outlook?
  5.5 Can I drive Outlook Express from code?
  5.6 What's going on with my default mail system? How do I make it 
      Outlook/stop it being Outlook/fix weird reply behavior?
  6. Mail format.
  6.1 How can I send mail containing RTF from CDO?
  6.2 How can I send mail containing HTML?
  7. Profiles and identity.
  7.1 How can I send mail without the "Choose Profile" dialog appearing?
  7.2 How do I send mail without knowing the name of a profile?
  7.3 How do I find the name of the default profile?
  7.4 What do I do if there is no default profile?
  7.5 How do I build a profile?
  7.6 Why does my MAPI application fail when I try and run it as an NT
      service?
  7.7 How can I find the mailbox for a particular NT account? (and
      vice versa).
  7.8 How can I loop over all the mailboxes on an Exchange Server and
      process them?
  7.9 How do I send mail with a different ReplyTo value than the sender?
  7.10 How do I find the SMTP address for someone? I keep getting the
       X.400 address for them.
  8.  Missing features/bugs.
  8.1 How can I send a task request from CDO/MAPI?
  8.2 How can I read calendar information from MAPI?
  8.3 Okay, how do I find the calendar folder at all from MAPI?
  8.4 How can I read someone else's calendar? I have permissions, but I
      can't read the messages as AppointmentItems.
  8.5 How do I find all appointments/meetings between given dates?
  8.6 Why does my code leak memory?
  8.7 How do I access custom properties in CDO? I get MAPI_E_NOT_FOUND
      when I try and read them.
  8.8 Why do my custom properties disappear from recurring meetings?
  8.9 Why does my sent mail stay in the Outbox?
  8.10 When I read an attachment with the VB MAPI controls, I can only 
      get the 8.3 version of the filename?
  8.11 Why do I get 2147483647 messages when I try and count the messages
       in a folder?
  8.12 Why does my advise sink miss the first event that passes it?
  8.13 Why can't I read calendar entries from _my_ calendar folder?
  8.14 Why do I get MAPI_E_NOT_FOUND trying to read/write properties on 
       messages?
  8.15 Why is it so complicated to do simple things in MAPI? Isn't there
       an easier way?
  8.16 I found the ID for a property on messages -- but now I'm on a 
       different server, the ID's changed. What gives?
  8.17 My MAPI application fails when I try and run it from an MTA thread
       and/or an ATL (D)COM server.
  8.18 What's with the HRESULTS I get in my C++ CDO errors? They don't 
       make any sense?  
  8.19 Why can't I open the messages I get in notifications to my 
       Outlook extension?
  8.20 Why do I get MAPI_E_NO_SUPPORT trying to open a calendar folder?
  8.21 What happens when I try mixing multi-threaded code and MAPI?
  8.22 Why do I get CdoE_NO_SUPPORT when trying to log in?
  8.23 Why don't I get calendar items in my event script?
 
  A. Other sources of information.
  B. Credits.
  C. Delphi extra bits.
 
  ______________________________________________________________________
 
  1.  Welcome
 
  This document has been written to attempt to answer some of the more
  frequently asked questions about sending mail using Microsoft's APIs and
  programming tools. Many questions come up time and time again on the
  assorted newsgroups dedicated to this, and hopefully this document should
  save people needing to ask the same questions, and provide a standard 
  answer to them. 
 
  Note that it does _not_ cover questions about Exchange or Outlook other
  than as much as is needed to cover mail-enabling applications. If you
  are having problems with your Out Of Office Wizard, for instance, this
  is not the FAQ you want. (I don't think such a FAQ exists yet, in fact,
  though I may be wrong.)
 
  It is also not meant to be a replacement for the online documentation 
  for the mail APIs, or a beginners' guide. It does answer some common 
  basic questions, but if you want sample code, then go to the 
  documentation.
 
  1.1  Disclaimer
 
  Disclaimer: ``This FAQ is presented with no warranties or guarantees
  of ANY KIND including correctness or fitness for any particular
  purpose.  The author of this document has attempted to verify
  correctness of the data contained herein; however, slip-ups can and do
  happen.  If you use this data, you do so at your own risk.''
 
  Disclaimer 2: ``This FAQ is in no way authorised or endorsed by 
  Microsoft, and should not be taken to speak for or on behalf of Microsoft.
  All references to Microsoft products acknowledge the trademarks owned
  by Microsoft.''
 
  1.2  Copyright
 
  Copyright 1999,2000 by Daniel J. Mitchell.  All rights reserved worldwide. 
  Permission is granted to copy this document for free distribution so long 
  as it remains intact and unmodified.  For other arrangements, contact the 
  author/maintainer via email: <djmitchella@yahoo.com>
 
  1.3  What's New?
 
  o  v1.0.0 : First version of FAQ.
  o  v1.0.1,2 : Table of contents fixed, xrefs fixed.
  o  v1.0.3 : URL added, Q8.3,8.13-15 added, other questions updated.
  o  v1.0.4 : Profile creation with MAPI info added.
  o  v1.0.5 : Delphi info added.
  o  v1.0.6 : Samples URL added, account<->mailbox info added.
  o  v1.0.7 : Whole bunch more stuff added.
  o  v1.0.8 : More KB articles added, link to recurring meetings info added.
 
  1.4 Where can I find this FAQ?
 
  The current version of this FAQ is posted every two weeks or so; it is
  also mirrored on the WWW at 
  http://www.geocities.com/djmitchella/mailfaq.txt
  or http://go.to/mailfaq if you want a shorter URL but more advertising
  junk. 
 
  1.5  What's with all the KB article numbers?
 
  A lot of these answers simply refer you to KB articles; sometimes I've
  put in a direct URL, sometimes I just give the number. In the latter
  case, go to http://support.microsoft.com/support/search/c.asp?FR=0 and
  do "search by article number" to find the article in question. At
  some stage I'll convert them all into links, probably at the same time
  as I make a real HTML version of this. Apologies for any inconvenience.
 
  Alternatively, substituting in the obvious way in this link:
  http://support.microsoft.com/support/kb/articles/q123/4/56.asp  
  will work with the current organisation of MS's website.
 
  At some point I'm intending to put in the keywords you could use to find
  these KB articles yourself; there's a knack to finding things in the KB, 
  but a lot of these questions are answered in there -- hopefully giving 
  guidelines to how to find things should mean that more questions can be 
  solved without needing outside assistance. That's for later..
 
  2.  Introduction.
 
  Microsoft provides a large number of possible ways to send mail from 
  your application. Some of these are easier to use than others; some
  provide more features; some provide a more low-level and powerful 
  interface. Depending on what you want to do with your application, the
  methods you use may vary.
 
  2.1 Which ways are there to send mail from my application?
 
  Note that this only covers Microsoft products. There are a number of
  third-party mail libraries, which are not covered here. Note also that
  not all of the methods listed below are available from all programming
  languages. Note also that it may be possible to shoehorn some APIs into
  some languages given a lot of knowledge of the language in question. Oh,
  and this only covers Visual Basic, C, and C++ as possible languages -- I
  don't have any experience with other languages. Also, when I say "C++"
  it generally means that they are a set of COM objects -- you can use these
  from C, it's just (a lot) more work. 
 
  Delphi information below courtesy of Paul Qualls.
 
  This isn't intended to document the APIs in question, just to list them --
  use the MSDN documentation for more. Where possible, I've provided the
  location in the MSDN helpfiles, because some of this stuff can be tricky
  to find. You can probably find it more rapidly by going to the index and 
  searching for the last entry in the hierarchy given.
 
  One other thing to note is that this doesn't cover sending mail using
  direct SMTP -- that's another thing entirely. 
 
  2.1.1 Simple MAPI.
 
  Very limited featureset -- send mail, read messages from inbox only, 
  pop up standard addressbook dialog. Usable from C/C++ from mapi.h, usable
  from VB by declaring the functions manually.  Usable from Delphi by
  including MAPI in the Uses Clause. 
  Documented: MSDN under Platform SDK|Messaging and 
  Collaboration|Guide|Programming with Simple MAPI. 
 
  2.1.2 CMC.
 
  Similar functionality to Simple MAPI; this is just another interface 
  created (I assume) to match up with some standard or another.
 
  2.1.3 MAPI ActiveX control.
 
  Visual version of simple MAPI for VB: use by project|components|Microsoft
  MAPI control. Not the same interface, but roughly the same level of 
  functionality. Documentation: Visual Studio 6.0 Documentation|Visual Basic
  Documentation|Using Visual Basic|Component Tools Guide|Using the ActiveX
  controls|Using the MAPI Control. Also usable from C++ by inserting the
  control as with any ActiveX control. Usable from any Delphi form 
  similarly.
 
  2.1.4 Extended MAPI.
 
  C++ only, as far as I know. This is the lowest level interface available,
  and is the interface that everything else eventually uses. As such, you 
  have the ability to do anything that you can do with any other API -- 
  but that makes some assumptions about documentation of message formats
  that aren't necessarily true.
 
  Not particularly easy to use -- once you get the hang of it, it's a 
  reasonably consistent set of interfaces. Until you do get the hang of it,
  though, it's a steep learning curve. Provides features that you can't
  get at with any of the other APIs, so you may have to use this.
 
  Also usable in Delphi: you need translated header files available at 
  http://sunsite.icm.edu.pl/delphi/ftp/d30free/mapid10.zip to be able to
  reference the interfaces, though. (I don't use Delphi, so I don't know
  how accurate these files are; I've had reports that there are problems 
  with them; to be precise, any constants in the original header files
  ending in B (for instance 0x123409AB) have the final digit removed
  in the corresponding .pas file (so this would become 0x123409A). This
  is presumably fixable manually, I guess. Many thanks to Ivan Borissov 
  Kojuharov for this information.)
 
  2.1.5 CDO. (Active Messaging/OLE Messaging).
 
  This is a more powerful set of APIs that lives on top of MAPI. Easier to
  use than MAPI, and provides a broader set of objects to wrap up some of 
  the undocumented formats of MAPI. Usable from VB, C++, Delphi (with 
  CreateComObject('Mapi.Session') ), etc. Lacks a lot of the low-level 
  features of MAPI, and has some obscure holes in the implementation. 
  Still much much easier to use than Extended MAPI, though.  Current 
  version is 1.2.1 -- v1.1 was called "Active Messaging", v1.0 was called 
  "OLE messaging". Documented in Platform SDK|Messaging and 
  Collaboration|CDO. 
 
  Here's a table of which versions of CDO do what, and where you can get
  them (thanks to Siegfried Weber for this list).
 
  CDO 1.x for MAPI enabled applications (CDO.DLL) 
    Comes with Outlook 9x/2K, Exchange server + client & OWA
    No native support for MHTML, SMTP, NNTP, POP3, IMAP4, LDAP etc.
  CDO 1.2 for Windows NT Server (CDONTS.DLL) 
    Comes with Windows NT 4 server option pack, IIS SMTP service only.
    Only support for SMTP and MHTML, no MAPI or OLEDB support - 
    runs ONLY on NT server with IIS4 and SMTP service installed 
  CDO for Windows 2000 AKA CDO 2.0 (CDOSYS.DLL) 
    Comes with Win2K Prof. Server, Adv. Server
    Not MAPI support at all, only SMTP and NNTP 
  CDO for Exchange 2000 - AKA CDO 3.0 (CDOEX.DLL) 
    Comes with Exch2K only. No client release as of yet
    No MAPI support at all, only OLEDB to access Exch2K Webstores etc.
    While Win2K comes with a CDONTS.DLL it is only provided for backwards 
    compatibility. Same applies for Exch2K which still delivers CDO.DLL 
    and CDOHTML.DLL (and a working MAPI subsystem) to support the "old" 
    MAPI based CDO stuff.
 
  2.1.6 Outlook Automation.
 
  Use Outlook itself through automation. This has a different featureset to
  CDO; it fills in some gaps, and opens up others. Easy to use from VB, 
  more painful to use from C++ because of strangenesses in the type library.
  Usable from Delphi with early/late binding; samples in appendix C.
  Documented in a difficult-to-find help file reputedly somewhere on one
  of the Outlook install CDs -- look in vbaoutl.hlp in your Office directory
  for more on this. 
 
  2.2 Which should I use?
 
  As with most questions of this nature, the best way to answer it is to 
  work out what you need to do; some features are only present in one of
  the APIs above. If your particular requirement is not listed below, then
  a more general set of recommendations follows.
 
  If you need to send task requests, you have to use Outlook. (see also
  8.1).
 
  If you need to send RTF messages, you have to use MAPI or CDO. (see also 
  5.4/6.1).
 
  If you need to process calendar entries, you have to use CDO or Outlook.
  (see also 8.2).
 
  If you need to log into a user that doesn't have a profile created on 
  the system, you have to use MAPI or CDO. (see also 7.1 et al)
  
  If you don't have one of those specific requirements, you can use any of
  the APIs. If all you want to do is pop up the standard "File|Send Mail"
  dialog, or just want to send plaintext mail messages, Simple MAPI will do 
  what you want just fine. If you want to do something more complex, CDO is
  probably your best bet. 
 

  3. Questions
 
  These aren't meant to cover all possible questions; they're just a list
  of questions that have come up frequently in the past.
 
  If your question is not answered below, please try and find the answer
  yourself before asking. Every single one of the URLs below was found by
  simply searching the resources mentioned at the end of this FAQ for 
  keywords found in the question.. Asking questions that are trivially
  answered by searching the KB for (for instance) "NT service" does not
  give a good first impression.
 

  4. General version issues.
 
  4.0 What exactly is MAPI, anyway?
 
  MAPI is the Messaging API -- it's the underlying system that all the other
  mail APIs use one way or another. This is the code that lives in 
  mapi32.dll. All the other APIs wrap MAPI in some way or another.
 
  4.1 Can I use MAPI/CDO with Outlook Express?
 
  (Windows 98 installs Outlook Express by default). No, you can't -- you
  have to install Windows Messaging. See Q3.2. Note that if you install
  Outlook Express, it will overwrite your MAPI settings and you may have 
  to reinstall Windows Messaging. Alternatively, if you already had MAPI
  installed, search for the file mapi32.oe, and rename that back to
  mapi32.dll; that should work. (but might have weird consequences for
  Outlook Express, so test this first on your system). Theoretically, 
  Outlook Express supports Simple MAPI, but in practise this tends not to 
  work. 
 
  4.2 How do I install Windows Messaging?
 
  If you have Windows 95, they should be installable from the Add/Remove
  programs dialog. If you have Windows 98, you can either run the file
  wms.exe from the Windows 98 CD, or you can try 
  ftp://ftp.microsoft.com/softlib/MSLFILES/exupdusa.exe which should also 
  work.
  You can download an old version of this from
  http://www.microsoft.com/Exchange/downloads/intro.htm, too.
  Also see http://www.slipstick.com/exchange/win98-wminstall.htm for 
  more info.
 
  4.3 Where can I get CDO?
 
  Download it from http://microsoft.com/exchange/downloads/CDO.htm.
 
  4.4 How do I use CDO from C++?
 
  Basically, put 
  #import <cdo.dll>
  using namespace MAPI;
  at the top of your code, make sure you call CoInitialize(NULL), and go
  from there -- the object model's the same as in VB, but you're using
  -> instead of . to access methods/properties.
 
  For samples, see KB articles 171098, 171429, 173550, 195545, and 178480.
  Also see 179233 for a glitch to be aware of.
 
  4.5 How do I use CDO from Java?
 
  (I've not tried this myself, but I came across this article while poking
  around): KB 216723 has fairly detailed instructions on doing this with
  Visual J++. If you're using a non-Microsoft Java, you may have more
  difficulty getting at the type library information -- your particular
  environment may have extra help. I know nothing about this myself, sadly).
 
  4.6 Which mail systems support CDO?
 
  Currently, the list of mail programs that definitely support CDO are
  (these all install the Extended MAPI system, in other words):
  Exchange 5.0 Client, Outlook 97, Outlook 98 (only in corporate/workgroup 
  mode), Outlook 2000 (only in corporate/workgroup mode).
 
  Exchange 4.0 client may work, but there are a lot of bugfixes not in the
  version of MAPI that comes with that. 
 
  4.7 How do I get the CDO HTML rendering library to run? I've installed
      Outlook, but still no joy.
 
  You can only use the CDO rendering library on a machine with Outlook Web
  Access installed. 
  
 
  
  
  5. Outlook.
 
  5.1 How do I use Outlook from my C++ code?
 
  Firstly, see KB 199870.
 
  If you're using Outlook 97, and just try "#import msoutl8.tlb", you'll
  get an enormous number of errors -- something is wrong with either 
  #import, or the type library information.  To workaround this, use
  the following code: (thanks to James B. at microsoft for this).
 
  (you'll need to change the #define OUTL8 and paths to the DLLs 
   appropriately for your system or it probably won't work too well).
  
// For using the Outloook Object Model
#define IMPPROPS rename_namespace("OL")
 
// Define this according to the OL version you are compiling under 
#define OUTL8 // #define OUTL8 or OUTL85 or OUTL9
#if defined(OUTL9) // Outlook 2000
#import "C:\Program Files\Microsoft Office\Office\mso9.dll" IMPPROPS
#import "C:\Program Files\Microsoft Office\Office\msoutl9.olb" IMPPROPS
#elif defined(OUTL85) // Outlook 98
#import "C:\Program Files\Microsoft Office\Office\mso97.dll" IMPPROPS
#import "C:\Program Files\Microsoft Office\Office\msoutl85.olb" IMPPROPS
#elif defined(OUTL8) // Outlook 97
#import "stdole2.tlb" IMPPROPS include("IPicture") \
 exclude("Font", "IUnknown", "IDispatch", "IEnumVARIANT", "IFont") 
#import "fm20.dll" IMPPROPS include("IFont") \
  exclude("OLE_COLOR", "OLE_HANDLE") rename("Pages", "FMPages") 
#pragma warning(disable: 4146)
#import "D:\Program Files\Microsoft Office\Office\mso97.dll" IMPPROPS \
rename("DocumentProperties", "DocProps") 
#pragma warning(default: 4146)
#import "D:\Program Files\Microsoft Office\Office\msoutl8.olb" IMPPROPS \
 rename("_IMailItem", "_MailItem")
#endif
 
  5.2 Can I run two Outlooks at the same time pointing at different 
      mailboxes?
 
  It doesn't seem to be possible to do this -- even setting the NewSession
  parameter to Outlook to be "true" doesn't get around this. The second
  Outlook always hooks up to the first running session.
 
  5.3 When my Outlook code is finished, Outlook doesn't unload. Why?
 
  This only seems to happen from C++ -- sometimes you'll get reference
  leaks, smart pointers and all. It's not clear exactly where the reference
  leaks come in, but you can usually get rid of them by putting an extra
  manual call to Release() on the underlying object. Generally, the best 
  way to find where to do this is the usual one of cutting out code until
  Outlook unloads, then put it back in until you find the source of the 
  leak.
 
  5.4 How can I send mail containing RTF from Outlook?
 
  This seems to be impossible, despite the fact you can do it from "real"
  Outlook. The only solution anyone has come up with thus far is to 
  configure Outlook to use Word as it's email composer, and automate the
  instance of Word that appears somehow. I haven't tried this.
 
  5.5 Can I drive Outlook Express from code?
 
  No, it doesn't expose any official interfaces for you to use. See KB 
  216281 for more on this.
 
  5.6 What's going on with my default mail system? How do I make it 
      Outlook/stop it being Outlook/fix weird reply behavior?
 
  See KB Q181056, Q180429, & Q175862 (more Outlook-related, but they still
  relate to setting MAPI as your default mail system in case it's not
  that any more).
 
  6. Mail format.
 
  6.1 How can I send mail containing RTF from CDO?
 
  Use the DLL provided by Microsoft at 
  http://support.microsoft.com/support/kb/articles/q172/0/38.asp .
 
  6.2 How can I send mail containing HTML?
 
  In the same way as you would send RTF -- use the DLL above, or use the
  Extended MAPI RTF interface, but with HTML text instead of RTF text. (I
  haven't tested this myself, because we use Outlook 97 here).
  You'll have to put "{\fromhtml1 " at the start of your HTML text, and
  "}" at the end, as well. See KB article 216344 for more on this.
 
  7. Profiles and identity.
 
  7.1 How can I send mail without the "Choose Profile" dialog appearing?
 
  This varies with the API you're using, but in general, look up the
  documentation for the relevant "Logon" function, and pass in the name
  of a mail profile, and set any showDialog flags to false.
 
  7.2 How do I send mail without knowing the name of a profile?
 
  You have to tell the system to use the default profile. This is possible
  using Extended MAPI -- set the MAPI_DEFAULT_PROFILE flag in the flags
  argument to MapiLogonEx. It's not directly possible using any other
  API; you can sneak this into CDO if you're using C++, using code like:
  IMAPISession * lpSession;
  MapiLogonEx(...); // log into default profile
  SessionPtr pCDOSession;
  pCDOSession->MAPIOBJECT = lpSession;
  which will give you a CDO session pointing at the MAPI session.
 
  7.3 How do I find the name of the default profile?
 
  Using Extended MAPI, look up the IProfAdmin interface. Using anything
  else, you're pretty much out of luck. The information _is_ in the
  registry, but this isn't documented so you may not want to trust this:
  Profile key is DefaultProfile, directory is:
  Win95/98: HKCU\Software\Microsoft\Windows Messaging Subsystem\Profiles
  WinNT: HKCU\Software\Microsoft\Windows NT\CurrentVersion\
         Windows Messaging Subsystem\Profiles
 
  Also see http://support.microsoft.com/support/kb/articles/Q171/4/22.asp
  for a VB implementation of the last.
 
  7.4 What do I do if there is no default profile?
 
  This can be the case -- just because someone only has one profile set 
  up, that's no guarantee that it's the only one. In this case, you have to
  use IProfAdmin and set that to be the default. If they have multiple 
  profiles and no default, there's no obviously correct solution other 
  than popping up UI and making them choose. Alternatively, you can use
  dynamic profiles. (see 7.5)
 
  7.5 How do I build a profile?
  
  If you want to build a permanent profile, you have to use the IProfAdmin
  interfaces in Extended MAPI. There are a number of external programs
  that will do this -- newprof.exe which comes with Outlook 97 is the 
  Microsoft version of this. See
  http://support.microsoft.com/support/kb/articles/q145/9/05.asp for more
  on this. There's also profgen, available at
  ftp://ftp.microsoft.com/bussys/exchange/exchange-unsup-ed/
 
  If you want a profile to be created based on the mailbox name and 
  server location, you can use CDO; see the documentation for the 
  ProfileInfo parameter to the Logon method of a Session object. 
 
  If you want to log into your Exchange Server anonymously, then assuming
  the server is set up to allow that, see
  http://support.microsoft.com/support/kb/articles/q195/6/62.asp for
  how to do this, and more information on the ProfileInfo parameter.
  
  See http://support.microsoft.com/support/kb/articles/Q173/5/50.asp for
  information on doing this from C++.
 
  If you need to do this with Extended MAPI, see 
  http://support.microsoft.com/support/kb/articles/Q170/2/25.asp, and the
  entry titled "Creating and Configuring a Profile" in MSDN.
 
  Other MSDN entries worth looking at are titled "Creating a profile with
  custom code", and "Creating a profile through MAPI".
  
  7.6 Why does my MAPI application fail when I try and run it as an NT
      service?
 
  Because profiles only exist for the user that your code is running 
  as, and services tend to run as the system account.
  See KB 177851 for how to build a VB NT service that'll send mail,
  KB 185139 for explanation of getting MAPI_E_INVALID_PARAMETER from
  logging on inside a service with very old MAPI dlls, and 
  KB 197820 for a nice overview of using MAPI from services.
 
  7.7 How can I find the mailbox for a particular NT account (and vice
      versa)?
 
  This isn't as simple as it might seem -- the problem is that the name
  of the mailbox isn't stored directly in the GAL. However, code along
  the following lines will do what you want (yes, it's not a pretty 
  solution, but it's the only way..)
 
  a. Open the GAL.
  b. For each entry in the GAL:
  c. Open the PR_EMS_AB_ASSOC_NT_ACCOUNT (or CdoPR_EMS_AB_ASSOC_NT_ACCOUNT)
     field.
  d. The value of this is a binary SID, Security Identifier. You can then
     translate this to an NT account and domain pairing using the NT-only
     function LookupAccountSid. You may need some VB/Delphi/whatever magic
     to call this function in those languages; whatever you usually do to
     call Win32 functions will work again here. (I don't know what this is,
     I should point out).
  e. You now have a name and domain. If this name and domain matches the
     name you're looking for, add the mailbox name to a list.
  f. Keep looping until you're done with the GAL.
  g. You now have a list of mailboxes. This list can contain:  
     0 entries. No mailbox is owned by this account.
     1 entry. Done!
     >1 entries. This account owns more than one mailbox -- now you'll need
                 to find some way of resolving which one is the correct 
                 one. (example: the system admin probably owns both
                 postmaster@company.com and JoeAdmin@company.com -- there's
                 no guaranteed way to tell which is correct).
 
  That'll convert from domain\user to mailbox. One obvious optimisation is
  that you can call LookupAccountSID on the user, and then just compare
  SIDs rather than doing a lookup for each entry. To go the other way 
  around is a bit easier, because a mailbox only has one owner, so you just have
  to open the GAL, open the relevant entry, get the SID, and call 
  LookupAccountSID on that entry.
 
  Things to be aware of: if you do a LookupAccountName("userfoo"), and
  there's a _local_ user "userfoo" on the machine you do the lookup on,
  you'll get the SID for the _local_ user. This will almost certainly not
  be the SID that's in the GAL, because the GAL contains users logged into
  domains -- make sure you do a lookup on "domainfoo\userfoo". This still
  isn't perfect; sometimes one user logs in from multiple domains and
  domainone\user and domaintwo\user both have access to J.User's mailbox 
  but it's owned by domainone\user -- in this case you won't get a match,
  so beware of this possible gotcha.
 
  See KB 244670 for VB code to do part of this lot.
 
  7.8 How can I loop over all the mailboxes on an Exchange Server and 
      process them?
 
  See http://support.microsoft.com/support/kb/articles/q198/7/52.asp
  (loops finding mailbox size for all mailboxes; MAPI/C++)
  http://support.microsoft.com/support/kb/articles/q194/6/27.asp
  (just loops opening all mailboxes; MAPI/C++)
  and http://support.microsoft.com/support/kb/articles/q203/0/19.asp
  (loops over mailboxes using CDO)
 

  7.9 How do I send mail with a different ReplyTo value than the sender?
 
  See KB 181408 and 195842 for methods to do this from VB and C++ 
  respectively.
 
  7.10 How do I find the SMTP address for someone? I keep getting the
       X.400 address for them.
 
  Two ways: firstly, open the PR_EMS_AB_PROXY_ADDRESSES property on a
  recipient and loop over them searching for the entry beginning with
  "SMTP:".  This lets you get at all possible addresses for someone, 
  which may be useful. 
 
  Secondly, use (thanks to Siegfried Weber for this code):
  Public Const CdoPR_EMAIL = &H39FE001E
  Set objAddressEntry = objMessage.Sender
  strAddressEntryID = objAddressEntry.ID
  strEMailAddress = _
    objSession.GetAddressEntry(strAddressEntryID).Fields(CdoPR_EMAIL)
 
  8. Missing features/bugs.
 
  Note that this is just a list of the most commonly found problems --
  it is not by any means a complete list of bugs/misfeatures. That can
  be approximated by searching the KB for "BUG:", but even that still
  doesn't list all the strangenesses that will occur from time to time.
 
  8.1 How can I send a task request from CDO/MAPI?
 
  You can't. The format of a task request is undocumented, and the last
  word from anyone at Microsoft was that the Outlook development team were
  not willing to give out any documentation. You _can_ send a plain task
  object -- set the message's Type to "IPM.Task" and it'll arrive as a task
  but without the accept/deny buttons. Task requests seem to arrive as two
  separate messages (one in the inbox, one in the tasks folder) linked in 
  some manner; trying to simply set the type to "IPM.TaskRequest" results
  in Outlook crashing when it opens the messages.  CDOLive has 
  a partial list of the other properties that affect tasks. (see appendix)
 
  You can send task requests from Outlook, however.
 
  8.2 How can I read calendar information from MAPI?
 
  This is also undocumented -- use CDO if at all possible. Alternatively,
  CDOLive has some documentation on the format of a calendar message. (see
  appendix).
 
  8.3 Okay, how do I find the calendar folder at all from MAPI?
 
  See http://support.microsoft.com/support/kb/articles/Q171/6/70.ASP
 

  8.4 How can I read someone else's calendar? I have permissions, but I
      can't read the messages as AppointmentItems. What about calendar
      entries in public folders?
 
  (solution at end of this lot)
 
  The documentation for AppointmentItems states that you can only read
  messages as AppointmentItems from a folder that you have got by using
  Folder f = session.GetDefaultFolder(CdoDefaultFolderCalendar). This is
  a restriction of CDO imposed for some unknown reason, and basically means
  you can only open calendar items for the primary user of the session.
 
  If you can read someone else's mailbox, you can navigate to the calendar
  by looking for "Calendar" as the folder title or a folder with
  PR_CONTAINER_CLASS = "IPF.Appointment". Once there, you still need to
  somehow decode the calendar items -- using the documentation from 
  CDOLive (see appendix) you can get at a lot of the information; 
  recurrences aren't documented there, but it is possible to 
  reverse-engineer the information. See 
  http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=422943739&fmt=text for
  code I wrote to do this for recurrences. Note that the properties I
  use in that sample probably won't work on your system; you'll have to do 
  named property stuff to get the actual values. Apologies for the
  inconvenience; but then again you'd have to use named properties anyway,
  so this is just more practise at finding the names for a given thing..
  Also see http://support.microsoft.com/support/kb/articles/q196/5/08.asp
  for the KB article about this.
 
  This also applies to calendar entries in public folders, only more so --
  because a public folder is never the default calendar folder for someone,
  you can never read calendar entries from this directly.
 
  An ingenious workaround (Thanks to Siegfried Weber for this tip) is to
  read the info on the Exchange Server and mailbox for the person in 
  question from the GAL, use that to log into a dynamic profile pointing
  at that user, and then, because you're logged into that person's mailbox
  directly, you can use GetDefaultFolder. This will work, but will hit 
  problems with either memory leaks (if you log in and out, see Q8.6) or
  just having an awful lot of open sessions. That said, it's by far the
  easiest way to get this stuff working.
 
  8.5 How do I find all appointments/meetings between given dates?
 
  Here's a code fragment to do this:
 
  ' s is a session that's been logged in.
  Dim f As MAPI.Folder
  Set f = s.GetDefaultFolder(CdoDefaultFolderCalendar)
  Dim ms As MAPI.Messages
  Set ms = f.Messages
  Dim fi As MAPI.MessageFilter
  Set fi = ms.Filter
  With fi
    Dim fs As MAPI.Fields
    Set fs = fi.Fields
    With fs
      Dim f1 As MAPI.Field
      Set f1 = .Add(CdoPR_START_DATE, #11/6/1998#)
      Set f1 = .Add(CdoPR_END_DATE, #11/2/1998#)
    End With
 End With
 ' now loop over `ms' using getfirst/getnext/whatever.
 
 The important thing to note here is that the start and end date are
  _reversed_ from what you might expect. This is a CDO glitch. See
  KB Q178508 for an MS sample that does this. Also see KB 192404 for
  more about why things are backwards.
 
  8.6 Why does my code leak memory?
 
  There's a leak in the login/out code in MAPI (and thus CDO):
  See KB 215463 (leak in login code), 171427 (leak in CDO1.1 (1.2?))
  folder handling code), 188958 (general survey of ways your MAPI
  code may not be freeing things up).
 
  If you're using CDO or Outlook by using #import, see KB 231872 --
  there's a leak in the code #import generates. 
 
  Workarounds for this: 
  
  a. Don't log in and out any more than you have to -- log in at the start
     of your program, and cache the session object so you stay logged in.
  b. Make sure your program finishes every so often; when it exits, the 
     leaked memory goes away with it.
 
  These aren't _good_ workarounds, but they're all there is..
 
  8.7 How do I access custom properties in CDO? I get MAPI_E_NOT_FOUND
      when I try and read them.
 
  There's a peculiarity in the way CDO decodes the propsetIDs; see KB
  195656.
 
  8.8 Why do my custom properties disappear from recurring meetings?
 
  Because instances of recurring meetings aren't "real" messages -- CDO
  creates fake instances internally and stores them as attachments on the
  base meeting. 
 
  The properties don't actually disappear -- it's just that when you open
  one of these instances with CDO, CDO, for some peculiar reason, gives you
  a message that you can't get at these properties with.
 
  Workaround as follows:
 
  a. Open instance of meeting.
  b. Get the Parent of the meeting's RecurrencePattern; this is the "base"
     message.
  c. Loop over the table of attachments in the base meeting searching for
     an attachment where property 0x7ffb0000 | PT_FILETIME contains the 
     same time as the start of the meeting instance (no timezone issues
     to worry about here).
  d. Read the PR_ATTACHMENT_INDEX property from this row, and then do:
     hr = pMsgMAPI->OpenAttach(index, &IID_IMAPIProp, MAPI_BEST_ACCESS,
                               (IAttach**)&pAttach1);                      
     LPMESSAGE pAttachMsg;
     hr = pAttach1->OpenProperty(PR_ATTACH_DATA_OBJ,&IID_IMessage,0,0,
                           (LPUNKNOWN*)&pAttachMsg);
     or use CDO, and code like:
     Set objAttachment = objMessage.Attachments.Items(1)
     Set objEmbeddedMsg = objAttachment.Source
 
  e. Use MAPI named property stuff to read your property from pAttachMsg.
  
  You can do this with CDO, too; thanks to Siegfried Weber for the 
  attachment.Source info. (I've not tried this myself, but it should be
  clear enough how to make this work).
 
  See http://www.geocities.com/djmitchella/recurringmeetings1.txt for
  a large explanation of how I came up with this particular solution, and
  why other possible workarounds won't work. (there are a _lot_ of bugs
  that you hit along the way..)
                       
 
  8.9 Why does my sent mail stay in the Outbox?
 
  Three possiblities: if the mail arrives, then you need to set the 
  PR_DELETE_AFTER_SUBMIT flag (assuming you're using extended MAPI).
  If you're using simple MAPI, you have to set the ForceDownload flag
  to true when you log in. If you're using CDO, you may need to use the 
  DeliverNow method on the Session object -- this forces delivery of all 
  currently pending messages.
 
  8.10 When I read an attachment with the VB MAPI controls, I can only 
      get the 8.3 version of the filename?
 
  This is a limitation on those controls; you will have to use CDO to 
  avoid it. To read the attachment in the first place, you need to use
  the AttachmentPathName property of the message; the attachment is stored
  in a temporary directory when you open the message.
 
  8.11 Why do I get 2147483647 messages when I try and count the messages
       in a folder?
 
  Because the Count property can lie to you. If you look at the 
  documentation, it says that it may return &HFFFFFFF as the count of 
  messages if it decides to not count things properly, and that's the number
  above.
 
  8.12 Why does my advise sink miss the first event that passes it?
 
  Because you have to "wake up" advise sinks by doing some sort of RPC 
  event (bug). Opening a new folder and doing GetContentsTable() on the 
  folder will do this. Also, see KB 190413 for the MS explanation of this.
 
  8.13 Why can't I read calendar entries from _my_ calendar folder?
 
  See KB Q196258 (version clash with CDO 1.1 being installed mistakenly 
  with Outlook) and 194806 (now vanished, annoyingly, but it might
  come back; talks about the message class being wrong on occasions).
 
  8.14 Why do I get MAPI_E_NOT_FOUND trying to read/write properties 
       on messages?
 
  See KB 179639 (survey of possible problems with CDO code giving this 
  error) and 183094 (specifically with properties)
 
  8.15 Why is it so complicated to do simple things in MAPI? Isn't there
       an easier way?
 
  A lot of things may seem very complicated; reading a single property
  involves building a one-element array of Proptags, calling GetProps on 
  the message, etc. There are a large set of helper functions provided for
  you (for instance HrGetOneProp will do the single-property
  read) -- try looking through the list in the documentation under
  Platform SDK|Messaging and Collaboration|Messaging API|Reference|MAPI 
  Functions.
  The Exchange SDK also provides a lot of useful helper functions; look 
  under Platform SDK|Messaging and Collaboration|Microsoft Exchange Server|
  Microsoft Exchange Server Programmers Guide|Reference|Functions|Function
  Descriptions. (for instance, a one-step function to get the GAL).
  
  Also, as mentioned before, CDO provides much nicer wrappers for a lot of
  MAPI stuff; the helper functions tend to make raw MAPI code shorter, but
  not necessarily easier.
 
  8.16 I found the ID for a property on messages -- but now I'm on a 
       different server, the ID's changed. What gives?
 
  A lot of the more obscure undocumented properties that make up messages 
  use named properties -- these are properties accessed by passing a name
  and propsetID to the Exchange Server in question; the server then 
  converts these into an ID and uses that ID to store them. If you move to
  another server, the ID corresponding to a particular name may change.
  To find the name for a particular ID, your easiest route is to use MDBView
  (see appendix A), open the message, find the property you're interested
  in in the property dialog, and use the NamesToIDs button. One trick to
  be aware of is that you'll probably get something along the lines of
  "*lppPropNames.Kind.IID = 34070" -- this means that the name is actually
  "0x8516" (ie a string, 0, x, hex representation of the number). Quite why
  things wind up this way is a mystery, but this is the way it goes.
 
  To read from a named property using CDO, you need code like:
  Fields fs = message.Fields
  Field f = fs.Item("0x8516", propsetid) where the propsetID is got from
  the value from MDBView. See Q8.7, though, because CDO is a bit glitchy
  here.
 
  Alternatively, look at http://www.cdolive.com/cdo10.htm where there's a
  big list of the names and propsetIDs for most of the properties you're
  every likely to need, and save yourself a lot of effort.
 
  8.17 My MAPI application fails when I try and run it from an MTA thread
       and/or an ATL (D)COM server.
 
  Threading in MAPI seems to have some issues -- in particular, when you
  call MAPIInitialize, it calls CoInitialize(NULL). If you've already called
  CoInitializeEx() with MTA threading, the MAPI call to plain CoInitialize
  will hit problems. This can happen with the boilerplate code that VC++ 
  builds for ATL (D)COM servers if you select the wrong option in the 
  wizards. (thanks to Didier Clabaut for this info).
 
  Also, see KB 239785 for possible interaction problems with Outlook 97;
  fix is to upgrade to Outlook '98. (For reference, I haven't hit this 
  problem myself and I'm in the situation this article describes.. I may
  just be lucky, though.)
 
  8.18 What's with the HRESULTS I get in my C++ CDO errors? They don't 
       make any sense?  
 
  The code that #import generates for CDO has a bug where the HRESULTs in
  the exceptions thrown are messed up -- see KB 235361 for a table of 
  results, and search that table for the middle column matching hrFake 
  where hrFake is calculated from the _com_error e as follows:
  HRESULT hrFake = e.WCode(); hrFake = hrFake & 0xffff;
  (I'm not sure what the +1000 stuff they talk about there is, to be honest;
  doing things this way works fine).
 
  8.19 Why can't I open the messages I get in notifications to my 
       Outlook extension?
  
  (I don't know anything about this code, I'm just putting it in here because
   this is a reasonably common problem. Thanks to James B. at Microsoft for
   the source here; I'm just quoting directly from him.)
    --startquote--
  LPMDB lpStore = NULL;
  LPMESSAGE lpMessage = NULL;
  LPADRBOOK lpAddrBook = NULL;
  LPSPropValue lpProps = NULL;
  lpeecb->GetObject(&lpStore, (LPMAPIPROP*) &lpMessage);
  HrGetOneProp((LPMAPIPROP) lpMessage, PR_ENTRYID, &lpProps);
  LPSTR lpszEID = (LPSTR) new char[(lpProps->Value.bin.cb*2)+1];
  HexFromBin(lpProps->Value.bin.lpb, lpProps->Value.bin.cb, lpszEID);
  // Open the item inside the Outlook Object Model
  LPOUTLEXTCALLBACK lpoecb = NULL;
  try {
    _NameSpacePtr spMAPI =
             m_lpCEE->m_spApplication->GetNamespace("MAPI");
    _MailItemPtr spMyItem =
    spMAPI->GetItemFromID(lpszEID);
    delete[] lpszEID;
   // Do work with the item here
  } catch (_com_error) {
    ::MessageBox(NULL, "Unable to get the MailItem in OnDelivery", 
      "Error", MB_OK);
  }
  I get the application pointer in the Install method
  under the TASK context, and I save it.  You can find out how to do
  that by searching the MSDN for GetOfficeCharacter and going to the
  bottom of the one article that will come up.
    --endquote--
 
  8.20 Why do I get MAPI_E_NO_SUPPORT trying to open a calendar folder?
 
  This is probably related to Outlook '98 -- see KB 194077.
 
  8.21 What happens when I try mixing multi-threaded code and MAPI?
 
  See KB 239096 (CDO glitch where it calls CoInitialize(NULL)) and 
  239853 (same thing wrt MAPI) for more information on this.
 
  8.22 Why do I get CdoE_NO_SUPPORT when trying to log in?
 
  See KB 244547 -- some versions of CDO.DLL are incorrectly labelled as
  being for both Win9x and NT, when they shouldn't be.
 
  8.23 Why don't I get calendar items in my event script?
 
  See KB 243387 -- which just says "yes, it does this" and doesn't give
  a workaround or suchlike.. See Q8.4 for more on this sort of thing.
 
  Appendix: Other sources of information.
 
  A.1 Microsoft KB.
 
  The first place you should look is the Microsoft Knowledge base: 
  http://support.microsoft.com/servicedesks/msdn/search/default.htm
  will get you to the search page for this. Select "Messaging SDK"
  in the first combobox, and do a keyword search, or search by KB 
  article.
  
  A.2 MSDN documentation.
 
  If you don't have this locally, then http://msdn.microsoft.com/library/
  will get you to the top of the documentation tree.
 
  Also see http://support.microsoft.com/support/MessagingSDK/FAQ/cdofaq.asp
  for a (brief) Microsoft FAQ on CDO.
 
  A.3 DejaNews
  
  http://www.dejanews.com, Power Search, and search for messages in the
  groups listed next.
 
  A.4 Usenet
 
  The current recommended newsgroup is 
  microsoft.public.win32.programmer.messaging -- this is available if you
  point your newsreader at msnews.microsoft.com, in case your local news
  feed is missing the group.
  
  When searching DejaNews, you could also try 
  microsoft.public.win32.programmer.mapi, which was the original group for
  discussion of this sort of thing.
 
  The microsoft.public.exchange hierarchy also tends to have mail questions
  asked there a lot, so that would be worth trying too; specifically,
  microsoft.public.exchange.applications is occasionally good, as is
  microsoft.public.exchange.clients.
 
  Other, obsolete (as far as I know) groups this is posted to:
  microsoft.public.messaging.misc
  microsoft.public.platformsdk.messaging
 
  A.5 MAPI Mailing list.
 
  The archives of this and a joining interface are at
  http://peach.ease.lsoft.com/archives/mapi-l.html
 
  A.6 Other web sites.
 
  CDOLive: http://www.cdolive.com
  CDOLive property lists: http://www.cdolive.com/cdo10.htm (contains a list
  of the majority of the undocumented properties for Outlook  calendar/task/
  note/contact/etc items)
 
  http://www.cdolive.com/kb.htm has an enormous list of relevant KB articles
  -- this is a good place to start looking if you don't want to search 
  the entire KB for the info you're after.
 
  Slipstick Solutions outlook info: http://www.slipstick.com (this contains
  a _huge_ amount of generally useful information on utilities and
  plugins that may already do what you want).
 
  Exchange FAQ (very server-oriented, but might be useful):
   http://www.swinc.com/resource/exch_faq.htm  
 
  Old MAPI FAQ: http://www.darkweb.com/~beng/exchange/mdevfaq.htm
 
  http://212.17.127.87/MAPIResource has some samples of MAPI advise sinks.
  
  MAPI samples can theoretically be found in the MAPI hierarchy on MSDN, 
  as a starting point -- in practise, the files referred to there
  aren't obviously locateable (does anyone know where they are?) A better 
  place to go is
  ftp://ftp.microsoft.com/developr/MAPI/Samples/MFCAPPS/MFCAPPS.ZIP -- this
  contains samples and a _lot_ of handy helper functions and stuff that
  will make your life immensely easier once you start using them. Really --
  if you're doing Extended MAPI development, the functions in the Common
  subdirectory are invaluable timesavers. 
  Also, this is where you find MDBView, which you'll find amazingly handy 
  as soon as you start doing anything fiddly. This is the most essential
  tool in any MAPI developer's toolbox, I promise.
 
  If you just want a very simple MAPI sample project, KB article 239795
  contains enough code to get going with; I'd still advise using the
  mfcapps sample just because it contains MDBView..
 
  A.7 Books.
 
  The primary source on MAPI programming is "Inside MAPI", by Irving de la
  Cruz and Les Thaler, Microsoft Press. It is now out of print, but you may
  be able to find a second-hand copy. If you want to do low-level MAPI stuff,
  your life will be _much_ easier if you can find one -- it's not necessary,
  but it's worth keeping an eye out for.
 
  The "MAPI, SAPI, and TAPI developers guide" you'll find by searching
  amazon.com for "MAPI" is pretty brief -- it's possibly better than nothing,
  but the documentation is better than it.
 
  If you want information on CDO, then there's a fair few books out there;
  "Professional CDO Programming", from Wrox Press, is a good starting point,
  though I should point out that I co-authored this, so am probably not
  the most impartial judge of quality.
 
  These are the only ones I've personally read -- if you search Amazon or
  your favorite online bookstore for "Outlook" or "CDO" in the title, you
  should find a lot of other books to pick from.
  
  B. Credits.
 
  Thanks to: James B. for the code sample given above, and for being the 
  source of information at Microsoft.
 
  Siegfried Weber for CDOLive.
 
  The Slipstick Systems folks for their excellent resources.
 
  Too many other people to mention for questions answered on newsgroups
  in times past, though I really must thank Eric June at Intuitive Data
  for fielding a lot of basic questions a lot of times..
 
  C. Delphi extra bits.
 
  Here's a couple of samples of doing Outlook Automation in Delphi; I don't
  know Delphi myself -- these are from Paul Qualls, just pasted directly
  in here exactly as sent, to avoid any risks of me breaking things by
  summarising.
 
  1. Early binding using Variants.
 
  uses comobj;
 
  procedure CreateAnOutlookEmail;
  var
    OA , 
    NS , 
    MI , // MailItem
    FO ,
    MyUserProperty : variant ;
  begin
 
    OA := CreateOleObject('Outlook.Application') ;
    NS := OA.GetNameSpace('MAPI') ;
 

    // IDispatch(MI) := FO.Items.Add('IPM.Note');
 
    MI := OA.CreateItem(0) ;
 
    MI.To := 'user@domain.com' ;
    MI.Subject := 'Outlook EMail from Delphi' ;
    MI.Body := 'Bla bla bla' ;
    //  uncomment the next line if you need to add an attachment
      MI.Attachments.Add('c:\foo.txt', emptyparam, emptyparam, emptyparam) ; 
    MI.Send ;
  end;
 

  2. Late Binding.  A little more complex.
 
  In Delphi, Import the typelib from Outlook by choosing Project>>Import 
  Type Library then choose the Outlook library.  Mine is "Microsoft Outlook 
  98 Object Model (Outlook 8.0) " After the import, you can now use 
  "Outlook_TLB" in your uses clause to Access EVERYthing in the Outlook 
  object model.  Note that it also imports Office and MSForms typelibs for 
  you to because Outlook's object model has dependencies on them.  Now you 
  are ready to use the following code.  This method is better than variants 
  because it gives you type checking and code completion.
 
  procedure SendMoreEmailFromDelphi;
  var
    OA : _DApplication ;
    NS : NameSpace ;
    MI : MailItem ;
  begin
    OA := CoApplication.Create ;
    NS := OA.GetNamespace('MAPI') ;
    NS.Logon('myProfile' , 'myPassword' , false , false ) ;
    MI := OA.CreateItem(olMailItem) as _DMailItem;
    MI.Recipients.Add('user@domain.com') ;
    MI.Subject := 'Mail From Delphi' ;
    MI.Body := 'Here is the body of the message' ;
    MI.Send ;
  end;


