add ntfs.sys standalone driver target, change default usb vhd layout formatting to ntfs, implement Fat32CreateDir for directory creation support in the fat32 file system driver, add a dedicated HAL serial output endpoint for COM1 writes in hal_serial.c and subscribe serial to HAL text streams, introduce waitable kernel timers with KeTimerCreate, KeTimerSet, and KeTimerCancel alongside spinlock-protected global timer list initialization and scheduler tick tracking, implement SyscallWriteFileAsync system call for asynchronous non-blocking file writes, refactor NetSocketConnect and NetSocketSendTo to use generic SYS_SOCKET_ADDRESS_K structures instead of being hardcoded to IPv4, update gethostbyname and DNS name resolution to support IPv6 parsing via ResolveNameFamily, update tcpserve.exe with -4 and -6 command-line flags to accept and display IPv6 addresses, append size and version headers to all kernel telemetry and statistics structures including SYS_PMM_STATS, SYS_CPU_STATS, and SYS_SCHEDULER_STATS, update winmm timeGetTime to look up high-resolution hardware frequencies via SysGetTickFrequency, integrate 14 native smoke test applications.

This commit is contained in:
maksw committed 2026-06-26 15:18:48 +02:00
1 parent 2c4a68a75f
commit ed3d065abd
156 files changed
+10509 -2643

No files matched your search

