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.

326 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 2000 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. David N. Cutler (davec) 13-May-2000
  11. Revision History:
  12. --*/
  13. #include "ntrtlp.h"
  14. #if defined(NTOS_KERNEL_RUNTIME)
  15. #pragma alloc_text(PAGE, RtlInitializeContext)
  16. #pragma alloc_text(PAGE, RtlRemoteCall)
  17. #endif
  18. VOID
  19. RtlInitializeContext(
  20. IN HANDLE Process,
  21. OUT PCONTEXT Context,
  22. IN PVOID Parameter OPTIONAL,
  23. IN PVOID InitialPc OPTIONAL,
  24. IN PVOID InitialSp OPTIONAL
  25. )
  26. /*++
  27. Routine Description:
  28. This function initializes a context record so that it can be used in a
  29. subsequent call to create thread.
  30. Arguments:
  31. Process - Supplies a handle to the process in which a thread is being
  32. created.
  33. Context - Supplies a pointer to a context record.
  34. InitialPc - Supplies an initial program counter value.
  35. InitialSp - Supplies an initial stack pointer value.
  36. Return Value:
  37. STATUS_BAD_INITIAL_STACK is raised if initial stack pointer value is not
  38. properly aligned.
  39. --*/
  40. {
  41. RTL_PAGED_CODE();
  42. //
  43. // Check stack alignment.
  44. //
  45. if (((ULONG64)InitialSp & 0xf) != 0) {
  46. RtlRaiseStatus(STATUS_BAD_INITIAL_STACK);
  47. }
  48. //
  49. // Initialize the EFflags field.
  50. //
  51. Context->EFlags = EFLAGS_IF_MASK | EFLAGS_AC_MASK;
  52. //
  53. // Initialize the integer registers.
  54. //
  55. Context->Rax = 0L;
  56. Context->Rcx = 2L;
  57. Context->Rbx = 1L;
  58. Context->Rsp = (ULONG64)InitialSp;
  59. Context->Rbp = 0L;
  60. Context->Rsi = 4L;
  61. Context->Rdi = 5L;
  62. Context->R8 = 8;
  63. Context->R9 = 9;
  64. Context->R10 = 10;
  65. Context->R11 = 11;
  66. Context->R12 = 12;
  67. Context->R13 = 13;
  68. Context->R14 = 14;
  69. Context->R15 = 15;
  70. //
  71. // Initialize the floating registers.
  72. //
  73. Context->Xmm0.Low = 0;
  74. Context->Xmm0.High = 0;
  75. Context->Xmm1.Low = 1;
  76. Context->Xmm1.High = 1;
  77. Context->Xmm2.Low = 2;
  78. Context->Xmm2.High = 2;
  79. Context->Xmm3.Low = 3;
  80. Context->Xmm3.High = 3;
  81. Context->Xmm4.Low = 4;
  82. Context->Xmm4.High = 4;
  83. Context->Xmm5.Low = 5;
  84. Context->Xmm5.High = 5;
  85. Context->Xmm6.Low = 6;
  86. Context->Xmm6.High = 6;
  87. Context->Xmm7.Low = 7;
  88. Context->Xmm7.High = 7;
  89. Context->Xmm8.Low = 8;
  90. Context->Xmm8.High = 8;
  91. Context->Xmm9.Low = 9;
  92. Context->Xmm9.High = 9;
  93. Context->Xmm10.Low = 10;
  94. Context->Xmm10.High = 10;
  95. Context->Xmm11.Low = 11;
  96. Context->Xmm11.High = 11;
  97. Context->Xmm12.Low = 12;
  98. Context->Xmm12.High = 12;
  99. Context->Xmm13.Low = 13;
  100. Context->Xmm13.High = 13;
  101. Context->Xmm14.Low = 14;
  102. Context->Xmm14.High = 14;
  103. Context->Xmm15.Low = 15;
  104. Context->Xmm15.High = 15;
  105. Context->MxCsr = INITIAL_MXCSR;
  106. //
  107. // Initialize the lagacy floatin point.
  108. //
  109. Context->FltSave.ControlWord = 0x23f;
  110. Context->FltSave.StatusWord = 0;
  111. Context->FltSave.TagWord = 0xffff;
  112. Context->FltSave.ErrorOffset = 0;
  113. Context->FltSave.ErrorSelector = 0;
  114. Context->FltSave.ErrorOpcode = 0;
  115. Context->FltSave.DataOffset = 0;
  116. Context->FltSave.DataSelector = 0;
  117. //
  118. // Initialize the program counter.
  119. //
  120. Context->Rip = (ULONG64)InitialPc;
  121. //
  122. // Set context record flags.
  123. //
  124. Context->ContextFlags = CONTEXT_FULL;
  125. //
  126. // Set the initial context of the thread in a machine specific way.
  127. //
  128. Context->Rcx = (ULONG64)Parameter;
  129. //
  130. // Unique stamp to tell wow64 that this is an RtlCreateUserThread context
  131. // rather than BaseCreateThread context.
  132. //
  133. Context->R9 = 0xf0e0d0c0a0908070UI64;
  134. return;
  135. }
  136. NTSTATUS
  137. RtlRemoteCall(
  138. HANDLE Process,
  139. HANDLE Thread,
  140. PVOID CallSite,
  141. ULONG ArgumentCount,
  142. PULONG_PTR Arguments,
  143. BOOLEAN PassContext,
  144. BOOLEAN AlreadySuspended
  145. )
  146. /*++
  147. Routine Description:
  148. This function calls a procedure in another thread/process, using the
  149. system functins NtGetContext and NtSetContext. Parameters are passed
  150. to the target procedure via the nonvolatile registers ().
  151. Arguments:
  152. Process - Supplies an open handle to the target process.
  153. Thread - Supplies an open handle to the target thread within the target
  154. process.
  155. CallSite - Supplies the address of the procedure to call in the target
  156. process.
  157. ArgumentCount - Supplies the number of parameters to pass to the target
  158. procedure.
  159. Arguments - Supplies a pointer to the array of parameters to pass.
  160. PassContext - Supplies a boolean value that determines whether a parameter
  161. is to be passed that points to a context record.
  162. AlreadySuspended - Supplies a boolean value that determines whether the
  163. target thread is already in a suspended or waiting state.
  164. Return Value:
  165. Status - Status value
  166. --*/
  167. {
  168. CONTEXT Context;
  169. ULONG Index;
  170. ULONG64 NewSp;
  171. NTSTATUS Status;
  172. RTL_PAGED_CODE();
  173. //
  174. // Check if too many arguments are specified.
  175. //
  176. if (ArgumentCount > 4) {
  177. return STATUS_INVALID_PARAMETER;
  178. }
  179. //
  180. // If necessary, suspend the target thread before getting the thread's
  181. // current state.
  182. //
  183. if (AlreadySuspended == FALSE) {
  184. Status = NtSuspendThread(Thread, NULL);
  185. if (!NT_SUCCESS(Status)) {
  186. return Status;
  187. }
  188. }
  189. //
  190. // Get the current context of the target thread.
  191. //
  192. Context.ContextFlags = CONTEXT_FULL;
  193. Status = NtGetContextThread(Thread, &Context);
  194. if (!NT_SUCCESS(Status)) {
  195. if (AlreadySuspended == FALSE) {
  196. NtResumeThread(Thread, NULL);
  197. }
  198. return Status;
  199. }
  200. if (AlreadySuspended != FALSE) {
  201. Context.Rax = STATUS_ALERTED;
  202. }
  203. //
  204. // Write previous thread context into the stack of the target thread.
  205. //
  206. NewSp = Context.Rsp - sizeof(CONTEXT);
  207. Status = NtWriteVirtualMemory(Process,
  208. (PVOID)NewSp,
  209. &Context,
  210. sizeof(CONTEXT),
  211. NULL);
  212. if (!NT_SUCCESS(Status)) {
  213. if (AlreadySuspended == FALSE) {
  214. NtResumeThread(Thread, NULL);
  215. }
  216. return Status;
  217. }
  218. //
  219. // Pass the parameters to the target thread via the nonvolatile registers
  220. // R11-R15.
  221. //
  222. Context.Rsp = NewSp;
  223. if (PassContext != FALSE) {
  224. Context.R11 = NewSp;
  225. for (Index = 0; Index < ArgumentCount; Index += 1) {
  226. (&Context.R12)[Index] = Arguments[Index];
  227. }
  228. } else {
  229. for (Index = 0; Index < ArgumentCount; Index += 1) {
  230. (&Context.R11)[Index] = Arguments[Index];
  231. }
  232. }
  233. //
  234. // Set the address of the target code into RIP and set the thread context
  235. // to cause the target procedure to be executed.
  236. //
  237. Context.Rip = (ULONG64)CallSite;
  238. Status = NtSetContextThread(Thread, &Context);
  239. if (AlreadySuspended == FALSE) {
  240. NtResumeThread(Thread, NULL);
  241. }
  242. return Status;
  243. }