Files
nt-lite/code/public/ntlite/syscall.h
T

524 lines
18 KiB
C

#pragma once
// Syscall.h
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <intrin.h>
#include <ntlite/string_view.h>
#include <ntlite/dirent.h>
#include <ntlite/input.h>
#include <ntlite/time.h>
#include <ntlite/display.h>
#define SYS_STATUS_SUCCESS 0u
#define SYS_STATUS_TIMEOUT 3u
#define SYS_STATUS_PENDING 4u
#define SYS_STATUS_ALERTED 5u
#define SYS_STATUS_INVALID_PARAMETER 0x10u
#define SYS_STATUS_NO_MEMORY 0x20u
#define SYS_STATUS_KERNEL_APC 6u
#define SYS_STATUS_USER_APC 7u
#define SYS_STATUS_CANCELLED 0x33u
#define SYS_STATUS_NOT_FOUND 0x22u
// ---------------------------------------------------------------------------
// User process/thread environment
// ---------------------------------------------------------------------------
// GS base points at SYS_TEB. GS:[0] is the process PEB pointer.
#define SYS_PEB_MAGIC 0x30424550u /* "PEB0" */
#define SYS_TEB_MAGIC 0x30424554u /* "TEB0" */
#define SYS_ENV_VERSION 1u
#define SYS_CWD_MAX 520u
#ifndef SYS_USER_ENV_TYPES_DEFINED
#define SYS_USER_ENV_TYPES_DEFINED 1
typedef struct SYS_PEB {
uint32_t Magic;
uint32_t Version;
uint32_t ProcessId;
SYS_STRING_VIEW ImagePath;
SYS_STRING_VIEW CommandLine;
SYS_STRING_VIEW CurrentDirectory;
} SYS_PEB;
typedef struct SYS_TEB {
SYS_PEB* Peb;
void* StackBase;
void* StackLimit;
struct SYS_TEB* Self;
uint32_t ThreadId;
uint32_t Magic;
// Native per-thread extension pointer. The kernel leaves this NULL;
// user-mode personalities/libraries may hang their own thread-local
// state here without baking subsystem semantics into SYS_TEB.
void* SubsystemData;
} SYS_TEB;
#endif // SYS_USER_ENV_TYPES_DEFINED
static inline SYS_PEB* SysGetPeb(void) {
return (SYS_PEB*)(uintptr_t)__readgsqword(0);
}
static inline SYS_TEB* SysGetTeb(void) {
return (SYS_TEB*)(uintptr_t)__readgsqword(offsetof(SYS_TEB, Self));
}
// ---------------------------------------------------------------------------
// APC and async I/O ABI
// ---------------------------------------------------------------------------
typedef struct SYS_IO_STATUS_BLOCK {
volatile uint32_t Status;
volatile uint64_t Information;
} SYS_IO_STATUS_BLOCK;
typedef void (*SYS_USER_APC_ROUTINE)(void* normalContext,
SYS_IO_STATUS_BLOCK* iosb,
uint64_t information);
typedef struct SYS_ASYNC_FILE_REQUEST {
uint32_t FileHandle;
uint32_t EventHandle; // optional; 0 means no event signal
uint32_t Flags;
uint64_t Offset; // explicit byte offset; does not touch file pointer
void* Buffer;
size_t Size;
SYS_IO_STATUS_BLOCK* Iosb; // required; initialized to SYS_STATUS_PENDING
SYS_USER_APC_ROUTINE ApcRoutine; // optional; requires SysSetUserApcDispatcher
void* ApcContext;
uint32_t* RequestHandleOut; // optional; receives cancel/query handle
} SYS_ASYNC_FILE_REQUEST;
typedef struct SYS_USER_APC_FRAME {
uint64_t Magic;
uint64_t OriginalRip;
uint64_t OriginalRsp;
uint64_t OriginalRflags;
uint64_t OriginalRax;
uint64_t Routine;
uint64_t NormalContext;
uint64_t SystemArgument1;
uint64_t SystemArgument2;
} SYS_USER_APC_FRAME;
#define SYS_USER_APC_FRAME_MAGIC 0x3143504152455355ULL
void SysUserApcDispatcher(void);
// ---------------------------------------------------------------------------
// Trap-frame query ABI
// ---------------------------------------------------------------------------
typedef struct SYS_TRAP_FRAME_INFO {
uint32_t Size;
uint32_t Kind;
uint32_t Vector;
uint32_t PreviousMode;
uint64_t Rip;
uint64_t Cs;
uint64_t Rflags;
uint64_t Rsp;
uint64_t Ss;
uint64_t Rax;
uint64_t Rcx;
uint64_t Rdx;
uint64_t R8;
uint64_t R9;
uint64_t R10;
uint64_t R11;
} SYS_TRAP_FRAME_INFO;
// ---------------------------------------------------------------------------
// String-view based syscall request structures
// ---------------------------------------------------------------------------
typedef struct SYS_CREATE_PROCESS_REQUEST {
SYS_STRING_VIEW Path;
SYS_STRING_VIEW CommandLine;
uint32_t* HandleOut;
} SYS_CREATE_PROCESS_REQUEST;
typedef struct SYS_PATH_HANDLE_REQUEST {
SYS_STRING_VIEW Path;
uint32_t* HandleOut;
} SYS_PATH_HANDLE_REQUEST;
typedef struct SYS_PATH_REQUEST {
SYS_STRING_VIEW Path;
} SYS_PATH_REQUEST;
typedef struct SYS_RENAME_FILE_REQUEST {
SYS_STRING_VIEW OldPath;
SYS_STRING_VIEW NewPath;
} SYS_RENAME_FILE_REQUEST;
typedef struct SYS_GET_CWD_REQUEST {
char* Buffer;
size_t Capacity;
size_t* LengthOut;
} SYS_GET_CWD_REQUEST;
typedef struct SYS_WRITE_CONSOLE_REQUEST {
SYS_STRING_VIEW Text;
} SYS_WRITE_CONSOLE_REQUEST;
typedef struct SYS_PRINT_DEBUG_REQUEST {
SYS_STRING_VIEW Text;
} SYS_PRINT_DEBUG_REQUEST;
typedef struct SYS_PUBLISH_QUEUE_REQUEST {
SYS_STRING_VIEW Name;
uint32_t QueueHandle;
} SYS_PUBLISH_QUEUE_REQUEST;
typedef struct SYS_OPEN_NAMED_QUEUE_REQUEST {
SYS_STRING_VIEW Name;
uint32_t* HandleOut;
} SYS_OPEN_NAMED_QUEUE_REQUEST;
typedef struct SYS_NAMED_QUEUE_OWNER_REQUEST {
SYS_STRING_VIEW Name;
uint32_t* PidOut;
} SYS_NAMED_QUEUE_OWNER_REQUEST;
// ---------------------------------------------------------------------------
// Process & thread lifecycle (0-14)
// ---------------------------------------------------------------------------
void SysExitProcess(int exitCode);
void SysExitThread(int exitCode);
uint32_t SysCreateProcess(const SYS_CREATE_PROCESS_REQUEST* request);
uint32_t SysWaitForProcess(uint32_t handle);
uint32_t SysGetProcessExitCode(uint32_t handle, int* exitCodeOut);
uint32_t SysKillProcess(uint32_t pid, int exitCode);
#define SYS_PROCESS_NAME_MAX 64u
#define SYS_PROCESS_CWD_MAX 128u
#define SYS_PROCESS_STATE_RUNNING 0u
#define SYS_PROCESS_STATE_TERMINATING 1u
#define SYS_PROCESS_STATE_EXITED 2u
#define SYS_PROCESS_FLAG_SYSTEM 0x00000001u
#define SYS_PROCESS_FLAG_CURRENT 0x00000002u
#define SYS_PROCESS_FLAG_TERMINATING 0x00000004u
#define SYS_PROCESS_FLAG_EXITED 0x00000008u
typedef struct SYS_PROCESS_INFO {
uint32_t Size;
uint32_t ProcessId;
uint32_t State;
uint32_t Flags;
uint32_t ThreadCount;
uint32_t HandleCount;
uint32_t ModuleCount;
uint32_t CurrentDrive;
int32_t ExitCode;
uint32_t Reserved0;
uintptr_t ImageBase;
size_t ImageSize;
uintptr_t PebBase;
size_t UserRegionCount;
size_t UserReservedBytes;
size_t UserCommittedBytes;
char Name[SYS_PROCESS_NAME_MAX];
char CurrentDirectory[SYS_PROCESS_CWD_MAX];
} SYS_PROCESS_INFO;
uint32_t SysGetProcessList(SYS_PROCESS_INFO* processesOut, size_t maxCount, size_t* countOut);
uint32_t SysGetProcessPid(uint32_t handle, uint32_t* pidOut);
uint32_t SysCreateThread(uintptr_t entry, uintptr_t arg, uint32_t priority, uint32_t* tidOut);
uint32_t SysWaitThread(uint32_t tid);
uint32_t SysGetCurrentTid(void);
uint32_t SysGetCurrentPid(void);
uint32_t SysSetThreadPriority(uint32_t priority);
uint32_t SysYield(void);
uint32_t SysSleep(uint64_t ms);
uint32_t SysSetUserApcDispatcher(void* dispatcher);
uint32_t SysApcReturn(const SYS_USER_APC_FRAME* frame);
// ---------------------------------------------------------------------------
// Virtual memory and handles
// ---------------------------------------------------------------------------
typedef enum SYS_PROTECT_VMION {
SYS_VM_NOACCESS = 0,
SYS_VM_READ = 1,
SYS_VM_READWRITE = 2,
SYS_VM_EXECUTE = 3,
SYS_VM_EXECUTE_READ = 4,
SYS_VM_EXECUTE_READWRITE = 5,
} SYS_PROTECT_VMION;
#define SYS_VM_FLAG_NONE 0u
#define SYS_VM_FLAG_FIXED 1u
typedef struct SYS_VM_REGION_INFO {
void* Base;
size_t PageCount;
uint32_t Protect;
uint32_t Flags;
uint32_t Type;
uint32_t OwnerPid;
} SYS_VM_REGION_INFO;
uint32_t SysAllocVm(void* preferredBase, size_t pageCount, uint32_t protect, uint32_t flags, void** baseOut);
uint32_t SysFreeVm(void* base);
uint32_t SysProtectVm(void* base, size_t pageCount, uint32_t protect, uint32_t* oldProtectOut);
uint32_t SysQueryVm(void* address, SYS_VM_REGION_INFO* out);
uint32_t SysCloseHandle(uint32_t handle);
// ---------------------------------------------------------------------------
// Synchronization primitives (19-31)
// ---------------------------------------------------------------------------
uint32_t SysCreateMutex(uint32_t* handleOut);
uint32_t SysAcquireMutex(uint32_t handle);
uint32_t SysTryAcquireMutex(uint32_t handle);
uint32_t SysReleaseMutex(uint32_t handle);
uint32_t SysCreateSem(int32_t initial, int32_t max, uint32_t* handleOut);
uint32_t SysWaitSem(uint32_t handle);
uint32_t SysTryWaitSem(uint32_t handle);
uint32_t SysSignalSem(uint32_t handle);
uint32_t SysCreateEvent(uint32_t type, uint32_t initialState, uint32_t* handleOut);
uint32_t SysSignalEvent(uint32_t handle);
uint32_t SysClearEvent(uint32_t handle);
uint32_t SysWaitEvent(uint32_t handle, uint32_t alertable);
// ---------------------------------------------------------------------------
// Queues and named queues (32-38)
// ---------------------------------------------------------------------------
uint32_t SysCreateQueue(uint32_t* handleOut);
uint32_t SysSendQueue(uint32_t handle, const void* msg, bool blocking);
uint32_t SysRecvQueue(uint32_t handle, void* msg, bool blocking);
uint32_t SysPublishQueue(const SYS_PUBLISH_QUEUE_REQUEST* request);
uint32_t SysOpenNamedQueue(const SYS_OPEN_NAMED_QUEUE_REQUEST* request);
uint32_t SysDuplicateQueue(uint32_t handle, uint32_t targetPid, uint32_t* handleOut);
uint32_t SysGetNamedQueueOwnerPid(const SYS_NAMED_QUEUE_OWNER_REQUEST* request);
// ---------------------------------------------------------------------------
// Files, directories, and current directory (39-56)
// ---------------------------------------------------------------------------
uint32_t SysOpenFile(const SYS_PATH_HANDLE_REQUEST* request);
uint32_t SysCreateFile(const SYS_PATH_HANDLE_REQUEST* request);
uint32_t SysReadFile(uint32_t handle, void* buf, size_t size, size_t* bytesRead);
uint32_t SysWriteFile(uint32_t handle, const void* buf, size_t size, size_t* written);
uint32_t SysReadFileAsync(const SYS_ASYNC_FILE_REQUEST* request);
uint32_t SysWriteFileAsync(const SYS_ASYNC_FILE_REQUEST* request);
uint32_t SysCancelIo(uint32_t asyncRequestHandle);
uint32_t SysSeekFile(uint32_t handle, uint64_t offset);
uint64_t SysGetFilePos(uint32_t handle);
uint64_t SysGetFileSize(uint32_t handle);
uint32_t SysTruncateFile(uint32_t handle, uint64_t newSize);
uint32_t SysDeleteFile(const SYS_PATH_REQUEST* request);
uint32_t SysRenameFile(const SYS_RENAME_FILE_REQUEST* request);
uint32_t SysOpenDir(const SYS_PATH_HANDLE_REQUEST* request);
uint32_t SysReadDir(uint32_t handle, SYS_DIR_ENTRY* entryOut);
uint32_t SysCreateDir(const SYS_PATH_REQUEST* request);
uint32_t SysRemoveDir(const SYS_PATH_REQUEST* request);
uint32_t SysSetCwd(const SYS_PATH_REQUEST* request);
uint32_t SysGetCwd(const SYS_GET_CWD_REQUEST* request);
// ---------------------------------------------------------------------------
// Console and graphics.
// ---------------------------------------------------------------------------
typedef struct SYS_CONSOLE_INFO {
uint32_t Columns;
uint32_t Rows;
uint32_t CursorX;
uint32_t CursorY;
uint16_t Attribute;
} SYS_CONSOLE_INFO;
uint32_t SysWriteConsole(const SYS_WRITE_CONSOLE_REQUEST* request);
uint32_t SysGetConsoleInfo(SYS_CONSOLE_INFO* infoOut);
uint32_t SysSetConsoleCursor(int x, int y);
uint32_t SysFillConsoleCharacter(char c, int x, int y, size_t length, size_t* writtenOut);
uint32_t SysFillConsoleAttribute(uint16_t attr, int x, int y, size_t length, size_t* writtenOut);
uint32_t SysPutScreenChar(char c, int x, int y, uint32_t fg, uint32_t bg);
uint32_t SysBlitScreen(int x, int y, int w, int h, const uint32_t* pixels);
uint32_t SysClearScreen(uint32_t color);
uint32_t SysGetScreenSize(int* widthOut, int* heightOut);
uint32_t SysQueryDisplayInfo(SYS_DISPLAY_INFO* infoOut);
// ---------------------------------------------------------------------------
// Input.
// ---------------------------------------------------------------------------
uint64_t SysPollKeyboard(void);
uint64_t SysIsKeyDown(INPUT_KEY key);
char SysReadKeyboardChar(void);
INPUT_KEY SysReadKey(void);
uint32_t SysGetKeyModifiers(void);
uint64_t SysPollMouse(void);
uint64_t SysReadMouse(int* dx, int* dy, uint8_t* buttons);
void SysGetMousePos(int* x, int* y);
// ---------------------------------------------------------------------------
// Native sockets
// ---------------------------------------------------------------------------
#define SYS_AF_INET 2u
#define SYS_SOCK_STREAM 1u
#define SYS_SOCK_DGRAM 2u
#define SYS_SOCK_RAW 3u
#define SYS_IPPROTO_ICMP 1u
#define SYS_IPPROTO_TCP 6u
#define SYS_IPPROTO_UDP 17u
#define SYS_RESOLVE_HOST_NAME_MAX 255u
#define SYS_SOCKET_OPT_RECV_TIMEOUT_MS 1u
#define SYS_SOCKET_OPT_SEND_TIMEOUT_MS 2u
#define SYS_SOCKET_OPT_NONBLOCKING 3u
#define SYS_POLL_READ 0x0001u
#define SYS_POLL_WRITE 0x0002u
#define SYS_POLL_ERROR 0x0004u
#define SYS_POLL_HANGUP 0x0008u
#define SYS_POLL_INVALID 0x0010u
#define SYS_POLL_TIMEOUT_INFINITE 0xFFFFFFFFu
#define SYS_SHUTDOWN_READ 0u
#define SYS_SHUTDOWN_WRITE 1u
#define SYS_SHUTDOWN_BOTH 2u
typedef struct SYS_SOCKET_ADDRESS_IPV4 {
uint16_t Family; // SYS_AF_INET
uint16_t Port; // host byte order
uint8_t Address[4]; // dotted-quad bytes, e.g. {10,0,2,2}
} SYS_SOCKET_ADDRESS_IPV4;
typedef struct SYS_SOCKET_SEND_TO_REQUEST {
const void* Buffer;
size_t Length;
uint32_t Flags;
const SYS_SOCKET_ADDRESS_IPV4* RemoteAddress;
size_t RemoteAddressSize;
size_t* SentOut;
} SYS_SOCKET_SEND_TO_REQUEST;
typedef struct SYS_SOCKET_RECV_FROM_REQUEST {
void* Buffer;
size_t Length;
uint32_t Flags;
SYS_SOCKET_ADDRESS_IPV4* RemoteAddressOut;
size_t* RemoteAddressSizeInOut;
size_t* ReceivedOut;
} SYS_SOCKET_RECV_FROM_REQUEST;
typedef struct SYS_RESOLVE_HOST_REQUEST {
SYS_STRING_VIEW Name;
uint32_t Family;
uint32_t Flags;
SYS_SOCKET_ADDRESS_IPV4* AddressOut;
size_t* AddressSizeInOut;
} SYS_RESOLVE_HOST_REQUEST;
typedef struct SYS_SOCKET_OPTION_REQUEST {
uint32_t Option;
void* Value;
size_t ValueSize;
size_t* ActualSizeOut;
} SYS_SOCKET_OPTION_REQUEST;
typedef struct SYS_POLLFD {
uint32_t Handle;
uint32_t Events;
uint32_t ReturnedEvents;
} SYS_POLLFD;
uint32_t SysCreateSocket(uint32_t domain, uint32_t type, uint32_t protocol, uint32_t* handleOut);
uint32_t SysBindSocket(uint32_t socket, const SYS_SOCKET_ADDRESS_IPV4* address, size_t addressSize);
uint32_t SysListenSocket(uint32_t socket, uint32_t backlog);
uint32_t SysAcceptSocket(uint32_t socket, SYS_SOCKET_ADDRESS_IPV4* remoteAddressOut, size_t* remoteAddressSizeInOut, uint32_t* acceptedHandleOut);
uint32_t SysConnectSocket(uint32_t socket, const SYS_SOCKET_ADDRESS_IPV4* address, size_t addressSize);
uint32_t SysSendSocket(uint32_t socket, const void* buffer, size_t length, uint32_t flags, size_t* sentOut);
uint32_t SysRecvSocket(uint32_t socket, void* buffer, size_t length, uint32_t flags, size_t* receivedOut);
uint32_t SysShutdownSocket(uint32_t socket, uint32_t how);
uint32_t SysSendToSocket(uint32_t socket, const SYS_SOCKET_SEND_TO_REQUEST* request);
uint32_t SysRecvFromSocket(uint32_t socket, const SYS_SOCKET_RECV_FROM_REQUEST* request);
uint32_t SysResolveHost(const SYS_RESOLVE_HOST_REQUEST* request);
uint32_t SysSetSocketOption(uint32_t socket, const SYS_SOCKET_OPTION_REQUEST* request);
uint32_t SysGetSocketOption(uint32_t socket, const SYS_SOCKET_OPTION_REQUEST* request);
uint32_t SysPoll(SYS_POLLFD* fds, size_t count, uint32_t timeoutMs, size_t* readyOut);
typedef struct SYS_MEMORY_STATUS {
uint64_t FreePhysicalBytes;
uint64_t KernelPoolBytes;
uint64_t UserHeapBytes;
} SYS_MEMORY_STATUS;
#define SYS_KERNEL_STATS_SCHEDULER 1u
#define SYS_KERNEL_STATS_PMM 2u
#define SYS_KERNEL_STATS_CPU 3u
#define SYS_KERNEL_STATS_MAX_CPUS 32u
typedef struct SYS_SCHEDULER_STATS {
uint64_t Ticks;
uint64_t ContextSwitches;
uint64_t KeepCurrentDecisions;
uint64_t IdleSelections;
uint64_t Demotions;
uint64_t AgingPromotions;
uint64_t QuantumExpirations;
uint64_t PriorityPreemptions;
uint64_t VoluntaryBlocks;
uint64_t CpuBurstDemotions;
uint64_t SmtSiblingDeferrals;
uint64_t SmtPrimaryPokes;
} SYS_SCHEDULER_STATS;
typedef struct SYS_PMM_STATS {
uint64_t TotalFrames;
uint64_t FreeFrames;
uint64_t UsedFrames;
uint64_t LargestFreeRun;
uint64_t FreeRunCount;
uint64_t FreeRunHistogram[8];
} SYS_PMM_STATS;
typedef struct SYS_CPU_STAT {
uint32_t CpuIndex;
uint32_t LapicId;
uint32_t Flags;
uint32_t CurrentTid;
uint64_t SchedulerTicks;
uint64_t ContextSwitches;
} SYS_CPU_STAT;
typedef struct SYS_CPU_STATS {
uint32_t CpuCount;
uint32_t Reserved;
SYS_CPU_STAT Cpu[SYS_KERNEL_STATS_MAX_CPUS];
} SYS_CPU_STATS;
#define SYS_CPU_FLAG_PRESENT 0x00000001u
#define SYS_CPU_FLAG_STARTED 0x00000002u
#define SYS_CPU_FLAG_PARKED 0x00000004u
#define SYS_CPU_FLAG_ONLINE 0x00000008u
#define SYS_CPU_FLAG_BSP 0x00000010u
#define SYS_CPU_FLAG_PRIMARY 0x00000020u
// ---------------------------------------------------------------------------
// Time and diagnostics
// ---------------------------------------------------------------------------
uint64_t SysGetTick(void);
uint32_t SysPrintDebug(const SYS_PRINT_DEBUG_REQUEST* request);
uint32_t SysQueryTrapFrame(SYS_TRAP_FRAME_INFO* info);
uint32_t SysGetMemoryStatus(SYS_MEMORY_STATUS* statusOut);
uint32_t SysQueryKernelStats(uint32_t classId, void* buffer, size_t bufferSize, size_t* requiredSizeOut);
uint32_t SysGetSystemTime(SYS_SYSTEM_TIME* timeOut);