Leaked source code of windows server 2003
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.

894 lines
27 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. exceptn.c
  5. Abstract:
  6. This module implement the code necessary to dispatch expections to the
  7. proper mode and invoke the exception dispatcher.
  8. Author:
  9. David N. Cutler (davec) 5-May-2000
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. VOID
  16. KeContextFromKframes (
  17. IN PKTRAP_FRAME TrapFrame,
  18. IN PKEXCEPTION_FRAME ExceptionFrame,
  19. IN OUT PCONTEXT ContextRecord
  20. )
  21. /*++
  22. Routine Description:
  23. This routine moves the selected contents of the specified trap and
  24. exception frames into the specified context frame according to the
  25. specified context flags.
  26. Arguments:
  27. TrapFrame - Supplies a pointer to a trap frame from which volatile
  28. context should be copied into the context record.
  29. ExceptionFrame - Supplies a pointer to an exception frame from which
  30. context should be copied into the context record.
  31. ContextRecord - Supplies a pointer to the context frame that receives
  32. the context copied from the trap and exception frames.
  33. Return Value:
  34. None.
  35. --*/
  36. {
  37. ULONG ContextFlags;
  38. PLEGACY_SAVE_AREA NpxFrame;
  39. KIRQL OldIrql;
  40. //
  41. // Raise IRQL to APC_LEVEL to guarantee that a consistent set of context
  42. // is transferred from the trap and exception frames.
  43. //
  44. OldIrql = KeGetCurrentIrql();
  45. if (OldIrql < APC_LEVEL) {
  46. KfRaiseIrql(APC_LEVEL);
  47. }
  48. //
  49. // Set control information if specified.
  50. //
  51. ContextFlags = ContextRecord->ContextFlags;
  52. if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  53. //
  54. // Set registers RIP, CS, RSP, SS, and EFlags.
  55. //
  56. ContextRecord->Rip = TrapFrame->Rip;
  57. ContextRecord->SegCs = TrapFrame->SegCs;
  58. ContextRecord->SegSs = TrapFrame->SegSs;
  59. ContextRecord->Rsp = TrapFrame->Rsp;
  60. ContextRecord->EFlags = TrapFrame->EFlags;
  61. }
  62. //
  63. // Set segment register contents if specified.
  64. //
  65. if ((ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) {
  66. //
  67. // Set segment registers GS, FS, ES, DS.
  68. //
  69. ContextRecord->SegDs = KGDT64_R3_DATA | RPL_MASK;
  70. ContextRecord->SegEs = KGDT64_R3_DATA | RPL_MASK;
  71. ContextRecord->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
  72. ContextRecord->SegGs = KGDT64_R3_DATA | RPL_MASK;
  73. }
  74. //
  75. // Set integer register contents if specified.
  76. //
  77. if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  78. //
  79. // Set integer registers RAX, RCX, RDX, RSI, RDI, R8, R9, R10, RBX,
  80. // RBP, R11, R12, R13, R14, and R15.
  81. //
  82. ContextRecord->Rax = TrapFrame->Rax;
  83. ContextRecord->Rcx = TrapFrame->Rcx;
  84. ContextRecord->Rdx = TrapFrame->Rdx;
  85. ContextRecord->R8 = TrapFrame->R8;
  86. ContextRecord->R9 = TrapFrame->R9;
  87. ContextRecord->R10 = TrapFrame->R10;
  88. ContextRecord->R11 = TrapFrame->R11;
  89. ContextRecord->Rbp = TrapFrame->Rbp;
  90. ContextRecord->Rbx = ExceptionFrame->Rbx;
  91. ContextRecord->Rdi = ExceptionFrame->Rdi;
  92. ContextRecord->Rsi = ExceptionFrame->Rsi;
  93. ContextRecord->R12 = ExceptionFrame->R12;
  94. ContextRecord->R13 = ExceptionFrame->R13;
  95. ContextRecord->R14 = ExceptionFrame->R14;
  96. ContextRecord->R15 = ExceptionFrame->R15;
  97. }
  98. //
  99. // Set floating point context if specified.
  100. //
  101. //
  102. if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  103. //
  104. // Set XMM registers Xmm0-Xmm15 and the XMM CSR contents.
  105. //
  106. RtlCopyMemory(&ContextRecord->Xmm0,
  107. &TrapFrame->Xmm0,
  108. sizeof(M128) * 6);
  109. RtlCopyMemory(&ContextRecord->Xmm6,
  110. &ExceptionFrame->Xmm6,
  111. sizeof(M128) * 10);
  112. ContextRecord->MxCsr = TrapFrame->MxCsr;
  113. //
  114. // If the specified mode is user, then set the legacy floating
  115. // point state.
  116. //
  117. if ((TrapFrame->SegCs & MODE_MASK) == UserMode) {
  118. //
  119. // Set the floating registers MM0/ST0 - MM7/ST7 and control state.
  120. //
  121. NpxFrame = (PLEGACY_SAVE_AREA)(TrapFrame + 1);
  122. RtlCopyMemory(&ContextRecord->FltSave,
  123. NpxFrame,
  124. sizeof(LEGACY_SAVE_AREA));
  125. }
  126. }
  127. //
  128. //
  129. // Set debug register contents if requested.
  130. //
  131. if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) {
  132. //
  133. // Set the debug registers DR0, DR1, DR2, DR3, DR6, and DR7.
  134. //
  135. if ((TrapFrame->Dr7 & DR7_ACTIVE) != 0) {
  136. ContextRecord->Dr0 = TrapFrame->Dr0;
  137. ContextRecord->Dr1 = TrapFrame->Dr1;
  138. ContextRecord->Dr2 = TrapFrame->Dr2;
  139. ContextRecord->Dr3 = TrapFrame->Dr3;
  140. ContextRecord->Dr6 = TrapFrame->Dr6;
  141. ContextRecord->Dr7 = TrapFrame->Dr7;
  142. } else {
  143. ContextRecord->Dr0 = 0;
  144. ContextRecord->Dr1 = 0;
  145. ContextRecord->Dr2 = 0;
  146. ContextRecord->Dr3 = 0;
  147. ContextRecord->Dr6 = 0;
  148. ContextRecord->Dr7 = 0;
  149. }
  150. }
  151. //
  152. // Lower IRQL to its previous value.
  153. //
  154. if (OldIrql < APC_LEVEL) {
  155. KeLowerIrql(OldIrql);
  156. }
  157. return;
  158. }
  159. VOID
  160. KeContextToKframes (
  161. IN OUT PKTRAP_FRAME TrapFrame,
  162. IN OUT PKEXCEPTION_FRAME ExceptionFrame,
  163. IN PCONTEXT ContextRecord,
  164. IN ULONG ContextFlags,
  165. IN KPROCESSOR_MODE PreviousMode
  166. )
  167. /*++
  168. Routine Description:
  169. This routine moves the selected contents of the specified context frame
  170. into the specified trap and exception frames according to the specified
  171. context flags.
  172. Arguments:
  173. TrapFrame - Supplies a pointer to a trap frame that receives the volatile
  174. context from the context record.
  175. ExceptionFrame - Supplies a pointer to an exception frame that receives
  176. the nonvolatile context from the context record.
  177. ContextRecord - Supplies a pointer to a context frame that contains the
  178. context that is to be copied into the trap and exception frames.
  179. ContextFlags - Supplies the set of flags that specify which parts of the
  180. context frame are to be copied into the trap and exception frames.
  181. PreviousMode - Supplies the processor mode for which the exception and
  182. trap frames are being built.
  183. Return Value:
  184. None.
  185. --*/
  186. {
  187. PLEGACY_SAVE_AREA NpxFrame;
  188. KIRQL OldIrql;
  189. //
  190. // Raise IRQL to APC_LEVEL to guarantee that a consistent set of context
  191. // is transferred from the trap and exception frames.
  192. //
  193. OldIrql = KeGetCurrentIrql();
  194. if (OldIrql < APC_LEVEL) {
  195. KfRaiseIrql(APC_LEVEL);
  196. }
  197. //
  198. // Set control information if specified.
  199. //
  200. if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  201. //
  202. // Set registers RIP, RSP, and EFlags.
  203. //
  204. TrapFrame->EFlags = SANITIZE_EFLAGS(ContextRecord->EFlags, PreviousMode);
  205. TrapFrame->Rip = ContextRecord->Rip;
  206. TrapFrame->Rsp = ContextRecord->Rsp;
  207. }
  208. //
  209. // The segment registers DS, ES, FS, and GS are never restored from saved
  210. // data. However, SS and CS are restored from the trap frame. Make sure
  211. // that these segment registers have the proper values.
  212. //
  213. if (PreviousMode == UserMode) {
  214. TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
  215. if (ContextRecord->SegCs != (KGDT64_R3_CODE | RPL_MASK)) {
  216. TrapFrame->SegCs = KGDT64_R3_CMCODE | RPL_MASK;
  217. } else {
  218. TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
  219. }
  220. } else {
  221. TrapFrame->SegCs = KGDT64_R0_CODE;
  222. TrapFrame->SegSs = KGDT64_NULL;
  223. }
  224. //
  225. // Set integer registers contents if specified.
  226. //
  227. if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  228. //
  229. // Set integer registers RAX, RCX, RDX, RSI, RDI, R8, R9, R10, RBX,
  230. // RBP, R11, R12, R13, R14, and R15.
  231. //
  232. TrapFrame->Rax = ContextRecord->Rax;
  233. TrapFrame->Rcx = ContextRecord->Rcx;
  234. TrapFrame->Rdx = ContextRecord->Rdx;
  235. TrapFrame->R8 = ContextRecord->R8;
  236. TrapFrame->R9 = ContextRecord->R9;
  237. TrapFrame->R10 = ContextRecord->R10;
  238. TrapFrame->R11 = ContextRecord->R11;
  239. TrapFrame->Rbp = ContextRecord->Rbp;
  240. ExceptionFrame->Rbx = ContextRecord->Rbx;
  241. ExceptionFrame->Rsi = ContextRecord->Rsi;
  242. ExceptionFrame->Rdi = ContextRecord->Rdi;
  243. ExceptionFrame->R12 = ContextRecord->R12;
  244. ExceptionFrame->R13 = ContextRecord->R13;
  245. ExceptionFrame->R14 = ContextRecord->R14;
  246. ExceptionFrame->R15 = ContextRecord->R15;
  247. }
  248. //
  249. // Set floating register contents if requested.
  250. //
  251. if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  252. //
  253. // Set XMM registers Xmm0-Xmm15 and the XMM CSR contents.
  254. //
  255. RtlCopyMemory(&TrapFrame->Xmm0,
  256. &ContextRecord->Xmm0,
  257. sizeof(M128) * 6);
  258. RtlCopyMemory(&ExceptionFrame->Xmm6,
  259. &ContextRecord->Xmm6,
  260. sizeof(M128) * 10);
  261. //
  262. // Clear all reserved bits in MXCSR.
  263. //
  264. TrapFrame->MxCsr = SANITIZE_MXCSR(ContextRecord->MxCsr);
  265. //
  266. // If the specified mode is user, then also set the legacy floating
  267. // point state.
  268. //
  269. if ((TrapFrame->SegCs & MODE_MASK) == UserMode) {
  270. //
  271. // Set the floating state MM0/ST0 - MM7/ST7 and the control state.
  272. //
  273. NpxFrame = (PLEGACY_SAVE_AREA)(TrapFrame + 1);
  274. RtlCopyMemory(NpxFrame,
  275. &ContextRecord->FltSave,
  276. sizeof(LEGACY_SAVE_AREA));
  277. NpxFrame->ControlWord = SANITIZE_FCW(NpxFrame->ControlWord);
  278. }
  279. }
  280. //
  281. // Set debug register state if specified.
  282. //
  283. if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) {
  284. //
  285. // Set the debug registers DR0, DR1, DR2, DR3, DR6, and DR7.
  286. //
  287. TrapFrame->Dr0 = SANITIZE_DRADDR(ContextRecord->Dr0, PreviousMode);
  288. TrapFrame->Dr1 = SANITIZE_DRADDR(ContextRecord->Dr1, PreviousMode);
  289. TrapFrame->Dr2 = SANITIZE_DRADDR(ContextRecord->Dr2, PreviousMode);
  290. TrapFrame->Dr3 = SANITIZE_DRADDR(ContextRecord->Dr3, PreviousMode);
  291. TrapFrame->Dr6 = 0;
  292. TrapFrame->Dr7 = SANITIZE_DR7(ContextRecord->Dr7, PreviousMode);
  293. if (PreviousMode != KernelMode) {
  294. KeGetCurrentThread()->Header.DebugActive =
  295. (BOOLEAN)((TrapFrame->Dr7 & DR7_ACTIVE) != 0);
  296. }
  297. }
  298. //
  299. // Lower IRQL to its previous value.
  300. //
  301. if (OldIrql < APC_LEVEL) {
  302. KeLowerIrql(OldIrql);
  303. }
  304. return;
  305. }
  306. VOID
  307. KiDispatchException (
  308. IN PEXCEPTION_RECORD ExceptionRecord,
  309. IN PKEXCEPTION_FRAME ExceptionFrame,
  310. IN PKTRAP_FRAME TrapFrame,
  311. IN KPROCESSOR_MODE PreviousMode,
  312. IN BOOLEAN FirstChance
  313. )
  314. /*++
  315. Routine Description:
  316. This function is called to dispatch an exception to the proper mode and
  317. to cause the exception dispatcher to be called. If the previous mode is
  318. kernel, then the exception dispatcher is called directly to process the
  319. exception. Otherwise the exception record, exception frame, and trap
  320. frame contents are copied to the user mode stack. The contents of the
  321. exception frame and trap are then modified such that when control is
  322. returned, execution will commense in user mode in a routine which will
  323. call the exception dispatcher.
  324. Arguments:
  325. ExceptionRecord - Supplies a pointer to an exception record.
  326. ExceptionFrame - Supplies a pointer to an exception frame. For NT386,
  327. this should be NULL.
  328. TrapFrame - Supplies a pointer to a trap frame.
  329. PreviousMode - Supplies the previous processor mode.
  330. FirstChance - Supplies a boolean value that specifies whether this is
  331. the first (TRUE) or second (FALSE) chance for the exception.
  332. Return Value:
  333. None.
  334. --*/
  335. {
  336. CONTEXT ContextRecord;
  337. BOOLEAN DebugService;
  338. EXCEPTION_RECORD ExceptionRecord1;
  339. BOOLEAN ExceptionWasForwarded = FALSE;
  340. ULONG64 FaultingRsp;
  341. PMACHINE_FRAME MachineFrame;
  342. ULONG64 UserStack1;
  343. ULONG64 UserStack2;
  344. //
  345. // Move machine state from trap and exception frames to a context frame
  346. // and increment the number of exceptions dispatched.
  347. //
  348. KeGetCurrentPrcb()->KeExceptionDispatchCount += 1;
  349. ContextRecord.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | CONTEXT_SEGMENTS;
  350. KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextRecord);
  351. //
  352. // If the exception is a break point, then convert the break point to a
  353. // fault.
  354. //
  355. if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
  356. ContextRecord.Rip -= 1;
  357. }
  358. //
  359. // Select the method of handling the exception based on the previous mode.
  360. //
  361. if (PreviousMode == KernelMode) {
  362. //
  363. // Previous mode was kernel.
  364. //
  365. // If the kernel debugger is active, then give the kernel debugger
  366. // the first chance to handle the exception. If the kernel debugger
  367. // handles the exception, then continue execution. Otherwise, attempt
  368. // to dispatch the exception to a frame based handler. If a frame
  369. // based handler handles the exception, then continue execution.
  370. //
  371. // If a frame based handler does not handle the exception, give the
  372. // kernel debugger a second chance, if it's present.
  373. //
  374. // If the exception is still unhandled call bugcheck.
  375. //
  376. if (FirstChance != FALSE) {
  377. if ((KiDebugRoutine)(TrapFrame,
  378. ExceptionFrame,
  379. ExceptionRecord,
  380. &ContextRecord,
  381. PreviousMode,
  382. FALSE) != FALSE) {
  383. goto Handled1;
  384. }
  385. //
  386. // Kernel debugger didn't handle exception.
  387. //
  388. // ******fix
  389. //
  390. // If interrupts are disabled, then bugcheck.
  391. //
  392. // ******fix
  393. if (RtlDispatchException(ExceptionRecord, &ContextRecord) != FALSE) {
  394. goto Handled1;
  395. }
  396. }
  397. //
  398. // This is the second chance to handle the exception.
  399. //
  400. if ((KiDebugRoutine)(TrapFrame,
  401. ExceptionFrame,
  402. ExceptionRecord,
  403. &ContextRecord,
  404. PreviousMode,
  405. TRUE) != FALSE) {
  406. goto Handled1;
  407. }
  408. KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
  409. ExceptionRecord->ExceptionCode,
  410. (ULONG64)ExceptionRecord->ExceptionAddress,
  411. ExceptionRecord->ExceptionInformation[0],
  412. ExceptionRecord->ExceptionInformation[1]);
  413. } else {
  414. //
  415. // Previous mode was user.
  416. //
  417. // If this is the first chance and the current process has a debugger
  418. // port, then send a message to the debugger port and wait for a reply.
  419. // If the debugger handles the exception, then continue execution. Else
  420. // transfer the exception information to the user stack, transition to
  421. // user mode, and attempt to dispatch the exception to a frame based
  422. // handler. If a frame based handler handles the exception, then continue
  423. // execution with the continue system service. Else execute the
  424. // NtRaiseException system service with FirstChance == FALSE, which
  425. // will call this routine a second time to process the exception.
  426. //
  427. // If this is the second chance and the current process has a debugger
  428. // port, then send a message to the debugger port and wait for a reply.
  429. // If the debugger handles the exception, then continue execution. Else
  430. // if the current process has a subsystem port, then send a message to
  431. // the subsystem port and wait for a reply. If the subsystem handles the
  432. // exception, then continue execution. Else terminate the thread.
  433. //
  434. // If the exception happened while executing 32-bit code, then convert
  435. // the exception to a wow64 exception. These codes are translated later
  436. // by wow64.
  437. //
  438. if ((ContextRecord.SegCs & 0xfff8) == KGDT64_R3_CMCODE) {
  439. switch (ExceptionRecord->ExceptionCode) {
  440. case STATUS_BREAKPOINT:
  441. ExceptionRecord->ExceptionCode = STATUS_WX86_BREAKPOINT;
  442. break;
  443. case STATUS_SINGLE_STEP:
  444. ExceptionRecord->ExceptionCode = STATUS_WX86_SINGLE_STEP;
  445. break;
  446. }
  447. //
  448. // If the user mode thread is executing in 32-bit mode, then
  449. // clear the upper 32-bits of the stack address and 16-byte
  450. // align the stack address.
  451. //
  452. FaultingRsp = (ContextRecord.Rsp & 0xfffffff0UI64);
  453. } else {
  454. FaultingRsp = ContextRecord.Rsp;
  455. }
  456. if (FirstChance == TRUE) {
  457. //
  458. // This is the first chance to handle the exception.
  459. //
  460. // If the current processor is not being debugged and user mode
  461. // exceptions are not being ignored, or this is a debug service,
  462. // then attempt to handle the exception via the kernel debugger.
  463. //
  464. DebugService = KdIsThisAKdTrap(ExceptionRecord,
  465. &ContextRecord,
  466. UserMode);
  467. if (((PsGetCurrentProcess()->DebugPort == NULL) &&
  468. (KdIgnoreUmExceptions == FALSE)) ||
  469. (DebugService == TRUE)) {
  470. //
  471. // If the kernel debugger is present, then attempt to handle
  472. // the exception with the kernel debugger. Otherwise, if the
  473. // exception is a debug service, then handle the exception
  474. // directly.
  475. //
  476. if (KdDebuggerNotPresent == FALSE) {
  477. if ((KiDebugRoutine)(TrapFrame,
  478. ExceptionFrame,
  479. ExceptionRecord,
  480. &ContextRecord,
  481. PreviousMode,
  482. FALSE) != FALSE) {
  483. goto Handled1;
  484. }
  485. } else if (DebugService == TRUE) {
  486. ContextRecord.Rip += 1;
  487. goto Handled1;
  488. }
  489. }
  490. if ((ExceptionWasForwarded == FALSE) &&
  491. (DbgkForwardException(ExceptionRecord, TRUE, FALSE))) {
  492. goto Handled2;
  493. }
  494. //
  495. // If the exception is single step, then clear the trace flag in
  496. // the trap frame.
  497. //
  498. if ((ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) ||
  499. (ExceptionRecord->ExceptionCode == STATUS_WX86_SINGLE_STEP)) {
  500. TrapFrame->EFlags &= ~EFLAGS_TF_MASK;
  501. }
  502. //
  503. // Transfer exception information to the user stack, transition
  504. // to user mode, and attempt to dispatch the exception to a frame
  505. // based handler.
  506. //
  507. ExceptionRecord1.ExceptionCode = STATUS_ACCESS_VIOLATION;
  508. repeat:
  509. try {
  510. //
  511. // Compute address of aligned machine frame, compute address
  512. // of exception record, compute address of context record,
  513. // and probe user stack for writeability.
  514. //
  515. MachineFrame =
  516. (PMACHINE_FRAME)((FaultingRsp - sizeof(MACHINE_FRAME)) & ~STACK_ROUND);
  517. UserStack1 = (ULONG64)MachineFrame - EXCEPTION_RECORD_LENGTH;
  518. UserStack2 = UserStack1 - CONTEXT_LENGTH;
  519. ProbeForWriteSmallStructure((PVOID)UserStack2,
  520. sizeof(MACHINE_FRAME) + EXCEPTION_RECORD_LENGTH + CONTEXT_LENGTH,
  521. STACK_ALIGN);
  522. //
  523. // Fill in machine frame information.
  524. //
  525. MachineFrame->Rsp = FaultingRsp;
  526. MachineFrame->Rip = ContextRecord.Rip;
  527. //
  528. // Copy exception record to the user stack.
  529. //
  530. RtlCopyMemory((PVOID)UserStack1,
  531. ExceptionRecord,
  532. sizeof(EXCEPTION_RECORD));
  533. //
  534. // Copy context record to the user stack.
  535. //
  536. RtlCopyMemory((PVOID)UserStack2,
  537. &ContextRecord,
  538. sizeof(CONTEXT));
  539. //
  540. // Set address of exception record, context record, and the
  541. // and the new stack pointer in the current trap frame.
  542. //
  543. ExceptionFrame->Rsi = UserStack1;
  544. ExceptionFrame->Rdi = UserStack2;
  545. TrapFrame->Rsp = UserStack2;
  546. //
  547. // Set the user mode 64-bit code selector.
  548. //
  549. TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
  550. //
  551. // Set the address of the exception routine that will call the
  552. // exception dispatcher and then return to the trap handler.
  553. // The trap handler will restore the exception and trap frame
  554. // context and continue execution in the routine that will
  555. // call the exception dispatcher.
  556. //
  557. TrapFrame->Rip = (ULONG64)KeUserExceptionDispatcher;
  558. return;
  559. } except (KiCopyInformation(&ExceptionRecord1,
  560. (GetExceptionInformation())->ExceptionRecord)) {
  561. //
  562. // If the exception is a stack overflow, then attempt to
  563. // raise the stack overflow exception. Otherwise, the user's
  564. // stack is not accessible, or is misaligned, and second
  565. // chance processing is performed.
  566. //
  567. if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) {
  568. ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress;
  569. RtlCopyMemory((PVOID)ExceptionRecord,
  570. &ExceptionRecord1,
  571. sizeof(EXCEPTION_RECORD));
  572. goto repeat;
  573. }
  574. }
  575. }
  576. //
  577. // This is the second chance to handle the exception.
  578. //
  579. if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) {
  580. goto Handled2;
  581. } else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) {
  582. goto Handled2;
  583. } else {
  584. ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
  585. KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
  586. ExceptionRecord->ExceptionCode,
  587. (ULONG64)ExceptionRecord->ExceptionAddress,
  588. ExceptionRecord->ExceptionInformation[0],
  589. ExceptionRecord->ExceptionInformation[1]);
  590. }
  591. }
  592. //
  593. // Move machine state from context frame to trap and exception frames and
  594. // then return to continue execution with the restored state.
  595. //
  596. Handled1:
  597. KeContextToKframes(TrapFrame,
  598. ExceptionFrame,
  599. &ContextRecord,
  600. ContextRecord.ContextFlags,
  601. PreviousMode);
  602. //
  603. // Exception was handled by the debugger or the associated subsystem
  604. // and state was modified, if necessary, using the get state and set
  605. // state capabilities. Therefore the context frame does not need to
  606. // be transfered to the trap and exception frames.
  607. //
  608. Handled2:
  609. return;
  610. }
  611. ULONG
  612. KiCopyInformation (
  613. IN OUT PEXCEPTION_RECORD ExceptionRecord1,
  614. IN PEXCEPTION_RECORD ExceptionRecord2
  615. )
  616. /*++
  617. Routine Description:
  618. This function is called from an exception filter to copy the exception
  619. information from one exception record to another when an exception occurs.
  620. Arguments:
  621. ExceptionRecord1 - Supplies a pointer to the destination exception record.
  622. ExceptionRecord2 - Supplies a pointer to the source exception record.
  623. Return Value:
  624. A value of EXCEPTION_EXECUTE_HANDLER is returned as the function value.
  625. --*/
  626. {
  627. //
  628. // Copy one exception record to another and return value that causes
  629. // an exception handler to be executed.
  630. //
  631. RtlCopyMemory((PVOID)ExceptionRecord1,
  632. (PVOID)ExceptionRecord2,
  633. sizeof(EXCEPTION_RECORD));
  634. return EXCEPTION_EXECUTE_HANDLER;
  635. }
  636. NTSTATUS
  637. KeRaiseUserException (
  638. IN NTSTATUS ExceptionCode
  639. )
  640. /*++
  641. Routine Description:
  642. This function causes an exception to be raised in the calling thread's
  643. user context.
  644. Arguments:
  645. ExceptionCode - Supplies the status value to be raised.
  646. Return Value:
  647. The status value that should be returned by the caller.
  648. --*/
  649. {
  650. PTEB Teb;
  651. PKTHREAD Thread;
  652. PKTRAP_FRAME TrapFrame;
  653. //
  654. // Save the exception code in the TEB and set the return address in the
  655. // trap frame to return to the raise user exception code in user mode.
  656. // This replaces the normal return which would go to the system service
  657. // dispatch stub. The system service dispatch stub is called thus the
  658. // return to the system service call site is on the top of the user stack.
  659. //
  660. Thread = KeGetCurrentThread();
  661. TrapFrame = Thread->TrapFrame;
  662. if ((TrapFrame != NULL) &&
  663. ((TrapFrame->SegCs & MODE_MASK) == UserMode)) {
  664. Teb = (PTEB)Thread->Teb;
  665. try {
  666. Teb->ExceptionCode = ExceptionCode;
  667. } except (EXCEPTION_EXECUTE_HANDLER) {
  668. return ExceptionCode;
  669. }
  670. TrapFrame->Rip = (ULONG64)KeRaiseUserExceptionDispatcher;
  671. }
  672. return ExceptionCode;
  673. }