Source code of Windows XP (NT5)
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.

273 lines
6.4 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. raisests.c
  5. Abstract:
  6. This module implements routines to raise a general exception from kernel
  7. mode or a noncontinuable exception from kernel mode.
  8. Author:
  9. David N. Cutler (davec) 18-Oct-1990
  10. Environment:
  11. Any mode.
  12. Revision History:
  13. Thomas Van Baak (tvb) 5-May-1992
  14. Adapted for Alpha AXP.
  15. --*/
  16. #include "exp.h"
  17. //
  18. // Define private function prototypes.
  19. //
  20. VOID
  21. ExpRaiseException (
  22. IN PEXCEPTION_RECORD ExceptionRecord
  23. );
  24. VOID
  25. ExpRaiseStatus (
  26. IN NTSTATUS ExceptionCode
  27. );
  28. VOID
  29. ExRaiseException (
  30. IN PEXCEPTION_RECORD ExceptionRecord
  31. )
  32. /*++
  33. Routine Description:
  34. This function raises a software exception by building a context record
  35. and calling the exception dispatcher directly.
  36. N.B. This routine is a shell routine that simply calls another routine
  37. to do the real work. The reason this is done is to avoid a problem
  38. in try/finally scopes where the last statement in the scope is a
  39. call to raise an exception.
  40. Arguments:
  41. ExceptionRecord - Supplies a pointer to an exception record.
  42. Return Value:
  43. None.
  44. --*/
  45. {
  46. #ifdef DBGtvb
  47. DbgPrint("ExRaiseException(ExceptionRecord = %lx) Status = %lx\n",
  48. ExceptionRecord, ExceptionRecord->ExceptionCode);
  49. );
  50. #endif
  51. ExpRaiseException(ExceptionRecord);
  52. return;
  53. }
  54. VOID
  55. ExpRaiseException (
  56. IN PEXCEPTION_RECORD ExceptionRecord
  57. )
  58. /*++
  59. Routine Description:
  60. This function raises a software exception by building a context record
  61. and calling the exception dispatcher directly.
  62. Arguments:
  63. ExceptionRecord - Supplies a pointer to an exception record.
  64. Return Value:
  65. None.
  66. --*/
  67. {
  68. ULONG_PTR ControlPc;
  69. CONTEXT ContextRecord;
  70. FRAME_POINTERS EstablisherFrame;
  71. PRUNTIME_FUNCTION FunctionEntry;
  72. BOOLEAN InFunction;
  73. ULONG_PTR NextPc;
  74. NTSTATUS Status;
  75. //
  76. // Capture the current context, virtually unwind to the caller of this
  77. // routine, set the fault instruction address to that of the caller, and
  78. // call the exception dispatcher.
  79. //
  80. RtlCaptureContext(&ContextRecord);
  81. ControlPc = (ULONG_PTR)ContextRecord.IntRa - 4;
  82. FunctionEntry = RtlLookupFunctionEntry(ControlPc);
  83. NextPc = RtlVirtualUnwind(ControlPc,
  84. FunctionEntry,
  85. &ContextRecord,
  86. &InFunction,
  87. &EstablisherFrame,
  88. NULL);
  89. ContextRecord.Fir = (ULONGLONG)(LONG_PTR)NextPc + 4;
  90. ExceptionRecord->ExceptionAddress = (PVOID)ContextRecord.Fir;
  91. //
  92. // If the exception is successfully dispatched, then continue execution.
  93. // Otherwise, give the kernel debugger a chance to handle the exception.
  94. //
  95. if (RtlDispatchException(ExceptionRecord, &ContextRecord)) {
  96. Status = ZwContinue(&ContextRecord, FALSE);
  97. } else {
  98. Status = ZwRaiseException(ExceptionRecord, &ContextRecord, FALSE);
  99. }
  100. //
  101. // Either the attempt to continue execution or the attempt to give
  102. // the kernel debugger a chance to handle the exception failed. Raise
  103. // a noncontinuable exception.
  104. //
  105. ExRaiseStatus(Status);
  106. }
  107. VOID
  108. ExRaiseStatus (
  109. IN NTSTATUS ExceptionCode
  110. )
  111. /*++
  112. Routine Description:
  113. This function raises an exception with the specified status value by
  114. building an exception record, building a context record, and calling the
  115. exception dispatcher directly. The exception is marked as noncontinuable
  116. with no parameters. There is no return from this function.
  117. N.B. This routine is a shell routine that simply calls another routine
  118. to do the real work. The reason this is done is to avoid a problem
  119. in try/finally scopes where the last statement in the scope is a
  120. call to raise an exception.
  121. Arguments:
  122. ExceptionCode - Supplies the status value to be used as the exception
  123. code for the exception that is to be raised.
  124. Return Value:
  125. None.
  126. --*/
  127. {
  128. #ifdef DBGxx
  129. DbgPrint("ExRaiseStatus(ExceptionCode = %lx)\n", ExceptionCode);
  130. #endif
  131. ExpRaiseStatus(ExceptionCode);
  132. return;
  133. }
  134. VOID
  135. ExpRaiseStatus (
  136. IN NTSTATUS ExceptionCode
  137. )
  138. /*++
  139. Routine Description:
  140. This function raises an exception with the specified status value by
  141. building an exception record, building a context record, and calling the
  142. exception dispatcher directly. The exception is marked as noncontinuable
  143. with no parameters. There is no return from this function.
  144. Arguments:
  145. ExceptionCode - Supplies the status value to be used as the exception
  146. code for the exception that is to be raised.
  147. Return Value:
  148. None.
  149. --*/
  150. {
  151. ULONG_PTR ControlPc;
  152. CONTEXT ContextRecord;
  153. FRAME_POINTERS EstablisherFrame;
  154. EXCEPTION_RECORD ExceptionRecord;
  155. PRUNTIME_FUNCTION FunctionEntry;
  156. BOOLEAN InFunction;
  157. ULONG_PTR NextPc;
  158. NTSTATUS Status;
  159. //
  160. // Construct an exception record.
  161. //
  162. ExceptionRecord.ExceptionCode = ExceptionCode;
  163. ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  164. ExceptionRecord.NumberParameters = 0;
  165. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  166. //
  167. // Capture the current context, virtually unwind to the caller of this
  168. // routine, set the fault instruction address to that of the caller, and
  169. // call the exception dispatcher.
  170. //
  171. RtlCaptureContext(&ContextRecord);
  172. ControlPc = (ULONG_PTR)ContextRecord.IntRa - 4;
  173. FunctionEntry = RtlLookupFunctionEntry(ControlPc);
  174. NextPc = RtlVirtualUnwind(ControlPc,
  175. FunctionEntry,
  176. &ContextRecord,
  177. &InFunction,
  178. &EstablisherFrame,
  179. NULL);
  180. ContextRecord.Fir = (ULONGLONG)(LONG_PTR)NextPc + 4;
  181. ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Fir;
  182. RtlDispatchException(&ExceptionRecord, &ContextRecord);
  183. //
  184. // An unwind was not initiated during the dispatching of a noncontinuable
  185. // exception. Give the kernel debugger a chance to handle the exception.
  186. //
  187. Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, FALSE);
  188. //
  189. // The attempt to give the kernel debugger a chance to handle the exception
  190. // failed. Raise another noncontinuable exception.
  191. //
  192. ExRaiseStatus(Status);
  193. }