Changeset 4433 for trunk/src/kernel32/exceptions.cpp
- Timestamp:
- Oct 5, 2000, 8:36:49 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/exceptions.cpp
r4264 r4433 1 /* $Id: exceptions.cpp,v 1.4 5 2000-09-15 13:24:29 sandervl Exp $ */1 /* $Id: exceptions.cpp,v 1.46 2000-10-05 18:36:49 sandervl Exp $ */ 2 2 3 3 /* WARNING: Compiling this module with ICC with optimizations turned on */ … … 74 74 #include "dbglocal.h" 75 75 76 /* Exception record for handling exceptions happening inside exception handlers */ 77 typedef struct 78 { 79 WINEXCEPTION_FRAME frame; 80 WINEXCEPTION_FRAME *prevFrame; 81 } EXC_NESTED_FRAME; 82 76 83 //Global Process Unhandled exception filter 77 84 static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL; … … 118 125 119 126 return(oldmode); 127 } 128 129 static inline WINEXCEPTION_FRAME * EXC_push_frame( WINEXCEPTION_FRAME *frame ) 130 { 131 // TODO: rewrite in assembly 132 TEB *teb = GetThreadTEB(); 133 frame->Prev = (PWINEXCEPTION_FRAME)teb->except; 134 teb->except = frame; 135 return frame->Prev; 136 } 137 138 static inline WINEXCEPTION_FRAME * EXC_pop_frame( WINEXCEPTION_FRAME *frame ) 139 { 140 // TODO: rewrite in assembly 141 TEB *teb = GetThreadTEB(); 142 teb->except = frame->Prev; 143 return frame->Prev; 120 144 } 121 145 … … 215 239 } 216 240 241 /******************************************************************* 242 * EXC_RaiseHandler 243 * 244 * Handler for exceptions happening inside a handler. 245 */ 246 static DWORD WIN32API EXC_RaiseHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame, 247 // WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher ) 248 WINCONTEXT *context, LPVOID dispatcher ) 249 { 250 if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) 251 return ExceptionContinueSearch; 252 /* We shouldn't get here so we store faulty frame in dispatcher */ 253 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame; 254 return ExceptionNestedException; 255 } 256 257 /******************************************************************* 258 * EXC_CallHandler 259 * 260 * Call an exception handler, setting up an exception frame to catch exceptions 261 * happening during the handler execution. 262 * WARNING: 263 * Please do not change the first 4 parameters order in any way - some exceptions handlers 264 * rely on Base Pointer (EBP) to have a fixed position related to the exception frame 265 */ 266 static DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame, 267 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher, 268 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler) 269 { 270 EXC_NESTED_FRAME newframe; 271 DWORD ret; 272 273 newframe.frame.Handler = nested_handler; 274 newframe.prevFrame = frame; 275 EXC_push_frame( &newframe.frame ); 276 dprintf(("KERNEL32: Calling handler at %p code=%lx flags=%lx\n", 277 handler, record->ExceptionCode, record->ExceptionFlags)); 278 ret = handler( record, frame, context, dispatcher ); 279 dprintf(("KERNEL32: Handler returned %lx\n", ret)); 280 EXC_pop_frame( &newframe.frame ); 281 return ret; 282 } 217 283 218 284 //****************************************************************************** … … 220 286 DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext) 221 287 { 222 PWINEXCEPTION_FRAME p frame, dispatch, nested_frame;288 PWINEXCEPTION_FRAME pFrame, dispatch, nested_frame; 223 289 int rc; 224 290 … … 228 294 nested_frame = NULL; 229 295 TEB *winteb = GetThreadTEB(); 230 p frame = (PWINEXCEPTION_FRAME)winteb->except;296 pFrame = (PWINEXCEPTION_FRAME)winteb->except; 231 297 232 298 dprintf(("KERNEL32: RtlDispatchException entered")); 233 299 234 PrintWin32ExceptionChain(p frame);300 PrintWin32ExceptionChain(pFrame); 235 301 236 302 // walk the exception chain 237 while( (p frame != NULL) && (pframe != ((void *)0xFFFFFFFF)) )303 while( (pFrame != NULL) && (pFrame != ((void *)0xFFFFFFFF)) ) 238 304 { 239 dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", p frame, pframe->Prev));240 if (p frame == pframe->Prev) {305 dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", pFrame, pFrame->Prev)); 306 if (pFrame == pFrame->Prev) { 241 307 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!")); 242 308 return 0; … … 246 312 247 313 /* Check frame address */ 248 if (((void*)p frame < winteb->stack_low) ||249 ((void*)(p frame+1) > winteb->stack_top) ||250 (int)p frame & 3)314 if (((void*)pFrame < winteb->stack_low) || 315 ((void*)(pFrame+1) > winteb->stack_top) || 316 (int)pFrame & 3) 251 317 { 252 318 dprintf(("Invalid stack! low=%08X, top=%08X, pframe = %08X", 253 winteb->stack_low, winteb->stack_top, p frame));319 winteb->stack_low, winteb->stack_top, pFrame)); 254 320 255 321 pRecord->ExceptionFlags |= EH_STACK_INVALID; … … 257 323 } 258 324 259 dprintf(("KERNEL32: RtlDispatchException - calling exception handler %08X", pframe->Handler)); 260 261 rc = pframe->Handler(pRecord, 262 pframe, 263 pContext, 264 dispatch); 265 266 dprintf(("KERNEL32: RtlDispatchException - exception handler returned %#x", rc)); 267 PrintWin32ExceptionChain(pframe); 268 269 if (pframe == nested_frame) 325 326 /* call handler */ 327 rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch, pFrame->Handler, EXC_RaiseHandler ); 328 329 PrintWin32ExceptionChain(pFrame); 330 331 if (pFrame == nested_frame) 270 332 { 271 333 /* no longer nested */ … … 293 355 } 294 356 295 dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", p frame, pframe->Prev));296 if (p frame == pframe->Prev) {357 dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", pFrame, pFrame->Prev)); 358 if (pFrame == pFrame->Prev) { 297 359 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!")); 298 360 break; 299 361 } 300 p frame = pframe->Prev;362 pFrame = pFrame->Prev; 301 363 } 302 364 dprintf(("KERNEL32: RtlDispatchException returns %#x", rc)); 303 PrintWin32ExceptionChain(p frame);365 PrintWin32ExceptionChain(pFrame); 304 366 return rc; 305 367 } … … 375 437 while ((frame != (PWINEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame)) 376 438 { 377 /* Check frame address */378 if (pEndFrame && (frame > pEndFrame))379 {380 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;381 newrec.ExceptionFlags = EH_NONCONTINUABLE;382 newrec.ExceptionRecord = pRecord;383 newrec.NumberParameters = 0;384 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));385 DosExit(EXIT_THREAD, 0);386 }387 if (((void*)frame < winteb->stack_low) ||388 ((void*)(frame+1) > winteb->stack_top) ||389 (int)frame & 3)390 {391 newrec.ExceptionCode = STATUS_BAD_STACK;392 newrec.ExceptionFlags = EH_NONCONTINUABLE;393 newrec.ExceptionRecord = pRecord;394 newrec.NumberParameters = 0;395 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));396 DosExit(EXIT_THREAD, 0);397 }398 399 /* Call handler */400 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler));401 rc = frame->Handler(pRecord, frame, &context, &dispatch);402 dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc));403 switch (rc)404 {405 case ExceptionContinueSearch:406 break;407 case ExceptionCollidedUnwind:408 frame = dispatch;409 break;410 default:411 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;412 newrec.ExceptionFlags = EH_NONCONTINUABLE;413 newrec.ExceptionRecord = pRecord;414 newrec.NumberParameters = 0;415 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));416 DosExit(EXIT_THREAD, 0);417 break;418 }419 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, frame->Prev));420 SetExceptionChain((DWORD)frame->Prev);421 frame = frame->Prev;422 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame, frame->Prev));423 }424 425 426 /* Note: I _think_ that on Win32, RtlUnwind unwinds exception handlers up */427 /* and _including_ the handler in pEndFrame argument. My reasons are: */428 /* - MSVCRT sometimes calls RtlUnwind with the address of the very first */429 /* exception handler - could be just inefficient code */430 /* - after a call to RtlUnwind, MSVCRT in some cases tries to restore */431 /* the original exception handler. If RtlUnwind didn't remove it, */432 /* the exception chain gets looped, spelling very bad mojo! */433 if (frame == pEndFrame)434 {435 /* Just repeat what we did in the while loop above */436 439 /* Check frame address */ 437 440 if (pEndFrame && (frame > pEndFrame)) … … 1174 1177 // recurse infinitely until we run out of stack space!! 1175 1178 if (pERepRec->fHandlerFlags & EH_NESTED_CALL) 1176 1179 return XCPT_CONTINUE_SEARCH; 1177 1180 1178 1181 #ifdef DEBUG
Note:
See TracChangeset
for help on using the changeset viewer.