October 1999
Figure 1   Two Workarounds

// If compiled with the Visual C++ 6.0 default /EHsc, synchronous exception 
// handling and assume extern C functions never throw exceptions, this 
// program will crash. To make it work, you need to compile with /EHa, 
// asynchronous exception handling.

#include "stdafx.h"

class CSEHError
{
public :
    CSEHError ( void )
    {
        m_uiErrCode = 0 ;
    }

    CSEHError ( unsigned int u )
    {
        m_uiErrCode = u ;
    }

    ~CSEHError ( void )
    {
    }

    unsigned int m_uiErrCode ;
} ;

void TransFunc ( unsigned int u , EXCEPTION_POINTERS * pEP )
{
    printf ( "In TransFunc\n" ) ;

    throw CSEHError ( u ) ;
}

void GrungyFunc ( char * p )
{

#ifdef INSTREAMTHROW
    if ( NULL == p )
    {
        throw CSEHError ( 0 ) ;
    }
#endif

    *p = 'p' ;
    printf("This should never be seen!\n");
}

#ifdef NO_OPTIMIZATION
#pragma optimize("g",off)
#endif
void DoBadThings ( void )
{
    try
    {
        GrungyFunc ( (char*)0x1 ) ;
    }
    catch ( CSEHError e )
    {
        printf ( "Got an exception! -> 0x%08X\n" , e.m_uiErrCode ) ;
    }

}
#ifdef NO_OPTIMIZATION
#pragma optimize("g",on)
#endif

int main(int argc, char* argv[])
{
    _set_se_translator ( TransFunc ) ;
    DoBadThings ( ) ;
    return 0;
}

Figure 2   DebugCoGetThreadingModel


/*----------------------------------------------------------------------
John Robbins - Microsoft Systems Journal Bugslayer Column - October '99
----------------------------------------------------------------------*/
#include "stdafx.h"

#define OLE_APT_MASK    0x080
#define OLE_FREE_MASK   0x140

/*----------------------------------------------------------------------
FUNCTION:   DebugCoGetThreadingModel
DISCUSSION: Returns the COM threading model for the current thread.
PARAMETERS: None.
RETURNS:
    COINIT_APARTMENTTHREADED - The thread was initialized with the
                               apartment threading model.
    COINIT_MULTITHREADED     - The thread was initialized with the
                               free threading model.
    0xFF                     - The thread was not initialized for COM.
----------------------------------------------------------------------*/
COINIT DebugCoGetThreadingModel ( void )
{
    DWORD dwOLETLS ;

    // Get the OLE thread structure out of the TEB block.

    // Get the TEB.
    __asm MOV EAX , FS:018h
    // Get the COM TLS structure from its offset.
    __asm MOV EAX , [EAX + 0F80h]
    __asm MOV dwOLETLS , EAX

    // If the value is zero, OLE has not been initialized.
    if ( 0 == dwOLETLS )
    {
        return ( (COINIT)0xFF ) ;
    }

    COINIT coRet = (COINIT)0xFF ;
    __try
    {

        // Get the threading model flag, which is 0xC bytes into the
        // structure.
        DWORD dwFlags = *(LPDWORD)((dwOLETLS + 0xC)) ;

        if ( OLE_APT_MASK == ( dwFlags & OLE_APT_MASK ) )
        {
            coRet = COINIT_APARTMENTTHREADED ;
        }
        if ( OLE_FREE_MASK == ( dwFlags & OLE_FREE_MASK ) )
        {
            coRet = COINIT_MULTITHREADED ;
        }
    }
    __except ( EXCEPTION_EXECUTE_HANDLER )
    {
        coRet = (COINIT)0xFF ;
    }
    return ( coRet ) ;
}

Figure 3   MapDLL.cpp


// MapDLL.cpp : Defines the entry point for the DLL application.

#include "stdafx.h"
#include "MapDLL.h"

BOOL APIENTRY DllMain( HANDLE /*hModule*/, 
                       DWORD  ul_reason_for_call, 
                       LPVOID /*lpReserved*/ )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

MAPDLL_API int MapDLLFunction ( void ) 
{
    printf ( "Hello from MapDLLFunction!\n" ) ;
    return ( 0x42 ) ;
}

static void InternalStaticFunction ( void )
{
    printf ( "Hello from InternalStaticFunction\n" ) ;
}

MAPDLL_API char * MapDLLHappyFunc ( char * p ) 
{
    InternalStaticFunction ( ) ;
    printf ( "Whoops, a crash is about to occur!\n" ) ;
    *p = 'c' ;
    return ( p ) ;
}

Figure 4   MAP File of MapDLL


