look as you see the function passage the last function to be executed is ZwTerminateProcess which is located in Kernel mode.
Now with that information, we can get started, every commercial AV (that I know of) operate all of the scanning from Kernel Mode (Ring0), using drivers, and ZwTerminateProcess also operates there as well this means that the AV drivers can hook those functions to the lowest level, what the hook does is return 0 or hide the command from the kernel for example say that the user (who is located in Ring3 (User-Land)) tries to terminate a process (AV process) the Terminate Process will pass the process name with the information to NtTerminateProcess and so on and when it finally reaches ZwTerminateProcess, there will be a "jmp" to the AV hook callback which would see the parameter and will react accordingly.
That is why AV process are protected, they tend to hook ZwOpenProcess - ZwTerminateProcess and few NT functions and other functions these protect the AV from being attacked and killed by malware.
Apart from protection they also help them detect Malware.
That is why you need to un-hook those functions, how well first you need to analyse the first 5 bytes of the function then create a stub then allocate it then call the real-function via the stub,
the function bytes would look like:
MOV EAX, <DWORD>
PUSH <RETURN ADDR>
so you need to re-assign the bytes to the stub in order to execute correct function.
Next question, the signal the windows does give is shutdown, lol and that is why all Anti-Viruses re-boot after installation because the drivers need to initialize and survive the reboot before they become attached to kernel.
The only way to kill access denied virus programs is to un-hook your own processes because these malware(s) tend to inject DLL\code into every process (apart from AV and Ring0 operated root kits and such because they have more privileges and get information first).
Therefore the virus blocks functions from being used such as NtOpenProcess and other NT functions or even ZW because they lie in same memory space but with less privileges , hoping the malware is operating in ring3.
Next even if you managed to call terminate function on them they will most likely take advantage of ACLS\DACLS therefore making it "harder" to kill them.
Next some have process persistence and other levels of persistence, there are so many protections a Malware will do to protect itself from removal and these are very hard to remove, there are few malware(s) which are easy to kill but few Malware programs are incredibly difficult to even detect such as Stuxnet which have a Digital Signatures which makes it very hard to remove.
As I said there other layers of protection integrated into the Malware, therefore TerminateProcess() is not only the function to kill malware, there are other ways.
The best way to kill Malwares in Ring3 is to hook at the lowest level of Ring3 which is KiFastSystemCall which is not only allows you to get access to every NT function without need of hooking every single export of ntdll.dll.
Although from my experience I can say that factoring all the data in one hook callback is a lot of work.