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.

926 lines
23 KiB

  1. /*++
  2. Copyright (c) 1999-1998 Microsoft Corporation
  3. Module Name:
  4. suspend.c
  5. Abstract:
  6. This module implements CpuSuspendThread, CpuGetContext and CpuSetContext.
  7. Author:
  8. 14-Dec-1999 SamerA
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <stdio.h>
  16. #define _WX86CPUAPI_
  17. #include "wx86.h"
  18. #include "wx86nt.h"
  19. #include "wx86cpu.h"
  20. #include "cpuassrt.h"
  21. #ifdef MSCCPU
  22. #include "ccpu.h"
  23. #include "msccpup.h"
  24. #undef GET_BYTE
  25. #undef GET_SHORT
  26. #undef GET_LONG
  27. #else
  28. #include "threadst.h"
  29. #include "instr.h"
  30. #include "frag.h"
  31. ASSERTNAME;
  32. #endif
  33. #include "fragp.h"
  34. #include "cpunotif.h"
  35. VOID
  36. RemoteSuspendAtNativeCode (
  37. VOID);
  38. NTSTATUS
  39. CpupFreeSuspendMsg(
  40. PCPU_SUSPEND_MSG CpuSuspendMsg)
  41. /*++
  42. Routine Description:
  43. This routine frees the resources associated with the suspend message structure on
  44. the remote side.
  45. Arguments:
  46. CpuSuspendMsg - Address of Suspend message structure
  47. Return Value:
  48. NTSTATUS.
  49. --*/
  50. {
  51. SIZE_T RegionSize;
  52. NtClose(CpuSuspendMsg->StartSuspendCallEvent);
  53. NtClose(CpuSuspendMsg->EndSuspendCallEvent);
  54. RegionSize = sizeof(*CpuSuspendMsg);
  55. NtFreeVirtualMemory(NtCurrentProcess(),
  56. &CpuSuspendMsg,
  57. &RegionSize,
  58. MEM_RELEASE);
  59. return STATUS_SUCCESS;
  60. }
  61. VOID
  62. CpupSuspendAtNativeCode(
  63. PCONTEXT Context,
  64. PCPU_SUSPEND_MSG SuspendMsg)
  65. /*++
  66. Routine Description:
  67. Prepares the current to get suspended. This routine is executed as a result
  68. of calling RtlRemoteCall on this current thread. This routine will
  69. update the CPUCONTEXT of the current thread with the passed SuspendM Message
  70. and notify the CPU that the current thread needs to be suspended.
  71. This routine must call NtContinue at the end to continue execution at
  72. the point where it has been interrupted.
  73. NOTE : Any change to the parameter list of this function must accompany
  74. a change to the RtlRemoteCall in CpuSuspendThread() and
  75. RemoteSuspendAtNativeCode().
  76. Arguments:
  77. Context - Context to return to execute at
  78. SuspendMsg - Suspend message address
  79. Return Value:
  80. NONE
  81. --*/
  82. {
  83. DECLARE_CPU;
  84. InterlockedCompareExchangePointer(&cpu->SuspendMsg,
  85. SuspendMsg,
  86. NULL);
  87. if (cpu->SuspendMsg == SuspendMsg)
  88. {
  89. cpu->CpuNotify |= CPUNOTIFY_SUSPEND;
  90. }
  91. else
  92. {
  93. CpupFreeSuspendMsg(SuspendMsg);
  94. }
  95. if (Context)
  96. {
  97. NtContinue(Context,FALSE);
  98. }
  99. CPUASSERT(FALSE);
  100. return;
  101. }
  102. NTSTATUS
  103. CpupSuspendCurrentThread(
  104. VOID)
  105. /*++
  106. Routine Description:
  107. This routine is called from the main CPU loop after leaving the translation cache,
  108. and start running native code.
  109. Now it's the best time to suspend the currently executing thread.
  110. Arguments:
  111. None.
  112. Return Value:
  113. NTSTATUS.
  114. --*/
  115. {
  116. NTSTATUS NtStatus;
  117. LARGE_INTEGER TimeOut;
  118. PCPU_SUSPEND_MSG CpuSuspendMsg;
  119. SIZE_T RegionSize;
  120. DECLARE_CPU;
  121. CpuSuspendMsg = cpu->SuspendMsg;
  122. NtStatus = NtSetEvent(CpuSuspendMsg->StartSuspendCallEvent, NULL);
  123. if (NT_SUCCESS(NtStatus))
  124. {
  125. TimeOut.QuadPart = UInt32x32To64( 40000, 10000 );
  126. TimeOut.QuadPart *= -1;
  127. NtStatus = NtWaitForSingleObject(CpuSuspendMsg->EndSuspendCallEvent,
  128. FALSE,
  129. &TimeOut);
  130. }
  131. else
  132. {
  133. LOGPRINT((TRACELOG, "CpupSuspendCurrentThread: Couldn't signal Start suspendcall event (%lx) -%lx\n",
  134. CpuSuspendMsg->StartSuspendCallEvent, NtStatus));
  135. }
  136. CpupFreeSuspendMsg(CpuSuspendMsg);
  137. cpu->SuspendMsg = NULL;
  138. return NtStatus;
  139. }
  140. NTSTATUS CpupReadBuffer(
  141. IN HANDLE ProcessHandle,
  142. IN PVOID Source,
  143. OUT PVOID Destination,
  144. IN ULONG Size)
  145. /*++
  146. Routine Description:
  147. This routine reads the source buffer into the destination buffer. It
  148. optimizes calls to NtReadVirtualMemory by checking whether the
  149. source buffer is in the currnt process or not.
  150. Arguments:
  151. ProcessHandle - Target process handle to read data from
  152. Source - Target base address to read data from
  153. Destination - Address of buffer to receive data read from the specified address space
  154. Size - Size of data to read
  155. Return Value:
  156. NTSTATUS.
  157. --*/
  158. {
  159. NTSTATUS NtStatus = STATUS_SUCCESS;
  160. return NtReadVirtualMemory(ProcessHandle,
  161. Source,
  162. Destination,
  163. Size,
  164. NULL);
  165. }
  166. NTSTATUS
  167. CpupWriteBuffer(
  168. IN HANDLE ProcessHandle,
  169. IN PVOID Target,
  170. IN PVOID Source,
  171. IN ULONG Size)
  172. /*++
  173. Routine Description:
  174. Writes data to memory taken into consideration if the write is cross-process
  175. or not
  176. Arguments:
  177. ProcessHandle - Target process handle to write data into
  178. Target - Target base address to write data at
  179. Source - Address of contents to write in the specified address space
  180. Size - Size of data to write
  181. Return Value:
  182. NTSTATUS.
  183. --*/
  184. {
  185. return NtWriteVirtualMemory(ProcessHandle,
  186. Target,
  187. Source,
  188. Size,
  189. NULL);
  190. }
  191. NTSTATUS
  192. CpupSetupSuspendCallParamters(
  193. IN HANDLE RemoteProcessHandle,
  194. IN PCPU_SUSPEND_MSG SuspendMsg,
  195. OUT PVOID *Arguments)
  196. /*++
  197. Routine Description:
  198. This routine setup the arguments for the remoted call to
  199. CpupSuspendAtNativeCode.
  200. Arguments:
  201. RemoteProcessHandle - Handle of process to setup the arguments in
  202. SuspendMsg - Suspend message to remote to the target process
  203. Arguments - Pointer to an array of parameters
  204. Return Value:
  205. NTSTATUS.
  206. --*/
  207. {
  208. NTSTATUS NtStatus = STATUS_SUCCESS;
  209. CPU_SUSPEND_MSG RemoteSuspendMsg;
  210. SIZE_T RegionSize;
  211. NtStatus = NtDuplicateObject(NtCurrentProcess(),
  212. SuspendMsg->StartSuspendCallEvent,
  213. RemoteProcessHandle,
  214. &RemoteSuspendMsg.StartSuspendCallEvent,
  215. 0,
  216. 0,
  217. DUPLICATE_SAME_ACCESS);
  218. if (!NT_SUCCESS(NtStatus))
  219. {
  220. LOGPRINT((ERRORLOG, "CpupSetupSuspendCallParamters: Couldn't duplicate event (%lx) into %lx -%lx\n",
  221. SuspendMsg->StartSuspendCallEvent, RemoteProcessHandle, NtStatus));
  222. return NtStatus;
  223. }
  224. NtStatus = NtDuplicateObject(NtCurrentProcess(),
  225. SuspendMsg->EndSuspendCallEvent,
  226. RemoteProcessHandle,
  227. &RemoteSuspendMsg.EndSuspendCallEvent,
  228. 0,
  229. 0,
  230. DUPLICATE_SAME_ACCESS);
  231. if (!NT_SUCCESS(NtStatus))
  232. {
  233. LOGPRINT((ERRORLOG, "CpupSetupSuspendCallParamters: Couldn't duplicate event (%lx) into %lx -%lx\n",
  234. SuspendMsg->EndSuspendCallEvent, RemoteProcessHandle, NtStatus));
  235. return NtStatus;
  236. }
  237. RegionSize = sizeof(RemoteSuspendMsg);
  238. *Arguments = NULL;
  239. NtStatus = NtAllocateVirtualMemory(RemoteProcessHandle,
  240. Arguments,
  241. 0,
  242. &RegionSize,
  243. MEM_RESERVE | MEM_COMMIT,
  244. PAGE_READWRITE);
  245. if (NT_SUCCESS(NtStatus))
  246. {
  247. NtStatus = NtWriteVirtualMemory(RemoteProcessHandle,
  248. *Arguments,
  249. &RemoteSuspendMsg,
  250. sizeof(RemoteSuspendMsg),
  251. NULL);
  252. if (!NT_SUCCESS(NtStatus))
  253. {
  254. LOGPRINT((ERRORLOG, "CpupSetupSuspendCallParamters: Couldn't write parameters in target process (%lx) -%lx\n",
  255. RemoteProcessHandle,NtStatus));
  256. NtFreeVirtualMemory(RemoteProcessHandle,
  257. Arguments,
  258. &RegionSize,
  259. MEM_RELEASE);
  260. }
  261. }
  262. else
  263. {
  264. LOGPRINT((ERRORLOG, "CpupSetupSuspendCallParamters: Couldn't allocate parameters space in target process (%lx) -%lx\n",
  265. RemoteProcessHandle,NtStatus));
  266. }
  267. return NtStatus;
  268. }
  269. NTSTATUS
  270. CpuSuspendThread(
  271. IN HANDLE ThreadHandle,
  272. IN HANDLE ProcessHandle,
  273. IN PTEB Teb,
  274. OUT PULONG PreviousSuspendCount OPTIONAL)
  275. /*++
  276. Routine Description:
  277. This routine is entered while the target thread is actually suspended, however, it's
  278. not known if the target thread is in a consistent state relative to
  279. the CPU. This routine guarantees that the target thread to suspend isn't the
  280. currently executing thread. It will establish a handshake protocol to suspend the
  281. target thread at a consistent cpu state.
  282. Arguments:
  283. ThreadHandle - Handle of target thread to suspend
  284. ProcessHandle - Handle of target thread's process
  285. Teb - Address of the target thread's TEB
  286. PreviousSuspendCount - Previous suspend count
  287. Return Value:
  288. NTSTATUS.
  289. --*/
  290. {
  291. NTSTATUS NtStatus = STATUS_SUCCESS, WaitStatus;
  292. ULONG_PTR CpuSimulationFlag;
  293. CPU_SUSPEND_MSG CpuSuspendMsg;
  294. PVOID Arguments;
  295. LARGE_INTEGER TimeOut;
  296. CpuSuspendMsg.StartSuspendCallEvent = INVALID_HANDLE_VALUE;
  297. CpuSuspendMsg.EndSuspendCallEvent = INVALID_HANDLE_VALUE;
  298. //
  299. // Are we in CPU simulation
  300. //
  301. NtStatus = CpupReadBuffer(ProcessHandle,
  302. ((PCHAR)Teb + FIELD_OFFSET(TEB, TlsSlots[WOW64_TLS_INCPUSIMULATION])),
  303. &CpuSimulationFlag,
  304. sizeof(CpuSimulationFlag));
  305. if (!NT_SUCCESS(NtStatus))
  306. {
  307. LOGPRINT((ERRORLOG, "CpuSuspendThread: Couldn't read INCPUSIMULATION flag (%lx) -%lx\n",
  308. CpuSimulationFlag, NtStatus));
  309. goto Cleanup;
  310. }
  311. if (!CpuSimulationFlag)
  312. {
  313. LOGPRINT((TRACELOG, "CpuSuspendThread: Thread is not running simulated code, so leave it suspended (%lx)",
  314. ThreadHandle));
  315. goto Cleanup;
  316. }
  317. NtStatus = NtCreateEvent(&CpuSuspendMsg.StartSuspendCallEvent,
  318. EVENT_ALL_ACCESS,
  319. NULL,
  320. SynchronizationEvent,
  321. FALSE);
  322. if (!NT_SUCCESS(NtStatus))
  323. {
  324. LOGPRINT((ERRORLOG, "CpuSuspendThread: Couldn't create StartSuspendCallEvent -%lx\n",
  325. NtStatus));
  326. goto Cleanup;
  327. }
  328. NtStatus = NtCreateEvent(&CpuSuspendMsg.EndSuspendCallEvent,
  329. EVENT_ALL_ACCESS,
  330. NULL,
  331. SynchronizationEvent,
  332. FALSE);
  333. if (!NT_SUCCESS(NtStatus))
  334. {
  335. LOGPRINT((ERRORLOG, "CpuSuspendThread: Couldn't create EndSuspendCallEvent -%lx\n",
  336. NtStatus));
  337. goto Cleanup;
  338. }
  339. NtStatus = CpupSetupSuspendCallParamters(ProcessHandle,
  340. &CpuSuspendMsg,
  341. &Arguments);
  342. if (NT_SUCCESS(NtStatus))
  343. {
  344. NtStatus = RtlRemoteCall(ProcessHandle,
  345. ThreadHandle,
  346. (PVOID)RemoteSuspendAtNativeCode,
  347. 1,
  348. (PULONG_PTR)&Arguments,
  349. TRUE,
  350. TRUE);
  351. if (NT_SUCCESS(NtStatus))
  352. {
  353. NtStatus = NtResumeThread(ThreadHandle, NULL);
  354. if (!NT_SUCCESS(NtStatus))
  355. {
  356. LOGPRINT((ERRORLOG, "CpuSuspendThread: Couldn't resume thread (%lx) -%lx\n",
  357. ThreadHandle, NtStatus));
  358. goto Cleanup;
  359. }
  360. TimeOut.QuadPart = UInt32x32To64( 20000, 10000 );
  361. TimeOut.QuadPart *= -1;
  362. WaitStatus = NtWaitForSingleObject(CpuSuspendMsg.StartSuspendCallEvent,
  363. FALSE,
  364. &TimeOut);
  365. NtStatus = NtSuspendThread(ThreadHandle, PreviousSuspendCount);
  366. if (!NT_SUCCESS(WaitStatus))
  367. {
  368. LOGPRINT((ERRORLOG, "CpuSuspendThread: Couldn't wait for StartSuspendCallEvent -%lx\n",
  369. NtStatus));
  370. goto Cleanup;
  371. }
  372. if (WaitStatus == STATUS_TIMEOUT)
  373. {
  374. LOGPRINT((ERRORLOG, "CpuSuspendThread: Timeout on StartSuspendCallEvent -%lx. Thread %lx may already be waiting.\n",
  375. NtStatus, ThreadHandle));
  376. }
  377. if (NT_SUCCESS(NtStatus))
  378. {
  379. NtSetEvent(CpuSuspendMsg.EndSuspendCallEvent, NULL);
  380. }
  381. }
  382. else
  383. {
  384. LOGPRINT((ERRORLOG, "CpuSuspendThread: RtlRemoteCall failed -%lx\n",
  385. NtStatus));
  386. }
  387. }
  388. Cleanup:
  389. ;
  390. if (CpuSuspendMsg.StartSuspendCallEvent != INVALID_HANDLE_VALUE)
  391. {
  392. NtClose(CpuSuspendMsg.StartSuspendCallEvent);
  393. }
  394. if (CpuSuspendMsg.EndSuspendCallEvent != INVALID_HANDLE_VALUE)
  395. {
  396. NtClose(CpuSuspendMsg.EndSuspendCallEvent);
  397. }
  398. return NtStatus;
  399. }
  400. NTSTATUS
  401. GetContextRecord(
  402. PCPUCONTEXT cpu,
  403. PCONTEXT_WX86 Context
  404. )
  405. /*++
  406. Routine Description:
  407. This routine extracts the context record out of the specified cpu context.
  408. Arguments:
  409. cpu - CPU context structure
  410. Context - Context record to fill
  411. Return Value:
  412. NTSTATUS.
  413. --*/
  414. {
  415. NTSTATUS NtStatus = STATUS_SUCCESS;
  416. ULONG ContextFlags;
  417. try
  418. {
  419. ContextFlags = Context->ContextFlags;
  420. if ((ContextFlags & CONTEXT_CONTROL_WX86) == CONTEXT_CONTROL_WX86)
  421. {
  422. Context->EFlags = GetEfl(cpu);
  423. Context->SegCs = CS;
  424. Context->Esp = esp;
  425. Context->SegSs = SS;
  426. Context->Ebp = ebp;
  427. Context->Eip = eip;
  428. //Context->Eip = cpu->eipReg.i4;
  429. }
  430. if ((ContextFlags & CONTEXT_SEGMENTS_WX86) == CONTEXT_SEGMENTS_WX86)
  431. {
  432. Context->SegGs = GS;
  433. Context->SegFs = FS;
  434. Context->SegEs = ES;
  435. Context->SegDs = DS;
  436. }
  437. if ((ContextFlags & CONTEXT_INTEGER_WX86) == CONTEXT_INTEGER_WX86)
  438. {
  439. Context->Eax = eax;
  440. Context->Ebx = ebx;
  441. Context->Ecx = ecx;
  442. Context->Edx = edx;
  443. Context->Edi = edi;
  444. Context->Esi = esi;
  445. }
  446. if ((ContextFlags & CONTEXT_FLOATING_POINT_WX86) == CONTEXT_FLOATING_POINT_WX86)
  447. {
  448. //
  449. // FpuSaveContext() is the same as FNSAVE, except FNSAVE resets the
  450. // FPU when its done.
  451. //
  452. CALLFRAG1(FpuSaveContext, (PBYTE)&Context->FloatSave);
  453. Context->FloatSave.Cr0NpxState = 1; // (Math Present)
  454. }
  455. // if ((ContextFlags & CONTEXT_DEBUG_WX86) == CONTEXT_DEBUG_WX86)
  456. // {
  457. // }
  458. }
  459. except (EXCEPTION_EXECUTE_HANDLER)
  460. {
  461. NtStatus = GetExceptionCode();
  462. }
  463. return NtStatus;
  464. }
  465. NTSTATUS
  466. CpupGetContextRecord(
  467. IN PCPUCONTEXT cpu,
  468. IN OUT PCONTEXT_WX86 Context)
  469. /*++
  470. Routine Description:
  471. This routine extracts the context record out of the specified cpu context.
  472. Arguments:
  473. cpu - CPU context structure
  474. Context - Context record to fill
  475. Return Value:
  476. NTSTATUS.
  477. --*/
  478. {
  479. return GetContextRecord(cpu, Context);
  480. }
  481. NTSTATUS
  482. MsCpuGetContext(
  483. IN OUT PCONTEXT_WX86 Context
  484. )
  485. /*++
  486. Routine Description:
  487. This routine extracts the context record for the currently
  488. executing thread.
  489. Arguments:
  490. Context - Context record to fill
  491. Return Value:
  492. NTSTATUS.
  493. --*/
  494. {
  495. DECLARE_CPU;
  496. return CpupGetContextRecord(cpu, Context);
  497. }
  498. NTSTATUS
  499. MsCpuGetContextThread(
  500. IN HANDLE ProcessHandle,
  501. IN PTEB Teb,
  502. IN OUT PCONTEXT_WX86 Context)
  503. /*++
  504. Routine Description:
  505. This routine extracts the context record of any thread. This is a generic routine.
  506. When entered, if the target thread isn't the currently executing thread, then it should be
  507. guaranteed that the target thread is suspended at a proper CPU state.
  508. Arguments:
  509. ProcessHandle - Open handle to the process that the thread runs in
  510. Teb - Pointer to the target's thread TEB
  511. optimization purposes.
  512. Context - Context record to fill
  513. Return Value:
  514. NTSTATUS.
  515. --*/
  516. {
  517. NTSTATUS NtStatus = STATUS_SUCCESS;
  518. PCPUCONTEXT CpuRemoteContext;
  519. CPUCONTEXT CpuContext;
  520. NtStatus = CpupReadBuffer(ProcessHandle,
  521. ((PCHAR)Teb + FIELD_OFFSET(TEB, TlsSlots[WOW64_TLS_CPURESERVED])),
  522. &CpuRemoteContext,
  523. sizeof(CpuRemoteContext));
  524. if (NT_SUCCESS(NtStatus))
  525. {
  526. NtStatus = CpupReadBuffer(ProcessHandle,
  527. CpuRemoteContext,
  528. &CpuContext,
  529. FIELD_OFFSET(CPUCONTEXT, FpData));
  530. if (NT_SUCCESS(NtStatus))
  531. {
  532. NtStatus = CpupGetContextRecord(&CpuContext, Context);
  533. }
  534. else
  535. {
  536. LOGPRINT((ERRORLOG, "MsCpuGetContextThread: Couldn't read CPU context %lx -%lx\n",
  537. CpuRemoteContext, NtStatus));
  538. }
  539. }
  540. else
  541. {
  542. LOGPRINT((ERRORLOG, "MsCpuGetContextThread: Couldn't read CPU context address-%lx\n",
  543. NtStatus));
  544. }
  545. return NtStatus;
  546. }
  547. NTSTATUS
  548. SetContextRecord(
  549. PCPUCONTEXT cpu,
  550. PCONTEXT_WX86 Context
  551. )
  552. /*++
  553. Routine Description:
  554. This routine sets the passed context record for the specified CPUCONTEXT.
  555. Arguments:
  556. cpu - CPU context structure
  557. Context - Context record to set
  558. Return Value:
  559. NTSTATUS.
  560. --*/
  561. {
  562. NTSTATUS NtStatus = STATUS_SUCCESS;
  563. ULONG ContextFlags;
  564. try
  565. {
  566. ContextFlags = Context->ContextFlags;
  567. if ((ContextFlags & CONTEXT_CONTROL_WX86) == CONTEXT_CONTROL_WX86)
  568. {
  569. SetEfl(cpu, Context->EFlags);
  570. CS = (USHORT)Context->SegCs;
  571. esp = Context->Esp;
  572. SS = (USHORT)Context->SegSs;
  573. ebp = Context->Ebp;
  574. eip = Context->Eip;
  575. #if MSCCPU
  576. eipTemp = Context->Eip;
  577. #endif
  578. }
  579. if ((ContextFlags & CONTEXT_SEGMENTS_WX86) == CONTEXT_SEGMENTS_WX86)
  580. {
  581. GS = (USHORT)Context->SegGs;
  582. FS = (USHORT)Context->SegFs;
  583. ES = (USHORT)Context->SegEs;
  584. DS = (USHORT)Context->SegDs;
  585. }
  586. if ((ContextFlags & CONTEXT_INTEGER_WX86) == CONTEXT_INTEGER_WX86)
  587. {
  588. eax = Context->Eax;
  589. ebx = Context->Ebx;
  590. ecx = Context->Ecx;
  591. edx = Context->Edx;
  592. edi = Context->Edi;
  593. esi = Context->Esi;
  594. }
  595. if ((ContextFlags & CONTEXT_FLOATING_POINT_WX86) == CONTEXT_FLOATING_POINT_WX86)
  596. {
  597. CALLFRAG1(FRSTOR, (PBYTE)&Context->FloatSave);
  598. // Ignore: Context->FloatSave.Cr0NpxState
  599. }
  600. // if ((ContextFlags & CONTEXT_DEBUG_WX86) == CONTEXT_DEBUG_WX86)
  601. // {
  602. // }
  603. }
  604. except (EXCEPTION_EXECUTE_HANDLER)
  605. {
  606. NtStatus = GetExceptionCode();
  607. }
  608. return NtStatus;
  609. }
  610. NTSTATUS
  611. CpupSetContextRecord(
  612. PCPUCONTEXT cpu,
  613. PCONTEXT_WX86 Context
  614. )
  615. /*++
  616. Routine Description:
  617. This routine sets the passed context record for the specified CPU.
  618. Arguments:
  619. cpu - CPU context structure
  620. Context - Context record to set
  621. Return Value:
  622. NTSTATUS.
  623. --*/
  624. {
  625. return SetContextRecord(cpu, Context);
  626. }
  627. NTSTATUS
  628. MsCpuSetContext(
  629. PCONTEXT_WX86 Context
  630. )
  631. /*++
  632. Routine Description:
  633. This routine sets the context record for the currently executing thread.
  634. Arguments:
  635. Context - Context record to fill
  636. Return Value:
  637. NTSTATUS.
  638. --*/
  639. {
  640. DECLARE_CPU;
  641. return CpupSetContextRecord(cpu, Context);
  642. }
  643. NTSTATUS
  644. MsCpuSetContextThread(
  645. IN HANDLE ProcessHandle,
  646. IN PTEB Teb,
  647. IN OUT PCONTEXT_WX86 Context)
  648. /*++
  649. Routine Description:
  650. This routine sets the context record of any thread. This is a generic routine.
  651. When entered, if the target thread isn't the currently executing thread, then it should be
  652. guaranteed that the target thread is suspended at a proper CPU state.
  653. Arguments:
  654. ProcessHandle - Open handle to the process that the thread runs in
  655. Teb - Pointer to the target's thread TEB
  656. Context - Context record to set
  657. Return Value:
  658. NTSTATUS.
  659. --*/
  660. {
  661. NTSTATUS NtStatus = STATUS_SUCCESS;
  662. PCPUCONTEXT CpuRemoteContext;
  663. CPUCONTEXT CpuContext;
  664. NtStatus = CpupReadBuffer(ProcessHandle,
  665. ((PCHAR)Teb + FIELD_OFFSET(TEB, TlsSlots[WOW64_TLS_CPURESERVED])),
  666. &CpuRemoteContext,
  667. sizeof(CpuRemoteContext));
  668. if (NT_SUCCESS(NtStatus))
  669. {
  670. NtStatus = CpupReadBuffer(ProcessHandle,
  671. CpuRemoteContext,
  672. &CpuContext,
  673. FIELD_OFFSET(CPUCONTEXT, FpData));
  674. if (NT_SUCCESS(NtStatus))
  675. {
  676. NtStatus = CpupSetContextRecord(&CpuContext, Context);
  677. if (NT_SUCCESS(NtStatus))
  678. {
  679. NtStatus = CpupWriteBuffer(ProcessHandle,
  680. CpuRemoteContext,
  681. &CpuContext,
  682. FIELD_OFFSET(CPUCONTEXT, FpData));
  683. if (!NT_SUCCESS(NtStatus))
  684. {
  685. LOGPRINT((ERRORLOG, "MsCpuSetContextThread: Couldn't write CPU context %lx -%lx\n",
  686. CpuRemoteContext, NtStatus));
  687. }
  688. }
  689. }
  690. }
  691. else
  692. {
  693. LOGPRINT((ERRORLOG, "MsCpuSetContextThread: Couldn't read CPU context address-%lx\n",
  694. NtStatus));
  695. }
  696. return NtStatus;
  697. }