On Mon Jan 1 12:20:35 2024 +0000, Dāvis Mosāns (davispuh) wrote:
I don't understand this, why we need `NtTestAlert()` when `NtContinue()` should already do that...
You're correct that `NtContinue()` indeed already tests for the alerts.
There's something you've missed, though: `NtContinue` is only called when there is a pending [APC][], which is usually not the case if you're calling it directly outside of an APC. In fact, the heavy lifting here is done by `pBTCpuSetContext` alone.
You're looking at an "emulator," called WoW64[^fname]. WoW64 works by switching[^hg] between 32bit mode and 64bit mode in the [user space][]. The 32bit guest app uses `I386_CONTEXT`, while the host process uses `AMD64_CONTEXT`. This means two things:
1. `NtContinue` here will accept host `CONTEXT`, which is synonymous with `AMD64_CONTEXT`. Therefore, this cannot be used to restore 32bit guest context. 2. `pBTCpuSetContext` is actually responsible for setting the 32bit guest context. After this context is set, the next 64bit-to-32bit transition[^hg] will restore this guest context.
Note that `frame == NULL` in the usual case (no APC pending), which means that `NtTestAlert` is still needed. If `frame != NULL`, then `NtContinue` (which is a "noreturn" function) will continue executing from the context, which means the `NtTestAlert()` below is not executed at all.
[^fname]: This is evident in the filename, `dlls/wow64/syscall.c`. [^hg]: This is made possible by x86 far jump which can switch from 64-bit code segment to a 32-bit code segment, and vice versa. This technique is also known as "Heaven's Gate."
[APC]: https://en.wikipedia.org/wiki/Asynchronous_procedure_call [user space]: https://en.wikipedia.org/wiki/User_space_and_kernel_space