isolate POSIX builds from the host UCRT, wire lwext4 and ntfs-3g as ext4.sys and ntfs.sys, split the FAT driver into directory/file/async/driver/mount units, add posixsrv and dwm plus input/console/desktop syscall clients and a pile of new smoke targets, rename serial.sys to cereal.sys, name HDA/USB/lwIP/AHCI workers, harden ATA probing/reset/removal around actual hardware deadlines, absent-channel detection, diagnostics and explicit worker lifetime, redo ACPI S5 shutdown around GAS/MMIO and HW-reduced firmware, scan SSDTs for _S5 and deal with Intel SMI sleep trapping, make serial and SMP timeouts use real monotonic deadlines, add thread names and fix terminal thread teardown, scheduler and APC prepare/commit races, make advisory file locks queryable and preserve split ranges and add mutable file append state, add shared-memory pipes with kernel-assisted wait/wake, introduce capability-scoped input and display managers, split surface map rights into read/write, add explicit unmap and replace present with commit/generation/damage tracking while keeping physical presentation under the display manager, decouple native exception classes from Win32 exception numbers and translate them in kernel32, add opaque process startup data, bump the resource protocol to v3 with namespace directories, symlinks and enumeration and service control to v2 with generic READY handle exports, add the new POSIX errno/status surface and rebuild fds around posixsrv-owned shared open descriptions, descriptor-local flags, exact inheritance snapshots, dup/fcntl/record locks and shared-ring pipes, add waitpid, POSIX credentials/groups/sessions/passwd/group lookups and move sockets onto stable open descriptions, port the shells and apps to the new console/input services and surface commit API, teach init to load services.ini and start/supervise RSSRV, DWM and generic services under restricted capabilities while publishing their endpoints through RSSRV, split RSSRV into namespace, volume, display, session, input, console and resource components and make /SystemRoot a real symlink to the independently published system volume, shift the syscall table again, expand lock/resource/surface/POSIX/service/thread smoke coverage, make docs scream ASK QUESTIONS and DISCUSS at LLMs, replace MIT No Attribution with WTFPL+.

This commit is contained in:
maksw committed 2026-09-16 10:33:20 +02:00
1 parent 3dacbd32c8
commit 73abd6f90d
441 files changed
+187073 -6549

No files matched your search

