replace ad hoc driver loading with a proper driver manager, new DDK, new PnP manager with device matching, asynchronous startup, resource ownership and removal, add shared PCI capability helpers, replace typed, rigid services with a proper service manager, implement proper system shutdown and restart, shutting down unloads drivers and shuts down services, add simple power button, remove heavyweight boot self-tests and SMP stress runs, add monotonic timestamps to kernel debug output, fruitless USB and PS/2 fixes, make test builds opt in.
This commit is contained in:
1 parent
c0ad63c27f
commit
d36f19509c
160 files changed
+6563
-7366
No files matched your search
@@ -0,0 +1,197 @@
|
||||
// Native named queue lifetime smoke test.
|
||||
// Verifies explicit name withdrawal and automatic withdrawal on owner handle close.
|
||||
|
||||
#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("named_queue_lifetime_smoke: ");
|
||||
print(msg);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Fails the test with one status value.
|
||||
static void fail_status(const char* what, uint32_t status) {
|
||||
print("named_queue_lifetime_smoke: ");
|
||||
print(what);
|
||||
print(" status=");
|
||||
print_u64(status);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Requires one exact status value.
|
||||
static void expect_status(const char* what, uint32_t got, uint32_t expected) {
|
||||
if (got == expected) return;
|
||||
print("named_queue_lifetime_smoke: ");
|
||||
print(what);
|
||||
print(" got=");
|
||||
print_u64(got);
|
||||
print(" expected=");
|
||||
print_u64(expected);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Publishes one queue under a short test name.
|
||||
static uint32_t publish_queue(const char* name, uint32_t queue) {
|
||||
SYS_PUBLISH_QUEUE_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Name = SysSvFromCstr(name);
|
||||
req.QueueHandle = queue;
|
||||
return SysPublishQueue(&req);
|
||||
}
|
||||
|
||||
// Withdraws one named queue publication.
|
||||
static uint32_t unpublish_queue(const char* name) {
|
||||
SYS_UNPUBLISH_QUEUE_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Name = SysSvFromCstr(name);
|
||||
return SysUnpublishQueue(&req);
|
||||
}
|
||||
|
||||
// Opens one named queue publication.
|
||||
static uint32_t open_named_queue(const char* name, uint32_t* out) {
|
||||
SYS_OPEN_NAMED_QUEUE_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Name = SysSvFromCstr(name);
|
||||
req.HandleOut = out;
|
||||
return SysOpenNamedQueue(&req);
|
||||
}
|
||||
|
||||
// Sends one fixed-size queue message.
|
||||
static uint32_t 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 explicit unpublish removes only the name, not existing handles.
|
||||
static void check_explicit_unpublish(void) {
|
||||
uint32_t queue = 0;
|
||||
uint32_t opened = 0;
|
||||
uint32_t status = SysCreateQueue(&queue);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("create queue", status);
|
||||
|
||||
status = publish_queue("ntl.queue.explicit", queue);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("publish queue", status);
|
||||
|
||||
status = open_named_queue("ntl.queue.explicit", &opened);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("open published queue", status);
|
||||
if (!opened) fail("opened handle is zero");
|
||||
|
||||
status = unpublish_queue("ntl.queue.explicit");
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("unpublish queue", status);
|
||||
|
||||
uint32_t missing = 0;
|
||||
status = open_named_queue("ntl.queue.explicit", &missing);
|
||||
expect_status("open withdrawn name", status, NTLSTATUS_NOT_FOUND);
|
||||
|
||||
TEST_QUEUE_MESSAGE out;
|
||||
TEST_QUEUE_MESSAGE in;
|
||||
memset(&out, 0, sizeof(out));
|
||||
memset(&in, 0, sizeof(in));
|
||||
out.Type = TEST_MESSAGE_TYPE;
|
||||
out.Param[0] = TEST_MESSAGE_VALUE;
|
||||
status = send_message(queue, &out);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("send after unpublish", status);
|
||||
status = recv_message(opened, &in);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("recv after unpublish", status);
|
||||
if (in.Type != TEST_MESSAGE_TYPE || in.Param[0] != TEST_MESSAGE_VALUE)
|
||||
fail("message mismatch after unpublish");
|
||||
|
||||
SysCloseHandle(opened);
|
||||
SysCloseHandle(queue);
|
||||
}
|
||||
|
||||
// Verifies closing the publishing handle withdraws its names.
|
||||
static void check_close_withdraws_name(void) {
|
||||
uint32_t queue = 0;
|
||||
uint32_t status = SysCreateQueue(&queue);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("create close queue", status);
|
||||
|
||||
status = publish_queue("ntl.queue.close", queue);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("publish close queue", status);
|
||||
|
||||
SysCloseHandle(queue);
|
||||
|
||||
uint32_t opened = 0;
|
||||
status = open_named_queue("ntl.queue.close", &opened);
|
||||
expect_status("open close-withdrawn name", status, NTLSTATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Runs the named queue lifetime smoke test.
|
||||
int main(void) {
|
||||
print("named_queue_lifetime_smoke: start\n");
|
||||
check_explicit_unpublish();
|
||||
check_close_withdraws_name();
|
||||
print("named_queue_lifetime_smoke: PASS\n");
|
||||
exit_now(0);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user