// User application entry points for shell_native. #include #include #include #include #include #include #include #include #include #include #include #define MAX_CMD 256 #define SHELL_FOREGROUND_POLL_MS 30u #define MAX_PROCS 64 // Maximum number of processes we will fetch at once #define MAX_THREADS 128 #define SHELL_PROMPT "> " #define SHELL_GLYPH_WIDTH 8 #define SHELL_GLYPH_HEIGHT 16 #define SHELL_TEXT_FOREGROUND 0x00CCCCCCu #define SHELL_TEXT_BACKGROUND 0x00012456u #define SHELL_CURSOR_FOREGROUND 0x00000000u #define SHELL_CURSOR_BACKGROUND 0x00E0E0E0u // Output helpers. static void print(const char* s) { (void)NtlConsoleWrite(SYS_HANDLE_INVALID, s, strlen(s), 0); } // Numeric diagnostic helpers used before their definitions. static void printUInt(uint32_t n); static void printHex32(uint32_t v); // Opens file. static KSTATUS open_file(const char* path, uint32_t* handleOut) { return NtlOpenFile(SysSvFromCstr(path), SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY, SYS_FILE_OPEN_EXISTING, SYS_FILE_FLAG_NONE, handleOut); } // Creates file. static KSTATUS create_file(const char* path, uint32_t* handleOut) { return NtlOpenFile(SysSvFromCstr(path), SYS_FILE_ACCESS_WRITE | SYS_FILE_ACCESS_QUERY, SYS_FILE_CREATE_ALWAYS, SYS_FILE_FLAG_NONE, handleOut); } // Opens dir. static KSTATUS open_dir(const char* path, uint32_t* handleOut) { return NtlOpenDir(SysSvFromCstr(path), SYS_DIR_ACCESS_ENUMERATE | SYS_DIR_ACCESS_OPEN, SYS_DIR_FLAG_NONE, handleOut); } // Updates cwd. static KSTATUS set_cwd(const char* path) { return NtlSetCurrentDirectory(SysSvFromCstr(path)); } // Releases file. static KSTATUS delete_file(const char* path) { return NtlDeleteFile(SysSvFromCstr(path)); } // Creates one process and reports which launch stage returned an error. static KSTATUS create_process(const char* path, uint32_t* handleOut, const char* cmdline, const char** failureStageOut) { if (failureStageOut) *failureStageOut = "open-image"; uint32_t imageFile = SYS_HANDLE_INVALID; KSTATUS status = open_file(path, &imageFile); if (!KSUCCESS(status)) return status; NTL_CREATE_SYSTEM_PROCESS_REQUEST req; memset(&req, 0, sizeof(req)); req.Size = sizeof(req); req.Flags = NTL_PROCESS_LOAD_FLAG_NONE; req.ImageFile = imageFile; req.Path = SysSvFromCstr(path); req.CommandLine = SysSvFromCstr(cmdline); req.SecurityContext = SYS_SECURITY_CONTEXT_CURRENT; req.ResolveModuleName = NtlResolveSystemModuleName; req.ProcessHandleOut = handleOut; if (failureStageOut) *failureStageOut = "process-loader"; status = NtlCreateSystemProcess(&req); (void)SysCloseHandle(imageFile); if (KSUCCESS(status) && failureStageOut) *failureStageOut = NULL; return status; } // Prints u Int. static void printUInt(uint32_t n) { char buf[12]; int i = 0; if (n == 0) { print("0"); return; } while (n > 0) { buf[i++] = (char)('0' + n % 10); n /= 10; } while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); } } // Prints int. static void printInt(int32_t n) { if (n < 0) { print("-"); printUInt((uint32_t)-(n + 1) + 1); } else { printUInt((uint32_t)n); } } // Parses an unsigned decimal integer. static bool parseUInt(const char* text, uint32_t* out) { if (!text || !out) return false; while (*text == ' ' || *text == '\t') text++; if (*text < '0' || *text > '9') return false; uint32_t value = 0; while (*text >= '0' && *text <= '9') { uint32_t digit = (uint32_t)(*text - '0'); if (value > (0xffffffffu - digit) / 10u) return false; value = value * 10u + digit; text++; } while (*text == ' ' || *text == '\t') text++; if (*text != '\0') return false; *out = value; return true; } // Prints u Int64. static void printUInt64(uint64_t n) { if (n == 0) { print("0"); return; } char buf[20]; int i = 0; while (n > 0) { buf[i++] = (char)('0' + (int)(n % 10)); n /= 10; } while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); } } // Implements the u64 Digits operation. static uint32_t u64Digits(uint64_t n) { uint32_t digits = 1; while (n >= 10u) { n /= 10u; digits++; } return digits; } // Prints spaces. static void printSpaces(size_t count) { while (count--) print(" "); } // Prints u Int Width. static void printUIntWidth(uint32_t n, size_t width) { uint32_t digits = u64Digits(n); if (width > digits) printSpaces(width - digits); printUInt(n); } // Prints u Int Zero Width. static void printUIntZeroWidth(uint32_t n, size_t width) { uint32_t digits = u64Digits(n); while (width > digits) { print("0"); width--; } printUInt(n); } // Prints u Int64 Width. static void printUInt64Width(uint64_t n, size_t width) { uint32_t digits = u64Digits(n); if (width > digits) printSpaces(width - digits); printUInt64(n); } // Names common nt-lite status values used by shell diagnostics. static const char* statusName(KSTATUS status) { switch (status) { case NTLSTATUS_SUCCESS: return "success"; case NTLSTATUS_FAILURE: return "failure"; case NTLSTATUS_NOT_SUPPORTED: return "not-supported"; case NTLSTATUS_INVALID_PARAMETER: return "invalid-parameter"; case NTLSTATUS_INVALID_HANDLE: return "invalid-handle"; case NTLSTATUS_BUFFER_TOO_SMALL: return "buffer-too-small"; case NTLSTATUS_CHECKSUM_MISMATCH: return "checksum-mismatch"; case NTLSTATUS_NO_MEMORY: return "no-memory"; case NTLSTATUS_ACCESS_DENIED: return "access-denied"; case NTLSTATUS_NOT_FOUND: return "not-found"; case NTLSTATUS_ALREADY_EXISTS: return "already-exists"; case NTLSTATUS_OBJECT_NAME_COLLISION: return "object-name-collision"; case NTLSTATUS_OBJECT_DEAD: return "object-dead"; case NTLSTATUS_LIMIT_REACHED: return "limit-reached"; case NTLSTATUS_INVALID_IMAGE_FORMAT: return "invalid-image-format"; case NTLSTATUS_NAME_TOO_LONG: return "name-too-long"; default: return NULL; } } // Prints one status with its stable numeric facility/code decomposition. static void printStatus(KSTATUS status) { print("0x"); printHex32(status); const char* name = statusName(status); if (name) { print(" ("); print(name); print(")"); } print(" facility="); printUInt(KSTATUS_FACILITY(status)); print(" code="); printUInt(KSTATUS_CODE(status)); } // Names nt-lite process-abort exit statuses. static const char* processExitStatusName(uint32_t code) { switch (code) { case NTLSTATUS_PROCESS_KILLED: return "killed"; case NTLSTATUS_PROCESS_PAGE_FAULT: return "page-fault"; case NTLSTATUS_PROCESS_GENERAL_PROTECTION: return "general-protection"; case NTLSTATUS_PROCESS_ILLEGAL_OPCODE: return "illegal-opcode"; case NTLSTATUS_PROCESS_DIVIDE_BY_ZERO: return "divide-by-zero"; case NTLSTATUS_PROCESS_BREAKPOINT: return "breakpoint"; case NTLSTATUS_PROCESS_ALIGNMENT_FAULT: return "alignment-fault"; case NTLSTATUS_PROCESS_UNKNOWN_FAULT: return "unknown-fault"; default: return NULL; } } // Prints hex32. static void printHex32(uint32_t v) { static const char hex[] = "0123456789abcdef"; char buf[9]; for (int i = 7; i >= 0; i--) { buf[i] = hex[v & 0xFu]; v >>= 4; } buf[8] = '\0'; print(buf); } // Prints dir Time. static void printDirTime(const SYS_SYSTEM_TIME* t) { if (!t || !(t->Flags & SYS_TIME_FLAG_VALID)) { print("---- -- -- --:-- "); return; } printUIntZeroWidth(t->Year, 4); print("-"); printUIntZeroWidth(t->Month, 2); print("-"); printUIntZeroWidth(t->Day, 2); print(" "); printUIntZeroWidth(t->Hour, 2); print(":"); printUIntZeroWidth(t->Minute, 2); print(" "); } // Prints string Width. static void printStringWidth(const char* s, size_t width) { size_t len = s ? strlen(s) : 0; if (s) print(s); if (width > len) printSpaces(width - len); } #define SHELL_HISTORY_DEPTH 16 static char gHistory[SHELL_HISTORY_DEPTH][MAX_CMD]; static size_t gHistoryCount; typedef struct SHELL_EDITOR { char* Buffer; int Capacity; int Length; int Cursor; } SHELL_EDITOR; typedef struct SHELL_VISIBLE_CURSOR { int Column; int Row; char Character; bool Visible; } SHELL_VISIBLE_CURSOR; static const char* const gShellBuiltinCommands[] = { "cd", "clear", "crash", "date", "del", "dir", "display", "exit", "surfbench", "gpu", "help", "kill", "mem", "ps", "stats", "telemetry", "threads", "time", "type", "volume", "write", }; // Converts a key event into the shell's printable character model. static char shellKeyToChar(INPUT_KEY key, uint32_t modifiers) { bool shifted = (modifiers & INPUT_MOD_SHIFT) != 0; bool caps = (modifiers & INPUT_MOD_CAPS_LOCK) != 0; if (key >= INPUT_KEY_A && key <= INPUT_KEY_Z) { char c = (char)('a' + (key - INPUT_KEY_A)); if (shifted ^ caps) c = (char)(c - 'a' + 'A'); return c; } if (key >= INPUT_KEY_1 && key <= INPUT_KEY_9) { static const char shiftedDigits[] = "!@#$%^&*("; char normal = (char)('1' + (key - INPUT_KEY_1)); return shifted ? shiftedDigits[key - INPUT_KEY_1] : normal; } switch (key) { case INPUT_KEY_0: return shifted ? ')' : '0'; case INPUT_KEY_MINUS: return shifted ? '_' : '-'; case INPUT_KEY_EQUAL: return shifted ? '+' : '='; case INPUT_KEY_LEFT_BRACKET: return shifted ? '{' : '['; case INPUT_KEY_RIGHT_BRACKET: return shifted ? '}' : ']'; case INPUT_KEY_BACKSLASH: return shifted ? '|' : '\\'; case INPUT_KEY_SEMICOLON: return shifted ? ':' : ';'; case INPUT_KEY_APOSTROPHE: return shifted ? '"' : '\''; case INPUT_KEY_GRAVE: return shifted ? '~' : '`'; case INPUT_KEY_COMMA: return shifted ? '<' : ','; case INPUT_KEY_PERIOD: return shifted ? '>' : '.'; case INPUT_KEY_SLASH: return shifted ? '?' : '/'; case INPUT_KEY_SPACE: return ' '; case INPUT_KEY_TAB: return '\t'; case INPUT_KEY_KP_DIVIDE: return '/'; case INPUT_KEY_KP_MULTIPLY: return '*'; case INPUT_KEY_KP_MINUS: return '-'; case INPUT_KEY_KP_PLUS: return '+'; case INPUT_KEY_KP_0: return '0'; case INPUT_KEY_KP_1: return '1'; case INPUT_KEY_KP_2: return '2'; case INPUT_KEY_KP_3: return '3'; case INPUT_KEY_KP_4: return '4'; case INPUT_KEY_KP_5: return '5'; case INPUT_KEY_KP_6: return '6'; case INPUT_KEY_KP_7: return '7'; case INPUT_KEY_KP_8: return '8'; case INPUT_KEY_KP_9: return '9'; case INPUT_KEY_KP_PERIOD: return '.'; default: return 0; } } // Adds a non-empty command to the in-memory history ring. static void shellHistoryAdd(const char* cmd) { if (!cmd || !*cmd) return; if (gHistoryCount > 0 && strcmp(gHistory[gHistoryCount - 1], cmd) == 0) return; if (gHistoryCount == SHELL_HISTORY_DEPTH) { memmove(gHistory[0], gHistory[1], (SHELL_HISTORY_DEPTH - 1) * MAX_CMD); gHistoryCount--; } strncpy(gHistory[gHistoryCount], cmd, MAX_CMD - 1); gHistory[gHistoryCount][MAX_CMD - 1] = '\0'; gHistoryCount++; } // Restores the character underneath the visible edit cursor. static void shellEditorHideVisibleCursor(SHELL_VISIBLE_CURSOR* cursor) { if (!cursor || !cursor->Visible) return; (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; } // Draws the same steady block cursor used by edit without changing console state. static void shellEditorShowVisibleCursor(SHELL_VISIBLE_CURSOR* cursor, const SHELL_EDITOR* editor) { if (!cursor || !editor) return; shellEditorHideVisibleCursor(cursor); NTL_CONSOLE_INFO info; if (NtlConsoleQueryInfo(SYS_HANDLE_INVALID, &info) != NTLSTATUS_SUCCESS) return; char character = editor->Cursor < editor->Length ? editor->Buffer[editor->Cursor] : ' '; 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; cursor->Row = (int)info.CursorY; cursor->Character = character; cursor->Visible = true; } // Moves the visible cursor left by the requested number of cells. static void shellEditorMoveLeftCells(int count) { while (count-- > 0) print("\b"); } // Moves the editor cursor without changing the buffer. static void shellEditorMoveCursor(SHELL_EDITOR* editor, int target) { if (!editor) return; if (target < 0) target = 0; if (target > editor->Length) target = editor->Length; if (target < editor->Cursor) { shellEditorMoveLeftCells(editor->Cursor - target); } else { while (editor->Cursor < target) { char echo[2] = { editor->Buffer[editor->Cursor], '\0' }; print(echo); editor->Cursor++; } } editor->Cursor = target; } // Redraws the changed tail and restores the requested cursor position. static void shellEditorRedrawTail(SHELL_EDITOR* editor, int start, int oldLength, int targetCursor) { if (!editor) return; print(editor->Buffer + start); if (oldLength > editor->Length) printSpaces((size_t)(oldLength - editor->Length)); int displayedEnd = oldLength > editor->Length ? oldLength : editor->Length; shellEditorMoveLeftCells(displayedEnd - targetCursor); editor->Cursor = targetCursor; } // Replaces one buffer range and keeps the visible line synchronized. static bool shellEditorReplaceRange(SHELL_EDITOR* editor, int start, int end, const char* text) { if (!editor || !editor->Buffer || editor->Capacity <= 0 || !text) return false; if (start < 0 || end < start || end > editor->Length) return false; shellEditorMoveCursor(editor, start); int oldLength = editor->Length; int removed = end - start; int available = editor->Capacity - 1 - (oldLength - removed); int replacementLength = 0; while (text[replacementLength] && replacementLength < available) replacementLength++; memmove(editor->Buffer + start + replacementLength, editor->Buffer + end, (size_t)(oldLength - end + 1)); if (replacementLength > 0) memcpy(editor->Buffer + start, text, (size_t)replacementLength); editor->Length = oldLength - removed + replacementLength; int targetCursor = start + replacementLength; shellEditorRedrawTail(editor, start, oldLength, targetCursor); return removed != replacementLength || replacementLength != 0; } // Inserts text at the current cursor position. static bool shellEditorInsert(SHELL_EDITOR* editor, const char* text) { if (!editor) return false; return shellEditorReplaceRange(editor, editor->Cursor, editor->Cursor, text); } // Replaces the complete visible line and leaves the cursor at its end. static void shellEditorReplaceLine(SHELL_EDITOR* editor, const char* text) { if (!editor) return; (void)shellEditorReplaceRange(editor, 0, editor->Length, text ? text : ""); } // Returns true when a character separates shell tokens. static bool shellIsTokenSeparator(char c) { return c == ' ' || c == '\t'; } // Returns true when a character separates path components. static bool shellIsPathSeparator(char c) { return c == '/' || c == '\\'; } // Returns true when the token already names an explicit path. static bool shellTokenHasPathSeparator(const char* token, size_t length) { for (size_t i = 0; i < length; i++) { if (shellIsPathSeparator(token[i])) return true; } return false; } // 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' || shellAsciiLower(name[i]) != shellAsciiLower(prefix[i])) return false; } return true; } // 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) { strncpy(common, name, commonSize - 1); common[commonSize - 1] = '\0'; return; } size_t i = 0; while (common[i] && name[i] && shellAsciiLower(common[i]) == shellAsciiLower(name[i])) i++; common[i] = '\0'; } // Prints one completion candidate. static void shellPrintCompletionCandidate(const char* name, bool directory) { print(" "); print(name); if (directory) print("/"); print("\n"); } // Tracks completion candidates without storing the full candidate list. typedef struct SHELL_COMPLETION_STATE { uint32_t MatchCount; bool LastIsDirectory; bool LastAddsSpace; char Common[SYS_DIR_NAME_MAX]; } SHELL_COMPLETION_STATE; // Records one completion candidate. static void shellRecordCompletion(SHELL_COMPLETION_STATE* state, const char* name, bool directory, bool addsSpace) { if (!state || !name || !*name) return; shellUpdateCommonPrefix(state->Common, sizeof(state->Common), name, state->MatchCount); state->MatchCount++; state->LastIsDirectory = directory; state->LastAddsSpace = addsSpace; } // Collects builtin command matches for a command-position token. static void shellCollectBuiltinCompletions(const char* prefix, size_t prefixLength, SHELL_COMPLETION_STATE* state, bool printMatches) { size_t count = sizeof(gShellBuiltinCommands) / sizeof(gShellBuiltinCommands[0]); for (size_t i = 0; i < count; i++) { const char* name = gShellBuiltinCommands[i]; if (!shellNameStartsWith(name, prefix, prefixLength)) continue; if (printMatches) shellPrintCompletionCandidate(name, false); else shellRecordCompletion(state, name, false, true); } } // Splits a token into a directory to scan and a filename prefix to match. static bool shellSplitCompletionPath(const char* token, size_t tokenLength, char* dir, size_t dirSize, const char** prefixOut, size_t* prefixLengthOut) { if (!token || !dir || dirSize == 0 || !prefixOut || !prefixLengthOut) return false; size_t lastSeparator = (size_t)-1; for (size_t i = 0; i < tokenLength; i++) { if (shellIsPathSeparator(token[i])) lastSeparator = i; } if (lastSeparator == (size_t)-1) { if (dirSize < 2) return false; dir[0] = '.'; dir[1] = '\0'; *prefixOut = token; *prefixLengthOut = tokenLength; return true; } size_t dirLength = lastSeparator; if (lastSeparator == 0) dirLength = 1; if (lastSeparator >= 2 && token[1] == ':' && shellIsPathSeparator(token[2])) dirLength = lastSeparator + 1; if (dirLength + 1 > dirSize) return false; memcpy(dir, token, dirLength); dir[dirLength] = '\0'; *prefixOut = token + lastSeparator + 1; *prefixLengthOut = tokenLength - lastSeparator - 1; 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, bool printMatches) { char dir[MAX_CMD]; const char* prefix = token; size_t prefixLength = tokenLength; if (!shellSplitCompletionPath(token, tokenLength, dir, sizeof(dir), &prefix, &prefixLength)) return; uint32_t hDir = 0; if (open_dir(dir, &hDir) != 0) return; SYS_DIR_ENTRY entry; while (SysReadDir(hDir, &entry) == 0) { if (!entry.Name[0]) continue; if (!shellNameStartsWith(entry.Name, prefix, prefixLength)) continue; bool directory = (entry.Attr & 0x10u) != 0; if (printMatches) shellPrintCompletionCandidate(entry.Name, directory); else shellRecordCompletion(state, entry.Name, directory, true); } SysCloseHandle(hDir); } // Redraws the prompt and current edit buffer after a completion list. static void shellRedrawPromptAndLine(SHELL_EDITOR* editor) { print(SHELL_PROMPT); if (!editor) return; print(editor->Buffer); shellEditorMoveLeftCells(editor->Length - editor->Cursor); } // Completes the token around the current cursor position. static void shellCompleteLine(SHELL_EDITOR* editor) { if (!editor || !editor->Buffer || editor->Capacity <= 0 || editor->Cursor < 0) return; char* buf = editor->Buffer; size_t cursor = (size_t)editor->Cursor; size_t tokenStart = cursor; while (tokenStart > 0 && !shellIsTokenSeparator(buf[tokenStart - 1])) tokenStart--; size_t tokenEnd = cursor; while (tokenEnd < (size_t)editor->Length && !shellIsTokenSeparator(buf[tokenEnd])) tokenEnd++; const char* token = buf + tokenStart; size_t tokenLength = cursor - tokenStart; bool commandPosition = tokenStart == 0; bool explicitPath = shellTokenHasPathSeparator(token, tokenLength); char completionDir[MAX_CMD]; const char* namePrefix = token; size_t namePrefixLength = tokenLength; (void)shellSplitCompletionPath(token, tokenLength, completionDir, sizeof(completionDir), &namePrefix, &namePrefixLength); SHELL_COMPLETION_STATE state; memset(&state, 0, sizeof(state)); 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; 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) { if (state.LastIsDirectory) { if (editor->Cursor < editor->Capacity - 1 && editor->Cursor > 0 && !shellIsPathSeparator(buf[editor->Cursor - 1])) (void)shellEditorInsert(editor, "/"); } else if (state.LastAddsSpace) { if (editor->Cursor < editor->Capacity - 1 && (editor->Cursor == editor->Length || !shellIsTokenSeparator(buf[editor->Cursor]))) (void)shellEditorInsert(editor, " "); } return; } if (expanded) return; print("\n"); if (commandPosition && !explicitPath) { shellCollectBuiltinCompletions(token, tokenLength, NULL, true); } shellCollectResourceCompletions(token, tokenLength, NULL, true); shellCollectPathCompletions(token, tokenLength, NULL, true); shellRedrawPromptAndLine(editor); } // Reads one editable command line from the keyboard. static bool readLine(char* buf, int len) { SHELL_EDITOR editor; SHELL_VISIBLE_CURSOR visibleCursor; char historyDraft[MAX_CMD]; size_t historyCursor = gHistoryCount; if (len <= 0) return false; editor.Buffer = buf; editor.Capacity = len; editor.Length = 0; editor.Cursor = 0; memset(&visibleCursor, 0, sizeof(visibleCursor)); buf[0] = '\0'; historyDraft[0] = '\0'; while (true) { shellEditorShowVisibleCursor(&visibleCursor, &editor); INPUT_KEY_RECORD input; KSTATUS inputStatus = NtlInputReadEvent(SYS_HANDLE_INVALID, SYS_WAIT_TIMEOUT_INFINITE, &input); shellEditorHideVisibleCursor(&visibleCursor); if (inputStatus != NTLSTATUS_SUCCESS) { SysYield(); continue; } INPUT_KEY key = input.Key; if (key == INPUT_KEY_NONE) { SysYield(); continue; } uint32_t modifiers = input.Modifiers; if ((modifiers & INPUT_MOD_CTRL) && key == INPUT_KEY_C) { buf[0] = '\0'; print("^C\n"); return true; } if (key == INPUT_KEY_ENTER || key == INPUT_KEY_KP_ENTER) { print("\n"); break; } if (key == INPUT_KEY_ESCAPE) { shellEditorReplaceLine(&editor, ""); historyCursor = gHistoryCount; historyDraft[0] = '\0'; continue; } if (key == INPUT_KEY_BACKSPACE) { if (editor.Cursor > 0) (void)shellEditorReplaceRange(&editor, editor.Cursor - 1, editor.Cursor, ""); continue; } if (key == INPUT_KEY_DELETE) { if (editor.Cursor < editor.Length) (void)shellEditorReplaceRange(&editor, editor.Cursor, editor.Cursor + 1, ""); continue; } if (key == INPUT_KEY_LEFT) { shellEditorMoveCursor(&editor, editor.Cursor - 1); continue; } if (key == INPUT_KEY_RIGHT) { shellEditorMoveCursor(&editor, editor.Cursor + 1); continue; } if (key == INPUT_KEY_HOME) { shellEditorMoveCursor(&editor, 0); continue; } if (key == INPUT_KEY_END) { shellEditorMoveCursor(&editor, editor.Length); continue; } if (key == INPUT_KEY_UP) { if (historyCursor > 0) { if (historyCursor == gHistoryCount) { strncpy(historyDraft, editor.Buffer, sizeof(historyDraft) - 1); historyDraft[sizeof(historyDraft) - 1] = '\0'; } historyCursor--; shellEditorReplaceLine(&editor, gHistory[historyCursor]); } continue; } if (key == INPUT_KEY_DOWN) { if (historyCursor < gHistoryCount) { historyCursor++; shellEditorReplaceLine(&editor, historyCursor < gHistoryCount ? gHistory[historyCursor] : historyDraft); } continue; } if (key == INPUT_KEY_TAB) { shellCompleteLine(&editor); continue; } char c = input.Char ? input.Char : shellKeyToChar(key, modifiers); if (c < 0x20 || c == 127) continue; char text[2] = { c, '\0' }; (void)shellEditorInsert(&editor, text); } return false; } // Implements the trim operation. static char* trim(char* s) { while (*s == ' ') s++; int len = (int)strlen(s); while (len > 0 && s[len - 1] == ' ') len--; s[len] = '\0'; return s; } // Built-in commands. static void cmd_help() { print("Available commands:\n" " help - Show this list\n" " mem - Show memory usage\n" " time - Show system wall-clock time\n" " display - Show display provider and counters\n" " surfbench - Benchmark Doom-size and full-screen surface commits\n" " stats - Show scheduler/CPU/MM telemetry\n" " ps - List processes\n" " threads - Show one process's thread statuses\n" " kill - Terminate a process\n" " dir [path] - List directory contents\n" " cd - Change directory\n" " type - Display file contents\n" " volume [0-100] - Query or set master audio volume\n" " volume mute - Mute the default audio endpoint\n" " volume unmute - Unmute the default audio endpoint\n" " del - Delete a file\n" " write - Create a file with text\n" " clear - Clear the screen\n" " shutdown - Request system shutdown\n" " reboot - Request system restart\n" " exit - Close the shell\n"); } // Prints size Ki B. static void printSizeKiB(uint64_t bytes) { printUInt64(bytes / 1024u); print(" KiB"); } // Prints pages Ki B. static void printPagesKiB(uint64_t pages) { printUInt64(pages * 4u); print(" KiB"); } // Prints cpu Flags. static void printCpuFlags(uint32_t flags) { if (flags & SYS_CPU_FLAG_BOOT_PROCESSOR) print("boot "); if (flags & SYS_CPU_FLAG_ONLINE) print("online "); if (flags & SYS_CPU_FLAG_PARKED) print("parked "); if (flags & SYS_CPU_FLAG_PRIMARY) print("primary "); if (flags & SYS_CPU_FLAG_STARTED) print("started "); if (flags & SYS_CPU_FLAG_PRESENT) print("present "); } // Selects the available default audio endpoint, or the first available endpoint. static bool shellQueryDefaultAudioEndpoint(SYS_AUDIO_ENDPOINT_INFO* endpointOut) { if (!endpointOut) return false; SYS_AUDIO_ENDPOINT_INFO endpoints[SYS_AUDIO_MAX_ENDPOINTS]; uint32_t count = 0; SYS_AUDIO_ENUMERATE_ENDPOINTS_REQUEST request; memset(&request, 0, sizeof(request)); request.Size = sizeof(request); request.Endpoints = endpoints; request.Capacity = SYS_AUDIO_MAX_ENDPOINTS; request.CountOut = &count; KSTATUS status = SysAudioEnumerateEndpoints(&request); if (status != NTLSTATUS_SUCCESS && status != NTLSTATUS_BUFFER_TOO_SMALL) { print("volume: endpoint query failed status="); printUInt(status); print("\n"); return false; } const SYS_AUDIO_ENDPOINT_INFO* fallback = NULL; uint32_t availableCount = count < SYS_AUDIO_MAX_ENDPOINTS ? count : SYS_AUDIO_MAX_ENDPOINTS; for (uint32_t index = 0; index < availableCount; index++) { const SYS_AUDIO_ENDPOINT_INFO* endpoint = &endpoints[index]; if (endpoint->Size != sizeof(*endpoint) || endpoint->Version != SYS_AUDIO_ABI_VERSION || endpoint->State != SysAudioEndpointReady || (endpoint->Flags & SYS_AUDIO_ENDPOINT_FLAG_AVAILABLE) == 0) continue; if (!fallback) fallback = endpoint; if (endpoint->Flags & SYS_AUDIO_ENDPOINT_FLAG_DEFAULT) { *endpointOut = *endpoint; return true; } } if (fallback) { *endpointOut = *fallback; return true; } print("volume: no available audio endpoint\n"); return false; } // Converts one public Q16 gain into a rounded percentage. static uint32_t shellAudioVolumePercent(uint32_t volumeQ16) { uint64_t scaled = (uint64_t)volumeQ16 * 100u + SYS_AUDIO_GAIN_Q16_UNITY / 2u; return (uint32_t)(scaled / SYS_AUDIO_GAIN_Q16_UNITY); } // Converts one percentage into public Q16 gain. static uint32_t shellAudioVolumeQ16(uint32_t percent) { return (uint32_t)(((uint64_t)percent * SYS_AUDIO_GAIN_Q16_UNITY + 50u) / 100u); } // Queries or updates the default endpoint master volume. static void cmd_volume(const char* args) { SYS_AUDIO_ENDPOINT_INFO endpoint; if (!shellQueryDefaultAudioEndpoint(&endpoint)) return; while (args && (*args == ' ' || *args == '\t')) args++; if (!args || *args == '\0') { print("Volume: "); printUInt(shellAudioVolumePercent(endpoint.MasterVolumeQ16)); print("%"); if (endpoint.MasterMuted) print(" (muted)"); print("\n"); return; } uint32_t volumeQ16 = endpoint.MasterVolumeQ16; uint32_t muted = endpoint.MasterMuted ? 1u : 0u; if (strcmp(args, "mute") == 0) { muted = 1u; } else if (strcmp(args, "unmute") == 0) { muted = 0u; } else { uint32_t percent = 0; if (!parseUInt(args, &percent) || percent > 100u) { print("Usage: volume [0-100|mute|unmute]\n"); return; } volumeQ16 = shellAudioVolumeQ16(percent); muted = 0u; } SYS_AUDIO_SET_MASTER_VOLUME_REQUEST request; memset(&request, 0, sizeof(request)); request.Size = sizeof(request); request.EndpointId = endpoint.EndpointId; request.Muted = muted; request.VolumeQ16 = volumeQ16; KSTATUS status = SysAudioSetMasterVolume(&request); if (status != NTLSTATUS_SUCCESS) { print("volume: update failed status="); printUInt(status); print("\n"); return; } print("Volume: "); printUInt(shellAudioVolumePercent(volumeQ16)); print("%"); if (muted) print(" (muted)"); print("\n"); } // Implements the cmd stats operation. static void cmd_stats(void) { SYS_SCHEDULER_STATS sched; SYS_PMM_STATS pmm; SYS_CPU_STATS* cpu = 0; void* cpuBuffer = 0; SYS_PFN_STATS pfn; SYS_VAD_STATS vad; SYS_SWAP_STATS swap; SYS_FILE_CACHE_STATS fileCache; SYS_FILESYSTEM_STATS filesystem; SYS_DISK_STATS disk; SYS_PTE_STATS pte; SYS_SURFACE_STATS surface; SYS_EXCEPTION_STATS exceptionStats; KSTATUS status; status = SysQueryKernelStats(SYS_KERNEL_STATS_SCHEDULER, &sched, sizeof(sched), NULL); if (status != 0) { print("stats: scheduler query failed: "); printUInt(status); print("\n"); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_PMM, &pmm, sizeof(pmm), NULL); if (status != 0) { print("stats: pmm query failed: "); printUInt(status); print("\n"); return; } size_t cpuSize = 0; status = SysQueryKernelStats(SYS_KERNEL_STATS_CPU, 0, 0, &cpuSize); if (status != 0 || cpuSize < sizeof(SYS_CPU_STATS)) { print("stats: cpu size query failed: "); printUInt(status); print("\n"); return; } size_t cpuPages = (cpuSize + 4095u) / 4096u; if (cpuPages == 0) cpuPages = 1; SYS_ALLOC_VM_REQUEST allocReq; memset(&allocReq, 0, sizeof(allocReq)); allocReq.Size = sizeof(allocReq); allocReq.PageCount = cpuPages; allocReq.Protect = SYS_VM_READWRITE; allocReq.Flags = SYS_VM_FLAG_NONE; allocReq.BaseOut = &cpuBuffer; status = SysAllocVm(&allocReq); if (status != 0 || !cpuBuffer) { print("stats: cpu buffer allocation failed: "); printUInt(status); print("\n"); return; } cpu = (SYS_CPU_STATS*)cpuBuffer; status = SysQueryKernelStats(SYS_KERNEL_STATS_CPU, cpu, cpuPages * 4096u, NULL); if (status != 0) { print("stats: cpu query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_PFN, &pfn, sizeof(pfn), NULL); if (status != 0) { print("stats: pfn query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_VAD, &vad, sizeof(vad), NULL); if (status != 0) { print("stats: vad query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_SWAP, &swap, sizeof(swap), NULL); if (status != 0) { print("stats: swap query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_FILE_CACHE, &fileCache, sizeof(fileCache), NULL); if (status != 0) { print("stats: file cache query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_FILESYSTEM, &filesystem, sizeof(filesystem), NULL); if (status != 0) { print("stats: filesystem query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_DISK, &disk, sizeof(disk), NULL); if (status != 0) { print("stats: disk query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_PTE, &pte, sizeof(pte), NULL); if (status != 0) { print("stats: pte query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_SURFACE, &surface, sizeof(surface), NULL); if (status != 0) { print("stats: surface query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_EXCEPTION, &exceptionStats, sizeof(exceptionStats), NULL); if (status != 0) { print("stats: exception query failed: "); printUInt(status); print("\n"); SysFreeVm(cpuBuffer); return; } print("Scheduler:\n"); print(" ticks: "); printUInt64(sched.Ticks); print("\n"); print(" context switches: "); printUInt64(sched.ContextSwitches); print("\n"); print(" quantum expires: "); printUInt64(sched.QuantumExpirations); print("\n"); print(" priority preempts: "); printUInt64(sched.PriorityPreemptions); print("\n"); print(" idle selections: "); printUInt64(sched.IdleSelections); print("\n"); print(" keep-current: "); printUInt64(sched.KeepCurrentDecisions); print("\n"); print(" demotions: "); printUInt64(sched.Demotions); print("\n"); print(" aging promotions: "); printUInt64(sched.AgingPromotions); print("\n"); print(" voluntary blocks: "); printUInt64(sched.VoluntaryBlocks); print("\n"); print(" SMT deferrals: "); printUInt64(sched.SmtSiblingDeferrals); print("\n"); print(" SMT primary pokes: "); printUInt64(sched.SmtPrimaryPokes); print("\n"); print(" RT dispatches: "); printUInt64(sched.RealtimeDispatches); print("\n"); print(" RT preemptions: "); printUInt64(sched.RealtimePreemptions); print("\n"); print(" PI boosts: "); printUInt64(sched.PriorityInheritanceBoosts); print("\n"); print(" PI drops: "); printUInt64(sched.PriorityInheritanceDrops); print("\n"); print(" PI propagations: "); printUInt64(sched.PriorityInheritancePropagations); print("\n"); print(" PI max depth: "); printUInt64(sched.PriorityInheritanceMaxDepth); print("\n"); print("Exceptions:\n"); print(" delivered: "); printUInt64(exceptionStats.Delivered); print("\n"); print(" user-raised: "); printUInt64(exceptionStats.UserRaised); print("\n"); print(" continued: "); printUInt64(exceptionStats.Continued); print("\n"); print(" unhandled: "); printUInt64(exceptionStats.Unhandled); print("\n"); print(" invalid continue: "); printUInt64(exceptionStats.InvalidContinue); print("\n"); print(" max nesting: "); printUInt(exceptionStats.MaxNestedDispatch); print("\n"); print(" last code: "); printUInt(exceptionStats.LastCode); print("\n"); print("CPUs:\n"); const SYS_CPU_STAT* cpuRecords = SYS_CPU_STATS_CONST_RECORDS(cpu); uint32_t n = cpu->RecordCount; for (uint32_t i = 0; i < n; i++) { const SYS_CPU_STAT* c = &cpuRecords[i]; print(" cpu"); printUInt(c->CpuIndex); print(" hardware="); printUInt(c->HardwareId); print(" current="); if (c->CurrentThreadFlags & SYS_CPU_THREAD_FLAG_IDLE) { print("idle/"); printUInt(c->CpuIndex); } else { print("tid/"); printUInt(c->CurrentTid); } print(" ticks="); printUInt64(c->SchedulerTicks); print(" switches="); printUInt64(c->ContextSwitches); print(" flags="); printCpuFlags(c->Flags); print("\n"); } print("Physical memory:\n"); print(" total: "); printPagesKiB(pmm.TotalFrames); print(" (frames="); printUInt64(pmm.TotalFrames); print(")\n"); print(" used: "); printPagesKiB(pmm.UsedFrames); print(" (frames="); printUInt64(pmm.UsedFrames); print(")\n"); print(" free: "); printPagesKiB(pmm.FreeFrames); print(" (frames="); printUInt64(pmm.FreeFrames); print(")\n"); print(" largest free run: "); printPagesKiB(pmm.LargestFreeRun); print(" (frames="); printUInt64(pmm.LargestFreeRun); print(")\n"); print(" free runs: "); printUInt64(pmm.FreeRunCount); print("\n"); print(" available+reclaim: "); printSizeKiB(pfn.AvailableFrames * 4096ull); print(" (reclaimable="); printSizeKiB(pfn.ReclaimableFrames * 4096ull); print(")\n"); print(" run histogram:\n"); print(" 1: "); printUInt64(pmm.FreeRunHistogram[0]); print("\n"); print(" 2-3: "); printUInt64(pmm.FreeRunHistogram[1]); print("\n"); print(" 4-7: "); printUInt64(pmm.FreeRunHistogram[2]); print("\n"); print(" 8-15: "); printUInt64(pmm.FreeRunHistogram[3]); print("\n"); print(" 16-63: "); printUInt64(pmm.FreeRunHistogram[4]); print("\n"); print(" 64-255: "); printUInt64(pmm.FreeRunHistogram[5]); print("\n"); print(" 256-1023: "); printUInt64(pmm.FreeRunHistogram[6]); print("\n"); print(" 1024+: "); printUInt64(pmm.FreeRunHistogram[7]); print("\n"); print("PFN database:\n"); print(" states: active="); printUInt64(pfn.ActiveFrames); print(" free="); printUInt64(pfn.FreeFrames); print(" zeroed="); printUInt64(pfn.ZeroedFrames); print(" standby="); printUInt64(pfn.StandbyFrames); print(" modified="); printUInt64(pfn.ModifiedFrames); print(" reserved="); printUInt64(pfn.ReservedFrames); print("\n"); print(" eviction: evictable="); printUInt64(pfn.EvictableFrames); print(" reclaimable="); printUInt64(pfn.ReclaimableFrames); print(" available="); printUInt64(pfn.AvailableFrames); print(" mapped="); printUInt64(pfn.MappedFrames); print(" non-evictable="); printUInt64(pfn.NonEvictableFrames); print(" pinned="); printUInt64(pfn.PinnedFrames); print("\n"); print(" usage frames: kernel="); printUInt64(pfn.KernelFrames); print(" pt="); printUInt64(pfn.PageTableFrames); print(" user="); printUInt64(pfn.UserFrames); print(" driver="); printUInt64(pfn.DriverFrames); print(" dma="); printUInt64(pfn.DmaFrames); print(" boot="); printUInt64(pfn.BootloaderFrames); print(" pfn-db="); printUInt64(pfn.PfnDatabaseFrames); print(" mmio="); printUInt64(pfn.MmioFrames); print("\n"); print(" buckets: clean-file="); printUInt64(pfn.CleanFileCacheFrames); print(" (active="); printUInt64(pfn.ActiveCleanFileCacheFrames); print(" standby="); printUInt64(pfn.StandbyCleanFileCacheFrames); print(")"); print(" image="); printUInt64(pfn.ImageFrames); print(" (active="); printUInt64(pfn.ActiveImageFrames); print(" standby="); printUInt64(pfn.StandbyImageFrames); print(")"); print(" mapped-file="); printUInt64(pfn.MappedFileFrames); print(" anon="); printUInt64(pfn.AnonymousFrames); print(" cow="); printUInt64(pfn.CowFrames); print(" surface="); printUInt64(pfn.SurfaceFrames); print("\n"); print(" operations: alloc="); printUInt64(pfn.AllocationCount); print(" free="); printUInt64(pfn.FreeCount); print(" retain="); printUInt64(pfn.RetainCount); print(" release="); printUInt64(pfn.ReleaseCount); print(" pin="); printUInt64(pfn.PinCount); print(" unpin="); printUInt64(pfn.UnpinCount); print("\n"); print(" failures: alloc="); printUInt64(pfn.FailedAllocations); print(" contiguous="); printUInt64(pfn.FailedContiguousAllocations); print("\n"); print(" alloc reasons: invalid-range="); printUInt64(pfn.FailedInvalidRange); print(" empty-range="); printUInt64(pfn.FailedEmptyRange); print(" reserve-denied="); printUInt64(pfn.FailedReserveDenied); print(" no-frame="); printUInt64(pfn.FailedNoFrame); print("\n"); print(" contig reasons: invalid="); printUInt64(pfn.FailedContiguousInvalidRequest); print(" reserve-denied="); printUInt64(pfn.FailedContiguousReserveDenied); print(" no-run="); printUInt64(pfn.FailedContiguousNoRun); print("\n"); print(" reclaim: attempts="); printUInt64(pfn.ReclaimAttempts); print(" requested="); printUInt64(pfn.ReclaimPagesRequested); print(" succeeded="); printUInt64(pfn.ReclaimPagesSucceeded); print(" failed="); printUInt64(pfn.ReclaimPagesFailed); print(" reentrant-skips="); printUInt64(pfn.ReclaimReentrantSkips); print("\n"); print("VAD faults:\n"); print(" resolve: calls="); printUInt64(vad.ResolveFaultCalls); print(" resolved="); printUInt64(vad.ResolvedFaults); print(" failed="); printUInt64(vad.FailedFaults); print("\n"); print(" failure reasons: protection="); printUInt64(vad.ProtectionFaults); print(" no-vad="); printUInt64(vad.NoVadFaults); print(" uncommitted="); printUInt64(vad.UncommittedFaults); print(" noaccess="); printUInt64(vad.NoAccessFaults); print("\n"); print(" materialization: demand-zero="); printUInt64(vad.DemandZeroPages); print(" zero-maps="); printUInt64(vad.ZeroPageMaps); print(" zero-splits="); printUInt64(vad.ZeroPageCowSplits); print(" ensure-calls="); printUInt64(vad.EnsureResidentCalls); print(" ensure-pages="); printUInt64(vad.EnsureResidentPages); print(" already-resident="); printUInt64(vad.AlreadyResidentPages); print("\n"); print(" cow: faults="); printUInt64(vad.CowFaults); print(" copied="); printUInt64(vad.CowPagesCopied); print(" views="); printUInt64(vad.CowViewsCreated); print(" shared-pages="); printUInt64(vad.CowPagesShared); print("\n"); print(" file-backed: faults="); printUInt64(vad.FileBackedFaults); print(" reads="); printUInt64(vad.FileBackedReads); print(" read-fail="); printUInt64(vad.FileBackedReadFailures); print(" discards="); printUInt64(vad.FileBackedDiscards); print("\n"); print(" mapped-file: shared-faults="); printUInt64(vad.FileBackedSharedWritableFaults); print(" dirty-faults="); printUInt64(vad.FileBackedDirtyFaults); print(" dirty-syncs="); printUInt64(vad.FileBackedDirtySyncs); print("\n"); print(" image-backed: faults="); printUInt64(vad.ImageBackedFaults); print(" zero-faults="); printUInt64(vad.ImageBackedZeroFaults); print(" private-faults="); printUInt64(vad.ImageBackedPrivateFaults); print("\n"); print(" image fixups: calls="); printUInt64(vad.ImageFixupPrivateCalls); print(" private-pages="); printUInt64(vad.ImageFixupPrivatePages); print("\n"); print(" swap-backed: page-outs="); printUInt64(vad.SwapPageOuts); print(" page-ins="); printUInt64(vad.SwapPageIns); print("\n"); print("Swap:\n"); print(" enabled: "); printUInt64(swap.Enabled); print("\n"); print(" slots: total="); printUInt64(swap.TotalSlots); print(" used="); printUInt64(swap.UsedSlots); print(" free="); printUInt64(swap.FreeSlots); print(" high-water="); printUInt64(swap.HighWaterSlots); print("\n"); print(" io: out="); printUInt64(swap.PageOuts); print(" in="); printUInt64(swap.PageIns); print(" out-fail="); printUInt64(swap.PageOutFailures); print(" in-fail="); printUInt64(swap.PageInFailures); print("\n"); print(" slots ops: alloc="); printUInt64(swap.SlotAllocations); print(" free="); printUInt64(swap.SlotFrees); print(" alloc-fail="); printUInt64(swap.SlotAllocationFailures); print("\n"); print("File cache:\n"); print(" lookups: total="); printUInt64(fileCache.Lookups); print(" hits="); printUInt64(fileCache.Hits); print(" misses="); printUInt64(fileCache.Misses); print("\n"); print(" loads: ok="); printUInt64(fileCache.Loads); print(" fail="); printUInt64(fileCache.LoadFailures); print(" races="); printUInt64(fileCache.RaceDiscards); print(" waits="); printUInt64(fileCache.InflightWaits); print("\n"); print(" lifetime: resident="); printUInt64(fileCache.ResidentPages); print(" active="); printUInt64(fileCache.ActivePages); print(" standby="); printUInt64(fileCache.StandbyPages); print(" max="); printUInt64(fileCache.MaxResidentPages); print(" invalidations="); printUInt64(fileCache.Invalidations); print("\n"); print(" dirty/writeback: dirty="); printUInt64(fileCache.DirtyPages); print(" max-dirty="); printUInt64(fileCache.MaxDirtyPages); print(" marks="); printUInt64(fileCache.DirtyMarks); print(" wb-req="); printUInt64(fileCache.WritebackRequests); print(" wb-pages="); printUInt64(fileCache.WritebackPages); print(" wb-bytes="); printUInt64(fileCache.WritebackBytes); print(" wb-fail="); printUInt64(fileCache.WritebackFailures); print("\n"); print(" mapped dirty: syncs="); printUInt64(fileCache.MappedDirtySyncs); print(" pages="); printUInt64(fileCache.MappedDirtyPages); print("\n"); print(" flushes: calls="); printUInt64(fileCache.FlushFileCalls); print(" fail="); printUInt64(fileCache.FlushFileFailures); print("\n"); print(" reclaim: drops="); printUInt64(fileCache.Drops); print(" standby="); printUInt64(fileCache.StandbyTransitions); print(" standby-hits="); printUInt64(fileCache.StandbyHits); print(" drop-fail="); printUInt64(fileCache.DropFailures); print("\n"); print("Filesystem:\n"); print(" path cache: lookups="); printUInt64(filesystem.PathLookups); print(" hits="); printUInt64(filesystem.PathCacheHits); print(" misses="); printUInt64(filesystem.PathCacheMisses); print(" stores="); printUInt64(filesystem.PathCacheStores); print("\n"); print(" invalidation: count="); printUInt64(filesystem.PathCacheInvalidations); print(" generation="); printUInt64(filesystem.PathCacheGeneration); print("\n"); print(" directory search: searches="); printUInt64(filesystem.DirectorySearches); print(" blocks="); printUInt64(filesystem.DirectoryBlocksRead); print(" entries="); printUInt64(filesystem.DirectoryEntriesScanned); print("\n"); print(" data read spans: runs="); printUInt64(filesystem.DataReadRuns); print(" sectors="); printUInt64(filesystem.DataReadSectors); print(" merges="); printUInt64(filesystem.DataReadRunMerges); print(" max-sectors="); printUInt64(filesystem.MaxDataReadSpanSectors); print("\n"); print("Disk I/O:\n"); print(" devices: registered="); printUInt64(disk.RegisteredDisks); print("\n"); print(" reads: requests="); printUInt64(disk.ReadRequests); print(" sectors="); printUInt64(disk.ReadSectors); print(" max-sectors="); printUInt64(disk.MaxReadSectors); print("\n"); print(" writes: requests="); printUInt64(disk.WriteRequests); print(" sectors="); printUInt64(disk.WriteSectors); print(" max-sectors="); printUInt64(disk.MaxWriteSectors); print("\n"); print("Surfaces:\n"); print(" lifetime: created="); printUInt64(surface.CreatedSurfaces); print(" destroyed="); printUInt64(surface.DestroyedSurfaces); print(" live="); printUInt64(surface.LiveSurfaces); print("\n"); print(" live memory: pages="); printUInt64(surface.LivePages); print(" bytes="); printUInt64(surface.LiveBytes); 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"); print(" page-table pages: "); printUInt64(pte.PageTablePagesAllocated); print("\n"); print(" map/unmap: map="); printUInt64(pte.MapCalls); print(" failed="); printUInt64(pte.MapFailures); print(" unmap="); printUInt64(pte.UnmapCalls); print(" failed="); printUInt64(pte.UnmapFailures); print("\n"); print(" protect: calls="); printUInt64(pte.ProtectCalls); print(" failed="); printUInt64(pte.ProtectFailures); print("\n"); print(" query: total="); printUInt64(pte.QueryCalls); print(" failed="); printUInt64(pte.QueryFailures); print(" translate="); printUInt64(pte.TranslateCalls); print("\n"); print(" generic: "); printUInt64(pte.QueryByPurpose[SYS_PTE_QUERY_GENERIC]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[SYS_PTE_QUERY_GENERIC]); print("\n"); print(" user-probe: "); printUInt64(pte.QueryByPurpose[SYS_PTE_QUERY_USER_PROBE]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[SYS_PTE_QUERY_USER_PROBE]); print("\n"); print(" heap: "); printUInt64(pte.QueryByPurpose[SYS_PTE_QUERY_HEAP]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[SYS_PTE_QUERY_HEAP]); print("\n"); print(" vad: "); printUInt64(pte.QueryByPurpose[SYS_PTE_QUERY_VAD]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[SYS_PTE_QUERY_VAD]); print("\n"); print(" debug: "); printUInt64(pte.QueryByPurpose[SYS_PTE_QUERY_DEBUG]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[SYS_PTE_QUERY_DEBUG]); print("\n"); print(" self-test: "); printUInt64(pte.QueryByPurpose[SYS_PTE_QUERY_SELF_TEST]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[SYS_PTE_QUERY_SELF_TEST]); print("\n"); print(" tlb: local="); printUInt64(pte.LocalFlushes); print(" global="); printUInt64(pte.GlobalFlushes); print(" new-map-skip="); printUInt64(pte.NewMappingNoFlushes); print(" replace-flush="); printUInt64(pte.ReplacedMappingFlushes); print("\n"); print(" shootdowns: requests="); printUInt64(pte.ShootdownRequests); print(" targets="); printUInt64(pte.ShootdownTargetCpus); print(" skipped="); printUInt64(pte.ShootdownSkippedNoTargets); print(" acks="); printUInt64(pte.ShootdownAcks); print(" timeouts="); printUInt64(pte.ShootdownTimeouts); print("\n"); SysFreeVm(cpuBuffer); } // Implements the cmd time operation. static void cmd_time(void) { SYS_SYSTEM_TIME t; KSTATUS status = SysGetSystemTime(&t); if (status != 0) { print("time: failed: "); printUInt(status); print("\n"); return; } printUIntZeroWidth(t.Year, 4); print("-"); printUIntZeroWidth(t.Month, 2); print("-"); printUIntZeroWidth(t.Day, 2); print(" "); printUIntZeroWidth(t.Hour, 2); print(":"); printUIntZeroWidth(t.Minute, 2); print(":"); printUIntZeroWidth(t.Second, 2); print("."); printUIntZeroWidth(t.Millisecond, 3); print(" epoch="); printUInt64(t.EpochSeconds); print(" flags=0x"); printUInt(t.Flags); if (t.Flags & SYS_TIME_FLAG_TZ_KNOWN) { print(" tz="); printInt(t.TimeZoneMinutes); } else { print(" tz=unspecified"); } print("\n"); } // Prints display Caps. static void printDisplayCaps(uint32_t caps) { bool any = false; if (caps & DISPLAY_CAP_FRAMEBUFFER) { print("framebuffer"); any = true; } if (caps & DISPLAY_CAP_SOFTWARE_CURSOR) { if (any) print(","); print("software-cursor"); any = true; } if (caps & DISPLAY_CAP_HARDWARE_CURSOR) { if (any) print(","); print("hardware-cursor"); any = true; } if (caps & DISPLAY_CAP_ACCEL_FILL) { if (any) print(","); print("accel-fill"); any = true; } if (caps & DISPLAY_CAP_ACCEL_COPY) { if (any) print(","); print("accel-copy"); any = true; } if (caps & DISPLAY_CAP_PRESENT_SYNC) { if (any) print(","); print("present-sync"); any = true; } if (caps & DISPLAY_CAP_VBLANK) { if (any) print(","); print("vblank"); any = true; } if (caps & DISPLAY_CAP_3D) { if (any) print(","); print("3d"); any = true; } if (!any) print("none"); } // Prints display Stats. static void printDisplayStats(const char* title, const DISPLAY_STATS* st) { print(title); print(":\n"); print(" blit: "); printUInt64(st->BlitCount); print("\n"); print(" fill: "); printUInt64(st->FillRectCount); print("\n"); print(" copy: "); printUInt64(st->CopyRectCount); print("\n"); print(" read: "); printUInt64(st->ReadRectCount); print("\n"); print(" present: "); printUInt64(st->PresentCount); print(" rects="); printUInt64(st->PresentRectCount); print(" direct="); printUInt64(st->DirectPresentCount); print("\n"); print(" dirty: "); printUInt64(st->DirtyRectCount); print(" all="); printUInt64(st->DirtyAllCount); print("\n"); print(" bytes: logical="); printUInt64(st->BytesCopied); print(" scanout="); printUInt64(st->ScanoutBytes); print("\n"); print(" sync: "); printUInt64(st->SyncCount); print("\n"); print(" cursor: move="); printUInt64(st->CursorMoveCount); print(" show="); printUInt64(st->CursorShowCount); print(" hide="); printUInt64(st->CursorHideCount); print("\n"); } // Implements the cmd display operation. static void cmd_display(void) { SYS_DISPLAY_INFO info; KSTATUS status = SysQueryDisplayInfo(&info); if (status != 0) { print("display: query failed: "); printUInt(status); print("\n"); return; } print("Display:\n"); print(" primary: "); print(info.PrimaryName[0] ? info.PrimaryName : "?"); print("\n"); print(" devices: "); printUInt(info.DeviceCount); print("\n"); print(" mode: "); printUInt(info.Mode.Width); print("x"); printUInt(info.Mode.Height); print(" stride="); printUInt(info.Mode.Stride); print(" format="); printUInt((uint32_t)info.Mode.Format); print("\n"); print(" caps: 0x"); printHex32(info.Caps); print(" ["); printDisplayCaps(info.Caps); print("]\n"); print(" scanout: "); print((info.Flags & DISPLAY_INFO_FLAG_PAT_WC_AVAILABLE) ? "PAT WC available" : "PAT WC unavailable"); print("\n"); printDisplayStats("Manager counters", &info.ManagerStats); printDisplayStats("Provider counters", &info.DeviceStats); } typedef struct SHELL_FB_BENCH_RESULT { uint32_t Width; uint32_t Height; uint32_t Frames; KSTATUS Status; uint64_t ElapsedTicks; uint64_t Frequency; uint64_t CommitBytes; } SHELL_FB_BENCH_RESULT; // Computes a decimal fixed-point ratio with one digit after the decimal point. static uint64_t shellRatioTenths(uint64_t numerator, uint64_t denominator) { if (!denominator) return 0; if (numerator > UINT64_MAX / 10u) return (numerator / denominator) * 10u; return (numerator * 10u) / denominator; } // Fills a benchmark surface with a deterministic high-contrast pattern. static void shellFillBenchmarkSurface(uint32_t* pixels, uint32_t pitchPixels, uint32_t width, uint32_t height) { for (uint32_t y = 0; y < height; y++) { uint32_t* row = pixels + (size_t)y * pitchPixels; for (uint32_t x = 0; x < width; x++) { uint32_t red = (x * 255u) / (width ? width : 1u); uint32_t green = (y * 255u) / (height ? height : 1u); uint32_t blue = ((x ^ y) & 0xFFu); row[x] = (red << 16) | (green << 8) | blue; } } } // Runs one synchronous surface-commit benchmark case. static void shellRunFramebufferBenchmark(uint32_t width, uint32_t height, uint32_t frames, uint64_t frequency, SHELL_FB_BENCH_RESULT* result) { memset(result, 0, sizeof(*result)); result->Width = width; result->Height = height; result->Frames = frames; result->Frequency = frequency; uint32_t surface = 0; SYS_CREATE_SURFACE_REQUEST create; memset(&create, 0, sizeof(create)); create.Size = sizeof(create); create.Width = width; create.Height = height; create.Format = SYS_SURFACE_FORMAT_XRGB8888; create.Flags = SYS_SURFACE_FLAG_NONE; create.HandleOut = &surface; KSTATUS status = SysCreateSurface(&create); if (status != NTLSTATUS_SUCCESS || !surface) { result->Status = status ? status : NTLSTATUS_FAILURE; return; } void* base = 0; uint32_t pitchBytes = 0; 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); return; } 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 && 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 = SysCommitSurface(surface, &rect, 1, 0); if (status != NTLSTATUS_SUCCESS) break; } end = SysGetTick(); } result->Frames = completed; result->Status = status; result->ElapsedTicks = end - begin; result->CommitBytes = (uint64_t)width * (uint64_t)height * sizeof(uint32_t) * completed; (void)SysUnmapSurface(base); SysCloseHandle(surface); } // Prints one framebuffer benchmark result. static void shellPrintFramebufferBenchmark(const char* name, const SHELL_FB_BENCH_RESULT* result) { print(" "); print(name); print(" "); printUInt(result->Width); print("x"); printUInt(result->Height); print(": "); if (result->Status != NTLSTATUS_SUCCESS || !result->ElapsedTicks || !result->Frequency) { print("failed status=0x"); printHex32(result->Status); print("\n"); return; } uint64_t elapsedUs = SysTicksToMicroseconds(result->ElapsedTicks, result->Frequency); uint64_t fpsTenths = shellRatioTenths((uint64_t)result->Frames * result->Frequency, result->ElapsedTicks); 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(" payload="); printUInt64(mibTenths / 10u); print("."); printUInt64(mibTenths % 10u); print(" MiB/s"); print(" bytes="); printUInt64(result->CommitBytes); print("\n"); } // Benchmarks surface commit bookkeeping without implying physical presentation. static void cmd_surfbench(void) { SYS_DISPLAY_INFO info; KSTATUS status = SysQueryDisplayInfo(&info); if (status != NTLSTATUS_SUCCESS) { 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("surfbench: timer query failed status=0x"); printHex32(status); print("\n"); return; } uint32_t doomWidth = info.Mode.Width < 960u ? info.Mode.Width : 960u; uint32_t doomHeight = info.Mode.Height < 600u ? info.Mode.Height : 600u; uint32_t fullWidth = info.Mode.Width; uint32_t fullHeight = info.Mode.Height; uint64_t targetBytes = 128ull * 1024ull * 1024ull; uint64_t doomFrameBytes = (uint64_t)doomWidth * doomHeight * sizeof(uint32_t); uint64_t fullFrameBytes = (uint64_t)fullWidth * fullHeight * sizeof(uint32_t); uint32_t doomFrames = doomFrameBytes ? (uint32_t)((targetBytes + doomFrameBytes - 1u) / doomFrameBytes) : 1u; uint32_t fullFrames = fullFrameBytes ? (uint32_t)((targetBytes + fullFrameBytes - 1u) / fullFrameBytes) : 1u; if (doomFrames < 8u) doomFrames = 8u; if (doomFrames > 128u) doomFrames = 128u; if (fullFrames < 8u) fullFrames = 8u; if (fullFrames > 64u) fullFrames = 64u; 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); 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); print(" stride="); printUInt(info.Mode.Stride); print(" cache="); print((info.Flags & DISPLAY_INFO_FLAG_PAT_WC_AVAILABLE) ? "PAT-WC" : "fallback"); print("\n"); shellPrintFramebufferBenchmark("doom", &doom); shellPrintFramebufferBenchmark("full", &full); } // Implements the cmd mem operation. static void cmd_mem(void) { SYS_MEMORY_STATUS st; if (SysGetMemoryStatus(&st) != 0) { print("mem: failed\n"); return; } print("Memory Status:\n"); print(" Free physical: "); printSizeKiB(st.FreePhysicalBytes); print("\n Reclaimable: "); printSizeKiB(st.ReclaimablePhysicalBytes); print("\n Available physical: "); printSizeKiB(st.AvailablePhysicalBytes); print("\n Pinned physical: "); printSizeKiB(st.PinnedPhysicalBytes); print("\n Non-evictable: "); printSizeKiB(st.NonEvictablePhysicalBytes); print("\n User frames: "); printSizeKiB(st.UserPhysicalBytes); print("\n Page tables: "); printSizeKiB(st.PageTablePhysicalBytes); print("\n Kernel pool: "); printSizeKiB(st.KernelPoolBytes); print("\n User heap: "); printSizeKiB(st.UserHeapBytes); print("\n"); } // Processes state Name. static const char* processStateName(uint32_t state) { switch (state) { case SYS_PROCESS_STATE_RUNNING: return "run"; case SYS_PROCESS_STATE_TERMINATING: return "term"; case SYS_PROCESS_STATE_EXITED: return "exit"; case SYS_PROCESS_STATE_CONSTRUCTING: return "build"; default: return "?"; } } // Names public thread states. static const char* threadStateName(uint32_t state) { switch (state) { case SYS_THREAD_STATE_READY: return "ready"; case SYS_THREAD_STATE_RUNNING: return "run"; case SYS_THREAD_STATE_WAITING: return "wait"; case SYS_THREAD_STATE_DEAD: return "dead"; case SYS_THREAD_STATE_SUSPENDED: return "suspend"; default: return "?"; } } // Names public wait object types. static const char* threadWaitName(uint32_t waitType) { switch (waitType) { case SYS_THREAD_WAIT_NONE: return "-"; case SYS_THREAD_WAIT_PROCESS: return "process"; case SYS_THREAD_WAIT_THREAD: return "thread"; case SYS_THREAD_WAIT_MUTEX: return "mutex"; case SYS_THREAD_WAIT_SEMAPHORE: return "sem"; case SYS_THREAD_WAIT_EVENT: return "event"; case SYS_THREAD_WAIT_QUEUE: return "queue"; case SYS_THREAD_WAIT_FILE: return "file"; case SYS_THREAD_WAIT_DIR: return "dir"; case SYS_THREAD_WAIT_ASYNC_IO: return "async"; case SYS_THREAD_WAIT_SOCKET: return "socket"; case SYS_THREAD_WAIT_DEVICE: return "device"; case SYS_THREAD_WAIT_DRIVER: return "driver"; case SYS_THREAD_WAIT_USB_DEVICE: return "usbdev"; 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"; } } // Prints thread status flags. static void printThreadFlags(uint32_t flags) { char buf[8]; size_t n = 0; if (flags & SYS_THREAD_FLAG_CURRENT) buf[n++] = '*'; if (flags & SYS_THREAD_FLAG_IDLE) buf[n++] = 'I'; if (flags & SYS_THREAD_FLAG_KERNEL) buf[n++] = 'K'; if (flags & SYS_THREAD_FLAG_QUEUED) buf[n++] = 'Q'; if (flags & SYS_THREAD_FLAG_ALERTABLE_WAIT) buf[n++] = 'A'; if (flags & SYS_THREAD_FLAG_KERNEL_APC_PENDING) buf[n++] = 'k'; if (flags & SYS_THREAD_FLAG_USER_APC_PENDING) buf[n++] = 'u'; if (n == 0) buf[n++] = '-'; buf[n] = '\0'; printStringWidth(buf, 7); } // Implements the cmd ps operation. static void cmd_ps(void) { SYS_PROCESS_INFO procs[MAX_PROCS]; size_t count = 0; KSTATUS status = SysGetProcessList(procs, MAX_PROCS, &count); if (status != 0) { print("ps: failed to retrieve process list\n"); return; } print("Processes (Count: "); printUInt((uint32_t)count); print("):\n"); print(" PID State Thr Hnd UserKiB ImageKiB Flags Name\n"); print(" Flags: S=system I=idle P=protected *=current T=terminating X=exited.\n"); size_t displayCount = count < MAX_PROCS ? count : MAX_PROCS; for (size_t i = 0; i < displayCount; i++) { SYS_PROCESS_INFO* p = &procs[i]; char flags[7]; size_t flagLen = 0; if (p->Flags & SYS_PROCESS_FLAG_SYSTEM) flags[flagLen++] = 'S'; if (p->Flags & SYS_PROCESS_FLAG_IDLE) flags[flagLen++] = 'I'; if (p->Flags & SYS_PROCESS_FLAG_TERMINATION_PROTECTED) flags[flagLen++] = 'P'; if (p->Flags & SYS_PROCESS_FLAG_CURRENT) flags[flagLen++] = '*'; if (p->Flags & SYS_PROCESS_FLAG_TERMINATING) flags[flagLen++] = 'T'; if (p->Flags & SYS_PROCESS_FLAG_EXITED) flags[flagLen++] = 'X'; if (flagLen == 0) flags[flagLen++] = '-'; flags[flagLen] = '\0'; print(" "); printUIntWidth(p->ProcessId, 3); print(" "); printStringWidth(processStateName(p->State), 5); print(" "); printUIntWidth(p->ThreadCount, 3); print(" "); printUIntWidth(p->HandleCount, 3); print(" "); printUInt64Width((uint64_t)p->UserCommittedBytes / 1024u, 7); print(" "); printUInt64Width((uint64_t)p->ImageSize / 1024u, 8); print(" "); printStringWidth(flags, 5); print(" "); print(p->Name); print("\n"); } if (count > MAX_PROCS) { print(" ... and "); printUInt((uint32_t)(count - MAX_PROCS)); print(" more processes.\n"); } } // Implements the cmd threads operation. static void cmd_threads(const char* args) { uint32_t pid = 0; if (!parseUInt(args, &pid)) { print("threads: usage: threads \n"); return; } SYS_THREAD_INFO threads[MAX_THREADS]; size_t count = 0; KSTATUS status = SysGetThreadList(pid, threads, MAX_THREADS, &count); if (status != 0) { print("threads: query failed status="); printUInt(status); print("\n"); return; } print("Threads for PID "); printUInt(pid); print(" (Count: "); printUInt((uint32_t)count); print("):\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; for (size_t i = 0; i < displayCount; i++) { SYS_THREAD_INFO* t = &threads[i]; print(" "); printUIntWidth(t->ThreadId, 3); print(" "); printStringWidth(threadStateName(t->State), 5); print(" "); if (t->BaseSchedulingClass == SYS_SCHEDULING_REALTIME) print("R"); else print("N"); printUIntWidth(t->BasePriority, 2); print(" "); if (t->EffectiveSchedulingClass == SYS_SCHEDULING_REALTIME) print("R"); else print("N"); printUIntWidth(t->EffectivePriority, 2); print(" "); if (t->RunningCpu == 0xffffffffu) printStringWidth("-", 3); else printUIntWidth(t->RunningCpu, 3); print(" "); if (t->LastCpu == 0xffffffffu) printStringWidth("-", 7); else printUIntWidth(t->LastCpu, 7); print(" "); printUIntWidth(t->QuantumRemaining, 4); print(" "); printUIntWidth(t->QuantumTicks, 5); print(" "); printUIntWidth(t->CpuBurstTicks, 5); print(" "); printStringWidth(threadWaitName(t->WaitObjectType), 8); print(" "); printUIntWidth(t->WaitStatus, 5); print(" "); printThreadFlags(t->Flags); print(" "); print(t->Name[0] ? t->Name : "-"); print("\n"); } if (count > MAX_THREADS) { print(" ... and "); printUInt((uint32_t)(count - MAX_THREADS)); print(" more threads.\n"); } } static void cmd_kill(const char* args) { uint32_t pid = 0; if (!parseUInt(args, &pid)) { print("kill: usage: kill \n"); return; } uint32_t hProc = 0; KSTATUS status = SysOpenProcess(pid, SYS_PROCESS_RIGHT_TERMINATE, &hProc); if (status == 0) { status = SysKillProcess(hProc, (int32_t)NTLSTATUS_PROCESS_KILLED); SysCloseHandle(hProc); } if (status == NTLSTATUS_ACCESS_DENIED) { print("kill: process "); printUInt(pid); print(" is termination-protected.\n"); } else if (status != 0) { print("shell: failed to kill process "); printUInt(pid); print(", error code: "); printUInt(status); print("\n"); } else { print("Process "); printUInt(pid); print(" terminated successfully.\n"); } } // Implements the cmd write operation. static void cmd_write(const char* args) { char filename[MAX_CMD]; int i = 0; while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) { filename[i] = args[i]; i++; } filename[i] = '\0'; if (args[i] == '\0' || args[i+1] == '\0') { print("write: usage: write \n"); return; } uint32_t hFile; if (create_file(filename, &hFile) != 0) { print("write: could not create file\n"); return; } size_t written; SYS_FILE_IO_REQUEST writeReq = SysMakeFileIoRequest(hFile, args + i + 1, strlen(args + i + 1), &written); SysWriteFile(&writeReq); SysCloseHandle(hFile); print("File written successfully.\n"); } #define SHELL_DIR_INITIAL_CAPACITY 64u // 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; if (!a) a = ""; if (!b) b = ""; while (true) { char ca = shellAsciiLower(a[i]); char cb = shellAsciiLower(b[i]); if (ca != cb) return (ca < cb) ? -1 : 1; if (ca == '\0') break; i++; } return strcmp(a, b); } // Compares two directory entries by display name. static int shellCompareDirEntries(const SYS_DIR_ENTRY* a, const SYS_DIR_ENTRY* b) { return shellCompareNames(a->Name, b->Name); } // Allocates a directory-entry array from VM so large listings do not consume stack. static KSTATUS shellAllocDirEntries(uint32_t capacity, SYS_DIR_ENTRY** entriesOut) { void* base = 0; size_t bytes = (size_t)capacity * sizeof(SYS_DIR_ENTRY); size_t pages = (bytes + 4095u) / 4096u; if (pages == 0) pages = 1; SYS_ALLOC_VM_REQUEST req; memset(&req, 0, sizeof(req)); req.Size = sizeof(req); req.Protect = SYS_VM_READWRITE; req.Flags = SYS_VM_FLAG_NONE; req.PageCount = pages; req.BaseOut = &base; KSTATUS status = SysAllocVm(&req); if (status != 0 || !base) { *entriesOut = 0; return status ? status : 1; } *entriesOut = (SYS_DIR_ENTRY*)base; return 0; } // Grows a directory-entry array while preserving already-read entries. static KSTATUS shellGrowDirEntries(SYS_DIR_ENTRY** entries, uint32_t* capacity, uint32_t count) { uint32_t oldCapacity = *capacity; uint32_t newCapacity = oldCapacity ? oldCapacity * 2u : SHELL_DIR_INITIAL_CAPACITY; SYS_DIR_ENTRY* next = 0; KSTATUS status = shellAllocDirEntries(newCapacity, &next); if (status != 0) return status; if (*entries && count) memcpy(next, *entries, (size_t)count * sizeof(SYS_DIR_ENTRY)); if (*entries) SysFreeVm(*entries); *entries = next; *capacity = newCapacity; return 0; } // Sorts directory entries alphabetically. static void shellSortDirEntries(SYS_DIR_ENTRY* entries, uint32_t count) { for (uint32_t i = 1; i < count; i++) { SYS_DIR_ENTRY current = entries[i]; uint32_t j = i; while (j > 0 && shellCompareDirEntries(¤t, &entries[j - 1]) < 0) { entries[j] = entries[j - 1]; j--; } entries[j] = current; } } // Prints one directory entry in cmd dir format. static void shellPrintDirEntry(const SYS_DIR_ENTRY* ke) { printDirTime(&ke->LastWriteTime); if (ke->Attr & 0x10) { print(" "); print(ke->Name); } else { print(" "); print(ke->Name); print(" ("); printUInt64(ke->FileSize); print(" bytes)"); } print("\n"); } // Prints one RSSRV namespace kind label. static void shellPrintResourceKind(uint32_t kind) { if (kind == NTL_RESOURCE_KIND_NAMESPACE_DIRECTORY) print(" "); else if (kind == NTL_RESOURCE_KIND_SYMBOLIC_LINK) print(" "); else if (kind == NTL_RESOURCE_KIND_VOLUME) print(" "); else if (kind == NTL_RESOURCE_KIND_DIRECTORY) print(" "); else if (kind == NTL_RESOURCE_KIND_DEVICE) print(" "); else print(" "); } // 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; KSTATUS st = open_dir(target, &hDir); if (st != 0) { print("dir: failed to open directory, status=0x"); printHex32(st); print("\n"); return; } SYS_DIR_ENTRY* entries = 0; uint32_t count = 0; uint32_t capacity = 0; while (true) { SYS_DIR_ENTRY ke; st = SysReadDir(hDir, &ke); if (st != 0) break; if (count == capacity) { st = shellGrowDirEntries(&entries, &capacity, count); if (st != 0) { print("dir: out of memory, status=0x"); printHex32(st); print("\n"); SysCloseHandle(hDir); if (entries) SysFreeVm(entries); return; } } entries[count++] = ke; } SysCloseHandle(hDir); shellSortDirEntries(entries, count); for (uint32_t i = 0; i < count; i++) shellPrintDirEntry(&entries[i]); if (entries) SysFreeVm(entries); } // Implements the cmd type operation. static void cmd_type(const char* filename) { uint32_t hFile; if (open_file(filename, &hFile) != 0) { print("type: cannot open file\n"); return; } char buffer[512]; size_t bytesRead; while (true) { SYS_FILE_IO_REQUEST readReq = SysMakeFileIoRequest(hFile, buffer, sizeof(buffer) - 1, &bytesRead); if (SysReadFile(&readReq) != 0 || bytesRead == 0) break; buffer[bytesRead] = '\0'; print(buffer); } SysCloseHandle(hFile); print("\n"); } // Implements the extract Program Path operation. static bool extractProgramPath(const char* cmdline, char* out, size_t outSize) { if (!cmdline || !out || outSize == 0) return false; while (*cmdline == ' ' || *cmdline == '\t') cmdline++; if (*cmdline == '\0') return false; size_t pos = 0; if (*cmdline == '"') { cmdline++; while (*cmdline && *cmdline != '"' && pos + 1 < outSize) out[pos++] = *cmdline++; } else { while (*cmdline && *cmdline != ' ' && *cmdline != '\t' && pos + 1 < outSize) out[pos++] = *cmdline++; } out[pos] = '\0'; return pos != 0; } // Returns whether one input key is currently held. static bool shellIsKeyDown(INPUT_KEY key) { bool down = false; return NtlInputIsKeyDown(key, &down) == NTLSTATUS_SUCCESS && down; } // Waits for a foreground process while polling Ctrl-C without consuming child input. static KSTATUS waitForegroundProcess(uint32_t hProc) { bool sentBreak = false; while (true) { KSTATUS status = SysWaitSingle(hProc, SYS_WAIT_FLAG_NONE, SHELL_FOREGROUND_POLL_MS); if (status == NTLSTATUS_SUCCESS) return status; if (status != NTLSTATUS_TIMEOUT) return status; uint32_t modifiers = NtlInputGetKeyModifiers(); if (!sentBreak && (modifiers & INPUT_MOD_CTRL) && shellIsKeyDown(INPUT_KEY_C)) { print("^C\n"); KSTATUS killStatus = SysKillProcess( hProc, (int32_t)NTLSTATUS_PROCESS_KILLED); if (killStatus != NTLSTATUS_SUCCESS) { print("shell: foreground termination failed status="); printUInt(killStatus); print("\n"); return killStatus; } sentBreak = true; } } } // Run one command. static bool runCommand(const char* cmd) { if (!cmd || *cmd == '\0') return false; if (strcmp(cmd, "shutdown") == 0 || strcmp(cmd, "reboot") == 0) { uint32_t action = strcmp(cmd, "reboot") == 0 ? SYS_POWER_ACTION_RESTART : SYS_POWER_ACTION_SHUTDOWN; KSTATUS st = SysRequestSystemPower(action); if (!KSUCCESS(st)) print("power: request failed\n"); return false; } if (strcmp(cmd, "exit") == 0) return true; if (strcmp(cmd, "help") == 0) { cmd_help(); return false; } if (strcmp(cmd, "clear") == 0) { (void)NtlConsoleClear(SYS_HANDLE_INVALID, 0x012456); return false; } if (strncmp(cmd, "crash", 5) == 0) { // Check the sub-option trailing "crash " (offset 6). if (strcmp(cmd + 6, "void") == 0) { // Jumping into the void. void (*invalid_func)(void) = NULL; invalid_func(); return false; } else if (strcmp(cmd + 6, "noncanonical") == 0) { // Non-canonical pointer dereference. volatile int* ptr = (volatile int*)0x4242424242424242ULL; *ptr = 1337; return false; } else if (strcmp(cmd + 6, "ud2") == 0) { __ud2(); return false; } else if (strcmp(cmd + 6, "nx") == 0) { // NX / DEP Violation. unsigned char code[] = { 0xC3 }; void (*execute_stack)(void) = (void (*)(void))code; execute_stack(); return false; } else if (strcmp(cmd + 6, "divzero") == 0) { // Division by zero. volatile int zero = 0; volatile int result = 1 / zero; (void)result; return false; } else { // Default fallback if just "crash" or an unknown sub-option is passed. *(volatile int*)0 = 42; return false; } } if (strcmp(cmd, "mem") == 0) { cmd_mem(); return false; } if (strcmp(cmd, "time") == 0 || strcmp(cmd, "date") == 0) { cmd_time(); return false; } if (strcmp(cmd, "display") == 0 || strcmp(cmd, "gpu") == 0) { cmd_display(); return false; } if (strcmp(cmd, "surfbench") == 0) { cmd_surfbench(); return false; } if (strcmp(cmd, "volume") == 0) { cmd_volume(""); return false; } if (strncmp(cmd, "volume ", 7) == 0) { cmd_volume(cmd + 7); return false; } if (strcmp(cmd, "stats") == 0 || strcmp(cmd, "telemetry") == 0) { cmd_stats(); return false; } if (strcmp(cmd, "ps") == 0) { cmd_ps(); return false; } if (strncmp(cmd, "threads ", 8) == 0) { cmd_threads(cmd + 8); return false; } if (strncmp(cmd, "kill ", 5) == 0) { cmd_kill(cmd + 5); return false; } if (strcmp(cmd, "dir") == 0) { cmd_dir("."); return false; } if (strncmp(cmd, "dir ", 4) == 0) { cmd_dir(cmd + 4); return false; } if (strncmp(cmd, "cd ", 3) == 0) { if (set_cwd(cmd + 3) != 0) print("cd: failed\n"); return false; } if (strncmp(cmd, "del ", 4) == 0) { delete_file(cmd + 4); return false; } if (strncmp(cmd, "type ", 5) == 0) { cmd_type(cmd + 5); return false; } if (strncmp(cmd, "write ", 6) == 0) { cmd_write(cmd + 6); return false; } // Make a local copy of the command line so we can mutate it safely if needed char modifiedCmd[MAX_CMD]; strncpy(modifiedCmd, cmd, sizeof(modifiedCmd) - 1); modifiedCmd[sizeof(modifiedCmd) - 1] = '\0'; // Parse background indicator execution flag (&) bool background = false; size_t cmdLen = strlen(modifiedCmd); if (cmdLen > 0 && modifiedCmd[cmdLen - 1] == '&') { background = true; modifiedCmd[cmdLen - 1] = '\0'; // Strip the ampersand // Clean up any trailing whitespace left before the ampersand cmdLen = strlen(modifiedCmd); while (cmdLen > 0 && (modifiedCmd[cmdLen - 1] == ' ' || modifiedCmd[cmdLen - 1] == '\t')) { modifiedCmd[cmdLen - 1] = '\0'; cmdLen--; } } char program[MAX_CMD]; if (!extractProgramPath(modifiedCmd, program, sizeof(program))) return false; uint32_t hProc; const char* launchFailureStage = NULL; KSTATUS launchStatus = create_process(program, &hProc, modifiedCmd, &launchFailureStage); if (KSUCCESS(launchStatus)) { if (background) { // Background mode: Clean up the handle immediately and skip waiting. print("[Launched in background, handle: "); printUInt(hProc); print("]\n"); SysCloseHandle(hProc); } else { // Foreground mode: Wait for completion and flush standard keyboard stream. KSTATUS waitStatus = waitForegroundProcess(hProc); if (waitStatus != NTLSTATUS_SUCCESS) { print("shell: wait failed: "); printUInt(waitStatus); print("\n"); } print("Process exited with code: "); int32_t exitCode; SysGetProcessExitCode(hProc, &exitCode); printInt(exitCode); const char* exitName = processExitStatusName((uint32_t)exitCode); if (exitName) { print(" (0x"); printHex32((uint32_t)exitCode); print(" "); print(exitName); print(")"); } print("\n"); SysCloseHandle(hProc); INPUT_KEY drainedKey; while (NtlInputPollKeyboard(&drainedKey) == NTLSTATUS_SUCCESS) (void)NtlInputReadKey(&drainedKey); } } else { print("shell: launch failed"); if (launchFailureStage) { print(" at "); print(launchFailureStage); } print(": "); printStatus(launchStatus); print("\n"); } return false; } // Runs the requested operation. int main(void) { const char* cmdline = SysGetPeb()->CommandLine.Data; char lineBuf[MAX_CMD]; print("shell: command line: "); print(cmdline); print("\n"); print("shell: ready\n"); while (true) { print(SHELL_PROMPT); if (readLine(lineBuf, MAX_CMD)) continue; char* cmd = trim(lineBuf); shellHistoryAdd(cmd); if (runCommand(cmd)) break; } print("shell: goodbye\n"); SysExitProcess(0); return 0; }