No to pytanie: czy chcesz to robić "w zgodzie z systemem" czy za
plecami? Jeśli za plecami, to upewnij się, że:
1. Przerwania są wyłączone przez cały czas obsługi Twojego.
2. Nie korzystasz z ŻADNYCH funkcji systemowych poza prostym RTL (np.
_snprintf, strcmp, _stricmp itp., ale już nie te operujące na Unicode)
3. Wszystko, z czego korzystasz (kod, dane), musi być w pamięci fizycznej.
Natomiast jeśli chcesz w zgodzie z systemem to najlepiej zamiast
hookować IDT użyj IoConnectInterrupt (czy jakoś tak) - to jest jedyna
"legalna" droga w NT.
Ostatecznie możesz zastosować poniższy prolog, który zapewni Ci
bezpieczne działanie w Ring-0 nawet przy włączonych przerwaniach. Na
pewno działa do miejsca w którym jest "...", to co dalej nie testowałem.
// Prolog, set up trap frame
pushad
pushfd
push fs
mov ebx, $30
mov fs, ebx ; podstawowa sprawa
sub esp, $50
mov ebp, esp
// Setup the exception frame to NULL
mov ebx, cs:[$FFDFF000]
mov dword ptr [$FFDFF000], -1
mov [ebp], ebx
// poniższe rzeczy są średnio użyteczne - niestety Microsoft musiał
// pozmieniać adresy w XP, np. KeGetPreviousMode używa teraz
// +0x140 nie +0x137.
// Save away the existing KSS EBP
mov esi, cs:[$ffdff124]
mov ebx, [esi + $128]
mov [ebp + 4], ebx
mov [esi + $128], ebp
// Save away the kernel time and the thread mode (kernel/user)
mov edi, [esi + $137]
mov [ebp + 8], edi
// Set the thread mode (kernel/user)
mov byte ptr [esi + $137], 1
sti
...
// Restore thread mode (kernel/user)
// znowu raczej trafiamy w co innego, ale mniejsza z tym ;)
mov byte ptr [esi + $137], 2
add esp, $50
pop fs
popfd
popad
iretd