move POSIX spawn, exec and child tracking into posixsrv, keep process transactions alive across reconnects and preserve stable PIDs across image replacement, flesh out spawn with ordered file actions, process-group selection and signal inheritance, implement execve with bootstrap validation and rollback before retiring the old process, add vfork children that share the native process while keeping separate POSIX descriptor and signal state, replace local spawn bookkeeping with child reaping, nonblocking and process-group waits and orphan cleanup, add signal dispositions, per-thread masks, pending delivery, process/group signalling and alarms, translate native exceptions into POSIX signals and inherit masks when creating threads, make pipe waits interruptible and raise SIGPIPE for broken pipes, pass arguments and environment into main and add getenv/environ, add direct user APC notifications that can run without an alertable wait, add current-thread capabilities and resume-and-wait, let accepted IPC endpoints open restricted peer process capabilities and preserve caller security during spawn and exec, make process preparation reusable and improve DLL lookup across current, executable and fallback directories, move keyboard repeat into RSSRV so PS/2 and USB share one repeat policy, fix video presentation, report launch failure stages and status codes, mooaaar tests.

This commit is contained in:
maksw committed 2026-09-23 09:39:42 +02:00
1 parent 73abd6f90d
commit 899225f551
57 files changed
+8817 -1216

No files matched your search

