add /IGNORE:4216 to HAL link step, add writing and directory listing to the FAT32 driver, add the concept of current working directory to the VFS, add writing to the VFS, more operations in the shell, rename KeCurrentThread to KeGetCurrentThread and add KeGetCurrentProcess, add STATUS_NO_MORE_FILES, change KeFault* to KePanic, add syscalls for writing to files, add a proper syscall to writing to the console, move Screen.Clear to after memory status debug print, add ObjectTypeDir to OBJECT_TYPE, extend kernel32 by file operations and upgrade user32 (and add gdi32) to match windows a bit more closely, change CreateProcessA to accept the first argument as NULL.

This commit is contained in:
maksw committed 2026-05-04 16:27:49 +02:00
1 parent a5f0acfac8
commit 8c7564d5e1
33 files changed
+2343 -429

No files matched your search

+162 -23
View File
@@ -4,28 +4,43 @@
#include <string.h>
// ---------------------------------------------------------------------------
// Win32 imports
// Win32 imports & definitions
// ---------------------------------------------------------------------------
_Noreturn void ExitProcess(unsigned int code);
void OutputDebugStringA(const char* s);
typedef void* HANDLE;
typedef void* HANDLE;
typedef unsigned long DWORD;
typedef int BOOL;
#define INVALID_HANDLE_VALUE ((HANDLE)0)
#define INFINITE 0xFFFFFFFFUL
#define STD_INPUT_HANDLE ((DWORD)-10)
#define INVALID_HANDLE_VALUE ((HANDLE)(intptr_t)-1)
#define INFINITE 0xFFFFFFFFUL
#define STD_INPUT_HANDLE ((DWORD)-10)
#define STD_OUTPUT_HANDLE ((DWORD)-11)
#define MAX_PATH 260
// File I/O constants
#define GENERIC_READ 0x80000000L
#define OPEN_EXISTING 3
#define FILE_SHARE_READ 0x00000001
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
HANDLE GetStdHandle(DWORD nStdHandle);
BOOL ReadConsoleA(HANDLE hConsoleInput, void* lpBuffer,
DWORD nNumberOfCharsToRead, DWORD* lpNumberOfCharsRead,
void* pInputControl);
DWORD GetLastError();
BOOL ReadConsoleA(HANDLE hConsoleInput, void* lpBuffer,
DWORD nNumberOfCharsToRead, DWORD* lpNumberOfCharsRead,
void* pInputControl);
BOOL WriteConsoleA(HANDLE hConsoleOutput, const void* lpBuffer,
DWORD nNumberOfCharsToWrite, DWORD* lpNumberOfCharsWritten,
void* lpReserved);
typedef struct {
DWORD cb;
char* lpReserved;
char* lpDesktop;
char* lpTitle;
char* lpReserved;
char* lpDesktop;
char* lpTitle;
DWORD dwX, dwY, dwXSize, dwYSize;
DWORD dwXCountChars, dwYCountChars;
DWORD dwFillAttribute, dwFlags;
@@ -41,6 +56,24 @@ typedef struct {
DWORD dwThreadId;
} PROCESS_INFORMATION;
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
typedef struct _WIN32_FIND_DATAA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
char cFileName[MAX_PATH];
char cAlternateFileName[14];
} WIN32_FIND_DATAA;
BOOL CreateProcessA(const char* lpApp, char* lpCmdLine,
void* lpPA, void* lpTA, BOOL bInherit,
DWORD dwFlags, void* lpEnv, const char* lpDir,
@@ -49,11 +82,35 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMs);
BOOL GetExitCodeProcess(HANDLE hProcess, DWORD* lpExitCode);
BOOL CloseHandle(HANDLE hObject);
// File operation imports
HANDLE FindFirstFileA(const char* lpFileName, WIN32_FIND_DATAA* lpFindFileData);
BOOL FindNextFileA(HANDLE hFindFile, WIN32_FIND_DATAA* lpFindFileData);
BOOL FindClose(HANDLE hFindFile);
BOOL SetCurrentDirectoryA(const char* lpPathName);
BOOL DeleteFileA(const char* lpFileName);
HANDLE CreateFileA(const char* lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
void* lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
BOOL ReadFile(HANDLE hFile, void* lpBuffer, DWORD nNumberOfBytesToRead,
DWORD* lpNumberOfBytesRead, void* lpOverlapped);
// ---------------------------------------------------------------------------
// Global handles
// ---------------------------------------------------------------------------
static HANDLE hIn = INVALID_HANDLE_VALUE;
static HANDLE hOut = INVALID_HANDLE_VALUE;
// ---------------------------------------------------------------------------
// Output helpers
// ---------------------------------------------------------------------------
static void print(const char* s) {
OutputDebugStringA(s);
DWORD written;
// Write to the actual console window
if (hOut != INVALID_HANDLE_VALUE) {
WriteConsoleA(hOut, s, (DWORD)strlen(s), &written, 0);
} else {
OutputDebugStringA(s);
}
}
static void printUInt(uint32_t n) {
@@ -70,12 +127,10 @@ static void printUInt(uint32_t n) {
// ---------------------------------------------------------------------------
// Line editor
// Reads one character at a time via ReadConsoleA, echoes it, handles
// backspace, returns on Enter.
// ---------------------------------------------------------------------------
#define MAX_CMD 256
static void readLine(HANDLE hIn, char* buf, int len) {
static void readLine(char* buf, int len) {
int pos = 0;
while (true) {
char c;
@@ -106,9 +161,6 @@ static void readLine(HANDLE hIn, char* buf, int len) {
buf[pos] = '\0';
}
// ---------------------------------------------------------------------------
// Trim leading/trailing spaces in-place; returns pointer into buf.
// ---------------------------------------------------------------------------
static char* trim(char* s) {
while (*s == ' ') s++;
int len = (int)strlen(s);
@@ -117,6 +169,51 @@ static char* trim(char* s) {
return s;
}
// ---------------------------------------------------------------------------
// Built-in commands
// ---------------------------------------------------------------------------
static void cmd_dir() {
WIN32_FIND_DATAA fd;
HANDLE hFind = FindFirstFileA("*", &fd);
if (hFind == INVALID_HANDLE_VALUE) {
print("dir: failed to read directory\n");
return;
}
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
print("<DIR> ");
} else {
print(" ");
}
print(fd.cFileName);
print("\n");
} while (FindNextFileA(hFind, &fd));
FindClose(hFind);
}
static void cmd_type(const char* filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE) {
print("type: could not open '");
print(filename);
print("'\n");
return;
}
char buffer[512];
DWORD bytesRead;
while (ReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead, 0) && bytesRead > 0) {
buffer[bytesRead] = '\0';
print(buffer);
}
CloseHandle(hFile);
print("\n");
}
// ---------------------------------------------------------------------------
// Run one command. Returns 1 if the shell should exit.
// ---------------------------------------------------------------------------
@@ -124,19 +221,59 @@ static int runCommand(const char* cmd) {
if (!cmd || *cmd == '\0')
return 0;
if (strcmp(cmd, "exit") == 0)
// --- Built-in commands ---
if (strcmp(cmd, "exit") == 0) {
return 1;
}
if (strcmp(cmd, "dir") == 0) {
cmd_dir();
return 0;
}
if (strncmp(cmd, "cd ", 3) == 0) {
const char* path = cmd + 3;
if (!SetCurrentDirectoryA(path)) {
print("cd: failed to change directory to '");
print(path);
print("'\n");
}
return 0;
}
if (strncmp(cmd, "del ", 4) == 0) {
const char* file = cmd + 4;
if (!DeleteFileA(file)) {
print("del: failed to delete '");
print(file);
print("'\n");
}
return 0;
}
if (strncmp(cmd, "type ", 5) == 0) {
cmd_type(cmd + 5);
return 0;
}
// --- External Process Execution ---
STARTUPINFOA si;
PROCESS_INFORMATION pi;
unsigned char* p = (unsigned char*)&si;
for (size_t i = 0; i < sizeof(si); i++) p[i] = 0;
si.cb = (DWORD)sizeof(si);
if (!CreateProcessA(cmd, 0, 0, 0, 0, 0, 0, 0, &si, &pi)) {
// CreateProcessA requires a mutable buffer for the command line argument
char cmdBuf[MAX_CMD];
strncpy(cmdBuf, cmd, MAX_CMD - 1);
cmdBuf[MAX_CMD - 1] = '\0';
if (!CreateProcessA(0, cmdBuf, 0, 0, 0, 0, 0, 0, &si, &pi)) {
print("shell: could not launch '");
print(cmd);
print("'\n");
print("', error code: ");
printUInt(GetLastError());
print("\n");
return 0;
}
@@ -145,6 +282,7 @@ static int runCommand(const char* cmd) {
DWORD exitCode = 0;
GetExitCodeProcess(pi.hProcess, &exitCode);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if (exitCode != 0) {
print("shell: '");
@@ -161,14 +299,15 @@ static int runCommand(const char* cmd) {
// Entry point
// ---------------------------------------------------------------------------
int main() {
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
hIn = GetStdHandle(STD_INPUT_HANDLE);
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
char lineBuf[MAX_CMD];
print("shell: ready\n");
while (true) {
print("> ");
readLine(hIn, lineBuf, MAX_CMD);
readLine(lineBuf, MAX_CMD);
if (runCommand(trim(lineBuf)))
break;
}