100 lines
4.2 KiB
C
100 lines
4.2 KiB
C
// Console-service smoke test. Verifies RSSRV publication, query, write, and cursor operations.
|
|
|
|
#include <ntlite/console_service.h>
|
|
#include <ntlite/port.h>
|
|
#include <ntlite/resource.h>
|
|
#include <ntlite/syscall.h>
|
|
#include <string.h>
|
|
|
|
static void exit_test(int code) {
|
|
for (;;) SysExitProcess(code);
|
|
}
|
|
|
|
static void print(const char* text) {
|
|
SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) };
|
|
(void)SysWriteConsole(&request);
|
|
}
|
|
|
|
static void print_status(KSTATUS status) {
|
|
static const char digits[] = "0123456789ABCDEF";
|
|
char buffer[11] = "0x00000000";
|
|
for (uint32_t i = 0; i < 8u; ++i)
|
|
buffer[2u + i] = digits[(status >> ((7u - i) * 4u)) & 0xFu];
|
|
print(buffer);
|
|
}
|
|
|
|
// Reports one failed console-service operation with its native status.
|
|
static void fail_status(const char* operation, KSTATUS status, int code) {
|
|
print("console_service_smoke: ");
|
|
print(operation);
|
|
print(" failed status=");
|
|
print_status(status);
|
|
print("\n");
|
|
exit_test(code);
|
|
}
|
|
|
|
// Reports one failed console-service invariant.
|
|
static void fail(const char* message, int code) {
|
|
print("console_service_smoke: ");
|
|
print(message);
|
|
print("\n");
|
|
exit_test(code);
|
|
}
|
|
|
|
// Runs the console-service smoke contract.
|
|
int main(void) {
|
|
SYS_HANDLE resources = SYS_HANDLE_INVALID;
|
|
KSTATUS status = NtlResourceConnect(&resources);
|
|
if (!KSUCCESS(status)) fail_status("connect resource service", status, 1);
|
|
|
|
uint32_t kind = NTL_RESOURCE_KIND_INVALID;
|
|
status = NtlResourceQuery(resources, SYS_SV_LITERAL("/Sessions/0"), &kind);
|
|
if (!KSUCCESS(status)) fail_status("query /Sessions/0", status, 2);
|
|
if (kind != NTL_RESOURCE_KIND_NAMESPACE_DIRECTORY) fail("/Sessions/0 has wrong resource kind", 2);
|
|
// DWM is noncritical, so the console contract must not depend on the desktop endpoint being published.
|
|
status = NtlResourceQuery(resources, SYS_SV_LITERAL("/Sessions/0/Console"), &kind);
|
|
if (!KSUCCESS(status)) fail_status("query /Sessions/0/Console", status, 3);
|
|
if (kind != NTL_RESOURCE_KIND_CAPABILITY) fail("/Sessions/0/Console has wrong resource kind", 3);
|
|
status = NtlResourceQuery(resources, SYS_SV_LITERAL("/Console"), &kind);
|
|
if (!KSUCCESS(status)) fail_status("query /Console", status, 4);
|
|
if (kind != NTL_RESOURCE_KIND_SYMBOLIC_LINK) fail("/Console has wrong resource kind", 4);
|
|
SYS_HANDLE alias = SYS_HANDLE_INVALID;
|
|
status = NtlResourceLookup(resources, SYS_SV_LITERAL("/Console"),
|
|
SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT, &alias);
|
|
if (!KSUCCESS(status)) fail_status("lookup /Console", status, 5);
|
|
if (alias == SYS_HANDLE_INVALID) fail("lookup /Console returned invalid handle", 5);
|
|
(void)SysCloseHandle(alias);
|
|
(void)NtlResourceClose(resources);
|
|
|
|
SYS_HANDLE session = SYS_HANDLE_INVALID;
|
|
status = NtlConsoleConnect(&session);
|
|
if (!KSUCCESS(status)) fail_status("connect console", status, 6);
|
|
|
|
NTL_CONSOLE_INFO before;
|
|
memset(&before, 0, sizeof(before));
|
|
status = NtlConsoleQueryInfo(session, &before);
|
|
if (!KSUCCESS(status)) fail_status("query console info", status, 7);
|
|
if (before.Size != sizeof(before) || before.Flags != NTL_CONSOLE_FLAG_NONE ||
|
|
before.Columns == 0 || before.Rows == 0 || before.PixelWidth == 0 || before.PixelHeight == 0)
|
|
fail("initial console info is invalid", 7);
|
|
|
|
static const char message[] = "[console_service_smoke] PASS\n";
|
|
size_t written = 0;
|
|
status = NtlConsoleWrite(session, message, sizeof(message) - 1u, &written);
|
|
if (!KSUCCESS(status)) fail_status("write console", status, 8);
|
|
if (written != sizeof(message) - 1u) fail("console write returned short byte count", 8);
|
|
|
|
NTL_CONSOLE_INFO after;
|
|
memset(&after, 0, sizeof(after));
|
|
status = NtlConsoleQueryInfo(session, &after);
|
|
if (!KSUCCESS(status)) fail_status("query console info after write", status, 9);
|
|
if (after.Generation <= before.Generation) fail("console generation did not advance", 9);
|
|
|
|
status = NtlConsoleSetCursor(session, (int)after.CursorX, (int)after.CursorY);
|
|
if (!KSUCCESS(status)) fail_status("set console cursor", status, 10);
|
|
|
|
(void)NtlConsoleClose(session);
|
|
exit_test(0);
|
|
return 0;
|
|
}
|