As far as I understand, the purpose of Zw calls is to perform the following:
set the previous mode to KernelMode
invoke the system service
restore the previous mode
This question can be divided to multiple sub-questions:
Why do Zw calls go through the SSDT? The address can be hardcoded into the Zw stub
Why do Zw calls create a new trap frame?
My best guess to this is: Because the Zw stub needs to run code after the system service (the code that restores the previous mode) it needs to copy the arguments of the caller. KiSystemService already has this functionality (via KiArgumentTable)… This still does not explain why it allocates a new trap frame though. I know specific services like NtRaiseException require a trap frame, maybe that’s the reason…?
I’m asking this out of curiosity and for my understanding of Zw calls, Thanks for answering!
Zw calls work from user mode OR kernel mode. They actually set the previous mode to… whatever the previous mode actually WAS. This is different to the Nt calls that ARE direct calls that leave the previous mode unchanged.
Zw calls work from user mode OR kernel mode. They actually set the previous mode to… > whatever the previous mode actually WAS.
Maybe my question was unclear… I’m talking only about kernel mode here. Undoubtedly if ZwCreateFile is called and CurrentThread->PreviousMode == UserMode, the PreviousMode will be changed to ‘KernelMode’ during the NtCreateFile call as can be seen in the following experiment:
I’m aware that the previous mode is restored after NtCreateFile finishes running to the value is was before the ZwCreateFile call, which in this case is UserMode.
The question was: why do we need a new trap frame and also why does ZwCreateFile go through the SSDT?