implement user mode catchable exceptions, refactor system status codes to use NTLSTATUS_ prefix, update build scripts to use shared literal macros for linker arguments, update named queue lifetime cleanup to include KeNamedQueueUnpublishHandle.
This commit is contained in:
1 parent
1f5477cf66
commit
b7fcfce6f7
140 files changed
+7649
-3943
No files matched your search
@@ -0,0 +1,143 @@
|
||||
// Native user-raised exception smoke test.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <ntlite/exception.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
#define SMOKE_EXCEPTION_CODE 0xE1111001u
|
||||
|
||||
static volatile uint32_t gHandlerHits;
|
||||
|
||||
// Prints one NUL-terminated string to the kernel console.
|
||||
static void print(const char* s) {
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
|
||||
// Prints one unsigned integer.
|
||||
static void print_u64(uint64_t v) {
|
||||
char buf[32];
|
||||
int i = 0;
|
||||
if (v == 0) {
|
||||
print("0");
|
||||
return;
|
||||
}
|
||||
while (v && i < (int)sizeof(buf)) {
|
||||
buf[i++] = (char)('0' + (v % 10));
|
||||
v /= 10;
|
||||
}
|
||||
while (i--) {
|
||||
char c = buf[i];
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
}
|
||||
|
||||
// Terminates the current process.
|
||||
static void exit_now(int32_t code) {
|
||||
for (;;) SysExitProcess(code);
|
||||
}
|
||||
|
||||
// Fails the test with one message.
|
||||
static void fail(const char* message) {
|
||||
print("native_raise_exception_smoke: ");
|
||||
print(message);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Fails the test with one status value.
|
||||
static void fail_status(const char* what, uint32_t status) {
|
||||
print("native_raise_exception_smoke: ");
|
||||
print(what);
|
||||
print(" status=");
|
||||
print_u64(status);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Requires one syscall to return the expected status.
|
||||
static void expect_status(const char* what, uint32_t got, uint32_t expected) {
|
||||
if (got != expected) {
|
||||
print("native_raise_exception_smoke: ");
|
||||
print(what);
|
||||
print(" expected=");
|
||||
print_u64(expected);
|
||||
print(" got=");
|
||||
print_u64(got);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Reads aggregate exception counters.
|
||||
static void query_exception_stats(SYS_EXCEPTION_STATS* out) {
|
||||
uint32_t status = SysQueryKernelStats(SYS_KERNEL_STATS_EXCEPTION, out, sizeof(*out), 0);
|
||||
expect_status("query exception stats", status, NTLSTATUS_SUCCESS);
|
||||
if (out->Size != sizeof(*out) || out->Version != SYS_STATS_VERSION)
|
||||
fail("exception stats ABI mismatch");
|
||||
}
|
||||
|
||||
// Handles the user-raised exception and verifies its native record payload.
|
||||
static int smoke_handler(SYS_EXCEPTION_RECORD* record, SYS_USER_CONTEXT* context, void* userContext) {
|
||||
if (userContext != (void*)(uintptr_t)0x111E)
|
||||
fail("handler context mismatch");
|
||||
if (!record || !context)
|
||||
fail("handler received null records");
|
||||
if (record->Code != SMOKE_EXCEPTION_CODE)
|
||||
fail("handler received wrong exception code");
|
||||
if ((record->Flags & SYS_EXCEPTION_FLAG_FIRST_CHANCE) == 0)
|
||||
fail("handler missing first-chance flag");
|
||||
if (record->Flags & SYS_EXCEPTION_FLAG_NONCONTINUABLE)
|
||||
fail("handler received unexpected noncontinuable flag");
|
||||
if (record->ParameterCount != 2)
|
||||
fail("handler received wrong parameter count");
|
||||
if (record->Parameters[0] != 0x12345678u || record->Parameters[1] != 0xABCDEF00u)
|
||||
fail("handler received wrong parameters");
|
||||
if (!context->Rip || !context->Rsp)
|
||||
fail("handler received empty context");
|
||||
|
||||
gHandlerHits++;
|
||||
return NTL_EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
print("native_raise_exception_smoke: start\n");
|
||||
|
||||
SYS_EXCEPTION_STATS before;
|
||||
SYS_EXCEPTION_STATS after;
|
||||
query_exception_stats(&before);
|
||||
|
||||
void* handle = NtlAddExceptionHandler(1, smoke_handler, (void*)(uintptr_t)0x111E);
|
||||
if (!handle)
|
||||
fail("failed to add native exception handler");
|
||||
|
||||
uint64_t args[2] = { 0x12345678u, 0xABCDEF00u };
|
||||
SYS_RAISE_EXCEPTION_REQUEST request;
|
||||
request.Size = sizeof(request);
|
||||
request.Flags = SYS_RAISE_EXCEPTION_FLAG_NONE;
|
||||
request.Code = SMOKE_EXCEPTION_CODE;
|
||||
request.ParameterCount = 2;
|
||||
request.Parameters = args;
|
||||
|
||||
uint32_t status = SysRaiseException(&request);
|
||||
expect_status("raise exception", status, NTLSTATUS_SUCCESS);
|
||||
if (gHandlerHits != 1)
|
||||
fail("handler was not called exactly once");
|
||||
|
||||
status = NtlRemoveExceptionHandler(handle);
|
||||
expect_status("remove native exception handler", status, NTLSTATUS_SUCCESS);
|
||||
|
||||
query_exception_stats(&after);
|
||||
if (after.Delivered < before.Delivered + 1 ||
|
||||
after.UserRaised < before.UserRaised + 1 ||
|
||||
after.Continued < before.Continued + 1)
|
||||
fail("exception counters did not advance");
|
||||
if (after.LastCode != SMOKE_EXCEPTION_CODE)
|
||||
fail("last exception code was not updated");
|
||||
|
||||
print("native_raise_exception_smoke: PASS\n");
|
||||
exit_now(0);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user