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.

263 lines
6.3 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. context.c
  5. Abstract:
  6. This module implements user-mode callable context manipulation routines.
  7. The interfaces exported from this module are portable, but they must
  8. be re-implemented for each architecture.
  9. Author:
  10. Mark Lucovsky (markl) 20-Jun-1989
  11. Revision History:
  12. Bryan Willman (bryanwi) 8-Mar-90
  13. Ported to the 80386
  14. --*/
  15. #include "ntrtlp.h"
  16. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  17. #pragma alloc_text(PAGE,RtlInitializeContext)
  18. #pragma alloc_text(PAGE,RtlRemoteCall)
  19. #endif
  20. VOID
  21. RtlInitializeContext(
  22. IN HANDLE Process,
  23. OUT PCONTEXT Context,
  24. IN PVOID Parameter OPTIONAL,
  25. IN PVOID InitialPc OPTIONAL,
  26. IN PVOID InitialSp OPTIONAL
  27. )
  28. /*++
  29. Routine Description:
  30. This function initializes a context structure so that it can
  31. be used in a subsequent call to NtCreateThread.
  32. Arguments:
  33. Context - Supplies a context buffer to be initialized by this routine.
  34. InitialPc - Supplies an initial program counter value.
  35. InitialSp - Supplies an initial stack pointer value.
  36. Return Value:
  37. Raises STATUS_BAD_INITIAL_STACK if the value of InitialSp is not properly
  38. aligned.
  39. Raises STATUS_BAD_INITIAL_PC if the value of InitialPc is not properly
  40. aligned.
  41. --*/
  42. {
  43. RTL_PAGED_CODE();
  44. Context->Eax = 0L;
  45. Context->Ebx = 1L;
  46. Context->Ecx = 2L;
  47. Context->Edx = 3L;
  48. Context->Esi = 4L;
  49. Context->Edi = 5L;
  50. Context->Ebp = 0L;
  51. Context->SegGs = 0;
  52. Context->SegFs = KGDT_R3_TEB;
  53. Context->SegEs = KGDT_R3_DATA;
  54. Context->SegDs = KGDT_R3_DATA;
  55. Context->SegSs = KGDT_R3_DATA;
  56. Context->SegCs = KGDT_R3_CODE;
  57. Context->EFlags = 0x200L; // force interrupts on, clear all else.
  58. //
  59. // Even though these are optional, they are used as is, since NULL
  60. // is what these would have been initialized to anyway
  61. //
  62. Context->Esp = (ULONG) InitialSp;
  63. Context->Eip = (ULONG) InitialPc;
  64. //
  65. // add code to check alignment and raise exception...
  66. //
  67. Context->ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS;
  68. //
  69. // Set the initial context of the thread in a machine specific way.
  70. // ie, pass the initial parameter to the start address
  71. //
  72. Context->Esp -= sizeof(Parameter);
  73. ZwWriteVirtualMemory(Process,
  74. (PVOID)Context->Esp,
  75. (PVOID)&Parameter,
  76. sizeof(Parameter),
  77. NULL);
  78. Context->Esp -= sizeof(Parameter); // Reserve room for ret address
  79. }
  80. NTSTATUS
  81. RtlRemoteCall(
  82. HANDLE Process,
  83. HANDLE Thread,
  84. PVOID CallSite,
  85. ULONG ArgumentCount,
  86. PULONG Arguments,
  87. BOOLEAN PassContext,
  88. BOOLEAN AlreadySuspended
  89. )
  90. /*++
  91. Routine Description:
  92. This function calls a procedure in another thread/process, using
  93. NtGetContext and NtSetContext. Parameters are passed to the
  94. target procedure via its stack.
  95. Arguments:
  96. Process - Handle of the target process
  97. Thread - Handle of the target thread within that process
  98. CallSite - Address of the procedure to call in the target process.
  99. ArgumentCount - Number of 32 bit parameters to pass to the target
  100. procedure.
  101. Arguments - Pointer to the array of 32 bit parameters to pass.
  102. PassContext - TRUE if an additional parameter is to be passed that
  103. points to a context record.
  104. AlreadySuspended - TRUE if the target thread is already in a suspended
  105. or waiting state.
  106. Return Value:
  107. Status - Status value
  108. --*/
  109. {
  110. NTSTATUS Status;
  111. CONTEXT Context;
  112. ULONG NewSp;
  113. ULONG ArgumentsCopy[5];
  114. RTL_PAGED_CODE();
  115. if (ArgumentCount > 4)
  116. return STATUS_INVALID_PARAMETER;
  117. //
  118. // If necessary, suspend the guy before with we mess with his stack.
  119. //
  120. if (!AlreadySuspended) {
  121. Status = NtSuspendThread( Thread, NULL );
  122. if (!NT_SUCCESS( Status )) {
  123. return( Status );
  124. }
  125. }
  126. //
  127. // Get the context record for the target thread.
  128. //
  129. Context.ContextFlags = CONTEXT_FULL;
  130. Status = NtGetContextThread( Thread, &Context );
  131. if (!NT_SUCCESS( Status )) {
  132. if (!AlreadySuspended) {
  133. NtResumeThread( Thread, NULL );
  134. }
  135. return( Status );
  136. }
  137. //
  138. // Pass all parameters on the stack, regardless of whether a
  139. // a context record is passed.
  140. //
  141. //
  142. // Put Context Record on stack first, so it is above other args.
  143. //
  144. NewSp = Context.Esp;
  145. if (PassContext) {
  146. NewSp -= sizeof( CONTEXT );
  147. Status = NtWriteVirtualMemory( Process,
  148. (PVOID)NewSp,
  149. &Context,
  150. sizeof( CONTEXT ),
  151. NULL
  152. );
  153. if (!NT_SUCCESS( Status )) {
  154. if (!AlreadySuspended) {
  155. NtResumeThread( Thread, NULL );
  156. }
  157. return( Status );
  158. }
  159. ArgumentsCopy[0] = NewSp; // pass pointer to context
  160. RtlCopyMemory(&(ArgumentsCopy[1]),Arguments,ArgumentCount*sizeof( ULONG ));
  161. ArgumentCount++;
  162. }
  163. else {
  164. RtlCopyMemory(ArgumentsCopy,Arguments,ArgumentCount*sizeof( ULONG ));
  165. }
  166. //
  167. // Copy the arguments onto the target stack
  168. //
  169. if (ArgumentCount) {
  170. NewSp -= ArgumentCount * sizeof( ULONG );
  171. Status = NtWriteVirtualMemory( Process,
  172. (PVOID)NewSp,
  173. ArgumentsCopy,
  174. ArgumentCount * sizeof( ULONG ),
  175. NULL
  176. );
  177. if (!NT_SUCCESS( Status )) {
  178. if (!AlreadySuspended) {
  179. NtResumeThread( Thread, NULL );
  180. }
  181. return( Status );
  182. }
  183. }
  184. //
  185. // Set the address of the target code into Eip, the new target stack
  186. // into Esp, and reload context to make it happen.
  187. //
  188. Context.Esp = NewSp;
  189. Context.Eip = (ULONG)CallSite;
  190. Status = NtSetContextThread( Thread, &Context );
  191. if (!AlreadySuspended) {
  192. NtResumeThread( Thread, NULL );
  193. }
  194. return( Status );
  195. }