implement proper IRQL, DPCs, kernel and user APCs, alertable waits, async file I/O with cancellation, trap frames, selftests, a real driver/device model, native async FAT32, VFAT dotfile fixes, syscall ABI cleanup, async_apc and async_cancel tests, POSIX multi-volume paths, and pimp the readme.
This commit is contained in:
1 parent
f5fd7bdd75
commit
529f816166
75 files changed
+9969
-5675
No files matched your search
+383
-125
@@ -23,7 +23,7 @@
|
||||
//
|
||||
// KeCloseHandle(proc, handle)
|
||||
// -> ObDereferenceObject(obj)
|
||||
// -> obj->Destroy(obj) [type-specific cleanup, e.g. FileDestroy]
|
||||
// -> obj->Destroy(obj) [type-specific cleanup, e.g. KiFileDestroy]
|
||||
// -> MmFreePool(obj)
|
||||
//
|
||||
// There is no separate SyscallCloseFile. Removing that stub was the right
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <ke_mutex.h>
|
||||
#include <ke_semaphore.h>
|
||||
#include <ke_event.h>
|
||||
#include <ke_apc.h>
|
||||
#include <ke_queue.h>
|
||||
#include <ke_debug.h>
|
||||
#include <mm_virt.h>
|
||||
@@ -46,12 +47,43 @@
|
||||
#include <syscall_nr.h>
|
||||
#include <hal_api.h>
|
||||
#include <io_file.h>
|
||||
#include <ke_trap.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// HAL pointer - set once at boot by KeSyscallSetHal()
|
||||
// ---------------------------------------------------------------------------
|
||||
static const HAL_API* gHal;
|
||||
|
||||
typedef struct SYS_IO_STATUS_BLOCK_K {
|
||||
volatile uint32_t Status;
|
||||
volatile uint64_t Information;
|
||||
} SYS_IO_STATUS_BLOCK_K;
|
||||
|
||||
typedef void (*SYS_USER_APC_ROUTINE_K)(void* normalContext,
|
||||
SYS_IO_STATUS_BLOCK_K* iosb,
|
||||
uint64_t information);
|
||||
|
||||
typedef struct SYS_ASYNC_FILE_REQUEST_K {
|
||||
uint32_t FileHandle;
|
||||
uint32_t EventHandle;
|
||||
uint32_t Flags;
|
||||
uint32_t Reserved;
|
||||
uint64_t Offset;
|
||||
void* Buffer;
|
||||
size_t Size;
|
||||
SYS_IO_STATUS_BLOCK_K* Iosb;
|
||||
SYS_USER_APC_ROUTINE_K ApcRoutine;
|
||||
void* ApcContext;
|
||||
uint32_t* RequestHandleOut; // optional cancellation/query handle output
|
||||
} SYS_ASYNC_FILE_REQUEST_K;
|
||||
|
||||
typedef struct SYS_USER_ASYNC_APC_CONTEXT {
|
||||
KAPC KernelApc;
|
||||
THREAD* TargetThread;
|
||||
SYS_USER_APC_ROUTINE_K UserRoutine;
|
||||
void* UserContext;
|
||||
} SYS_USER_ASYNC_APC_CONTEXT;
|
||||
|
||||
void KeSyscallSetHal(const HAL_API* hal) { gHal = hal; }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -59,7 +91,7 @@ void KeSyscallSetHal(const HAL_API* hal) { gHal = hal; }
|
||||
// Bumps the refcount on success; caller must ObDereferenceObject when done.
|
||||
// Returns NULL if the handle is invalid or the type does not match.
|
||||
// ---------------------------------------------------------------------------
|
||||
static OBJECT* HandleToObject(uint32_t handle, OBJECT_TYPE expected) {
|
||||
static OBJECT* KiHandleToObject(uint32_t handle, OBJECT_TYPE expected) {
|
||||
PROCESS* proc = KeGetCurrentProcess();
|
||||
if (!proc) return NULL;
|
||||
OBJECT* obj = KeLookupHandle(proc, handle); // bumps refcount
|
||||
@@ -76,7 +108,7 @@ static OBJECT* HandleToObject(uint32_t handle, OBJECT_TYPE expected) {
|
||||
// Takes one reference on behalf of the handle slot.
|
||||
// On failure, drops the reference it would have stored.
|
||||
// ---------------------------------------------------------------------------
|
||||
static KSTATUS AllocHandleForCurrent(OBJECT* obj, uint32_t* handleOut) {
|
||||
static KSTATUS KiAllocHandleForCurrent(OBJECT* obj, uint32_t* handleOut) {
|
||||
PROCESS* proc = KeGetCurrentProcess();
|
||||
if (!proc) return STATUS_FAILURE;
|
||||
KSTATUS s = KeAllocateHandle(proc, obj, handleOut);
|
||||
@@ -173,6 +205,24 @@ static uint64_t SyscallSleep(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_SET_USER_APC_DISPATCHER a0 = dispatcher entry in syscall.dll/user image
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallSetUserApcDispatcher(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
return KeSetUserApcDispatcher((void*)(uintptr_t)a0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_APC_RETURN a0 = SYS_USER_APC_FRAME* on the user stack
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallApcReturn(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
return KeUserApcReturn((const SYS_USER_APC_FRAME_K*)(uintptr_t)a0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_SET_THREAD_PRIORITY (7) a0 = priority
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -197,12 +247,12 @@ static uint64_t SyscallAlloc(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_FREE (9) a0 = ptr, a1 = size
|
||||
// SYS_FREE a0 = ptr
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallFree(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
if (a0) MmFreeUserMemory((void*)(uintptr_t)a0, (size_t)a1);
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
if (a0) MmFreeUserMemory((void*)(uintptr_t)a0);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -224,10 +274,10 @@ static uint64_t SyscallMutexCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
if (!a0) return STATUS_INVALID_PARAMETER;
|
||||
MUTEX* mx = NULL;
|
||||
KSTATUS s = MutexCreate(&mx);
|
||||
KSTATUS s = KeMutexCreate(&mx);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
uint32_t h = 0;
|
||||
s = AllocHandleForCurrent(&mx->Header, &h); // takes ownership of the ref
|
||||
s = KiAllocHandleForCurrent(&mx->Header, &h); // takes ownership of the ref
|
||||
if (!KSUCCESS(s)) return s;
|
||||
*(uint32_t*)(uintptr_t)a0 = h;
|
||||
return STATUS_SUCCESS;
|
||||
@@ -239,7 +289,7 @@ static uint64_t SyscallMutexCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallMutexAcquire(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
MUTEX* mx = (MUTEX*)HandleToObject((uint32_t)a0, ObjectTypeMutex);
|
||||
MUTEX* mx = (MUTEX*)KiHandleToObject((uint32_t)a0, ObjectTypeMutex);
|
||||
if (!mx) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = KeAcquireMutex(mx);
|
||||
ObDereferenceObject(&mx->Header);
|
||||
@@ -252,7 +302,7 @@ static uint64_t SyscallMutexAcquire(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallMutexTryAcquire(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
MUTEX* mx = (MUTEX*)HandleToObject((uint32_t)a0, ObjectTypeMutex);
|
||||
MUTEX* mx = (MUTEX*)KiHandleToObject((uint32_t)a0, ObjectTypeMutex);
|
||||
if (!mx) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = KeTryAcquireMutex(mx);
|
||||
ObDereferenceObject(&mx->Header);
|
||||
@@ -265,7 +315,7 @@ static uint64_t SyscallMutexTryAcquire(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallMutexRelease(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
MUTEX* mx = (MUTEX*)HandleToObject((uint32_t)a0, ObjectTypeMutex);
|
||||
MUTEX* mx = (MUTEX*)KiHandleToObject((uint32_t)a0, ObjectTypeMutex);
|
||||
if (!mx) return STATUS_NOT_FOUND;
|
||||
KeReleaseMutex(mx);
|
||||
ObDereferenceObject(&mx->Header);
|
||||
@@ -283,7 +333,7 @@ static uint64_t SyscallSemCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
KSTATUS s = KeSemaphoreCreate((int32_t)a0, (int32_t)a1, &sem);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
uint32_t h = 0;
|
||||
s = AllocHandleForCurrent(&sem->Header, &h);
|
||||
s = KiAllocHandleForCurrent(&sem->Header, &h);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
*(uint32_t*)(uintptr_t)a2 = h;
|
||||
return STATUS_SUCCESS;
|
||||
@@ -295,7 +345,7 @@ static uint64_t SyscallSemCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallSemWait(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
SEMAPHORE* sem = (SEMAPHORE*)HandleToObject((uint32_t)a0, ObjectTypeSemaphore);
|
||||
SEMAPHORE* sem = (SEMAPHORE*)KiHandleToObject((uint32_t)a0, ObjectTypeSemaphore);
|
||||
if (!sem) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = KeWaitSemaphore(sem);
|
||||
ObDereferenceObject(&sem->Header);
|
||||
@@ -308,7 +358,7 @@ static uint64_t SyscallSemWait(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallSemTryWait(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
SEMAPHORE* sem = (SEMAPHORE*)HandleToObject((uint32_t)a0, ObjectTypeSemaphore);
|
||||
SEMAPHORE* sem = (SEMAPHORE*)KiHandleToObject((uint32_t)a0, ObjectTypeSemaphore);
|
||||
if (!sem) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = KeTrySemaphore(sem);
|
||||
ObDereferenceObject(&sem->Header);
|
||||
@@ -321,7 +371,7 @@ static uint64_t SyscallSemTryWait(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallSemSignal(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
SEMAPHORE* sem = (SEMAPHORE*)HandleToObject((uint32_t)a0, ObjectTypeSemaphore);
|
||||
SEMAPHORE* sem = (SEMAPHORE*)KiHandleToObject((uint32_t)a0, ObjectTypeSemaphore);
|
||||
if (!sem) return STATUS_NOT_FOUND;
|
||||
KeSignalSemaphore(sem);
|
||||
ObDereferenceObject(&sem->Header);
|
||||
@@ -339,7 +389,7 @@ static uint64_t SyscallEventCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
KSTATUS s = KeEventCreate((EVENT_TYPE)a0, (uint32_t)a1, &ev);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
uint32_t h = 0;
|
||||
s = AllocHandleForCurrent(&ev->Header, &h);
|
||||
s = KiAllocHandleForCurrent(&ev->Header, &h);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
*(uint32_t*)(uintptr_t)a2 = h;
|
||||
return STATUS_SUCCESS;
|
||||
@@ -351,7 +401,7 @@ static uint64_t SyscallEventCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallEventSignal(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
EVENT* ev = (EVENT*)HandleToObject((uint32_t)a0, ObjectTypeEvent);
|
||||
EVENT* ev = (EVENT*)KiHandleToObject((uint32_t)a0, ObjectTypeEvent);
|
||||
if (!ev) return STATUS_NOT_FOUND;
|
||||
KeSignalEvent(ev);
|
||||
ObDereferenceObject(&ev->Header);
|
||||
@@ -364,7 +414,7 @@ static uint64_t SyscallEventSignal(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallEventClear(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
EVENT* ev = (EVENT*)HandleToObject((uint32_t)a0, ObjectTypeEvent);
|
||||
EVENT* ev = (EVENT*)KiHandleToObject((uint32_t)a0, ObjectTypeEvent);
|
||||
if (!ev) return STATUS_NOT_FOUND;
|
||||
KeClearEvent(ev);
|
||||
ObDereferenceObject(&ev->Header);
|
||||
@@ -372,14 +422,20 @@ static uint64_t SyscallEventClear(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_EVENT_WAIT (22) a0 = handle
|
||||
// SYS_EVENT_WAIT a0 = handle, a1 = alertable
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallEventWait(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
EVENT* ev = (EVENT*)HandleToObject((uint32_t)a0, ObjectTypeEvent);
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
EVENT* ev = (EVENT*)KiHandleToObject((uint32_t)a0, ObjectTypeEvent);
|
||||
if (!ev) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = KeWaitForEvent(ev);
|
||||
uint8_t alertable = a1 ? 1 : 0;
|
||||
KSTATUS s = KeWaitForEvent(ev, alertable);
|
||||
if (alertable) {
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
if (thread && thread->UserApcPending)
|
||||
thread->UserApcDeliverable = 1;
|
||||
}
|
||||
ObDereferenceObject(&ev->Header);
|
||||
return s;
|
||||
}
|
||||
@@ -392,10 +448,10 @@ static uint64_t SyscallQueueCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
if (!a0) return STATUS_INVALID_PARAMETER;
|
||||
QUEUE* q = NULL;
|
||||
KSTATUS s = QueueCreate(&q);
|
||||
KSTATUS s = KeQueueCreate(&q);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
uint32_t h = 0;
|
||||
s = AllocHandleForCurrent(&q->Header, &h);
|
||||
s = KiAllocHandleForCurrent(&q->Header, &h);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
*(uint32_t*)(uintptr_t)a0 = h;
|
||||
return STATUS_SUCCESS;
|
||||
@@ -408,7 +464,7 @@ static uint64_t SyscallQueueSend(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
if (!a1) return STATUS_INVALID_PARAMETER;
|
||||
QUEUE* q = (QUEUE*)HandleToObject((uint32_t)a0, ObjectTypeQueue);
|
||||
QUEUE* q = (QUEUE*)KiHandleToObject((uint32_t)a0, ObjectTypeQueue);
|
||||
if (!q) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = KeSendMessage(q, (const QUEUE_MESSAGE*)(uintptr_t)a1, (bool)a2);
|
||||
ObDereferenceObject(&q->Header);
|
||||
@@ -422,7 +478,7 @@ static uint64_t SyscallQueueRecv(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
if (!a1) return STATUS_INVALID_PARAMETER;
|
||||
QUEUE* q = (QUEUE*)HandleToObject((uint32_t)a0, ObjectTypeQueue);
|
||||
QUEUE* q = (QUEUE*)KiHandleToObject((uint32_t)a0, ObjectTypeQueue);
|
||||
if (!q) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = KeReceiveMessage(q, (QUEUE_MESSAGE*)(uintptr_t)a1, (bool)a2);
|
||||
ObDereferenceObject(&q->Header);
|
||||
@@ -434,7 +490,7 @@ static uint64_t SyscallQueueRecv(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
//
|
||||
// The one and only close path. KeCloseHandle drops the handle-table reference
|
||||
// on 'obj'. If that was the last reference, ObDereferenceObject runs the
|
||||
// type-specific Destroy callback (FileDestroy, etc.) and frees the pool memory.
|
||||
// type-specific Destroy callback (KiFileDestroy, etc.) and frees the pool memory.
|
||||
// No per-type close syscall needed or wanted.
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallCloseHandle(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
@@ -457,10 +513,10 @@ static uint64_t SyscallOpenFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
KSTATUS s = IoOpenFile((const char*)(uintptr_t)a0, &file);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
uint32_t h = 0;
|
||||
s = AllocHandleForCurrent(&file->Header, &h);
|
||||
s = KiAllocHandleForCurrent(&file->Header, &h);
|
||||
if (!KSUCCESS(s)) {
|
||||
// AllocHandleForCurrent already dropped the ref on failure;
|
||||
// the refcount is now 0, so ObDereferenceObject will run FileDestroy.
|
||||
// KiAllocHandleForCurrent already dropped the ref on failure;
|
||||
// the refcount is now 0, so ObDereferenceObject will run KiFileDestroy.
|
||||
ObDereferenceObject(&file->Header);
|
||||
return s;
|
||||
}
|
||||
@@ -475,7 +531,7 @@ static uint64_t SyscallReadFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a4; (void)a5;
|
||||
if (!a1) return STATUS_INVALID_PARAMETER;
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)KiHandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
if (!file) return STATUS_NOT_FOUND;
|
||||
size_t got = 0;
|
||||
KSTATUS s = IoReadFile(file, (void*)(uintptr_t)a1, (size_t)a2, &got);
|
||||
@@ -491,7 +547,7 @@ static uint64_t SyscallWriteFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a4; (void)a5;
|
||||
if (!a1) return STATUS_INVALID_PARAMETER;
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)KiHandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
if (!file) return STATUS_NOT_FOUND;
|
||||
size_t written = 0;
|
||||
KSTATUS s = IoWriteFile(file, (const void*)(uintptr_t)a1, (size_t)a2, &written);
|
||||
@@ -500,6 +556,189 @@ static uint64_t SyscallWriteFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
return s;
|
||||
}
|
||||
|
||||
static void SyscallUserAsyncKernelRoutine(KAPC* apc,
|
||||
void** normalRoutine,
|
||||
void** normalContext,
|
||||
void** systemArgument1,
|
||||
void** systemArgument2) {
|
||||
(void)normalRoutine;
|
||||
(void)normalContext;
|
||||
(void)systemArgument1;
|
||||
(void)systemArgument2;
|
||||
|
||||
SYS_USER_ASYNC_APC_CONTEXT* ctx = CONTAINING_RECORD(apc, SYS_USER_ASYNC_APC_CONTEXT, KernelApc);
|
||||
DbgPrint("USER/APC async: kernel routine ctx=0x%llX iosb=0x%llX status=%u info=%llu irql=%u\n",
|
||||
(uint64_t)ctx,
|
||||
(uint64_t)(uintptr_t)apc->SystemArgument1,
|
||||
(uint32_t)(uintptr_t)apc->SystemArgument2,
|
||||
apc->SystemArgument1 ? ((SYS_IO_STATUS_BLOCK_K*)apc->SystemArgument1)->Information : 0,
|
||||
KeGetCurrentIrql());
|
||||
}
|
||||
|
||||
static void SyscallUserAsyncApcContextFree(SYS_USER_ASYNC_APC_CONTEXT* ctx) {
|
||||
if (!ctx) return;
|
||||
if (ctx->TargetThread) {
|
||||
ObDereferenceObject(&ctx->TargetThread->Header);
|
||||
ctx->TargetThread = (THREAD*)0;
|
||||
}
|
||||
MmFreePool(ctx);
|
||||
}
|
||||
|
||||
static void SyscallUserAsyncApcRundown(KAPC* apc) {
|
||||
if (!apc) return;
|
||||
SYS_USER_ASYNC_APC_CONTEXT* ctx = CONTAINING_RECORD(apc, SYS_USER_ASYNC_APC_CONTEXT, KernelApc);
|
||||
SyscallUserAsyncApcContextFree(ctx);
|
||||
}
|
||||
|
||||
static void SyscallUserAsyncNormalRoutine(void* normalContext,
|
||||
void* systemArgument1,
|
||||
void* systemArgument2) {
|
||||
SYS_USER_ASYNC_APC_CONTEXT* ctx = (SYS_USER_ASYNC_APC_CONTEXT*)normalContext;
|
||||
SYS_IO_STATUS_BLOCK_K* iosb = (SYS_IO_STATUS_BLOCK_K*)systemArgument1;
|
||||
uint64_t information = iosb ? iosb->Information : 0;
|
||||
(void)systemArgument2;
|
||||
|
||||
if (ctx && ctx->UserRoutine) {
|
||||
KSTATUS s = KeQueueUserApc(ctx->TargetThread,
|
||||
(void*)ctx->UserRoutine,
|
||||
ctx->UserContext,
|
||||
iosb,
|
||||
(void*)(uintptr_t)information);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("USER/APC async: KeQueueUserApc failed status=%u\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
SyscallUserAsyncApcContextFree(ctx);
|
||||
}
|
||||
|
||||
static uint64_t SyscallAsyncFileCommon(uint64_t a0, bool write) {
|
||||
if (!a0) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
const SYS_ASYNC_FILE_REQUEST_K* req =
|
||||
(const SYS_ASYNC_FILE_REQUEST_K*)(uintptr_t)a0;
|
||||
|
||||
if (req->Flags || req->Reserved) return STATUS_INVALID_PARAMETER;
|
||||
if (!req->Iosb) return STATUS_INVALID_PARAMETER;
|
||||
if (!req->Buffer && req->Size) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
FILE_OBJECT* file =
|
||||
(FILE_OBJECT*)KiHandleToObject(req->FileHandle, ObjectTypeFile);
|
||||
if (!file) return STATUS_NOT_FOUND;
|
||||
|
||||
EVENT* event = (EVENT*)0;
|
||||
if (req->EventHandle) {
|
||||
event = (EVENT*)KiHandleToObject(req->EventHandle, ObjectTypeEvent);
|
||||
if (!event) {
|
||||
ObDereferenceObject(&file->Header);
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
KAPC* completionApc = (KAPC*)0;
|
||||
SYS_USER_ASYNC_APC_CONTEXT* apcCtx = (SYS_USER_ASYNC_APC_CONTEXT*)0;
|
||||
if (req->ApcRoutine) {
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
if (!thread || !thread->UserApcDispatcher) {
|
||||
if (event) ObDereferenceObject(&event->Header);
|
||||
ObDereferenceObject(&file->Header);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
apcCtx = (SYS_USER_ASYNC_APC_CONTEXT*)MmAllocatePool(sizeof(SYS_USER_ASYNC_APC_CONTEXT));
|
||||
if (!apcCtx) {
|
||||
if (event) ObDereferenceObject(&event->Header);
|
||||
ObDereferenceObject(&file->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(apcCtx, 0, sizeof(*apcCtx));
|
||||
ObReferenceObject(&thread->Header);
|
||||
apcCtx->TargetThread = thread;
|
||||
apcCtx->UserRoutine = req->ApcRoutine;
|
||||
apcCtx->UserContext = req->ApcContext;
|
||||
KeInitializeApc(&apcCtx->KernelApc,
|
||||
thread,
|
||||
SyscallUserAsyncKernelRoutine,
|
||||
SyscallUserAsyncNormalRoutine,
|
||||
apcCtx);
|
||||
KeSetApcRundownRoutine(&apcCtx->KernelApc, SyscallUserAsyncApcRundown);
|
||||
completionApc = &apcCtx->KernelApc;
|
||||
}
|
||||
|
||||
IO_ASYNC_FILE_REQUEST_OBJECT* asyncReq = (IO_ASYNC_FILE_REQUEST_OBJECT*)0;
|
||||
KSTATUS s;
|
||||
if (write) {
|
||||
s = IoWriteFileAsyncKernel(file, req->Buffer, req->Size, req->Offset,
|
||||
(IO_STATUS_BLOCK*)req->Iosb, event,
|
||||
completionApc,
|
||||
&asyncReq);
|
||||
} else {
|
||||
s = IoReadFileAsyncKernel(file, req->Buffer, req->Size, req->Offset,
|
||||
(IO_STATUS_BLOCK*)req->Iosb, event,
|
||||
completionApc,
|
||||
&asyncReq);
|
||||
}
|
||||
|
||||
if (s == STATUS_PENDING && req->RequestHandleOut && asyncReq) {
|
||||
uint32_t requestHandle = 0;
|
||||
KSTATUS hs = KiAllocHandleForCurrent(IoAsyncFileRequestObject(asyncReq), &requestHandle);
|
||||
if (!KSUCCESS(hs)) {
|
||||
(void)IoCancelAsyncFileRequest(asyncReq);
|
||||
ObDereferenceObject(IoAsyncFileRequestObject(asyncReq));
|
||||
if (event) ObDereferenceObject(&event->Header);
|
||||
ObDereferenceObject(&file->Header);
|
||||
return hs;
|
||||
}
|
||||
*req->RequestHandleOut = requestHandle;
|
||||
} else if (req->RequestHandleOut) {
|
||||
*req->RequestHandleOut = 0;
|
||||
}
|
||||
|
||||
if (asyncReq)
|
||||
ObDereferenceObject(IoAsyncFileRequestObject(asyncReq)); // drop creator reference
|
||||
|
||||
if (!KSUCCESS(s) && s != STATUS_PENDING && apcCtx)
|
||||
SyscallUserAsyncApcContextFree(apcCtx);
|
||||
|
||||
if (event) ObDereferenceObject(&event->Header);
|
||||
ObDereferenceObject(&file->Header);
|
||||
return s;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_READ_FILE_ASYNC (43) a0=*SYS_ASYNC_FILE_REQUEST
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallReadFileAsync(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
return SyscallAsyncFileCommon(a0, false);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_WRITE_FILE_ASYNC (44) a0=*SYS_ASYNC_FILE_REQUEST
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallWriteFileAsync(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
return SyscallAsyncFileCommon(a0, true);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_CANCEL_IO a0 = async request handle
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallCancelIo(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
IO_ASYNC_FILE_REQUEST_OBJECT* req =
|
||||
(IO_ASYNC_FILE_REQUEST_OBJECT*)KiHandleToObject((uint32_t)a0, ObjectTypeAsyncIo);
|
||||
if (!req) return STATUS_INVALID_HANDLE;
|
||||
|
||||
KSTATUS s = IoCancelAsyncFileRequest(req);
|
||||
ObDereferenceObject(IoAsyncFileRequestObject(req));
|
||||
return s;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_CREATE_FILE (30) a0=*path a1=*handleOut
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -511,7 +750,7 @@ static uint64_t SyscallCreateFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
KSTATUS s = IoCreateFile((const char*)(uintptr_t)a0, &file);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
uint32_t h = 0;
|
||||
s = AllocHandleForCurrent(&file->Header, &h);
|
||||
s = KiAllocHandleForCurrent(&file->Header, &h);
|
||||
if (!KSUCCESS(s)) {
|
||||
ObDereferenceObject(&file->Header);
|
||||
return s;
|
||||
@@ -536,7 +775,7 @@ static uint64_t SyscallDeleteFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallTruncateFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)KiHandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
if (!file) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = IoTruncateFile(file, (uint64_t)a1);
|
||||
ObDereferenceObject(&file->Header);
|
||||
@@ -549,9 +788,11 @@ static uint64_t SyscallTruncateFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallGetFilePos(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)KiHandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
if (!file) return (uint64_t)-1;
|
||||
uintptr_t flags = KeAcquireSpinlock(&file->Lock);
|
||||
uint64_t pos = file->Offset;
|
||||
KeReleaseSpinlock(&file->Lock, flags);
|
||||
ObDereferenceObject(&file->Header);
|
||||
return pos;
|
||||
}
|
||||
@@ -562,7 +803,7 @@ static uint64_t SyscallGetFilePos(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallSeekFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)KiHandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
if (!file) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = IoSeekFile(file, (uint64_t)a1);
|
||||
ObDereferenceObject(&file->Header);
|
||||
@@ -575,7 +816,7 @@ static uint64_t SyscallSeekFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
static uint64_t SyscallGetFileSize(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
FILE_OBJECT* file = (FILE_OBJECT*)KiHandleToObject((uint32_t)a0, ObjectTypeFile);
|
||||
if (!file) return 0;
|
||||
uint64_t sz = IoGetFileSize(file);
|
||||
ObDereferenceObject(&file->Header);
|
||||
@@ -738,6 +979,15 @@ static uint64_t SyscallDebugPrint(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_QUERY_TRAP_FRAME a0=*SYS_TRAP_FRAME_INFO
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallQueryTrapFrame(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
return KeQueryCurrentTrapFrame((SYS_TRAP_FRAME_INFO_K*)(uintptr_t)a0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_CREATE_PROCESS (50) a0=*path a1=*handleOut a2=*cmdline (optional)
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -775,6 +1025,7 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uintptr_t flags = KeAcquireSpinlock(&parent->CwdLock);
|
||||
strncpy(proc->CurrentDirectory, parent->CurrentDirectory, sizeof(proc->CurrentDirectory) - 1);
|
||||
proc->CurrentDirectory[sizeof(proc->CurrentDirectory) - 1] = '\0';
|
||||
proc->CurrentDrive = parent->CurrentDrive;
|
||||
KeReleaseSpinlock(&parent->CwdLock, flags);
|
||||
}
|
||||
|
||||
@@ -789,7 +1040,7 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
|
||||
s = LdrResolveImportsForProcess(proc, imageBase);
|
||||
if (!KSUCCESS(s)) {
|
||||
MmFreeUserMemory((void*)imageBase, LdrGetImageSize(imageBase));
|
||||
MmFreeUserMemory((void*)imageBase);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return s;
|
||||
}
|
||||
@@ -802,7 +1053,7 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
// to finish wiring it up.
|
||||
PROCESS* caller = KeGetCurrentProcess();
|
||||
if (!caller) {
|
||||
MmFreeUserMemory((void*)imageBase, proc->ImageSize);
|
||||
MmFreeUserMemory((void*)imageBase);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
@@ -813,7 +1064,7 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
KeCloseHandle(caller, handle);
|
||||
proc->ImageBase = 0;
|
||||
proc->ImageSize = 0;
|
||||
MmFreeUserMemory((void*)imageBase, proc->ImageSize);
|
||||
MmFreeUserMemory((void*)imageBase);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return s;
|
||||
}
|
||||
@@ -825,7 +1076,7 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uintptr_t entryPoint = LdrGetEntryPoint(imageBase);
|
||||
s = KeCreateThread(proc, entryPoint, 0, PriorityNormal, &thread);
|
||||
if (!KSUCCESS(s)) {
|
||||
MmFreeUserMemory((void*)imageBase, LdrGetImageSize(imageBase));
|
||||
MmFreeUserMemory((void*)imageBase);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return s;
|
||||
}
|
||||
@@ -841,10 +1092,10 @@ static uint64_t SyscallWaitForProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
|
||||
PROCESS* proc = (PROCESS*)HandleToObject((uint32_t)a0, ObjectTypeProcess);
|
||||
PROCESS* proc = (PROCESS*)KiHandleToObject((uint32_t)a0, ObjectTypeProcess);
|
||||
if (!proc) return STATUS_INVALID_HANDLE;
|
||||
|
||||
KSTATUS s = KeWaitForEvent(proc->ExitEvent);
|
||||
KSTATUS s = KeWaitForEvent(proc->ExitEvent, 0);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return s;
|
||||
}
|
||||
@@ -856,7 +1107,7 @@ static uint64_t SyscallGetProcessExitCode(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
|
||||
PROCESS* proc = (PROCESS*)HandleToObject((uint32_t)a0, ObjectTypeProcess);
|
||||
PROCESS* proc = (PROCESS*)KiHandleToObject((uint32_t)a0, ObjectTypeProcess);
|
||||
if (!proc) return STATUS_INVALID_HANDLE;
|
||||
|
||||
int* exitCodeOut = (int*)(uintptr_t)a1;
|
||||
@@ -915,12 +1166,12 @@ static uint64_t SyscallReadDir(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
// a1 = KDIR_ENTRY* buffer
|
||||
|
||||
// Look up a DIR_OBJECT using ObjectTypeDir (not ObjectTypeFile)
|
||||
DIR_OBJECT* dir = (DIR_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeDir);
|
||||
DIR_OBJECT* dir = (DIR_OBJECT*)KiHandleToObject((uint32_t)a0, ObjectTypeDir);
|
||||
if (!dir) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS s = IoReadDir(dir, (void*)(uintptr_t)a1);
|
||||
|
||||
ObDereferenceObject(&dir->Header); // Drop the ref taken by HandleToObject
|
||||
ObDereferenceObject(&dir->Header); // Drop the ref taken by KiHandleToObject
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -986,7 +1237,7 @@ static uint64_t SyscallWaitThread(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
KSTATUS s = KeWaitForEvent(exitEvent);
|
||||
KSTATUS s = KeWaitForEvent(exitEvent, 0);
|
||||
ObDereferenceObject(&exitEvent->Header);
|
||||
return s;
|
||||
}
|
||||
@@ -1000,7 +1251,7 @@ static uint64_t SyscallGetProcessPid(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
|
||||
PROCESS* proc = (PROCESS*)HandleToObject((uint32_t)a0, ObjectTypeProcess);
|
||||
PROCESS* proc = (PROCESS*)KiHandleToObject((uint32_t)a0, ObjectTypeProcess);
|
||||
uint32_t* pidOut = (uint32_t*)(uintptr_t)a1;
|
||||
if (!proc) return STATUS_INVALID_HANDLE;
|
||||
if (!pidOut) { ObDereferenceObject(&proc->Header); return STATUS_INVALID_PARAMETER; }
|
||||
@@ -1048,9 +1299,9 @@ static uint64_t SyscallPublishQueue(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
const char* name = (const char*)(uintptr_t)a0;
|
||||
if (!name || !name[0]) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
// Resolve the handle to a QUEUE object. HandleToObject bumps the
|
||||
// Resolve the handle to a QUEUE object. KiHandleToObject bumps the
|
||||
// refcount by one; we keep that ref in the registry slot.
|
||||
QUEUE* q = (QUEUE*)HandleToObject((uint32_t)a1, ObjectTypeQueue);
|
||||
QUEUE* q = (QUEUE*)KiHandleToObject((uint32_t)a1, ObjectTypeQueue);
|
||||
if (!q) return STATUS_INVALID_HANDLE;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gNamedQueueLock);
|
||||
@@ -1113,9 +1364,9 @@ static uint64_t SyscallOpenNamedQueue(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
|
||||
if (!q) return STATUS_NOT_FOUND;
|
||||
|
||||
// AllocHandleForCurrent consumes the ref we just bumped.
|
||||
// KiAllocHandleForCurrent consumes the ref we just bumped.
|
||||
// On failure it calls ObDereferenceObject internally.
|
||||
return AllocHandleForCurrent(&q->Header, handleOut);
|
||||
return KiAllocHandleForCurrent(&q->Header, handleOut);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1131,7 +1382,7 @@ static uint64_t SyscallQueueDuplicate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
if (!a2) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
QUEUE* q = (QUEUE*)HandleToObject((uint32_t)a0, ObjectTypeQueue);
|
||||
QUEUE* q = (QUEUE*)KiHandleToObject((uint32_t)a0, ObjectTypeQueue);
|
||||
if (!q) return STATUS_NOT_FOUND;
|
||||
|
||||
PROCESS* target = KeGetProcessById((uint32_t)a1);
|
||||
@@ -1250,82 +1501,89 @@ typedef uint64_t (*SYSCALL_HANDLER)(uint64_t, uint64_t, uint64_t,
|
||||
uint64_t, uint64_t, uint64_t);
|
||||
|
||||
static const SYSCALL_HANDLER gSyscallTable[SYS_MAX] = {
|
||||
/* 00 SYS_EXIT_PROCESS */ SyscallExitProcess,
|
||||
/* 01 SYS_EXIT_THREAD */ SyscallExitThread,
|
||||
/* 02 SYS_CREATE_THREAD */ SyscallCreateThread,
|
||||
/* 03 SYS_GET_CURRENT_TID */ SyscallGetCurrentTid,
|
||||
/* 04 SYS_GET_CURRENT_PID */ SyscallGetCurrentPid,
|
||||
/* 05 SYS_YIELD */ SyscallYield,
|
||||
/* 06 SYS_SLEEP */ SyscallSleep,
|
||||
/* 07 SYS_SET_THREAD_PRIORITY */ SyscallSetThreadPriority,
|
||||
/* 08 SYS_ALLOC */ SyscallAlloc,
|
||||
/* 09 SYS_FREE */ SyscallFree,
|
||||
/* 10 SYS_REALLOC */ SyscallRealloc,
|
||||
/* 11 SYS_MUTEX_CREATE */ SyscallMutexCreate,
|
||||
/* 12 SYS_MUTEX_ACQUIRE */ SyscallMutexAcquire,
|
||||
/* 13 SYS_MUTEX_TRY_ACQUIRE */ SyscallMutexTryAcquire,
|
||||
/* 14 SYS_MUTEX_RELEASE */ SyscallMutexRelease,
|
||||
/* 15 SYS_SEM_CREATE */ SyscallSemCreate,
|
||||
/* 16 SYS_SEM_WAIT */ SyscallSemWait,
|
||||
/* 17 SYS_SEM_TRY_WAIT */ SyscallSemTryWait,
|
||||
/* 18 SYS_SEM_SIGNAL */ SyscallSemSignal,
|
||||
/* 19 SYS_EVENT_CREATE */ SyscallEventCreate,
|
||||
/* 20 SYS_EVENT_SIGNAL */ SyscallEventSignal,
|
||||
/* 21 SYS_EVENT_CLEAR */ SyscallEventClear,
|
||||
/* 22 SYS_EVENT_WAIT */ SyscallEventWait,
|
||||
/* 23 SYS_QUEUE_CREATE */ SyscallQueueCreate,
|
||||
/* 24 SYS_QUEUE_SEND */ SyscallQueueSend,
|
||||
/* 25 SYS_QUEUE_RECV */ SyscallQueueRecv,
|
||||
/* 26 SYS_CLOSE_HANDLE */ SyscallCloseHandle,
|
||||
/* 27 SYS_OPEN_FILE */ SyscallOpenFile,
|
||||
/* 28 SYS_READ_FILE */ SyscallReadFile,
|
||||
/* 29 SYS_WRITE_FILE */ SyscallWriteFile,
|
||||
/* 30 SYS_CREATE_FILE */ SyscallCreateFile,
|
||||
/* 31 SYS_DELETE_FILE */ SyscallDeleteFile,
|
||||
/* 32 SYS_TRUNCATE_FILE */ SyscallTruncateFile,
|
||||
/* 33 SYS_GET_FILE_POS */ SyscallGetFilePos,
|
||||
/* 34 SYS_SEEK_FILE */ SyscallSeekFile,
|
||||
/* 35 SYS_GET_FILE_SIZE */ SyscallGetFileSize,
|
||||
/* 36 SYS_SCREEN_BLIT */ SyscallScreenBlit,
|
||||
/* 37 SYS_SCREEN_CLEAR */ SyscallScreenClear,
|
||||
/* 38 SYS_SCREEN_GET_SIZE */ SyscallScreenGetSize,
|
||||
/* 39 SYS_SCREEN_PUT_CHAR */ SyscallScreenPutChar,
|
||||
/* 40 SYS_KB_POLL */ SyscallKbPoll,
|
||||
/* 41 SYS_KB_IS_KEY_DOWN */ SyscallKbIsKeyDown,
|
||||
/* 42 SYS_KB_READ_CHAR */ SyscallKbReadChar,
|
||||
/* 43 SYS_KB_READ_SCANCODE */ SyscallKbReadScancode,
|
||||
/* 44 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
|
||||
/* 45 SYS_MOUSE_POLL */ SyscallMousePoll,
|
||||
/* 46 SYS_MOUSE_READ */ SyscallMouseRead,
|
||||
/* 47 SYS_MOUSE_GET_POS */ SyscallMouseGetPos,
|
||||
/* 48 SYS_GET_TICK */ SyscallGetTick,
|
||||
/* 49 SYS_DEBUG_PRINT */ SyscallDebugPrint,
|
||||
/* 50 SYS_CREATE_PROCESS */ SyscallCreateProcess,
|
||||
/* 51 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess,
|
||||
/* 52 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode,
|
||||
/* 53 SYS_WRITE_CONSOLE */ SyscallWriteConsole,
|
||||
/* 54 SYS_OPEN_DIR */ SyscallOpenDir,
|
||||
/* 55 SYS_READ_DIR */ SyscallReadDir,
|
||||
/* 56 SYS_SET_CWD */ SyscallSetCwd,
|
||||
/* 57 SYS_GET_CWD */ SyscallGetCwd,
|
||||
/* 58 SYS_WAIT_THREAD */ SyscallWaitThread,
|
||||
/* 59 SYS_GET_PROCESS_PID */ SyscallGetProcessPid,
|
||||
/* 60 SYS_PUBLISH_QUEUE */ SyscallPublishQueue,
|
||||
/* 61 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
|
||||
/* 62 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
|
||||
/* 63 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
|
||||
/* 64 SYS_KILL_PROCESS */ SyscallKillProcess,
|
||||
/* 65 SYS_GET_PROCESS_LIST */ SyscallGetProcessList,
|
||||
/* 66 SYS_RENAME_FILE */ SyscallRenameFile,
|
||||
/* 67 SYS_CREATE_DIR */ SyscallCreateDir,
|
||||
/* 68 SYS_REMOVE_DIR */ SyscallRemoveDir,
|
||||
/* 00 SYS_EXIT_PROCESS */ SyscallExitProcess,
|
||||
/* 01 SYS_EXIT_THREAD */ SyscallExitThread,
|
||||
/* 02 SYS_CREATE_PROCESS */ SyscallCreateProcess,
|
||||
/* 03 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess,
|
||||
/* 04 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode,
|
||||
/* 05 SYS_KILL_PROCESS */ SyscallKillProcess,
|
||||
/* 06 SYS_GET_PROCESS_LIST */ SyscallGetProcessList,
|
||||
/* 07 SYS_GET_PROCESS_PID */ SyscallGetProcessPid,
|
||||
/* 08 SYS_CREATE_THREAD */ SyscallCreateThread,
|
||||
/* 09 SYS_WAIT_THREAD */ SyscallWaitThread,
|
||||
/* 10 SYS_GET_CURRENT_TID */ SyscallGetCurrentTid,
|
||||
/* 11 SYS_GET_CURRENT_PID */ SyscallGetCurrentPid,
|
||||
/* 12 SYS_SET_THREAD_PRIORITY */ SyscallSetThreadPriority,
|
||||
/* 13 SYS_YIELD */ SyscallYield,
|
||||
/* 14 SYS_SLEEP */ SyscallSleep,
|
||||
/* 15 SYS_SET_USER_APC_DISPATCHER */ SyscallSetUserApcDispatcher,
|
||||
/* 16 SYS_APC_RETURN */ SyscallApcReturn,
|
||||
/* 17 SYS_ALLOC */ SyscallAlloc,
|
||||
/* 18 SYS_FREE */ SyscallFree,
|
||||
/* 19 SYS_REALLOC */ SyscallRealloc,
|
||||
/* 20 SYS_CLOSE_HANDLE */ SyscallCloseHandle,
|
||||
/* 21 SYS_MUTEX_CREATE */ SyscallMutexCreate,
|
||||
/* 22 SYS_MUTEX_ACQUIRE */ SyscallMutexAcquire,
|
||||
/* 23 SYS_MUTEX_TRY_ACQUIRE */ SyscallMutexTryAcquire,
|
||||
/* 24 SYS_MUTEX_RELEASE */ SyscallMutexRelease,
|
||||
/* 25 SYS_SEM_CREATE */ SyscallSemCreate,
|
||||
/* 26 SYS_SEM_WAIT */ SyscallSemWait,
|
||||
/* 27 SYS_SEM_TRY_WAIT */ SyscallSemTryWait,
|
||||
/* 28 SYS_SEM_SIGNAL */ SyscallSemSignal,
|
||||
/* 29 SYS_EVENT_CREATE */ SyscallEventCreate,
|
||||
/* 30 SYS_EVENT_SIGNAL */ SyscallEventSignal,
|
||||
/* 31 SYS_EVENT_CLEAR */ SyscallEventClear,
|
||||
/* 32 SYS_EVENT_WAIT */ SyscallEventWait,
|
||||
/* 34 SYS_QUEUE_CREATE */ SyscallQueueCreate,
|
||||
/* 35 SYS_QUEUE_SEND */ SyscallQueueSend,
|
||||
/* 36 SYS_QUEUE_RECV */ SyscallQueueRecv,
|
||||
/* 37 SYS_PUBLISH_QUEUE */ SyscallPublishQueue,
|
||||
/* 38 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
|
||||
/* 39 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
|
||||
/* 40 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
|
||||
/* 41 SYS_OPEN_FILE */ SyscallOpenFile,
|
||||
/* 42 SYS_CREATE_FILE */ SyscallCreateFile,
|
||||
/* 43 SYS_READ_FILE */ SyscallReadFile,
|
||||
/* 44 SYS_WRITE_FILE */ SyscallWriteFile,
|
||||
/* 45 SYS_READ_FILE_ASYNC */ SyscallReadFileAsync,
|
||||
/* 46 SYS_WRITE_FILE_ASYNC */ SyscallWriteFileAsync,
|
||||
/* 47 SYS_CANCEL_IO */ SyscallCancelIo,
|
||||
/* 48 SYS_SEEK_FILE */ SyscallSeekFile,
|
||||
/* 49 SYS_GET_FILE_POS */ SyscallGetFilePos,
|
||||
/* 50 SYS_GET_FILE_SIZE */ SyscallGetFileSize,
|
||||
/* 51 SYS_TRUNCATE_FILE */ SyscallTruncateFile,
|
||||
/* 52 SYS_DELETE_FILE */ SyscallDeleteFile,
|
||||
/* 53 SYS_RENAME_FILE */ SyscallRenameFile,
|
||||
/* 54 SYS_OPEN_DIR */ SyscallOpenDir,
|
||||
/* 55 SYS_READ_DIR */ SyscallReadDir,
|
||||
/* 56 SYS_CREATE_DIR */ SyscallCreateDir,
|
||||
/* 57 SYS_REMOVE_DIR */ SyscallRemoveDir,
|
||||
/* 58 SYS_SET_CWD */ SyscallSetCwd,
|
||||
/* 59 SYS_GET_CWD */ SyscallGetCwd,
|
||||
/* 60 SYS_WRITE_CONSOLE */ SyscallWriteConsole,
|
||||
/* 61 SYS_SCREEN_BLIT */ SyscallScreenBlit,
|
||||
/* 62 SYS_SCREEN_CLEAR */ SyscallScreenClear,
|
||||
/* 63 SYS_SCREEN_GET_SIZE */ SyscallScreenGetSize,
|
||||
/* 64 SYS_SCREEN_PUT_CHAR */ SyscallScreenPutChar,
|
||||
/* 65 SYS_KB_POLL */ SyscallKbPoll,
|
||||
/* 66 SYS_KB_IS_KEY_DOWN */ SyscallKbIsKeyDown,
|
||||
/* 67 SYS_KB_READ_CHAR */ SyscallKbReadChar,
|
||||
/* 68 SYS_KB_READ_SCANCODE */ SyscallKbReadScancode,
|
||||
/* 69 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
|
||||
/* 70 SYS_MOUSE_POLL */ SyscallMousePoll,
|
||||
/* 71 SYS_MOUSE_READ */ SyscallMouseRead,
|
||||
/* 72 SYS_MOUSE_GET_POS */ SyscallMouseGetPos,
|
||||
/* 73 SYS_GET_TICK */ SyscallGetTick,
|
||||
/* 74 SYS_DEBUG_PRINT */ SyscallDebugPrint,
|
||||
/* 75 SYS_QUERY_TRAP_FRAME */ SyscallQueryTrapFrame,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Entry point - called from ke_syscall.asm after argument re-ordering
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1,
|
||||
uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1,
|
||||
uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
KiValidateSyscallTrapFrame(nr, a0, a1, a2, a3, a4, a5);
|
||||
if (nr >= SYS_MAX || !gSyscallTable[nr]) return STATUS_NOT_SUPPORTED;
|
||||
return (KSTATUS)gSyscallTable[nr](a0, a1, a2, a3, a4, a5);
|
||||
return gSyscallTable[nr](a0, a1, a2, a3, a4, a5);
|
||||
}
|
||||
Reference in new issue
Block a user