Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
6.8 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. chandler.c
  5. Abstract:
  6. This module implements the C specific exception handler that provides
  7. structured condition handling for the C language.
  8. Author:
  9. Modified for PowerPC by Rick Simpson 27-Sep-1993
  10. from MIPS version by David N. Cutler (davec) 11-Sep-1990
  11. Environment:
  12. Any mode.
  13. Revision History:
  14. Tom Wood (twood) 1-Nov-1993
  15. Use __C_ExecuteExceptionFilter and __C_ExecuteTerminationHandler
  16. previously deleted from the MIPS version.
  17. --*/
  18. #include "nt.h"
  19. //
  20. // Define procedure prototypes for exception filter and termination handler
  21. // execution routines defined in jmpunwnd.s
  22. //
  23. LONG
  24. __C_ExecuteExceptionFilter (
  25. PEXCEPTION_POINTERS ExceptionPointers,
  26. EXCEPTION_FILTER ExceptionFilter,
  27. ULONG EstablisherFrame
  28. );
  29. VOID
  30. __C_ExecuteTerminationHandler (
  31. BOOLEAN AbnormalTermination,
  32. TERMINATION_HANDLER TerminationHandler,
  33. ULONG EstablisherFrame
  34. );
  35. EXCEPTION_DISPOSITION
  36. __C_specific_handler (
  37. IN PEXCEPTION_RECORD ExceptionRecord,
  38. IN PVOID EstablisherFrame,
  39. IN OUT PCONTEXT ContextRecord,
  40. IN OUT PDISPATCHER_CONTEXT DispatcherContext
  41. )
  42. /*++
  43. Routine Description:
  44. This function scans the scope tables associated with the specified
  45. procedure and calls exception and termination handlers as necessary.
  46. Arguments:
  47. ExceptionRecord - Supplies a pointer to an exception record.
  48. EstablisherFrame - Supplies a pointer to frame of the establisher function.
  49. ContextRecord - Supplies a pointer to a context record.
  50. DispatcherContext - Supplies a pointer to the exception dispatcher or
  51. unwind dispatcher context.
  52. Return Value:
  53. If the exception is handled by one of the exception filter routines, then
  54. there is no return from this routine and RtlUnwind is called. Otherwise,
  55. an exception disposition value of continue execution or continue search is
  56. returned.
  57. --*/
  58. {
  59. ULONG ControlPc;
  60. EXCEPTION_FILTER ExceptionFilter;
  61. EXCEPTION_POINTERS ExceptionPointers;
  62. PRUNTIME_FUNCTION FunctionEntry;
  63. ULONG Index;
  64. PSCOPE_TABLE ScopeTable;
  65. ULONG TargetPc;
  66. TERMINATION_HANDLER TerminationHandler;
  67. LONG Value;
  68. //
  69. // Get address of where control left the establisher, the address of the
  70. // function table entry that describes the function, and the address of
  71. // the scope table.
  72. //
  73. ControlPc = DispatcherContext->ControlPc;
  74. FunctionEntry = DispatcherContext->FunctionEntry;
  75. ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData);
  76. //
  77. // If an unwind is not in progress, then scan the scope table and call
  78. // the appropriate exception filter routines. Otherwise, scan the scope
  79. // table and call the appropriate termination handlers using the target
  80. // PC obtained from the context record.
  81. // are called.
  82. //
  83. if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
  84. //
  85. // Scan the scope table and call the appropriate exception filter
  86. // routines.
  87. //
  88. ExceptionPointers.ExceptionRecord = ExceptionRecord;
  89. ExceptionPointers.ContextRecord = ContextRecord;
  90. for (Index = 0; Index < ScopeTable->Count; Index += 1) {
  91. if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
  92. (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) &&
  93. (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) {
  94. //
  95. // Call the exception filter routine.
  96. //
  97. ExceptionFilter =
  98. (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress;
  99. Value = __C_ExecuteExceptionFilter(&ExceptionPointers,
  100. ExceptionFilter,
  101. (ULONG)EstablisherFrame);
  102. //
  103. // If the return value is less than zero, then dismiss the
  104. // exception. Otherwise, if the value is greater than zero,
  105. // then unwind to the target exception handler. Otherwise,
  106. // continue the search for an exception filter.
  107. //
  108. if (Value < 0) {
  109. return ExceptionContinueExecution;
  110. } else if (Value > 0) {
  111. RtlUnwind(EstablisherFrame,
  112. (PVOID)ScopeTable->ScopeRecord[Index].JumpTarget,
  113. ExceptionRecord,
  114. (PVOID)ExceptionRecord->ExceptionCode);
  115. }
  116. }
  117. }
  118. } else {
  119. //
  120. // Scan the scope table and call the appropriate termination handler
  121. // routines.
  122. //
  123. TargetPc = ContextRecord->Iar;
  124. for (Index = 0; Index < ScopeTable->Count; Index += 1) {
  125. if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
  126. (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) {
  127. //
  128. // If the target PC is within the same scope the control PC
  129. // is within, then this is an uplevel goto out of an inner try
  130. // scope or a long jump back into a try scope. Terminate the
  131. // scan termination handlers.
  132. //
  133. // N.B. The target PC can be just beyond the end of the scope,
  134. // in which case it is a leave from the scope.
  135. //
  136. if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
  137. (TargetPc <= ScopeTable->ScopeRecord[Index].EndAddress)) {
  138. break;
  139. } else {
  140. //
  141. // If the scope table entry describes an exception filter
  142. // and the associated exception handler is the target of
  143. // the unwind, then terminate the scan for termination
  144. // handlers. Otherwise, if the scope table entry describes
  145. // a termination handler, then record the address of the
  146. // end of the scope as the new control PC address and call
  147. // the termination handler.
  148. //
  149. if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) {
  150. if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) {
  151. break;
  152. }
  153. } else {
  154. DispatcherContext->ControlPc =
  155. ScopeTable->ScopeRecord[Index].EndAddress + 4;
  156. TerminationHandler =
  157. (TERMINATION_HANDLER)ScopeTable->ScopeRecord[Index].HandlerAddress;
  158. __C_ExecuteTerminationHandler(TRUE,
  159. TerminationHandler,
  160. (ULONG)EstablisherFrame);
  161. }
  162. }
  163. }
  164. }
  165. }
  166. //
  167. // Continue search for exception or termination handlers.
  168. //
  169. return ExceptionContinueSearch;
  170. }