1791 lines
61 KiB
C
1791 lines
61 KiB
C
// Public NTLite syscall ABI declarations shared between kernel, drivers, and user mode.
|
|
|
|
#pragma once
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <intrin.h>
|
|
#include <ntlite/string_view.h>
|
|
#include <ntlite/dirent.h>
|
|
#include <ntlite/file_stat.h>
|
|
#include <ntlite/input.h>
|
|
#include <ntlite/time.h>
|
|
#include <ntlite/display.h>
|
|
#include <ntlite/status.h>
|
|
#include <ntlite/handle.h>
|
|
#include <ntlite/security.h>
|
|
#include <ntlite/port.h>
|
|
#include <ntlite/service.h>
|
|
#include <ntlite/audio.h>
|
|
#include <ntlite/volume_manager.h>
|
|
#include <ntlite/thread.h>
|
|
|
|
// Syscall ABI convention: status-returning calls use KSTATUS. Syscalls use at most
|
|
// four register arguments; larger operations use request structures. Every
|
|
// SYS_*_REQUEST begins with Size, which must equal the exact structure size for
|
|
// the current ABI. Payload byte counts use Length or another semantic name.
|
|
|
|
// 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 5u
|
|
#define SYS_PATH_MAX 1024u
|
|
|
|
#ifndef SYS_USER_ENV_TYPES_DEFINED
|
|
#define SYS_USER_ENV_TYPES_DEFINED 1
|
|
|
|
#define SYS_STARTUP_CAPABILITY_MAX 32u
|
|
|
|
// Named startup grants form an immutable process-local manifest. Names confer no rights.
|
|
typedef struct SYS_STARTUP_CAPABILITY {
|
|
char Name[SYS_STARTUP_CAPABILITY_NAME_MAX + 1u];
|
|
SYS_HANDLE Handle;
|
|
} SYS_STARTUP_CAPABILITY;
|
|
|
|
// Validates a canonical, zero-padded grant name received from the process loader.
|
|
static inline bool SysStartupCapabilityNameValid(const char name[SYS_STARTUP_CAPABILITY_NAME_MAX + 1u]) {
|
|
if (!name || !name[0]) return false;
|
|
bool ended = false;
|
|
for (uint32_t i = 0; i <= SYS_STARTUP_CAPABILITY_NAME_MAX; ++i) {
|
|
char c = name[i];
|
|
if (!c) { ended = true; continue; }
|
|
if (ended || !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
|
(c >= '0' && c <= '9') || c == '_' || c == '-' || c == '.')) return false;
|
|
}
|
|
return ended;
|
|
}
|
|
|
|
typedef struct SYS_PEB {
|
|
uint32_t Magic;
|
|
uint32_t Version;
|
|
uint32_t ProcessId;
|
|
|
|
SYS_STRING_VIEW ImagePath;
|
|
SYS_STRING_VIEW CommandLine;
|
|
const SYS_STARTUP_CAPABILITY* StartupCapabilities;
|
|
uint32_t StartupCapabilityCount;
|
|
uint32_t Reserved;
|
|
|
|
const void* LoaderData;
|
|
} SYS_PEB;
|
|
|
|
typedef struct SYS_TEB {
|
|
SYS_PEB* Peb;
|
|
void* StackBase;
|
|
void* StackLimit;
|
|
struct SYS_TEB* Self;
|
|
uint32_t ThreadId;
|
|
uint32_t Magic;
|
|
|
|
// The kernel leaves this NULL so personalities can attach per-thread state.
|
|
void* SubsystemData;
|
|
} SYS_TEB;
|
|
|
|
// User bootstrap is consumed by the kernel, loader and personalities.
|
|
_Static_assert(sizeof(SYS_STARTUP_CAPABILITY) == 68u, "SYS_STARTUP_CAPABILITY ABI size changed");
|
|
_Static_assert(offsetof(SYS_PEB, ImagePath) == 16u, "SYS_PEB ImagePath offset changed");
|
|
_Static_assert(offsetof(SYS_PEB, LoaderData) == 64u, "SYS_PEB LoaderData offset changed");
|
|
_Static_assert(sizeof(SYS_PEB) == 72u, "SYS_PEB ABI size changed");
|
|
_Static_assert(offsetof(SYS_TEB, Peb) == 0u, "SYS_TEB GS:[0] PEB pointer changed");
|
|
_Static_assert(offsetof(SYS_TEB, SubsystemData) == 40u, "SYS_TEB personality slot offset changed");
|
|
_Static_assert(sizeof(SYS_TEB) == 48u, "SYS_TEB ABI size changed");
|
|
|
|
#endif // SYS_USER_ENV_TYPES_DEFINED
|
|
|
|
// Returns the current thread's process environment block.
|
|
static inline SYS_PEB* SysGetPeb(void) {
|
|
return (SYS_PEB*)(uintptr_t)__readgsqword(0);
|
|
}
|
|
|
|
// Resolves an immutable capability name without interpreting its authority.
|
|
static inline SYS_HANDLE SysGetStartupCapability(const char* name) {
|
|
SYS_PEB* peb = SysGetPeb();
|
|
if (!peb || peb->Magic != SYS_PEB_MAGIC || peb->Version != SYS_ENV_VERSION ||
|
|
!name || !name[0] || peb->StartupCapabilityCount > SYS_STARTUP_CAPABILITY_MAX ||
|
|
(peb->StartupCapabilityCount && !peb->StartupCapabilities))
|
|
return SYS_HANDLE_INVALID;
|
|
for (uint32_t i = 0; i < peb->StartupCapabilityCount; ++i) {
|
|
const char* entry = peb->StartupCapabilities[i].Name;
|
|
uint32_t n = 0;
|
|
while (n <= SYS_STARTUP_CAPABILITY_NAME_MAX && name[n] && entry[n] && name[n] == entry[n]) ++n;
|
|
if (n <= SYS_STARTUP_CAPABILITY_NAME_MAX && name[n] == '\0' && entry[n] == '\0')
|
|
return peb->StartupCapabilities[i].Handle;
|
|
}
|
|
return SYS_HANDLE_INVALID;
|
|
}
|
|
|
|
// Returns the current thread environment block.
|
|
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 KSTATUS Status;
|
|
volatile uint64_t Information;
|
|
} SYS_IO_STATUS_BLOCK;
|
|
// A completion status is a native KSTATUS even when written asynchronously.
|
|
_Static_assert(sizeof(SYS_IO_STATUS_BLOCK) == 16u, "SYS_IO_STATUS_BLOCK size changed");
|
|
_Static_assert(offsetof(SYS_IO_STATUS_BLOCK, Information) == 8u, "SYS_IO_STATUS_BLOCK Information offset changed");
|
|
|
|
|
|
typedef void (*SYS_USER_APC_ROUTINE)(void* normalContext,
|
|
SYS_IO_STATUS_BLOCK* iosb,
|
|
uint64_t information);
|
|
|
|
// Generic user APC callback shape used by capability-scoped direct notifications.
|
|
typedef void (*SYS_USER_APC_CALLBACK)(void* normalContext,
|
|
void* systemArgument1,
|
|
void* systemArgument2);
|
|
|
|
typedef struct SYS_FILE_IO_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE FileHandle;
|
|
uint32_t Flags;
|
|
void* Buffer;
|
|
size_t Length;
|
|
size_t* TransferredOut;
|
|
} SYS_FILE_IO_REQUEST;
|
|
|
|
static inline SYS_FILE_IO_REQUEST SysMakeFileIoRequest(SYS_HANDLE fileHandle,
|
|
const void* buffer,
|
|
size_t size,
|
|
size_t* transferredOut) {
|
|
SYS_FILE_IO_REQUEST request;
|
|
request.Size = sizeof(request);
|
|
request.FileHandle = fileHandle;
|
|
request.Flags = 0;
|
|
request.Buffer = (void*)(uintptr_t)buffer;
|
|
request.Length = size;
|
|
request.TransferredOut = transferredOut;
|
|
return request;
|
|
}
|
|
|
|
typedef struct SYS_ASYNC_FILE_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE FileHandle;
|
|
SYS_HANDLE 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 Length;
|
|
SYS_IO_STATUS_BLOCK* Iosb; // required; initialized to NTLSTATUS_PENDING
|
|
SYS_USER_APC_ROUTINE ApcRoutine; // optional; requires SysSetUserApcDispatcher
|
|
void* ApcContext;
|
|
SYS_HANDLE* RequestHandleOut; // optional; receives cancel/query handle
|
|
} SYS_ASYNC_FILE_REQUEST;
|
|
|
|
// User APC frames are kernel-issued control records, not resume contexts.
|
|
// User mode may read the routine and arguments, but SysApcReturn only accepts
|
|
// the active frame token and restores the kernel-owned saved return state.
|
|
typedef struct SYS_USER_APC_FRAME {
|
|
uint64_t Magic;
|
|
uint64_t ReturnToken;
|
|
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;
|
|
|
|
|
|
// Structured exception delivery ABI. The kernel owns capture, delivery, and
|
|
// context validation; personalities own VEH, SEH, signal, and unwind policy.
|
|
#define SYS_EXCEPTION_ABI_VERSION 2u
|
|
#define SYS_EXCEPTION_MAXIMUM_PARAMETERS 15u
|
|
|
|
#define SYS_EXCEPTION_FLAG_NONE 0x00000000u
|
|
#define SYS_EXCEPTION_FLAG_NONCONTINUABLE 0x00000001u
|
|
#define SYS_EXCEPTION_FLAG_FIRST_CHANCE 0x00000002u
|
|
|
|
#define SYS_EXCEPTION_DISPATCH_FLAG_NONE 0x00000000u
|
|
#define SYS_EXCEPTION_CONTINUE_FLAG_NONE 0x00000000u
|
|
#define SYS_RAISE_EXCEPTION_FLAG_NONE 0x00000000u
|
|
#define SYS_RAISE_EXCEPTION_FLAG_NONCONTINUABLE 0x00000001u
|
|
|
|
// Native exception codes are an nt-lite ABI. Personality runtimes translate
|
|
// them to their own exception or signal namespaces at the user-mode boundary.
|
|
#define SYS_EXCEPTION_CODE_UNKNOWN 1u
|
|
#define SYS_EXCEPTION_CODE_USER_RAISED 2u
|
|
#define SYS_EXCEPTION_CODE_ACCESS_VIOLATION 3u
|
|
#define SYS_EXCEPTION_CODE_DATATYPE_MISALIGNMENT 4u
|
|
#define SYS_EXCEPTION_CODE_ILLEGAL_INSTRUCTION 5u
|
|
#define SYS_EXCEPTION_CODE_PRIVILEGED_INSTRUCTION 6u
|
|
#define SYS_EXCEPTION_CODE_BREAKPOINT 7u
|
|
#define SYS_EXCEPTION_CODE_SINGLE_STEP 8u
|
|
#define SYS_EXCEPTION_CODE_INT_DIVIDE_BY_ZERO 9u
|
|
#define SYS_EXCEPTION_CODE_INT_OVERFLOW 10u
|
|
#define SYS_EXCEPTION_CODE_ARRAY_BOUNDS_EXCEEDED 11u
|
|
#define SYS_EXCEPTION_CODE_FLT_DENORMAL_OPERAND 12u
|
|
#define SYS_EXCEPTION_CODE_FLT_DIVIDE_BY_ZERO 13u
|
|
#define SYS_EXCEPTION_CODE_FLT_INEXACT_RESULT 14u
|
|
#define SYS_EXCEPTION_CODE_FLT_INVALID_OPERATION 15u
|
|
#define SYS_EXCEPTION_CODE_FLT_OVERFLOW 16u
|
|
#define SYS_EXCEPTION_CODE_FLT_STACK_CHECK 17u
|
|
#define SYS_EXCEPTION_CODE_FLT_UNDERFLOW 18u
|
|
#define SYS_EXCEPTION_CODE_STACK_OVERFLOW 19u
|
|
#define SYS_EXCEPTION_CODE_GUARD_PAGE_VIOLATION 20u
|
|
|
|
#define SYS_EXCEPTION_DISPOSITION_CONTINUE_EXECUTION 0u
|
|
#define SYS_EXCEPTION_DISPOSITION_CONTINUE_SEARCH 1u
|
|
#define SYS_EXCEPTION_DISPOSITION_EXECUTE_HANDLER 2u
|
|
#define SYS_EXCEPTION_DISPOSITION_TERMINATE_PROCESS 3u
|
|
|
|
#define SYS_CONTEXT_FLAG_NONE 0x0000000000000000ull
|
|
#define SYS_CONTEXT_FLAG_CONTROL 0x0000000000000001ull
|
|
#define SYS_CONTEXT_FLAG_INTEGER 0x0000000000000002ull
|
|
#define SYS_CONTEXT_FLAG_SEGMENTS 0x0000000000000004ull
|
|
#define SYS_CONTEXT_FLAG_ALL (SYS_CONTEXT_FLAG_CONTROL | \
|
|
SYS_CONTEXT_FLAG_INTEGER | \
|
|
SYS_CONTEXT_FLAG_SEGMENTS)
|
|
|
|
typedef struct SYS_USER_CONTEXT {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t Flags;
|
|
|
|
uint64_t Rip;
|
|
uint64_t Rsp;
|
|
uint64_t Rflags;
|
|
|
|
uint64_t Rax;
|
|
uint64_t Rcx;
|
|
uint64_t Rdx;
|
|
uint64_t Rbx;
|
|
uint64_t Rbp;
|
|
uint64_t Rsi;
|
|
uint64_t Rdi;
|
|
uint64_t R8;
|
|
uint64_t R9;
|
|
uint64_t R10;
|
|
uint64_t R11;
|
|
uint64_t R12;
|
|
uint64_t R13;
|
|
uint64_t R14;
|
|
uint64_t R15;
|
|
|
|
uint32_t SegCs;
|
|
uint32_t SegSs;
|
|
uint32_t SegDs;
|
|
uint32_t SegEs;
|
|
uint32_t SegFs;
|
|
uint32_t SegGs;
|
|
uint32_t Reserved0;
|
|
uint32_t Reserved1;
|
|
} SYS_USER_CONTEXT;
|
|
|
|
typedef struct SYS_EXCEPTION_RECORD {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint32_t Code;
|
|
uint32_t Flags;
|
|
|
|
uintptr_t ExceptionAddress;
|
|
uintptr_t FaultAddress;
|
|
uint64_t ErrorCode;
|
|
|
|
uint32_t ParameterCount;
|
|
// Meaningful only when Code is SYS_EXCEPTION_CODE_USER_RAISED. The native
|
|
// kernel treats this as an opaque personality/application value.
|
|
uint32_t UserCode;
|
|
uint64_t Parameters[SYS_EXCEPTION_MAXIMUM_PARAMETERS];
|
|
} SYS_EXCEPTION_RECORD;
|
|
|
|
typedef struct SYS_EXCEPTION_FRAME {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint32_t Flags;
|
|
uint32_t Reserved;
|
|
|
|
SYS_EXCEPTION_RECORD ExceptionRecord;
|
|
SYS_USER_CONTEXT ContextRecord;
|
|
void* DispatcherContext;
|
|
} SYS_EXCEPTION_FRAME;
|
|
|
|
typedef void (*SYS_USER_EXCEPTION_DISPATCHER)(SYS_EXCEPTION_FRAME* frame);
|
|
|
|
typedef struct SYS_EXCEPTION_DISPATCHER_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Flags;
|
|
|
|
// A null routine unregisters the dispatcher and clears the optional stack.
|
|
SYS_USER_EXCEPTION_DISPATCHER DispatcherRoutine;
|
|
|
|
// Opaque user-mode value passed back to the dispatcher.
|
|
void* DispatcherContext;
|
|
|
|
// Optional user-mode stack extent. Base is the low address and size is the
|
|
// byte length; delivery will consume it from high addresses downward.
|
|
void* ExceptionStackBase;
|
|
size_t ExceptionStackSize;
|
|
} SYS_EXCEPTION_DISPATCHER_REQUEST;
|
|
|
|
typedef struct SYS_CONTINUE_EXCEPTION_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Flags;
|
|
uint32_t Disposition;
|
|
uint32_t Reserved;
|
|
const SYS_USER_CONTEXT* Context;
|
|
} SYS_CONTINUE_EXCEPTION_REQUEST;
|
|
|
|
typedef struct SYS_RAISE_EXCEPTION_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Flags;
|
|
// Opaque user/personality exception value carried in SYS_EXCEPTION_RECORD.UserCode.
|
|
uint32_t UserCode;
|
|
uint32_t ParameterCount;
|
|
const uint64_t* Parameters;
|
|
} SYS_RAISE_EXCEPTION_REQUEST;
|
|
|
|
// String-view based syscall request structures.
|
|
#define SYS_CREATE_PROCESS_OBJECT_FLAG_NONE 0x00000000u
|
|
|
|
typedef struct SYS_CREATE_PROCESS_OBJECT_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Flags;
|
|
SYS_STRING_VIEW ImagePath;
|
|
SYS_STRING_VIEW CommandLine;
|
|
SYS_HANDLE SecurityContext;
|
|
SYS_HANDLE* ProcessHandleOut;
|
|
} SYS_CREATE_PROCESS_OBJECT_REQUEST;
|
|
|
|
typedef struct SYS_ALLOC_PROCESS_VM_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE ProcessHandle;
|
|
uint32_t Protect;
|
|
uint32_t Flags;
|
|
size_t PageCount;
|
|
void** BaseOut;
|
|
} SYS_ALLOC_PROCESS_VM_REQUEST;
|
|
|
|
#define SYS_START_PROCESS_FLAG_NONE 0x00000000u
|
|
typedef struct SYS_START_PROCESS_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE ProcessHandle;
|
|
uint32_t Flags;
|
|
uintptr_t MainImageBase;
|
|
size_t MainImageSize;
|
|
uintptr_t EntryPoint;
|
|
const SYS_STARTUP_CAPABILITY* StartupCapabilities;
|
|
uint32_t StartupCapabilityCount;
|
|
const void* LoaderData;
|
|
} SYS_START_PROCESS_REQUEST;
|
|
|
|
#define SYS_FILE_ACCESS_READ 0x00000001u
|
|
#define SYS_FILE_ACCESS_WRITE 0x00000002u
|
|
#define SYS_FILE_ACCESS_APPEND 0x00000004u
|
|
#define SYS_FILE_ACCESS_QUERY 0x00000008u
|
|
#define SYS_FILE_ACCESS_LOCK 0x00000010u
|
|
|
|
#define SYS_FILE_OPEN_EXISTING 1u
|
|
#define SYS_FILE_CREATE_NEW 2u
|
|
#define SYS_FILE_CREATE_ALWAYS 3u
|
|
#define SYS_FILE_OPEN_ALWAYS 4u
|
|
#define SYS_FILE_TRUNCATE_EXISTING 5u
|
|
|
|
#define SYS_FILE_FLAG_NONE 0x00000000u
|
|
|
|
// Opens or creates a file beneath a mounted-volume or directory capability.
|
|
// Path is a canonical native relative path: '/' separators only, with no leading/trailing
|
|
// separator, empty component, '.', '..', backslash, or embedded NUL.
|
|
typedef struct SYS_OPEN_FILE_AT_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE RootHandle;
|
|
SYS_STRING_VIEW Path;
|
|
uint32_t Access;
|
|
uint32_t Disposition;
|
|
uint32_t Flags;
|
|
SYS_HANDLE* HandleOut;
|
|
} SYS_OPEN_FILE_AT_REQUEST;
|
|
|
|
#define SYS_DIR_ACCESS_ENUMERATE 0x00000001u
|
|
#define SYS_DIR_ACCESS_OPEN 0x00000002u
|
|
#define SYS_DIR_ACCESS_MODIFY 0x00000004u
|
|
#define SYS_DIR_FLAG_NONE 0x00000000u
|
|
|
|
// Opens a directory beneath a mounted-volume or directory capability. An empty Path
|
|
// opens the root itself; non-empty paths use the same canonical relative-path contract.
|
|
typedef struct SYS_OPEN_DIR_AT_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE RootHandle;
|
|
SYS_STRING_VIEW Path;
|
|
uint32_t Access;
|
|
uint32_t Flags;
|
|
SYS_HANDLE* HandleOut;
|
|
} SYS_OPEN_DIR_AT_REQUEST;
|
|
|
|
// Performs one path-only operation beneath a mounted-volume or directory capability.
|
|
typedef struct SYS_PATH_AT_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE RootHandle;
|
|
SYS_STRING_VIEW Path;
|
|
} SYS_PATH_AT_REQUEST;
|
|
|
|
// Queries metadata beneath a mounted-volume or directory capability.
|
|
typedef struct SYS_STAT_AT_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE RootHandle;
|
|
SYS_STRING_VIEW Path;
|
|
SYS_FILE_STAT* StatOut;
|
|
} SYS_STAT_AT_REQUEST;
|
|
|
|
// Renames one path between capability-relative roots. Cross-volume rename is rejected.
|
|
typedef struct SYS_RENAME_AT_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE OldRootHandle;
|
|
SYS_STRING_VIEW OldPath;
|
|
SYS_HANDLE NewRootHandle;
|
|
SYS_STRING_VIEW NewPath;
|
|
} SYS_RENAME_AT_REQUEST;
|
|
|
|
// Builds a capability-relative file-open request.
|
|
static inline SYS_OPEN_FILE_AT_REQUEST SysMakeOpenFileAtRequest(SYS_HANDLE rootHandle,
|
|
SYS_STRING_VIEW path,
|
|
uint32_t access,
|
|
uint32_t disposition,
|
|
uint32_t flags,
|
|
SYS_HANDLE* handleOut) {
|
|
SYS_OPEN_FILE_AT_REQUEST request;
|
|
request.Size = sizeof(request);
|
|
request.RootHandle = rootHandle;
|
|
request.Path = path;
|
|
request.Access = access;
|
|
request.Disposition = disposition;
|
|
request.Flags = flags;
|
|
request.HandleOut = handleOut;
|
|
return request;
|
|
}
|
|
|
|
// Builds a capability-relative directory-open request.
|
|
static inline SYS_OPEN_DIR_AT_REQUEST SysMakeOpenDirAtRequest(SYS_HANDLE rootHandle,
|
|
SYS_STRING_VIEW path,
|
|
uint32_t access,
|
|
uint32_t flags,
|
|
SYS_HANDLE* handleOut) {
|
|
SYS_OPEN_DIR_AT_REQUEST request;
|
|
request.Size = sizeof(request);
|
|
request.RootHandle = rootHandle;
|
|
request.Path = path;
|
|
request.Access = access;
|
|
request.Flags = flags;
|
|
request.HandleOut = handleOut;
|
|
return request;
|
|
}
|
|
|
|
#define SYS_FILE_LOCK_SHARED 1u
|
|
#define SYS_FILE_LOCK_EXCLUSIVE 2u
|
|
#define SYS_FILE_LOCK_FLAG_NONE 0x00000000u
|
|
#define SYS_FILE_LOCK_TO_EOF UINT64_MAX
|
|
|
|
// File locks are advisory, process-owned byte-range locks keyed by filesystem
|
|
// identity. A zero timeout is an immediate try and returns NTLSTATUS_WOULD_BLOCK
|
|
// on conflict. A finite timeout returns NTLSTATUS_TIMEOUT only when its deadline
|
|
// expires. SYS_WAIT_TIMEOUT_INFINITE waits without a deadline. Length must be
|
|
// nonzero; SYS_FILE_LOCK_TO_EOF locks from Offset through end-of-file growth.
|
|
// Unlock removes this process's overlapping locks for the file identity.
|
|
typedef struct SYS_LOCK_FILE_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE FileHandle;
|
|
uint32_t Mode;
|
|
uint32_t Flags;
|
|
uint64_t Offset;
|
|
uint64_t Length;
|
|
uint64_t TimeoutMilliseconds;
|
|
} SYS_LOCK_FILE_REQUEST;
|
|
|
|
typedef struct SYS_UNLOCK_FILE_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE FileHandle;
|
|
uint32_t Flags;
|
|
uint64_t Offset;
|
|
uint64_t Length;
|
|
} SYS_UNLOCK_FILE_REQUEST;
|
|
|
|
#define SYS_FILE_LOCK_NONE 0u
|
|
|
|
typedef struct SYS_FILE_LOCK_INFO {
|
|
uint32_t Size;
|
|
uint32_t Mode;
|
|
uint32_t OwnerProcessId;
|
|
uint32_t Reserved;
|
|
uint64_t Offset;
|
|
uint64_t Length;
|
|
} SYS_FILE_LOCK_INFO;
|
|
|
|
typedef struct SYS_QUERY_FILE_LOCK_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE FileHandle;
|
|
uint32_t Mode;
|
|
uint32_t Flags;
|
|
uint64_t Offset;
|
|
uint64_t Length;
|
|
SYS_FILE_LOCK_INFO* InfoOut;
|
|
} SYS_QUERY_FILE_LOCK_REQUEST;
|
|
|
|
#define SYS_FILE_STATUS_APPEND 0x00000001u
|
|
|
|
typedef struct SYS_SET_FILE_STATUS_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE FileHandle;
|
|
uint32_t Mask;
|
|
uint32_t Flags;
|
|
} SYS_SET_FILE_STATUS_REQUEST;
|
|
|
|
#define SYS_PIPE_ATOMIC_WRITE_MAX 4096u
|
|
#define SYS_PIPE_BUFFER_CAPACITY 16384u
|
|
#define SYS_PIPE_SHARED_VERSION 1u
|
|
#define SYS_PIPE_SHARED_MAGIC 0x31504950u
|
|
#define SYS_PIPE_SHARED_HEADER_BYTES 4096u
|
|
|
|
// Shared pipe state. The first page is mapped read-only and contains
|
|
// kernel-authoritative lifecycle state. The following pages are writable and
|
|
// form the user-mode ring data plane. Positions are monotonic byte counters.
|
|
typedef struct SYS_PIPE_SHARED_STATE {
|
|
uint32_t Magic;
|
|
uint32_t Version;
|
|
uint32_t Capacity;
|
|
uint32_t HeaderBytes;
|
|
volatile int32_t ReaderOpen;
|
|
volatile int32_t WriterOpen;
|
|
uint8_t HeaderReserved[SYS_PIPE_SHARED_HEADER_BYTES - 24u];
|
|
|
|
volatile uint64_t ReadPosition;
|
|
volatile uint64_t WritePosition;
|
|
volatile int32_t ReadLock;
|
|
volatile int32_t WriteLock;
|
|
volatile int32_t ReadWaiters;
|
|
volatile int32_t WriteWaiters;
|
|
uint8_t RingReserved[16];
|
|
uint8_t Buffer[SYS_PIPE_BUFFER_CAPACITY];
|
|
} SYS_PIPE_SHARED_STATE;
|
|
|
|
_Static_assert(offsetof(SYS_PIPE_SHARED_STATE, ReadPosition) == SYS_PIPE_SHARED_HEADER_BYTES,
|
|
"SYS_PIPE_SHARED_STATE control page layout changed");
|
|
_Static_assert(offsetof(SYS_PIPE_SHARED_STATE, Buffer) == SYS_PIPE_SHARED_HEADER_BYTES + 48u,
|
|
"SYS_PIPE_SHARED_STATE ring layout changed");
|
|
_Static_assert(sizeof(SYS_PIPE_SHARED_STATE) == SYS_PIPE_SHARED_HEADER_BYTES + 48u + SYS_PIPE_BUFFER_CAPACITY,
|
|
"SYS_PIPE_SHARED_STATE ABI size changed");
|
|
|
|
typedef struct SYS_CREATE_PIPE_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Flags;
|
|
SYS_HANDLE* ReadHandleOut;
|
|
SYS_HANDLE* WriteHandleOut;
|
|
SYS_PIPE_SHARED_STATE** SharedStateOut;
|
|
} SYS_CREATE_PIPE_REQUEST;
|
|
|
|
typedef struct SYS_WRITE_CONSOLE_REQUEST {
|
|
uint32_t Size;
|
|
SYS_STRING_VIEW Text;
|
|
} SYS_WRITE_CONSOLE_REQUEST;
|
|
|
|
typedef struct SYS_PRINT_DEBUG_REQUEST {
|
|
uint32_t Size;
|
|
SYS_STRING_VIEW Text;
|
|
} SYS_PRINT_DEBUG_REQUEST;
|
|
|
|
|
|
#define SYS_QUEUE_FLAG_NONE 0x00000000u
|
|
#define SYS_QUEUE_MESSAGE_SIZE 56u
|
|
|
|
// Queue send and receive requests use wait-style timeouts. A zero timeout is
|
|
// an immediate try operation and returns NTLSTATUS_WOULD_BLOCK if the queue cannot
|
|
// make progress without waiting. SYS_WAIT_TIMEOUT_INFINITE requests a blocking
|
|
// wait without a deadline. Message pointers reference SYS_QUEUE_MESSAGE_SIZE
|
|
// bytes owned by the caller for the duration of the syscall. The common IPC
|
|
// pattern is a small control record with one pointer-sized payload token: the
|
|
// shared address-space model means that token does not need translation when
|
|
// both endpoints agree on the object lifetime. Queues order the token; they do
|
|
// not copy storage behind it.
|
|
typedef struct SYS_QUEUE_SEND_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE QueueHandle;
|
|
uint32_t Flags;
|
|
uint64_t TimeoutMilliseconds;
|
|
const void* Message;
|
|
} SYS_QUEUE_SEND_REQUEST;
|
|
|
|
typedef struct SYS_QUEUE_RECV_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE QueueHandle;
|
|
uint32_t Flags;
|
|
uint64_t TimeoutMilliseconds;
|
|
void* MessageOut;
|
|
} SYS_QUEUE_RECV_REQUEST;
|
|
|
|
#define SYS_WAIT_FLAG_NONE 0x00000000u
|
|
#define SYS_WAIT_FLAG_ALERTABLE 0x00000001u
|
|
#define SYS_WAIT_TIMEOUT_INFINITE UINT64_MAX
|
|
|
|
// SysWaitMany copies handles through a fixed kernel stack buffer. This public
|
|
// ABI/resource limit is intentionally small to keep wait setup bounded.
|
|
#define SYS_WAIT_MANY_MAX_HANDLES 32u
|
|
|
|
typedef struct SYS_WAIT_MANY_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Flags;
|
|
const SYS_HANDLE* Handles;
|
|
uint32_t Count;
|
|
uint32_t* SignaledIndexOut;
|
|
uint64_t TimeoutMilliseconds;
|
|
} SYS_WAIT_MANY_REQUEST;
|
|
|
|
typedef struct SYS_CREATE_THREAD_REQUEST {
|
|
uint32_t Size;
|
|
uintptr_t Entry;
|
|
uintptr_t Argument;
|
|
uint32_t Priority;
|
|
uint32_t Flags;
|
|
// Both outputs are optional for a running detached thread. Suspended creation
|
|
// requires ThreadHandleOut so the caller retains a capability to resume it.
|
|
SYS_HANDLE* ThreadHandleOut;
|
|
uint32_t* ThreadIdOut;
|
|
} SYS_CREATE_THREAD_REQUEST;
|
|
|
|
#define SYS_CREATE_THREAD_FLAG_NONE 0x00000000u
|
|
#define SYS_CREATE_THREAD_FLAG_SUSPENDED 0x00000001u
|
|
|
|
// Describes one generic user APC queued through a thread capability. The
|
|
// routine and arguments are interpreted in the target thread's user address
|
|
// space; possession of SYS_THREAD_RIGHT_NOTIFY is the authority boundary.
|
|
// INTERRUPT permits delivery on the next user return without requiring an
|
|
// alertable wait; ordinary APCs retain alertable-wait delivery semantics.
|
|
#define SYS_QUEUE_USER_APC_FLAG_NONE 0x00000000u
|
|
#define SYS_QUEUE_USER_APC_FLAG_INTERRUPT 0x00000001u
|
|
|
|
typedef struct SYS_QUEUE_USER_APC_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE ThreadHandle;
|
|
SYS_USER_APC_CALLBACK Routine;
|
|
void* NormalContext;
|
|
void* SystemArgument1;
|
|
void* SystemArgument2;
|
|
uint32_t Flags;
|
|
uint32_t Reserved;
|
|
} SYS_QUEUE_USER_APC_REQUEST;
|
|
|
|
#define SYS_POWER_ACTION_SHUTDOWN 1u
|
|
#define SYS_POWER_ACTION_RESTART 2u
|
|
|
|
KSTATUS SysOpenPowerEvent(SYS_HANDLE* eventHandleOut);
|
|
KSTATUS SysRequestSystemPower(uint32_t action);
|
|
KSTATUS SysQuerySystemPower(uint32_t* actionOut);
|
|
KSTATUS SysCompleteSystemPower(uint32_t action);
|
|
|
|
void SysExitProcess(int32_t exitCode);
|
|
void SysExitThread(int32_t exitCode);
|
|
KSTATUS SysCreateProcessObject(const SYS_CREATE_PROCESS_OBJECT_REQUEST* request);
|
|
KSTATUS SysAllocProcessVm(const SYS_ALLOC_PROCESS_VM_REQUEST* request);
|
|
KSTATUS SysProtectProcessVm(SYS_HANDLE processHandle, void* base, size_t pageCount, uint32_t protect);
|
|
KSTATUS SysStartProcess(const SYS_START_PROCESS_REQUEST* request);
|
|
KSTATUS SysWaitSingle(SYS_HANDLE handle, uint32_t flags, uint64_t timeoutMilliseconds);
|
|
KSTATUS SysWaitMany(const SYS_WAIT_MANY_REQUEST* request);
|
|
|
|
static inline KSTATUS SysWait(SYS_HANDLE handle, uint32_t flags) {
|
|
return SysWaitSingle(handle, flags, SYS_WAIT_TIMEOUT_INFINITE);
|
|
}
|
|
KSTATUS SysGetProcessExitCode(SYS_HANDLE handle, int32_t* exitCodeOut);
|
|
KSTATUS SysOpenProcess(uint32_t pid, SYS_RIGHTS desiredAccess, SYS_HANDLE* handleOut);
|
|
// Protected kernel processes remain openable for query and wait operations,
|
|
// but SysKillProcess returns NTLSTATUS_ACCESS_DENIED for them.
|
|
KSTATUS SysKillProcess(SYS_HANDLE processHandle, int32_t exitCode);
|
|
|
|
#define SYS_PROCESS_NAME_MAX 64u
|
|
|
|
#define SYS_PROCESS_STATE_RUNNING 0u
|
|
#define SYS_PROCESS_STATE_TERMINATING 1u
|
|
#define SYS_PROCESS_STATE_EXITED 2u
|
|
#define SYS_PROCESS_STATE_CONSTRUCTING 3u
|
|
|
|
#define SYS_PROCESS_FLAG_SYSTEM 0x00000001u
|
|
#define SYS_PROCESS_FLAG_CURRENT 0x00000002u
|
|
#define SYS_PROCESS_FLAG_TERMINATING 0x00000004u
|
|
#define SYS_PROCESS_FLAG_EXITED 0x00000008u
|
|
#define SYS_PROCESS_FLAG_IDLE 0x00000010u
|
|
#define SYS_PROCESS_FLAG_TERMINATION_PROTECTED 0x00000020u
|
|
#define SYS_PROCESS_FLAG_CONSTRUCTING 0x00000040u
|
|
|
|
#define SYS_THREAD_STATE_READY 0u
|
|
#define SYS_THREAD_STATE_RUNNING 1u
|
|
#define SYS_THREAD_STATE_WAITING 2u
|
|
#define SYS_THREAD_STATE_DEAD 3u
|
|
#define SYS_THREAD_STATE_SUSPENDED 4u
|
|
|
|
#define SYS_SCHEDULING_NORMAL 0u
|
|
#define SYS_SCHEDULING_REALTIME 1u
|
|
|
|
#define SYS_THREAD_FLAG_CURRENT 0x00000001u
|
|
#define SYS_THREAD_FLAG_IDLE 0x00000002u
|
|
#define SYS_THREAD_FLAG_KERNEL 0x00000004u
|
|
#define SYS_THREAD_FLAG_QUEUED 0x00000008u
|
|
#define SYS_THREAD_FLAG_ALERTABLE_WAIT 0x00000010u
|
|
#define SYS_THREAD_FLAG_KERNEL_APC_PENDING 0x00000020u
|
|
#define SYS_THREAD_FLAG_USER_APC_PENDING 0x00000040u
|
|
|
|
#define SYS_THREAD_WAIT_NONE 0u
|
|
#define SYS_THREAD_WAIT_PROCESS 1u
|
|
#define SYS_THREAD_WAIT_THREAD 2u
|
|
#define SYS_THREAD_WAIT_MUTEX 3u
|
|
#define SYS_THREAD_WAIT_SEMAPHORE 4u
|
|
#define SYS_THREAD_WAIT_EVENT 5u
|
|
#define SYS_THREAD_WAIT_QUEUE 6u
|
|
#define SYS_THREAD_WAIT_FILE 7u
|
|
#define SYS_THREAD_WAIT_DIR 8u
|
|
#define SYS_THREAD_WAIT_ASYNC_IO 9u
|
|
#define SYS_THREAD_WAIT_SOCKET 10u
|
|
#define SYS_THREAD_WAIT_DEVICE 11u
|
|
#define SYS_THREAD_WAIT_DRIVER 12u
|
|
#define SYS_THREAD_WAIT_USB_DEVICE 13u
|
|
#define SYS_THREAD_WAIT_USB_PIPE 14u
|
|
#define SYS_THREAD_WAIT_FILE_MAPPING 15u
|
|
#define SYS_THREAD_WAIT_SURFACE 16u
|
|
#define SYS_THREAD_WAIT_TIMER 17u
|
|
#define SYS_THREAD_WAIT_DISPLAY_CLOCK 18u
|
|
#define SYS_THREAD_WAIT_PIPE 19u
|
|
#define SYS_THREAD_WAIT_UNKNOWN 0xffffffffu
|
|
|
|
#define SYS_THREAD_NAME_MAX NTL_THREAD_NAME_MAX
|
|
|
|
typedef struct SYS_THREAD_INFO {
|
|
uint32_t Size;
|
|
uint32_t ProcessId;
|
|
uint32_t ThreadId;
|
|
uint32_t State;
|
|
|
|
uint32_t BaseSchedulingClass;
|
|
uint32_t BasePriority;
|
|
uint32_t EffectiveSchedulingClass;
|
|
uint32_t EffectivePriority;
|
|
|
|
uint32_t Flags;
|
|
uint32_t RunningCpu;
|
|
uint32_t LastCpu;
|
|
|
|
uint32_t QuantumRemaining;
|
|
uint32_t QuantumTicks;
|
|
uint32_t CpuBurstTicks;
|
|
uint32_t LastRunTicks;
|
|
|
|
uint32_t WaitObjectType;
|
|
uint32_t WaitStatus;
|
|
uint32_t KernelApcDisable;
|
|
|
|
char Name[SYS_THREAD_NAME_MAX];
|
|
} SYS_THREAD_INFO;
|
|
|
|
// Sets one thread description. ThreadHandle == SYS_HANDLE_INVALID targets the
|
|
// calling thread. Name may be empty to clear the description.
|
|
typedef struct SYS_SET_THREAD_NAME_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE ThreadHandle;
|
|
SYS_STRING_VIEW Name;
|
|
} SYS_SET_THREAD_NAME_REQUEST;
|
|
|
|
typedef struct SYS_PROCESS_INFO {
|
|
uint32_t Size;
|
|
uint32_t ProcessId;
|
|
uint32_t SecurityId;
|
|
uint32_t State;
|
|
uint32_t Flags;
|
|
|
|
uint32_t ThreadCount;
|
|
uint32_t HandleCount;
|
|
int32_t ExitCode;
|
|
|
|
uintptr_t ImageBase;
|
|
size_t ImageSize;
|
|
uintptr_t PebBase;
|
|
|
|
size_t VadCount;
|
|
size_t UserReservedBytes;
|
|
size_t UserCommittedBytes;
|
|
|
|
uint64_t ExceptionDelivered;
|
|
uint64_t ExceptionUserRaised;
|
|
uint64_t ExceptionContinued;
|
|
uint64_t ExceptionUnhandled;
|
|
uint64_t ExceptionInvalidContinue;
|
|
uint32_t ExceptionMaxNestedDispatch;
|
|
uint32_t LastExceptionCode;
|
|
uintptr_t LastExceptionAddress;
|
|
uintptr_t LastExceptionFaultAddress;
|
|
|
|
char Name[SYS_PROCESS_NAME_MAX];
|
|
} SYS_PROCESS_INFO;
|
|
|
|
KSTATUS SysGetProcessList(SYS_PROCESS_INFO* processesOut, size_t maxCount, size_t* countOut);
|
|
KSTATUS SysGetProcessPid(SYS_HANDLE handle, uint32_t* pidOut);
|
|
KSTATUS SysGetThreadList(uint32_t pid, SYS_THREAD_INFO* threadsOut, size_t maxCount, size_t* countOut);
|
|
KSTATUS SysGetThreadTid(SYS_HANDLE handle, uint32_t* tidOut);
|
|
|
|
KSTATUS SysCreateThread(const SYS_CREATE_THREAD_REQUEST* request);
|
|
KSTATUS SysOpenCurrentThread(SYS_RIGHTS desiredAccess, SYS_HANDLE* handleOut);
|
|
KSTATUS SysResumeThread(SYS_HANDLE threadHandle, uint32_t* previousSuspendCountOut);
|
|
KSTATUS SysResumeThreadAndWait(SYS_HANDLE threadHandle, uint32_t* previousSuspendCountOut);
|
|
uint32_t SysGetCurrentTid(void);
|
|
uint32_t SysGetCurrentPid(void);
|
|
KSTATUS SysSetThreadPriority(uint32_t priority);
|
|
KSTATUS SysSetThreadName(const SYS_SET_THREAD_NAME_REQUEST* request);
|
|
KSTATUS SysQueryThreadName(SYS_HANDLE threadHandle, char* buffer, size_t bufferSize, size_t* lengthOut);
|
|
KSTATUS SysYield(void);
|
|
|
|
#define SYS_TIMER_FLAG_NONE 0u
|
|
|
|
// Timer deadlines are relative millisecond delays. A zero due time makes the
|
|
// timer signaled immediately; a zero period makes it one-shot. Setting an
|
|
// already-set timer replaces the previous deadline and clears stale signal
|
|
// state before applying the new schedule.
|
|
typedef struct SYS_SET_TIMER_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE TimerHandle;
|
|
uint32_t Flags;
|
|
uint64_t DueTimeMilliseconds;
|
|
uint64_t PeriodMilliseconds;
|
|
} SYS_SET_TIMER_REQUEST;
|
|
|
|
KSTATUS SysCreateTimer(SYS_HANDLE* handleOut);
|
|
KSTATUS SysSetTimer(const SYS_SET_TIMER_REQUEST* request);
|
|
KSTATUS SysCancelTimer(SYS_HANDLE timerHandle);
|
|
|
|
// SysSleep blocks the current thread through the same timer backend used by
|
|
// waitable timer handles. A zero-length sleep yields the processor.
|
|
KSTATUS SysSleep(uint64_t ms);
|
|
KSTATUS SysSetUserApcDispatcher(void* dispatcher);
|
|
KSTATUS SysQueueUserApc(const SYS_QUEUE_USER_APC_REQUEST* request);
|
|
|
|
// Returns from the active user APC dispatcher. The frame pointer must identify
|
|
// the kernel-issued frame for the current delivery; it is not a general resume
|
|
// or context-switch syscall.
|
|
KSTATUS SysApcReturn(const SYS_USER_APC_FRAME* frame);
|
|
|
|
// Registers or queries the native user-mode exception dispatcher. Actual fault
|
|
// delivery, validated continuation, and user-raised exceptions are later cuts.
|
|
KSTATUS SysSetExceptionDispatcher(const SYS_EXCEPTION_DISPATCHER_REQUEST* request);
|
|
KSTATUS SysGetExceptionDispatcher(SYS_EXCEPTION_DISPATCHER_REQUEST* request);
|
|
KSTATUS SysContinueException(const SYS_CONTINUE_EXCEPTION_REQUEST* request);
|
|
KSTATUS SysRaiseException(const SYS_RAISE_EXCEPTION_REQUEST* request);
|
|
|
|
// Virtual memory and handles.
|
|
typedef enum SYS_VM_PROTECTION {
|
|
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_VM_PROTECTION;
|
|
|
|
#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;
|
|
|
|
typedef struct SYS_ALLOC_VM_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Protect;
|
|
uint32_t Flags;
|
|
uint32_t Reserved;
|
|
void* PreferredBase;
|
|
size_t PageCount;
|
|
void** BaseOut;
|
|
} SYS_ALLOC_VM_REQUEST;
|
|
|
|
KSTATUS SysAllocVm(const SYS_ALLOC_VM_REQUEST* request);
|
|
KSTATUS SysFreeVm(void* base);
|
|
KSTATUS SysProtectVm(void* base, size_t pageCount, uint32_t protect, uint32_t* oldProtectOut);
|
|
KSTATUS SysQueryVm(void* address, SYS_VM_REGION_INFO* out);
|
|
|
|
#define SYS_MAP_ACCESS_READ 0x00000001u
|
|
#define SYS_MAP_ACCESS_WRITE 0x00000002u
|
|
#define SYS_MAP_ACCESS_COPY 0x00000004u
|
|
#define SYS_MAP_ACCESS_EXECUTE 0x00000008u
|
|
#define SYS_MAP_FLAG_NONE 0x00000000u
|
|
|
|
typedef struct SYS_CREATE_FILE_MAPPING_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE FileHandle;
|
|
uint32_t Protect;
|
|
uint32_t Flags;
|
|
uint64_t MaximumSize;
|
|
SYS_HANDLE* MappingHandleOut;
|
|
} SYS_CREATE_FILE_MAPPING_REQUEST;
|
|
|
|
typedef struct SYS_MAP_FILE_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE MappingHandle;
|
|
uint32_t Access;
|
|
uint32_t Flags;
|
|
uint64_t Offset;
|
|
size_t Length;
|
|
void** BaseOut;
|
|
} SYS_MAP_FILE_REQUEST;
|
|
|
|
KSTATUS SysCreateFileMapping(const SYS_CREATE_FILE_MAPPING_REQUEST* request);
|
|
KSTATUS SysMapFile(const SYS_MAP_FILE_REQUEST* request);
|
|
KSTATUS SysCloseHandle(SYS_HANDLE handle);
|
|
|
|
#define SYS_DUPLICATE_HANDLE_FLAG_NONE 0x00000000u
|
|
#define SYS_DUPLICATE_HANDLE_FLAG_SAME_RIGHTS 0x00000001u
|
|
|
|
typedef struct SYS_DUPLICATE_HANDLE_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE SourceHandle;
|
|
SYS_HANDLE TargetProcessHandle;
|
|
SYS_RIGHTS DesiredRights;
|
|
uint32_t Flags;
|
|
SYS_HANDLE* TargetHandleOut;
|
|
} SYS_DUPLICATE_HANDLE_REQUEST;
|
|
|
|
// Duplicate creates another handle to the same revocation grant. DesiredRights
|
|
// may attenuate the alias but can never exceed the source handle's rights.
|
|
// Cross-process duplication also requires transfer authority on the source.
|
|
KSTATUS SysDuplicateHandle(const SYS_DUPLICATE_HANDLE_REQUEST* request);
|
|
|
|
typedef struct SYS_DERIVE_HANDLE_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE SourceHandle;
|
|
SYS_RIGHTS DesiredRights;
|
|
SYS_HANDLE* DerivedHandleOut;
|
|
} SYS_DERIVE_HANDLE_REQUEST;
|
|
|
|
// Derive creates a child grant. Revoking that child invalidates its aliases and
|
|
// descendants without revoking the parent grant.
|
|
KSTATUS SysDeriveHandle(const SYS_DERIVE_HANDLE_REQUEST* request);
|
|
// Revoke invalidates the selected grant, every alias of it, and all descendants.
|
|
KSTATUS SysRevokeHandle(SYS_HANDLE handle);
|
|
|
|
KSTATUS SysCreateMutex(SYS_HANDLE* handleOut);
|
|
KSTATUS SysTryAcquireMutex(SYS_HANDLE handle);
|
|
KSTATUS SysReleaseMutex(SYS_HANDLE handle);
|
|
|
|
KSTATUS SysCreateSem(int32_t initial, int32_t max, SYS_HANDLE* handleOut);
|
|
KSTATUS SysTryWaitSem(SYS_HANDLE handle);
|
|
KSTATUS SysSignalSem(SYS_HANDLE handle);
|
|
|
|
KSTATUS SysCreateEvent(uint32_t type, uint32_t initialState, SYS_HANDLE* handleOut);
|
|
KSTATUS SysSignalEvent(SYS_HANDLE handle);
|
|
KSTATUS SysClearEvent(SYS_HANDLE handle);
|
|
|
|
KSTATUS SysCreateQueue(SYS_HANDLE* handleOut);
|
|
KSTATUS SysSendQueue(const SYS_QUEUE_SEND_REQUEST* request);
|
|
KSTATUS SysRecvQueue(const SYS_QUEUE_RECV_REQUEST* request);
|
|
|
|
KSTATUS SysCreatePort(const SYS_CREATE_PORT_REQUEST* request);
|
|
KSTATUS SysConnectPort(const SYS_CONNECT_PORT_REQUEST* request);
|
|
KSTATUS SysAcceptPort(const SYS_ACCEPT_PORT_REQUEST* request);
|
|
KSTATUS SysSendPort(const SYS_SEND_PORT_REQUEST* request);
|
|
KSTATUS SysReceivePort(const SYS_RECEIVE_PORT_REQUEST* request);
|
|
KSTATUS SysCallPort(const SYS_CALL_PORT_REQUEST* request);
|
|
KSTATUS SysReplyPort(const SYS_REPLY_PORT_REQUEST* request);
|
|
KSTATUS SysDisconnectPort(SYS_HANDLE endpointHandle);
|
|
KSTATUS SysOpenPortPeerProcess(SYS_HANDLE endpointHandle, SYS_RIGHTS desiredRights,
|
|
SYS_HANDLE* processHandleOut);
|
|
// The registration capability selects one numeric registry key and authorizes publication.
|
|
KSTATUS SysRegisterSystemService(SYS_HANDLE registrationHandle, SYS_HANDLE listenerHandle);
|
|
KSTATUS SysUnregisterSystemService(SYS_HANDLE registrationHandle, SYS_HANDLE listenerHandle);
|
|
KSTATUS SysConnectSystemService(const SYS_CONNECT_SYSTEM_SERVICE_REQUEST* request);
|
|
|
|
KSTATUS SysQueryVolumes(const SYS_QUERY_VOLUMES_REQUEST* request);
|
|
KSTATUS SysOpenVolume(SYS_HANDLE managerHandle, uint32_t instanceId, SYS_RIGHTS desiredRights, SYS_HANDLE* volumeHandleOut);
|
|
KSTATUS SysWaitVolumeChange(SYS_HANDLE managerHandle, uint64_t observedGeneration, uint64_t timeoutMilliseconds);
|
|
|
|
KSTATUS SysOpenFileAt(const SYS_OPEN_FILE_AT_REQUEST* request);
|
|
KSTATUS SysOpenDirAt(const SYS_OPEN_DIR_AT_REQUEST* request);
|
|
KSTATUS SysStatAt(const SYS_STAT_AT_REQUEST* request);
|
|
KSTATUS SysDeleteAt(const SYS_PATH_AT_REQUEST* request);
|
|
KSTATUS SysRenameAt(const SYS_RENAME_AT_REQUEST* request);
|
|
KSTATUS SysCreateDirAt(const SYS_PATH_AT_REQUEST* request);
|
|
KSTATUS SysRemoveDirAt(const SYS_PATH_AT_REQUEST* request);
|
|
KSTATUS SysReadFile(const SYS_FILE_IO_REQUEST* request);
|
|
KSTATUS SysWriteFile(const SYS_FILE_IO_REQUEST* request);
|
|
KSTATUS SysReadFileAsync(const SYS_ASYNC_FILE_REQUEST* request);
|
|
KSTATUS SysWriteFileAsync(const SYS_ASYNC_FILE_REQUEST* request);
|
|
KSTATUS SysCancelIo(SYS_HANDLE asyncRequestHandle);
|
|
KSTATUS SysSeekFile(SYS_HANDLE handle, uint64_t offset);
|
|
KSTATUS SysGetFilePos(SYS_HANDLE handle, uint64_t* positionOut);
|
|
KSTATUS SysGetFileSize(SYS_HANDLE handle, uint64_t* sizeOut);
|
|
KSTATUS SysGetFileStat(SYS_HANDLE handle, SYS_FILE_STAT* statOut);
|
|
KSTATUS SysTruncateFile(SYS_HANDLE handle, uint64_t newSize);
|
|
KSTATUS SysFlushFile(SYS_HANDLE handle);
|
|
KSTATUS SysLockFile(const SYS_LOCK_FILE_REQUEST* request);
|
|
KSTATUS SysUnlockFile(const SYS_UNLOCK_FILE_REQUEST* request);
|
|
KSTATUS SysQueryFileLock(const SYS_QUERY_FILE_LOCK_REQUEST* request);
|
|
KSTATUS SysSetFileStatus(const SYS_SET_FILE_STATUS_REQUEST* request);
|
|
KSTATUS SysCreatePipe(const SYS_CREATE_PIPE_REQUEST* request);
|
|
KSTATUS SysNotifyPipe(SYS_HANDLE pipeHandle);
|
|
|
|
KSTATUS SysReadDir(SYS_HANDLE handle, SYS_DIR_ENTRY* entryOut);
|
|
|
|
// 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;
|
|
|
|
KSTATUS SysWriteConsole(const SYS_WRITE_CONSOLE_REQUEST* request);
|
|
KSTATUS SysGetConsoleInfo(SYS_CONSOLE_INFO* infoOut);
|
|
KSTATUS SysSetConsoleCursor(int32_t x, int32_t y);
|
|
|
|
typedef struct SYS_FILL_CONSOLE_CHARACTER_REQUEST {
|
|
uint32_t Size;
|
|
char Character;
|
|
uint8_t Reserved[3];
|
|
int32_t X;
|
|
int32_t Y;
|
|
size_t Length;
|
|
size_t* WrittenOut;
|
|
} SYS_FILL_CONSOLE_CHARACTER_REQUEST;
|
|
|
|
typedef struct SYS_FILL_CONSOLE_ATTRIBUTE_REQUEST {
|
|
uint32_t Size;
|
|
uint16_t Attribute;
|
|
uint16_t Reserved;
|
|
int32_t X;
|
|
int32_t Y;
|
|
size_t Length;
|
|
size_t* WrittenOut;
|
|
} SYS_FILL_CONSOLE_ATTRIBUTE_REQUEST;
|
|
|
|
typedef struct SYS_PUT_SCREEN_CHAR_REQUEST {
|
|
uint32_t Size;
|
|
char Character;
|
|
uint8_t Reserved[3];
|
|
int32_t X;
|
|
int32_t Y;
|
|
uint32_t Foreground;
|
|
uint32_t Background;
|
|
} SYS_PUT_SCREEN_CHAR_REQUEST;
|
|
|
|
KSTATUS SysFillConsoleCharacter(const SYS_FILL_CONSOLE_CHARACTER_REQUEST* request);
|
|
KSTATUS SysFillConsoleAttribute(const SYS_FILL_CONSOLE_ATTRIBUTE_REQUEST* request);
|
|
KSTATUS SysPutScreenChar(const SYS_PUT_SCREEN_CHAR_REQUEST* request);
|
|
|
|
typedef struct SYS_CREATE_SURFACE_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Width;
|
|
uint32_t Height;
|
|
uint32_t Format;
|
|
uint32_t Flags;
|
|
SYS_HANDLE* HandleOut;
|
|
} SYS_CREATE_SURFACE_REQUEST;
|
|
|
|
KSTATUS SysCreateSurface(const SYS_CREATE_SURFACE_REQUEST* request);
|
|
KSTATUS SysMapSurface(SYS_HANDLE surfaceHandle, uint32_t flags, void** baseOut, uint32_t* pitchBytesOut);
|
|
KSTATUS SysUnmapSurface(void* base);
|
|
KSTATUS SysQuerySurface(SYS_HANDLE surfaceHandle, SYS_SURFACE_DESC* descOut);
|
|
KSTATUS SysCommitSurface(SYS_HANDLE surfaceHandle, const DISPLAY_RECT* rects, uint32_t rectCount, uint64_t* generationOut);
|
|
KSTATUS SysClearScreen(uint32_t color);
|
|
KSTATUS SysGetScreenSize(int32_t* widthOut, int32_t* heightOut);
|
|
KSTATUS SysQueryDisplayInfo(SYS_DISPLAY_INFO* infoOut);
|
|
|
|
#define SYS_DISPLAY_MANAGER_CURSOR_FLAG_NONE 0x00000000u
|
|
#define SYS_DISPLAY_MANAGER_CURSOR_FLAG_SHOW 0x00000001u
|
|
#define SYS_DISPLAY_MANAGER_CURSOR_FLAG_HIDE 0x00000002u
|
|
|
|
typedef struct SYS_DISPLAY_MANAGER_CURSOR_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE ManagerHandle;
|
|
uint32_t Flags;
|
|
int32_t X;
|
|
int32_t Y;
|
|
} SYS_DISPLAY_MANAGER_CURSOR_REQUEST;
|
|
|
|
// Capability-scoped display operations used by the native resource plane.
|
|
KSTATUS SysQueryDisplayManagerInfo(SYS_HANDLE managerHandle, SYS_DISPLAY_INFO* infoOut);
|
|
KSTATUS SysSetDisplayManagerCursor(const SYS_DISPLAY_MANAGER_CURSOR_REQUEST* request);
|
|
KSTATUS SysPresentDisplayManagerSurface(SYS_HANDLE managerHandle, SYS_HANDLE surfaceHandle,
|
|
const DISPLAY_RECT* rects, uint32_t rectCount);
|
|
KSTATUS SysWriteDisplayManagerConsole(SYS_HANDLE managerHandle, const SYS_WRITE_CONSOLE_REQUEST* request);
|
|
KSTATUS SysQueryDisplayManagerConsoleInfo(SYS_HANDLE managerHandle, SYS_CONSOLE_INFO* infoOut);
|
|
KSTATUS SysSetDisplayManagerConsoleCursor(SYS_HANDLE managerHandle, int32_t x, int32_t y);
|
|
KSTATUS SysFillDisplayManagerConsoleCharacter(SYS_HANDLE managerHandle, const SYS_FILL_CONSOLE_CHARACTER_REQUEST* request);
|
|
KSTATUS SysFillDisplayManagerConsoleAttribute(SYS_HANDLE managerHandle, const SYS_FILL_CONSOLE_ATTRIBUTE_REQUEST* request);
|
|
KSTATUS SysPutDisplayManagerConsoleCharacter(SYS_HANDLE managerHandle, const SYS_PUT_SCREEN_CHAR_REQUEST* request);
|
|
KSTATUS SysClearDisplayManagerConsole(SYS_HANDLE managerHandle, uint32_t color);
|
|
|
|
// Display clocks are waitable pacing objects. Providers with frame-event
|
|
// support signal them once per submitted frame. Other providers use the boot processor
|
|
// scheduler tick, with PeriodMilliseconds rounded up to one or more ticks.
|
|
#define SYS_DISPLAY_CLOCK_FLAG_NONE 0u
|
|
#define SYS_DISPLAY_CLOCK_DEFAULT_PERIOD_MS 1ull
|
|
|
|
typedef struct SYS_OPEN_DISPLAY_CLOCK_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Flags;
|
|
uint64_t PeriodMilliseconds;
|
|
SYS_HANDLE* HandleOut;
|
|
} SYS_OPEN_DISPLAY_CLOCK_REQUEST;
|
|
|
|
KSTATUS SysOpenDisplayClock(const SYS_OPEN_DISPLAY_CLOCK_REQUEST* request);
|
|
|
|
// Input.
|
|
#define SYS_INPUT_MANAGER_EVENT_FLAG_NONE 0x00000000u
|
|
#define SYS_INPUT_MANAGER_EVENT_KEY 1u
|
|
#define SYS_INPUT_MANAGER_EVENT_MOUSE 2u
|
|
|
|
typedef struct SYS_INPUT_MANAGER_EVENT {
|
|
uint32_t Size;
|
|
uint32_t Type;
|
|
uint64_t Sequence;
|
|
union {
|
|
INPUT_KEY_EVENT Key;
|
|
INPUT_MOUSE_EVENT Mouse;
|
|
} Data;
|
|
} SYS_INPUT_MANAGER_EVENT;
|
|
|
|
typedef struct SYS_INPUT_MANAGER_READ_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE ManagerHandle;
|
|
uint32_t Flags;
|
|
uint64_t TimeoutMilliseconds;
|
|
SYS_INPUT_MANAGER_EVENT* EventOut;
|
|
} SYS_INPUT_MANAGER_READ_REQUEST;
|
|
|
|
// Reads the next normalized physical input event through an input-manager capability.
|
|
KSTATUS SysReadInputManagerEvent(const SYS_INPUT_MANAGER_READ_REQUEST* request);
|
|
|
|
// Native sockets.
|
|
#define SYS_AF_INET 2u
|
|
#define SYS_AF_INET6 10u
|
|
#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_IPPROTO_ICMPV6 58u
|
|
#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
|
|
|
|
#define SYS_SOCKET_ADDRESS_SIZE 28u
|
|
|
|
// Socket addresses are tagged native records with one fixed ABI size. The
|
|
// syscall pointer-length parameter is the user-buffer bound and must be exactly
|
|
// SYS_SOCKET_ADDRESS_SIZE for input addresses; Size must also equal
|
|
// SYS_SOCKET_ADDRESS_SIZE after the kernel copies the fixed record. The macro is
|
|
// only the compile-time ABI constant. Address stores textual-order bytes
|
|
// (for example, 127,0,0,1), not an integer requiring byte-order conversion. Port
|
|
// is host byte order.
|
|
typedef struct SYS_SOCKET_ADDRESS {
|
|
uint16_t Family;
|
|
uint16_t Size;
|
|
uint16_t Port;
|
|
uint8_t Address[16];
|
|
uint32_t ScopeId;
|
|
} SYS_SOCKET_ADDRESS;
|
|
|
|
typedef struct SYS_SOCKET_SEND_TO_REQUEST {
|
|
uint32_t Size;
|
|
const void* Buffer;
|
|
size_t Length;
|
|
uint32_t Flags;
|
|
const SYS_SOCKET_ADDRESS* RemoteAddress;
|
|
size_t RemoteAddressSize;
|
|
size_t* SentOut;
|
|
} SYS_SOCKET_SEND_TO_REQUEST;
|
|
|
|
typedef struct SYS_SOCKET_RECV_FROM_REQUEST {
|
|
uint32_t Size;
|
|
void* Buffer;
|
|
size_t Length;
|
|
uint32_t Flags;
|
|
SYS_SOCKET_ADDRESS* RemoteAddressOut;
|
|
size_t* RemoteAddressSizeInOut;
|
|
size_t* ReceivedOut;
|
|
} SYS_SOCKET_RECV_FROM_REQUEST;
|
|
|
|
typedef struct SYS_RESOLVE_HOST_REQUEST {
|
|
uint32_t Size;
|
|
SYS_STRING_VIEW Name;
|
|
uint32_t Family;
|
|
uint32_t Flags;
|
|
SYS_SOCKET_ADDRESS* AddressOut;
|
|
size_t* AddressSizeInOut;
|
|
} SYS_RESOLVE_HOST_REQUEST;
|
|
|
|
typedef struct SYS_SOCKET_OPTION_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t Option;
|
|
void* Value;
|
|
size_t ValueSize;
|
|
size_t* ActualSizeOut;
|
|
} SYS_SOCKET_OPTION_REQUEST;
|
|
|
|
typedef struct SYS_POLLFD {
|
|
SYS_HANDLE Handle;
|
|
uint32_t Events;
|
|
uint32_t ReturnedEvents;
|
|
} SYS_POLLFD;
|
|
|
|
typedef struct SYS_POLL_REQUEST {
|
|
uint32_t Size;
|
|
uint32_t TimeoutMs;
|
|
SYS_POLLFD* Fds;
|
|
size_t Count;
|
|
size_t* ReadyOut;
|
|
} SYS_POLL_REQUEST;
|
|
|
|
#define SYS_ASYNC_SOCKET_FLAG_NONE 0x00000000u
|
|
|
|
#define SYS_ASYNC_SOCKET_OP_BIND 1u
|
|
#define SYS_ASYNC_SOCKET_OP_LISTEN 2u
|
|
#define SYS_ASYNC_SOCKET_OP_ACCEPT 3u
|
|
#define SYS_ASYNC_SOCKET_OP_CONNECT 4u
|
|
#define SYS_ASYNC_SOCKET_OP_SEND 5u
|
|
#define SYS_ASYNC_SOCKET_OP_RECV 6u
|
|
#define SYS_ASYNC_SOCKET_OP_SEND_TO 7u
|
|
#define SYS_ASYNC_SOCKET_OP_RECV_FROM 8u
|
|
#define SYS_ASYNC_SOCKET_OP_SHUTDOWN 9u
|
|
#define SYS_ASYNC_SOCKET_OP_SET_OPT 10u
|
|
#define SYS_ASYNC_SOCKET_OP_GET_OPT 11u
|
|
#define SYS_ASYNC_SOCKET_OP_POLL 12u
|
|
|
|
// Async socket requests return operation-specific byte counts through Iosb.
|
|
// Information is the byte count for send/receive, the accepted handle for
|
|
// accept, returned poll events for poll, and the actual option byte count for
|
|
// get-option. RequestHandleOut receives a waitable/cancellable async I/O handle
|
|
// when the request is queued. A zero handle means the operation failed before
|
|
// queueing.
|
|
typedef struct SYS_ASYNC_SOCKET_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE SocketHandle;
|
|
SYS_HANDLE EventHandle;
|
|
uint32_t Operation;
|
|
uint32_t Flags;
|
|
uint32_t SocketFlags;
|
|
uint32_t Backlog;
|
|
uint32_t ShutdownHow;
|
|
uint32_t Option;
|
|
uint32_t PollEvents;
|
|
|
|
void* Buffer;
|
|
size_t Length;
|
|
|
|
const SYS_SOCKET_ADDRESS* Address;
|
|
size_t AddressSize;
|
|
SYS_SOCKET_ADDRESS* AddressOut;
|
|
size_t* AddressSizeInOut;
|
|
|
|
void* OptionValue;
|
|
size_t OptionValueSize;
|
|
size_t* OptionActualSizeOut;
|
|
|
|
SYS_HANDLE* HandleOut;
|
|
uint32_t* PollReturnedEventsOut;
|
|
|
|
SYS_IO_STATUS_BLOCK* Iosb;
|
|
SYS_USER_APC_ROUTINE ApcRoutine;
|
|
void* ApcContext;
|
|
SYS_HANDLE* RequestHandleOut;
|
|
} SYS_ASYNC_SOCKET_REQUEST;
|
|
|
|
KSTATUS SysCreateSocket(uint32_t domain, uint32_t type, uint32_t protocol, SYS_HANDLE* handleOut);
|
|
KSTATUS SysBindSocket(SYS_HANDLE socket, const SYS_SOCKET_ADDRESS* address, size_t addressSize);
|
|
KSTATUS SysListenSocket(SYS_HANDLE socket, uint32_t backlog);
|
|
KSTATUS SysAcceptSocket(SYS_HANDLE socket, SYS_SOCKET_ADDRESS* remoteAddressOut, size_t* remoteAddressSizeInOut, SYS_HANDLE* acceptedHandleOut);
|
|
KSTATUS SysConnectSocket(SYS_HANDLE socket, const SYS_SOCKET_ADDRESS* address, size_t addressSize);
|
|
|
|
typedef struct SYS_SOCKET_SEND_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE Socket;
|
|
uint32_t Flags;
|
|
const void* Buffer;
|
|
size_t Length;
|
|
size_t* SentOut;
|
|
} SYS_SOCKET_SEND_REQUEST;
|
|
|
|
typedef struct SYS_SOCKET_RECV_REQUEST {
|
|
uint32_t Size;
|
|
SYS_HANDLE Socket;
|
|
uint32_t Flags;
|
|
void* Buffer;
|
|
size_t Length;
|
|
size_t* ReceivedOut;
|
|
} SYS_SOCKET_RECV_REQUEST;
|
|
|
|
KSTATUS SysSendSocket(const SYS_SOCKET_SEND_REQUEST* request);
|
|
KSTATUS SysRecvSocket(const SYS_SOCKET_RECV_REQUEST* request);
|
|
KSTATUS SysShutdownSocket(SYS_HANDLE socket, uint32_t how);
|
|
KSTATUS SysSendToSocket(SYS_HANDLE socket, const SYS_SOCKET_SEND_TO_REQUEST* request);
|
|
KSTATUS SysRecvFromSocket(SYS_HANDLE socket, const SYS_SOCKET_RECV_FROM_REQUEST* request);
|
|
KSTATUS SysResolveHost(const SYS_RESOLVE_HOST_REQUEST* request); // Cry about it.
|
|
KSTATUS SysSetSocketOption(SYS_HANDLE socket, const SYS_SOCKET_OPTION_REQUEST* request);
|
|
KSTATUS SysGetSocketOption(SYS_HANDLE socket, const SYS_SOCKET_OPTION_REQUEST* request);
|
|
KSTATUS SysPoll(const SYS_POLL_REQUEST* request);
|
|
KSTATUS SysSocketIoAsync(const SYS_ASYNC_SOCKET_REQUEST* request);
|
|
|
|
typedef struct SYS_MEMORY_STATUS {
|
|
uint64_t FreePhysicalBytes;
|
|
uint64_t KernelPoolBytes;
|
|
uint64_t UserHeapBytes;
|
|
uint64_t ReclaimablePhysicalBytes;
|
|
uint64_t AvailablePhysicalBytes;
|
|
uint64_t PinnedPhysicalBytes;
|
|
uint64_t NonEvictablePhysicalBytes;
|
|
uint64_t UserPhysicalBytes;
|
|
uint64_t PageTablePhysicalBytes;
|
|
} 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_PFN 4u
|
|
#define SYS_KERNEL_STATS_PTE 5u
|
|
#define SYS_KERNEL_STATS_VAD 6u
|
|
#define SYS_KERNEL_STATS_SWAP 7u
|
|
#define SYS_KERNEL_STATS_FILE_CACHE 8u
|
|
#define SYS_KERNEL_STATS_SURFACE 9u
|
|
#define SYS_KERNEL_STATS_FILESYSTEM 10u
|
|
#define SYS_KERNEL_STATS_DISK 11u
|
|
#define SYS_KERNEL_STATS_NET_IRP 12u
|
|
#define SYS_KERNEL_STATS_EXCEPTION 13u
|
|
#define SYS_KERNEL_STATS_PORT 14u
|
|
#define SYS_KERNEL_STATS_VOLUME 15u
|
|
#define SYS_KERNEL_STATS_VOLUME_MANAGER 16u
|
|
|
|
// Public stats payloads start with Size and Version. Size is the byte count
|
|
// returned for that payload, including any trailing records. Version describes
|
|
// the field layout for fixed fields in the named payload.
|
|
#define SYS_STATS_VERSION 4u
|
|
|
|
|
|
typedef struct SYS_EXCEPTION_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t Delivered;
|
|
uint64_t UserRaised;
|
|
uint64_t Continued;
|
|
uint64_t Unhandled;
|
|
uint64_t InvalidContinue;
|
|
uint32_t MaxNestedDispatch;
|
|
uint32_t LastCode;
|
|
uintptr_t LastExceptionAddress;
|
|
uintptr_t LastFaultAddress;
|
|
} SYS_EXCEPTION_STATS;
|
|
|
|
typedef struct SYS_PORT_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t ConnectionsCreated;
|
|
uint64_t DirectDeliveries;
|
|
uint64_t DirectBytes;
|
|
uint64_t QueuedMessages;
|
|
uint64_t QueuedBytes;
|
|
uint64_t QueuedDeliveries;
|
|
uint64_t RepliesCompleted;
|
|
uint64_t Disconnects;
|
|
uint64_t ProcessQuotaRejects;
|
|
} SYS_PORT_STATS;
|
|
|
|
typedef struct SYS_SCHEDULER_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
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;
|
|
uint64_t RealtimeDispatches;
|
|
uint64_t RealtimePreemptions;
|
|
uint64_t PriorityInheritanceBoosts;
|
|
uint64_t PriorityInheritanceDrops;
|
|
uint64_t PriorityInheritancePropagations;
|
|
uint64_t PriorityInheritanceMaxDepth;
|
|
} SYS_SCHEDULER_STATS;
|
|
|
|
typedef struct SYS_PMM_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t TotalFrames;
|
|
uint64_t FreeFrames;
|
|
uint64_t UsedFrames;
|
|
uint64_t LargestFreeRun;
|
|
uint64_t FreeRunCount;
|
|
uint64_t FreeRunHistogram[8];
|
|
} SYS_PMM_STATS;
|
|
|
|
#define SYS_CPU_THREAD_FLAG_IDLE 0x00000001u
|
|
|
|
typedef struct SYS_CPU_STAT {
|
|
uint32_t CpuIndex;
|
|
uint32_t HardwareId;
|
|
uint32_t Flags;
|
|
uint32_t CurrentTid;
|
|
uint32_t CurrentThreadFlags;
|
|
uint64_t SchedulerTicks;
|
|
uint64_t ContextSwitches;
|
|
} SYS_CPU_STAT;
|
|
|
|
// CPU stats use trailing SYS_CPU_STAT records after the fixed header.
|
|
typedef struct SYS_CPU_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint32_t HeaderSize;
|
|
uint32_t CpuCount;
|
|
uint32_t RecordSize;
|
|
uint32_t RecordCount;
|
|
} SYS_CPU_STATS;
|
|
|
|
#define SYS_CPU_STATS_RECORDS(stats) ((SYS_CPU_STAT*)((uint8_t*)(stats) + sizeof(SYS_CPU_STATS)))
|
|
#define SYS_CPU_STATS_CONST_RECORDS(stats) ((const SYS_CPU_STAT*)((const uint8_t*)(stats) + sizeof(SYS_CPU_STATS)))
|
|
|
|
typedef struct SYS_PFN_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t TotalFrames;
|
|
uint64_t FreeFrames;
|
|
uint64_t UsedFrames;
|
|
|
|
uint64_t ReservedFrames;
|
|
uint64_t ZeroedFrames;
|
|
uint64_t ActiveFrames;
|
|
uint64_t StandbyFrames;
|
|
uint64_t ModifiedFrames;
|
|
uint64_t PinnedFrames;
|
|
uint64_t EvictableFrames;
|
|
uint64_t NonEvictableFrames;
|
|
uint64_t ReclaimableFrames;
|
|
uint64_t AvailableFrames;
|
|
uint64_t MappedFrames;
|
|
|
|
uint64_t KernelFrames;
|
|
uint64_t PageTableFrames;
|
|
uint64_t UserFrames;
|
|
uint64_t CleanFileCacheFrames;
|
|
uint64_t ActiveCleanFileCacheFrames;
|
|
uint64_t StandbyCleanFileCacheFrames;
|
|
uint64_t ImageFrames;
|
|
uint64_t ActiveImageFrames;
|
|
uint64_t StandbyImageFrames;
|
|
uint64_t MappedFileFrames;
|
|
uint64_t AnonymousFrames;
|
|
uint64_t CowFrames;
|
|
uint64_t SurfaceFrames;
|
|
uint64_t DriverFrames;
|
|
uint64_t DmaFrames;
|
|
uint64_t BootloaderFrames;
|
|
uint64_t PfnDatabaseFrames;
|
|
uint64_t MmioFrames;
|
|
|
|
uint64_t AllocationCount;
|
|
uint64_t FreeCount;
|
|
uint64_t RetainCount;
|
|
uint64_t ReleaseCount;
|
|
uint64_t PinCount;
|
|
uint64_t UnpinCount;
|
|
uint64_t FailedAllocations;
|
|
uint64_t FailedContiguousAllocations;
|
|
|
|
uint64_t FailedInvalidRange;
|
|
uint64_t FailedEmptyRange;
|
|
uint64_t FailedReserveDenied;
|
|
uint64_t FailedNoFrame;
|
|
|
|
uint64_t FailedContiguousInvalidRequest;
|
|
uint64_t FailedContiguousReserveDenied;
|
|
uint64_t FailedContiguousNoRun;
|
|
|
|
uint64_t ReclaimAttempts;
|
|
uint64_t ReclaimPagesRequested;
|
|
uint64_t ReclaimPagesSucceeded;
|
|
uint64_t ReclaimPagesFailed;
|
|
uint64_t ReclaimReentrantSkips;
|
|
} SYS_PFN_STATS;
|
|
|
|
typedef struct SYS_VAD_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t ResolveFaultCalls;
|
|
uint64_t ResolvedFaults;
|
|
uint64_t FailedFaults;
|
|
uint64_t ProtectionFaults;
|
|
uint64_t NoVadFaults;
|
|
uint64_t UncommittedFaults;
|
|
uint64_t NoAccessFaults;
|
|
uint64_t DemandZeroPages;
|
|
uint64_t ZeroPageMaps;
|
|
uint64_t ZeroPageCowSplits;
|
|
uint64_t CowFaults;
|
|
uint64_t CowPagesCopied;
|
|
uint64_t CowViewsCreated;
|
|
uint64_t CowPagesShared;
|
|
uint64_t EnsureResidentCalls;
|
|
uint64_t EnsureResidentPages;
|
|
uint64_t AlreadyResidentPages;
|
|
uint64_t FileBackedFaults;
|
|
uint64_t FileBackedReads;
|
|
uint64_t FileBackedReadFailures;
|
|
uint64_t FileBackedDiscards;
|
|
uint64_t FileBackedSharedWritableFaults;
|
|
uint64_t FileBackedDirtyFaults;
|
|
uint64_t FileBackedDirtySyncs;
|
|
uint64_t ImageBackedFaults;
|
|
uint64_t ImageBackedZeroFaults;
|
|
uint64_t ImageBackedPrivateFaults;
|
|
uint64_t ImageFixupPrivateCalls;
|
|
uint64_t ImageFixupPrivatePages;
|
|
uint64_t SwapPageOuts;
|
|
uint64_t SwapPageIns;
|
|
} SYS_VAD_STATS;
|
|
|
|
typedef struct SYS_FILE_CACHE_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t Lookups;
|
|
uint64_t Hits;
|
|
uint64_t Misses;
|
|
uint64_t Loads;
|
|
uint64_t LoadFailures;
|
|
uint64_t RaceDiscards;
|
|
uint64_t InflightWaits;
|
|
uint64_t Invalidations;
|
|
uint64_t DirtyPages;
|
|
uint64_t MaxDirtyPages;
|
|
uint64_t DirtyMarks;
|
|
uint64_t WritebackRequests;
|
|
uint64_t WritebackPages;
|
|
uint64_t WritebackBytes;
|
|
uint64_t WritebackFailures;
|
|
uint64_t FlushFileCalls;
|
|
uint64_t FlushFileFailures;
|
|
uint64_t MappedDirtySyncs;
|
|
uint64_t MappedDirtyPages;
|
|
uint64_t Drops;
|
|
uint64_t DropFailures;
|
|
uint64_t StandbyTransitions;
|
|
uint64_t StandbyHits;
|
|
uint64_t ResidentPages;
|
|
uint64_t ActivePages;
|
|
uint64_t StandbyPages;
|
|
uint64_t MaxResidentPages;
|
|
} SYS_FILE_CACHE_STATS;
|
|
|
|
// Filesystem stats are generic I/O/provider telemetry. Drivers should map
|
|
// private metadata work onto these counters instead of exposing filesystem-
|
|
// specific cache names through the public ABI.
|
|
typedef struct SYS_FILESYSTEM_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t PathLookups;
|
|
uint64_t PathCacheHits;
|
|
uint64_t PathCacheMisses;
|
|
uint64_t PathCacheStores;
|
|
uint64_t PathCacheInvalidations;
|
|
uint64_t PathCacheGeneration;
|
|
uint64_t DirectorySearches;
|
|
uint64_t DirectoryBlocksRead;
|
|
uint64_t DirectoryEntriesScanned;
|
|
uint64_t DataReadRuns;
|
|
uint64_t DataReadSectors;
|
|
uint64_t DataReadRunMerges;
|
|
uint64_t MaxDataReadSpanSectors;
|
|
} SYS_FILESYSTEM_STATS;
|
|
|
|
typedef struct SYS_VOLUME_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t CreatedVolumes;
|
|
uint64_t MountedVolumes;
|
|
uint64_t RemovedVolumes;
|
|
uint64_t DeadIoRejects;
|
|
uint64_t ProviderDestroys;
|
|
} SYS_VOLUME_STATS;
|
|
|
|
typedef struct SYS_VOLUME_MANAGER_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t Snapshots;
|
|
uint64_t VolumeOpens;
|
|
uint64_t Waits;
|
|
uint64_t Wakeups;
|
|
} SYS_VOLUME_MANAGER_STATS;
|
|
|
|
typedef struct SYS_DISK_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t RegisteredDisks;
|
|
uint64_t ReadRequests;
|
|
uint64_t ReadSectors;
|
|
uint64_t WriteRequests;
|
|
uint64_t WriteSectors;
|
|
uint64_t MaxReadSectors;
|
|
uint64_t MaxWriteSectors;
|
|
} SYS_DISK_STATS;
|
|
|
|
#define SYS_NET_IRP_OPERATION_COUNT 16u
|
|
#define SYS_NET_IRP_OP_INVALID 0u
|
|
#define SYS_NET_IRP_OP_CREATE 1u
|
|
#define SYS_NET_IRP_OP_CLOSE 2u
|
|
#define SYS_NET_IRP_OP_BIND 3u
|
|
#define SYS_NET_IRP_OP_LISTEN 4u
|
|
#define SYS_NET_IRP_OP_ACCEPT 5u
|
|
#define SYS_NET_IRP_OP_CONNECT 6u
|
|
#define SYS_NET_IRP_OP_SEND 7u
|
|
#define SYS_NET_IRP_OP_RECEIVE 8u
|
|
#define SYS_NET_IRP_OP_SEND_TO 9u
|
|
#define SYS_NET_IRP_OP_RECEIVE_FROM 10u
|
|
#define SYS_NET_IRP_OP_SHUTDOWN 11u
|
|
#define SYS_NET_IRP_OP_SET_OPTION 12u
|
|
#define SYS_NET_IRP_OP_GET_OPTION 13u
|
|
#define SYS_NET_IRP_OP_POLL 14u
|
|
#define SYS_NET_IRP_OP_RESOLVE_HOST 15u
|
|
|
|
typedef struct SYS_NET_IRP_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t Submitted;
|
|
uint64_t Completed;
|
|
uint64_t CompletedSynchronously;
|
|
uint64_t CompletedAsynchronously;
|
|
uint64_t Pending;
|
|
uint64_t CancelRequested;
|
|
uint64_t Cancelled;
|
|
uint64_t WouldBlock;
|
|
uint64_t Timeout;
|
|
uint64_t Failed;
|
|
uint64_t ByOperation[SYS_NET_IRP_OPERATION_COUNT];
|
|
} SYS_NET_IRP_STATS;
|
|
|
|
typedef struct SYS_SWAP_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
bool Enabled;
|
|
uint64_t TotalSlots;
|
|
uint64_t UsedSlots;
|
|
uint64_t FreeSlots;
|
|
uint64_t HighWaterSlots;
|
|
uint64_t PageOuts;
|
|
uint64_t PageIns;
|
|
uint64_t PageOutFailures;
|
|
uint64_t PageInFailures;
|
|
uint64_t SlotAllocations;
|
|
uint64_t SlotFrees;
|
|
uint64_t SlotAllocationFailures;
|
|
} SYS_SWAP_STATS;
|
|
|
|
#define SYS_PTE_QUERY_GENERIC 0u
|
|
#define SYS_PTE_QUERY_USER_PROBE 1u
|
|
#define SYS_PTE_QUERY_HEAP 2u
|
|
#define SYS_PTE_QUERY_VAD 3u
|
|
#define SYS_PTE_QUERY_DEBUG 4u
|
|
#define SYS_PTE_QUERY_SELF_TEST 5u
|
|
#define SYS_PTE_QUERY_PURPOSE_COUNT 6u
|
|
|
|
typedef struct SYS_PTE_STATS {
|
|
uint32_t Size;
|
|
uint32_t Version;
|
|
uint64_t MapCalls;
|
|
uint64_t MapFailures;
|
|
uint64_t UnmapCalls;
|
|
uint64_t UnmapFailures;
|
|
uint64_t ProtectCalls;
|
|
uint64_t ProtectFailures;
|
|
uint64_t QueryCalls;
|
|
uint64_t QueryFailures;
|
|
uint64_t QueryByPurpose[SYS_PTE_QUERY_PURPOSE_COUNT];
|
|
uint64_t QueryFailuresByPurpose[SYS_PTE_QUERY_PURPOSE_COUNT];
|
|
uint64_t TranslateCalls;
|
|
uint64_t LocalFlushes;
|
|
uint64_t GlobalFlushes;
|
|
uint64_t ShootdownRequests;
|
|
uint64_t ShootdownTargetCpus;
|
|
uint64_t ShootdownSkippedNoTargets;
|
|
uint64_t ShootdownAcks;
|
|
uint64_t ShootdownTimeouts;
|
|
uint64_t NewMappingNoFlushes;
|
|
uint64_t ReplacedMappingFlushes;
|
|
uint64_t PageTablePagesAllocated;
|
|
uint64_t CurrentLeafMappings;
|
|
} SYS_PTE_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_BOOT_PROCESSOR 0x00000010u
|
|
#define SYS_CPU_FLAG_PRIMARY 0x00000020u
|
|
|
|
// Time and diagnostics.
|
|
// SysGetTick returns monotonic ticks since boot. The tick unit is defined by
|
|
// SysGetTickFrequency and is not a wall-clock timestamp.
|
|
uint64_t SysGetTick(void);
|
|
|
|
// SysGetTickFrequency writes the number of SysGetTick ticks per second to frequencyOut.
|
|
KSTATUS SysGetTickFrequency(uint64_t* frequencyOut);
|
|
|
|
// Converts a tick delta to milliseconds using the supplied tick frequency.
|
|
static inline uint64_t SysTicksToMilliseconds(uint64_t ticks, uint64_t frequency) {
|
|
if (!frequency) return 0;
|
|
return (ticks / frequency) * 1000ull + ((ticks % frequency) * 1000ull) / frequency;
|
|
}
|
|
|
|
// Converts a tick delta to microseconds using the supplied tick frequency.
|
|
static inline uint64_t SysTicksToMicroseconds(uint64_t ticks, uint64_t frequency) {
|
|
if (!frequency) return 0;
|
|
return (ticks / frequency) * 1000000ull + ((ticks % frequency) * 1000000ull) / frequency;
|
|
}
|
|
|
|
KSTATUS SysPrintDebug(const SYS_PRINT_DEBUG_REQUEST* request);
|
|
KSTATUS SysQueryTrapFrame(SYS_TRAP_FRAME_INFO* info);
|
|
|
|
KSTATUS SysGetMemoryStatus(SYS_MEMORY_STATUS* statusOut);
|
|
KSTATUS SysQueryKernelStats(uint32_t classId, void* buffer, size_t bufferSize, size_t* requiredSizeOut);
|
|
KSTATUS SysGetSystemTime(SYS_SYSTEM_TIME* timeOut);
|