Changeset 21999


Ignore:
Timestamp:
Apr 18, 2012, 10:46:37 PM (13 years ago)
Author:
dmik
Message:

kernel32: Make SEH work in OS/2 context.

See #82 for details.

Location:
trunk
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/excpt.h

    r21636 r21999  
    4343
    4444struct ___seh_EXCEPTION_FRAME;
    45 typedef int (*__seh_PEXCEPTION_HANDLER)(PEXCEPTION_RECORD,
    46                                         struct ___seh_EXCEPTION_FRAME *,
    47                                         PCONTEXT, PVOID);
     45
     46#ifdef ODIN_FORCE_WIN32_TIB
     47
     48typedef int (*__seh_PEXCEPTION_HANDLER_WIN32)(PEXCEPTION_RECORD,
     49                                              struct ___seh_EXCEPTION_FRAME *,
     50                                              PCONTEXT, PVOID);
    4851
    4952#pragma pack(1)
     
    5255{
    5356    /* + 0 */ struct ___seh_EXCEPTION_FRAME *pPrev;
    54     /* + 4 */ __seh_PEXCEPTION_HANDLER pHandler;
     57    /* + 4 */ __seh_PEXCEPTION_HANDLER_WIN32 pHandler;
    5558    /* + 8 */ void *pFilterCallback;
    5659    /* +12 */ void *pHandlerCallback;
     
    7275#pragma pack()
    7376
    74 extern int __seh_handler(PEXCEPTION_RECORD pRec,
     77extern int __seh_handler_win32(PEXCEPTION_RECORD pRec,
     78                               struct ___seh_EXCEPTION_FRAME *pFrame,
     79                               PCONTEXT pContext, PVOID pVoid);
     80
     81#else /* ODIN_FORCE_WIN32_TIB */
     82
     83typedef int (*__seh_PEXCEPTION_HANDLER)(PVOID,
     84                                        struct ___seh_EXCEPTION_FRAME *,
     85                                        PVOID, PVOID);
     86
     87#pragma pack(1)
     88
     89typedef struct ___seh_EXCEPTION_FRAME
     90{
     91    /* + 0 */ struct ___seh_EXCEPTION_FRAME *pPrev;
     92    /* + 4 */ __seh_PEXCEPTION_HANDLER pHandler;
     93    /* + 8 */ void *pFilterCallback;
     94    /* +12 */ void *pHandlerCallback;
     95    /* +16 */ void *pHandlerContext;
     96    /* +20 */ int filterResult;
     97    /* +24 */ DWORD EBX;
     98    /* +28 */ DWORD ESI;
     99    /* +32 */ DWORD EDI;
     100    /* +36 */ DWORD EBP;
     101    /* +40 */ DWORD ESP;
     102    /* +44 */ EXCEPTION_POINTERS Pointers;
     103    /* +52 */ int state;
     104}
     105__seh_EXCEPTION_FRAME;
     106
     107#pragma pack()
     108
     109extern int __seh_handler(PVOID pRec,
    75110                         struct ___seh_EXCEPTION_FRAME *pFrame,
    76                          PCONTEXT pContext, PVOID pVoid);
     111                         PVOID pContext, PVOID pVoid);
     112
     113#endif /* ODIN_FORCE_WIN32_TIB */
    77114
    78115#define _exception_code() (__seh_frame.Pointers.ExceptionRecord->ExceptionCode)
     
    85122#define GetExceptionInformation (PEXCEPTION_POINTERS)_exception_info
    86123
     124#ifdef ODIN_FORCE_WIN32_TIB
     125
    87126#define __try \
    88127    volatile __seh_EXCEPTION_FRAME __seh_frame;                                \
    89     __seh_frame.pHandler = __seh_handler;                                      \
     128    __seh_frame.pHandler = __seh_handler_win32;                                \
    90129    __seh_frame.Pointers.ExceptionRecord = NULL;                               \
    91130    __seh_frame.Pointers.ContextRecord = NULL;                                 \
     
    201240            continue;
    202241
     242#else /* ODIN_FORCE_WIN32_TIB */
     243
     244#define __try \
     245    volatile __seh_EXCEPTION_FRAME __seh_frame;                                \
     246    __seh_frame.pHandler = __seh_handler;                                      \
     247    __seh_frame.Pointers.ExceptionRecord = NULL;                               \
     248    __seh_frame.Pointers.ContextRecord = NULL;                                 \
     249    __seh_frame.state = 0;                                                     \
     250    /* install OS/2 exception handler (note: EDX is in clobber too since it    \
     251     * may carry any value when we jump back to pFilterCallback from the       \
     252     * handler */                                                              \
     253    __asm__ ("leal %0, %%ecx; "                                                \
     254             "pushl %%fs; "                                                    \
     255             "pushl $Dos32TIB; "                                               \
     256             "popl %%fs; "                                                     \
     257             "movl %%fs:0, %%eax; "                                            \
     258             "movl %%eax, 0(%%ecx); "                                          \
     259             "movl $0f, 8(%%ecx); "                                            \
     260             "movl %%ebx, 24(%%ecx); "                                         \
     261             "movl %%esi, 28(%%ecx); "                                         \
     262             "movl %%edi, 32(%%ecx); "                                         \
     263             "movl %%ebp, 36(%%ecx); "                                         \
     264             "movl %%esp, 40(%%ecx); "                                         \
     265             "movl %%ecx, %%fs:0; "                                            \
     266             "popl %%fs; "                                                     \
     267                                                                               \
     268             "\n0: /* pFilterCallback */ \n"                                   \
     269                                                                               \
     270             : : "m" (__seh_frame)                                             \
     271             : "%eax", "%ecx", "%edx");                                        \
     272    for (; __seh_frame.state <= 3; ++__seh_frame.state)                        \
     273        if (__seh_frame.state == 0)                                            \
     274        {                                                                      \
     275            {
     276
     277#define __except(filter_expr) \
     278            }                                                                  \
     279            /* cause the next state to be 3 */                                 \
     280            __seh_frame.state = 2;                                             \
     281        }                                                                      \
     282        else if (__seh_frame.state == 1) {                                     \
     283            /* execption caught, call filter expression */                     \
     284            __seh_frame.filterResult = (filter_expr);                          \
     285            __asm__("leal %0, %%ebx; jmp *%1"                                  \
     286                    : : "m"(__seh_frame), "m"(__seh_frame.pHandlerCallback)    \
     287                    : "%ebx");                                                 \
     288        }                                                                      \
     289        else if (__seh_frame.state == 3)                                       \
     290            /* remove exception handler */                                     \
     291            __asm__ ("leal %0, %%ecx; "                                        \
     292                     "pushl %%fs; "                                            \
     293                     "pushl $Dos32TIB; "                                       \
     294                     "popl %%fs; "                                             \
     295                     "movl 0(%%ecx), %%eax; "                                  \
     296                     "movl %%eax, %%fs:0; "                                    \
     297                     "popl %%fs; "                                             \
     298                     : : "m"(__seh_frame)                                      \
     299                     : "%eax", "%ecx");                                        \
     300        else /* __seh_frame.state == 2 -> execute except block */
     301
     302#define __finally \
     303            }                                                                  \
     304            /* cause the next state to be 2 */                                 \
     305            __seh_frame.state = 1;                                             \
     306        }                                                                      \
     307        else if (__seh_frame.state == 1) {                                     \
     308            /* execption caught, handle and proceed to the filally block */    \
     309            __seh_frame.filterResult = EXCEPTION_EXECUTE_HANDLER;              \
     310            __asm__("leal %0, %%ebx; jmp *%1"                                  \
     311                    : : "m"(__seh_frame), "m"(__seh_frame.pHandlerCallback)    \
     312                    : "%ebx");                                                 \
     313        }                                                                      \
     314        else if (__seh_frame.state == 3)                                       \
     315            /* remove exception handler */                                     \
     316            __asm__ ("leal %0, %%ecx; "                                        \
     317                     "pushl %%fs; "                                            \
     318                     "pushl $Dos32TIB; "                                       \
     319                     "popl %%fs; "                                             \
     320                     "movl 0(%%ecx), %%eax; "                                  \
     321                     "movl %%eax, %%fs:0; "                                    \
     322                     "popl %%fs; "                                             \
     323                     : : "m"(__seh_frame)                                      \
     324                     : "%eax", "%ecx");                                        \
     325        else /* __seh_frame.state == 2 -> execute finally block */
     326
     327#define __leave \
     328            /* cause the next state to be 2 */                                 \
     329            __seh_frame.state = 1;                                             \
     330            continue;
     331
     332#endif /* ODIN_FORCE_WIN32_TIB */
     333
    203334#else /* defined(__GNUC__) */
    204335
  • trunk/include/odinlx.h

    r21941 r21999  
    6767
    6868//******************************************************************************
    69 //Enable SEH (structured exception handling) support. This call is necessary
    70 //for the __try/__except statement to work correctly. Must be called before
    71 // RegisterLxDll()/RegisterLxExe().
     69//Makes FS register point to the Win32 thread information block. For Win32
     70//binaries, this is set automatically but for OS/2 binaries it must be set by
     71//hand when ODIN_FORCE_WIN32_TIB is defined in order for SEH (structured
     72//exception handling) to work properly. Must be called before RegisterLxDll()/
     73//RegisterLxExe().
    7274//******************************************************************************
    73 VOID WIN32API EnableSEH();
     75VOID WIN32API ForceWin32TIB();
    7476
    7577#ifdef __cplusplus
  • trunk/include/wprocess.h

    r21941 r21999  
    6262extern BOOL fSwitchTIBSel; // TRUE  -> switch TIB selectors
    6363                           // FALSE -> don't
    64 extern BOOL fSEHEnabled;   // TRUE  -> SEH support enabled
     64extern BOOL fForceWin32TIB;// TRUE  -> SEH support enabled
    6565                           // FALSE -> not enabled
    6666extern BOOL fExitProcess;
  • trunk/src/Odin32API/odindll.cpp

    r21384 r21999  
    8787
    8888         // Uncomment this to enable proper __try/__except support:
    89          //EnableSEH();
     89#ifdef ODIN_FORCE_WIN32_TIB
     90         ForceWin32TIB();
     91#endif
    9092         dllHandle = RegisterLxDll(hModule, LibMain, (PVOID)&_Resource_PEResTab);
    9193         if(dllHandle == 0)
  • trunk/src/Odin32API/odinexe.cpp

    r21384 r21999  
    2727int main(int argc, char *argv[])
    2828{
    29   // Uncomment this to enable proper __try/__except support:
    30   //EnableSEH();
     29#ifdef ODIN_FORCE_WIN32_TIB
     30  // Needed for proper __try/__except support:
     31  ForceWin32TIB();
     32#endif
    3133  RegisterLxExe(WinMain, (PVOID)&_Resource_PEResTab);
    3234}
  • trunk/src/kernel32/exceptions.cpp

    r21980 r21999  
    120120                             PCONTEXTRECORD pCtxRec, PVOID p, PSZ szTrapDump);
    121121
    122 int __cdecl __seh_handler(PWINEXCEPTION_RECORD pRec,
    123                           PWINEXCEPTION_FRAME pFrame,
    124                           PCONTEXTRECORD pContext, PVOID pVoid);
    125 
    126 PWINEXCEPTION_FRAME __cdecl __seh_get_prev_frame(PWINEXCEPTION_FRAME pFrame);
     122int __cdecl __seh_handler(PVOID pRec, PVOID pFrame,
     123                          PVOID pContext, PVOID pVoid);
     124
     125int __cdecl __seh_handler_win32(PWINEXCEPTION_RECORD pRec,
     126                                PWINEXCEPTION_FRAME pFrame,
     127                                PCONTEXTRECORD pContext, PVOID pVoid);
     128
     129PWINEXCEPTION_FRAME __cdecl __seh_get_prev_frame_win32(PWINEXCEPTION_FRAME pFrame);
    127130
    128131#ifdef DEBUG
     
    363366    while( (pFrame != NULL) && ((ULONG)((ULONG)pFrame & 0xFFFFF000) != 0xFFFFF000) )
    364367    {
    365         pPrevFrame = __seh_get_prev_frame(pFrame);
     368        pPrevFrame = __seh_get_prev_frame_win32(pFrame);
    366369
    367370        dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X",
     
    518521  while (((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) && (frame != pEndFrame))
    519522  {
    520         prevFrame = __seh_get_prev_frame(frame);
     523        prevFrame = __seh_get_prev_frame_win32(frame);
    521524
    522525        /* Check frame address */
     
    590593        dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame,
    591594                 ((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) ?
    592                  __seh_get_prev_frame(frame) : (void*)0xFFFFFFFF));
     595                 __seh_get_prev_frame_win32(frame) : (void*)0xFFFFFFFF));
    593596  }
    594597
     
    12421245                                           PVOID                        p)
    12431246{
     1247    // we need special processing when reused from ___seh_handler
     1248    BOOL fSEH = pERegRec->ExceptionHandler == (_ERR *)__seh_handler;
     1249
    12441250#ifdef DEBUG
    12451251    //SvL: Check if exception inside debug fprintf -> if so, clear lock so
     
    12791285        if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
    12801286        {
    1281             dprintf(("KERNEL32: OS2ExceptionHandler: EH_EXIT_UNWIND, "
    1282                      "unwinding all the Win32 exception chain"));
     1287            dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): EH_EXIT_UNWIND, "
     1288                     "unwinding all the Win32 exception chain", fSEH));
    12831289            RtlUnwind(NULL, 0, 0, 0);
    12841290        }
    12851291        else
    12861292        {
    1287             dprintf(("KERNEL32: OS2ExceptionHandler: EH_UNWINDING, "
    1288                      "unwinding the Win32 exception chain up to 0x%p", pERegRec));
     1293            dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): EH_UNWINDING, "
     1294                     "unwinding the Win32 exception chain up to 0x%p", fSEH, pERegRec));
    12891295
    12901296            // find a Win32 exception frame closest to the OS/2 one (pERegRec)
     
    12951301            while (frame != NULL && ((ULONG)frame)!= 0xFFFFFFFF &&
    12961302                   ((ULONG)frame) <= ((ULONG)pERegRec))
    1297                 frame = __seh_get_prev_frame(frame);
     1303                frame = __seh_get_prev_frame_win32(frame);
    12981304            if (((ULONG)frame) == 0xFFFFFFFF)
    12991305                frame = NULL;
     
    13161322    case XCPT_FLOAT_UNDERFLOW:
    13171323        dprintfException(pERepRec, pERegRec, pCtxRec, p);
    1318         dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
    1319         if((!fIsOS2Image || fSEHEnabled) && !fExitProcess)  //Only for real win32 apps or if SEH enabled
    1320         {
    1321             if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
     1324        dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): FPU exception\n", fSEH));
     1325        if((!fIsOS2Image || fForceWin32TIB || fSEH) && !fExitProcess)  //Only for real win32 apps or when forced
     1326        {
     1327            if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p, fSEH) == FALSE)
    13221328            {
    13231329                pCtxRec->ctx_env[0] |= 0x1F;
     
    13281334            else
    13291335            {
    1330                 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
     1336                dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): fix and continue\n", fSEH));
    13311337                goto continueexecution;
    13321338            }
    13331339        }
    1334         dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
     1340        dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): continue search\n", fSEH));
    13351341        goto continuesearch;
    13361342
     
    14391445        DosQueryMem((PVOID) pERepRec->ExceptionInfo[1],
    14401446                    &offset, &accessflag);
    1441         dprintf(("KERNEL32: OS2ExceptionHandler: failed address info 0x%X size 0x%X. flag %X\n",
    1442                  pERepRec->ExceptionInfo[1], offset, accessflag));
     1447        dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): failed address info 0x%X size 0x%X. flag %X\n",
     1448                 fSEH, pERepRec->ExceptionInfo[1], offset, accessflag));
    14431449        /* check for valid address */
    14441450        if (!pERepRec->ExceptionInfo[1] ||
     
    14541460                             offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
    14551461                  accessflag | PAG_WRITE | PAG_COMMIT);
    1456         dprintf(("KERNEL32: OS2ExceptionHandler: commiting 0x%X size 0x%X. RC: %i\n",
    1457                  pERepRec->ExceptionInfo[1] & 0xFFFFF000,
     1462        dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): commiting 0x%X size 0x%X. RC: %i\n",
     1463                 fSEH, pERepRec->ExceptionInfo[1] & 0xFFFFF000,
    14581464                 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
    14591465                           rc));
     
    15081514
    15091515                //NOTE: This will not work properly in case multiple threads execute this code
    1510                 dprintf(("Changing thread registers (SetThreadContext)!!"));
     1516                dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): Changing thread registers (SetThreadContext)!!", fSEH));
    15111517
    15121518                if(teb->o.odin.context.ContextFlags & WINCONTEXT_CONTROL) {
     
    15831589#endif
    15841590
    1585         if((!fIsOS2Image || fSEHEnabled) && !fExitProcess)  //Only for real win32 apps or if SEH enabled
    1586         {
    1587             if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
     1591        if((!fIsOS2Image || fForceWin32TIB || fSEH) && !fExitProcess)  //Only for real win32 apps or when forced
     1592        {
     1593            if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p, fSEH) == TRUE)
    15881594            {
    1589                 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
     1595                dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): fix and continue\n", fSEH));
    15901596                goto continueexecution;
    15911597            }
    15921598            else
    15931599            {
    1594                 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
     1600                dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): continue search\n", fSEH));
    15951601                goto continuesearch;
    15961602            }
     
    16051611                if(rc == NO_ERROR)
    16061612                {
    1607                     dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill thread"));
     1613                    dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): Continue and kill thread", fSEH));
    16081614
    16091615                    pCtxRec->ctx_RegEip = (pTIB->tib_ptib2->tib2_ultid != 1) ? (ULONG)KillWin32Thread : (ULONG)KillWin32Process;
     
    16201626        logException(pERepRec, pERegRec, pCtxRec, p);
    16211627
    1622         dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
     1628        dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): Continue and kill\n", fSEH));
    16231629
    16241630        pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
     
    16481654
    16491655        // Make sure we detect a stack overflow condition before the system does
    1650         if ((!fIsOS2Image || fSEHEnabled) && //Only for real win32 apps or if SEH enabled
     1656        if ((!fIsOS2Image || fForceWin32TIB || fSEH) && //Only for real win32 apps or when forced
    16511657            pERepRec->ExceptionInfo[1]  >= stackbottom &&
    16521658            pERepRec->ExceptionInfo[1]  <  stacktop
     
    17041710                    recoutofstack.cParameters   = 0;
    17051711
    1706                     if(OSLibDispatchException(&recoutofstack, pERegRec, pCtxRec, p) == TRUE)
     1712                    if(OSLibDispatchException(&recoutofstack, pERegRec, pCtxRec, p, fSEH) == TRUE)
    17071713                    {
    17081714                        goto continueexecution;
     
    17141720        {
    17151721            // Throw EXCEPTION_GUARD_PAGE_VIOLATION in the Win32 context
    1716             if((!fIsOS2Image || fSEHEnabled) && !fExitProcess)  //Only for real win32 apps or if SEH enabled
     1722            if((!fIsOS2Image || fForceWin32TIB || fSEH) && !fExitProcess)  //Only for real win32 apps or when forced
    17171723            {
    1718                 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
     1724                if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p, fSEH) == TRUE)
    17191725                {
    17201726                    goto continueexecution;
     
    19611967    while ((pFrame != NULL) && ((ULONG)pFrame != 0xFFFFFFFF))
    19621968    {
    1963         PWINEXCEPTION_FRAME pPrevFrame = __seh_get_prev_frame(pFrame);
     1969        PWINEXCEPTION_FRAME pPrevFrame = __seh_get_prev_frame_win32(pFrame);
    19641970        dprintf(("  Record at %08X, Prev at %08X, handler at %08X%s",
    19651971                 pFrame, pPrevFrame, pFrame->Handler,
    1966                  pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler ?
    1967                  " (SEH)" : ""));
     1972                 pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler ? " (SEH)" :
     1973                 pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler_win32 ? " (SEH Win32)" : ""));
    19681974        if (pFrame == pPrevFrame)
    19691975        {
  • trunk/src/kernel32/exceptutil.asm

    r21916 r21999  
    151151OS2ExceptionHandler endp
    152152
     153
     154        PUBLIC OSLibDispatchException
     155        EXTRN  OSLibDispatchExceptionWin32:NEAR
     156        EXTRN  ___seh_handler_filter:NEAR
     157
     158; BOOL APIENTRY OSLibDispatchException(PEXCEPTIONREPORTRECORD pReportRec,
     159;                                      PEXCEPTIONREGISTRATIONRECORD pRegistrationRec,
     160;                                      PCONTEXTRECORD pContextRec, PVOID p,
     161;                                      BOOL fSEH);
     162OSLibDispatchException proc near
     163        cmp dword ptr [esp + 20], 0 ; fSEH == FALSE?
     164        jz  OSLibDispatchExceptionWin32
     165        jmp ___seh_handler_filter
     166OSLibDispatchException endp
     167
     168
    153169        PUBLIC _QueryExceptionChain
    154170
  • trunk/src/kernel32/kernel32.def

    r21996 r21999  
    13581358    RtlUniform                 = "_RtlUniform@4"                  @3531 NONAME
    13591359
    1360     ___seh_handler                                                @3600 NONAME
    1361     "_EnableSEH@0"                                                @3601 NONAME
     1360    ___seh_handler_win32                                          @3600 NONAME
     1361    "_ForceWin32TIB@0"                                            @3601 NONAME
     1362    ___seh_handler                                                @3602 NONAME
  • trunk/src/kernel32/kernel32dbg.def

    r21996 r21999  
    13571357    RtlUniform                 = "_RtlUniform@4"                  @3531 NONAME
    13581358
    1359     ___seh_handler                                                @3600 NONAME
    1360     "_EnableSEH@0"                                                @3601 NONAME
     1359    ___seh_handler_win32                                          @3600 NONAME
     1360    "_ForceWin32TIB@0"                                            @3601 NONAME
     1361    ___seh_handler                                                @3602 NONAME
  • trunk/src/kernel32/oslibexcept.cpp

    r21980 r21999  
    1616#include <win32type.h>
    1717#include <misc.h>
    18 #include "oslibexcept.h"
    1918#include <exceptions.h>
    2019#include <wprocess.h>
    2120
     21#include "oslibexcept.h"
     22
    2223#define DBG_LOCALLOG    DBG_oslibexcept
    2324#include "dbglocal.h"
    2425
    25 //******************************************************************************
    26 //Dispatches OS/2 exception to win32 handler
    27 //Returns: TRUE, win32 exception handler returned continue execution
    28 //         FALSE, otherwise
    29 //******************************************************************************
    30 BOOL APIENTRY OSLibDispatchException(PEXCEPTIONREPORTRECORD pReportRec,
    31                                      PEXCEPTIONREGISTRATIONRECORD pRegistrationRec,
    32                                      PCONTEXTRECORD pContextRec, PVOID p)
     26/**
     27 * Converts the OS/2 exception information to the Win32 exception information.
     28 *
     29 * Returns TRUE on succes and FALSE otherwise.
     30 */
     31BOOL APIENTRY OSLibConvertExceptionInfo(PEXCEPTIONREPORTRECORD pReportRec,
     32                                        PCONTEXTRECORD pContextRec,
     33                                        PWINEXCEPTION_RECORD pWinReportRec,
     34                                        PWINCONTEXT pWinContextRec,
     35                                        TEB *pWinTEB)
    3336{
    34  WINEXCEPTION_RECORD winreportrec;
    35  WINCONTEXT          wincontextrec;
    36  ULONG               rc;
    37 
    38   memset(&winreportrec, 0, sizeof(winreportrec));
    39   memcpy(&winreportrec, pReportRec, sizeof(*pReportRec));
    40 
    41   switch(pReportRec->ExceptionNum) {
    42   case XCPT_FLOAT_DENORMAL_OPERAND:
    43         winreportrec.ExceptionCode = EXCEPTION_FLT_DENORMAL_OPERAND;
    44         break;
    45   case XCPT_FLOAT_DIVIDE_BY_ZERO:
    46         winreportrec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
    47         break;
    48   case XCPT_FLOAT_INEXACT_RESULT:
    49         winreportrec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
    50         break;
    51   case XCPT_FLOAT_INVALID_OPERATION:
    52         winreportrec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
    53         break;
    54   case XCPT_FLOAT_OVERFLOW:
    55         winreportrec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
    56         break;
    57   case XCPT_FLOAT_STACK_CHECK:
    58         winreportrec.ExceptionCode = EXCEPTION_FLT_STACK_CHECK;
    59         break;
    60   case XCPT_FLOAT_UNDERFLOW:
    61         winreportrec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
    62         break;
    63   case XCPT_INTEGER_DIVIDE_BY_ZERO:
    64         winreportrec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
    65         break;
    66   case XCPT_INTEGER_OVERFLOW:
    67         winreportrec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
    68         break;
    69   case XCPT_PRIVILEGED_INSTRUCTION:
    70         winreportrec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
    71         break;
    72   case XCPT_BREAKPOINT:
    73         winreportrec.ExceptionCode = EXCEPTION_BREAKPOINT;
    74         break;
    75   case XCPT_SINGLE_STEP:
    76         winreportrec.ExceptionCode = EXCEPTION_SINGLE_STEP;
    77         break;
    78   case XCPT_ARRAY_BOUNDS_EXCEEDED:
    79         winreportrec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
    80         break;
    81   case XCPT_DATATYPE_MISALIGNMENT:
    82         winreportrec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
    83         break;
    84   case XCPT_ILLEGAL_INSTRUCTION:
    85         winreportrec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
    86         break;
    87   case XCPT_INVALID_LOCK_SEQUENCE:
    88         winreportrec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
    89         break;
    90   case XCPT_GUARD_PAGE_VIOLATION:
    91         winreportrec.ExceptionCode = EXCEPTION_GUARD_PAGE;
    92         break;
    93   case XCPT_UNABLE_TO_GROW_STACK:
    94         winreportrec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
    95         break;
    96   case XCPT_IN_PAGE_ERROR:
    97         winreportrec.ExceptionCode = EXCEPTION_IN_PAGE_ERROR;
    98         break;
    99   case XCPT_ACCESS_VIOLATION:
    100         winreportrec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
    101         break;
    102   default: //no other exceptions should be dispatched to win32 apps
     37    memset(pWinReportRec, 0, sizeof(*pWinReportRec));
     38    memcpy(pWinReportRec, pReportRec, sizeof(*pReportRec));
     39
     40    switch (pReportRec->ExceptionNum)
     41    {
     42    case XCPT_FLOAT_DENORMAL_OPERAND:
     43        pWinReportRec->ExceptionCode = EXCEPTION_FLT_DENORMAL_OPERAND;
     44        break;
     45    case XCPT_FLOAT_DIVIDE_BY_ZERO:
     46        pWinReportRec->ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
     47        break;
     48    case XCPT_FLOAT_INEXACT_RESULT:
     49        pWinReportRec->ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
     50        break;
     51    case XCPT_FLOAT_INVALID_OPERATION:
     52        pWinReportRec->ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
     53        break;
     54    case XCPT_FLOAT_OVERFLOW:
     55        pWinReportRec->ExceptionCode = EXCEPTION_FLT_OVERFLOW;
     56        break;
     57    case XCPT_FLOAT_STACK_CHECK:
     58        pWinReportRec->ExceptionCode = EXCEPTION_FLT_STACK_CHECK;
     59        break;
     60    case XCPT_FLOAT_UNDERFLOW:
     61        pWinReportRec->ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
     62        break;
     63    case XCPT_INTEGER_DIVIDE_BY_ZERO:
     64        pWinReportRec->ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
     65        break;
     66    case XCPT_INTEGER_OVERFLOW:
     67        pWinReportRec->ExceptionCode = EXCEPTION_INT_OVERFLOW;
     68        break;
     69    case XCPT_PRIVILEGED_INSTRUCTION:
     70        pWinReportRec->ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
     71        break;
     72    case XCPT_BREAKPOINT:
     73        pWinReportRec->ExceptionCode = EXCEPTION_BREAKPOINT;
     74        break;
     75    case XCPT_SINGLE_STEP:
     76        pWinReportRec->ExceptionCode = EXCEPTION_SINGLE_STEP;
     77        break;
     78    case XCPT_ARRAY_BOUNDS_EXCEEDED:
     79        pWinReportRec->ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
     80        break;
     81    case XCPT_DATATYPE_MISALIGNMENT:
     82        pWinReportRec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
     83        break;
     84    case XCPT_ILLEGAL_INSTRUCTION:
     85        pWinReportRec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
     86        break;
     87    case XCPT_INVALID_LOCK_SEQUENCE:
     88        pWinReportRec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
     89        break;
     90    case XCPT_GUARD_PAGE_VIOLATION:
     91        pWinReportRec->ExceptionCode = EXCEPTION_GUARD_PAGE;
     92        break;
     93    case XCPT_UNABLE_TO_GROW_STACK:
     94        pWinReportRec->ExceptionCode = EXCEPTION_STACK_OVERFLOW;
     95        break;
     96    case XCPT_IN_PAGE_ERROR:
     97        pWinReportRec->ExceptionCode = EXCEPTION_IN_PAGE_ERROR;
     98        break;
     99    case XCPT_ACCESS_VIOLATION:
     100        pWinReportRec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
     101        break;
     102    default: // no other exceptions should be dispatched to win32 apps
    103103        return FALSE;
    104   }
    105   //TODO:
    106   //According to the Wine folks the flags are the same in OS/2 and win32
    107   //Let's assume for now the rest is identical as well
    108 
    109   //copy context record info
    110   memset(&wincontextrec, 0, sizeof(wincontextrec));
    111   if(pContextRec->ContextFlags & CONTEXT_CONTROL) {
    112         wincontextrec.ContextFlags |= WINCONTEXT_CONTROL;
    113         wincontextrec.Ebp     = pContextRec->ctx_RegEbp;
    114         wincontextrec.Eip     = pContextRec->ctx_RegEip;
    115         wincontextrec.SegCs   = pContextRec->ctx_SegCs;
    116         wincontextrec.EFlags  = pContextRec->ctx_EFlags;
    117         wincontextrec.Esp     = pContextRec->ctx_RegEsp;
    118         wincontextrec.SegSs   = pContextRec->ctx_SegSs;
    119   }
    120   if(pContextRec->ContextFlags & CONTEXT_INTEGER) {
    121         wincontextrec.ContextFlags |= WINCONTEXT_INTEGER;
    122         wincontextrec.Edi     = pContextRec->ctx_RegEdi;
    123         wincontextrec.Esi     = pContextRec->ctx_RegEsi;
    124         wincontextrec.Ebx     = pContextRec->ctx_RegEbx;
    125         wincontextrec.Edx     = pContextRec->ctx_RegEdx;
    126         wincontextrec.Ecx     = pContextRec->ctx_RegEcx;
    127         wincontextrec.Eax     = pContextRec->ctx_RegEax;
    128   }
    129 
    130   TEB *winteb = GetThreadTEB();
    131 
    132   if(pContextRec->ContextFlags & CONTEXT_SEGMENTS) {
    133         wincontextrec.ContextFlags |= WINCONTEXT_SEGMENTS;
    134         wincontextrec.SegGs   = pContextRec->ctx_SegGs;
    135 //   This resets FS to 0x150B - we DON'T want that!!
    136 //      wincontextrec.SegFs   = pContextRec->ctx_SegFs;
    137         wincontextrec.SegFs   = winteb->teb_sel;
    138         wincontextrec.SegEs   = pContextRec->ctx_SegEs;
    139         wincontextrec.SegDs   = pContextRec->ctx_SegDs;
    140   }
    141   if(pContextRec->ContextFlags & CONTEXT_FLOATING_POINT) {
    142         wincontextrec.ContextFlags |= WINCONTEXT_FLOATING_POINT;
     104    }
     105
     106    // TODO:
     107    // According to the Wine folks the flags are the same in OS/2 and win32
     108    // Let's assume for now the rest is identical as well
     109
     110    // copy context record info
     111    memset(pWinContextRec, 0, sizeof(*pWinContextRec));
     112    if (pContextRec->ContextFlags & CONTEXT_CONTROL)
     113    {
     114        pWinContextRec->ContextFlags |= WINCONTEXT_CONTROL;
     115        pWinContextRec->Ebp     = pContextRec->ctx_RegEbp;
     116        pWinContextRec->Eip     = pContextRec->ctx_RegEip;
     117        pWinContextRec->SegCs   = pContextRec->ctx_SegCs;
     118        pWinContextRec->EFlags  = pContextRec->ctx_EFlags;
     119        pWinContextRec->Esp     = pContextRec->ctx_RegEsp;
     120        pWinContextRec->SegSs   = pContextRec->ctx_SegSs;
     121    }
     122    if (pContextRec->ContextFlags & CONTEXT_INTEGER)
     123    {
     124        pWinContextRec->ContextFlags |= WINCONTEXT_INTEGER;
     125        pWinContextRec->Edi     = pContextRec->ctx_RegEdi;
     126        pWinContextRec->Esi     = pContextRec->ctx_RegEsi;
     127        pWinContextRec->Ebx     = pContextRec->ctx_RegEbx;
     128        pWinContextRec->Edx     = pContextRec->ctx_RegEdx;
     129        pWinContextRec->Ecx     = pContextRec->ctx_RegEcx;
     130        pWinContextRec->Eax     = pContextRec->ctx_RegEax;
     131    }
     132
     133    if (pContextRec->ContextFlags & CONTEXT_SEGMENTS)
     134    {
     135        pWinContextRec->ContextFlags |= WINCONTEXT_SEGMENTS;
     136        pWinContextRec->SegGs   = pContextRec->ctx_SegGs;
     137        // set Wn32 TEB if we run in switch FS mode
     138        if (pWinTEB)
     139            pWinContextRec->SegFs   = pWinTEB->teb_sel;
     140        else
     141            pWinContextRec->SegFs   = pContextRec->ctx_SegFs;
     142        pWinContextRec->SegEs   = pContextRec->ctx_SegEs;
     143        pWinContextRec->SegDs   = pContextRec->ctx_SegDs;
     144    }
     145
     146    if (pContextRec->ContextFlags & CONTEXT_FLOATING_POINT)
     147    {
     148        pWinContextRec->ContextFlags |= WINCONTEXT_FLOATING_POINT;
    143149        //TODO: First 7 dwords the same?
    144         memcpy(&wincontextrec.FloatSave, pContextRec->ctx_env, sizeof(pContextRec->ctx_env));
    145         memcpy(&wincontextrec.FloatSave.RegisterArea, pContextRec->ctx_stack, sizeof(pContextRec->ctx_stack));
    146   }
    147   //It doesn't seem correct if we dispatch real exceptions to win32 apps
    148   //Some just call RtlUnwind and continue as if they were processing an
    149   //exception thrown by C++ code. (instead of real OS exception)
    150 #if 1
    151   // We need to reset FS to its original (Win32) value, otherwise we'll likely
    152   // fuck up the Win32 exception handlers. They could end up using the wrong
    153   // exception chain if they access FS:[0] directly.
    154   DWORD oldsel = SetReturnFS(winteb->teb_sel);
    155 
    156   switch(pReportRec->ExceptionNum) {
    157   case XCPT_FLOAT_DENORMAL_OPERAND:
    158   case XCPT_FLOAT_DIVIDE_BY_ZERO:
    159   case XCPT_FLOAT_INEXACT_RESULT:
    160   case XCPT_FLOAT_INVALID_OPERATION:
    161   case XCPT_FLOAT_OVERFLOW:
    162   case XCPT_FLOAT_STACK_CHECK:
    163   case XCPT_FLOAT_UNDERFLOW:
    164         rc = RtlDispatchException(&winreportrec, &wincontextrec);
    165         break;
    166 
    167   case XCPT_ACCESS_VIOLATION:
    168         rc = RtlDispatchException(&winreportrec, &wincontextrec);
    169         break;
    170 
    171   case XCPT_ILLEGAL_INSTRUCTION:
    172   case XCPT_PRIVILEGED_INSTRUCTION:
    173   case XCPT_INTEGER_DIVIDE_BY_ZERO:
    174   case XCPT_UNABLE_TO_GROW_STACK:
    175   case XCPT_GUARD_PAGE_VIOLATION:
     150        memcpy(&pWinContextRec->FloatSave,
     151               pContextRec->ctx_env, sizeof(pContextRec->ctx_env));
     152        memcpy(&pWinContextRec->FloatSave.RegisterArea,
     153               pContextRec->ctx_stack, sizeof(pContextRec->ctx_stack));
     154    }
     155
     156    return TRUE;
     157}
     158
     159/**
     160 * Converts the Win32 exception handler result to the OS/2 exception handler
     161 * result.
     162 *
     163 * Returns TRUE if the OS/2 exception handler result should be
     164 * XCPT_CONTINUE_EXECUTION and FALSE otherwise.
     165 */
     166BOOL APIENTRY OSLibConvertExceptionResult(ULONG rc,
     167                                          PWINCONTEXT pWinContextRec,
     168                                          PCONTEXTRECORD pContextRec)
     169{
     170    if (rc != ExceptionContinueExecution)
     171    {
     172        dprintf(("Win32 exception handler returned %x", rc));
     173        return FALSE;
     174    }
     175
     176    dprintf(("Win32 exception handler returned ExceptionContinueExecution"));
     177
     178    if (pWinContextRec->ContextFlags & WINCONTEXT_CONTROL)
     179    {
     180        pContextRec->ctx_RegEbp = pWinContextRec->Ebp;
     181        pContextRec->ctx_RegEip = pWinContextRec->Eip;
     182        pContextRec->ctx_SegCs  = pWinContextRec->SegCs;
     183        pContextRec->ctx_EFlags = pWinContextRec->EFlags;
     184        pContextRec->ctx_RegEsp = pWinContextRec->Esp;
     185        pContextRec->ctx_SegSs  = pWinContextRec->SegSs;
     186    }
     187
     188    if (pWinContextRec->ContextFlags & WINCONTEXT_INTEGER)
     189    {
     190        pContextRec->ctx_RegEdi = pWinContextRec->Edi;
     191        pContextRec->ctx_RegEsi = pWinContextRec->Esi;
     192        pContextRec->ctx_RegEbx = pWinContextRec->Ebx;
     193        pContextRec->ctx_RegEdx = pWinContextRec->Edx;
     194        pContextRec->ctx_RegEcx = pWinContextRec->Ecx;
     195        pContextRec->ctx_RegEax = pWinContextRec->Eax;
     196    }
     197
     198#if 0
     199    // This is not a good idea
     200    if (pWinContextRec->ContextFlags & WINCONTEXT_SEGMENTS)
     201    {
     202        pContextRec->ctx_SegGs = pWinContextRec->SegGs;
     203        pContextRec->ctx_SegFs = pWinContextRec->SegFs;
     204        pContextRec->ctx_SegEs = pWinContextRec->SegEs;
     205        pContextRec->ctx_SegDs = pWinContextRec->SegDs;
     206    }
     207#endif
     208
     209    if (pWinContextRec->ContextFlags & WINCONTEXT_FLOATING_POINT)
     210    {
     211        //TODO: First 7 dwords the same?
     212        memcpy(pContextRec->ctx_env, &pWinContextRec->FloatSave,
     213               sizeof(pContextRec->ctx_env));
     214        memcpy(pContextRec->ctx_stack, &pWinContextRec->FloatSave.RegisterArea,
     215               sizeof(pContextRec->ctx_stack));
     216    }
     217
     218    if (pContextRec->ContextFlags & CONTEXT_CONTROL)         /* check flags */
     219        dprintf(("   SS:ESP=%04x:%08x EFLAGS=%08x\n",
     220                 pContextRec->ctx_SegSs,
     221                 pContextRec->ctx_RegEsp,
     222                 pContextRec->ctx_EFlags));
     223    dprintf(("   CS:EIP=%04x:%08x EBP   =%08x\n",
     224             pContextRec->ctx_SegCs,
     225             pContextRec->ctx_RegEip,
     226             pContextRec->ctx_RegEbp));
     227
     228    if (pContextRec->ContextFlags & CONTEXT_INTEGER)         /* check flags */
     229        dprintf(("   EAX=%08x EBX=%08x ESI=%08x\n",
     230                 pContextRec->ctx_RegEax,
     231                 pContextRec->ctx_RegEbx,
     232                 pContextRec->ctx_RegEsi));
     233    dprintf(("   ECX=%08x EDX=%08x EDI=%08x\n",
     234             pContextRec->ctx_RegEcx,
     235             pContextRec->ctx_RegEdx,
     236             pContextRec->ctx_RegEdi));
     237
     238    if (pContextRec->ContextFlags & CONTEXT_SEGMENTS)        /* check flags */
     239        dprintf(("   DS=%04x     ES=%08x"
     240                 "   FS=%04x     GS=%04x\n",
     241                 pContextRec->ctx_SegDs,
     242                 pContextRec->ctx_SegEs,
     243                 pContextRec->ctx_SegFs,
     244                 pContextRec->ctx_SegGs));
     245
     246    if (pContextRec->ContextFlags & CONTEXT_FLOATING_POINT)  /* check flags */
     247    {
     248        ULONG ulCounter;                 /* temporary local counter for fp stack */
     249
     250        dprintf(("   Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
     251                 pContextRec->ctx_env[0],
     252                 pContextRec->ctx_env[1],
     253                 pContextRec->ctx_env[2],
     254                 pContextRec->ctx_env[3]));
     255
     256        dprintf(("   Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
     257                 pContextRec->ctx_env[4],
     258                 pContextRec->ctx_env[5],
     259                 pContextRec->ctx_env[6]));
     260
     261        for (ulCounter = 0;
     262             ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
     263             ulCounter ++)
     264            dprintf(("   FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
     265                     ulCounter,
     266                     pContextRec->ctx_stack[0].losig,
     267                     pContextRec->ctx_stack[0].hisig,
     268                     pContextRec->ctx_stack[0].signexp));
     269    }
     270
     271    return TRUE;
     272}
     273
     274/**
     275 * Dispatches OS/2 exception to win32 handler.
     276 *
     277 * Returns TRUE if the Win32 exception handler returned
     278 * ExceptionContinueExecution and FALSE otherwise.
     279 */
     280BOOL APIENTRY OSLibDispatchExceptionWin32(PEXCEPTIONREPORTRECORD pReportRec,
     281                                          PEXCEPTIONREGISTRATIONRECORD pRegistrationRec,
     282                                          PCONTEXTRECORD pContextRec, PVOID p)
     283{
     284    WINEXCEPTION_RECORD winReportRec;
     285    WINCONTEXT          winContextRec;
     286
     287    ULONG rc;
     288
     289    TEB *pWinTEB = GetThreadTEB();
     290
     291    OSLibConvertExceptionInfo(pReportRec, pContextRec,
     292                              &winReportRec, &winContextRec, pWinTEB);
     293
     294    // It doesn't seem correct if we dispatch real exceptions to win32 apps
     295    // Some just call RtlUnwind and continue as if they were processing an
     296    // exception thrown by C++ code. (instead of real OS exception)
     297
     298    // We need to reset FS to its original (Win32) value, otherwise we'll likely
     299    // fuck up the Win32 exception handlers. They could end up using the wrong
     300    // exception chain if they access FS:[0] directly.
     301    DWORD oldsel = SetReturnFS(pWinTEB->teb_sel);
     302
     303    switch(pReportRec->ExceptionNum)
     304    {
     305    case XCPT_FLOAT_DENORMAL_OPERAND:
     306    case XCPT_FLOAT_DIVIDE_BY_ZERO:
     307    case XCPT_FLOAT_INEXACT_RESULT:
     308    case XCPT_FLOAT_INVALID_OPERATION:
     309    case XCPT_FLOAT_OVERFLOW:
     310    case XCPT_FLOAT_STACK_CHECK:
     311    case XCPT_FLOAT_UNDERFLOW:
     312        rc = RtlDispatchException(&winReportRec, &winContextRec);
     313        break;
     314
     315    case XCPT_ACCESS_VIOLATION:
     316        rc = RtlDispatchException(&winReportRec, &winContextRec);
     317        break;
     318
     319    case XCPT_ILLEGAL_INSTRUCTION:
     320    case XCPT_PRIVILEGED_INSTRUCTION:
     321    case XCPT_INTEGER_DIVIDE_BY_ZERO:
     322    case XCPT_UNABLE_TO_GROW_STACK:
     323    case XCPT_GUARD_PAGE_VIOLATION:
    176324#ifndef DEBUG
    177   case XCPT_BREAKPOINT:
     325    case XCPT_BREAKPOINT:
    178326#endif
    179         rc = RtlDispatchException(&winreportrec, &wincontextrec);
     327        rc = RtlDispatchException(&winReportRec, &winContextRec);
    180328        break;
    181329
    182330#ifdef DEBUG
    183   case XCPT_BREAKPOINT:
     331    case XCPT_BREAKPOINT:
    184332#endif
    185   case XCPT_INTEGER_OVERFLOW:
    186   case XCPT_SINGLE_STEP:
    187   case XCPT_ARRAY_BOUNDS_EXCEEDED:
    188   case XCPT_DATATYPE_MISALIGNMENT:
    189   case XCPT_INVALID_LOCK_SEQUENCE:
    190   case XCPT_IN_PAGE_ERROR:
    191   default:
    192         SetFS(oldsel);  //restore FS
     333    case XCPT_INTEGER_OVERFLOW:
     334    case XCPT_SINGLE_STEP:
     335    case XCPT_ARRAY_BOUNDS_EXCEEDED:
     336    case XCPT_DATATYPE_MISALIGNMENT:
     337    case XCPT_INVALID_LOCK_SEQUENCE:
     338    case XCPT_IN_PAGE_ERROR:
     339    default:
     340        SetFS(oldsel);  //restore FS
    193341        return FALSE; //let's not dispatch those for now
    194   }
    195   SetFS(oldsel);        //restore FS
    196 
    197   if(rc == ExceptionContinueExecution) {
    198         dprintf(("Win32 exception handler returned ExceptionContinueExecution"));
    199         if(wincontextrec.ContextFlags & WINCONTEXT_CONTROL) {
    200                 pContextRec->ctx_RegEbp = wincontextrec.Ebp;
    201                 pContextRec->ctx_RegEip = wincontextrec.Eip;
    202                 pContextRec->ctx_SegCs  = wincontextrec.SegCs;
    203                 pContextRec->ctx_EFlags = wincontextrec.EFlags;
    204                 pContextRec->ctx_RegEsp = wincontextrec.Esp;
    205                 pContextRec->ctx_SegSs  = wincontextrec.SegSs;
    206         }
    207         if(wincontextrec.ContextFlags & WINCONTEXT_INTEGER) {
    208                 pContextRec->ctx_RegEdi = wincontextrec.Edi;
    209                 pContextRec->ctx_RegEsi = wincontextrec.Esi;
    210                 pContextRec->ctx_RegEbx = wincontextrec.Ebx;
    211                 pContextRec->ctx_RegEdx = wincontextrec.Edx;
    212                 pContextRec->ctx_RegEcx = wincontextrec.Ecx;
    213                 pContextRec->ctx_RegEax = wincontextrec.Eax;
    214         }
    215 #if 0
    216         //This is not a good idea
    217         if(wincontextrec.ContextFlags & WINCONTEXT_SEGMENTS) {
    218                 pContextRec->ctx_SegGs = wincontextrec.SegGs;
    219                 pContextRec->ctx_SegFs = wincontextrec.SegFs;
    220                 pContextRec->ctx_SegEs = wincontextrec.SegEs;
    221                 pContextRec->ctx_SegDs = wincontextrec.SegDs;
    222         }
    223 #endif
    224         if(wincontextrec.ContextFlags & WINCONTEXT_FLOATING_POINT) {
    225                 //TODO: First 7 dwords the same?
    226                 memcpy(pContextRec->ctx_env, &wincontextrec.FloatSave, sizeof(pContextRec->ctx_env));
    227                 memcpy(pContextRec->ctx_stack, &wincontextrec.FloatSave.RegisterArea, sizeof(pContextRec->ctx_stack));
    228         }
    229         if (pContextRec->ContextFlags & CONTEXT_CONTROL)         /* check flags */
    230                 dprintf(("   SS:ESP=%04x:%08x EFLAGS=%08x\n",
    231                              pContextRec->ctx_SegSs,
    232                              pContextRec->ctx_RegEsp,
    233                              pContextRec->ctx_EFlags));
    234                 dprintf(("   CS:EIP=%04x:%08x EBP   =%08x\n",
    235                              pContextRec->ctx_SegCs,
    236                              pContextRec->ctx_RegEip,
    237                              pContextRec->ctx_RegEbp));
    238 
    239         if (pContextRec->ContextFlags & CONTEXT_INTEGER)         /* check flags */
    240                     dprintf(("   EAX=%08x EBX=%08x ESI=%08x\n",
    241                              pContextRec->ctx_RegEax,
    242                              pContextRec->ctx_RegEbx,
    243                              pContextRec->ctx_RegEsi));
    244                     dprintf(("   ECX=%08x EDX=%08x EDI=%08x\n",
    245                              pContextRec->ctx_RegEcx,
    246                              pContextRec->ctx_RegEdx,
    247                              pContextRec->ctx_RegEdi));
    248 
    249         if (pContextRec->ContextFlags & CONTEXT_SEGMENTS)        /* check flags */
    250                     dprintf(("   DS=%04x     ES=%08x"
    251                              "   FS=%04x     GS=%04x\n",
    252                               pContextRec->ctx_SegDs,
    253                               pContextRec->ctx_SegEs,
    254                               pContextRec->ctx_SegFs,
    255                               pContextRec->ctx_SegGs));
    256 
    257         if (pContextRec->ContextFlags & CONTEXT_FLOATING_POINT)  /* check flags */
    258         {
    259             ULONG ulCounter;                 /* temporary local counter for fp stack */
    260 
    261                 dprintf(("   Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
    262                              pContextRec->ctx_env[0],
    263                              pContextRec->ctx_env[1],
    264                              pContextRec->ctx_env[2],
    265                              pContextRec->ctx_env[3]));
    266 
    267                 dprintf(("   Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
    268                              pContextRec->ctx_env[4],
    269                              pContextRec->ctx_env[5],
    270                              pContextRec->ctx_env[6]));
    271 
    272                 for (ulCounter = 0;
    273                      ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
    274                      ulCounter ++)
    275                       dprintf(("   FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
    276                                ulCounter,
    277                                pContextRec->ctx_stack[0].losig,
    278                                pContextRec->ctx_stack[0].hisig,
    279                                pContextRec->ctx_stack[0].signexp));
    280         }
    281 
    282         return TRUE;
    283   }
    284   dprintf(("Win32 exception handler returned %x", rc));
    285 #endif
    286   return FALSE;
     342    }
     343
     344    SetFS(oldsel);      //restore FS
     345
     346    return OSLibConvertExceptionResult(rc, &winContextRec, pContextRec);
    287347}
    288 //******************************************************************************
    289 //******************************************************************************
  • trunk/src/kernel32/oslibexcept.h

    r9617 r21999  
    99#define __OSLIBEXCEPT_H__
    1010
    11 #ifdef __cplusplus
    12 extern "C" {
    13 #endif
     11BOOL APIENTRY OSLibConvertExceptionInfo(PEXCEPTIONREPORTRECORD pReportRec,
     12                                        PCONTEXTRECORD pContextRec,
     13                                        PWINEXCEPTION_RECORD pWinReportRec,
     14                                        PWINCONTEXT pWinContextRec,
     15                                        TEB *pWinTEB);
    1416
    15 //******************************************************************************
    16 //Dispatches OS/2 exception to win32 handler
    17 //Returns: TRUE, win32 exception handler returned continue execution
    18 //         FALSE, otherwise
    19 //******************************************************************************
     17BOOL APIENTRY OSLibConvertExceptionResult(ULONG rc,
     18                                          PWINCONTEXT pWinContextRec,
     19                                          PCONTEXTRECORD pContextRec);
     20
    2021BOOL APIENTRY OSLibDispatchException(PEXCEPTIONREPORTRECORD pReportRec,
    2122                                     PEXCEPTIONREGISTRATIONRECORD pRegistrationRec,
    22                                      PCONTEXTRECORD pContextRec, PVOID p);
    23 
    24 #ifdef __cplusplus
    25 }
    26 #endif
     23                                     PCONTEXTRECORD pContextRec, PVOID p,
     24                                     BOOL fSEH);
    2725
    2826#endif
  • trunk/src/kernel32/seh/sehutil.s

    r21916 r21999  
    88
    99.global ___seh_handler
    10 .global ___seh_get_prev_frame
     10.global ___seh_handler_filter
     11.global ___seh_handler_win32
     12.global ___seh_get_prev_frame_win32
     13
     14#define sizeof_WINEXCEPTION_RECORD 80
     15#define sizeof_WINCONTEXT          296
    1116
    1217/*
    1318 * extern "C"
    14  * int __seh_handler(PEXCEPTION_RECORD pRec,
     19 * int __seh_handler(PEXCEPTIONREPORTRECORD pRec,
    1520 *                   struct ___seh_EXCEPTION_FRAME *pFrame,
    16  *                   PCONTEXT pContext, PVOID)
    17  *
    18  * Win32 structured exception handler that implements the __try/__except
    19  * functionality for GCC.
     21 *                   PCONTEXTRECORD pContext, PVOID)
     22 *
     23 * OS/2 exception handler that implements the __try/__except
     24 * functionality for GCC in non-ODIN_FORCE_WIN32_TIB mode.
    2025 *
    2126 * NOTE: This is a heavily platform specific stuff. The code depends on the
     
    2631 * the stack.
    2732 */
    28 
    2933___seh_handler:
    3034
    31     pushl %ebp
    32     movl %esp, %ebp
     35    /* call the common handler to do the job */
     36    jmp OS2ExceptionHandler2ndLevel
     37
     38/*
     39 * extern "C"
     40 * BOOL __seh_handler_filter(PEXCEPTIONREPORTRECORD pRec,
     41 *                           struct ___seh_EXCEPTION_FRAME *pFrame,
     42 *                           PCONTEXTRECORD pContext)
     43 *
     44 * Calls the filter expression of the __try/__except block
     45 * in non-ODIN_FORCE_WIN32_TIB mode.
     46 *
     47 * Return TRUE if the filter asks to continue execution and FALSE
     48 * otherwise. Note that if the filter chooses to execute the __except block,
     49 * this function does not return.
     50 *
     51 * NOTE: This is a heavily platform specific stuff. The code depends on the
     52 * struct ___seh_EXCEPTION_FRAME layout so be very careful and keep both
     53 * in sync!
     54 *
     55 * __cdecl: EAX/ECX/EDX are not preserved, result in EAX/EDX, caller cleans up
     56 * the stack.
     57 */
     58
     59___seh_handler_filter:
    3360
    3461    /*
     
    3663     * 12(%ebp) - pFrame
    3764     * 16(%ebp) - pContext
    38      * 20(%ebp) - pVoid
    3965     */
     66
     67    pushl %ebp
     68    movl %esp, %ebp
    4069
    4170    /* preserve used registers */
     
    4473    pushl %esi
    4574
    46     movl %fs, %eax
    47     andl $0x0000FFFF, %eax
    48     cmpl $Dos32TIB, %eax /* Running along the OS/2 chain? */
    49     jne ___seh_handler_Win32 /* No, assume the Win32 chain */
    50 
    51     /* Note: Unwinding is disabled here since a) it is more correct to do
    52      * centralized unwinding from OS2ExceptionHandler2ndLevel() (i.e. not only
    53      * for SEH frames) and b) it crashes under SMP kernel due to stack being
    54      * corrupt by the time when unwinding happens. See comments in
    55      * OS2ExceptionHandler2ndLevel() for more details. */
    56 
    57 #if 0
    58 
    59     movl 8(%ebp), %eax
    60     movl 4(%eax), %eax /* fHandlerFlags */
    61     testl $0x02, %eax  /* EH_UNWINDING? */
    62     jne ___seh_handler_OS2_Unwind
    63 
    64     /* restore the OS/2 chain in our frame */
    65     movl 12(%ebp), %eax
    66     movl 44(%eax), %ecx /* pPrevFrameOS2 */
    67     movl %ecx, 0(%eax)  /* pPrev */
    68 
    69     xorl %eax, %eax  /* return XCPT_CONTINUE_SEARCH (0) */
    70     jmp ___seh_handler_Return
    71 
    72 ___seh_handler_OS2_Unwind:
    73 
    74     /* unwind the Win32 chain including our frame as someone's definitely
    75      * jumping outside it if we're being unwound by OS/2 */
    76     movl 12(%ebp), %eax
    77     cmpl $0, 64(%eax)                   /* Win32FS == 0? */
    78     je ___seh_handler_OS2_Unwind_End    /* Yes, we already unwound this frame */
    79 
    80     /* restore the Win32 chain in our frame */
    81     movl 60(%eax), %ebx /* pPrevFrameWin32 */
    82     movl %ebx, 0(%eax)  /* pPrev */
    83 
    84     pushl %fs
    85 
    86     pushl 64(%eax)  /* Win32FS */
    87     popl %fs
    88 
    89     pushl $0        /* DWORD (unused) */
    90     pushl $0        /* PEXCEPTION_RECORD */
    91     pushl $0        /* LPVOID (unused) */
    92     pushl %ebx      /* PEXCEPTION_FRAME */
    93     call _RtlUnwind@16 /* _stdcall, rtl, callee cleans stack */
    94 
    95     popl %fs
    96 
    97     /* restore the OS/2 chain in our frame */
    98     movl 12(%ebp), %eax
    99     movl 44(%eax), %ecx /* pPrevFrameOS2 */
    100     movl %ecx, 0(%eax)  /* pPrev */
    101 
    102 ___seh_handler_OS2_Unwind_End:
    103 
    104     xor %eax, %eax  /* return code is irrelevant for EH_UNWINDING */
    105     jmp ___seh_handler_Return
    106 
    107 #else
    108 
    109     /* restore the OS/2 chain in our frame */
    110     movl 12(%ebp), %eax
    111     movl 44(%eax), %ecx /* pPrevFrameOS2 */
    112     movl %ecx, 0(%eax)  /* pPrev */
    113 
    114     xorl %eax, %eax  /* return XCPT_CONTINUE_SEARCH (0) */
    115     jmp ___seh_handler_Return
    116 
    117 #endif
    118 
    119 ___seh_handler_Win32:
    120 
    121     /* restore the Win32 chain in our frame */
    122     movl 12(%ebp), %eax
    123     movl 60(%eax), %ecx /* pPrevFrameWin32 */
    124     movl %ecx, 0(%eax)  /* pPrev */
    125 
    126     /* skip EH_UNWINDING calls (for compatibility with MSVC) */
    127     movl 8(%ebp), %ebx
    128     movl 4(%ebx), %eax                      /* pRec->ExceptionFlags */
    129     testl $0x2, %eax                        /* EH_UNWINDING? */
    130     je ___seh_handler_Win32_NotUnwinding    /* No, continue normally */
    131 
    132     /* See the comment above */
    133 #if 0
    134     /* clear out the Win32FS field so that we will not attempt to unwind twice
    135      * (first, as a result of forced unwind from ExitProcess/ExitThread/etc and
    136      * then from the OS/2 EH_UNWINDING call of our handler) */
    137     movl 12(%ebp), %eax
    138     movl $0, 64(%eax)   /* Win32FS */
    139 #endif
    140 
    141     movl $1, %eax /* ExceptionContinueSearch */
    142     jmp ___seh_handler_Return
    143 
    144 ___seh_handler_Win32_NotUnwinding:
    145 
    14675    /* save handler's context */
    14776    pushl %ebp
     
    15382
    15483    /* get the size of the handler's stack */
    155     movl 40(%ebx), %ecx /* pFrame->pTryRegs[4] is ESP */
     84    movl 40(%ebx), %ecx /* pFrame->ESP */
    15685    subl %esp, %ecx
    15786    jle ___seh_handler_Error /* Invalid stack! */
    15887    movl %ecx, 4(%esp) /* save length */
    15988
    160     /* check that EXCEPTION_RECORD and CONTEXT are on our stack
    161      * and save their offsets in pFrame */
    162     movl 8(%ebp), %eax
    163     subl %esp, %eax
    164     jl ___seh_handler_Error /* Invalid stack! */
    165     cmpl %ecx, %eax
    166     jg ___seh_handler_Error /* Invalid stack! */
    167     movl %eax, 48(%ebx) /* pFrame->Pointers.ExceptionRecord */
    168 
    169     movl 16(%ebp), %eax
    170     subl %esp, %eax
    171     jl ___seh_handler_Error /* Invalid stack! */
    172     cmpl %ecx, %eax
    173     jg ___seh_handler_Error /* Invalid stack! */
    174     movl %eax, 52(%ebx) /* pFrame->Pointers.ContextRecord */
    175 
    17689    /* save the handler's stack on heap */
    17790    movl %ecx, %eax /* size_t */
     91    /* also reserve space for Win32 exeption info structs */
     92    addl $(sizeof_WINEXCEPTION_RECORD + sizeof_WINCONTEXT), %eax
    17893    subl $4, %esp
    17994    movl %eax, 0(%esp)
     
    188103    rep movsb
    189104
    190     /* correct Pointers offsets to point to the saved stack on heap */
     105    /* convert OS/2 exception info -> Win32 */
     106    movl 16(%ebx), %eax          /* pFrame->pHandlerContext */
     107    addl 4(%esp), %eax           /* + size of stack = ptr to WINCONTEXT */
     108    movl %eax, 48(%ebx)          /* pFrame->Pointers.ContextRecord */
     109    addl $sizeof_WINCONTEXT, %eax/* = ptr to WINEXCEPTION_RECORD */
     110    movl %eax, 44(%ebx)          /* pFrame->Pointers.ExceptionRecord */
     111    pushl $0                     /* TEB* */
     112    pushl 48(%ebx)               /* WINCONTEXT */
     113    pushl 44(%ebx)               /* WINEXCEPTION_RECORD */
     114    pushl 16(%ebp)               /* pContext */
     115    pushl 8(%ebp)                /* pRec */
     116    call OSLibConvertExceptionInfo
     117    addl $20, %esp
     118    jne ___seh_handler_CallFilter/* conversion successful? */
     119
     120    /* free heap block */
    191121    movl 16(%ebx), %eax /* pFrame->pHandlerContext */
    192     addl %eax, 48(%ebx) /* pFrame->Pointers.ExceptionRecord */
    193     addl %eax, 52(%ebx) /* pFrame->Pointers.ContextRecord */
     122    subl $4, %esp
     123    movl %eax, 0(%esp)
     124    call _free /* __cdecl (and _Optlink compatible -> EAX/EDX/ECX-in) */
     125    addl $4, %esp
     126    jmp ___seh_handler_Error /* Info conversion error! */
     127
     128___seh_handler_CallFilter:
    194129
    195130    /* restore __try/__catch context */
    196131    movl 12(%ebp), %eax
    197     movl 24(%eax), %ebx /* pFrame->pTryRegs */
    198     movl 28(%eax), %esi
    199     movl 32(%eax), %edi
    200     movl 36(%eax), %ebp
    201     movl 40(%eax), %esp
     132    movl 24(%eax), %ebx /* pFrame->EBX */
     133    movl 28(%eax), %esi /* pFrame->ESI */
     134    movl 32(%eax), %edi /* pFrame->EDI */
     135    movl 36(%eax), %ebp /* pFrame->EBP */
     136    movl 40(%eax), %esp /* pFrame->ESP */
    202137
    203138    /* jump to the filter callback */
    204     movl $1, 56(%eax) /* pFrame->state */
     139    movl $1, 52(%eax) /* pFrame->state */
    205140    jmp *8(%eax) /* pFrame->pFilterCallback */
    206141
     
    232167    cmpl $-1, %eax /* EXCEPTION_CONTINUE_EXECUTION? */
    233168    jne 1f
    234     movl $0, 56(%ebx) /* pFrame->state */
    235     movl $0, %eax /* ExceptionContinueExecution */
     169    movl $0, 52(%ebx) /* pFrame->state */
     170    //movl $-1, %eax /* XCPT_CONTINUE_EXECUTION (-1) */
     171    movl $1, %eax
    236172    jmp ___seh_handler_Return
    2371731:
    238174    /* assume EXCEPTION_CONTINUE_SEARCH (0) */
     175    xorl %eax, %eax /* return XCPT_CONTINUE_SEARCH (0) */
     176    jmp ___seh_handler_Return
     177
     178___seh_handler_Unwind:
     179
     180    /* unwind OS/2 exception chain up to ours */
     181    pushl $0        /* PEXCEPTIONREPORTRECORD */
     182    pushl $1f       /* PVOID pTargetIP */
     183    pushl 12(%ebp)  /* PEXCEPTIONREGISTRATIONRECORD */
     184    call _DosUnwindException /* _syscall, rtl, but stack is not restored! */
     1851:
     186    /* restore __try/__except context */
     187    movl 12(%ebp), %eax
     188    movl 24(%eax), %ebx
     189    movl 28(%eax), %esi
     190    movl 32(%eax), %edi
     191    movl 36(%eax), %ebp
     192    movl 40(%eax), %esp
     193
     194    /* jump to __except */
     195    movl $2, 52(%eax) /* pFrame->state */
     196    jmp *8(%eax) /* pFrame->pFilterCallback */
     197
     198___seh_handler_Error:
     199
     200    addl $8, %esp
     201    popl %ebp
     202
     203    xorl %eax, %eax  /* return XCPT_CONTINUE_SEARCH (0) */
     204
     205___seh_handler_Return:
     206
     207    popl %esi
     208    popl %edi
     209    popl %ebx
     210
     211    popl %ebp
     212    ret
     213
     214/*
     215 * extern "C"
     216 * int __seh_handler_win32(PEXCEPTION_RECORD pRec,
     217 *                         struct ___seh_EXCEPTION_FRAME *pFrame,
     218 *                         PCONTEXT pContext, PVOID)
     219 *
     220 * Win32 structured exception handler that implements the __try/__except
     221 * functionality for GCC in ODIN_FORCE_WIN32_TIB mode.
     222 *
     223 * NOTE: This is a heavily platform specific stuff. The code depends on the
     224 * struct ___seh_EXCEPTION_FRAME layout so be very careful and keep both
     225 * in sync!
     226 *
     227 * __cdecl: EAX/ECX/EDX are not preserved, result in EAX/EDX, caller cleans up
     228 * the stack.
     229 */
     230
     231___seh_handler_win32:
     232
     233    pushl %ebp
     234    movl %esp, %ebp
     235
     236    /*
     237     * 8(%ebp)  - pRec
     238     * 12(%ebp) - pFrame
     239     * 16(%ebp) - pContext
     240     * 20(%ebp) - pVoid
     241     */
     242
     243    /* preserve used registers */
     244    pushl %ebx
     245    pushl %edi
     246    pushl %esi
     247
     248    movl %fs, %eax
     249    andl $0x0000FFFF, %eax
     250    cmpl $Dos32TIB, %eax /* Running along the OS/2 chain? */
     251    jne __seh_handler_win32_Win32 /* No, assume the Win32 chain */
     252
     253    /* Note: Unwinding is disabled here since a) it is more correct to do
     254     * centralized unwinding from OS2ExceptionHandler2ndLevel() (i.e. not only
     255     * for SEH frames) and b) it crashes under SMP kernel due to stack being
     256     * corrupt by the time when unwinding happens. See comments in
     257     * OS2ExceptionHandler2ndLevel() for more details. */
     258
     259#if 0
     260
     261    movl 8(%ebp), %eax
     262    movl 4(%eax), %eax /* fHandlerFlags */
     263    testl $0x02, %eax  /* EH_UNWINDING? */
     264    jne __seh_handler_win32_OS2_Unwind
     265
     266    /* restore the OS/2 chain in our frame */
     267    movl 12(%ebp), %eax
     268    movl 44(%eax), %ecx /* pPrevFrameOS2 */
     269    movl %ecx, 0(%eax)  /* pPrev */
     270
     271    xorl %eax, %eax  /* return XCPT_CONTINUE_SEARCH (0) */
     272    jmp __seh_handler_win32_Return
     273
     274__seh_handler_win32_OS2_Unwind:
     275
     276    /* unwind the Win32 chain including our frame as someone's definitely
     277     * jumping outside it if we're being unwound by OS/2 */
     278    movl 12(%ebp), %eax
     279    cmpl $0, 64(%eax)                   /* Win32FS == 0? */
     280    je __seh_handler_win32_OS2_Unwind_End    /* Yes, we already unwound this frame */
     281
     282    /* restore the Win32 chain in our frame */
     283    movl 60(%eax), %ebx /* pPrevFrameWin32 */
     284    movl %ebx, 0(%eax)  /* pPrev */
     285
     286    pushl %fs
     287
     288    pushl 64(%eax)  /* Win32FS */
     289    popl %fs
     290
     291    pushl $0        /* DWORD (unused) */
     292    pushl $0        /* PEXCEPTION_RECORD */
     293    pushl $0        /* LPVOID (unused) */
     294    pushl %ebx      /* PEXCEPTION_FRAME */
     295    call _RtlUnwind@16 /* _stdcall, rtl, callee cleans stack */
     296
     297    popl %fs
     298
     299    /* restore the OS/2 chain in our frame */
     300    movl 12(%ebp), %eax
     301    movl 44(%eax), %ecx /* pPrevFrameOS2 */
     302    movl %ecx, 0(%eax)  /* pPrev */
     303
     304__seh_handler_win32_OS2_Unwind_End:
     305
     306    xor %eax, %eax  /* return code is irrelevant for EH_UNWINDING */
     307    jmp __seh_handler_win32_Return
     308
     309#else
     310
     311    /* restore the OS/2 chain in our frame */
     312    movl 12(%ebp), %eax
     313    movl 44(%eax), %ecx /* pPrevFrameOS2 */
     314    movl %ecx, 0(%eax)  /* pPrev */
     315
     316    xorl %eax, %eax  /* return XCPT_CONTINUE_SEARCH (0) */
     317    jmp __seh_handler_win32_Return
     318
     319#endif
     320
     321__seh_handler_win32_Win32:
     322
     323    /* restore the Win32 chain in our frame */
     324    movl 12(%ebp), %eax
     325    movl 60(%eax), %ecx /* pPrevFrameWin32 */
     326    movl %ecx, 0(%eax)  /* pPrev */
     327
     328    /* skip EH_UNWINDING calls (for compatibility with MSVC) */
     329    movl 8(%ebp), %ebx
     330    movl 4(%ebx), %eax                      /* pRec->ExceptionFlags */
     331    testl $0x2, %eax                        /* EH_UNWINDING? */
     332    je ___seh_handler_win32_Win32_NotUnwinding    /* No, continue normally */
     333
     334    /* See the comment above */
     335#if 0
     336    /* clear out the Win32FS field so that we will not attempt to unwind twice
     337     * (first, as a result of forced unwind from ExitProcess/ExitThread/etc and
     338     * then from the OS/2 EH_UNWINDING call of our handler) */
     339    movl 12(%ebp), %eax
     340    movl $0, 64(%eax)   /* Win32FS */
     341#endif
     342
    239343    movl $1, %eax /* ExceptionContinueSearch */
    240     jmp ___seh_handler_Return
    241 
    242 ___seh_handler_Unwind:
     344    jmp __seh_handler_win32_Return
     345
     346___seh_handler_win32_Win32_NotUnwinding:
     347
     348    /* save handler's context */
     349    pushl %ebp
     350    pushl $0   /* reserve space for length, must be saved right before ESP! */
     351    pushl %esp /* ESP must be saved last! */
     352
     353    movl 12(%ebp), %ebx
     354    movl $0f, 12(%ebx) /* pFrame->pHandlerCallback */
     355
     356    /* get the size of the handler's stack */
     357    movl 40(%ebx), %ecx /* pFrame->pTryRegs[4] is ESP */
     358    subl %esp, %ecx
     359    jle __seh_handler_win32_Error /* Invalid stack! */
     360    movl %ecx, 4(%esp) /* save length */
     361
     362    /* check that EXCEPTION_RECORD and CONTEXT are on our stack
     363     * and save their offsets in pFrame */
     364    movl 8(%ebp), %eax
     365    subl %esp, %eax
     366    jl __seh_handler_win32_Error /* Invalid stack! */
     367    cmpl %ecx, %eax
     368    jg __seh_handler_win32_Error /* Invalid stack! */
     369    movl %eax, 48(%ebx) /* pFrame->Pointers.ExceptionRecord */
     370
     371    movl 16(%ebp), %eax
     372    subl %esp, %eax
     373    jl __seh_handler_win32_Error /* Invalid stack! */
     374    cmpl %ecx, %eax
     375    jg __seh_handler_win32_Error /* Invalid stack! */
     376    movl %eax, 52(%ebx) /* pFrame->Pointers.ContextRecord */
     377
     378    /* save the handler's stack on heap */
     379    movl %ecx, %eax /* size_t */
     380    subl $4, %esp
     381    movl %eax, 0(%esp)
     382    call _malloc /* __cdecl (and _Optlink compatible -> EAX/EDX/ECX-in) */
     383    addl $4, %esp
     384    testl %eax, %eax
     385    je __seh_handler_win32_Error /* No memory! */
     386    movl 4(%esp), %ecx
     387    movl %eax, %edi
     388    movl %edi, 16(%ebx) /* pFrame->pHandlerContext */
     389    movl %esp, %esi
     390    rep movsb
     391
     392    /* correct Pointers offsets to point to the saved stack on heap */
     393    movl 16(%ebx), %eax /* pFrame->pHandlerContext */
     394    addl %eax, 48(%ebx) /* pFrame->Pointers.ExceptionRecord */
     395    addl %eax, 52(%ebx) /* pFrame->Pointers.ContextRecord */
     396
     397    /* restore __try/__catch context */
     398    movl 12(%ebp), %eax
     399    movl 24(%eax), %ebx /* pFrame->pTryRegs */
     400    movl 28(%eax), %esi
     401    movl 32(%eax), %edi
     402    movl 36(%eax), %ebp
     403    movl 40(%eax), %esp
     404
     405    /* jump to the filter callback */
     406    movl $1, 56(%eax) /* pFrame->state */
     407    jmp *8(%eax) /* pFrame->pFilterCallback */
     408
     4090:
     410    /* restore handler's context (we assume that the callback puts the address
     411     * of pFrame back to EBX!) */
     412    movl 16(%ebx), %esi /* pFrame->pHandlerContext */
     413    movl 0(%esi), %esp  /* restore saved ESP */
     414    movl 4(%esi), %ecx  /* saved stack length */
     415    subl $4, %esp /* correct ESP to compensate for PUSH ESP logic */
     416    movl %esp, %edi
     417    rep movsb
     418
     419    popl %esp
     420    addl $4, %esp
     421    popl %ebp
     422
     423    /* free heap block */
     424    movl 16(%ebx), %eax /* pFrame->pHandlerContext */
     425    subl $4, %esp
     426    movl %eax, 0(%esp)
     427    call _free /* __cdecl (and _Optlink compatible -> EAX/EDX/ECX-in) */
     428    addl $4, %esp
     429
     430    /* analyze filter result */
     431    movl 20(%ebx), %eax /* pFrame->filterResult */
     432    cmpl $1, %eax /* EXCEPTION_EXECUTE_HANDLER? */
     433    je __seh_handler_win32_Unwind
     434    cmpl $-1, %eax /* EXCEPTION_CONTINUE_EXECUTION? */
     435    jne 1f
     436    movl $0, 56(%ebx) /* pFrame->state */
     437    movl $0, %eax /* ExceptionContinueExecution */
     438    jmp __seh_handler_win32_Return
     4391:
     440    /* assume EXCEPTION_CONTINUE_SEARCH (0) */
     441    movl $1, %eax /* ExceptionContinueSearch */
     442    jmp __seh_handler_win32_Return
     443
     444__seh_handler_win32_Unwind:
    243445
    244446    /* unwind Win32 exception chain up to ours */
     
    282484    jmp *8(%eax) /* pFrame->pFilterCallback */
    283485
    284 ___seh_handler_Error:
     486__seh_handler_win32_Error:
    285487
    286488    addl $8, %esp
     
    289491    movl $1, %eax /* ExceptionContinueSearch */
    290492
    291 ___seh_handler_Return:
     493__seh_handler_win32_Return:
    292494
    293495    popl %esi
     
    300502/*
    301503 * extern "C"
    302  * EXCEPTION_FRAME *__seh_get_prev_frame(EXCEPTION_FRAME *pFrame)
     504 * EXCEPTION_FRAME *__seh_get_prev_frame_win32(EXCEPTION_FRAME *pFrame)
    303505 *
    304506 * Returns the previous Win32 exception frame given an existing frame.
     
    319521 */
    320522
    321 ___seh_get_prev_frame:
     523___seh_get_prev_frame_win32:
    322524
    323525    /*
     
    328530    /*leal ___seh_handler, %ecx*/
    329531    movl 4(%eax), %ecx /* pFrame->Handler */
    330     cmpl $___seh_handler, %ecx
    331     jne ___seh_get_prev_frame_Normal
     532    cmpl $___seh_handler_win32, %ecx
     533    jne ___seh_get_prev_frame_win32_Normal
    332534
    333535    movl 60(%eax), %eax /* pPrevFrameWin32 */
    334536    ret
    335537
    336 ___seh_get_prev_frame_Normal:
     538___seh_get_prev_frame_win32_Normal:
    337539
    338540    movl 0(%eax), %eax /* pFrame->Prev */
  • trunk/src/kernel32/winexelx.cpp

    r21916 r21999  
    4747 PTIB   ptib;
    4848
    49   if (!fSEHEnabled) {
     49  if (!fForceWin32TIB) {
    5050      //Signal to TEB management that we're a real OS/2 app and don't
    5151      //require setting FS to our special win32 selector
  • trunk/src/kernel32/wprocess.cpp

    r21916 r21999  
    7979BOOL    fSwitchTIBSel = TRUE;           // TRUE  -> switch TIB selectors
    8080                                        // FALSE -> don't
    81 BOOL    fSEHEnabled = FALSE;            // TRUE  -> SEH support enabled
     81BOOL    fForceWin32TIB = FALSE;         // TRUE  -> force TIB switch
    8282                                        // FALSE -> not enabled
    8383BOOL    fExitProcess = FALSE;
     
    113113//******************************************************************************
    114114//******************************************************************************
    115 VOID WIN32API EnableSEH()
    116 {
    117     if(!fSEHEnabled) {
     115VOID WIN32API ForceWin32TIB()
     116{
     117    if(!fForceWin32TIB) {
    118118        ODIN_SetTIBSwitch(TRUE);
    119         fSEHEnabled = TRUE;
     119        fForceWin32TIB = TRUE;
    120120    }
    121121    return;
     
    510510{
    511511    dprintf(("ODIN_SetTIBSwitch %d", fSwitchTIB));
    512     if (!fSEHEnabled) {
     512    if (!fForceWin32TIB) {
    513513        fSwitchTIBSel = fSwitchTIB;
    514514        if(fSwitchTIBSel) {
     
    517517        else RestoreOS2TIB();
    518518    } else {
    519         dprintf(("ODIN_SetTIBSwitch: ignored due to fSEHEnabled = TRUE"));
     519        dprintf(("ODIN_SetTIBSwitch: ignored due to fForceWin32TIB = TRUE"));
    520520    }
    521521}
  • trunk/testapp/console/file/file.c

    r21565 r21999  
    2323    _argc = argc;
    2424    _argv = argv;
    25     EnableSEH();
     25#ifdef ODIN_FORCE_WIN32_TIB
     26    ForceWin32TIB();
     27#endif
    2628    RegisterLxExe(WinMain, NULL);
    2729}
  • trunk/testapp/console/fullpath/fullpath.c

    r21631 r21999  
    2525    _argc = argc;
    2626    _argv = argv;
    27     EnableSEH();
     27#ifdef ODIN_FORCE_WIN32_TIB
     28    ForceWin32TIB();
     29#endif
    2830    RegisterLxExe(WinMain, NULL);
    2931}
  • trunk/testapp/encodings/test.c

    r21916 r21999  
    2020int main(int argc, char **argv)
    2121{
    22     EnableSEH();
     22#ifdef ODIN_FORCE_WIN32_TIB
     23    ForceWin32TIB();
     24#endif
    2325    RegisterLxExe(WinMain, NULL);
    2426}
  • trunk/testapp/exceptions/GuardPages/main.cpp

    r21982 r21999  
    149149    ///////////////////////////////////////////////////
    150150
     151#if 1
     152
    151153    printf ("\nTEST 1 (STACK)\n");
    152154
     
    154156    DWORD dwYellowZoneSize = sSysInfo.dwPageSize * 3;
    155157
    156 #if 1
    157158    if (VirtualAlloc ((LPVOID) dwStackBase, dwYellowZoneSize,
    158159                      MEM_COMMIT, PAGE_READWRITE))
     
    186187        }
    187188    }
    188 #endif
    189189
    190190    PrintMemLayout (&dwStackTop);
    191191
     192#endif
     193
    192194    ///////////////////////////////////////////////////
     195
     196#if 1
    193197
    194198    printf ("\nTEST 2 (PAGE_GUARD)\n");
     
    220224    VirtualFree (pNonStack, 0, MEM_RELEASE);
    221225
     226#endif
     227
    222228    return 0;
    223229}
     
    226232{
    227233#ifdef __WIN32OS2__
    228     EnableSEH();
     234#ifdef ODIN_FORCE_WIN32_TIB
     235    ForceWin32TIB();
     236#endif
    229237#endif
    230238
  • trunk/testapp/exceptions/seh/crash.c

    r21663 r21999  
    2424    _argc = argc;
    2525    _argv = argv;
    26     EnableSEH();
     26#ifdef ODIN_FORCE_WIN32_TIB
     27    ForceWin32TIB();
     28#endif
    2729    RegisterLxExe(WinMain, NULL);
    2830}
     
    8789void foo(int code)
    8890{
    89    __try
    90    {
    91        printf("In foo(%d)...\n", code);
     91    __try
     92    {
     93        printf("In foo(%d)...\n", code);
    9294
    93        if (code == 2)
    94        {
    95            throw_EXCEPTION_INT_DIVIDE_BY_ZERO();
    96            printf("FAILED: No exception!\n");
    97        }
    98        else
    99        {
    100            foo(code + 1);
    101        }
    102    }
    103    __except(exc_filter(exception_info()))
    104    {
    105        printf("FAILED: foo(%d) exception handled.\n", code);
    106    }
     95        if (code == 2)
     96        {
     97            throw_EXCEPTION_INT_DIVIDE_BY_ZERO();
     98            printf("FAILED: No exception!\n");
     99        }
     100        else
     101        {
     102            foo(code + 1);
     103        }
     104    }
     105    __except(exc_filter(exception_info()))
     106    {
     107        printf("FAILED: foo(%d) exception handled.\n", code);
     108    }
    107109}
    108110
     
    118120{
    119121    printf("The program should now expectedly crash "
    120            "(but NO POPUPLOG.OS2 entry!)...\n");
     122           "(and may be a NO POPUPLOG.OS2 entry)...\n");
    121123
    122124    HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
  • trunk/testapp/exceptions/seh/except.c

    r21476 r21999  
    2323    _argc = argc;
    2424    _argv = argv;
    25     EnableSEH();
     25#ifdef ODIN_FORCE_WIN32_TIB
     26    ForceWin32TIB();
     27#endif
    2628    RegisterLxExe(WinMain, NULL);
    2729}
  • trunk/testapp/exceptions/seh/finally.c

    r21449 r21999  
    2323    _argc = argc;
    2424    _argv = argv;
    25     EnableSEH();
     25#ifdef ODIN_FORCE_WIN32_TIB
     26    ForceWin32TIB();
     27#endif
    2628    RegisterLxExe(WinMain, NULL);
    2729}
  • trunk/testapp/exceptions/seh/longjmp.c

    r21662 r21999  
    2424    _argc = argc;
    2525    _argv = argv;
    26     EnableSEH();
     26#ifdef ODIN_FORCE_WIN32_TIB
     27    ForceWin32TIB();
     28#endif
    2729    RegisterLxExe(WinMain, NULL);
    2830}
  • trunk/testapp/gui/fontlist/fontlist.c

    r21539 r21999  
    2525    _argc = argc;
    2626    _argv = argv;
    27     EnableSEH();
     27#ifdef ODIN_FORCE_WIN32_TIB
     28    ForceWin32TIB();
     29#endif
    2830    RegisterLxExe(WinMain, NULL);
    2931}
  • trunk/testapp/gui/input/input.c

    r21916 r21999  
    1717int main()
    1818{
    19     EnableSEH();
     19#ifdef ODIN_FORCE_WIN32_TIB
     20    ForceWin32TIB();
     21#endif
    2022    RegisterLxExe(WinMain, NULL);
    2123    return 0;
  • trunk/testapp/gui/systray/StealthDialog.cpp

    r21603 r21999  
    2929int main(int argc, char **argv)
    3030{
    31     EnableSEH();
     31#ifdef ODIN_FORCE_WIN32_TIB
     32    ForceWin32TIB();
     33#endif
    3234    RegisterLxExe((WINMAIN)_tWinMain, (PVOID)&Resource_PEResTab);
    3335}
  • trunk/testapp/threads/threads.c

    r21916 r21999  
    5959int main(int argc, char **argv)
    6060{
    61     EnableSEH();
     61#ifdef ODIN_FORCE_WIN32_TIB
     62    ForceWin32TIB();
     63#endif
    6264    RegisterLxExe((WINMAIN)WinMain, NULL);
    6365    return _tmain();
Note: See TracChangeset for help on using the changeset viewer.