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.

148 lines
3.8 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. apcuser.c
  5. Abstract:
  6. This module implements the machine dependent code necessary to initialize
  7. a user mode APC.
  8. Author:
  9. David N. Cutler (davec) 23-Apr-1990
  10. Environment:
  11. Kernel mode only, IRQL APC_LEVEL.
  12. Revision History:
  13. Thomas Van Baak (tvb) 13-May-1992
  14. Adapted for Alpha AXP.
  15. --*/
  16. #include "ki.h"
  17. VOID
  18. KiInitializeUserApc (
  19. IN PKEXCEPTION_FRAME ExceptionFrame,
  20. IN PKTRAP_FRAME TrapFrame,
  21. IN PKNORMAL_ROUTINE NormalRoutine,
  22. IN PVOID NormalContext,
  23. IN PVOID SystemArgument1,
  24. IN PVOID SystemArgument2
  25. )
  26. /*++
  27. Routine Description:
  28. This function is called to initialize the context for a user mode APC.
  29. Arguments:
  30. ExceptionFrame - Supplies a pointer to an exception frame.
  31. TrapFrame - Supplies a pointer to a trap frame.
  32. NormalRoutine - Supplies a pointer to the user mode APC routine.
  33. NormalContext - Supplies a pointer to the user context for the APC
  34. routine.
  35. SystemArgument1 - Supplies the first system supplied value.
  36. SystemArgument2 - Supplies the second system supplied value.
  37. Return Value:
  38. None.
  39. --*/
  40. {
  41. CONTEXT ContextRecord;
  42. EXCEPTION_RECORD ExceptionRecord;
  43. LONG_PTR Length;
  44. ULONG_PTR UserStack;
  45. //
  46. // Move the user mode state from the trap and exception frames to the
  47. // context frame.
  48. //
  49. ContextRecord.ContextFlags = CONTEXT_FULL;
  50. KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextRecord);
  51. //
  52. // Transfer the context information to the user stack, initialize the
  53. // APC routine parameters, and modify the trap frame so execution will
  54. // continue in user mode at the user mode APC dispatch routine.
  55. //
  56. try {
  57. //
  58. // Compute length of context record and new aligned user stack pointer.
  59. //
  60. Length = (sizeof(CONTEXT) + 15) & (~15);
  61. UserStack = ((ULONG_PTR)ContextRecord.IntSp & (~15)) - Length;
  62. //
  63. // Probe user stack area for writeability and then transfer the
  64. // context record to the user stack.
  65. //
  66. ProbeForWrite((PVOID)UserStack, (ULONG)Length, sizeof(QUAD));
  67. RtlMoveMemory((PVOID)UserStack, &ContextRecord, sizeof(CONTEXT));
  68. //
  69. // Set the address of the user APC routine, the APC parameters, the
  70. // new frame pointer, and the new stack pointer in the current trap
  71. // frame. Set the continuation address so control will be transferred
  72. // to the user APC dispatcher.
  73. //
  74. // N.B. It is not possible to pass 64 bit arguments to the routine.
  75. // N.B. ULONG becomes canonical longword with (ULONGLONG)(LONG) cast.
  76. //
  77. //
  78. TrapFrame->IntSp = (ULONGLONG)(LONG_PTR)UserStack;
  79. TrapFrame->IntFp = (ULONGLONG)(LONG_PTR)UserStack;
  80. TrapFrame->IntA0 = (ULONGLONG)(LONG_PTR)NormalContext;
  81. TrapFrame->IntA1 = (ULONGLONG)(LONG_PTR)SystemArgument1;
  82. TrapFrame->IntA2 = (ULONGLONG)(LONG_PTR)SystemArgument2;
  83. TrapFrame->IntA3 = (ULONGLONG)(LONG_PTR)NormalRoutine;
  84. TrapFrame->Fir = (ULONGLONG)(LONG_PTR)KeUserApcDispatcher;
  85. //
  86. // If an exception occurs, then copy the exception information to an
  87. // exception record and handle the exception.
  88. //
  89. } except (KiCopyInformation(&ExceptionRecord,
  90. (GetExceptionInformation())->ExceptionRecord)) {
  91. //
  92. // Set the address of the exception to the current program address
  93. // and raise the exception by calling the exception dispatcher.
  94. //
  95. ExceptionRecord.ExceptionAddress = (PVOID)(TrapFrame->Fir);
  96. KiDispatchException(&ExceptionRecord,
  97. ExceptionFrame,
  98. TrapFrame,
  99. UserMode,
  100. TRUE);
  101. }
  102. return;
  103. }