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.

156 lines
4.2 KiB

  1. /*++
  2. Copyright (c) 2000 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) 5-May-2000
  10. Environment:
  11. Kernel mode only, IRQL APC_LEVEL.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. VOID
  16. KiInitializeUserApc (
  17. IN PKEXCEPTION_FRAME ExceptionFrame,
  18. IN PKTRAP_FRAME TrapFrame,
  19. IN PKNORMAL_ROUTINE NormalRoutine,
  20. IN PVOID NormalContext,
  21. IN PVOID SystemArgument1,
  22. IN PVOID SystemArgument2
  23. )
  24. /*++
  25. Routine Description:
  26. This function is called to initialize the context for a user mode APC.
  27. Arguments:
  28. ExceptionFrame - Supplies a pointer to an exception frame.
  29. TrapFrame - Supplies a pointer to a trap frame.
  30. NormalRoutine - Supplies a pointer to the user mode APC routine.
  31. NormalContext - Supplies a pointer to the user context for the APC
  32. routine.
  33. SystemArgument1 - Supplies the first system supplied value.
  34. SystemArgument2 - Supplies the second system supplied value.
  35. Return Value:
  36. None.
  37. --*/
  38. {
  39. CONTEXT ContextRecord;
  40. EXCEPTION_RECORD ExceptionRecord;
  41. PMACHINE_FRAME MachineFrame;
  42. ULONG64 UserStack;
  43. //
  44. // Move machine state from trap and exception frames to the context frame.
  45. //
  46. ContextRecord.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
  47. KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextRecord);
  48. //
  49. // Transfer the context information to the user stack, initialize the
  50. // APC routine parameters, and modify the trap frame so execution will
  51. // continue in user mode at the user mode APC dispatch routine.
  52. //
  53. try {
  54. //
  55. // Compute address of aligned machine frame, compute address of
  56. // context record, and probe user stack for writeability.
  57. //
  58. MachineFrame =
  59. (PMACHINE_FRAME)((ContextRecord.Rsp - sizeof(MACHINE_FRAME)) & ~STACK_ROUND);
  60. UserStack = (ULONG64)MachineFrame - CONTEXT_LENGTH;
  61. ProbeForWriteSmallStructure((PVOID)UserStack,
  62. sizeof(MACHINE_FRAME) + CONTEXT_LENGTH,
  63. STACK_ALIGN);
  64. //
  65. // Fill in machine frame information.
  66. //
  67. MachineFrame->Rsp = ContextRecord.Rsp;
  68. MachineFrame->Rip = ContextRecord.Rip;
  69. //
  70. // Initialize the user APC parameters.
  71. //
  72. ContextRecord.P1Home = (ULONG64)NormalContext;
  73. ContextRecord.P2Home = (ULONG64)SystemArgument1;
  74. ContextRecord.P3Home = (ULONG64)SystemArgument2;
  75. ContextRecord.P4Home = (ULONG64)NormalRoutine;
  76. //
  77. // Copy context record to the user stack.
  78. //
  79. RtlCopyMemory((PVOID)UserStack, &ContextRecord, sizeof(CONTEXT));
  80. //
  81. // Set the address new stack pointer in the current trap frame and
  82. // the continuation address so control will be transfered to the user
  83. // APC dispatcher.
  84. //
  85. TrapFrame->Rsp = UserStack;
  86. TrapFrame->Rip = (ULONG64)KeUserApcDispatcher;
  87. } except (KiCopyInformation(&ExceptionRecord,
  88. (GetExceptionInformation())->ExceptionRecord)) {
  89. //
  90. // Lower the IRQL to PASSIVE_LEVEL, set the exception address to
  91. // the current program address, and raise an exception by calling
  92. // the exception dispatcher.
  93. //
  94. // N.B. The IRQL is lowered to PASSIVE_LEVEL to allow APC interrupts
  95. // during the dispatching of the exception. The current thread
  96. // will be terminated during the dispatching of the exception,
  97. // but lowering of the IRQL is required to enable the debugger
  98. // to obtain the context of the current thread.
  99. //
  100. KeLowerIrql(PASSIVE_LEVEL);
  101. ExceptionRecord.ExceptionAddress = (PVOID)(TrapFrame->Rip);
  102. KiDispatchException(&ExceptionRecord,
  103. ExceptionFrame,
  104. TrapFrame,
  105. UserMode,
  106. TRUE);
  107. }
  108. return;
  109. }