clean up and standardize types across the codebase, unify atomic operations, improve UTF-8 handling throughout the system, remove obsolete input and named queue interfaces, redesign process preparation and creation, tighten IPC and service boundaries, improve error handling and reliability, minor documentation cleanup, fix doom surfaces, fix panic in ini parsing.
This commit is contained in:
1 parent
899225f551
commit
c0ad63c27f
226 files changed
+6562
-4147
No files matched your search
@@ -0,0 +1,138 @@
|
||||
// Native anonymous queue lifetime smoke test.
|
||||
// Verifies queue message delivery and survival through a derived handle.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
#define TEST_MESSAGE_TYPE 0x71756575u
|
||||
#define TEST_MESSAGE_VALUE 0x123456789abcdef0ull
|
||||
|
||||
typedef struct TEST_QUEUE_MESSAGE {
|
||||
uint32_t Type;
|
||||
uint32_t Flags;
|
||||
uint64_t Param[6];
|
||||
} TEST_QUEUE_MESSAGE;
|
||||
|
||||
typedef char TEST_QUEUE_MESSAGE_SIZE_CHECK[
|
||||
(sizeof(TEST_QUEUE_MESSAGE) == SYS_QUEUE_MESSAGE_SIZE) ? 1 : -1
|
||||
];
|
||||
|
||||
// Prints one NUL-terminated string to the kernel console.
|
||||
static void print(const char* s) {
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
|
||||
// Prints one unsigned integer to the kernel console.
|
||||
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 = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromParts(&c, 1) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
}
|
||||
|
||||
// Terminates the current test process.
|
||||
static void exit_now(int code) {
|
||||
while (true) SysExitProcess(code);
|
||||
}
|
||||
|
||||
// Fails the test with one plain message.
|
||||
static void fail(const char* msg) {
|
||||
print("anonymous_queue_smoke: ");
|
||||
print(msg);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Fails the test with one status value.
|
||||
static void fail_status(const char* what, KSTATUS status) {
|
||||
print("anonymous_queue_smoke: ");
|
||||
print(what);
|
||||
print(" status=");
|
||||
print_u64(status);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Sends one fixed-size queue message.
|
||||
static KSTATUS send_message(uint32_t queue, const TEST_QUEUE_MESSAGE* message) {
|
||||
SYS_QUEUE_SEND_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.QueueHandle = queue;
|
||||
req.Flags = SYS_QUEUE_FLAG_NONE;
|
||||
req.TimeoutMilliseconds = 0;
|
||||
req.Message = message;
|
||||
return SysSendQueue(&req);
|
||||
}
|
||||
|
||||
// Receives one fixed-size queue message.
|
||||
static uint32_t recv_message(uint32_t queue, TEST_QUEUE_MESSAGE* message) {
|
||||
SYS_QUEUE_RECV_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.QueueHandle = queue;
|
||||
req.Flags = SYS_QUEUE_FLAG_NONE;
|
||||
req.TimeoutMilliseconds = 0;
|
||||
req.MessageOut = message;
|
||||
return SysRecvQueue(&req);
|
||||
}
|
||||
|
||||
// Verifies aliases keep an anonymous queue alive after the original handle closes.
|
||||
static void check_alias_lifetime(void) {
|
||||
SYS_HANDLE queue = SYS_HANDLE_INVALID;
|
||||
SYS_HANDLE alias = SYS_HANDLE_INVALID;
|
||||
KSTATUS status = SysCreateQueue(&queue);
|
||||
if (!KSUCCESS(status)) fail_status("create queue", status);
|
||||
|
||||
SYS_HANDLE self = SYS_HANDLE_INVALID;
|
||||
status = SysOpenProcess(SysGetCurrentPid(), SYS_RIGHT_QUERY | SYS_PROCESS_RIGHT_INSERT_HANDLE, &self);
|
||||
if (!KSUCCESS(status)) fail_status("open self", status);
|
||||
SYS_DUPLICATE_HANDLE_REQUEST duplicate = {0};
|
||||
duplicate.Size = sizeof(duplicate);
|
||||
duplicate.SourceHandle = queue;
|
||||
duplicate.TargetProcessHandle = self;
|
||||
duplicate.DesiredRights = SYS_QUEUE_RIGHT_SEND | SYS_QUEUE_RIGHT_RECEIVE;
|
||||
duplicate.TargetHandleOut = &alias;
|
||||
status = SysDuplicateHandle(&duplicate);
|
||||
if (!KSUCCESS(status)) fail_status("duplicate queue", status);
|
||||
(void)SysCloseHandle(self);
|
||||
|
||||
TEST_QUEUE_MESSAGE out = {0};
|
||||
TEST_QUEUE_MESSAGE in = {0};
|
||||
out.Type = TEST_MESSAGE_TYPE;
|
||||
out.Param[0] = TEST_MESSAGE_VALUE;
|
||||
status = send_message(queue, &out);
|
||||
if (!KSUCCESS(status)) fail_status("send queue", status);
|
||||
status = SysCloseHandle(queue);
|
||||
if (!KSUCCESS(status)) fail_status("close original", status);
|
||||
status = recv_message(alias, &in);
|
||||
if (!KSUCCESS(status)) fail_status("recv via surviving alias", status);
|
||||
if (in.Type != TEST_MESSAGE_TYPE || in.Param[0] != TEST_MESSAGE_VALUE)
|
||||
fail("message corrupted");
|
||||
|
||||
status = recv_message(alias, &in);
|
||||
if (status != NTLSTATUS_WOULD_BLOCK) fail_status("empty queue", status);
|
||||
(void)SysCloseHandle(alias);
|
||||
}
|
||||
|
||||
// Runs the anonymous queue lifetime smoke test.
|
||||
int main(void) {
|
||||
print("anonymous_queue_smoke: start\n");
|
||||
check_alias_lifetime();
|
||||
print("anonymous_queue_smoke: PASS\n");
|
||||
exit_now(0);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user