-1
View File
@@ -54,7 +54,6 @@ typedef struct tagBITMAPINFO {
RGBQUAD bmiColors[1];
} BITMAPINFO;
// GDI Exports.
// Static buffers to persist between function calls.
+136 -145
View File
@@ -13,11 +13,8 @@
// multiple heaps, and NULL is a legal (no-op) heap argument under Win32.
// - Win32 per-thread state lives behind SYS_TEB::SubsystemData so the native
// TEB ABI stays subsystem-neutral.
// - File I/O uses SYS_OPEN_FILE / SYS_READ_FILE / SYS_SEEK_FILE /
// SYS_GET_FILE_SIZE / SYS_CLOSE_HANDLE (unified close path - no separate
// SysCloseFile).
// - WriteFile / CreateFileA in write-mode / SetEndOfFile are stubs because
// the VFS has no write path yet.
// - File I/O uses the flags-based SYS_OPEN_FILE request plus the common
// read/write/seek/query/close syscalls.
#include <stdint.h>
#include <stddef.h>
@@ -221,19 +218,19 @@ static void TranslatePath(const char* input, char* output) {
}
}
// Implements the k32 Open File Native operation.
static uint32_t K32OpenFileNative(const char* path, uint32_t* handleOut) {
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut };
static uint32_t K32OpenFileNative(const char* path,
uint32_t access,
uint32_t disposition,
uint32_t* handleOut) {
SYS_OPEN_FILE_REQUEST req = SysMakeOpenFileRequest(SysSvFromCstr(path),
access,
disposition,
SYS_FILE_FLAG_NONE,
handleOut);
return SysOpenFile(&req);
}
// Implements the k32 Create File Native operation.
static uint32_t K32CreateFileNative(const char* path, uint32_t* handleOut) {
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut };
return SysCreateFile(&req);
}
// Implements the k32 Delete File Native operation.
static uint32_t K32DeleteFileNative(const char* path) {
SYS_PATH_REQUEST req = { SysSvFromCstr(path) };
@@ -254,13 +251,14 @@ static uint32_t K32SetCwdNative(const char* path) {
// Implements the k32 Get Cwd Native operation.
static uint32_t K32GetCwdNative(char* buffer, size_t capacity, size_t* lengthOut) {
size_t len = 0;
size_t writable = (buffer && capacity) ? capacity - 1 : 0;
SYS_GET_CWD_REQUEST req = { buffer, writable, &len };
uint32_t s = SysGetCwd(&req);
if (lengthOut) *lengthOut = len;
if (s == 0 && buffer && capacity) buffer[len] = '\0';
return s;
SYS_STRING_VIEW cwd = SysGetCurrentDirectoryView();
if ((cwd.Length && !cwd.Data) || cwd.Length > SYS_CWD_MAX) return STATUS_INVALID_PARAMETER;
if (lengthOut) *lengthOut = cwd.Length;
if (!buffer || cwd.Length + 1 > capacity) return STATUS_BUFFER_TOO_SMALL;
if (cwd.Length) memcpy(buffer, cwd.Data, cwd.Length);
buffer[cwd.Length] = '\0';
return STATUS_SUCCESS;
}
// Implements the k32 Create Process Native operation.
@@ -323,7 +321,10 @@ static BOOL KiFileExistsA(const char* path) {
char native[MAX_PATH];
TranslatePath(path, native);
uint32_t h = 0;
if (K32OpenFileNative(native, &h) != 0) return FALSE;
if (K32OpenFileNative(native,
SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY,
SYS_FILE_OPEN_EXISTING,
&h) != 0) return FALSE;
SysCloseHandle(h);
return TRUE;
}
@@ -396,7 +397,7 @@ __declspec(dllexport) DWORD SearchPathA(const char* lpPath, const char* lpFileNa
return 0;
}
// GetLastError / SetLastError (single-threaded stub).
// GetLastError / SetLastError (single-threaded stub).
static SYS_PEB* gProcessPeb = NULL;
// Implements the peb operation.
@@ -416,7 +417,7 @@ __declspec(dllexport) void SetLastError(DWORD err) {
// Process termination.
__declspec(dllexport) _Noreturn void ExitProcess(unsigned int code) {
SysExitProcess((int)code);
SysExitProcess((int32_t)code);
while (true) ; // unreachable
}
@@ -425,17 +426,31 @@ __declspec(dllexport) void OutputDebugStringA(const char* str) {
if (str) K32DebugPrintA(str);
}
// Queries the native monotonic tick frequency.
static uint64_t K32TickFrequency(void) {
uint64_t frequency = 0;
if (SysGetTickFrequency(&frequency) != STATUS_SUCCESS) return 0;
return frequency;
}
// Returns monotonic milliseconds since boot.
static uint64_t K32TickMilliseconds(void) {
uint64_t frequency = K32TickFrequency();
if (!frequency) return 0;
return SysTicksToMilliseconds(SysGetTick(), frequency);
}
// Timer.
__declspec(dllexport) DWORD GetTickCount(void) {
return (DWORD)(SysGetTick() / 1000);
return (DWORD)K32TickMilliseconds();
}
// Returns tick Count64.
__declspec(dllexport) uint64_t GetTickCount64(void) {
return SysGetTick() / 1000;
return K32TickMilliseconds();
}
// Memory (heap argument is ignored - single user-mode heap).
// Memory (heap argument is ignored - single user-mode heap).
#define HEAP_ZERO_MEMORY 0x00000008UL
#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010UL
@@ -511,8 +526,8 @@ __declspec(dllexport) void* VirtualAlloc(void* lpAddress, size_t dwSize,
void* base = NULL;
uint32_t flags = lpAddress ? SYS_VM_FLAG_FIXED : SYS_VM_FLAG_NONE;
uint32_t s = SysAllocVm(lpAddress, pages, WinProtectToSysVm(flProtect), flags, &base);
if (s != SYS_STATUS_SUCCESS) {
gLastError = (s == SYS_STATUS_NOT_FOUND || s == SYS_STATUS_INVALID_PARAMETER) ? 87 : 8;
if (s != STATUS_SUCCESS) {
gLastError = (s == STATUS_NOT_FOUND || s == STATUS_INVALID_PARAMETER) ? 87 : 8;
return NULL;
}
return base;
@@ -523,7 +538,7 @@ __declspec(dllexport) BOOL VirtualFree(void* lpAddress, size_t dwSize, DWORD dwF
(void)dwSize; (void)dwFreeType;
if (!lpAddress) return TRUE;
uint32_t s = SysFreeVm(lpAddress);
if (s != SYS_STATUS_SUCCESS) { gLastError = 87; return FALSE; }
if (s != STATUS_SUCCESS) { gLastError = 87; return FALSE; }
return TRUE;
}
@@ -534,7 +549,7 @@ __declspec(dllexport) BOOL VirtualProtect(void* lpAddress, size_t dwSize,
uint32_t oldSysProtect = 0;
uint32_t s = SysProtectVm(lpAddress, pages, WinProtectToSysVm(flNewProtect),
lpflOldProtect ? &oldSysProtect : NULL);
if (s != SYS_STATUS_SUCCESS) { gLastError = 87; return FALSE; }
if (s != STATUS_SUCCESS) { gLastError = 87; return FALSE; }
if (lpflOldProtect) *lpflOldProtect = SysProtectVmToWin(oldSysProtect);
return TRUE;
}
@@ -549,7 +564,7 @@ __declspec(dllexport) size_t VirtualQuery(const void* lpAddress,
SYS_VM_REGION_INFO info;
uint32_t s = SysQueryVm((void*)lpAddress, &info);
if (s != SYS_STATUS_SUCCESS) {
if (s != STATUS_SUCCESS) {
gLastError = 87;
return 0;
}
@@ -585,8 +600,8 @@ __declspec(dllexport) HANDLE CreateFileMappingA(HANDLE hFile,
SYS_MAP_FLAG_NONE,
maximumSize,
&kh);
if (s != SYS_STATUS_SUCCESS) {
gLastError = (s == SYS_STATUS_NOT_SUPPORTED) ? 120 : ((s == SYS_STATUS_NO_MEMORY) ? 8 : 87);
if (s != STATUS_SUCCESS) {
gLastError = (s == STATUS_NOT_SUPPORTED) ? 120 : ((s == STATUS_NO_MEMORY) ? 8 : 87);
return NULL;
}
return KH_TO_HANDLE(kh);
@@ -621,8 +636,8 @@ __declspec(dllexport) void* MapViewOfFile(HANDLE hFileMappingObject,
WinFileMapAccessToSys(dwDesiredAccess),
SYS_MAP_FLAG_NONE,
&base);
if (s != SYS_STATUS_SUCCESS) {
gLastError = (s == SYS_STATUS_NOT_SUPPORTED) ? 120 : ((s == SYS_STATUS_NO_MEMORY) ? 8 : 87);
if (s != STATUS_SUCCESS) {
gLastError = (s == STATUS_NOT_SUPPORTED) ? 120 : ((s == STATUS_NO_MEMORY) ? 8 : 87);
return NULL;
}
return base;
@@ -631,7 +646,7 @@ __declspec(dllexport) void* MapViewOfFile(HANDLE hFileMappingObject,
__declspec(dllexport) BOOL UnmapViewOfFile(const void* lpBaseAddress) {
if (!lpBaseAddress) { gLastError = 87; return FALSE; }
uint32_t s = SysFreeVm((void*)lpBaseAddress);
if (s != SYS_STATUS_SUCCESS) { gLastError = 87; return FALSE; }
if (s != STATUS_SUCCESS) { gLastError = 87; return FALSE; }
return TRUE;
}
@@ -645,16 +660,22 @@ __declspec(dllexport) BOOL FlushViewOfFile(const void* lpBaseAddress, size_t dwN
// --- Win32 API ---.
// Returns whether one input key is currently held for Win32 adapters.
static bool Win32IsInputKeyDown(INPUT_KEY key) {
bool down = false;
return SysIsKeyDown(key, &down) == STATUS_SUCCESS && down;
}
// GetAsyncKeyState implementation over the canonical input key namespace.
__declspec(dllexport) SHORT GetAsyncKeyState(int vKey) {
if (vKey == 0x11) { // VK_CONTROL
return (SysIsKeyDown(INPUT_KEY_LEFT_CTRL) || SysIsKeyDown(INPUT_KEY_RIGHT_CTRL)) ? (SHORT)0x8000 : 0;
return (Win32IsInputKeyDown(INPUT_KEY_LEFT_CTRL) || Win32IsInputKeyDown(INPUT_KEY_RIGHT_CTRL)) ? (SHORT)0x8000 : 0;
}
if (vKey == 0x10) { // VK_SHIFT
return (SysIsKeyDown(INPUT_KEY_LEFT_SHIFT) || SysIsKeyDown(INPUT_KEY_RIGHT_SHIFT)) ? (SHORT)0x8000 : 0;
return (Win32IsInputKeyDown(INPUT_KEY_LEFT_SHIFT) || Win32IsInputKeyDown(INPUT_KEY_RIGHT_SHIFT)) ? (SHORT)0x8000 : 0;
}
if (vKey == 0x12) { // VK_MENU / ALT
return (SysIsKeyDown(INPUT_KEY_LEFT_ALT) || SysIsKeyDown(INPUT_KEY_RIGHT_ALT)) ? (SHORT)0x8000 : 0;
return (Win32IsInputKeyDown(INPUT_KEY_LEFT_ALT) || Win32IsInputKeyDown(INPUT_KEY_RIGHT_ALT)) ? (SHORT)0x8000 : 0;
}
static const struct { int vk; INPUT_KEY key; } vk_to_key[] = {
@@ -697,7 +718,7 @@ __declspec(dllexport) SHORT GetAsyncKeyState(int vKey) {
for (size_t i = 0; i < sizeof(vk_to_key) / sizeof(vk_to_key[0]); ++i) {
if (vk_to_key[i].vk == vKey) {
if (SysIsKeyDown(vk_to_key[i].key))
if (Win32IsInputKeyDown(vk_to_key[i].key))
return (SHORT)0x8000;
break;
}
@@ -709,8 +730,10 @@ __declspec(dllexport) SHORT GetAsyncKeyState(int vKey) {
__declspec(dllexport) BOOL FlushConsoleInputBuffer(HANDLE hConsoleInput) {
(void)hConsoleInput;
// Drain the keyboard buffer by reading until empty.
while (SysPollKeyboard()) {
(void)SysReadKeyboardChar();
INPUT_KEY key;
while (SysPollKeyboard(&key) == STATUS_SUCCESS) {
char ignored;
(void)SysReadKeyboardChar(&ignored);
}
return TRUE;
}
@@ -788,71 +811,42 @@ __declspec(dllexport) HANDLE CreateFileA(const char* name,
char translatedName[260];
TranslatePath(name, translatedName);
int wantWrite = (access & GENERIC_WRITE) != 0;
uint32_t sysAccess = SYS_FILE_ACCESS_QUERY;
if (access & GENERIC_READ)
sysAccess |= SYS_FILE_ACCESS_READ;
if (access & GENERIC_WRITE)
sysAccess |= SYS_FILE_ACCESS_WRITE;
if (disposition == OPEN_EXISTING || disposition == TRUNCATE_EXISTING) {
// Open the file via the read path (it must already exist).
uint32_t kh = 0;
uint32_t s = K32OpenFileNative(translatedName, &kh);
if (s != 0) { gLastError = 2; return INVALID_HANDLE_VALUE; }
if (disposition == TRUNCATE_EXISTING && wantWrite) {
// Immediately truncate to zero.
uint32_t ts = SysTruncateFile(kh, 0);
if (ts != 0) {
SysCloseHandle(kh);
gLastError = 5;
return INVALID_HANDLE_VALUE;
}
}
return KH_TO_HANDLE(kh);
uint32_t sysDisposition;
switch (disposition) {
case OPEN_EXISTING: sysDisposition = SYS_FILE_OPEN_EXISTING; break;
case OPEN_ALWAYS: sysDisposition = SYS_FILE_OPEN_ALWAYS; break;
case CREATE_ALWAYS: sysDisposition = SYS_FILE_CREATE_ALWAYS; break;
case CREATE_NEW: sysDisposition = SYS_FILE_CREATE_NEW; break;
case TRUNCATE_EXISTING: sysDisposition = SYS_FILE_TRUNCATE_EXISTING; break;
default:
gLastError = 87;
return INVALID_HANDLE_VALUE;
}
if (disposition == CREATE_ALWAYS && wantWrite) {
// Create-or-replace: try to create; if the file already exists,
// open it and truncate it to zero instead.
uint32_t kh = 0;
uint32_t s = K32CreateFileNative(translatedName, &kh);
if (s != 0) {
// File may already exist - open and truncate.
s = K32OpenFileNative(translatedName, &kh);
if (s != 0) { gLastError = 5; return INVALID_HANDLE_VALUE; }
SysTruncateFile(kh, 0);
}
return KH_TO_HANDLE(kh);
uint32_t kh = 0;
uint32_t s = K32OpenFileNative(translatedName, sysAccess, sysDisposition, &kh);
if (s != 0) {
gLastError = (s == STATUS_OBJECT_NAME_COLLISION) ? 80 :
(s == STATUS_NOT_FOUND) ? 2 : 5;
return INVALID_HANDLE_VALUE;
}
if (disposition == OPEN_ALWAYS && wantWrite) {
// Open if exists, create if not.
uint32_t kh = 0;
if (K32OpenFileNative(translatedName, &kh) != 0) {
if (K32CreateFileNative(translatedName, &kh) != 0) {
gLastError = 5;
return INVALID_HANDLE_VALUE;
}
}
return KH_TO_HANDLE(kh);
}
if (disposition == CREATE_NEW && wantWrite) {
// Fail if the file already exists (we can't check atomically,
// but SysCreateFile returns NAME_COLLISION for existing files).
uint32_t kh = 0;
uint32_t s = K32CreateFileNative(translatedName, &kh);
if (s != 0) { gLastError = 80; return INVALID_HANDLE_VALUE; } // ERROR_FILE_EXISTS
return KH_TO_HANDLE(kh);
}
// Any other combination (e.g. read-only CREATE_ALWAYS) is not supported.
gLastError = 87; // ERROR_INVALID_PARAMETER
return INVALID_HANDLE_VALUE;
return KH_TO_HANDLE(kh);
}
// GetFileSize - fills optional high-DWORD pointer, returns low DWORD.
// Returns 0xFFFFFFFF on error, matching Win32 behaviour.
__declspec(dllexport) DWORD GetFileSize(HANDLE hFile, DWORD* fileSizeHigh) {
if (!hFile || hFile == INVALID_HANDLE_VALUE) { gLastError = 6; return 0xFFFFFFFFUL; }
uint64_t sz = SysGetFileSize(HANDLE_TO_KH(hFile));
uint64_t sz = 0;
uint32_t s = SysGetFileSize(HANDLE_TO_KH(hFile), &sz);
if (s != 0) { gLastError = 6; return 0xFFFFFFFFUL; }
if (fileSizeHigh) *fileSizeHigh = (DWORD)(sz >> 32);
return (DWORD)(sz & 0xFFFFFFFFULL);
}
@@ -922,12 +916,14 @@ __declspec(dllexport) DWORD SetFilePointer(HANDLE hFile, long dist,
if (method == FILE_BEGIN) {
target = delta;
} else if (method == FILE_CURRENT) {
uint64_t cur = SysGetFilePos(kh);
if (cur == (uint64_t)-1 || cur > 0x7FFFFFFFFFFFFFFFULL) { gLastError = 6; return 0xFFFFFFFFUL; }
uint64_t cur = 0;
uint32_t s = SysGetFilePos(kh, &cur);
if (s != 0 || cur > 0x7FFFFFFFFFFFFFFFULL) { gLastError = 6; return 0xFFFFFFFFUL; }
target = (int64_t)cur + delta;
} else if (method == FILE_END) {
uint64_t sz = SysGetFileSize(kh);
if (sz > 0x7FFFFFFFFFFFFFFFULL) { gLastError = 6; return 0xFFFFFFFFUL; }
uint64_t sz = 0;
uint32_t s = SysGetFileSize(kh, &sz);
if (s != 0 || sz > 0x7FFFFFFFFFFFFFFFULL) { gLastError = 6; return 0xFFFFFFFFUL; }
target = (int64_t)sz + delta;
} else {
gLastError = 87; return 0xFFFFFFFFUL;
@@ -949,9 +945,10 @@ __declspec(dllexport) DWORD SetFilePointer(HANDLE hFile, long dist,
__declspec(dllexport) BOOL SetEndOfFile(HANDLE hFile) {
if (!hFile || hFile == INVALID_HANDLE_VALUE) { gLastError = 6; return FALSE; }
uint32_t kh = HANDLE_TO_KH(hFile);
uint64_t pos = SysGetFilePos(kh);
if (pos == (uint64_t)-1) { gLastError = 6; return FALSE; }
uint32_t s = SysTruncateFile(kh, pos);
uint64_t pos = 0;
uint32_t s = SysGetFilePos(kh, &pos);
if (s != 0) { gLastError = 6; return FALSE; }
s = SysTruncateFile(kh, pos);
if (s != 0) { gLastError = 1; return FALSE; }
return TRUE;
}
@@ -1184,7 +1181,7 @@ __declspec(dllexport) DWORD GetModuleFileNameA(HANDLE hModule,
// Implements the terminate Process operation.
__declspec(dllexport) BOOL TerminateProcess(HANDLE hProcess, unsigned int uExitCode) {
if (hProcess == GetCurrentProcess()) {
SysExitProcess((int)uExitCode);
SysExitProcess((int32_t)uExitCode);
while (true) ;
}
@@ -1193,16 +1190,9 @@ __declspec(dllexport) BOOL TerminateProcess(HANDLE hProcess, unsigned int uExitC
return FALSE;
}
uint32_t pid = 0;
uint32_t s = SysGetProcessPid(HANDLE_TO_KH(hProcess), &pid);
if (s != 0 || pid == 0) {
gLastError = 6; // ERROR_INVALID_HANDLE
return FALSE;
}
s = SysKillProcess(pid, (int)uExitCode);
uint32_t s = SysKillProcess(HANDLE_TO_KH(hProcess), (int32_t)uExitCode);
if (s != 0) {
gLastError = 5; // ERROR_ACCESS_DENIED / generic failure for now
gLastError = (s == STATUS_INVALID_HANDLE) ? 6 : 5;
return FALSE;
}
return TRUE;
@@ -1290,7 +1280,6 @@ __declspec(dllexport) DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMillisec
return 0xFFFFFFFFUL;
}
// Implements the extract Application Path A operation.
static BOOL ExtractApplicationPathA(const char* commandLine, char* out, size_t outSize) {
if (!commandLine || !out || outSize == 0) return FALSE;
@@ -1411,7 +1400,7 @@ __declspec(dllexport) BOOL GetExitCodeProcess(HANDLE hProcess, DWORD* lpExitCode
if (!lpExitCode) { gLastError = 87; return FALSE; }
uint32_t kh = HANDLE_TO_KH(hProcess);
if (!kh) { gLastError = 6; return FALSE; } // ERROR_INVALID_HANDLE
int code = 0;
int32_t code = 0;
uint32_t s = SysGetProcessExitCode(kh, &code);
if (s != 0) { gLastError = 6; return FALSE; }
*lpExitCode = (DWORD)code;
@@ -1471,13 +1460,13 @@ static BOOL K32IsConsoleOutputHandle(HANDLE h) {
// Implements the k32 Set Console Last Error operation.
static void K32SetConsoleLastError(uint32_t status) {
switch (status) {
case SYS_STATUS_SUCCESS:
case STATUS_SUCCESS:
gLastError = 0;
break;
case SYS_STATUS_INVALID_PARAMETER:
case STATUS_INVALID_PARAMETER:
gLastError = 87;
break;
case SYS_STATUS_NO_MEMORY:
case STATUS_NO_MEMORY:
gLastError = 8;
break;
default:
@@ -1506,7 +1495,8 @@ __declspec(dllexport) BOOL ReadConsoleA(HANDLE hConsoleInput,
DWORD i = 0; // Notice we switched to a while loop
while (i < nNumberOfCharsToRead) {
char c = SysReadKeyboardChar();
char c = 0;
if (SysReadKeyboardChar(&c) != STATUS_SUCCESS) continue;
// Ignore unmapped keys (Shift, Ctrl, etc.).
if (c == 0) continue;
@@ -1518,7 +1508,7 @@ __declspec(dllexport) BOOL ReadConsoleA(HANDLE hConsoleInput,
// Stop reading when the user presses Enter.
if (c == '\n' || c == '\r') {
// If your shell expects strings to be \n terminated, leave this.
// If your shell expects \0 termination without a newline,
// If your shell expects \0 termination without a newline,
// you might want to replace buf[i-1] with \0 here!
break;
}
@@ -1558,7 +1548,7 @@ __declspec(dllexport) BOOL GetConsoleScreenBufferInfo(HANDLE hConsoleOutput,
SYS_CONSOLE_INFO info;
uint32_t s = SysGetConsoleInfo(&info);
if (s != SYS_STATUS_SUCCESS) {
if (s != STATUS_SUCCESS) {
K32SetConsoleLastError(s);
return FALSE;
}
@@ -1589,7 +1579,7 @@ __declspec(dllexport) BOOL SetConsoleCursorPosition(HANDLE hConsoleOutput,
}
uint32_t s = SysSetConsoleCursor((int)dwCursorPosition.X, (int)dwCursorPosition.Y);
if (s != SYS_STATUS_SUCCESS) {
if (s != STATUS_SUCCESS) {
K32SetConsoleLastError(s);
return FALSE;
}
@@ -1618,7 +1608,7 @@ __declspec(dllexport) BOOL FillConsoleOutputCharacterA(HANDLE hConsoleOutput,
(int)dwWriteCoord.Y, (size_t)nLength,
&written);
if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = (DWORD)written;
if (s != SYS_STATUS_SUCCESS) {
if (s != STATUS_SUCCESS) {
K32SetConsoleLastError(s);
return FALSE;
}
@@ -1647,18 +1637,17 @@ __declspec(dllexport) BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput,
(int)dwWriteCoord.Y, (size_t)nLength,
&written);
if (lpNumberOfAttrsWritten) *lpNumberOfAttrsWritten = (DWORD)written;
if (s != SYS_STATUS_SUCCESS) {
if (s != STATUS_SUCCESS) {
K32SetConsoleLastError(s);
return FALSE;
}
return TRUE;
}
// Directory enumeration (FindFirstFileA / FindNextFileA / FindClose).
// Directory enumeration (FindFirstFileA / FindNextFileA / FindClose).
typedef SYS_DIR_ENTRY KDIR_ENTRY;
// FIND_HANDLE is a user-side wrapper: it stores the kernel dir handle and
// the wildcard pattern so FindNextFileA can filter subsequent entries.
// We return a pointer to this struct cast to HANDLE; it is NOT a kernel
@@ -1912,16 +1901,16 @@ __declspec(dllexport) BOOL SetCurrentDirectoryA(const char* lpPathName) {
// Returns current Directory A.
__declspec(dllexport) DWORD GetCurrentDirectoryA(DWORD nBufferLength, char* lpBuffer) {
if (!lpBuffer || nBufferLength == 0) {
// Return required size (including NUL). Max CWD is 512 bytes + "C:\\".
return 515;
// Return a conservative required size including NUL.
return SYS_CWD_MAX + 1;
}
// Kernel returns native "N:/path". Present it as a Win32 drive letter.
char raw[512];
char raw[SYS_CWD_MAX + 1];
uint32_t s = K32GetCwdNative(raw, sizeof(raw), NULL);
if (s != 0) { gLastError = 1; return 0; }
char full[515];
char full[SYS_CWD_MAX + 1];
char drive = 'C';
const char* rel = raw;
if (raw[0] >= '0' && raw[0] <= '7' && raw[1] == ':' &&
@@ -1948,7 +1937,6 @@ __declspec(dllexport) DWORD GetCurrentDirectoryA(DWORD nBufferLength, char* lpBu
return (DWORD)(needed - 1); // length without NUL, matching Win32
}
__declspec(dllexport) HANDLE CreateMutexA(void* lpMutexAttributes, BOOL bInitialOwner,
const char* lpName) {
(void)lpMutexAttributes; (void)lpName;
@@ -2108,26 +2096,28 @@ static long long TscFreqFromCpuid(void) {
return (long long)crystal_hz * numer / denom;
}
// Calibrate TSC against SysGetTick (1 unit = 1 microsecond).
// Calibrates TSC against the native monotonic tick source.
static long long TscFreqCalibrate(void) {
// We'll wait for 100ms (100,000 microseconds) to get a stable sample.
const uint64_t CALIBRATION_US = 100000;
uint64_t frequency = K32TickFrequency();
if (!frequency) return 0;
uint64_t calibrationTicks = frequency / 10ull;
if (!calibrationTicks) calibrationTicks = 1;
uint64_t t0 = SysGetTick();
uint64_t tsc0 = __rdtsc();
// Simple busy wait for the duration.
while ((SysGetTick() - t0) < CALIBRATION_US) {
_mm_pause();
while ((SysGetTick() - t0) < calibrationTicks) {
_mm_pause();
}
uint64_t t1 = SysGetTick();
uint64_t tsc1 = __rdtsc();
uint64_t delta_tsc = tsc1 - tsc0;
uint64_t delta_us = t1 - t0;
uint64_t delta_us = SysTicksToMicroseconds(t1 - t0, frequency);
if (!delta_us) return 0;
// Hz = (Delta TSC / Delta Microseconds) * 1,000,000.
return (long long)(delta_tsc * 1000000ULL / delta_us);
}
@@ -2199,7 +2189,7 @@ __declspec(dllexport) void GetSystemTime(SYSTEMTIME* lpSystemTime) {
if (!lpSystemTime) return;
SYS_SYSTEM_TIME st;
if (SysGetSystemTime(&st) != SYS_STATUS_SUCCESS) {
if (SysGetSystemTime(&st) != STATUS_SUCCESS) {
memset(lpSystemTime, 0, sizeof(*lpSystemTime));
return;
}
@@ -2237,11 +2227,12 @@ __declspec(dllexport) void GetSystemTimeAsFileTime(void* lpSystemTimeAsFileTime)
SYS_SYSTEM_TIME st;
uint64_t ft;
if (SysGetSystemTime(&st) == SYS_STATUS_SUCCESS) {
if (SysGetSystemTime(&st) == STATUS_SUCCESS) {
ft = K32EpochToFileTime(st.EpochSeconds, st.Nanosecond);
} else {
uint64_t frequency = K32TickFrequency();
const uint64_t FALLBACK_2024_01_01_FT = 133485408000000000ULL;
ft = FALLBACK_2024_01_01_FT + (SysGetTick() * 10ULL);
ft = FALLBACK_2024_01_01_FT + SysTicksToMicroseconds(SysGetTick(), frequency) * 10ULL;
}
memcpy(lpSystemTimeAsFileTime, &ft, sizeof(ft));
}
@@ -2461,7 +2452,7 @@ __declspec(dllexport) BOOL IsDebuggerPresent(void) {
return FALSE;
}
// RTL Exception / Unwind (SEH infrastructure - all stubs).
// RTL Exception / Unwind (SEH infrastructure - all stubs).
typedef struct _RUNTIME_FUNCTION {
unsigned int BeginAddress;
@@ -2635,7 +2626,7 @@ __declspec(dllexport) BOOL FlsFree(DWORD dwFlsIndex) {
return TRUE;
}
// Pointer encoding (security cookie obfuscation)
// Pointer encoding (security cookie obfuscation)
// We have no security cookie; return the pointer unchanged.
__declspec(dllexport) void* EncodePointer(void* Ptr) { return Ptr; }
-1
View File
@@ -14,7 +14,6 @@ typedef struct tagPAINTSTRUCT {
HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; char res[32];
} PAINTSTRUCT;
// Implements the user32 Debug Print A operation.
static void User32DebugPrintA(const char* s) {
if (!s) return;
+3 -1
View File
@@ -49,7 +49,9 @@ typedef struct {
// Timer.
__declspec(dllexport) unsigned long timeGetTime(void) {
return (unsigned long)(SysGetTick() / 1000u);
uint64_t frequency = 0;
if (SysGetTickFrequency(&frequency) != STATUS_SUCCESS || !frequency) return 0;
return (unsigned long)SysTicksToMilliseconds(SysGetTick(), frequency);
}
// Waveform audio (stubs - no audio hardware at this stage).