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.

146 lines
3.4 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. callback.c
  5. Abstract:
  6. This module implements user mode call back services.
  7. Author:
  8. David N. Cutler (davec) 5-Jul-2000
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. #pragma alloc_text(PAGE, KeUserModeCallback)
  15. NTSTATUS
  16. KeUserModeCallback (
  17. IN ULONG ApiNumber,
  18. IN PVOID InputBuffer,
  19. IN ULONG InputLength,
  20. OUT PVOID *OutputBuffer,
  21. IN PULONG OutputLength
  22. )
  23. /*++
  24. Routine Description:
  25. This function call out from kernel mode to a user mode function.
  26. Arguments:
  27. ApiNumber - Supplies the API number.
  28. InputBuffer - Supplies a pointer to a structure that is copied
  29. to the user stack.
  30. InputLength - Supplies the length of the input structure.
  31. Outputbuffer - Supplies a pointer to a variable that receives
  32. the address of the output buffer.
  33. Outputlength - Supplies a pointer to a variable that receives
  34. the length of the output buffer.
  35. Return Value:
  36. If the callout cannot be executed, then an error status is returned.
  37. Otherwise, the status returned by the callback function is returned.
  38. --*/
  39. {
  40. volatile ULONG BatchCount;
  41. PUCALLOUT_FRAME CalloutFrame;
  42. ULONG Length;
  43. ULONG64 OldStack;
  44. NTSTATUS Status;
  45. PKTRAP_FRAME TrapFrame;
  46. ASSERT(KeGetPreviousMode() == UserMode);
  47. //
  48. // Get the user mode stack pointer and attempt to copy input buffer
  49. // to the user stack.
  50. //
  51. TrapFrame = KeGetCurrentThread()->TrapFrame;
  52. OldStack = TrapFrame->Rsp;
  53. try {
  54. //
  55. // Compute new user mode stack address, probe for writability, and
  56. // copy the input buffer to the user stack.
  57. //
  58. Length = ((InputLength + STACK_ROUND) & ~STACK_ROUND) + UCALLOUT_FRAME_LENGTH;
  59. CalloutFrame = (PUCALLOUT_FRAME)((OldStack - Length) & ~STACK_ROUND);
  60. ProbeForWrite(CalloutFrame, Length, STACK_ALIGN);
  61. RtlCopyMemory(CalloutFrame + 1, InputBuffer, InputLength);
  62. //
  63. // Fill in callout arguments.
  64. //
  65. CalloutFrame->Buffer = (PVOID)(CalloutFrame + 1);
  66. CalloutFrame->Length = InputLength;
  67. CalloutFrame->ApiNumber = ApiNumber;
  68. CalloutFrame->MachineFrame.Rsp = OldStack;
  69. CalloutFrame->MachineFrame.Rip = TrapFrame->Rip;
  70. //
  71. // If an exception occurs during the probe of the user stack, then
  72. // always handle the exception and return the exception code as the
  73. // status value.
  74. //
  75. } except (EXCEPTION_EXECUTE_HANDLER) {
  76. return GetExceptionCode();
  77. }
  78. //
  79. // Call user mode.
  80. //
  81. TrapFrame->Rsp = (ULONG64)CalloutFrame;
  82. Status = KiCallUserMode(OutputBuffer, OutputLength);
  83. //
  84. // When returning from user mode, any drawing done to the GDI TEB
  85. // batch must be flushed.
  86. //
  87. // N.B. It is possible to fault while referencing the user TEB. If
  88. // a fault occurs, then always flush the batch count.
  89. //
  90. BatchCount = 1;
  91. try {
  92. BatchCount = ((PTEB)KeGetCurrentThread()->Teb)->GdiBatchCount;
  93. } except (EXCEPTION_EXECUTE_HANDLER) {
  94. NOTHING;
  95. }
  96. if (BatchCount > 0) {
  97. TrapFrame->Rsp -= 256;
  98. KeGdiFlushUserBatch();
  99. }
  100. TrapFrame->Rsp = OldStack;
  101. return Status;
  102. }