+151 -91
View File
@@ -5,8 +5,11 @@
#include <stdbool.h>
#include <string.h>
#include <ntlite/syscall.h>
#include <ntlite/input_service.h>
#include <ntlite/console_service.h>
#include <ntlite/process_loader.h>
#include <ntlite/path.h>
#include <ntlite/resource.h>
#include <ntlite/status.h>
#define MAX_CMD 256
@@ -22,7 +25,7 @@
#define SHELL_CURSOR_BACKGROUND 0x00E0E0E0u
// Output helpers.
static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); }
static void print(const char* s) { (void)NtlConsoleWrite(SYS_HANDLE_INVALID, s, strlen(s), 0); }
// Opens file.
static uint32_t open_file(const char* path, uint32_t* handleOut) {
@@ -228,7 +231,7 @@ static const char* const gShellBuiltinCommands[] = {
"dir",
"display",
"exit",
"fbbench",
"surfbench",
"gpu",
"help",
"kill",
@@ -313,13 +316,10 @@ static void shellHistoryAdd(const char* cmd) {
static void shellEditorHideVisibleCursor(SHELL_VISIBLE_CURSOR* cursor) {
if (!cursor || !cursor->Visible) return;
SYS_PUT_SCREEN_CHAR_REQUEST request = {
sizeof(SYS_PUT_SCREEN_CHAR_REQUEST), cursor->Character, { 0, 0, 0 },
cursor->Column * SHELL_GLYPH_WIDTH,
cursor->Row * SHELL_GLYPH_HEIGHT,
SHELL_TEXT_FOREGROUND, SHELL_TEXT_BACKGROUND
};
(void)SysPutScreenChar(&request);
(void)NtlConsolePutCharacter(SYS_HANDLE_INVALID, cursor->Character,
cursor->Column * SHELL_GLYPH_WIDTH,
cursor->Row * SHELL_GLYPH_HEIGHT,
SHELL_TEXT_FOREGROUND, SHELL_TEXT_BACKGROUND);
cursor->Visible = false;
}
@@ -328,19 +328,16 @@ static void shellEditorShowVisibleCursor(SHELL_VISIBLE_CURSOR* cursor, const SHE
if (!cursor || !editor) return;
shellEditorHideVisibleCursor(cursor);
SYS_CONSOLE_INFO info;
if (SysGetConsoleInfo(&info) != NTLSTATUS_SUCCESS) return;
NTL_CONSOLE_INFO info;
if (NtlConsoleQueryInfo(SYS_HANDLE_INVALID, &info) != NTLSTATUS_SUCCESS) return;
char character = editor->Cursor < editor->Length
? editor->Buffer[editor->Cursor]
: ' ';
SYS_PUT_SCREEN_CHAR_REQUEST request = {
sizeof(SYS_PUT_SCREEN_CHAR_REQUEST), character, { 0, 0, 0 },
(int)info.CursorX * SHELL_GLYPH_WIDTH,
(int)info.CursorY * SHELL_GLYPH_HEIGHT,
SHELL_CURSOR_FOREGROUND, SHELL_CURSOR_BACKGROUND
};
if (SysPutScreenChar(&request) != NTLSTATUS_SUCCESS)
if (NtlConsolePutCharacter(SYS_HANDLE_INVALID, character,
(int)info.CursorX * SHELL_GLYPH_WIDTH,
(int)info.CursorY * SHELL_GLYPH_HEIGHT,
SHELL_CURSOR_FOREGROUND, SHELL_CURSOR_BACKGROUND) != NTLSTATUS_SUCCESS)
return;
cursor->Column = (int)info.CursorX;
@@ -439,16 +436,23 @@ static bool shellTokenHasPathSeparator(const char* token, size_t length) {
return false;
}
// Returns true when name starts with prefix.
// Returns an ASCII lower-case value for case-insensitive shell name handling.
static char shellAsciiLower(char c) {
if (c >= 'A' && c <= 'Z')
return (char)(c - 'A' + 'a');
return c;
}
// Returns true when name starts with prefix without treating ASCII case as significant.
static bool shellNameStartsWith(const char* name, const char* prefix, size_t prefixLength) {
if (!name || !prefix) return false;
for (size_t i = 0; i < prefixLength; i++) {
if (name[i] == '\0' || name[i] != prefix[i]) return false;
if (name[i] == '\0' || shellAsciiLower(name[i]) != shellAsciiLower(prefix[i])) return false;
}
return true;
}
// Extends an in-progress common prefix with one completion candidate.
// Extends an in-progress common prefix case-insensitively while preserving the first candidate's spelling.
static void shellUpdateCommonPrefix(char* common, size_t commonSize, const char* name, uint32_t matchCount) {
if (!common || commonSize == 0 || !name) return;
if (matchCount == 0) {
@@ -458,7 +462,7 @@ static void shellUpdateCommonPrefix(char* common, size_t commonSize, const char*
}
size_t i = 0;
while (common[i] && name[i] && common[i] == name[i]) i++;
while (common[i] && name[i] && shellAsciiLower(common[i]) == shellAsciiLower(name[i])) i++;
common[i] = '\0';
}
@@ -532,6 +536,42 @@ static bool shellSplitCompletionPath(const char* token, size_t tokenLength,
return true;
}
// Collects immediate RSSRV namespace children when the completion directory is a namespace directory.
static void shellCollectResourceCompletions(const char* token, size_t tokenLength,
SHELL_COMPLETION_STATE* state,
bool printMatches) {
char dir[MAX_CMD];
const char* prefix = token;
size_t prefixLength = tokenLength;
if (!shellSplitCompletionPath(token, tokenLength, dir, sizeof(dir), &prefix, &prefixLength)) return;
if (dir[0] != '/') return;
SYS_HANDLE session = SYS_HANDLE_INVALID;
if (!KSUCCESS(NtlResourceConnect(&session))) return;
uint32_t kind = NTL_RESOURCE_KIND_INVALID;
KSTATUS status = NtlResourceQuery(session, SysSvFromCstr(dir), &kind);
if (!KSUCCESS(status) || kind != NTL_RESOURCE_KIND_NAMESPACE_DIRECTORY) {
(void)NtlResourceClose(session);
return;
}
NTL_RESOURCE_ENUM_CURSOR cursor;
memset(&cursor, 0, sizeof(cursor));
for (;;) {
NTL_RESOURCE_ENUM_ENTRY entry;
status = NtlResourceEnumerate(session, SysSvFromCstr(dir), &cursor, &entry);
if (status == NTLSTATUS_NO_MORE_FILES) break;
if (!KSUCCESS(status)) break;
if (!shellNameStartsWith(entry.Name, prefix, prefixLength)) continue;
bool directory = entry.Kind == NTL_RESOURCE_KIND_NAMESPACE_DIRECTORY ||
entry.Kind == NTL_RESOURCE_KIND_SYMBOLIC_LINK;
if (printMatches) shellPrintCompletionCandidate(entry.Name, directory);
else shellRecordCompletion(state, entry.Name, directory, true);
}
(void)NtlResourceClose(session);
}
// Collects filesystem path matches using the existing directory enumeration ABI.
static void shellCollectPathCompletions(const char* token, size_t tokenLength,
SHELL_COMPLETION_STATE* state,
@@ -593,15 +633,18 @@ static void shellCompleteLine(SHELL_EDITOR* editor) {
if (commandPosition && !explicitPath) {
shellCollectBuiltinCompletions(token, tokenLength, &state, false);
}
shellCollectResourceCompletions(token, tokenLength, &state, false);
shellCollectPathCompletions(token, tokenLength, &state, false);
if (state.MatchCount == 0) return;
size_t commonLength = strlen(state.Common);
bool expanded = commonLength > namePrefixLength;
if (expanded) {
(void)shellEditorReplaceRange(editor, editor->Cursor, (int)tokenEnd,
state.Common + namePrefixLength);
bool canonicalized = commonLength == namePrefixLength &&
memcmp(state.Common, namePrefix, namePrefixLength) != 0;
if (expanded || canonicalized) {
size_t nameStart = tokenStart + (size_t)(namePrefix - token);
(void)shellEditorReplaceRange(editor, (int)nameStart, (int)tokenEnd, state.Common);
}
if (state.MatchCount == 1) {
@@ -624,6 +667,7 @@ static void shellCompleteLine(SHELL_EDITOR* editor) {
if (commandPosition && !explicitPath) {
shellCollectBuiltinCompletions(token, tokenLength, NULL, true);
}
shellCollectResourceCompletions(token, tokenLength, NULL, true);
shellCollectPathCompletions(token, tokenLength, NULL, true);
shellRedrawPromptAndLine(editor);
}
@@ -647,13 +691,7 @@ static bool readLine(char* buf, int len) {
while (true) {
shellEditorShowVisibleCursor(&visibleCursor, &editor);
INPUT_KEY_RECORD input;
SYS_INPUT_EVENT_REQUEST inputReq;
inputReq.Size = sizeof(inputReq);
inputReq.QueueHandle = 0;
inputReq.Flags = SYS_INPUT_EVENT_FLAG_NONE;
inputReq.TimeoutMilliseconds = SYS_WAIT_TIMEOUT_INFINITE;
inputReq.RecordOut = &input;
KSTATUS inputStatus = SysReadInputEvent(&inputReq);
KSTATUS inputStatus = NtlInputReadEvent(SYS_HANDLE_INVALID, SYS_WAIT_TIMEOUT_INFINITE, &input);
shellEditorHideVisibleCursor(&visibleCursor);
if (inputStatus != NTLSTATUS_SUCCESS) { SysYield(); continue; }
@@ -755,7 +793,7 @@ static void cmd_help() {
" mem - Show memory usage\n"
" time - Show system wall-clock time\n"
" display - Show display provider and counters\n"
" fbbench - Benchmark Doom-size and full-screen presents\n"
" surfbench - Benchmark Doom-size and full-screen surface commits\n"
" stats - Show scheduler/CPU/MM telemetry\n"
" ps - List processes\n"
" threads <pid> - Show one process's thread statuses\n"
@@ -1276,13 +1314,13 @@ static void cmd_stats(void) {
print(" live="); printUInt64(surface.LiveSurfaces); print("\n");
print(" live memory: pages="); printUInt64(surface.LivePages);
print(" bytes="); printUInt64(surface.LiveBytes); print("\n");
print(" maps/presents: maps="); printUInt64(surface.MapCalls);
print(" presents="); printUInt64(surface.PresentCalls);
print(" input-rects="); printUInt64(surface.PresentRectInputs); print("\n");
print(" present work: clipped="); printUInt64(surface.PresentClippedRects);
print(" empty="); printUInt64(surface.PresentEmptyClips);
print(" rows="); printUInt64(surface.PresentRowsCopied);
print(" bytes="); printUInt64(surface.PresentBytesCopied); print("\n");
print(" maps/commits: maps="); printUInt64(surface.MapCalls);
print(" commits="); printUInt64(surface.CommitCalls);
print(" input-rects="); printUInt64(surface.CommitRectInputs); print("\n");
print(" commit work: clipped="); printUInt64(surface.CommitClippedRects);
print(" empty="); printUInt64(surface.CommitEmptyClips); print("\n");
print(" physical present: calls="); printUInt64(surface.PhysicalPresentCalls);
print(" bytes="); printUInt64(surface.PhysicalPresentBytesCopied); print("\n");
print("Page tables:\n");
print(" leaf mappings: "); printUInt64(pte.CurrentLeafMappings); print("\n");
@@ -1411,9 +1449,7 @@ typedef struct SHELL_FB_BENCH_RESULT {
uint32_t Status;
uint64_t ElapsedTicks;
uint64_t Frequency;
uint64_t ExpectedBytes;
uint64_t ScanoutBytes;
uint64_t DirectPresents;
uint64_t CommitBytes;
} SHELL_FB_BENCH_RESULT;
// Computes a decimal fixed-point ratio with one digit after the decimal point.
@@ -1441,7 +1477,7 @@ static void shellFillBenchmarkSurface(uint32_t* pixels,
}
}
// Runs one synchronous surface-present benchmark case.
// Runs one synchronous surface-commit benchmark case.
static void shellRunFramebufferBenchmark(uint32_t width,
uint32_t height,
uint32_t frames,
@@ -1471,7 +1507,8 @@ static void shellRunFramebufferBenchmark(uint32_t width,
void* base = 0;
uint32_t pitchBytes = 0;
status = SysMapSurface(surface, &base, &pitchBytes);
status = SysMapSurface(surface, SYS_SURFACE_MAP_READ | SYS_SURFACE_MAP_WRITE,
&base, &pitchBytes);
if (status != NTLSTATUS_SUCCESS || !base || pitchBytes < width * sizeof(uint32_t)) {
result->Status = status ? status : NTLSTATUS_FAILURE;
SysCloseHandle(surface);
@@ -1481,44 +1518,28 @@ static void shellRunFramebufferBenchmark(uint32_t width,
shellFillBenchmarkSurface((uint32_t*)base, pitchBytes / sizeof(uint32_t), width, height);
DISPLAY_RECT rect = { 0, 0, (int32_t)width, (int32_t)height };
for (uint32_t i = 0; i < 2; i++) {
status = SysPresentSurface(surface, &rect, 1);
if (status != NTLSTATUS_SUCCESS)
break;
}
SYS_DISPLAY_INFO before;
SYS_DISPLAY_INFO after;
memset(&before, 0, sizeof(before));
memset(&after, 0, sizeof(after));
if (status == NTLSTATUS_SUCCESS)
status = SysQueryDisplayInfo(&before);
for (uint32_t i = 0; i < 2 && status == NTLSTATUS_SUCCESS; ++i)
status = SysCommitSurface(surface, &rect, 1, 0);
uint64_t begin = 0;
uint64_t end = 0;
uint32_t completed = 0;
if (status == NTLSTATUS_SUCCESS) {
begin = SysGetTick();
for (; completed < frames; completed++) {
status = SysPresentSurface(surface, &rect, 1);
for (; completed < frames; ++completed) {
status = SysCommitSurface(surface, &rect, 1, 0);
if (status != NTLSTATUS_SUCCESS)
break;
}
end = SysGetTick();
uint32_t queryStatus = SysQueryDisplayInfo(&after);
if (status == NTLSTATUS_SUCCESS && queryStatus != NTLSTATUS_SUCCESS)
status = queryStatus;
}
result->Frames = completed;
result->Status = status;
result->ElapsedTicks = end - begin;
result->ExpectedBytes = (uint64_t)width * (uint64_t)height * sizeof(uint32_t) * completed;
if (after.DeviceStats.ScanoutBytes >= before.DeviceStats.ScanoutBytes)
result->ScanoutBytes = after.DeviceStats.ScanoutBytes - before.DeviceStats.ScanoutBytes;
if (after.DeviceStats.DirectPresentCount >= before.DeviceStats.DirectPresentCount)
result->DirectPresents = after.DeviceStats.DirectPresentCount - before.DeviceStats.DirectPresentCount;
result->CommitBytes = (uint64_t)width * (uint64_t)height * sizeof(uint32_t) * completed;
(void)SysUnmapSurface(base);
SysCloseHandle(surface);
}
@@ -1535,32 +1556,30 @@ static void shellPrintFramebufferBenchmark(const char* name,
uint64_t elapsedUs = SysTicksToMicroseconds(result->ElapsedTicks, result->Frequency);
uint64_t fpsTenths = shellRatioTenths((uint64_t)result->Frames * result->Frequency,
result->ElapsedTicks);
uint64_t bytes = result->ScanoutBytes ? result->ScanoutBytes : result->ExpectedBytes;
uint64_t mibTenths = shellRatioTenths(bytes * result->Frequency,
uint64_t mibTenths = shellRatioTenths(result->CommitBytes * result->Frequency,
result->ElapsedTicks * 1024u * 1024u);
print("frames="); printUInt(result->Frames);
print(" time="); printUInt64(elapsedUs / 1000u); print(" ms");
print(" fps="); printUInt64(fpsTenths / 10u); print("."); printUInt64(fpsTenths % 10u);
print(" scanout="); printUInt64(mibTenths / 10u); print("."); printUInt64(mibTenths % 10u); print(" MiB/s");
print(" direct="); printUInt64(result->DirectPresents);
print(" bytes="); printUInt64(bytes);
print(" payload="); printUInt64(mibTenths / 10u); print("."); printUInt64(mibTenths % 10u); print(" MiB/s");
print(" bytes="); printUInt64(result->CommitBytes);
print("\n");
}
// Benchmarks the synchronous surface-to-scanout path without console traffic.
static void cmd_fbbench(void) {
// Benchmarks surface commit bookkeeping without implying physical presentation.
static void cmd_surfbench(void) {
SYS_DISPLAY_INFO info;
uint32_t status = SysQueryDisplayInfo(&info);
if (status != NTLSTATUS_SUCCESS) {
print("fbbench: display query failed status=0x"); printHex32(status); print("\n");
print("surfbench: display query failed status=0x"); printHex32(status); print("\n");
return;
}
uint64_t frequency = 0;
status = SysGetTickFrequency(&frequency);
if (status != NTLSTATUS_SUCCESS || !frequency) {
print("fbbench: timer query failed status=0x"); printHex32(status); print("\n");
print("surfbench: timer query failed status=0x"); printHex32(status); print("\n");
return;
}
@@ -1579,13 +1598,13 @@ static void cmd_fbbench(void) {
if (fullFrames < 8u) fullFrames = 8u;
if (fullFrames > 64u) fullFrames = 64u;
print("fbbench: running; the framebuffer will be overwritten temporarily\n");
print("surfbench: commit notifications only; scanout is DWM-owned\n");
SHELL_FB_BENCH_RESULT doom;
SHELL_FB_BENCH_RESULT full;
shellRunFramebufferBenchmark(doomWidth, doomHeight, doomFrames, frequency, &doom);
shellRunFramebufferBenchmark(fullWidth, fullHeight, fullFrames, frequency, &full);
SysClearScreen(0x00012456u);
NtlConsoleClear(SYS_HANDLE_INVALID, 0x00012456u);
print("Framebuffer benchmark:\n");
print(" provider: "); print(info.PrimaryName[0] ? info.PrimaryName : "?");
print(" mode="); printUInt(info.Mode.Width); print("x"); printUInt(info.Mode.Height);
@@ -1669,6 +1688,7 @@ static const char* threadWaitName(uint32_t waitType) {
case SYS_THREAD_WAIT_USB_PIPE: return "usbpipe";
case SYS_THREAD_WAIT_FILE_MAPPING: return "mapping";
case SYS_THREAD_WAIT_SURFACE: return "surface";
case SYS_THREAD_WAIT_PIPE: return "pipe";
default: return "unknown";
}
}
@@ -1770,7 +1790,7 @@ static void cmd_threads(const char* args) {
print(" (Count: ");
printUInt((uint32_t)count);
print("):\n");
print(" TID State Base Eff CPU LastCPU QRem QTick Burst Wait WStat Flags\n");
print(" TID State Base Eff CPU LastCPU QRem QTick Burst Wait WStat Flags Name\n");
print(" Flags: *=current I=idle K=kernel Q=queued A=alertable k=kernel-apc u=user-apc.\n");
size_t displayCount = count < MAX_THREADS ? count : MAX_THREADS;
@@ -1804,6 +1824,8 @@ static void cmd_threads(const char* args) {
printUIntWidth(t->WaitStatus, 5);
print(" ");
printThreadFlags(t->Flags);
print(" ");
print(t->Name[0] ? t->Name : "-");
print("\n");
}
@@ -1861,13 +1883,6 @@ static void cmd_write(const char* args) {
#define SHELL_DIR_INITIAL_CAPACITY 64u
// Returns an ASCII lower-case value for case-insensitive directory sorting.
static char shellAsciiLower(char c) {
if (c >= 'A' && c <= 'Z')
return (char)(c - 'A' + 'a');
return c;
}
// Compares two names using case-insensitive order with a stable case tie-breaker.
static int shellCompareNames(const char* a, const char* b) {
size_t i = 0;
@@ -1966,10 +1981,55 @@ static void shellPrintDirEntry(const SYS_DIR_ENTRY* ke) {
print("\n");
}
// Prints one RSSRV namespace kind label.
static void shellPrintResourceKind(uint32_t kind) {
if (kind == NTL_RESOURCE_KIND_NAMESPACE_DIRECTORY) print("<NSDIR> ");
else if (kind == NTL_RESOURCE_KIND_SYMBOLIC_LINK) print("<SYMLINK> ");
else if (kind == NTL_RESOURCE_KIND_VOLUME) print("<VOLUME> ");
else if (kind == NTL_RESOURCE_KIND_DIRECTORY) print("<DIRCAP> ");
else if (kind == NTL_RESOURCE_KIND_DEVICE) print("<DEVICE> ");
else print("<OBJECT> ");
}
// Handles dir for an exact RSSRV namespace directory and returns whether it owned the request.
static bool shellTryResourceDir(const char* target) {
if (!target || target[0] != '/') return false;
SYS_HANDLE session = SYS_HANDLE_INVALID;
if (!KSUCCESS(NtlResourceConnect(&session))) return false;
uint32_t kind = NTL_RESOURCE_KIND_INVALID;
KSTATUS status = NtlResourceQuery(session, SysSvFromCstr(target), &kind);
if (!KSUCCESS(status) || kind != NTL_RESOURCE_KIND_NAMESPACE_DIRECTORY) {
(void)NtlResourceClose(session);
return false;
}
NTL_RESOURCE_ENUM_CURSOR cursor;
memset(&cursor, 0, sizeof(cursor));
for (;;) {
NTL_RESOURCE_ENUM_ENTRY entry;
status = NtlResourceEnumerate(session, SysSvFromCstr(target), &cursor, &entry);
if (status == NTLSTATUS_NO_MORE_FILES) break;
if (!KSUCCESS(status)) {
print("dir: namespace enumeration failed, status=0x");
printHex32(status);
print("\n");
break;
}
shellPrintResourceKind(entry.Kind);
print(entry.Name);
if (entry.Kind == NTL_RESOURCE_KIND_NAMESPACE_DIRECTORY) print("/");
print("\n");
}
(void)NtlResourceClose(session);
return true;
}
// Implements the cmd dir operation.
static void cmd_dir(const char* path) {
uint32_t hDir;
const char* target = (path && *path != '\0') ? path : ".";
if (shellTryResourceDir(target)) return;
uint32_t st = open_dir(target, &hDir);
if (st != 0) {
@@ -2050,7 +2110,7 @@ static bool extractProgramPath(const char* cmdline, char* out, size_t outSize) {
// Returns whether one input key is currently held.
static bool shellIsKeyDown(INPUT_KEY key) {
bool down = false;
return SysIsKeyDown(key, &down) == NTLSTATUS_SUCCESS && down;
return NtlInputIsKeyDown(key, &down) == NTLSTATUS_SUCCESS && down;
}
// Waits for a foreground process while polling Ctrl-C without consuming child input.
@@ -2066,7 +2126,7 @@ static uint32_t waitForegroundProcess(uint32_t hProc) {
if (status != NTLSTATUS_TIMEOUT)
return status;
uint32_t modifiers = SysGetKeyModifiers();
uint32_t modifiers = NtlInputGetKeyModifiers();
if (!sentBreak && (modifiers & INPUT_MOD_CTRL) &&
shellIsKeyDown(INPUT_KEY_C)) {
print("^C\n");
@@ -2089,7 +2149,7 @@ static int runCommand(const char* cmd) {
if (!cmd || *cmd == '\0') return 0;
if (strcmp(cmd, "exit") == 0) return 1;
if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; }
if (strcmp(cmd, "clear") == 0) { SysClearScreen(0x012456); return 0; }
if (strcmp(cmd, "clear") == 0) { (void)NtlConsoleClear(SYS_HANDLE_INVALID, 0x012456); return 0; }
if (strncmp(cmd, "crash", 5) == 0) {
// Check the sub-option trailing "crash " (offset 6).
if (strcmp(cmd + 6, "void") == 0) {
@@ -2131,7 +2191,7 @@ static int runCommand(const char* cmd) {
if (strcmp(cmd, "mem") == 0) { cmd_mem(); return 0; }
if (strcmp(cmd, "time") == 0 || strcmp(cmd, "date") == 0) { cmd_time(); return 0; }
if (strcmp(cmd, "display") == 0 || strcmp(cmd, "gpu") == 0) { cmd_display(); return 0; }
if (strcmp(cmd, "fbbench") == 0) { cmd_fbbench(); return 0; }
if (strcmp(cmd, "surfbench") == 0) { cmd_surfbench(); return 0; }
if (strcmp(cmd, "volume") == 0) { cmd_volume(""); return 0; }
if (strncmp(cmd, "volume ", 7) == 0) { cmd_volume(cmd + 7); return 0; }
if (strcmp(cmd, "stats") == 0 || strcmp(cmd, "telemetry") == 0) { cmd_stats(); return 0; }
@@ -2199,7 +2259,7 @@ static int runCommand(const char* cmd) {
print("\n");
SysCloseHandle(hProc);
INPUT_KEY drainedKey;
while (SysPollKeyboard(&drainedKey) == NTLSTATUS_SUCCESS) (void)SysReadKey(&drainedKey);
while (NtlInputPollKeyboard(&drainedKey) == NTLSTATUS_SUCCESS) (void)NtlInputReadKey(&drainedKey);
}
} else {
print("shell: launch failed\n");