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.

238 lines
5.2 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. callback.c
  5. Abstract:
  6. This module implements stubs for the user mode call back services.
  7. Author:
  8. David N. Cutler (davec) 29-Oct-1994
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. NTSTATUS
  15. KeUserModeCallback (
  16. IN ULONG ApiNumber,
  17. IN PVOID InputBuffer,
  18. IN ULONG InputLength,
  19. OUT PVOID *OutputBuffer,
  20. IN PULONG OutputLength
  21. )
  22. /*++
  23. Routine Description:
  24. This function call out from kernel mode to a user mode function.
  25. Arguments:
  26. ApiNumber - Supplies the API number.
  27. InputBuffer - Supplies a pointer to a structure that is copied
  28. to the user stack.
  29. InputLength - Supplies the length of the input structure.
  30. Outputbuffer - Supplies a pointer to a variable that receives
  31. the address of the output buffer.
  32. Outputlength - Supplies a pointer to a variable that receives
  33. the length of the output buffer.
  34. Return Value:
  35. If the callout cannot be executed, then an error status is
  36. returned. Otherwise, the status returned by the callback function
  37. is returned.
  38. --*/
  39. {
  40. PUCALLOUT_FRAME CalloutFrame;
  41. ULONG Length;
  42. ULONGLONG OldStack;
  43. NTSTATUS Status;
  44. PKTRAP_FRAME TrapFrame;
  45. PVOID ValueBuffer;
  46. ULONG ValueLength;
  47. ASSERT(KeGetPreviousMode() == UserMode);
  48. //
  49. // Get the user mode stack pointer and attempt to copy input buffer
  50. // to the user stack.
  51. //
  52. TrapFrame = KeGetCurrentThread()->TrapFrame;
  53. OldStack = TrapFrame->IntSp;
  54. try {
  55. //
  56. // Compute new user mode stack address, probe for writability,
  57. // and copy the input buffer to the user stack.
  58. //
  59. // N.B. Alpha requires stacks to be 16-byte aligned, therefore
  60. // the input length must be rounded up to a 16-byte boundary.
  61. //
  62. Length = (InputLength +
  63. 16 - 1 + sizeof(UCALLOUT_FRAME)) & ~(16 - 1);
  64. CalloutFrame = (PUCALLOUT_FRAME)(OldStack - Length);
  65. ProbeForWrite(CalloutFrame, Length, sizeof(QUAD));
  66. RtlCopyMemory(CalloutFrame + 1, InputBuffer, InputLength);
  67. //
  68. // Allocate stack frame and fill in callout arguments.
  69. //
  70. CalloutFrame->Buffer = (PVOID)(CalloutFrame + 1);
  71. CalloutFrame->Length = InputLength;
  72. CalloutFrame->ApiNumber = ApiNumber;
  73. CalloutFrame->Sp = OldStack;
  74. CalloutFrame->Ra = TrapFrame->IntRa;
  75. //
  76. // If an exception occurs during the probe of the user stack, then
  77. // always handle the exception and return the exception code as the
  78. // status value.
  79. //
  80. } except (EXCEPTION_EXECUTE_HANDLER) {
  81. return GetExceptionCode();
  82. }
  83. //
  84. // Call user mode.
  85. //
  86. TrapFrame->IntSp = (ULONGLONG)(LONG_PTR)CalloutFrame;
  87. Status = KiCallUserMode(OutputBuffer, OutputLength);
  88. //
  89. // When returning from user mode, any drawing done to the GDI TEB
  90. // batch must be flushed.
  91. //
  92. if (((PTEB)KeGetCurrentThread()->Teb)->GdiBatchCount > 0) {
  93. TrapFrame->IntSp -= 256;
  94. KeGdiFlushUserBatch();
  95. }
  96. TrapFrame->IntSp = OldStack;
  97. return Status;
  98. }
  99. NTSTATUS
  100. NtW32Call (
  101. IN ULONG ApiNumber,
  102. IN PVOID InputBuffer,
  103. IN ULONG InputLength,
  104. OUT PVOID *OutputBuffer,
  105. OUT PULONG OutputLength
  106. )
  107. /*++
  108. Routine Description:
  109. This function calls a W32 function.
  110. Arguments:
  111. ApiNumber - Supplies the API number.
  112. InputBuffer - Supplies a pointer to a structure that is copied to
  113. the user stack.
  114. InputLength - Supplies the length of the input structure.
  115. Outputbuffer - Supplies a pointer to a variable that recevies the
  116. output buffer address.
  117. Outputlength - Supplies a pointer to a variable that recevies the
  118. output buffer length.
  119. Return Value:
  120. TBS.
  121. --*/
  122. {
  123. PVOID ValueBuffer;
  124. ULONG ValueLength;
  125. NTSTATUS Status;
  126. ASSERT(KeGetPreviousMode() == UserMode);
  127. //
  128. // If the current thread is not a GUI thread, then fail the service
  129. // since the thread does not have a large stack.
  130. //
  131. if (KeGetCurrentThread()->Win32Thread == (PVOID)&KeServiceDescriptorTable[0]) {
  132. return STATUS_NOT_IMPLEMENTED;
  133. }
  134. //
  135. // Probe the output buffer address and length for writeability.
  136. //
  137. try {
  138. ProbeForWriteUlong((PULONG)OutputBuffer);
  139. ProbeForWriteUlong(OutputLength);
  140. //
  141. // If an exception occurs during the probe of the output buffer or
  142. // length, then always handle the exception and return the exception
  143. // code as the status value.
  144. //
  145. } except(EXCEPTION_EXECUTE_HANDLER) {
  146. return GetExceptionCode();
  147. }
  148. //
  149. // Call out to user mode specifying the input buffer and API number.
  150. //
  151. Status = KeUserModeCallback(ApiNumber,
  152. InputBuffer,
  153. InputLength,
  154. &ValueBuffer,
  155. &ValueLength);
  156. //
  157. // If the callout is successful, then the output buffer address and
  158. // length.
  159. //
  160. if (NT_SUCCESS(Status)) {
  161. try {
  162. *OutputBuffer = ValueBuffer;
  163. *OutputLength = ValueLength;
  164. } except(EXCEPTION_EXECUTE_HANDLER) {
  165. }
  166. }
  167. return Status;
  168. }