copyright (c) 2001 Ajit Jadhav
All rights reserved. See detailed notice in Win32Error.h
========================================================

CWin32Error Example Usages:
========================== 

// Example 1: Simplified Exception Handling For Win32 API Errors
//            This was my main purpose in writing this class.
//            --------------------------------------------------

void MyFunction( void ) throw CWin32Error see client below
{
    if( ! SomeWin32API() ) 
    {
        // ::GetLastError() and ::FormatMessage() 
        // automatically get called during construction.
        // Catch by value or by ref--the code stays the same.
        // Smart copying means you can rethrow the object by 
        // value as many times as you like!
        
        throw CWin32Error(); 
    }
}

void ClientToMyFunction( void )
{
    try
    {
        MyFunction();
    }
    catch( CWin32Error e ) catching by value is OK (smart copying)
    {
        // Note: Automatic conversion to const TCHAR* type.

        ::OutputDebugTrace( e ); 
    }
}


// Example 2: "Vanilla" usage (No Exception Handling)
//            ---------------------------------------
// This function returns a CWin32Error object. Smart copy
// means you can return objects even during normal 
// (non-exception-related) execution, without having to
// take undue performance hit.

CWin32Error MyFunction( void ) 
{
    if( ! SomeWin32API() )
    {
        // Constructor gets last error and keeps the text 
        // of the error message ready.

        CWin32Error e; 

        // Don't have to call a member function even in 
        // MFC trace macro [i.e. no e.c_str() or (const char*) e]

        TRACE( "%s\n", e );

        return e;
    }
    // In Win32 API, the '0' value corresponds to the 
    // error string: "Operation completed successfully"
    // The error string is automatically taken from the OS 
    // in the returned CWin32Error object.

    return 0; ctor taking unsigned int called here
}


// Example 3:  Simplest: Neither exception-handling nor returning 
//             errors. Just a help for getting the message-strings
//             formatted from the OS.
//             --------------------------------------------------

void MyFunction( void ) 
{
    if( ! SomeWin32API() )
    {
        // If you want to retrieve the error code yourself...

        DWORD dwErr = ::GetLastError();

        // ...perhaps for some check on the code like this...

        if( AlertUser( dwErr ) )
        {
            // This form of CWin32Error ctor does NOT call 
            // ::GetLastError().

            CWin32Error e = dwErr; 
            
            // CWin32Error supplies const char* conversion

            AfxMessageBox( e );
        }
        // Else, forget prompting the user. 
        // Just return from the function...

        return;
    }
    // other code ...
}

Technical Notes for CWin32Error:
===============================

On-Stack- Vs. On-Heap-Instantiation:
-----------------------------------
This class was designed so that error objects can be freely created
on the stack and returned by value across exception frames/blocks.

Creating objects of this class dynamically (i.e on the heap)
offers no particular advantage. Usually, people tend to 
reuse such heap-allocated objects via pointers. Heap is not harmful 
by itself, but there are object reuse issues, as given below.

Reusing the same instance (object) at runtime.
---------------------------------------------
(i) You have to remember to call CWin32Error::ReGetLastError() 
(ii) You have to provide thread-protection in multi-threaded
apps--the single global object may grab error code from place in 
another thread. 

Of course, if you do not *reuse* the same instance, then it's 
perfectly OK to create CWin32Error objects on the heap.

Remember not to delete [] Description() return value
----------------------------------------------------
- The only reason I didn't return an MFC CString or an STL string or 
wstring object is because I didn't want to create dependencies on
other libraries right in this small utility class. 
- On the minus side of this decision is exposing the internal buffer 
(even if as a const). 
- On the plus side, you can use this class intact in almost any
kind of Win32 development--whether in performance-critical sockets
apps; or in ATL COM components; or in console app using STL; or
in a database project using some third-party ODBC library, or in 
the AppWizard generated MFC MDI App.

Suggestions for improvements to the class
=========================================
- Enhancements/checks for handling Value-collision of error codes:
    - MAPI errors vs Win32
    - Win32 vs custom MC-dll
- Provide support for ::FormatMessage() arguments:
    - Formatting messages from strings.
    - Inserts and argument arrays.
- Using a custom message (MC-compiled) dll for messages. 
    - Use its instance module handle to format messages. 
    - Add/Alter member functions suitably.
    Caution:
        - Who loads the dll? Manages its in-proc-time?
        - Who sets the thread error number? When?