MapDLL

 Timestamp is 3755e4de (Wed Jun 02 22:13:50 1999)

 Preferred load address is 03900000

 Start         Length     Name                   Class
 0001:00000000 00001421H .text                   CODE
 0002:00000000 0000012cH .rdata                  DATA
 0002:00000130 00000193H .edata                  DATA
 0003:00000000 00000104H .CRT$XCA                DATA
 0003:00000104 00000104H .CRT$XCZ                DATA
 0003:00000208 00000104H .CRT$XIA                DATA
 0003:0000030c 00000104H .CRT$XIZ                DATA
 0003:00000410 00000176H .data                   DATA
 0003:00000588 00000030H .bss                    DATA
 0004:00000000 00000014H .idata$2                DATA
 0004:00000014 00000014H .idata$3                DATA
 0004:00000028 00000050H .idata$4                DATA
 0004:00000078 00000050H .idata$5                DATA
 0004:000000c8 00000179H .idata$6                DATA

  Address         Publics by Value              Rva+Base     Lib:Object

 0001:00000030       _DllMain@12                03901030 f   MapDLL.obj
 0001:0000004c       ?MapDLLFunction@@YAHXZ     0390104c f   MapDLL.obj
 0001:00000076       ?MapDLLHappyFunc@@YAPADPAD@Z 03901076 f   MapDLL.obj
 0001:000000f6       _printf                    039010f6 f   MSVCRTD:MSVCRTD.dll
 0001:000000fc       __chkesp                   039010fc f   MSVCRTD:MSVCRTD.dll
 0001:00000110       __CRT_INIT@12              03901110 f   MSVCRTD:crtdll.obj
 0001:00000220       __DllMainCRTStartup@12     03901220 f   MSVCRTD:crtdll.obj
 0001:00000314       __free_dbg                 03901314 f   MSVCRTD:MSVCRTD.dll
 0001:0000031a       __initterm                 0390131a f   MSVCRTD:MSVCRTD.dll
 0001:00000320       __onexit                   03901320 f   MSVCRTD:atonexit.obj
 0001:00000360       _atexit                    03901360 f   MSVCRTD:atonexit.obj
 0001:00000378       __malloc_dbg               03901378 f   MSVCRTD:MSVCRTD.dll
 0001:0000037e       ___dllonexit               0390137e f   MSVCRTD:MSVCRTD.dll
 0002:0000001c       ??_C@_08JKC@crtdll?4c?$AA@ 0390301c     MSVCRTD:crtdll.obj
 0003:00000000       ___xc_a                    03904000     MSVCRTD:cinitexe.obj
 0003:00000104       ___xc_z                    03904104     MSVCRTD:cinitexe.obj
 0003:00000208       ___xi_a                    03904208     MSVCRTD:cinitexe.obj
 0003:0000030c       ___xi_z                    0390430c     MSVCRTD:cinitexe.obj
 0003:0000058c       __adjust_fdiv              0390458c     <common>
 0003:00000598       ___onexitend               03904598     <common>
 0003:000005a8       ___onexitbegin             039045a8     <common>
 0003:000005ac       __pRawDllMain              039045ac     <common>
 0004:00000000       __IMPORT_DESCRIPTOR_MSVCRTD 03905000    MSVCRTD:MSVCRTD.dll
 0004:00000014       __NULL_IMPORT_DESCRIPTOR   03905014     MSVCRTD:MSVCRTD.dll
 0004:00000078       __imp___malloc_dbg         03905078     MSVCRTD:MSVCRTD.dll
 0004:0000007c       __imp___chkesp             0390507c     MSVCRTD:MSVCRTD.dll
 0004:00000080       __imp___free_dbg           03905080     MSVCRTD:MSVCRTD.dll
 0004:00000084       __imp___initterm           03905084     MSVCRTD:MSVCRTD.dll
 0004:00000088       __imp__printf              03905088     MSVCRTD:MSVCRTD.dll
 0004:0000008c       __imp___adjust_fdiv        0390508c     MSVCRTD:MSVCRTD.dll
 0004:00000090       __imp____dllonexit         03905090     MSVCRTD:MSVCRTD.dll
 0004:00000094       __imp___onexit             03905094     MSVCRTD:MSVCRTD.dll
 0004:00000098       \177MSVCRTD_NULL_THUNK_DATA 03905098     MSVCRTD:MSVCRTD.dll

 entry point at        0001:00000220


Line numbers for .\Debug\MapDLL.obj(D:\Dev\Column\October99\SourceCode\MapFile\MapDLL\MapDLL.cpp) segment .text

    10 0001:00000030    12 0001:0000003b    19 0001:00000041    20 0001:00000046
    24 0001:0000004c    25 0001:00000050    26 0001:00000067    27 0001:0000006c
    35 0001:00000076    36 0001:0000007a    37 0001:0000007f    38 0001:00000096
    39 0001:0000009c    40 0001:0000009f    30 0001:000000a9    31 0001:000000ad
    32 0001:000000c4

Line numbers for g:\vc\LIB\MSVCRTD.lib(atonexit.c) segment .text

    84 0001:00000320    89 0001:00000324    98 0001:0000035b   103 0001:00000360
   104 0001:00000363   105 0001:00000376

Line numbers for g:\vc\LIB\MSVCRTD.lib(crtdll.c) segment .text

   135 0001:00000110   140 0001:00000114   141 0001:0000011a   142 0001:00000123
   143 0001:00000130   147 0001:00000132   156 0001:00000139   164 0001:00000147
   170 0001:0000014d   175 0001:00000175   177 0001:0000017c   179 0001:00000187
   184 0001:00000193   189 0001:000001a5   192 0001:000001b4   219 0001:000001bc
   220 0001:000001c5   222 0001:000001cd   227 0001:000001e1   228 0001:000001e9
   236 0001:000001ee   238 0001:00000202   242 0001:0000020c   243 0001:00000211
   251 0001:00000220   252 0001:00000224   258 0001:0000022b   259 0001:0000023a
   261 0001:00000241   263 0001:0000024d   264 0001:00000256   266 0001:0000026b
   267 0001:00000271   269 0001:00000285   270 0001:0000028b   273 0001:0000028f
   276 0001:000002a3   284 0001:000002af   287 0001:000002be   289 0001:000002ca
   290 0001:000002df   292 0001:000002e6   293 0001:000002f5   296 0001:0000030a
   297 0001:0000030d

 Exports

  ordinal    name

        1    ?MapDLLFunction@@YAHXZ (int __cdecl MapDLLFunction(void))
        2    ?MapDLLHappyFunc@@YAPADPAD@Z (char * __cdecl MapDLLHappyFunc(char *))