+251 -76
View File
@@ -13,7 +13,7 @@
#define NTL_MODULE_CONTEXT_MAGIC 0x4D4F444Cu
#define NTL_MODULE_PAGE_SIZE 4096u
#define NTL_LOADER_DATA_MAGIC 0x30444C4Eu
#define NTL_LOADER_DATA_VERSION 3u
#define NTL_LOADER_DATA_VERSION 4u
typedef struct NTL_LOADER_IMAGE_RECORD {
uintptr_t Base;
@@ -22,6 +22,11 @@ typedef struct NTL_LOADER_IMAGE_RECORD {
char Name[NTL_MODULE_NAME_MAX];
} NTL_LOADER_IMAGE_RECORD;
typedef struct NTL_LOADER_STRING_RECORD {
uint32_t Offset;
uint32_t Length;
} NTL_LOADER_STRING_RECORD;
typedef struct NTL_LOADER_DATA {
uint32_t Magic;
uint32_t Version;
@@ -31,6 +36,10 @@ typedef struct NTL_LOADER_DATA {
uint32_t CurrentDirectoryLength;
uint32_t StartupDataOffset;
uint32_t StartupDataLength;
uint32_t ArgumentVectorOffset;
uint32_t ArgumentCount;
uint32_t EnvironmentVectorOffset;
uint32_t EnvironmentCount;
NTL_LOADER_IMAGE_RECORD Images[];
} NTL_LOADER_DATA;
@@ -48,8 +57,12 @@ typedef struct NTL_MODULE_ENTRY {
struct NTL_MODULE_CONTEXT {
uint32_t Magic;
SYS_HANDLE ProcessHandle;
SYS_HANDLE ModuleRootHandle;
SYS_STRING_VIEW ModuleDirectory;
SYS_HANDLE PrimaryModuleRootHandle;
SYS_STRING_VIEW PrimaryModuleDirectory;
SYS_HANDLE SecondaryModuleRootHandle;
SYS_STRING_VIEW SecondaryModuleDirectory;
SYS_HANDLE FallbackModuleRootHandle;
SYS_STRING_VIEW FallbackModuleDirectory;
NTL_MODULE_NAME_RESOLVER Resolver;
void* ResolverContext;
NTL_MODULE_ENTRY* Head;
@@ -202,27 +215,6 @@ static KSTATUS NtlpCanonicalName(NTL_MODULE_CONTEXT* context,
return NtlpCopyName(*canonicalOut, scratch);
}
// Builds the capability-relative dependency path beneath the configured module directory.
static KSTATUS NtlpBuildModulePath(NTL_MODULE_CONTEXT* context,
SYS_STRING_VIEW canonical,
char out[SYS_PATH_MAX]) {
if (!context || !out) return NTLSTATUS_INVALID_PARAMETER;
char name[NTL_MODULE_NAME_MAX];
KSTATUS status = NtlpCopyName(canonical, name);
if (!KSUCCESS(status)) return status;
size_t dirLength = context->ModuleDirectory.Length;
if (!SysSvIsValid(context->ModuleDirectory) || SysSvContainsByte(context->ModuleDirectory, '\0'))
return NTLSTATUS_INVALID_PARAMETER;
size_t total = dirLength + (dirLength ? 1u : 0u) + canonical.Length;
if (total + 1u > SYS_PATH_MAX) return NTLSTATUS_BUFFER_TOO_SMALL;
if (dirLength) memcpy(out, context->ModuleDirectory.Data, dirLength);
size_t pos = dirLength;
if (dirLength) out[pos++] = '/';
memcpy(out + pos, canonical.Data, canonical.Length);
out[total] = '\0';
return NTLSTATUS_SUCCESS;
}
// Replaces the final component of an explicit module path with its canonical policy name.
static KSTATUS NtlpBuildCanonicalPath(SYS_STRING_VIEW path,
SYS_STRING_VIEW canonical,
@@ -246,23 +238,54 @@ static KSTATUS NtlpBuildCanonicalPath(SYS_STRING_VIEW path,
return NTLSTATUS_SUCCESS;
}
// Opens one canonical dependency through the caller-supplied module-root capability.
// Opens one canonical dependency from a single capability-relative search location.
static KSTATUS NtlpOpenDependencyAt(SYS_HANDLE rootHandle,
SYS_STRING_VIEW directory,
SYS_STRING_VIEW canonical,
SYS_HANDLE* fileOut) {
if (rootHandle == SYS_HANDLE_INVALID || !fileOut || !SysSvIsValid(directory) ||
SysSvContainsByte(directory, '\0'))
return NTLSTATUS_INVALID_PARAMETER;
*fileOut = SYS_HANDLE_INVALID;
char path[SYS_PATH_MAX];
char name[NTL_MODULE_NAME_MAX];
KSTATUS status = NtlpCopyName(canonical, name);
if (!KSUCCESS(status)) return status;
size_t dirLength = directory.Length;
size_t total = dirLength + (dirLength ? 1u : 0u) + canonical.Length;
if (total + 1u > sizeof(path)) return NTLSTATUS_BUFFER_TOO_SMALL;
if (dirLength) memcpy(path, directory.Data, dirLength);
size_t pos = dirLength;
if (dirLength) path[pos++] = '/';
memcpy(path + pos, canonical.Data, canonical.Length);
path[total] = '\0';
SYS_OPEN_FILE_AT_REQUEST open = SysMakeOpenFileAtRequest(rootHandle, SysSvFromCstr(path),
SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY,
SYS_FILE_OPEN_EXISTING,
SYS_FILE_FLAG_NONE, fileOut);
return SysOpenFileAt(&open);
}
// Searches the available current-directory root, then image-private and configured fallback roots.
static KSTATUS NtlpOpenDependency(NTL_MODULE_CONTEXT* context,
SYS_STRING_VIEW canonical,
SYS_HANDLE* fileOut) {
if (!context || context->ModuleRootHandle == SYS_HANDLE_INVALID || !fileOut)
return NTLSTATUS_INVALID_PARAMETER;
*fileOut = SYS_HANDLE_INVALID;
char path[SYS_PATH_MAX];
KSTATUS status = NtlpBuildModulePath(context, canonical, path);
if (!KSUCCESS(status)) return status;
SYS_OPEN_FILE_AT_REQUEST open = SysMakeOpenFileAtRequest(context->ModuleRootHandle,
SysSvFromCstr(path),
SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY,
SYS_FILE_OPEN_EXISTING,
SYS_FILE_FLAG_NONE,
fileOut);
return SysOpenFileAt(&open);
if (!context || !fileOut) return NTLSTATUS_INVALID_PARAMETER;
KSTATUS status = NtlpOpenDependencyAt(context->PrimaryModuleRootHandle,
context->PrimaryModuleDirectory, canonical, fileOut);
if (status != NTLSTATUS_NOT_FOUND) return status;
if (context->SecondaryModuleRootHandle != SYS_HANDLE_INVALID) {
status = NtlpOpenDependencyAt(context->SecondaryModuleRootHandle,
context->SecondaryModuleDirectory, canonical, fileOut);
if (status != NTLSTATUS_NOT_FOUND) return status;
}
if (context->FallbackModuleRootHandle == SYS_HANDLE_INVALID) return NTLSTATUS_NOT_FOUND;
return NtlpOpenDependencyAt(context->FallbackModuleRootHandle,
context->FallbackModuleDirectory, canonical, fileOut);
}
// Publishes a mapped image before import binding so cyclic dependencies can resolve it.
@@ -356,14 +379,22 @@ static KSTATUS NtlpResolveImport(void* opaque,
// Creates loader state for a child process or seeds the current process from PEB loader data.
KSTATUS NtlpCreateModuleContext(SYS_HANDLE processHandle,
SYS_HANDLE moduleRootHandle,
SYS_STRING_VIEW moduleDirectory,
SYS_HANDLE primaryModuleRootHandle,
SYS_STRING_VIEW primaryModuleDirectory,
SYS_HANDLE secondaryModuleRootHandle,
SYS_STRING_VIEW secondaryModuleDirectory,
SYS_HANDLE fallbackModuleRootHandle,
SYS_STRING_VIEW fallbackModuleDirectory,
NTL_MODULE_NAME_RESOLVER resolver,
void* resolverContext,
int seedCurrentProcess,
NTL_MODULE_CONTEXT** contextOut) {
if (!contextOut || moduleRootHandle == SYS_HANDLE_INVALID || !SysSvIsValid(moduleDirectory) ||
SysSvContainsByte(moduleDirectory, '\0'))
if (!contextOut || primaryModuleRootHandle == SYS_HANDLE_INVALID ||
!SysSvIsValid(primaryModuleDirectory) || SysSvContainsByte(primaryModuleDirectory, '\0') ||
(secondaryModuleRootHandle != SYS_HANDLE_INVALID &&
(!SysSvIsValid(secondaryModuleDirectory) || SysSvContainsByte(secondaryModuleDirectory, '\0'))) ||
(fallbackModuleRootHandle != SYS_HANDLE_INVALID &&
(!SysSvIsValid(fallbackModuleDirectory) || SysSvContainsByte(fallbackModuleDirectory, '\0'))))
return NTLSTATUS_INVALID_PARAMETER;
*contextOut = 0;
@@ -372,8 +403,12 @@ KSTATUS NtlpCreateModuleContext(SYS_HANDLE processHandle,
if (!KSUCCESS(status)) return status;
context->Magic = NTL_MODULE_CONTEXT_MAGIC;
context->ProcessHandle = processHandle;
context->ModuleRootHandle = moduleRootHandle;
context->ModuleDirectory = moduleDirectory;
context->PrimaryModuleRootHandle = primaryModuleRootHandle;
context->PrimaryModuleDirectory = primaryModuleDirectory;
context->SecondaryModuleRootHandle = secondaryModuleRootHandle;
context->SecondaryModuleDirectory = secondaryModuleDirectory;
context->FallbackModuleRootHandle = fallbackModuleRootHandle;
context->FallbackModuleDirectory = fallbackModuleDirectory;
context->Resolver = resolver;
context->ResolverContext = resolverContext;
context->OwnsStorage = 1u;
@@ -495,9 +530,26 @@ KSTATUS NtlpLoadMainImage(NTL_MODULE_CONTEXT* context,
return NtlLoadPeImage(&load);
}
// Validates one caller-owned process string vector and returns its serialized string bytes.
static KSTATUS NtlpMeasureProcessVector(NTL_PROCESS_STRING_VECTOR vector, size_t* bytesOut) {
if (!bytesOut || (vector.Count && !vector.Entries)) return NTLSTATUS_INVALID_PARAMETER;
size_t bytes = 0;
for (uint32_t i = 0; i < vector.Count; ++i) {
SYS_STRING_VIEW entry = vector.Entries[i];
if (!SysSvIsValid(entry) || SysSvContainsByte(entry, '\0') || entry.Length > UINT32_MAX)
return NTLSTATUS_INVALID_PARAMETER;
if (entry.Length > SIZE_MAX - bytes - 1u) return NTLSTATUS_NO_MEMORY;
bytes += entry.Length + 1u;
}
*bytesOut = bytes;
return NTLSTATUS_SUCCESS;
}
// Serializes startup dependency metadata into a read-only child-owned VAD.
KSTATUS NtlpBuildLoaderData(NTL_MODULE_CONTEXT* context,
SYS_STRING_VIEW currentDirectory,
NTL_PROCESS_STRING_VECTOR arguments,
NTL_PROCESS_STRING_VECTOR environment,
const void* startupData,
size_t startupDataSize,
void** loaderDataOut) {
@@ -510,10 +562,28 @@ KSTATUS NtlpBuildLoaderData(NTL_MODULE_CONTEXT* context,
return NTLSTATUS_INVALID_PARAMETER;
*loaderDataOut = 0;
size_t argumentStringBytes = 0;
size_t environmentStringBytes = 0;
KSTATUS status = NtlpMeasureProcessVector(arguments, &argumentStringBytes);
if (!KSUCCESS(status)) return status;
status = NtlpMeasureProcessVector(environment, &environmentStringBytes);
if (!KSUCCESS(status)) return status;
size_t recordsBytes = (size_t)context->Count * sizeof(NTL_LOADER_IMAGE_RECORD);
if (context->Count && recordsBytes / sizeof(NTL_LOADER_IMAGE_RECORD) != context->Count)
return NTLSTATUS_NO_MEMORY;
size_t bytes = sizeof(NTL_LOADER_DATA) + recordsBytes;
size_t argumentRecordsBytes = (size_t)arguments.Count * sizeof(NTL_LOADER_STRING_RECORD);
size_t environmentRecordsBytes = (size_t)environment.Count * sizeof(NTL_LOADER_STRING_RECORD);
if ((arguments.Count && argumentRecordsBytes / sizeof(NTL_LOADER_STRING_RECORD) != arguments.Count) ||
(environment.Count && environmentRecordsBytes / sizeof(NTL_LOADER_STRING_RECORD) != environment.Count) ||
argumentRecordsBytes > SIZE_MAX - bytes)
return NTLSTATUS_NO_MEMORY;
size_t argumentVectorOffset = arguments.Count ? bytes : 0u;
bytes += argumentRecordsBytes;
if (environmentRecordsBytes > SIZE_MAX - bytes) return NTLSTATUS_NO_MEMORY;
size_t environmentVectorOffset = environment.Count ? bytes : 0u;
bytes += environmentRecordsBytes;
if (bytes < sizeof(NTL_LOADER_DATA) || currentDirectory.Length > SIZE_MAX - bytes - 1u)
return NTLSTATUS_NO_MEMORY;
size_t currentDirectoryOffset = bytes;
@@ -524,6 +594,12 @@ KSTATUS NtlpBuildLoaderData(NTL_MODULE_CONTEXT* context,
startupDataOffset = bytes;
bytes += startupDataSize;
}
if (argumentStringBytes > SIZE_MAX - bytes) return NTLSTATUS_NO_MEMORY;
size_t argumentStringsOffset = bytes;
bytes += argumentStringBytes;
if (environmentStringBytes > SIZE_MAX - bytes) return NTLSTATUS_NO_MEMORY;
size_t environmentStringsOffset = bytes;
bytes += environmentStringBytes;
if (bytes > UINT32_MAX) return NTLSTATUS_NO_MEMORY;
if (bytes > SIZE_MAX - (NTL_MODULE_PAGE_SIZE - 1u)) return NTLSTATUS_NO_MEMORY;
size_t pages = (bytes + NTL_MODULE_PAGE_SIZE - 1u) / NTL_MODULE_PAGE_SIZE;
@@ -537,7 +613,7 @@ KSTATUS NtlpBuildLoaderData(NTL_MODULE_CONTEXT* context,
alloc.Flags = SYS_VM_FLAG_NONE;
alloc.PageCount = pages;
alloc.BaseOut = &base;
KSTATUS status = SysAllocProcessVm(&alloc);
status = SysAllocProcessVm(&alloc);
if (!KSUCCESS(status)) return status;
NTL_LOADER_DATA* data = (NTL_LOADER_DATA*)base;
@@ -550,6 +626,10 @@ KSTATUS NtlpBuildLoaderData(NTL_MODULE_CONTEXT* context,
data->CurrentDirectoryLength = (uint32_t)currentDirectory.Length;
data->StartupDataOffset = startupDataSize ? (uint32_t)startupDataOffset : 0u;
data->StartupDataLength = (uint32_t)startupDataSize;
data->ArgumentVectorOffset = arguments.Count ? (uint32_t)argumentVectorOffset : 0u;
data->ArgumentCount = arguments.Count;
data->EnvironmentVectorOffset = environment.Count ? (uint32_t)environmentVectorOffset : 0u;
data->EnvironmentCount = environment.Count;
uint32_t i = 0;
for (NTL_MODULE_ENTRY* entry = context->Head; entry; entry = entry->Next) {
NTL_LOADER_IMAGE_RECORD* image = &data->Images[i++];
@@ -564,16 +644,40 @@ KSTATUS NtlpBuildLoaderData(NTL_MODULE_CONTEXT* context,
if (startupDataSize)
memcpy((char*)data + startupDataOffset, startupData, startupDataSize);
NTL_LOADER_STRING_RECORD* argumentRecords = arguments.Count
? (NTL_LOADER_STRING_RECORD*)((char*)data + argumentVectorOffset) : 0;
size_t stringOffset = argumentStringsOffset;
for (uint32_t argumentIndex = 0; argumentIndex < arguments.Count; ++argumentIndex) {
SYS_STRING_VIEW entry = arguments.Entries[argumentIndex];
argumentRecords[argumentIndex].Offset = (uint32_t)stringOffset;
argumentRecords[argumentIndex].Length = (uint32_t)entry.Length;
if (entry.Length) memcpy((char*)data + stringOffset, entry.Data, entry.Length);
((char*)data)[stringOffset + entry.Length] = '\0';
stringOffset += entry.Length + 1u;
}
NTL_LOADER_STRING_RECORD* environmentRecords = environment.Count
? (NTL_LOADER_STRING_RECORD*)((char*)data + environmentVectorOffset) : 0;
stringOffset = environmentStringsOffset;
for (uint32_t environmentIndex = 0; environmentIndex < environment.Count; ++environmentIndex) {
SYS_STRING_VIEW entry = environment.Entries[environmentIndex];
environmentRecords[environmentIndex].Offset = (uint32_t)stringOffset;
environmentRecords[environmentIndex].Length = (uint32_t)entry.Length;
if (entry.Length) memcpy((char*)data + stringOffset, entry.Data, entry.Length);
((char*)data)[stringOffset + entry.Length] = '\0';
stringOffset += entry.Length + 1u;
}
status = SysProtectProcessVm(context->ProcessHandle, base, pages, SYS_VM_READ);
if (!KSUCCESS(status)) return status;
*loaderDataOut = base;
return NTLSTATUS_SUCCESS;
}
// Copies the opaque userspace bootstrap payload from the current process loader block.
KSTATUS NtlGetProcessStartupData(void* buffer, size_t bufferSize, size_t* sizeOut) {
if (!sizeOut || (bufferSize && !buffer)) return NTLSTATUS_INVALID_PARAMETER;
*sizeOut = 0;
// Validates and returns the immutable loader block for the current process.
static KSTATUS NtlpGetCurrentLoaderData(const NTL_LOADER_DATA** dataOut) {
if (!dataOut) return NTLSTATUS_INVALID_PARAMETER;
*dataOut = 0;
SYS_PEB* peb = SysGetPeb();
if (!peb || peb->Magic != SYS_PEB_MAGIC || peb->Version != SYS_ENV_VERSION || !peb->LoaderData)
@@ -595,8 +699,21 @@ KSTATUS NtlGetProcessStartupData(void* buffer, size_t bufferSize, size_t* sizeOu
const NTL_LOADER_DATA* data = (const NTL_LOADER_DATA*)peb->LoaderData;
if (data->Magic != NTL_LOADER_DATA_MAGIC || data->Version != NTL_LOADER_DATA_VERSION ||
data->Size < sizeof(*data) || data->Size > regionBytes - (dataBase - regionBase) ||
data->StartupDataLength > NTL_PROCESS_STARTUP_DATA_MAX ||
data->Size < sizeof(*data) || data->Size > regionBytes - (dataBase - regionBase))
return NTLSTATUS_FAILURE;
*dataOut = data;
return NTLSTATUS_SUCCESS;
}
// Copies the opaque userspace bootstrap payload from the current process loader block.
KSTATUS NtlGetProcessStartupData(void* buffer, size_t bufferSize, size_t* sizeOut) {
if (!sizeOut || (bufferSize && !buffer)) return NTLSTATUS_INVALID_PARAMETER;
*sizeOut = 0;
const NTL_LOADER_DATA* data = 0;
KSTATUS status = NtlpGetCurrentLoaderData(&data);
if (!KSUCCESS(status)) return status;
if (data->StartupDataLength > NTL_PROCESS_STARTUP_DATA_MAX ||
(data->StartupDataLength == 0 && data->StartupDataOffset != 0) ||
(data->StartupDataLength != 0 &&
(data->StartupDataOffset < sizeof(*data) || data->StartupDataOffset > data->Size ||
@@ -612,33 +729,85 @@ KSTATUS NtlGetProcessStartupData(void* buffer, size_t bufferSize, size_t* sizeOu
return NTLSTATUS_SUCCESS;
}
// Returns one loader string vector count after validating its descriptor table.
static KSTATUS NtlpGetProcessVectorCount(int environment, uint32_t* countOut) {
if (!countOut) return NTLSTATUS_INVALID_PARAMETER;
*countOut = 0;
const NTL_LOADER_DATA* data = 0;
KSTATUS status = NtlpGetCurrentLoaderData(&data);
if (!KSUCCESS(status)) return status;
uint32_t count = environment ? data->EnvironmentCount : data->ArgumentCount;
uint32_t offset = environment ? data->EnvironmentVectorOffset : data->ArgumentVectorOffset;
if ((count == 0 && offset != 0) || (count != 0 && offset == 0)) return NTLSTATUS_FAILURE;
size_t recordsBytes = (size_t)count * sizeof(NTL_LOADER_STRING_RECORD);
if (count && recordsBytes / sizeof(NTL_LOADER_STRING_RECORD) != count)
return NTLSTATUS_FAILURE;
if (offset > data->Size || recordsBytes > data->Size - offset)
return NTLSTATUS_FAILURE;
*countOut = count;
return NTLSTATUS_SUCCESS;
}
// Returns one immutable loader string vector entry.
static KSTATUS NtlpGetProcessVectorEntry(int environment, uint32_t index, SYS_STRING_VIEW* entryOut) {
if (!entryOut) return NTLSTATUS_INVALID_PARAMETER;
*entryOut = SYS_SV_NULL;
const NTL_LOADER_DATA* data = 0;
KSTATUS status = NtlpGetCurrentLoaderData(&data);
if (!KSUCCESS(status)) return status;
uint32_t count = environment ? data->EnvironmentCount : data->ArgumentCount;
uint32_t offset = environment ? data->EnvironmentVectorOffset : data->ArgumentVectorOffset;
if (index >= count || !count || !offset) return NTLSTATUS_NOT_FOUND;
size_t recordsBytes = (size_t)count * sizeof(NTL_LOADER_STRING_RECORD);
if (recordsBytes / sizeof(NTL_LOADER_STRING_RECORD) != count ||
offset > data->Size || recordsBytes > data->Size - offset)
return NTLSTATUS_FAILURE;
const NTL_LOADER_STRING_RECORD* records =
(const NTL_LOADER_STRING_RECORD*)((const char*)data + offset);
NTL_LOADER_STRING_RECORD record = records[index];
if (record.Offset >= data->Size || record.Length > data->Size - record.Offset ||
record.Length == data->Size - record.Offset)
return NTLSTATUS_FAILURE;
const char* string = (const char*)data + record.Offset;
SYS_STRING_VIEW view = SysSvFromParts(string, record.Length);
if (string[record.Length] != '\0' || SysSvContainsByte(view, '\0'))
return NTLSTATUS_FAILURE;
*entryOut = view;
return NTLSTATUS_SUCCESS;
}
// Returns the number of serialized process arguments.
KSTATUS NtlGetProcessArgumentCount(uint32_t* countOut) {
return NtlpGetProcessVectorCount(0, countOut);
}
// Returns one serialized process argument.
KSTATUS NtlGetProcessArgument(uint32_t index, SYS_STRING_VIEW* argumentOut) {
return NtlpGetProcessVectorEntry(0, index, argumentOut);
}
// Returns the number of serialized environment entries.
KSTATUS NtlGetProcessEnvironmentCount(uint32_t* countOut) {
return NtlpGetProcessVectorCount(1, countOut);
}
// Returns one serialized environment entry.
KSTATUS NtlGetProcessEnvironment(uint32_t index, SYS_STRING_VIEW* entryOut) {
return NtlpGetProcessVectorEntry(1, index, entryOut);
}
// Returns the canonical inherited resource CWD stored in this process's loader data.
KSTATUS NtlpGetLoaderCurrentDirectory(SYS_STRING_VIEW* currentDirectoryOut) {
if (!currentDirectoryOut) return NTLSTATUS_INVALID_PARAMETER;
*currentDirectoryOut = SysSvFromParts((const char*)0, 0);
*currentDirectoryOut = SYS_SV_NULL;
SYS_PEB* peb = SysGetPeb();
if (!peb || peb->Magic != SYS_PEB_MAGIC || peb->Version != SYS_ENV_VERSION || !peb->LoaderData)
return NTLSTATUS_NOT_FOUND;
SYS_VM_REGION_INFO region;
memset(&region, 0, sizeof(region));
KSTATUS status = SysQueryVm((void*)peb->LoaderData, &region);
if (!KSUCCESS(status) || !region.Base || !region.PageCount ||
region.PageCount > SIZE_MAX / NTL_MODULE_PAGE_SIZE)
return NTLSTATUS_FAILURE;
size_t regionBytes = region.PageCount * NTL_MODULE_PAGE_SIZE;
uintptr_t regionBase = (uintptr_t)region.Base;
uintptr_t dataBase = (uintptr_t)peb->LoaderData;
if (dataBase < regionBase || dataBase - regionBase > regionBytes ||
regionBytes - (dataBase - regionBase) < sizeof(NTL_LOADER_DATA))
return NTLSTATUS_FAILURE;
const NTL_LOADER_DATA* data = (const NTL_LOADER_DATA*)peb->LoaderData;
if (data->Magic != NTL_LOADER_DATA_MAGIC || data->Version != NTL_LOADER_DATA_VERSION ||
data->Size < sizeof(*data) || data->Size > regionBytes - (dataBase - regionBase) ||
data->CurrentDirectoryOffset < sizeof(*data) ||
const NTL_LOADER_DATA* data = 0;
KSTATUS status = NtlpGetCurrentLoaderData(&data);
if (!KSUCCESS(status)) return status;
if (data->CurrentDirectoryOffset < sizeof(*data) ||
data->CurrentDirectoryLength == 0 ||
data->CurrentDirectoryOffset > data->Size ||
data->CurrentDirectoryLength > data->Size - data->CurrentDirectoryOffset ||
@@ -664,6 +833,8 @@ static KSTATUS NtlpEnsureCurrentContext(SYS_HANDLE moduleRoot,
if (_InterlockedCompareExchange(&gCurrentContextState, 1, 0) == 0) {
NTL_MODULE_CONTEXT* temporary = 0;
KSTATUS status = NtlpCreateModuleContext(SYS_HANDLE_INVALID, moduleRoot, moduleDirectory,
SYS_HANDLE_INVALID, SysSvFromParts((const char*)0, 0),
SYS_HANDLE_INVALID, SysSvFromParts((const char*)0, 0),
resolver, resolverContext, 1, &temporary);
if (!KSUCCESS(status)) {
_InterlockedExchange(&gCurrentContextState, 0);
@@ -679,8 +850,12 @@ static KSTATUS NtlpEnsureCurrentContext(SYS_HANDLE moduleRoot,
while (_InterlockedCompareExchange(&gCurrentContextState, 2, 2) == 1) SysYield();
if (_InterlockedCompareExchange(&gCurrentContextState, 2, 2) != 2)
return NTLSTATUS_FAILURE;
gCurrentContext.ModuleRootHandle = moduleRoot;
gCurrentContext.ModuleDirectory = moduleDirectory;
gCurrentContext.PrimaryModuleRootHandle = moduleRoot;
gCurrentContext.PrimaryModuleDirectory = moduleDirectory;
gCurrentContext.SecondaryModuleRootHandle = SYS_HANDLE_INVALID;
gCurrentContext.SecondaryModuleDirectory = SysSvFromParts((const char*)0, 0);
gCurrentContext.FallbackModuleRootHandle = SYS_HANDLE_INVALID;
gCurrentContext.FallbackModuleDirectory = SysSvFromParts((const char*)0, 0);
gCurrentContext.Resolver = resolver;
gCurrentContext.ResolverContext = resolverContext;
}
+9 -2
View File
@@ -4,14 +4,19 @@
#include <ntlite/module_loader.h>
#include <ntlite/pe_loader.h>
#include <ntlite/process_loader.h>
#include <ntlite/syscall.h>
typedef struct NTL_MODULE_CONTEXT NTL_MODULE_CONTEXT;
// Creates dependency-loader state for one constructing child or the current process.
KSTATUS NtlpCreateModuleContext(SYS_HANDLE processHandle,
SYS_HANDLE moduleRootHandle,
SYS_STRING_VIEW moduleDirectory,
SYS_HANDLE primaryModuleRootHandle,
SYS_STRING_VIEW primaryModuleDirectory,
SYS_HANDLE secondaryModuleRootHandle,
SYS_STRING_VIEW secondaryModuleDirectory,
SYS_HANDLE fallbackModuleRootHandle,
SYS_STRING_VIEW fallbackModuleDirectory,
NTL_MODULE_NAME_RESOLVER resolver,
void* resolverContext,
int seedCurrentProcess,
@@ -25,6 +30,8 @@ KSTATUS NtlpLoadMainImage(NTL_MODULE_CONTEXT* context,
// Builds the opaque read-only loader-data block consumed later by userspace base services.
KSTATUS NtlpBuildLoaderData(NTL_MODULE_CONTEXT* context,
SYS_STRING_VIEW currentDirectory,
NTL_PROCESS_STRING_VECTOR arguments,
NTL_PROCESS_STRING_VECTOR environment,
const void* startupData,
size_t startupDataSize,
void** loaderDataOut);
+282 -95
View File
@@ -15,12 +15,116 @@ static void NtlDiscardChild(SYS_HANDLE processHandle) {
(void)SysCloseHandle(processHandle);
}
// Creates and starts one child from an already-open PE file capability.
static KSTATUS NtlCreateProcessFile(const NTL_CREATE_PROCESS_AT_REQUEST* request, SYS_HANDLE fileHandle) {
if (!request || fileHandle == SYS_HANDLE_INVALID)
return NTLSTATUS_INVALID_PARAMETER;
#define NTL_PROCESS_BUILDER_MAGIC 0x3142504Eu
typedef struct NTL_PROCESS_BUILDER_INTERNAL {
uint32_t Magic;
uint32_t StartupCapabilityCount;
SYS_HANDLE ProcessHandle;
NTL_MODULE_CONTEXT* Modules;
NTL_PE_IMAGE Image;
void* LoaderData;
SYS_STARTUP_CAPABILITY ChildCapabilities[SYS_STARTUP_CAPABILITY_MAX];
} NTL_PROCESS_BUILDER_INTERNAL;
typedef char NTL_PROCESS_BUILDER_SIZE_CHECK[
sizeof(NTL_PROCESS_BUILDER_INTERNAL) <= sizeof(NTL_PROCESS_BUILDER) ? 1 : -1];
static NTL_PROCESS_BUILDER_INTERNAL* NtlBuilderInternal(NTL_PROCESS_BUILDER* builder) {
return (NTL_PROCESS_BUILDER_INTERNAL*)(void*)builder;
}
static int NtlBuilderRequestValid(const NTL_PROCESS_BUILDER_REQUEST* request) {
return request && request->Size == sizeof(*request) &&
request->Flags == NTL_PROCESS_LOAD_FLAG_NONE &&
request->RootHandle != SYS_HANDLE_INVALID &&
request->ModuleRootHandle != SYS_HANDLE_INVALID &&
request->Path.Data && request->Path.Length != 0 &&
SysSvIsValid(request->ModuleDirectory) &&
request->StartupCapabilityCount <= SYS_STARTUP_CAPABILITY_MAX &&
(!request->StartupCapabilityCount || request->StartupCapabilities) &&
(!request->Arguments.Count || request->Arguments.Entries) &&
(!request->Environment.Count || request->Environment.Entries) &&
request->StartupDataSize <= NTL_PROCESS_STARTUP_DATA_MAX &&
(!request->StartupDataSize || request->StartupData);
}
static void NtlBuilderReset(NTL_PROCESS_BUILDER* builder) {
if (builder) memset(builder, 0, sizeof(*builder));
}
// Aborts one prepared inert child. This is deliberately safe on an empty builder.
void NtlProcessBuilderAbort(NTL_PROCESS_BUILDER* builder) {
if (!builder) return;
NTL_PROCESS_BUILDER_INTERNAL* state = NtlBuilderInternal(builder);
if (state->Magic != NTL_PROCESS_BUILDER_MAGIC) {
NtlBuilderReset(builder);
return;
}
if (state->Modules) NtlpDestroyModuleContext(state->Modules);
if (state->ProcessHandle != SYS_HANDLE_INVALID) NtlDiscardChild(state->ProcessHandle);
NtlBuilderReset(builder);
}
// Opens the executable's containing directory as the private dependency-search root.
static KSTATUS NtlOpenImageDirectory(const NTL_PROCESS_BUILDER_REQUEST* request,
SYS_HANDLE* directoryOut, int* borrowedRootOut) {
if (!request || !directoryOut || !borrowedRootOut || !SysSvIsValid(request->Path) ||
request->Path.Length == 0 || SysSvContainsByte(request->Path, '\0'))
return NTLSTATUS_INVALID_PARAMETER;
*directoryOut = SYS_HANDLE_INVALID;
*borrowedRootOut = 0;
size_t slash = SIZE_MAX;
for (size_t i = 0; i < request->Path.Length; ++i) {
if (request->Path.Data[i] == '/') slash = i;
else if (request->Path.Data[i] == '\\') return NTLSTATUS_INVALID_PARAMETER;
}
if (slash == SIZE_MAX) {
*directoryOut = request->RootHandle;
*borrowedRootOut = 1;
return NTLSTATUS_SUCCESS;
}
SYS_STRING_VIEW directoryPath;
if (slash == 0) directoryPath = SYS_SV_LITERAL("/");
else directoryPath = SysSvFromParts(request->Path.Data, slash);
if (request->Path.Data[0] == '/')
return NtlOpenDir(directoryPath, SYS_DIR_ACCESS_OPEN, SYS_DIR_FLAG_NONE, directoryOut);
SYS_OPEN_DIR_AT_REQUEST open = SysMakeOpenDirAtRequest(request->RootHandle, directoryPath,
SYS_DIR_ACCESS_OPEN, SYS_DIR_FLAG_NONE,
directoryOut);
return SysOpenDirAt(&open);
}
// Prepares an inert child: process object, image/dependencies, inherited startup
// capabilities, CWD, and loader/bootstrap block are all complete before return.
KSTATUS NtlProcessBuilderPrepare(NTL_PROCESS_BUILDER* builder,
const NTL_PROCESS_BUILDER_REQUEST* request,
SYS_HANDLE imageFile) {
if (!builder || !NtlBuilderRequestValid(request)) return NTLSTATUS_INVALID_PARAMETER;
NtlBuilderReset(builder);
NTL_PROCESS_BUILDER_INTERNAL* state = NtlBuilderInternal(builder);
state->ProcessHandle = SYS_HANDLE_INVALID;
SYS_HANDLE openedImage = SYS_HANDLE_INVALID;
if (imageFile == SYS_HANDLE_INVALID) {
SYS_OPEN_FILE_AT_REQUEST open;
memset(&open, 0, sizeof(open));
open.Size = sizeof(open);
open.RootHandle = request->RootHandle;
open.Path = request->Path;
open.Access = SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY;
open.Disposition = SYS_FILE_OPEN_EXISTING;
open.Flags = SYS_FILE_FLAG_NONE;
open.HandleOut = &openedImage;
KSTATUS openStatus = SysOpenFileAt(&open);
if (!KSUCCESS(openStatus)) return openStatus;
imageFile = openedImage;
}
SYS_HANDLE processHandle = SYS_HANDLE_INVALID;
SYS_CREATE_PROCESS_OBJECT_REQUEST create;
memset(&create, 0, sizeof(create));
create.Size = sizeof(create);
@@ -28,133 +132,200 @@ static KSTATUS NtlCreateProcessFile(const NTL_CREATE_PROCESS_AT_REQUEST* request
create.ImagePath = request->Path;
create.CommandLine = request->CommandLine;
create.SecurityContext = request->SecurityContext;
create.ProcessHandleOut = &processHandle;
create.ProcessHandleOut = &state->ProcessHandle;
KSTATUS status = SysCreateProcessObject(&create);
if (!KSUCCESS(status))
return status;
if (!KSUCCESS(status)) goto done;
NTL_MODULE_CONTEXT* modules = 0;
status = NtlpCreateModuleContext(processHandle,
request->ModuleRootHandle,
request->ModuleDirectory,
request->ResolveModuleName,
request->ResolveContext,
0,
&modules);
char currentDirectoryBuffer[SYS_PATH_MAX + 1u];
SYS_STRING_VIEW currentDirectory;
size_t currentDirectorySize = 0;
if (request->CurrentDirectory.Length != 0) {
status = NtlRealPath(request->CurrentDirectory, currentDirectoryBuffer,
sizeof(currentDirectoryBuffer), &currentDirectorySize);
} else {
status = NtlGetCurrentDirectory(currentDirectoryBuffer, sizeof(currentDirectoryBuffer),
&currentDirectorySize);
}
if (!KSUCCESS(status)) goto fail;
currentDirectory = SysSvFromParts(currentDirectoryBuffer, currentDirectorySize - 1u);
SYS_HANDLE currentDirectoryHandle = SYS_HANDLE_INVALID;
KSTATUS currentDirectoryStatus = NtlOpenDir(currentDirectory, SYS_DIR_ACCESS_OPEN,
SYS_DIR_FLAG_NONE, &currentDirectoryHandle);
SYS_HANDLE imageDirectory = SYS_HANDLE_INVALID;
int imageDirectoryBorrowed = 0;
status = NtlOpenImageDirectory(request, &imageDirectory, &imageDirectoryBorrowed);
if (!KSUCCESS(status)) {
NtlDiscardChild(processHandle);
return status;
if (currentDirectoryHandle != SYS_HANDLE_INVALID)
(void)SysCloseHandle(currentDirectoryHandle);
goto fail;
}
NTL_PE_IMAGE image;
memset(&image, 0, sizeof(image));
status = NtlpLoadMainImage(modules, fileHandle, &image);
if (!KSUCCESS(status)) {
NtlpDestroyModuleContext(modules);
NtlDiscardChild(processHandle);
return status;
SYS_HANDLE primaryModuleRoot = imageDirectory;
SYS_STRING_VIEW primaryModuleDirectory = SysSvFromParts((const char*)0, 0);
SYS_HANDLE secondaryModuleRoot = request->ModuleRootHandle;
SYS_STRING_VIEW secondaryModuleDirectory = request->ModuleDirectory;
SYS_HANDLE fallbackModuleRoot = SYS_HANDLE_INVALID;
SYS_STRING_VIEW fallbackModuleDirectory = SysSvFromParts((const char*)0, 0);
// Current-directory lookup is a search-path optimization, not a bootstrap dependency.
if (KSUCCESS(currentDirectoryStatus)) {
primaryModuleRoot = currentDirectoryHandle;
secondaryModuleRoot = imageDirectory;
secondaryModuleDirectory = SysSvFromParts((const char*)0, 0);
fallbackModuleRoot = request->ModuleRootHandle;
fallbackModuleDirectory = request->ModuleDirectory;
}
SYS_STARTUP_CAPABILITY childCapabilities[SYS_STARTUP_CAPABILITY_MAX];
memset(childCapabilities, 0, sizeof(childCapabilities));
status = NtlpCreateModuleContext(state->ProcessHandle, primaryModuleRoot,
primaryModuleDirectory, secondaryModuleRoot,
secondaryModuleDirectory, fallbackModuleRoot,
fallbackModuleDirectory, request->ResolveModuleName,
request->ResolveContext, 0, &state->Modules);
if (!KSUCCESS(status)) {
if (!imageDirectoryBorrowed) (void)SysCloseHandle(imageDirectory);
if (currentDirectoryHandle != SYS_HANDLE_INVALID)
(void)SysCloseHandle(currentDirectoryHandle);
goto fail;
}
memset(&state->Image, 0, sizeof(state->Image));
status = NtlpLoadMainImage(state->Modules, imageFile, &state->Image);
if (!imageDirectoryBorrowed) (void)SysCloseHandle(imageDirectory);
if (currentDirectoryHandle != SYS_HANDLE_INVALID)
(void)SysCloseHandle(currentDirectoryHandle);
if (!KSUCCESS(status)) goto fail;
memset(state->ChildCapabilities, 0, sizeof(state->ChildCapabilities));
for (uint32_t i = 0; i < request->StartupCapabilityCount; ++i) {
const NTL_PROCESS_STARTUP_CAPABILITY* source = &request->StartupCapabilities[i];
if (!source->Tag || source->SourceHandle == SYS_HANDLE_INVALID) {
NtlpDestroyModuleContext(modules);
NtlDiscardChild(processHandle);
return NTLSTATUS_INVALID_PARAMETER;
status = NTLSTATUS_INVALID_PARAMETER;
goto fail;
}
for (uint32_t j = 0; j < i; ++j) {
if (childCapabilities[j].Tag == source->Tag) {
NtlpDestroyModuleContext(modules);
NtlDiscardChild(processHandle);
return NTLSTATUS_INVALID_PARAMETER;
if (state->ChildCapabilities[j].Tag == source->Tag) {
status = NTLSTATUS_INVALID_PARAMETER;
goto fail;
}
}
SYS_HANDLE childHandle = SYS_HANDLE_INVALID;
SYS_DUPLICATE_HANDLE_REQUEST duplicate;
memset(&duplicate, 0, sizeof(duplicate));
duplicate.Size = sizeof(duplicate);
duplicate.SourceHandle = source->SourceHandle;
duplicate.TargetProcessHandle = processHandle;
duplicate.TargetProcessHandle = state->ProcessHandle;
duplicate.DesiredRights = source->DesiredRights;
duplicate.Flags = source->DuplicateFlags;
duplicate.TargetHandleOut = &childHandle;
status = SysDuplicateHandle(&duplicate);
if (!KSUCCESS(status)) {
NtlpDestroyModuleContext(modules);
NtlDiscardChild(processHandle);
return status;
}
childCapabilities[i].Tag = source->Tag;
childCapabilities[i].Handle = childHandle;
if (!KSUCCESS(status)) goto fail;
state->ChildCapabilities[i].Tag = source->Tag;
state->ChildCapabilities[i].Handle = childHandle;
}
state->StartupCapabilityCount = request->StartupCapabilityCount;
char currentDirectoryBuffer[SYS_PATH_MAX + 1u];
SYS_STRING_VIEW currentDirectory;
if (request->CurrentDirectory.Length != 0) {
size_t required = 0;
status = NtlRealPath(request->CurrentDirectory, currentDirectoryBuffer,
sizeof(currentDirectoryBuffer), &required);
if (!KSUCCESS(status)) {
NtlpDestroyModuleContext(modules);
NtlDiscardChild(processHandle);
return status;
}
currentDirectory = SysSvFromParts(currentDirectoryBuffer, required - 1u);
status = NtlpBuildLoaderData(state->Modules, currentDirectory, request->Arguments,
request->Environment, request->StartupData,
request->StartupDataSize, &state->LoaderData);
if (!KSUCCESS(status)) goto fail;
SYS_HANDLE cwdHandle = SYS_HANDLE_INVALID;
status = NtlOpenDir(currentDirectory, SYS_DIR_ACCESS_ENUMERATE | SYS_DIR_ACCESS_OPEN,
SYS_DIR_FLAG_NONE, &cwdHandle);
if (!KSUCCESS(status)) {
NtlpDestroyModuleContext(modules);
NtlDiscardChild(processHandle);
return status;
}
(void)SysCloseHandle(cwdHandle);
} else {
size_t required = 0;
status = NtlGetCurrentDirectory(currentDirectoryBuffer, sizeof(currentDirectoryBuffer), &required);
if (!KSUCCESS(status)) {
NtlpDestroyModuleContext(modules);
NtlDiscardChild(processHandle);
return status;
}
currentDirectory = SysSvFromParts(currentDirectoryBuffer, required - 1u);
}
state->Magic = NTL_PROCESS_BUILDER_MAGIC;
status = NTLSTATUS_SUCCESS;
goto done;
void* loaderData = 0;
status = NtlpBuildLoaderData(modules, currentDirectory, request->StartupData,
request->StartupDataSize, &loaderData);
if (!KSUCCESS(status)) {
NtlpDestroyModuleContext(modules);
NtlDiscardChild(processHandle);
return status;
}
fail:
if (state->Modules) NtlpDestroyModuleContext(state->Modules);
if (state->ProcessHandle != SYS_HANDLE_INVALID) NtlDiscardChild(state->ProcessHandle);
NtlBuilderReset(builder);
done:
if (openedImage != SYS_HANDLE_INVALID) (void)SysCloseHandle(openedImage);
return status;
}
// Returns the process capability owned by one prepared builder without transferring it.
KSTATUS NtlProcessBuilderGetProcessHandle(NTL_PROCESS_BUILDER* builder,
SYS_HANDLE* processHandleOut) {
if (!builder || !processHandleOut) return NTLSTATUS_INVALID_PARAMETER;
*processHandleOut = SYS_HANDLE_INVALID;
NTL_PROCESS_BUILDER_INTERNAL* state = NtlBuilderInternal(builder);
if (state->Magic != NTL_PROCESS_BUILDER_MAGIC ||
state->ProcessHandle == SYS_HANDLE_INVALID || !state->Modules || !state->LoaderData)
return NTLSTATUS_INVALID_PARAMETER;
*processHandleOut = state->ProcessHandle;
return NTLSTATUS_SUCCESS;
}
// Starts one prepared child. On success ownership of the retained native process
// capability moves to the caller; on failure the child is destroyed.
KSTATUS NtlProcessBuilderStart(NTL_PROCESS_BUILDER* builder, SYS_HANDLE* processHandleOut) {
if (!builder || !processHandleOut) return NTLSTATUS_INVALID_PARAMETER;
*processHandleOut = SYS_HANDLE_INVALID;
NTL_PROCESS_BUILDER_INTERNAL* state = NtlBuilderInternal(builder);
if (state->Magic != NTL_PROCESS_BUILDER_MAGIC ||
state->ProcessHandle == SYS_HANDLE_INVALID || !state->Modules || !state->LoaderData)
return NTLSTATUS_INVALID_PARAMETER;
SYS_START_PROCESS_REQUEST startRequest;
memset(&startRequest, 0, sizeof(startRequest));
startRequest.Size = sizeof(startRequest);
startRequest.ProcessHandle = processHandle;
startRequest.ProcessHandle = state->ProcessHandle;
startRequest.Flags = SYS_START_PROCESS_FLAG_NONE;
startRequest.MainImageBase = image.Base;
startRequest.MainImageSize = image.Size;
startRequest.EntryPoint = image.EntryPoint;
startRequest.StartupCapabilities = childCapabilities;
startRequest.StartupCapabilityCount = request->StartupCapabilityCount;
startRequest.LoaderData = loaderData;
status = SysStartProcess(&startRequest);
NtlpDestroyModuleContext(modules);
startRequest.MainImageBase = state->Image.Base;
startRequest.MainImageSize = state->Image.Size;
startRequest.EntryPoint = state->Image.EntryPoint;
startRequest.StartupCapabilities = state->ChildCapabilities;
startRequest.StartupCapabilityCount = state->StartupCapabilityCount;
startRequest.LoaderData = state->LoaderData;
KSTATUS status = SysStartProcess(&startRequest);
NtlpDestroyModuleContext(state->Modules);
state->Modules = 0;
if (!KSUCCESS(status)) {
NtlDiscardChild(processHandle);
NtlDiscardChild(state->ProcessHandle);
NtlBuilderReset(builder);
return status;
}
*request->ProcessHandleOut = processHandle;
*processHandleOut = state->ProcessHandle;
NtlBuilderReset(builder);
return NTLSTATUS_SUCCESS;
}
static void NtlBuilderRequestFromCreate(const NTL_CREATE_PROCESS_AT_REQUEST* create,
NTL_PROCESS_BUILDER_REQUEST* builder) {
memset(builder, 0, sizeof(*builder));
builder->Size = sizeof(*builder);
builder->Flags = create->Flags;
builder->RootHandle = create->RootHandle;
builder->Path = create->Path;
builder->CommandLine = create->CommandLine;
builder->CurrentDirectory = create->CurrentDirectory;
builder->SecurityContext = create->SecurityContext;
builder->ModuleRootHandle = create->ModuleRootHandle;
builder->ModuleDirectory = create->ModuleDirectory;
builder->ResolveModuleName = create->ResolveModuleName;
builder->ResolveContext = create->ResolveContext;
builder->StartupCapabilities = create->StartupCapabilities;
builder->StartupCapabilityCount = create->StartupCapabilityCount;
builder->Arguments = create->Arguments;
builder->Environment = create->Environment;
builder->StartupData = create->StartupData;
builder->StartupDataSize = create->StartupDataSize;
}
static KSTATUS NtlCreateProcessFile(const NTL_CREATE_PROCESS_AT_REQUEST* request, SYS_HANDLE fileHandle) {
NTL_PROCESS_BUILDER_REQUEST builderRequest;
NtlBuilderRequestFromCreate(request, &builderRequest);
NTL_PROCESS_BUILDER builder;
memset(&builder, 0, sizeof(builder));
KSTATUS status = NtlProcessBuilderPrepare(&builder, &builderRequest, fileHandle);
if (!KSUCCESS(status)) return status;
status = NtlProcessBuilderStart(&builder, request->ProcessHandleOut);
if (!KSUCCESS(status)) NtlProcessBuilderAbort(&builder);
return status;
}
// Creates and starts one child from a PE file beneath a capability-relative root.
KSTATUS NtlCreateProcessAt(const NTL_CREATE_PROCESS_AT_REQUEST* request) {
if (!request || request->Size != sizeof(*request) ||
@@ -165,6 +336,8 @@ KSTATUS NtlCreateProcessAt(const NTL_CREATE_PROCESS_AT_REQUEST* request) {
!SysSvIsValid(request->ModuleDirectory) ||
request->StartupCapabilityCount > SYS_STARTUP_CAPABILITY_MAX ||
(request->StartupCapabilityCount && !request->StartupCapabilities) ||
(request->Arguments.Count && !request->Arguments.Entries) ||
(request->Environment.Count && !request->Environment.Entries) ||
request->StartupDataSize > NTL_PROCESS_STARTUP_DATA_MAX ||
(request->StartupDataSize && !request->StartupData) ||
!request->ProcessHandleOut)
@@ -195,11 +368,23 @@ KSTATUS NtlCreateSystemProcess(const NTL_CREATE_SYSTEM_PROCESS_REQUEST* request)
if (!request || request->Size != sizeof(*request) ||
request->Flags != NTL_PROCESS_LOAD_FLAG_NONE || !request->Path.Data ||
request->Path.Length == 0 || request->StartupDataSize > NTL_PROCESS_STARTUP_DATA_MAX ||
(request->Arguments.Count && !request->Arguments.Entries) ||
(request->Environment.Count && !request->Environment.Entries) ||
(request->StartupDataSize && !request->StartupData) || !request->ProcessHandleOut)
return NTLSTATUS_INVALID_PARAMETER;
*request->ProcessHandleOut = SYS_HANDLE_INVALID;
char canonicalPath[SYS_PATH_MAX + 1u];
size_t canonicalSize = 0;
KSTATUS canonicalStatus = NtlRealPath(request->Path, canonicalPath, sizeof(canonicalPath),
&canonicalSize);
SYS_STRING_VIEW imagePath = request->Path;
if (KSUCCESS(canonicalStatus))
imagePath = SysSvFromParts(canonicalPath, canonicalSize - 1u);
else if (request->ImageFile == SYS_HANDLE_INVALID)
return canonicalStatus;
SYS_HANDLE systemRoot = SYS_HANDLE_INVALID;
KSTATUS status = NtlResourceOpenSystemRoot(SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN, &systemRoot);
if (!KSUCCESS(status)) return status;
@@ -209,7 +394,7 @@ KSTATUS NtlCreateSystemProcess(const NTL_CREATE_SYSTEM_PROCESS_REQUEST* request)
create.Size = sizeof(create);
create.Flags = request->Flags;
create.RootHandle = systemRoot;
create.Path = request->Path;
create.Path = imagePath;
create.CommandLine = request->CommandLine;
create.CurrentDirectory = request->CurrentDirectory;
create.SecurityContext = request->SecurityContext;
@@ -219,6 +404,8 @@ KSTATUS NtlCreateSystemProcess(const NTL_CREATE_SYSTEM_PROCESS_REQUEST* request)
create.ResolveContext = request->ResolveContext;
create.StartupCapabilities = request->StartupCapabilities;
create.StartupCapabilityCount = request->StartupCapabilityCount;
create.Arguments = request->Arguments;
create.Environment = request->Environment;
create.StartupData = request->StartupData;
create.StartupDataSize = request->StartupDataSize;
create.ProcessHandleOut = request->ProcessHandleOut;
@@ -226,7 +413,7 @@ KSTATUS NtlCreateSystemProcess(const NTL_CREATE_SYSTEM_PROCESS_REQUEST* request)
status = NtlCreateProcessFile(&create, request->ImageFile);
} else {
SYS_HANDLE imageFile = SYS_HANDLE_INVALID;
status = NtlOpenFile(request->Path, SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY,
status = NtlOpenFile(create.Path, SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY,
SYS_FILE_OPEN_EXISTING, SYS_FILE_FLAG_NONE, &imageFile);
if (KSUCCESS(status)) {
status = NtlCreateProcessFile(&create, imageFile);
+167 -161
View File
@@ -13,187 +13,193 @@ SYS_KILL_PROCESS EQU 8
SYS_GET_PROCESS_LIST EQU 9
SYS_GET_PROCESS_PID EQU 10
SYS_CREATE_THREAD EQU 11
SYS_RESUME_THREAD EQU 12
SYS_GET_THREAD_LIST EQU 13
SYS_GET_CURRENT_TID EQU 14
SYS_GET_CURRENT_PID EQU 15
SYS_SET_THREAD_PRIORITY EQU 16
SYS_SET_THREAD_NAME EQU 17
SYS_QUERY_THREAD_NAME EQU 18
SYS_YIELD EQU 19
SYS_SLEEP EQU 20
SYS_WAIT_SINGLE EQU 21
SYS_WAIT_MANY EQU 22
SYS_SET_USER_APC_DISPATCHER EQU 23
SYS_APC_RETURN EQU 24
SYS_SET_EXCEPTION_DISPATCHER EQU 25
SYS_GET_EXCEPTION_DISPATCHER EQU 26
SYS_CONTINUE_EXCEPTION EQU 27
SYS_RAISE_EXCEPTION EQU 28
SYS_OPEN_CURRENT_THREAD EQU 12
SYS_RESUME_THREAD EQU 13
SYS_RESUME_THREAD_AND_WAIT EQU 14
SYS_GET_THREAD_LIST EQU 15
SYS_GET_THREAD_TID EQU 16
SYS_GET_CURRENT_TID EQU 17
SYS_GET_CURRENT_PID EQU 18
SYS_SET_THREAD_PRIORITY EQU 19
SYS_SET_THREAD_NAME EQU 20
SYS_QUERY_THREAD_NAME EQU 21
SYS_YIELD EQU 22
SYS_SLEEP EQU 23
SYS_WAIT_SINGLE EQU 24
SYS_WAIT_MANY EQU 25
SYS_SET_USER_APC_DISPATCHER EQU 26
SYS_QUEUE_USER_APC EQU 27
SYS_APC_RETURN EQU 28
SYS_SET_EXCEPTION_DISPATCHER EQU 29
SYS_GET_EXCEPTION_DISPATCHER EQU 30
SYS_CONTINUE_EXCEPTION EQU 31
SYS_RAISE_EXCEPTION EQU 32
; Virtual memory, mappings, and handles.
SYS_ALLOC_VM EQU 29
SYS_FREE_VM EQU 30
SYS_PROTECT_VM EQU 31
SYS_QUERY_VM EQU 32
SYS_CLOSE_HANDLE EQU 33
SYS_DUPLICATE_HANDLE EQU 34
SYS_DERIVE_HANDLE EQU 35
SYS_REVOKE_HANDLE EQU 36
SYS_DERIVE_SECURITY_CONTEXT EQU 37
SYS_QUERY_SECURITY_CONTEXT EQU 38
SYS_CREATE_FILE_MAPPING EQU 39
SYS_MAP_FILE EQU 40
SYS_ALLOC_VM EQU 33
SYS_FREE_VM EQU 34
SYS_PROTECT_VM EQU 35
SYS_QUERY_VM EQU 36
SYS_CLOSE_HANDLE EQU 37
SYS_DUPLICATE_HANDLE EQU 38
SYS_DERIVE_HANDLE EQU 39
SYS_REVOKE_HANDLE EQU 40
SYS_DERIVE_SECURITY_CONTEXT EQU 41
SYS_QUERY_SECURITY_CONTEXT EQU 42
SYS_OPEN_PROCESS_SECURITY_CONTEXT EQU 43
SYS_CREATE_FILE_MAPPING EQU 44
SYS_MAP_FILE EQU 45
; Synchronization objects.
SYS_CREATE_MUTEX EQU 41
SYS_TRY_ACQUIRE_MUTEX EQU 42
SYS_RELEASE_MUTEX EQU 43
SYS_CREATE_SEM EQU 44
SYS_TRY_WAIT_SEM EQU 45
SYS_SIGNAL_SEM EQU 46
SYS_CREATE_EVENT EQU 47
SYS_SIGNAL_EVENT EQU 48
SYS_CLEAR_EVENT EQU 49
SYS_CREATE_MUTEX EQU 46
SYS_TRY_ACQUIRE_MUTEX EQU 47
SYS_RELEASE_MUTEX EQU 48
SYS_CREATE_SEM EQU 49
SYS_TRY_WAIT_SEM EQU 50
SYS_SIGNAL_SEM EQU 51
SYS_CREATE_EVENT EQU 52
SYS_SIGNAL_EVENT EQU 53
SYS_CLEAR_EVENT EQU 54
; Queues and named queues.
SYS_CREATE_QUEUE EQU 50
SYS_SEND_QUEUE EQU 51
SYS_RECV_QUEUE EQU 52
SYS_PUBLISH_QUEUE EQU 53
SYS_OPEN_NAMED_QUEUE EQU 54
SYS_OPEN_NAMED_QUEUE_OWNER_PROCESS EQU 55
SYS_UNPUBLISH_QUEUE EQU 56
SYS_CREATE_QUEUE EQU 55
SYS_SEND_QUEUE EQU 56
SYS_RECV_QUEUE EQU 57
SYS_PUBLISH_QUEUE EQU 58
SYS_OPEN_NAMED_QUEUE EQU 59
SYS_OPEN_NAMED_QUEUE_OWNER_PROCESS EQU 60
SYS_UNPUBLISH_QUEUE EQU 61
; LPC-like Ports and well-known system services.
SYS_CREATE_PORT EQU 57
SYS_CONNECT_PORT EQU 58
SYS_ACCEPT_PORT EQU 59
SYS_SEND_PORT EQU 60
SYS_RECEIVE_PORT EQU 61
SYS_CALL_PORT EQU 62
SYS_REPLY_PORT EQU 63
SYS_DISCONNECT_PORT EQU 64
SYS_REGISTER_SYSTEM_SERVICE EQU 65
SYS_UNREGISTER_SYSTEM_SERVICE EQU 66
SYS_CONNECT_SYSTEM_SERVICE EQU 67
SYS_CREATE_PORT EQU 62
SYS_CONNECT_PORT EQU 63
SYS_ACCEPT_PORT EQU 64
SYS_SEND_PORT EQU 65
SYS_RECEIVE_PORT EQU 66
SYS_CALL_PORT EQU 67
SYS_REPLY_PORT EQU 68
SYS_DISCONNECT_PORT EQU 69
SYS_OPEN_PORT_PEER_PROCESS EQU 70
SYS_REGISTER_SYSTEM_SERVICE EQU 71
SYS_UNREGISTER_SYSTEM_SERVICE EQU 72
SYS_CONNECT_SYSTEM_SERVICE EQU 73
; Mounted-volume manager control plane.
SYS_QUERY_VOLUMES EQU 68
SYS_OPEN_VOLUME EQU 69
SYS_WAIT_VOLUME_CHANGE EQU 70
SYS_QUERY_VOLUMES EQU 74
SYS_OPEN_VOLUME EQU 75
SYS_WAIT_VOLUME_CHANGE EQU 76
; Files and directories.
SYS_OPEN_FILE_AT EQU 71
SYS_OPEN_DIR_AT EQU 72
SYS_STAT_AT EQU 73
SYS_DELETE_AT EQU 74
SYS_RENAME_AT EQU 75
SYS_CREATE_DIR_AT EQU 76
SYS_REMOVE_DIR_AT EQU 77
SYS_READ_FILE EQU 78
SYS_WRITE_FILE EQU 79
SYS_READ_FILE_ASYNC EQU 80
SYS_WRITE_FILE_ASYNC EQU 81
SYS_CANCEL_IO EQU 82
SYS_SEEK_FILE EQU 83
SYS_GET_FILE_POS EQU 84
SYS_GET_FILE_SIZE EQU 85
SYS_GET_FILE_STAT EQU 86
SYS_TRUNCATE_FILE EQU 87
SYS_FLUSH_FILE EQU 88
SYS_LOCK_FILE EQU 89
SYS_UNLOCK_FILE EQU 90
SYS_QUERY_FILE_LOCK EQU 91
SYS_SET_FILE_STATUS EQU 92
SYS_CREATE_PIPE EQU 93
SYS_NOTIFY_PIPE EQU 94
SYS_READ_DIR EQU 95
SYS_OPEN_FILE_AT EQU 77
SYS_OPEN_DIR_AT EQU 78
SYS_STAT_AT EQU 79
SYS_DELETE_AT EQU 80
SYS_RENAME_AT EQU 81
SYS_CREATE_DIR_AT EQU 82
SYS_REMOVE_DIR_AT EQU 83
SYS_READ_FILE EQU 84
SYS_WRITE_FILE EQU 85
SYS_READ_FILE_ASYNC EQU 86
SYS_WRITE_FILE_ASYNC EQU 87
SYS_CANCEL_IO EQU 88
SYS_SEEK_FILE EQU 89
SYS_GET_FILE_POS EQU 90
SYS_GET_FILE_SIZE EQU 91
SYS_GET_FILE_STAT EQU 92
SYS_TRUNCATE_FILE EQU 93
SYS_FLUSH_FILE EQU 94
SYS_LOCK_FILE EQU 95
SYS_UNLOCK_FILE EQU 96
SYS_QUERY_FILE_LOCK EQU 97
SYS_SET_FILE_STATUS EQU 98
SYS_CREATE_PIPE EQU 99
SYS_NOTIFY_PIPE EQU 100
SYS_READ_DIR EQU 101
; Console, display, and surfaces.
SYS_WRITE_CONSOLE EQU 96
SYS_GET_CONSOLE_INFO EQU 97
SYS_SET_CONSOLE_CURSOR EQU 98
SYS_FILL_CONSOLE_CHARACTER EQU 99
SYS_FILL_CONSOLE_ATTRIBUTE EQU 100
SYS_PUT_SCREEN_CHAR EQU 101
SYS_CLEAR_SCREEN EQU 102
SYS_GET_SCREEN_SIZE EQU 103
SYS_QUERY_DISPLAY_INFO EQU 104
SYS_QUERY_DISPLAY_MANAGER_INFO EQU 105
SYS_PRESENT_DISPLAY_MANAGER_SURFACE EQU 106
SYS_SET_DISPLAY_MANAGER_CURSOR EQU 107
SYS_WRITE_DISPLAY_MANAGER_CONSOLE EQU 108
SYS_QUERY_DISPLAY_MANAGER_CONSOLE_INFO EQU 109
SYS_SET_DISPLAY_MANAGER_CONSOLE_CURSOR EQU 110
SYS_FILL_DISPLAY_MANAGER_CONSOLE_CHARACTER EQU 111
SYS_FILL_DISPLAY_MANAGER_CONSOLE_ATTRIBUTE EQU 112
SYS_PUT_DISPLAY_MANAGER_CONSOLE_CHARACTER EQU 113
SYS_CLEAR_DISPLAY_MANAGER_CONSOLE EQU 114
SYS_OPEN_DISPLAY_CLOCK EQU 115
SYS_CREATE_SURFACE EQU 116
SYS_MAP_SURFACE EQU 117
SYS_UNMAP_SURFACE EQU 118
SYS_QUERY_SURFACE EQU 119
SYS_COMMIT_SURFACE EQU 120
SYS_WRITE_CONSOLE EQU 102
SYS_GET_CONSOLE_INFO EQU 103
SYS_SET_CONSOLE_CURSOR EQU 104
SYS_FILL_CONSOLE_CHARACTER EQU 105
SYS_FILL_CONSOLE_ATTRIBUTE EQU 106
SYS_PUT_SCREEN_CHAR EQU 107
SYS_CLEAR_SCREEN EQU 108
SYS_GET_SCREEN_SIZE EQU 109
SYS_QUERY_DISPLAY_INFO EQU 110
SYS_QUERY_DISPLAY_MANAGER_INFO EQU 111
SYS_PRESENT_DISPLAY_MANAGER_SURFACE EQU 112
SYS_SET_DISPLAY_MANAGER_CURSOR EQU 113
SYS_WRITE_DISPLAY_MANAGER_CONSOLE EQU 114
SYS_QUERY_DISPLAY_MANAGER_CONSOLE_INFO EQU 115
SYS_SET_DISPLAY_MANAGER_CONSOLE_CURSOR EQU 116
SYS_FILL_DISPLAY_MANAGER_CONSOLE_CHARACTER EQU 117
SYS_FILL_DISPLAY_MANAGER_CONSOLE_ATTRIBUTE EQU 118
SYS_PUT_DISPLAY_MANAGER_CONSOLE_CHARACTER EQU 119
SYS_CLEAR_DISPLAY_MANAGER_CONSOLE EQU 120
SYS_OPEN_DISPLAY_CLOCK EQU 121
SYS_CREATE_SURFACE EQU 122
SYS_MAP_SURFACE EQU 123
SYS_UNMAP_SURFACE EQU 124
SYS_QUERY_SURFACE EQU 125
SYS_COMMIT_SURFACE EQU 126
; Native render audio.
SYS_AUDIO_ENUMERATE_ENDPOINTS EQU 121
SYS_AUDIO_OPEN_STREAM EQU 122
SYS_AUDIO_WRITE EQU 123
SYS_AUDIO_ARM_WAIT EQU 124
SYS_AUDIO_QUERY_STREAM EQU 125
SYS_AUDIO_START EQU 126
SYS_AUDIO_PAUSE EQU 127
SYS_AUDIO_RESUME EQU 128
SYS_AUDIO_DRAIN EQU 129
SYS_AUDIO_STOP EQU 130
SYS_AUDIO_RESET EQU 131
SYS_AUDIO_SET_VOLUME EQU 132
SYS_AUDIO_SET_MASTER_VOLUME EQU 133
SYS_AUDIO_ENUMERATE_ENDPOINTS EQU 127
SYS_AUDIO_OPEN_STREAM EQU 128
SYS_AUDIO_WRITE EQU 129
SYS_AUDIO_ARM_WAIT EQU 130
SYS_AUDIO_QUERY_STREAM EQU 131
SYS_AUDIO_START EQU 132
SYS_AUDIO_PAUSE EQU 133
SYS_AUDIO_RESUME EQU 134
SYS_AUDIO_DRAIN EQU 135
SYS_AUDIO_STOP EQU 136
SYS_AUDIO_RESET EQU 137
SYS_AUDIO_SET_VOLUME EQU 138
SYS_AUDIO_SET_MASTER_VOLUME EQU 139
; Input.
SYS_READ_INPUT_MANAGER_EVENT EQU 134
SYS_POLL_KEYBOARD EQU 135
SYS_IS_KEY_DOWN EQU 136
SYS_READ_KEYBOARD_CHAR EQU 137
SYS_READ_KEY EQU 138
SYS_GET_KEY_MODIFIERS EQU 139
SYS_QUERY_GLOBAL_INPUT_STATE EQU 140
SYS_OPEN_INPUT_QUEUE EQU 141
SYS_READ_INPUT_EVENT EQU 142
SYS_PEEK_INPUT_EVENT EQU 143
SYS_PEEK_MOUSE EQU 144
SYS_READ_MOUSE EQU 145
SYS_GET_MOUSE_POS EQU 146
SYS_READ_INPUT_MANAGER_EVENT EQU 140
SYS_POLL_KEYBOARD EQU 141
SYS_IS_KEY_DOWN EQU 142
SYS_READ_KEYBOARD_CHAR EQU 143
SYS_READ_KEY EQU 144
SYS_GET_KEY_MODIFIERS EQU 145
SYS_QUERY_GLOBAL_INPUT_STATE EQU 146
SYS_OPEN_INPUT_QUEUE EQU 147
SYS_READ_INPUT_EVENT EQU 148
SYS_PEEK_INPUT_EVENT EQU 149
SYS_PEEK_MOUSE EQU 150
SYS_READ_MOUSE EQU 151
SYS_GET_MOUSE_POS EQU 152
; Time, debug, and system information.
SYS_CREATE_TIMER EQU 147
SYS_SET_TIMER EQU 148
SYS_CANCEL_TIMER EQU 149
SYS_GET_TICK EQU 150
SYS_GET_TICK_FREQUENCY EQU 151
SYS_GET_SYSTEM_TIME EQU 152
SYS_PRINT_DEBUG EQU 153
SYS_QUERY_TRAP_FRAME EQU 154
SYS_GET_MEMORY_STATUS EQU 155
SYS_QUERY_KERNEL_STATS EQU 156
SYS_CREATE_TIMER EQU 153
SYS_SET_TIMER EQU 154
SYS_CANCEL_TIMER EQU 155
SYS_GET_TICK EQU 156
SYS_GET_TICK_FREQUENCY EQU 157
SYS_GET_SYSTEM_TIME EQU 158
SYS_PRINT_DEBUG EQU 159
SYS_QUERY_TRAP_FRAME EQU 160
SYS_GET_MEMORY_STATUS EQU 161
SYS_QUERY_KERNEL_STATS EQU 162
; Native sockets and polling.
SYS_CREATE_SOCKET EQU 157
SYS_SOCKET_IO_ASYNC EQU 158
SYS_BIND_SOCKET EQU 159
SYS_LISTEN_SOCKET EQU 160
SYS_ACCEPT_SOCKET EQU 161
SYS_CONNECT_SOCKET EQU 162
SYS_SEND_SOCKET EQU 163
SYS_RECV_SOCKET EQU 164
SYS_SHUTDOWN_SOCKET EQU 165
SYS_SEND_TO_SOCKET EQU 166
SYS_RECV_FROM_SOCKET EQU 167
SYS_RESOLVE_HOST EQU 168
SYS_SET_SOCKET_OPTION EQU 169
SYS_GET_SOCKET_OPTION EQU 170
SYS_POLL EQU 171
SYS_CREATE_SOCKET EQU 163
SYS_SOCKET_IO_ASYNC EQU 164
SYS_BIND_SOCKET EQU 165
SYS_LISTEN_SOCKET EQU 166
SYS_ACCEPT_SOCKET EQU 167
SYS_CONNECT_SOCKET EQU 168
SYS_SEND_SOCKET EQU 169
SYS_RECV_SOCKET EQU 170
SYS_SHUTDOWN_SOCKET EQU 171
SYS_SEND_TO_SOCKET EQU 172
SYS_RECV_FROM_SOCKET EQU 173
SYS_RESOLVE_HOST EQU 174
SYS_SET_SOCKET_OPTION EQU 175
SYS_GET_SOCKET_OPTION EQU 176
SYS_POLL EQU 177
SYS_MAX EQU 172
SYS_MAX EQU 178
+6
View File
@@ -53,9 +53,12 @@ SYSCALL_STUB KillProcess, SYS_KILL_PROCESS
SYSCALL_STUB GetProcessList, SYS_GET_PROCESS_LIST
SYSCALL_STUB GetProcessPid, SYS_GET_PROCESS_PID
SYSCALL_STUB GetThreadList, SYS_GET_THREAD_LIST
SYSCALL_STUB GetThreadTid, SYS_GET_THREAD_TID
SYSCALL_STUB CreateThread, SYS_CREATE_THREAD
SYSCALL_STUB OpenCurrentThread, SYS_OPEN_CURRENT_THREAD
SYSCALL_STUB ResumeThread, SYS_RESUME_THREAD
SYSCALL_STUB ResumeThreadAndWait, SYS_RESUME_THREAD_AND_WAIT
SYSCALL_STUB GetCurrentTid, SYS_GET_CURRENT_TID
SYSCALL_STUB GetCurrentPid, SYS_GET_CURRENT_PID
SYSCALL_STUB SetThreadPriority, SYS_SET_THREAD_PRIORITY
@@ -64,6 +67,7 @@ SYSCALL_STUB QueryThreadName, SYS_QUERY_THREAD_NAME
SYSCALL_STUB Yield, SYS_YIELD
SYSCALL_STUB Sleep, SYS_SLEEP
SYSCALL_STUB SetUserApcDispatcher, SYS_SET_USER_APC_DISPATCHER
SYSCALL_STUB QueueUserApc, SYS_QUEUE_USER_APC
SYSCALL_STUB ApcReturn, SYS_APC_RETURN
SYSCALL_STUB SetExceptionDispatcher, SYS_SET_EXCEPTION_DISPATCHER
SYSCALL_STUB GetExceptionDispatcher, SYS_GET_EXCEPTION_DISPATCHER
@@ -116,6 +120,7 @@ SYSCALL_STUB DeriveHandle, SYS_DERIVE_HANDLE
SYSCALL_STUB RevokeHandle, SYS_REVOKE_HANDLE
SYSCALL_STUB DeriveSecurityContext, SYS_DERIVE_SECURITY_CONTEXT
SYSCALL_STUB QuerySecurityContext, SYS_QUERY_SECURITY_CONTEXT
SYSCALL_STUB OpenProcessSecurityContext, SYS_OPEN_PROCESS_SECURITY_CONTEXT
; ---------------------------------------------------------------------------
; Synchronization objects
@@ -155,6 +160,7 @@ SYSCALL_STUB ReceivePort, SYS_RECEIVE_PORT
SYSCALL_STUB CallPort, SYS_CALL_PORT
SYSCALL_STUB ReplyPort, SYS_REPLY_PORT
SYSCALL_STUB DisconnectPort, SYS_DISCONNECT_PORT
SYSCALL_STUB OpenPortPeerProcess, SYS_OPEN_PORT_PEER_PROCESS
SYSCALL_STUB RegisterSystemService, SYS_REGISTER_SYSTEM_SERVICE
SYSCALL_STUB UnregisterSystemService, SYS_UNREGISTER_SYSTEM_SERVICE
SYSCALL_STUB ConnectSystemService, SYS_CONNECT_SYSTEM_SERVICE