implement user mode catchable exceptions, refactor system status codes to use NTLSTATUS_ prefix, update build scripts to use shared literal macros for linker arguments, update named queue lifetime cleanup to include KeNamedQueueUnpublishHandle.
This commit is contained in:
1 parent
1f5477cf66
commit
b7fcfce6f7
140 files changed
+7649
-3943
No files matched your search
@@ -166,9 +166,9 @@ __declspec(dllexport) void HalApicSendTlbShootdownIpi(uint32_t lapicId) {
|
||||
// Starts application Processor.
|
||||
__declspec(dllexport) KSTATUS HalStartApplicationProcessor(uint32_t lapicId, uint8_t startupVector) {
|
||||
if ((!gLapic && !gX2ApicEnabled) || !startupVector || lapicId == gBspLapicId)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!HalApicCanAddressId(lapicId))
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
// INIT assert/deassert, then two SIPIs. The target begins at startupVector << 12.
|
||||
HalApicSendIpi(lapicId, 0x0000C500u); // INIT, level assert, level-triggered
|
||||
@@ -179,7 +179,7 @@ __declspec(dllexport) KSTATUS HalStartApplicationProcessor(uint32_t lapicId, uin
|
||||
HalApicStallUs(200);
|
||||
HalApicSendIpi(lapicId, 0x00000600u | startupVector); // SIPI retry
|
||||
HalApicStallUs(200);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the apic Route Irq operation.
|
||||
|
||||
@@ -513,7 +513,7 @@ static void HalShutdown(void) {
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS HalGetProcessorTopology(HAL_CPU_TOPOLOGY* out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
*out = gCpuTopology;
|
||||
@@ -526,7 +526,7 @@ __declspec(dllexport) KSTATUS HalGetProcessorTopology(HAL_CPU_TOPOLOGY* out) {
|
||||
out->Cpus[0].Flags = 1;
|
||||
out->Cpus[0].Enabled = 1;
|
||||
out->Cpus[0].IsBsp = 1;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t bsp = HalGetBspLapicId();
|
||||
@@ -546,11 +546,11 @@ __declspec(dllexport) KSTATUS HalGetProcessorTopology(HAL_CPU_TOPOLOGY* out) {
|
||||
cpu->Enabled = 1;
|
||||
cpu->IsBsp = 1;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
|
||||
if (gInitialised) return STATUS_ALREADY_EXISTS;
|
||||
if (gInitialised) return NTLSTATUS_ALREADY_EXISTS;
|
||||
gPhysBase = initParams->PhysicalWindowBase;
|
||||
gApi.PhysToVirt = HalPhysToVirt;
|
||||
debugEnabled = initParams->Debug;
|
||||
@@ -606,7 +606,7 @@ __declspec(dllexport) KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
|
||||
}
|
||||
|
||||
HalDbgPrint("HAL: initialisation complete.\n");
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Registers scheduler.
|
||||
|
||||
@@ -36,9 +36,9 @@ static void HalOutputReleaseRegistrationLock(void) {
|
||||
static KSTATUS HalOutputRegisterEndpoint(const HAL_OUTPUT_ENDPOINT* endpoint, uint32_t* endpointIdOut) {
|
||||
if (!endpoint || !endpointIdOut || !endpoint->Name || !endpoint->Write ||
|
||||
endpoint->StreamMask == 0 || (endpoint->StreamMask & ~HAL_OUTPUT_STREAM_ALL) != 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = STATUS_NO_MEMORY;
|
||||
KSTATUS status = NTLSTATUS_NO_MEMORY;
|
||||
HalOutputAcquireRegistrationLock();
|
||||
for (uint32_t i = 0; i < HAL_OUTPUT_ENDPOINT_CAPACITY; i++) {
|
||||
HAL_OUTPUT_SLOT* slot = &gOutputSlots[i];
|
||||
@@ -50,7 +50,7 @@ static KSTATUS HalOutputRegisterEndpoint(const HAL_OUTPUT_ENDPOINT* endpoint, ui
|
||||
_InterlockedExchange(&slot->Published, 1);
|
||||
_InterlockedIncrement(&gOutputEndpointCount);
|
||||
*endpointIdOut = i;
|
||||
status = STATUS_SUCCESS;
|
||||
status = NTLSTATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
HalOutputReleaseRegistrationLock();
|
||||
@@ -61,14 +61,14 @@ static KSTATUS HalOutputRegisterEndpoint(const HAL_OUTPUT_ENDPOINT* endpoint, ui
|
||||
static KSTATUS HalOutputSetEndpointStreams(uint32_t endpointId, uint32_t streamMask) {
|
||||
if (endpointId >= HAL_OUTPUT_ENDPOINT_CAPACITY ||
|
||||
(streamMask & ~HAL_OUTPUT_STREAM_ALL) != 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
HAL_OUTPUT_SLOT* slot = &gOutputSlots[endpointId];
|
||||
if (_InterlockedCompareExchange(&slot->Published, 0, 0) == 0)
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
_InterlockedExchange((volatile long*)&slot->Endpoint.StreamMask, (long)streamMask);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Fans one text record out to every subscribed endpoint.
|
||||
|
||||
@@ -142,15 +142,15 @@ static bool RtcValid(const HAL_RTC_TIME* t) {
|
||||
|
||||
// Implements the rtc Query Time operation.
|
||||
static KSTATUS HalRtcQueryTime(HAL_RTC_TIME* outTime) {
|
||||
if (!outTime) return STATUS_INVALID_PARAMETER;
|
||||
if (!outTime) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
HAL_RTC_TIME t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
if (!RtcReadStable(&t) || !RtcValid(&t))
|
||||
return STATUS_DEVICE_ERROR;
|
||||
return NTLSTATUS_DEVICE_ERROR;
|
||||
|
||||
*outTime = t;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the rtc Set Century Register operation.
|
||||
@@ -164,7 +164,7 @@ void HalRtcInitialize(HAL_RTC* out) {
|
||||
out->QueryTime = HalRtcQueryTime;
|
||||
|
||||
HAL_RTC_TIME t;
|
||||
if (HalRtcQueryTime(&t) == STATUS_SUCCESS) {
|
||||
if (HalRtcQueryTime(&t) == NTLSTATUS_SUCCESS) {
|
||||
HalDbgPrint("HAL: RTC %04u-%02u-%02u %02u:%02u:%02u century-reg=0x%02x\n",
|
||||
t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Second,
|
||||
gCenturyRegister);
|
||||
|
||||
@@ -117,14 +117,14 @@ static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; }
|
||||
// Implements the screen Get Framebuffer operation.
|
||||
static KSTATUS ScreenGetFramebuffer(HAL_FRAMEBUFFER_INFO* outInfo) {
|
||||
if (!outInfo || !gFb || gWidth <= 0 || gHeight <= 0 || gStride <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
outInfo->Base = (uintptr_t)gFb;
|
||||
outInfo->Width = (uint32_t)gWidth;
|
||||
outInfo->Height = (uint32_t)gHeight;
|
||||
outInfo->Stride = (uint32_t)gStride;
|
||||
outInfo->Format = 1; // X8R8G8B8
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the screen Scroll operation.
|
||||
|
||||
@@ -210,7 +210,7 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *o
|
||||
}
|
||||
if (!ticksPerMs) {
|
||||
HalDbgPrint("HAL: APIC calibration failed. How?\n");
|
||||
return STATUS_DEVICE_ERROR;
|
||||
return NTLSTATUS_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
gApicTicksPerUs = ticksPerMs / 1000;
|
||||
@@ -234,5 +234,5 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *o
|
||||
out->Stall = Stall;
|
||||
out->Isr = TimerIsr;
|
||||
out->IrqNumber = 0;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ typedef SYS_DIR_ENTRY KDIR_ENTRY;
|
||||
#define KDIR_NAME_MAX SYS_DIR_NAME_MAX
|
||||
|
||||
// Native asynchronous filesystem completion. Filesystems that provide
|
||||
// ReadAsync/WriteAsync accept the operation, return STATUS_PENDING, and later
|
||||
// ReadAsync/WriteAsync accept the operation, return NTLSTATUS_PENDING, and later
|
||||
// call Complete(CompleteContext, status, information). Filesystems without
|
||||
// these callbacks fall back to the generic VFS async worker.
|
||||
typedef void (*IO_FS_ASYNC_COMPLETE)(void* completeContext,
|
||||
@@ -130,7 +130,7 @@ typedef struct IO_FILESYSTEM {
|
||||
|
||||
// Advance to the next entry.
|
||||
// Fills 'out' with name, attributes, and size.
|
||||
// Returns STATUS_NO_MORE_FILES when the directory is exhausted.
|
||||
// Returns NTLSTATUS_NO_MORE_FILES when the directory is exhausted.
|
||||
KSTATUS (*ReadDir)(struct IO_FILESYSTEM* fs, void* dirCtx,
|
||||
KDIR_ENTRY* out);
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ typedef struct KFAULT_FRAME {
|
||||
uint64_t R15;
|
||||
} KFAULT_FRAME;
|
||||
|
||||
__declspec(dllexport) KSTATUS KeFaultDispatchFrame(const KFAULT_FRAME* frame);
|
||||
__declspec(dllexport) KSTATUS KeFaultDispatchFrame(KFAULT_FRAME* frame);
|
||||
|
||||
// Compatibility wrapper for any older assembly/object still calling this.
|
||||
__declspec(dllexport) _Noreturn void KeFaultDispatch(int vector, uintptr_t rip,
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Kernel exception classification shared by trap and crash-report paths.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <ntlite/status.h>
|
||||
#include <ntlite/syscall.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
|
||||
#define KFAULT_FRAME_MAGIC_VALUE 0x3146544C5541464BULL
|
||||
|
||||
bool KeFaultFrameIsValid(const KFAULT_FRAME* frame);
|
||||
bool KeFaultFrameFromUser(const KFAULT_FRAME* frame);
|
||||
const char* KeExceptionVectorName(uint32_t vector);
|
||||
bool KeExceptionVectorHasErrorCode(uint32_t vector);
|
||||
KSTATUS KeExceptionProcessExitStatus(uint32_t vector);
|
||||
KSTATUS KeExceptionResolveRecoverableFault(const KFAULT_FRAME* frame);
|
||||
|
||||
struct PROCESS;
|
||||
|
||||
KSTATUS KeSetExceptionDispatcher(struct PROCESS* process, const SYS_EXCEPTION_DISPATCHER_REQUEST* request);
|
||||
KSTATUS KeGetExceptionDispatcher(struct PROCESS* process, SYS_EXCEPTION_DISPATCHER_REQUEST* request);
|
||||
KSTATUS KeDeliverUserException(KFAULT_FRAME* frame);
|
||||
uint64_t KeContinueException(const SYS_CONTINUE_EXCEPTION_REQUEST* request);
|
||||
uint64_t KeRaiseUserException(const SYS_RAISE_EXCEPTION_REQUEST* request, const uint64_t* parameters);
|
||||
@@ -0,0 +1,11 @@
|
||||
// Named queue registry hooks shared by process handle cleanup and syscalls.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct PROCESS;
|
||||
struct OBJECT;
|
||||
|
||||
// Removes registry entries owned by the given process handle/object pair.
|
||||
void KeNamedQueueUnpublishHandle(struct PROCESS* process, uint32_t handle, struct OBJECT* object);
|
||||
@@ -32,6 +32,8 @@
|
||||
#define HANDLE_RIGHT_LOCK 0x00000080u
|
||||
#define HANDLE_RIGHT_ALL 0xFFFFFFFFu
|
||||
|
||||
struct SYS_EXCEPTION_STATS;
|
||||
|
||||
typedef struct HANDLE_ENTRY {
|
||||
OBJECT* Object;
|
||||
uint32_t Rights;
|
||||
@@ -100,6 +102,24 @@ typedef struct PROCESS {
|
||||
uint32_t ModuleCount;
|
||||
SPINLOCK ModuleLock;
|
||||
|
||||
// Native structured-exception dispatcher registration. The user-mode
|
||||
// personality owns VEH, SEH, signal, and unwind policy behind this hook.
|
||||
uintptr_t ExceptionDispatcher;
|
||||
uintptr_t ExceptionDispatcherContext;
|
||||
uintptr_t ExceptionStackBase;
|
||||
size_t ExceptionStackSize;
|
||||
uint32_t ExceptionDispatchFlags;
|
||||
uint64_t ExceptionDeliveredCount;
|
||||
uint64_t ExceptionUserRaisedCount;
|
||||
uint64_t ExceptionContinuedCount;
|
||||
uint64_t ExceptionUnhandledCount;
|
||||
uint64_t ExceptionInvalidContinueCount;
|
||||
uint32_t ExceptionMaxNestedDispatch;
|
||||
uint32_t LastExceptionCode;
|
||||
uintptr_t LastExceptionAddress;
|
||||
uintptr_t LastExceptionFaultAddress;
|
||||
SPINLOCK ExceptionLock;
|
||||
|
||||
// Signaled (manual-reset) when the process exits.
|
||||
// Waiters block on this via KeWaitForEvent.
|
||||
EVENT* ExitEvent;
|
||||
@@ -119,6 +139,7 @@ void KeCompleteProcessExitIfLastThread(PROCESS* process);
|
||||
int KeIsProcessTerminating(PROCESS* process);
|
||||
int KeIsProcessTerminationProtected(PROCESS* process);
|
||||
KSTATUS KeGetProcessExitCode(PROCESS* process, int32_t* exitCodeOut);
|
||||
void KeQueryExceptionStats(struct SYS_EXCEPTION_STATS* statsOut);
|
||||
|
||||
// Handle table operations.
|
||||
KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#define KSTACK_SIZE (64 * 1024) // 64 KB kernel stack
|
||||
#define USTACK_SIZE (512 * 1024) // 512 KB user stack
|
||||
#define KE_USER_EXCEPTION_MAX_DEPTH 8u
|
||||
|
||||
typedef struct THREAD THREAD;
|
||||
|
||||
@@ -153,6 +154,14 @@ struct THREAD {
|
||||
uint64_t UserApcSavedRsp;
|
||||
uint64_t UserApcSavedRflags;
|
||||
uint64_t UserApcSavedRax;
|
||||
|
||||
// User exception dispatch state. The kernel tracks delivery nesting,
|
||||
// continuability, and the process status to use if user policy declines
|
||||
// the active exception. User-mode personalities own handler policy.
|
||||
uint32_t UserExceptionDepth;
|
||||
uint32_t UserExceptionNoncontinuableMask;
|
||||
uintptr_t UserExceptionFrameUserAddress;
|
||||
KSTATUS UserExceptionExitStatus[KE_USER_EXCEPTION_MAX_DEPTH];
|
||||
};
|
||||
|
||||
// Creates and queues a user thread. On success, *out receives a referenced
|
||||
|
||||
@@ -7,141 +7,146 @@
|
||||
// R10 and R11 carry args 4-5 and are loaded by six-argument stubs.
|
||||
// RAX carries the return value.
|
||||
|
||||
// Process, threads, modules, waits, and APC.
|
||||
#define SYS_EXIT_PROCESS 0
|
||||
#define SYS_EXIT_THREAD 1
|
||||
#define SYS_CREATE_PROCESS 2
|
||||
#define SYS_OPEN_PROCESS 3
|
||||
#define SYS_GET_PROCESS_EXIT_CODE 4
|
||||
#define SYS_KILL_PROCESS 5
|
||||
#define SYS_GET_PROCESS_LIST 6
|
||||
#define SYS_GET_PROCESS_PID 7
|
||||
#define SYS_CREATE_THREAD 8
|
||||
#define SYS_GET_THREAD_LIST 9
|
||||
#define SYS_LOAD_MODULE 10
|
||||
#define SYS_UNLOAD_MODULE 11
|
||||
#define SYS_GET_MODULE_INFO 12
|
||||
#define SYS_GET_MODULE_EXPORT 13
|
||||
#define SYS_GET_MODULE_LIST 14
|
||||
#define SYS_GET_CURRENT_TID 15
|
||||
#define SYS_GET_CURRENT_PID 16
|
||||
#define SYS_SET_THREAD_PRIORITY 17
|
||||
#define SYS_YIELD 18
|
||||
#define SYS_SLEEP 19
|
||||
#define SYS_WAIT_SINGLE 20
|
||||
#define SYS_WAIT_MANY 21
|
||||
#define SYS_SET_USER_APC_DISPATCHER 22
|
||||
#define SYS_APC_RETURN 23
|
||||
// Process, threads, modules, waits, APC, and exceptions.
|
||||
#define SYS_EXIT_PROCESS 0
|
||||
#define SYS_EXIT_THREAD 1
|
||||
#define SYS_CREATE_PROCESS 2
|
||||
#define SYS_OPEN_PROCESS 3
|
||||
#define SYS_GET_PROCESS_EXIT_CODE 4
|
||||
#define SYS_KILL_PROCESS 5
|
||||
#define SYS_GET_PROCESS_LIST 6
|
||||
#define SYS_GET_PROCESS_PID 7
|
||||
#define SYS_CREATE_THREAD 8
|
||||
#define SYS_GET_THREAD_LIST 9
|
||||
#define SYS_LOAD_MODULE 10
|
||||
#define SYS_UNLOAD_MODULE 11
|
||||
#define SYS_GET_MODULE_INFO 12
|
||||
#define SYS_GET_MODULE_EXPORT 13
|
||||
#define SYS_GET_MODULE_LIST 14
|
||||
#define SYS_GET_CURRENT_TID 15
|
||||
#define SYS_GET_CURRENT_PID 16
|
||||
#define SYS_SET_THREAD_PRIORITY 17
|
||||
#define SYS_YIELD 18
|
||||
#define SYS_SLEEP 19
|
||||
#define SYS_WAIT_SINGLE 20
|
||||
#define SYS_WAIT_MANY 21
|
||||
#define SYS_SET_USER_APC_DISPATCHER 22
|
||||
#define SYS_APC_RETURN 23
|
||||
#define SYS_SET_EXCEPTION_DISPATCHER 24
|
||||
#define SYS_GET_EXCEPTION_DISPATCHER 25
|
||||
#define SYS_CONTINUE_EXCEPTION 26
|
||||
#define SYS_RAISE_EXCEPTION 27
|
||||
|
||||
// Virtual memory, mappings, and handles.
|
||||
#define SYS_ALLOC_VM 24
|
||||
#define SYS_FREE_VM 25
|
||||
#define SYS_PROTECT_VM 26
|
||||
#define SYS_QUERY_VM 27
|
||||
#define SYS_CLOSE_HANDLE 28
|
||||
#define SYS_DUPLICATE_HANDLE 29
|
||||
#define SYS_CREATE_FILE_MAPPING 30
|
||||
#define SYS_MAP_FILE 31
|
||||
#define SYS_ALLOC_VM 28
|
||||
#define SYS_FREE_VM 29
|
||||
#define SYS_PROTECT_VM 30
|
||||
#define SYS_QUERY_VM 31
|
||||
#define SYS_CLOSE_HANDLE 32
|
||||
#define SYS_DUPLICATE_HANDLE 33
|
||||
#define SYS_CREATE_FILE_MAPPING 34
|
||||
#define SYS_MAP_FILE 35
|
||||
|
||||
// Synchronization objects.
|
||||
#define SYS_CREATE_MUTEX 32
|
||||
#define SYS_TRY_ACQUIRE_MUTEX 33
|
||||
#define SYS_RELEASE_MUTEX 34
|
||||
#define SYS_CREATE_SEM 35
|
||||
#define SYS_TRY_WAIT_SEM 36
|
||||
#define SYS_SIGNAL_SEM 37
|
||||
#define SYS_CREATE_EVENT 38
|
||||
#define SYS_SIGNAL_EVENT 39
|
||||
#define SYS_CLEAR_EVENT 40
|
||||
#define SYS_CREATE_MUTEX 36
|
||||
#define SYS_TRY_ACQUIRE_MUTEX 37
|
||||
#define SYS_RELEASE_MUTEX 38
|
||||
#define SYS_CREATE_SEM 39
|
||||
#define SYS_TRY_WAIT_SEM 40
|
||||
#define SYS_SIGNAL_SEM 41
|
||||
#define SYS_CREATE_EVENT 42
|
||||
#define SYS_SIGNAL_EVENT 43
|
||||
#define SYS_CLEAR_EVENT 44
|
||||
|
||||
// Queues and named queues.
|
||||
#define SYS_CREATE_QUEUE 41
|
||||
#define SYS_SEND_QUEUE 42
|
||||
#define SYS_RECV_QUEUE 43
|
||||
#define SYS_PUBLISH_QUEUE 44
|
||||
#define SYS_OPEN_NAMED_QUEUE 45
|
||||
#define SYS_OPEN_NAMED_QUEUE_OWNER_PROCESS 46
|
||||
#define SYS_CREATE_QUEUE 45
|
||||
#define SYS_SEND_QUEUE 46
|
||||
#define SYS_RECV_QUEUE 47
|
||||
#define SYS_PUBLISH_QUEUE 48
|
||||
#define SYS_OPEN_NAMED_QUEUE 49
|
||||
#define SYS_OPEN_NAMED_QUEUE_OWNER_PROCESS 50
|
||||
|
||||
// Files, directories, and current directory.
|
||||
#define SYS_OPEN_FILE 47
|
||||
#define SYS_READ_FILE 48
|
||||
#define SYS_WRITE_FILE 49
|
||||
#define SYS_READ_FILE_ASYNC 50
|
||||
#define SYS_WRITE_FILE_ASYNC 51
|
||||
#define SYS_CANCEL_IO 52
|
||||
#define SYS_SEEK_FILE 53
|
||||
#define SYS_GET_FILE_POS 54
|
||||
#define SYS_GET_FILE_SIZE 55
|
||||
#define SYS_GET_FILE_STAT 56
|
||||
#define SYS_STAT_FILE 57
|
||||
#define SYS_TRUNCATE_FILE 58
|
||||
#define SYS_FLUSH_FILE 59
|
||||
#define SYS_DELETE_FILE 60
|
||||
#define SYS_RENAME_FILE 61
|
||||
#define SYS_LOCK_FILE 62
|
||||
#define SYS_UNLOCK_FILE 63
|
||||
#define SYS_OPEN_DIR 64
|
||||
#define SYS_READ_DIR 65
|
||||
#define SYS_CREATE_DIR 66
|
||||
#define SYS_REMOVE_DIR 67
|
||||
#define SYS_SET_CWD 68
|
||||
#define SYS_REAL_PATH 69
|
||||
#define SYS_OPEN_FILE 51
|
||||
#define SYS_READ_FILE 52
|
||||
#define SYS_WRITE_FILE 53
|
||||
#define SYS_READ_FILE_ASYNC 54
|
||||
#define SYS_WRITE_FILE_ASYNC 55
|
||||
#define SYS_CANCEL_IO 56
|
||||
#define SYS_SEEK_FILE 57
|
||||
#define SYS_GET_FILE_POS 58
|
||||
#define SYS_GET_FILE_SIZE 59
|
||||
#define SYS_GET_FILE_STAT 60
|
||||
#define SYS_STAT_FILE 61
|
||||
#define SYS_TRUNCATE_FILE 62
|
||||
#define SYS_FLUSH_FILE 63
|
||||
#define SYS_DELETE_FILE 64
|
||||
#define SYS_RENAME_FILE 65
|
||||
#define SYS_LOCK_FILE 66
|
||||
#define SYS_UNLOCK_FILE 67
|
||||
#define SYS_OPEN_DIR 68
|
||||
#define SYS_READ_DIR 69
|
||||
#define SYS_CREATE_DIR 70
|
||||
#define SYS_REMOVE_DIR 71
|
||||
#define SYS_SET_CWD 72
|
||||
#define SYS_REAL_PATH 73
|
||||
|
||||
// Console, display, and surfaces.
|
||||
#define SYS_WRITE_CONSOLE 70
|
||||
#define SYS_GET_CONSOLE_INFO 71
|
||||
#define SYS_SET_CONSOLE_CURSOR 72
|
||||
#define SYS_FILL_CONSOLE_CHARACTER 73
|
||||
#define SYS_FILL_CONSOLE_ATTRIBUTE 74
|
||||
#define SYS_PUT_SCREEN_CHAR 75
|
||||
#define SYS_CLEAR_SCREEN 76
|
||||
#define SYS_GET_SCREEN_SIZE 77
|
||||
#define SYS_QUERY_DISPLAY_INFO 78
|
||||
#define SYS_CREATE_SURFACE 79
|
||||
#define SYS_MAP_SURFACE 80
|
||||
#define SYS_QUERY_SURFACE 81
|
||||
#define SYS_PRESENT_SURFACE 82
|
||||
#define SYS_WRITE_CONSOLE 74
|
||||
#define SYS_GET_CONSOLE_INFO 75
|
||||
#define SYS_SET_CONSOLE_CURSOR 76
|
||||
#define SYS_FILL_CONSOLE_CHARACTER 77
|
||||
#define SYS_FILL_CONSOLE_ATTRIBUTE 78
|
||||
#define SYS_PUT_SCREEN_CHAR 79
|
||||
#define SYS_CLEAR_SCREEN 80
|
||||
#define SYS_GET_SCREEN_SIZE 81
|
||||
#define SYS_QUERY_DISPLAY_INFO 82
|
||||
#define SYS_CREATE_SURFACE 83
|
||||
#define SYS_MAP_SURFACE 84
|
||||
#define SYS_QUERY_SURFACE 85
|
||||
#define SYS_PRESENT_SURFACE 86
|
||||
|
||||
// Input.
|
||||
#define SYS_POLL_KEYBOARD 83
|
||||
#define SYS_IS_KEY_DOWN 84
|
||||
#define SYS_READ_KEYBOARD_CHAR 85
|
||||
#define SYS_READ_KEY 86
|
||||
#define SYS_GET_KEY_MODIFIERS 87
|
||||
#define SYS_OPEN_INPUT_QUEUE 88
|
||||
#define SYS_READ_INPUT_EVENT 89
|
||||
#define SYS_PEEK_INPUT_EVENT 90
|
||||
#define SYS_PEEK_MOUSE 91
|
||||
#define SYS_READ_MOUSE 92
|
||||
#define SYS_GET_MOUSE_POS 93
|
||||
#define SYS_POLL_KEYBOARD 87
|
||||
#define SYS_IS_KEY_DOWN 88
|
||||
#define SYS_READ_KEYBOARD_CHAR 89
|
||||
#define SYS_READ_KEY 90
|
||||
#define SYS_GET_KEY_MODIFIERS 91
|
||||
#define SYS_OPEN_INPUT_QUEUE 92
|
||||
#define SYS_READ_INPUT_EVENT 93
|
||||
#define SYS_PEEK_INPUT_EVENT 94
|
||||
#define SYS_PEEK_MOUSE 95
|
||||
#define SYS_READ_MOUSE 96
|
||||
#define SYS_GET_MOUSE_POS 97
|
||||
|
||||
// Time, debug, and system information.
|
||||
#define SYS_CREATE_TIMER 94
|
||||
#define SYS_SET_TIMER 95
|
||||
#define SYS_CANCEL_TIMER 96
|
||||
#define SYS_GET_TICK 97
|
||||
#define SYS_GET_TICK_FREQUENCY 98
|
||||
#define SYS_GET_SYSTEM_TIME 99
|
||||
#define SYS_PRINT_DEBUG 100
|
||||
#define SYS_QUERY_TRAP_FRAME 101
|
||||
#define SYS_GET_MEMORY_STATUS 102
|
||||
#define SYS_QUERY_KERNEL_STATS 103
|
||||
#define SYS_CREATE_TIMER 98
|
||||
#define SYS_SET_TIMER 99
|
||||
#define SYS_CANCEL_TIMER 100
|
||||
#define SYS_GET_TICK 101
|
||||
#define SYS_GET_TICK_FREQUENCY 102
|
||||
#define SYS_GET_SYSTEM_TIME 103
|
||||
#define SYS_PRINT_DEBUG 104
|
||||
#define SYS_QUERY_TRAP_FRAME 105
|
||||
#define SYS_GET_MEMORY_STATUS 106
|
||||
#define SYS_QUERY_KERNEL_STATS 107
|
||||
|
||||
// Native sockets and polling.
|
||||
#define SYS_CREATE_SOCKET 104
|
||||
#define SYS_SOCKET_IO_ASYNC 105
|
||||
#define SYS_BIND_SOCKET 106
|
||||
#define SYS_LISTEN_SOCKET 107
|
||||
#define SYS_ACCEPT_SOCKET 108
|
||||
#define SYS_CONNECT_SOCKET 109
|
||||
#define SYS_SEND_SOCKET 110
|
||||
#define SYS_RECV_SOCKET 111
|
||||
#define SYS_SHUTDOWN_SOCKET 112
|
||||
#define SYS_SEND_TO_SOCKET 113
|
||||
#define SYS_RECV_FROM_SOCKET 114
|
||||
#define SYS_RESOLVE_HOST 115
|
||||
#define SYS_SET_SOCKET_OPTION 116
|
||||
#define SYS_GET_SOCKET_OPTION 117
|
||||
#define SYS_POLL 118
|
||||
#define SYS_CREATE_SOCKET 108
|
||||
#define SYS_SOCKET_IO_ASYNC 109
|
||||
#define SYS_BIND_SOCKET 110
|
||||
#define SYS_LISTEN_SOCKET 111
|
||||
#define SYS_ACCEPT_SOCKET 112
|
||||
#define SYS_CONNECT_SOCKET 113
|
||||
#define SYS_SEND_SOCKET 114
|
||||
#define SYS_RECV_SOCKET 115
|
||||
#define SYS_SHUTDOWN_SOCKET 116
|
||||
#define SYS_SEND_TO_SOCKET 117
|
||||
#define SYS_RECV_FROM_SOCKET 118
|
||||
#define SYS_RESOLVE_HOST 119
|
||||
#define SYS_SET_SOCKET_OPTION 120
|
||||
#define SYS_GET_SOCKET_OPTION 121
|
||||
#define SYS_POLL 122
|
||||
#define SYS_UNPUBLISH_QUEUE 123
|
||||
|
||||
#define SYS_MAX 119
|
||||
#define SYS_MAX 124
|
||||
+17
-17
@@ -42,19 +42,19 @@ __declspec(dllexport) KSTATUS IoCreateAsyncRequest(size_t objectSize,
|
||||
IO_ASYNC_REQUEST_CANCEL_ROUTINE cancelRoutine,
|
||||
void* cancelContext,
|
||||
IO_ASYNC_REQUEST_OBJECT** requestOut) {
|
||||
if (!requestOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!requestOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*requestOut = (IO_ASYNC_REQUEST_OBJECT*)0;
|
||||
if (objectSize < sizeof(IO_ASYNC_REQUEST_OBJECT)) return STATUS_INVALID_PARAMETER;
|
||||
if (objectSize < sizeof(IO_ASYNC_REQUEST_OBJECT)) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
IO_ASYNC_REQUEST_OBJECT* request =
|
||||
(IO_ASYNC_REQUEST_OBJECT*)ObAllocateObject(ObjectTypeAsyncIo, objectSize);
|
||||
if (!request) return STATUS_NO_MEMORY;
|
||||
if (!request) return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
request->Header.Destroy = KiIoAsyncRequestDestroy;
|
||||
LIST_INIT(&request->Link);
|
||||
request->State = IoAsyncRequestQueued;
|
||||
request->CancelRequested = 0;
|
||||
request->IosbSnapshot.Status = STATUS_PENDING;
|
||||
request->IosbSnapshot.Status = NTLSTATUS_PENDING;
|
||||
request->IosbSnapshot.Information = 0;
|
||||
request->CleanupRoutine = cleanupRoutine;
|
||||
request->CleanupContext = cleanupContext;
|
||||
@@ -68,7 +68,7 @@ __declspec(dllexport) KSTATUS IoCreateAsyncRequest(size_t objectSize,
|
||||
}
|
||||
|
||||
*requestOut = request;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns the object header embedded in an async request.
|
||||
@@ -90,11 +90,11 @@ __declspec(dllexport) void IoInitializeAsyncRequestCompletion(IO_ASYNC_REQUEST_O
|
||||
request->Iosb = iosb;
|
||||
request->LockedBuffer = lockedBuffer;
|
||||
request->LockedIosb = lockedIosb;
|
||||
request->IosbSnapshot.Status = STATUS_PENDING;
|
||||
request->IosbSnapshot.Status = NTLSTATUS_PENDING;
|
||||
request->IosbSnapshot.Information = 0;
|
||||
|
||||
if (iosb) {
|
||||
iosb->Status = STATUS_PENDING;
|
||||
iosb->Status = NTLSTATUS_PENDING;
|
||||
iosb->Information = 0;
|
||||
}
|
||||
if (completionEvent)
|
||||
@@ -130,34 +130,34 @@ __declspec(dllexport) EVENT* IoGetAsyncRequestWaitEvent(IO_ASYNC_REQUEST_OBJECT*
|
||||
// Waits for an async request to complete according to wait flags.
|
||||
__declspec(dllexport) KSTATUS IoWaitAsyncRequest(IO_ASYNC_REQUEST_OBJECT* request,
|
||||
uint32_t flags) {
|
||||
if (!request || !request->WaitEvent) return STATUS_INVALID_PARAMETER;
|
||||
if (flags & ~SYS_WAIT_FLAG_ALERTABLE) return STATUS_INVALID_PARAMETER;
|
||||
if (!request || !request->WaitEvent) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (flags & ~SYS_WAIT_FLAG_ALERTABLE) return NTLSTATUS_INVALID_PARAMETER;
|
||||
return KeWaitForEvent(request->WaitEvent,
|
||||
(flags & SYS_WAIT_FLAG_ALERTABLE) ? 1 : 0);
|
||||
}
|
||||
|
||||
// Cancels an async request through its operation-family cancel routine.
|
||||
__declspec(dllexport) KSTATUS IoCancelAsyncRequest(IO_ASYNC_REQUEST_OBJECT* request) {
|
||||
if (!request) return STATUS_INVALID_PARAMETER;
|
||||
if (!request) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->CancelRoutine)
|
||||
return request->CancelRoutine(request, request->CancelContext);
|
||||
|
||||
request->CancelRequested = 1;
|
||||
if (request->State == IoAsyncRequestCompleted ||
|
||||
request->State == IoAsyncRequestCancelled)
|
||||
return STATUS_OBJECT_DEAD;
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
return NTLSTATUS_PENDING;
|
||||
}
|
||||
|
||||
// Completes an async request and publishes all caller-visible completion state.
|
||||
__declspec(dllexport) KSTATUS IoCompleteAsyncRequest(IO_ASYNC_REQUEST_OBJECT* request,
|
||||
KSTATUS status,
|
||||
size_t information) {
|
||||
if (!request) return STATUS_INVALID_PARAMETER;
|
||||
if (!request) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
request->IosbSnapshot.Status = status;
|
||||
request->IosbSnapshot.Information = information;
|
||||
request->State = (status == STATUS_CANCELLED) ? IoAsyncRequestCancelled
|
||||
request->State = (status == NTLSTATUS_CANCELLED) ? IoAsyncRequestCancelled
|
||||
: IoAsyncRequestCompleted;
|
||||
|
||||
if (request->Iosb) {
|
||||
@@ -189,14 +189,14 @@ __declspec(dllexport) KSTATUS IoCompleteAsyncRequest(IO_ASYNC_REQUEST_OBJECT* re
|
||||
request->LockedIosb = (MM_LOCKED_USER_BUFFER*)0;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Copies the last completion snapshot out of an async request.
|
||||
__declspec(dllexport) KSTATUS IoQueryAsyncRequest(IO_ASYNC_REQUEST_OBJECT* request,
|
||||
IO_STATUS_BLOCK* iosbOut) {
|
||||
if (!request || !iosbOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!request || !iosbOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
iosbOut->Status = request->IosbSnapshot.Status;
|
||||
iosbOut->Information = request->IosbSnapshot.Information;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
+82
-64
@@ -63,7 +63,7 @@ static bool IoTryAddDeviceForDriver(DRIVER_OBJECT* driver, DEVICE_OBJECT* pdo) {
|
||||
IoSvOrUnnamed(driver->Name), IoSvOrUnnamed(pdo->Name), IoBusTypeName(pdo->u.Pdo.BusType));
|
||||
|
||||
KSTATUS start = IoSendPnpIrpSync(pdo, IRP_MN_START_DEVICE);
|
||||
if (!KSUCCESS(start) && start != STATUS_NOT_SUPPORTED) {
|
||||
if (!KSUCCESS(start) && start != NTLSTATUS_NOT_SUPPORTED) {
|
||||
DbgPrint("io: START_DEVICE failed driver=%v pdo=%v st=0x%x\n",
|
||||
IoSvOrUnnamed(driver->Name), IoSvOrUnnamed(pdo->Name), start);
|
||||
}
|
||||
@@ -87,9 +87,9 @@ __declspec(dllexport) void IoInitializeDriverObject(DRIVER_OBJECT* driver,
|
||||
|
||||
// Registers driver Object.
|
||||
__declspec(dllexport) KSTATUS IoRegisterDriverObject(DRIVER_OBJECT* driver) {
|
||||
if (!driver) return STATUS_INVALID_PARAMETER;
|
||||
if (!driver) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (gDriverObjectCount >= MAX_DRIVER_OBJECTS)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
if (driver->Header.Type != ObjectTypeDriver) {
|
||||
driver->Header.Type = ObjectTypeDriver;
|
||||
@@ -102,7 +102,7 @@ __declspec(dllexport) KSTATUS IoRegisterDriverObject(DRIVER_OBJECT* driver) {
|
||||
for (uint32_t i = 0; i < gPhysicalDeviceCount; i++)
|
||||
(void)IoTryAddDeviceForDriver(driver, gPhysicalDevices[i]);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Device object lifetime.
|
||||
@@ -144,11 +144,11 @@ static KSTATUS IoCreateDeviceInternal(DRIVER_OBJECT* driver,
|
||||
DEVICE_OBJECT_TYPE type,
|
||||
size_t extensionSize,
|
||||
DEVICE_OBJECT** outDevice) {
|
||||
if (!driver || !outDevice) return STATUS_INVALID_PARAMETER;
|
||||
if (!driver || !outDevice) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
size_t total = sizeof(DEVICE_OBJECT) + extensionSize;
|
||||
DEVICE_OBJECT* dev = (DEVICE_OBJECT*)ObAllocateObject(ObjectTypeDevice, total);
|
||||
if (!dev) return STATUS_NO_MEMORY;
|
||||
if (!dev) return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
dev->Header.Destroy = IoDeviceDestroy;
|
||||
dev->DriverObject = driver;
|
||||
@@ -169,7 +169,7 @@ static KSTATUS IoCreateDeviceInternal(DRIVER_OBJECT* driver,
|
||||
dev->DeviceExtension = (void*)((uint8_t*)dev + sizeof(DEVICE_OBJECT));
|
||||
|
||||
*outDevice = dev;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoCreateDevice(DRIVER_OBJECT* driver,
|
||||
@@ -184,8 +184,8 @@ __declspec(dllexport) KSTATUS IoCreatePhysicalDevice(DRIVER_OBJECT* busDriver,
|
||||
size_t idCount,
|
||||
size_t extensionSize,
|
||||
DEVICE_OBJECT** outPdo) {
|
||||
if (!busDriver || !outPdo) return STATUS_INVALID_PARAMETER;
|
||||
if (idCount > IO_MAX_DEVICE_IDS) return STATUS_INVALID_PARAMETER;
|
||||
if (!busDriver || !outPdo) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (idCount > IO_MAX_DEVICE_IDS) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
DEVICE_OBJECT* pdo = (DEVICE_OBJECT*)0;
|
||||
KSTATUS st = IoCreateDeviceInternal(busDriver, DeviceObjectPhysical, extensionSize, &pdo);
|
||||
@@ -195,7 +195,7 @@ __declspec(dllexport) KSTATUS IoCreatePhysicalDevice(DRIVER_OBJECT* busDriver,
|
||||
for (size_t i = 0; i < idCount; i++) {
|
||||
if (!SysSvIsValid(ids[i].Id) || ids[i].Id.Length >= IO_MAX_DEVICE_ID_CHARS) {
|
||||
IoDeleteDevice(pdo);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
char* dst = pdo->u.Pdo.IdStorage[i];
|
||||
@@ -221,21 +221,21 @@ __declspec(dllexport) KSTATUS IoCreatePhysicalDevice(DRIVER_OBJECT* busDriver,
|
||||
}
|
||||
|
||||
*outPdo = pdo;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Registers physical Device.
|
||||
__declspec(dllexport) KSTATUS IoRegisterPhysicalDevice(DEVICE_OBJECT* pdo) {
|
||||
if (!pdo || pdo->Type != DeviceObjectPhysical)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
for (uint32_t i = 0; i < gPhysicalDeviceCount; i++) {
|
||||
if (gPhysicalDevices[i] == pdo)
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
if (gPhysicalDeviceCount >= MAX_PDO_OBJECTS)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
gPhysicalDevices[gPhysicalDeviceCount++] = pdo;
|
||||
|
||||
@@ -250,21 +250,21 @@ __declspec(dllexport) KSTATUS IoRegisterPhysicalDevice(DEVICE_OBJECT* pdo) {
|
||||
DbgPrint("io: no function driver for pdo=%v id=%v bus=%s\n",
|
||||
IoSvOrUnnamed(pdo->Name), id, IoBusTypeName(pdo->u.Pdo.BusType));
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoSetDeviceName(DEVICE_OBJECT* device,
|
||||
SYS_STRING_VIEW name) {
|
||||
if (!device || !SysSvIsValid(name))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (name.Length >= IO_MAX_DEVICE_NAME_CHARS)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
if (name.Length)
|
||||
memcpy(device->NameStorage, name.Data, name.Length);
|
||||
device->NameStorage[name.Length] = '\0';
|
||||
device->Name = SysSvFromParts(device->NameStorage, name.Length);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the reference Device Object operation.
|
||||
@@ -378,12 +378,12 @@ __declspec(dllexport) uint8_t IoGetDeviceStackSize(DEVICE_OBJECT* device) {
|
||||
// Implements the forward Irp To Lower operation.
|
||||
__declspec(dllexport) KSTATUS IoForwardIrpToLower(DEVICE_OBJECT* device, IRP* irp) {
|
||||
if (!device || !irp || !device->LowerDevice)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
IO_STACK_LOCATION* cur = IoGetCurrentIrpStackLocation(irp);
|
||||
IO_STACK_LOCATION* next = IoGetNextIrpStackLocation(irp);
|
||||
if (!cur || !next)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
DEVICE_OBJECT* currentDevice = cur->DeviceObject;
|
||||
memcpy(next, cur, sizeof(*next));
|
||||
@@ -400,10 +400,10 @@ __declspec(dllexport) KSTATUS IoForwardIrpToLower(DEVICE_OBJECT* device, IRP* ir
|
||||
|
||||
__declspec(dllexport) KSTATUS IoSendPnpIrpSync(DEVICE_OBJECT* device,
|
||||
IO_PNP_MINOR_FUNCTION minor) {
|
||||
if (!device) return STATUS_INVALID_PARAMETER;
|
||||
if (!device) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
DEVICE_OBJECT* top = IoGetAttachedDeviceReference(device);
|
||||
if (!top) return STATUS_INVALID_PARAMETER;
|
||||
if (!top) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint8_t stackCount = IoGetDeviceStackSize(top);
|
||||
IRP* irp = (IRP*)0;
|
||||
@@ -611,14 +611,28 @@ static void IoDiskReadAheadNoteWrite(uint8_t driveIndex, uint32_t count) {
|
||||
static void IoNotifyDiskChange(uint8_t driveIndex, DEVICE_OBJECT* device, IO_DEVICE_CHANGE change) {
|
||||
for (uint32_t i = 0; i < gDiskChangeCallbackCount; i++) {
|
||||
IO_DISK_CHANGE_CALLBACK_ENTRY* entry = &gDiskChangeCallbacks[i];
|
||||
if (entry->Used && entry->Callback)
|
||||
entry->Callback(driveIndex, device, change, entry->Context);
|
||||
IO_DISK_CHANGE_CALLBACK callback = entry->Callback;
|
||||
void* context = entry->Context;
|
||||
if (entry->Used && callback) {
|
||||
callback(driveIndex, device, change, context);
|
||||
} else if (entry->Used) {
|
||||
KePanic(KE_PANIC_CODE_DRIVER,
|
||||
"io: disk change callback entry has null callback index=%u ctx=0x%016llX change=%u drive=%u dev=0x%016llX\n",
|
||||
i, context, (uint32_t)change, driveIndex, device);
|
||||
}
|
||||
}
|
||||
if (change == IoDeviceArrived) {
|
||||
for (uint32_t i = 0; i < gDiskArrivalCallbackCount; i++) {
|
||||
IO_DISK_ARRIVAL_CALLBACK_ENTRY* entry = &gDiskArrivalCallbacks[i];
|
||||
if (entry->Used && entry->Callback)
|
||||
entry->Callback(driveIndex, device, entry->Context);
|
||||
IO_DISK_ARRIVAL_CALLBACK callback = entry->Callback;
|
||||
void* context = entry->Context;
|
||||
if (entry->Used && callback) {
|
||||
callback(driveIndex, device, context);
|
||||
} else if (entry->Used) {
|
||||
KePanic(KE_PANIC_CODE_DRIVER,
|
||||
"io: disk arrival callback entry has null callback index=%u ctx=0x%016llX drive=%u dev=0x%016llX\n",
|
||||
i, context, driveIndex, device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,9 +640,9 @@ static void IoNotifyDiskChange(uint8_t driveIndex, DEVICE_OBJECT* device, IO_DEV
|
||||
__declspec(dllexport) KSTATUS IoRegisterDiskDevice(uint8_t driveIndex,
|
||||
DEVICE_OBJECT* device) {
|
||||
if (driveIndex >= MAX_DISK_DEVICES || !device || !device->DriverObject)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (gDiskDevices[driveIndex])
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
|
||||
device->Flags |= DEVICE_OBJECT_DISK;
|
||||
device->u.Disk.DiskIndex = driveIndex;
|
||||
@@ -636,9 +650,9 @@ __declspec(dllexport) KSTATUS IoRegisterDiskDevice(uint8_t driveIndex,
|
||||
device->u.Disk.SectorSize = 512;
|
||||
|
||||
KSTATUS pnpStatus = IoSendPnpIrpSync(device, IRP_MN_START_DEVICE);
|
||||
if (!KSUCCESS(pnpStatus) && pnpStatus != STATUS_NOT_SUPPORTED)
|
||||
if (!KSUCCESS(pnpStatus) && pnpStatus != NTLSTATUS_NOT_SUPPORTED)
|
||||
return pnpStatus;
|
||||
if (pnpStatus == STATUS_NOT_SUPPORTED)
|
||||
if (pnpStatus == NTLSTATUS_NOT_SUPPORTED)
|
||||
device->PnpState = DevicePnpStarted;
|
||||
|
||||
IoDiskReadAheadPrepare(driveIndex);
|
||||
@@ -646,35 +660,35 @@ __declspec(dllexport) KSTATUS IoRegisterDiskDevice(uint8_t driveIndex,
|
||||
IoReferenceDeviceObject(device);
|
||||
gDiskDevices[driveIndex] = device;
|
||||
IoNotifyDiskChange(driveIndex, device, IoDeviceArrived);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the notify Disk Surprise Removed operation.
|
||||
__declspec(dllexport) KSTATUS IoNotifyDiskSurpriseRemoved(uint8_t driveIndex) {
|
||||
if (driveIndex >= MAX_DISK_DEVICES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
DEVICE_OBJECT* dev = gDiskDevices[driveIndex];
|
||||
if (!dev) return STATUS_NOT_FOUND;
|
||||
if (!dev) return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
IoDiskReadAheadInvalidate(driveIndex);
|
||||
|
||||
dev->PnpState = DevicePnpSurpriseRemoved;
|
||||
IoNotifyDiskChange(driveIndex, dev, IoDeviceSurpriseRemoved);
|
||||
(void)IoSendPnpIrpSync(dev, IRP_MN_SURPRISE_REMOVAL);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the unregister Disk Device operation.
|
||||
__declspec(dllexport) KSTATUS IoUnregisterDiskDevice(uint8_t driveIndex) {
|
||||
if (driveIndex >= MAX_DISK_DEVICES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
DEVICE_OBJECT* dev = gDiskDevices[driveIndex];
|
||||
if (!dev) return STATUS_NOT_FOUND;
|
||||
if (!dev) return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
if (dev->PnpState != DevicePnpSurpriseRemoved) {
|
||||
IoNotifyDiskChange(driveIndex, dev, IoDeviceQueryRemove);
|
||||
KSTATUS queryStatus = IoSendPnpIrpSync(dev, IRP_MN_QUERY_REMOVE_DEVICE);
|
||||
if (!KSUCCESS(queryStatus) && queryStatus != STATUS_NOT_SUPPORTED)
|
||||
if (!KSUCCESS(queryStatus) && queryStatus != NTLSTATUS_NOT_SUPPORTED)
|
||||
return queryStatus;
|
||||
|
||||
dev->PnpState = DevicePnpSurpriseRemoved;
|
||||
@@ -689,54 +703,58 @@ __declspec(dllexport) KSTATUS IoUnregisterDiskDevice(uint8_t driveIndex) {
|
||||
IoDiskReadAheadRelease(driveIndex);
|
||||
IoNotifyDiskChange(driveIndex, dev, IoDeviceRemoved);
|
||||
IoDereferenceDeviceObject(dev);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoRegisterDiskArrivalCallback(IO_DISK_ARRIVAL_CALLBACK callback,
|
||||
void* context) {
|
||||
if (!callback)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (gDiskArrivalCallbackCount >= MAX_DISK_CALLBACKS)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
IO_DISK_ARRIVAL_CALLBACK_ENTRY* entry = &gDiskArrivalCallbacks[gDiskArrivalCallbackCount++];
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
entry->Used = true;
|
||||
entry->Callback = callback;
|
||||
entry->Context = context;
|
||||
DbgPrint("io: registered disk arrival callback index=%u cb=0x%016llX ctx=0x%016llX\n",
|
||||
gDiskArrivalCallbackCount - 1u, callback, context);
|
||||
|
||||
for (uint8_t i = 0; i < MAX_DISK_DEVICES; i++) {
|
||||
if (gDiskDevices[i])
|
||||
callback(i, gDiskDevices[i], context);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoRegisterDiskChangeCallback(IO_DISK_CHANGE_CALLBACK callback,
|
||||
void* context) {
|
||||
if (!callback)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (gDiskChangeCallbackCount >= MAX_DISK_CALLBACKS)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
IO_DISK_CHANGE_CALLBACK_ENTRY* entry = &gDiskChangeCallbacks[gDiskChangeCallbackCount++];
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
entry->Used = true;
|
||||
entry->Callback = callback;
|
||||
entry->Context = context;
|
||||
return STATUS_SUCCESS;
|
||||
DbgPrint("io: registered disk change callback index=%u cb=0x%016llX ctx=0x%016llX\n",
|
||||
gDiskChangeCallbackCount - 1u, callback, context);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoEnumerateDiskDevices(IO_DISK_ARRIVAL_CALLBACK callback,
|
||||
void* context) {
|
||||
if (!callback)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
for (uint8_t i = 0; i < MAX_DISK_DEVICES; i++) {
|
||||
if (gDiskDevices[i])
|
||||
callback(i, gDiskDevices[i], context);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns disk Device.
|
||||
@@ -767,31 +785,31 @@ __declspec(dllexport) uint64_t IoDiskSectorCount(uint8_t driveIndex) {
|
||||
|
||||
__declspec(dllexport) KSTATUS IoCallDriver(DEVICE_OBJECT* device, IRP* irp) {
|
||||
if (!device || !device->DriverObject || !irp)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
IO_STACK_LOCATION* ios = IoGetCurrentIrpStackLocation(irp);
|
||||
if (!ios)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
IO_MAJOR_FUNCTION major = ios->MajorFunction;
|
||||
if (major >= IRP_MJ_MAXIMUM_FUNCTION)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
if (major != IRP_MJ_PNP &&
|
||||
(device->DeletePending || device->PnpState == DevicePnpSurpriseRemoved ||
|
||||
device->PnpState == DevicePnpRemovePending || device->PnpState == DevicePnpDeleted))
|
||||
return STATUS_OBJECT_DEAD;
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
|
||||
PDRIVER_DISPATCH dispatch = device->DriverObject->MajorFunction[major];
|
||||
if (!dispatch)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
ios->DeviceObject = device;
|
||||
IoReferenceDeviceObject(device);
|
||||
_InterlockedIncrement(&device->OutstandingIrps);
|
||||
|
||||
KSTATUS st = dispatch(device, irp);
|
||||
if (st != STATUS_PENDING) {
|
||||
if (st != NTLSTATUS_PENDING) {
|
||||
if (ios->DeviceObject == device) {
|
||||
ios->DeviceObject = (DEVICE_OBJECT*)0;
|
||||
_InterlockedDecrement(&device->OutstandingIrps);
|
||||
@@ -803,17 +821,17 @@ __declspec(dllexport) KSTATUS IoCallDriver(DEVICE_OBJECT* device, IRP* irp) {
|
||||
|
||||
// Validates that a sector range fits the disk and IRP byte length.
|
||||
static KSTATUS IoValidateDiskSectorRange(DEVICE_OBJECT* dev, uint64_t lba, uint32_t count) {
|
||||
if (!dev || count == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (count > (0xffffffffu / IO_DISK_SECTOR_BYTES)) return STATUS_INVALID_PARAMETER;
|
||||
if (lba > dev->u.Disk.SectorCount) return STATUS_INVALID_PARAMETER;
|
||||
if ((uint64_t)count > dev->u.Disk.SectorCount - lba) return STATUS_INVALID_PARAMETER;
|
||||
return STATUS_SUCCESS;
|
||||
if (!dev || count == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (count > (0xffffffffu / IO_DISK_SECTOR_BYTES)) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (lba > dev->u.Disk.SectorCount) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if ((uint64_t)count > dev->u.Disk.SectorCount - lba) return NTLSTATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Submits one raw disk read IRP.
|
||||
static KSTATUS IoReadDiskSectorsRaw(DEVICE_OBJECT* dev, uint64_t lba,
|
||||
uint32_t count, void* buffer) {
|
||||
if (!dev || !buffer || count == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!dev || !buffer || count == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
IRP irp;
|
||||
IoBuildReadWriteIrp(&irp, IRP_MJ_READ, lba * 512ull, count * 512u, buffer);
|
||||
@@ -823,7 +841,7 @@ static KSTATUS IoReadDiskSectorsRaw(DEVICE_OBJECT* dev, uint64_t lba,
|
||||
// Submits one raw disk write IRP.
|
||||
static KSTATUS IoWriteDiskSectorsRaw(DEVICE_OBJECT* dev, uint64_t lba,
|
||||
uint32_t count, void* buffer) {
|
||||
if (!dev || !buffer || count == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!dev || !buffer || count == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
IRP irp;
|
||||
IoBuildReadWriteIrp(&irp, IRP_MJ_WRITE, lba * 512ull, count * 512u, buffer);
|
||||
@@ -911,10 +929,10 @@ __declspec(dllexport) KSTATUS IoReadDiskSectors(uint8_t driveIndex,
|
||||
uint64_t lba,
|
||||
uint32_t count,
|
||||
void* buffer) {
|
||||
if (!buffer || count == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!buffer || count == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
DEVICE_OBJECT* dev = IoReferenceDiskDevice(driveIndex);
|
||||
if (!dev) return STATUS_NOT_FOUND;
|
||||
if (!dev) return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
KSTATUS rangeStatus = IoValidateDiskSectorRange(dev, lba, count);
|
||||
if (!KSUCCESS(rangeStatus)) {
|
||||
@@ -926,7 +944,7 @@ __declspec(dllexport) KSTATUS IoReadDiskSectors(uint8_t driveIndex,
|
||||
uint32_t score = IoDiskReadAheadNoteRead(driveIndex, lba, count);
|
||||
IoDiskMaybeReadAhead(driveIndex, dev, lba + count, count, score);
|
||||
IoDereferenceDeviceObject(dev);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS st = IoReadDiskSectorsRaw(dev, lba, count, buffer);
|
||||
@@ -942,10 +960,10 @@ __declspec(dllexport) KSTATUS IoWriteDiskSectors(uint8_t driveIndex,
|
||||
uint64_t lba,
|
||||
uint32_t count,
|
||||
const void* buffer) {
|
||||
if (!buffer || count == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!buffer || count == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
DEVICE_OBJECT* dev = IoReferenceDiskDevice(driveIndex);
|
||||
if (!dev) return STATUS_NOT_FOUND;
|
||||
if (!dev) return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
KSTATUS rangeStatus = IoValidateDiskSectorRange(dev, lba, count);
|
||||
if (!KSUCCESS(rangeStatus)) {
|
||||
|
||||
+129
-129
@@ -183,13 +183,13 @@ static uint64_t KiIoFileLockRemainingMilliseconds(uint64_t deadlineTick) {
|
||||
// Waits for a file-lock conflict to change.
|
||||
static KSTATUS KiIoWaitForFileLockChange(EVENT* event, uint64_t timeoutMilliseconds, uint64_t deadlineTick) {
|
||||
if (!event)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t waitMilliseconds = timeoutMilliseconds;
|
||||
if (timeoutMilliseconds != SYS_WAIT_TIMEOUT_INFINITE) {
|
||||
waitMilliseconds = KiIoFileLockRemainingMilliseconds(deadlineTick);
|
||||
if (waitMilliseconds == 0)
|
||||
return STATUS_TIMEOUT;
|
||||
return NTLSTATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
EVENT* events[1] = { event };
|
||||
@@ -224,7 +224,7 @@ static void KiIoAsyncFileRequestCleanup(IO_ASYNC_REQUEST_OBJECT* async, void* co
|
||||
// Cancels an async file request from the common async request surface.
|
||||
static KSTATUS KiIoCancelAsyncFileRequest(IO_ASYNC_REQUEST_OBJECT* async, void* context) {
|
||||
(void)context;
|
||||
if (!async) return STATUS_INVALID_PARAMETER;
|
||||
if (!async) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gAsyncFileQueueLock);
|
||||
IO_ASYNC_REQUEST_STATE state = IoAsyncRequestGetState(async);
|
||||
@@ -235,19 +235,19 @@ static KSTATUS KiIoCancelAsyncFileRequest(IO_ASYNC_REQUEST_OBJECT* async, void*
|
||||
IoAsyncRequestSetState(async, IoAsyncRequestCancelled);
|
||||
KeReleaseSpinlock(&gAsyncFileQueueLock, flags);
|
||||
|
||||
IoCompleteAsyncRequest(async, STATUS_CANCELLED, 0);
|
||||
IoCompleteAsyncRequest(async, NTLSTATUS_CANCELLED, 0);
|
||||
ObDereferenceObject(&async->Header);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (state == IoAsyncRequestRunning) {
|
||||
IoAsyncRequestRequestCancel(async);
|
||||
KeReleaseSpinlock(&gAsyncFileQueueLock, flags);
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_PENDING;
|
||||
}
|
||||
|
||||
KeReleaseSpinlock(&gAsyncFileQueueLock, flags);
|
||||
return STATUS_OBJECT_DEAD;
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
}
|
||||
|
||||
// Implements the io Async File Dequeue operation.
|
||||
@@ -286,7 +286,7 @@ static void KiIoAsyncFileWorker(void* arg) {
|
||||
if (!req) continue;
|
||||
|
||||
if (IoAsyncRequestIsCancelRequested(&req->Async) || IoAsyncRequestGetState(&req->Async) == IoAsyncRequestCancelled) {
|
||||
IoCompleteAsyncRequest(&req->Async, STATUS_CANCELLED, 0);
|
||||
IoCompleteAsyncRequest(&req->Async, NTLSTATUS_CANCELLED, 0);
|
||||
ObDereferenceObject(&req->Async.Header); // queue/worker reference
|
||||
continue;
|
||||
}
|
||||
@@ -304,7 +304,7 @@ static void KiIoAsyncFileWorker(void* arg) {
|
||||
// The operation may already have reached the filesystem. The
|
||||
// completion contract still reports cancellation so waiters/APCs do
|
||||
// not mistake a cancelled request for useful data.
|
||||
s = STATUS_CANCELLED;
|
||||
s = NTLSTATUS_CANCELLED;
|
||||
done = 0;
|
||||
}
|
||||
|
||||
@@ -318,13 +318,13 @@ static KSTATUS KiIoEnsureAsyncFileIoStarted(void) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gAsyncFileInitLock);
|
||||
if (gAsyncFileInitState == 2) {
|
||||
KeReleaseSpinlock(&gAsyncFileInitLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
if (gAsyncFileInitState == 1) {
|
||||
KeReleaseSpinlock(&gAsyncFileInitLock, flags);
|
||||
while (gAsyncFileInitState == 1)
|
||||
KeYield();
|
||||
return (gAsyncFileInitState == 2) ? STATUS_SUCCESS : STATUS_FAILURE;
|
||||
return (gAsyncFileInitState == 2) ? NTLSTATUS_SUCCESS : NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
gAsyncFileInitState = 1;
|
||||
@@ -359,7 +359,7 @@ static void KiIoNativeFsAsyncComplete(void* completeContext,
|
||||
if (!req) return;
|
||||
|
||||
if (IoAsyncRequestIsCancelRequested(&req->Async)) {
|
||||
status = STATUS_CANCELLED;
|
||||
status = NTLSTATUS_CANCELLED;
|
||||
information = 0;
|
||||
}
|
||||
|
||||
@@ -381,20 +381,20 @@ static KSTATUS KiIoSubmitAsyncFileRequest(IO_ASYNC_FILE_OP op,
|
||||
if (!file || !iosb) {
|
||||
MmUnlockUserBuffer(lockedBuffer);
|
||||
MmUnlockUserBuffer(lockedIosb);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (!buffer && size) {
|
||||
MmUnlockUserBuffer(lockedBuffer);
|
||||
MmUnlockUserBuffer(lockedIosb);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (!KeCanWait()) {
|
||||
MmUnlockUserBuffer(lockedBuffer);
|
||||
MmUnlockUserBuffer(lockedIosb);
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
}
|
||||
|
||||
iosb->Status = STATUS_PENDING;
|
||||
iosb->Status = NTLSTATUS_PENDING;
|
||||
iosb->Information = 0;
|
||||
|
||||
IO_ASYNC_REQUEST_OBJECT* async = (IO_ASYNC_REQUEST_OBJECT*)0;
|
||||
@@ -423,7 +423,7 @@ static KSTATUS KiIoSubmitAsyncFileRequest(IO_ASYNC_FILE_OP op,
|
||||
ObReferenceObject(&file->Header);
|
||||
|
||||
IO_FS_ASYNC_COMPLETE complete = KiIoNativeFsAsyncComplete;
|
||||
KSTATUS ns = STATUS_NOT_SUPPORTED;
|
||||
KSTATUS ns = NTLSTATUS_NOT_SUPPORTED;
|
||||
bool hasNative = (op == IoAsyncFileRead) ? (file->Fs->ReadAsync != 0)
|
||||
: (file->Fs->WriteAsync != 0);
|
||||
|
||||
@@ -440,13 +440,13 @@ static KSTATUS KiIoSubmitAsyncFileRequest(IO_ASYNC_FILE_OP op,
|
||||
ns = file->Fs->WriteAsync(file->Fs, file->FileCtx, offset, buffer,
|
||||
size, complete, req);
|
||||
}
|
||||
if (ns == STATUS_PENDING) {
|
||||
if (ns == NTLSTATUS_PENDING) {
|
||||
if (requestOut) {
|
||||
*requestOut = req;
|
||||
} else {
|
||||
ObDereferenceObject(&req->Async.Header);
|
||||
}
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_PENDING;
|
||||
}
|
||||
|
||||
ObDereferenceObject(&req->Async.Header); // provider rejected synchronously
|
||||
@@ -482,7 +482,7 @@ static KSTATUS KiIoSubmitAsyncFileRequest(IO_ASYNC_FILE_OP op,
|
||||
ObDereferenceObject(&req->Async.Header);
|
||||
}
|
||||
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_PENDING;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoReadFileAsyncKernel(FILE_OBJECT* file, void* buf,
|
||||
@@ -607,12 +607,12 @@ static void KiPopComponent(char* work, size_t* workLen) {
|
||||
// Resolve a possibly-relative string view against the CWD.
|
||||
// The returned view is backed by out->Storage and remains valid while 'out' lives.
|
||||
static KSTATUS KiResolvePathV(SYS_STRING_VIEW input, KRESOLVED_PATH* out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
if (!SysSvIsValid(input)) return STATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(input, '\0')) return STATUS_INVALID_PARAMETER;
|
||||
if (input.Length >= CWD_MAX) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (!SysSvIsValid(input)) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(input, '\0')) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (input.Length >= CWD_MAX) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
uint8_t drive = 0;
|
||||
PROCESS* proc = KeGetCurrentProcess();
|
||||
@@ -662,25 +662,25 @@ static KSTATUS KiResolvePathV(SYS_STRING_VIEW input, KRESOLVED_PATH* out) {
|
||||
KiPopComponent(work, &workLen);
|
||||
continue;
|
||||
}
|
||||
if (compLen >= 256) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (compLen >= 256) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
if (!KiAppendComponent(work, &workLen, sizeof(work), input.Data + compStart, compLen))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (workLen + 1 > sizeof(out->Storage)) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (workLen + 1 > sizeof(out->Storage)) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
memcpy(out->Storage, work, workLen);
|
||||
out->Storage[workLen] = '\0';
|
||||
out->Drive = drive;
|
||||
out->Path = SysSvFromParts(out->Storage, workLen);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Builds a canonical native path using the kernel-owned process CWD.
|
||||
__declspec(dllexport) KSTATUS IoRealPath(SYS_STRING_VIEW path, char* buffer, size_t bufferSize, size_t* requiredSizeOut) {
|
||||
if (requiredSizeOut) *requiredSizeOut = 0;
|
||||
if (path.Length && !path.Data) return STATUS_INVALID_PARAMETER;
|
||||
if (path.Length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!buffer && bufferSize != 0) return STATUS_INVALID_PARAMETER;
|
||||
if (path.Length && !path.Data) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (path.Length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!buffer && bufferSize != 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s = KiResolvePathV(path, &resolved);
|
||||
@@ -688,38 +688,38 @@ __declspec(dllexport) KSTATUS IoRealPath(SYS_STRING_VIEW path, char* buffer, siz
|
||||
|
||||
char formatted[SYS_CWD_MAX];
|
||||
size_t required = KiFormatCwd(resolved.Drive, resolved.Path, formatted, sizeof(formatted));
|
||||
if (!required || required > sizeof(formatted)) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (!required || required > sizeof(formatted)) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
if (requiredSizeOut) *requiredSizeOut = required;
|
||||
if (!buffer) return STATUS_SUCCESS;
|
||||
if (bufferSize < required) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (!buffer) return NTLSTATUS_SUCCESS;
|
||||
if (bufferSize < required) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
memcpy(buffer, formatted, required);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Updates cwd.
|
||||
__declspec(dllexport) KSTATUS IoSetCwd(SYS_STRING_VIEW path) {
|
||||
if (path.Length && !path.Data) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (path.Length && !path.Data) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
PROCESS* proc = KeGetCurrentProcess();
|
||||
if (!proc) return STATUS_ACCESS_DENIED;
|
||||
if (!proc) return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s = KiResolvePathV(path, &resolved);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[resolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->OpenDir) return STATUS_NOT_SUPPORTED;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
if (!fs->OpenDir) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
void* dirCtx = NULL;
|
||||
s = fs->OpenDir(fs, resolved.Path, &dirCtx);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
fs->CloseDir(fs, dirCtx);
|
||||
|
||||
if (resolved.Path.Length + 1 > sizeof(proc->CurrentDirectory)) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (resolved.Path.Length + 1 > sizeof(proc->CurrentDirectory)) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&proc->CwdLock);
|
||||
proc->CurrentDrive = resolved.Drive;
|
||||
@@ -738,7 +738,7 @@ __declspec(dllexport) KSTATUS IoSetCwd(SYS_STRING_VIEW path) {
|
||||
}
|
||||
|
||||
KeReleaseSpinlock(&proc->CwdLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Registration.
|
||||
@@ -746,32 +746,32 @@ __declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t volumeIndex,
|
||||
IO_FILESYSTEM *fs,
|
||||
const IO_VOLUME_PARAMS *vol) {
|
||||
if (volumeIndex >= MAX_DRIVES || !fs || !vol)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (gVolumes[volumeIndex].Fs)
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
gVolumes[volumeIndex].Fs = fs;
|
||||
gVolumes[volumeIndex].Vol = *vol;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the unregister Filesystem operation.
|
||||
__declspec(dllexport) KSTATUS IoUnregisterFilesystem(uint8_t volumeIndex) {
|
||||
if (volumeIndex >= MAX_DRIVES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!gVolumes[volumeIndex].Fs)
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
memset(&gVolumes[volumeIndex], 0, sizeof(gVolumes[volumeIndex]));
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the unregister Filesystems For Disk operation.
|
||||
__declspec(dllexport) KSTATUS IoUnregisterFilesystemsForDisk(uint8_t diskIndex) {
|
||||
KSTATUS last = STATUS_NOT_FOUND;
|
||||
KSTATUS last = NTLSTATUS_NOT_FOUND;
|
||||
for (uint8_t i = 0; i < MAX_DRIVES; i++) {
|
||||
if (gVolumes[i].Fs && gVolumes[i].Vol.DiskIndex == diskIndex) {
|
||||
memset(&gVolumes[i], 0, sizeof(gVolumes[i]));
|
||||
last = STATUS_SUCCESS;
|
||||
last = NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
return last;
|
||||
@@ -827,16 +827,16 @@ static void KiFileDestroy(OBJECT* obj) {
|
||||
|
||||
// IoOpenFile.
|
||||
__declspec(dllexport) KSTATUS IoOpenFile(SYS_STRING_VIEW path, FILE_OBJECT **out) {
|
||||
if ((!path.Data && path.Length) || !out) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (path.Length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if ((!path.Data && path.Length) || !out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
if (path.Length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s = KiResolvePathV(path, &resolved);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[resolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
void* fileCtx;
|
||||
s = fs->Open(fs, resolved.Path, &fileCtx);
|
||||
@@ -845,7 +845,7 @@ __declspec(dllexport) KSTATUS IoOpenFile(SYS_STRING_VIEW path, FILE_OBJECT **out
|
||||
// File objects reuse the generic object slot because the handle table only needs the shared header contract here.
|
||||
FILE_OBJECT* f = (FILE_OBJECT *)ObAllocateObject(ObjectTypeFile,
|
||||
sizeof(FILE_OBJECT));
|
||||
if (!f) { fs->Close(fs, fileCtx); return STATUS_NO_MEMORY; }
|
||||
if (!f) { fs->Close(fs, fileCtx); return NTLSTATUS_NO_MEMORY; }
|
||||
f->Header.Destroy = KiFileDestroy;
|
||||
f->Fs = fs;
|
||||
f->FileCtx = fileCtx;
|
||||
@@ -859,7 +859,7 @@ __declspec(dllexport) KSTATUS IoOpenFile(SYS_STRING_VIEW path, FILE_OBJECT **out
|
||||
f->ReadaheadSuppressedUntil = 0;
|
||||
|
||||
*out = f;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t KiAlignUpPage64(uint64_t value) {
|
||||
@@ -906,7 +906,7 @@ static void KiIoMaybeScheduleReadAhead(FILE_OBJECT* file, uint64_t offset, size_
|
||||
|
||||
if (pages) {
|
||||
KSTATUS ras = MmFileCacheScheduleReadAhead(file, start, pages);
|
||||
if (ras == STATUS_QUEUE_FULL) {
|
||||
if (ras == NTLSTATUS_QUEUE_FULL) {
|
||||
flags = KeAcquireSpinlock(&file->Lock);
|
||||
uint64_t suppressUntil = end + (1024u * 1024u);
|
||||
if (suppressUntil < end || suppressUntil > fileSize)
|
||||
@@ -924,15 +924,15 @@ __declspec(dllexport) KSTATUS IoReadFileAt(FILE_OBJECT* file, uint64_t offset,
|
||||
void* buf, size_t size,
|
||||
size_t* bytesRead) {
|
||||
if (bytesRead) *bytesRead = 0;
|
||||
if (!file || !buf || !bytesRead) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (size == 0) return STATUS_SUCCESS;
|
||||
if (!file || !buf || !bytesRead) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
if (size == 0) return NTLSTATUS_SUCCESS;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&file->Lock);
|
||||
uint64_t fileSize = file->Size;
|
||||
KeReleaseSpinlock(&file->Lock, flags);
|
||||
|
||||
if (offset >= fileSize) return STATUS_SUCCESS;
|
||||
if (offset >= fileSize) return NTLSTATUS_SUCCESS;
|
||||
|
||||
size_t remaining = (size_t)(fileSize - offset);
|
||||
if (size > remaining) size = remaining;
|
||||
@@ -954,7 +954,7 @@ __declspec(dllexport) KSTATUS IoReadFileAt(FILE_OBJECT* file, uint64_t offset,
|
||||
if (!KSUCCESS(s)) {
|
||||
if (total) {
|
||||
*bytesRead = total;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -969,7 +969,7 @@ __declspec(dllexport) KSTATUS IoReadFileAt(FILE_OBJECT* file, uint64_t offset,
|
||||
void* srcPage = MmPfnToVirtual(page.Frame);
|
||||
if (!srcPage) {
|
||||
MmFileCacheReleasePage(&page);
|
||||
return total ? STATUS_SUCCESS : STATUS_FAILURE;
|
||||
return total ? NTLSTATUS_SUCCESS : NTLSTATUS_FAILURE;
|
||||
}
|
||||
memcpy(dst + total, (const uint8_t*)srcPage + inPage, chunk);
|
||||
MmFileCacheReleasePage(&page);
|
||||
@@ -980,17 +980,17 @@ __declspec(dllexport) KSTATUS IoReadFileAt(FILE_OBJECT* file, uint64_t offset,
|
||||
|
||||
*bytesRead = total;
|
||||
KiIoMaybeScheduleReadAhead(file, offset, total, fileSize);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoWriteFileAt(FILE_OBJECT* file, uint64_t offset,
|
||||
const void* buf, size_t size,
|
||||
size_t* bytesWritten) {
|
||||
if (bytesWritten) *bytesWritten = 0;
|
||||
if (!file || !buf || !bytesWritten) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!file->Fs->Write) return STATUS_NOT_SUPPORTED;
|
||||
if (size == 0) return STATUS_SUCCESS;
|
||||
if (!file || !buf || !bytesWritten) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
if (!file->Fs->Write) return NTLSTATUS_NOT_SUPPORTED;
|
||||
if (size == 0) return NTLSTATUS_SUCCESS;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&file->Lock);
|
||||
uint64_t oldSize = file->Size;
|
||||
@@ -1018,8 +1018,8 @@ __declspec(dllexport) KSTATUS IoWriteFileAt(FILE_OBJECT* file, uint64_t offset,
|
||||
|
||||
// Flushes dirty mapped and cached pages for one file object.
|
||||
__declspec(dllexport) KSTATUS IoFlushFile(FILE_OBJECT* file) {
|
||||
if (!file) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!file) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
KSTATUS sync = MmVadSyncFileMappings(file);
|
||||
KSTATUS flush = MmFileCacheFlushFile(file);
|
||||
@@ -1030,7 +1030,7 @@ __declspec(dllexport) KSTATUS IoFlushFile(FILE_OBJECT* file) {
|
||||
__declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf,
|
||||
size_t size, size_t* bytesRead) {
|
||||
if (bytesRead) *bytesRead = 0;
|
||||
if (!file || !buf || !bytesRead) return STATUS_INVALID_PARAMETER;
|
||||
if (!file || !buf || !bytesRead) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&file->Lock);
|
||||
uint64_t offset = file->Offset;
|
||||
@@ -1049,7 +1049,7 @@ __declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf,
|
||||
__declspec(dllexport) KSTATUS IoWriteFile(FILE_OBJECT* file, const void* buf,
|
||||
size_t size, size_t* bytesWritten) {
|
||||
if (bytesWritten) *bytesWritten = 0;
|
||||
if (!file || !buf || !bytesWritten) return STATUS_INVALID_PARAMETER;
|
||||
if (!file || !buf || !bytesWritten) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&file->Lock);
|
||||
uint64_t offset = (file->Flags & IO_FILE_FLAG_APPEND) ? file->Size : file->Offset;
|
||||
@@ -1066,16 +1066,16 @@ __declspec(dllexport) KSTATUS IoWriteFile(FILE_OBJECT* file, const void* buf,
|
||||
|
||||
// IoCreateFile - create a new file and return it open for writing.
|
||||
__declspec(dllexport) KSTATUS IoCreateFile(SYS_STRING_VIEW path, FILE_OBJECT** out) {
|
||||
if ((!path.Data && path.Length) || !out || path.Length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if ((!path.Data && path.Length) || !out || path.Length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s = KiResolvePathV(path, &resolved);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[resolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->Create) return STATUS_NOT_SUPPORTED;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
if (!fs->Create) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
void* fileCtx;
|
||||
s = fs->Create(fs, resolved.Path, &fileCtx);
|
||||
@@ -1083,7 +1083,7 @@ __declspec(dllexport) KSTATUS IoCreateFile(SYS_STRING_VIEW path, FILE_OBJECT** o
|
||||
|
||||
FILE_OBJECT* f = (FILE_OBJECT*)ObAllocateObject(ObjectTypeFile,
|
||||
sizeof(FILE_OBJECT));
|
||||
if (!f) { fs->Close(fs, fileCtx); return STATUS_NO_MEMORY; }
|
||||
if (!f) { fs->Close(fs, fileCtx); return NTLSTATUS_NO_MEMORY; }
|
||||
f->Header.Destroy = KiFileDestroy;
|
||||
f->Fs = fs;
|
||||
f->FileCtx = fileCtx;
|
||||
@@ -1097,21 +1097,21 @@ __declspec(dllexport) KSTATUS IoCreateFile(SYS_STRING_VIEW path, FILE_OBJECT** o
|
||||
f->ReadaheadSuppressedUntil = 0;
|
||||
|
||||
*out = f;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// IoDeleteFile - delete a file by path (does not require an open handle).
|
||||
__declspec(dllexport) KSTATUS IoDeleteFile(SYS_STRING_VIEW path) {
|
||||
if ((!path.Data && path.Length) || path.Length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if ((!path.Data && path.Length) || path.Length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s = KiResolvePathV(path, &resolved);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[resolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->Delete) return STATUS_NOT_SUPPORTED;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
if (!fs->Delete) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
return fs->Delete(fs, resolved.Path);
|
||||
}
|
||||
@@ -1119,8 +1119,8 @@ __declspec(dllexport) KSTATUS IoDeleteFile(SYS_STRING_VIEW path) {
|
||||
// Implements the rename File operation.
|
||||
__declspec(dllexport) KSTATUS IoRenameFile(SYS_STRING_VIEW oldPath, SYS_STRING_VIEW newPath) {
|
||||
if ((!oldPath.Data && oldPath.Length) || (!newPath.Data && newPath.Length) ||
|
||||
oldPath.Length == 0 || newPath.Length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
oldPath.Length == 0 || newPath.Length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
KRESOLVED_PATH oldResolved;
|
||||
KRESOLVED_PATH newResolved;
|
||||
@@ -1128,52 +1128,52 @@ __declspec(dllexport) KSTATUS IoRenameFile(SYS_STRING_VIEW oldPath, SYS_STRING_V
|
||||
if (!KSUCCESS(s)) return s;
|
||||
s = KiResolvePathV(newPath, &newResolved);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
if (oldResolved.Drive != newResolved.Drive) return STATUS_NOT_SUPPORTED;
|
||||
if (oldResolved.Drive != newResolved.Drive) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[oldResolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->Rename) return STATUS_NOT_SUPPORTED;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
if (!fs->Rename) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
return fs->Rename(fs, oldResolved.Path, newResolved.Path);
|
||||
}
|
||||
|
||||
// Creates dir.
|
||||
__declspec(dllexport) KSTATUS IoCreateDir(SYS_STRING_VIEW path) {
|
||||
if ((!path.Data && path.Length) || path.Length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if ((!path.Data && path.Length) || path.Length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s = KiResolvePathV(path, &resolved);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[resolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->CreateDir) return STATUS_NOT_SUPPORTED;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
if (!fs->CreateDir) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
return fs->CreateDir(fs, resolved.Path);
|
||||
}
|
||||
|
||||
// Releases dir.
|
||||
__declspec(dllexport) KSTATUS IoRemoveDir(SYS_STRING_VIEW path) {
|
||||
if ((!path.Data && path.Length) || path.Length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if ((!path.Data && path.Length) || path.Length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s = KiResolvePathV(path, &resolved);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[resolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->RemoveDir) return STATUS_NOT_SUPPORTED;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
if (!fs->RemoveDir) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
return fs->RemoveDir(fs, resolved.Path);
|
||||
}
|
||||
|
||||
// IoTruncateFile - resize the file; updates the cached Size on success.
|
||||
__declspec(dllexport) KSTATUS IoTruncateFile(FILE_OBJECT* file, uint64_t newSize) {
|
||||
if (!file) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!file->Fs->Truncate) return STATUS_NOT_SUPPORTED;
|
||||
if (!file) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
if (!file->Fs->Truncate) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS flush = IoFlushFile(file);
|
||||
if (!KSUCCESS(flush)) return flush;
|
||||
@@ -1190,11 +1190,11 @@ __declspec(dllexport) KSTATUS IoTruncateFile(FILE_OBJECT* file, uint64_t newSize
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) {
|
||||
if (!file) return STATUS_INVALID_PARAMETER;
|
||||
if (!file) return NTLSTATUS_INVALID_PARAMETER;
|
||||
uintptr_t flags = KeAcquireSpinlock(&file->Lock);
|
||||
file->Offset = offset;
|
||||
KeReleaseSpinlock(&file->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns file Size.
|
||||
@@ -1208,7 +1208,7 @@ __declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file) {
|
||||
|
||||
// Queries metadata for an open file object.
|
||||
__declspec(dllexport) KSTATUS IoGetFileStat(FILE_OBJECT* file, SYS_FILE_STAT* out) {
|
||||
if (!file || !out) return STATUS_INVALID_PARAMETER;
|
||||
if (!file || !out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
memset(out, 0, sizeof(*out));
|
||||
out->Size = sizeof(*out);
|
||||
out->Type = SYS_FILE_TYPE_REGULAR;
|
||||
@@ -1216,7 +1216,7 @@ __declspec(dllexport) KSTATUS IoGetFileStat(FILE_OBJECT* file, SYS_FILE_STAT* ou
|
||||
out->FileSize = IoGetFileSize(file);
|
||||
|
||||
if (!file->Fs || !file->Fs->QueryInfo)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
KSTATUS s = file->Fs->QueryInfo(file->Fs, file->FileCtx, out);
|
||||
if (KSUCCESS(s)) {
|
||||
@@ -1229,16 +1229,16 @@ __declspec(dllexport) KSTATUS IoGetFileStat(FILE_OBJECT* file, SYS_FILE_STAT* ou
|
||||
|
||||
// Queries metadata for a filesystem path.
|
||||
__declspec(dllexport) KSTATUS IoStatFile(SYS_STRING_VIEW path, SYS_FILE_STAT* out) {
|
||||
if ((!path.Data && path.Length) || path.Length == 0 || !out) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if ((!path.Data && path.Length) || path.Length == 0 || !out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s = KiResolvePathV(path, &resolved);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[resolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->Stat) return STATUS_NOT_SUPPORTED;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
if (!fs->Stat) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
out->Size = sizeof(*out);
|
||||
@@ -1248,10 +1248,10 @@ __declspec(dllexport) KSTATUS IoStatFile(SYS_STRING_VIEW path, SYS_FILE_STAT* ou
|
||||
// Queries the filesystem identity for a file object.
|
||||
__declspec(dllexport) KSTATUS IoQueryFileIdentity(FILE_OBJECT* file, IO_FILE_IDENTITY* out) {
|
||||
if (!file || !out)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
memset(out, 0, sizeof(*out));
|
||||
if (!file->Fs || !file->Fs->QueryIdentity)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
return file->Fs->QueryIdentity(file->Fs, file->FileCtx, out);
|
||||
}
|
||||
|
||||
@@ -1259,10 +1259,10 @@ __declspec(dllexport) KSTATUS IoQueryFileIdentity(FILE_OBJECT* file, IO_FILE_IDE
|
||||
__declspec(dllexport) KSTATUS IoLockFile(FILE_OBJECT* file, PROCESS* owner, uint32_t mode,
|
||||
uint64_t offset, uint64_t length,
|
||||
uint64_t timeoutMilliseconds) {
|
||||
if (!file || !owner) return STATUS_INVALID_PARAMETER;
|
||||
if (mode != SYS_FILE_LOCK_SHARED && mode != SYS_FILE_LOCK_EXCLUSIVE) return STATUS_INVALID_PARAMETER;
|
||||
if (length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (timeoutMilliseconds != 0 && !KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!file || !owner) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (mode != SYS_FILE_LOCK_SHARED && mode != SYS_FILE_LOCK_EXCLUSIVE) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (timeoutMilliseconds != 0 && !KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
IO_FILE_IDENTITY identity;
|
||||
KSTATUS s = IoQueryFileIdentity(file, &identity);
|
||||
@@ -1282,7 +1282,7 @@ __declspec(dllexport) KSTATUS IoLockFile(FILE_OBJECT* file, PROCESS* owner, uint
|
||||
IO_FILE_LOCK_ENTRY* entry = (IO_FILE_LOCK_ENTRY*)MmAllocatePoolTag(sizeof(*entry), MM_POOL_TAG('f', 'l', 'c', 'k'));
|
||||
if (!entry) {
|
||||
if (waitEvent) ObDereferenceObject(&waitEvent->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFileLockLock);
|
||||
@@ -1296,14 +1296,14 @@ __declspec(dllexport) KSTATUS IoLockFile(FILE_OBJECT* file, PROCESS* owner, uint
|
||||
ListInsertTail(&gFileLocks, &entry->Link);
|
||||
KeReleaseSpinlock(&gFileLockLock, flags);
|
||||
if (waitEvent) ObDereferenceObject(&waitEvent->Header);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KeReleaseSpinlock(&gFileLockLock, flags);
|
||||
MmFreePool(entry);
|
||||
|
||||
if (timeoutMilliseconds == 0) {
|
||||
if (waitEvent) ObDereferenceObject(&waitEvent->Header);
|
||||
return STATUS_WOULD_BLOCK;
|
||||
return NTLSTATUS_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
if (!waitEvent) {
|
||||
@@ -1347,7 +1347,7 @@ __declspec(dllexport) KSTATUS IoLockFile(FILE_OBJECT* file, PROCESS* owner, uint
|
||||
|
||||
// Releases this process's overlapping advisory locks for one file identity.
|
||||
__declspec(dllexport) KSTATUS IoUnlockFile(FILE_OBJECT* file, PROCESS* owner, uint64_t offset, uint64_t length) {
|
||||
if (!file || !owner || length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!file || !owner || length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
IO_FILE_IDENTITY identity;
|
||||
KSTATUS s = IoQueryFileIdentity(file, &identity);
|
||||
@@ -1375,7 +1375,7 @@ __declspec(dllexport) KSTATUS IoUnlockFile(FILE_OBJECT* file, PROCESS* owner, ui
|
||||
KiIoSignalFileLockWaitersLocked(&identity);
|
||||
KeReleaseSpinlock(&gFileLockLock, flags);
|
||||
|
||||
return released ? STATUS_SUCCESS : STATUS_NOT_FOUND;
|
||||
return released ? NTLSTATUS_SUCCESS : NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Releases every advisory file lock owned by one exiting process.
|
||||
@@ -1424,22 +1424,22 @@ static void KiDirDestroy(OBJECT* obj) {
|
||||
|
||||
// Opens dir.
|
||||
__declspec(dllexport) KSTATUS IoOpenDir(SYS_STRING_VIEW dirPath, DIR_OBJECT** out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (dirPath.Length && !dirPath.Data) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (dirPath.Length && !dirPath.Data) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
KRESOLVED_PATH resolved;
|
||||
KSTATUS s;
|
||||
|
||||
if (dirPath.Length == 0) {
|
||||
PROCESS* proc = KeGetCurrentProcess();
|
||||
if (!proc) return STATUS_ACCESS_DENIED;
|
||||
if (!proc) return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&proc->CwdLock);
|
||||
size_t cwdLen = proc->CurrentDirectoryLength;
|
||||
if (cwdLen + 1 > sizeof(resolved.Storage)) {
|
||||
KeReleaseSpinlock(&proc->CwdLock, flags);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
memcpy(resolved.Storage, proc->CurrentDirectory, cwdLen + 1);
|
||||
resolved.Drive = proc->CurrentDrive;
|
||||
@@ -1451,29 +1451,29 @@ __declspec(dllexport) KSTATUS IoOpenDir(SYS_STRING_VIEW dirPath, DIR_OBJECT** ou
|
||||
}
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[resolved.Drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->OpenDir) return STATUS_NOT_SUPPORTED;
|
||||
if (!fs) return NTLSTATUS_NOT_FOUND;
|
||||
if (!fs->OpenDir) return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
void* dirCtx = NULL;
|
||||
s = fs->OpenDir(fs, resolved.Path, &dirCtx);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
DIR_OBJECT* d = (DIR_OBJECT*)ObAllocateObject(ObjectTypeDir, sizeof(DIR_OBJECT));
|
||||
if (!d) { fs->CloseDir(fs, dirCtx); return STATUS_NO_MEMORY; }
|
||||
if (!d) { fs->CloseDir(fs, dirCtx); return NTLSTATUS_NO_MEMORY; }
|
||||
|
||||
d->Header.Destroy = KiDirDestroy;
|
||||
d->Fs = fs;
|
||||
d->DirCtx = dirCtx;
|
||||
|
||||
*out = d;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns dir.
|
||||
__declspec(dllexport) KSTATUS IoReadDir(DIR_OBJECT* dir, KDIR_ENTRY* entryOut) {
|
||||
if (!dir || !entryOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!dir->Fs->ReadDir) return STATUS_NOT_SUPPORTED;
|
||||
if (!dir || !entryOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
if (!dir->Fs->ReadDir) return NTLSTATUS_NOT_SUPPORTED;
|
||||
return dir->Fs->ReadDir(dir->Fs, dir->DirCtx, entryOut);
|
||||
}
|
||||
|
||||
|
||||
+20
-20
@@ -38,12 +38,12 @@ static bool KiUserRflagsValid(uint64_t rflags) {
|
||||
static KSTATUS KiValidateUserApcResumeState(uint64_t rip, uint64_t rsp, uint64_t rflags,
|
||||
uint64_t cs, uint64_t ss) {
|
||||
if (!KiUserAddressValid(rip) || !KiUserAddressValid(rsp))
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
if (cs != KI_USER_CS || ss != KI_USER_SS)
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
if (!KiUserRflagsValid(rflags))
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Allocates a nonzero token for one active user APC return frame.
|
||||
@@ -128,7 +128,7 @@ __declspec(dllexport) bool KeInsertQueueApc(KAPC* apc,
|
||||
|
||||
// If the target opted into an alertable wait, make the APC itself the
|
||||
// wait completion. The target thread will deliver the APC before
|
||||
// KeWaitForEvent(..., true) returns STATUS_KERNEL_APC.
|
||||
// KeWaitForEvent(..., true) returns NTLSTATUS_KERNEL_APC.
|
||||
if (wakeAlertable)
|
||||
KiWakeThreadForKernelApc(thread);
|
||||
|
||||
@@ -238,15 +238,15 @@ void KiDeliverKernelApcs(void) {
|
||||
// Updates user Apc Dispatcher.
|
||||
__declspec(dllexport) KSTATUS KeSetUserApcDispatcher(void* dispatcher) {
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
if (!thread) return STATUS_FAILURE;
|
||||
if (!dispatcher) return STATUS_INVALID_PARAMETER;
|
||||
if (!KiUserAddressValid((uint64_t)(uintptr_t)dispatcher)) return STATUS_ACCESS_DENIED;
|
||||
if (!thread) return NTLSTATUS_FAILURE;
|
||||
if (!dispatcher) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KiUserAddressValid((uint64_t)(uintptr_t)dispatcher)) return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
KSTATUS s = MmProbeUserRead(dispatcher, 1);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
thread->UserApcDispatcher = (uintptr_t)dispatcher;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread,
|
||||
@@ -255,15 +255,15 @@ __declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread,
|
||||
void* systemArgument1,
|
||||
void* systemArgument2) {
|
||||
if (!thread || !routine)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KiUserAddressValid((uint64_t)(uintptr_t)routine))
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
if (thread->State == ThreadDead)
|
||||
return STATUS_OBJECT_DEAD;
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
|
||||
KUSER_APC* apc = (KUSER_APC*)MmAllocatePoolTag(sizeof(KUSER_APC), MM_POOL_TAG('a', 'p', 'c', ' '));
|
||||
if (!apc)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
memset(apc, 0, sizeof(*apc));
|
||||
LIST_INIT(&apc->Link);
|
||||
@@ -283,7 +283,7 @@ __declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread,
|
||||
if (wakeAlertable)
|
||||
KiWakeThreadForUserApc(thread);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the pop User Apc operation.
|
||||
@@ -359,11 +359,11 @@ void KiCheckForUserApcDelivery(KTRAP_FRAME* frame) {
|
||||
thread->UserApcSavedRip = frame->Rip;
|
||||
thread->UserApcSavedRsp = frame->Rsp;
|
||||
thread->UserApcSavedRflags = frame->Rflags;
|
||||
thread->UserApcSavedRax = STATUS_USER_APC;
|
||||
thread->UserApcSavedRax = NTLSTATUS_USER_APC;
|
||||
|
||||
frame->Rip = thread->UserApcDispatcher;
|
||||
frame->Rsp = newRsp;
|
||||
frame->Rax = STATUS_USER_APC;
|
||||
frame->Rax = NTLSTATUS_USER_APC;
|
||||
|
||||
thread->UserApcDeliverable = 0;
|
||||
thread->UserApcDeliveryActive = 1;
|
||||
@@ -416,10 +416,10 @@ void KiRundownApcState(THREAD* thread) {
|
||||
__declspec(dllexport) uint64_t KeUserApcReturn(const SYS_USER_APC_FRAME_K* userFrame) {
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
if (!thread)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
if (!thread->UserApcDeliveryActive || !userFrame)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
SYS_USER_APC_FRAME_K frameCopy;
|
||||
KSTATUS s = CopyFromUser(&frameCopy, userFrame, sizeof(frameCopy));
|
||||
@@ -434,12 +434,12 @@ __declspec(dllexport) uint64_t KeUserApcReturn(const SYS_USER_APC_FRAME_K* userF
|
||||
(uint64_t)thread->UserApcFrameUserAddress,
|
||||
frameCopy.ReturnToken,
|
||||
thread->UserApcReturnToken);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
KTRAP_FRAME* frame = KeGetCurrentTrapFrame();
|
||||
if (!frame || !KeTrapFrameFromUser(frame) || frame->Kind != KTRAP_KIND_SYSCALL)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
s = KiValidateUserApcResumeState(thread->UserApcSavedRip,
|
||||
thread->UserApcSavedRsp,
|
||||
|
||||
+95
-156
@@ -8,6 +8,7 @@
|
||||
#include <kernel/hal/hal_apic.h>
|
||||
#include <intrin.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
#include <kernel/ke_exception.h>
|
||||
#include <kernel/ke_cpu.h>
|
||||
#include <kernel/ke_spinlock.h>
|
||||
#include <kernel/ke_process.h>
|
||||
@@ -220,12 +221,12 @@ __declspec(dllexport) void DbgPrint(const char* fmt, ...) {
|
||||
// Flushes debug Log To File.
|
||||
__declspec(dllexport) KSTATUS KeFlushDebugLogToFile(SYS_STRING_VIEW path) {
|
||||
if (!gDebugLogBuffer || gDebugLogSize == 0 || !SysSvIsValid(path) || path.Length == 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait())
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
if (_InterlockedCompareExchange((volatile long*)&gDebugLogFlushing, 1, 0) != 0)
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_PENDING;
|
||||
|
||||
size_t used;
|
||||
size_t start;
|
||||
@@ -236,7 +237,7 @@ __declspec(dllexport) KSTATUS KeFlushDebugLogToFile(SYS_STRING_VIEW path) {
|
||||
|
||||
if (used == 0) {
|
||||
_InterlockedExchange((volatile long*)&gDebugLogFlushing, 0);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
(void)IoDeleteFile(path);
|
||||
@@ -264,7 +265,7 @@ __declspec(dllexport) KSTATUS KeFlushDebugLogToFile(SYS_STRING_VIEW path) {
|
||||
IoCloseFile(file);
|
||||
|
||||
_InterlockedExchange((volatile long*)&gDebugLogFlushing, 0);
|
||||
return (KSUCCESS(st) && totalWritten == used) ? STATUS_SUCCESS : st;
|
||||
return (KSUCCESS(st) && totalWritten == used) ? NTLSTATUS_SUCCESS : st;
|
||||
}
|
||||
|
||||
// Attempts to persist the debug log during a panic when the filesystem is usable.
|
||||
@@ -348,73 +349,6 @@ static void KiFaultPrintf(const char* format, ...) {
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// KeBugCheckProcess - user-mode fault handler
|
||||
|
||||
// Resolves the faulting RIP to a module name, prints a yellow crash banner,
|
||||
// kills the offending process, then exits the current thread so the scheduler
|
||||
// can continue running everything else.
|
||||
|
||||
// Return the short exception name for a CPU exception vector.
|
||||
// Keep this table complete for vectors 0..31 so faults never collapse into
|
||||
// a vague "general protection" bucket just because the IDT entry existed
|
||||
// first or the crash printer lacked a name.
|
||||
static const char* KiFaultVectorName(int vector) {
|
||||
switch (vector) {
|
||||
case 0: return "#DE Divide Error";
|
||||
case 1: return "#DB Debug";
|
||||
case 2: return "NMI Interrupt";
|
||||
case 3: return "#BP Breakpoint";
|
||||
case 4: return "#OF Overflow";
|
||||
case 5: return "#BR Bound Range Exceeded";
|
||||
case 6: return "#UD Invalid Opcode";
|
||||
case 7: return "#NM Device Not Available";
|
||||
case 8: return "#DF Double Fault";
|
||||
case 9: return "Coprocessor Segment Overrun";
|
||||
case 10: return "#TS Invalid TSS";
|
||||
case 11: return "#NP Segment Not Present";
|
||||
case 12: return "#SS Stack-Segment Fault";
|
||||
case 13: return "#GP General Protection";
|
||||
case 14: return "#PF Page Fault";
|
||||
case 15: return "Reserved Exception 15";
|
||||
case 16: return "#MF x87 Floating-Point Exception";
|
||||
case 17: return "#AC Alignment Check";
|
||||
case 18: return "#MC Machine Check";
|
||||
case 19: return "#XM SIMD Floating-Point Exception";
|
||||
case 20: return "#VE Virtualization Exception";
|
||||
case 21: return "#CP Control Protection Exception";
|
||||
case 22: return "Reserved Exception 22";
|
||||
case 23: return "Reserved Exception 23";
|
||||
case 24: return "Reserved Exception 24";
|
||||
case 25: return "Reserved Exception 25";
|
||||
case 26: return "Reserved Exception 26";
|
||||
case 27: return "Reserved Exception 27";
|
||||
case 28: return "#HV Hypervisor Injection Exception";
|
||||
case 29: return "#VC VMM Communication Exception";
|
||||
case 30: return "#SX Security Exception";
|
||||
case 31: return "Reserved Exception 31";
|
||||
default: return "Unknown Exception";
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the fault Has Error Code operation.
|
||||
static int KiFaultHasErrorCode(int vector) {
|
||||
switch (vector) {
|
||||
case 8: // #DF
|
||||
case 10: // #TS
|
||||
case 11: // #NP
|
||||
case 12: // #SS
|
||||
case 13: // #GP
|
||||
case 14: // #PF
|
||||
case 17: // #AC
|
||||
case 21: // #CP
|
||||
case 29: // #VC
|
||||
case 30: // #SX
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Walk the process module list to find which image owns an address.
|
||||
// Returns the module name string, or "unknown" if the address is outside all
|
||||
// known image ranges. Base/size are optional and are useful for offset dumps.
|
||||
@@ -703,21 +637,9 @@ static void KiDumpFaultFrame(PROCESS* proc, const KFAULT_FRAME* f) {
|
||||
KiDumpUserStack(proc, (uintptr_t)f->Rsp);
|
||||
}
|
||||
|
||||
static KSTATUS KiFaultExitStatus(int vector) {
|
||||
switch (vector) {
|
||||
case 0: return STATUS_PROCESS_DIVIDE_BY_ZERO;
|
||||
case 3: return STATUS_PROCESS_BREAKPOINT;
|
||||
case 6: return STATUS_PROCESS_ILLEGAL_OPCODE;
|
||||
case 13: return STATUS_PROCESS_GENERAL_PROTECTION;
|
||||
case 14: return STATUS_PROCESS_PAGE_FAULT;
|
||||
case 17: return STATUS_PROCESS_ALIGNMENT_FAULT;
|
||||
default: return STATUS_PROCESS_UNKNOWN_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
static void KiPrintCrashHeader(PROCESS* proc, int vector, uintptr_t rip,
|
||||
uintptr_t errCode, uintptr_t cr2) {
|
||||
const char* faultName = KiFaultVectorName(vector);
|
||||
const char* faultName = KeExceptionVectorName((uint32_t)vector);
|
||||
const char* procName = proc ? proc->Name : "unknown";
|
||||
uint32_t pid = proc ? proc->ProcessId : 0;
|
||||
const char* modName = proc ? KiResolveModule(proc, rip) : "unknown";
|
||||
@@ -768,11 +690,79 @@ _Noreturn void KeBugCheckProcess(int vector, uintptr_t rip, uintptr_t errCode, u
|
||||
KiPrintCrashHeader(proc, vector, rip, errCode, cr2);
|
||||
KiDumpModules(proc);
|
||||
|
||||
KiFinishFaultedProcess(proc, thread, KiFaultExitStatus(vector));
|
||||
KiFinishFaultedProcess(proc, thread, KeExceptionProcessExitStatus((uint32_t)vector));
|
||||
}
|
||||
|
||||
// Dispatches a CPU fault frame and returns only when a user #PF was repaired.
|
||||
__declspec(dllexport) KSTATUS KeFaultDispatchFrame(const KFAULT_FRAME* frame) {
|
||||
// Panics after printing a kernel-mode CPU exception report.
|
||||
static _Noreturn void KiPanicKernelFault(PROCESS* proc, THREAD* thread, const KFAULT_FRAME* frame) {
|
||||
KiBeginFatalReport();
|
||||
|
||||
int vector = (int)frame->Vector;
|
||||
const char* name = KeExceptionVectorName((uint32_t)vector);
|
||||
|
||||
DbgPrint("FAULT: kernel exception vector=%d name=%s rip=%016llx rsp=%016llx err=%04llx cr2=%016llx thread=0x%016llX pid=%u proc=%s\n",
|
||||
vector,
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->Rsp,
|
||||
(unsigned long long)frame->ErrorCode,
|
||||
(unsigned long long)frame->Cr2,
|
||||
thread,
|
||||
proc ? proc->ProcessId : 0,
|
||||
proc ? proc->Name : "<none>");
|
||||
KiDumpFaultFrame(proc, frame);
|
||||
if (vector == 14) {
|
||||
MmDebugDescribeAddress((uintptr_t)frame->Cr2);
|
||||
if (frame->Rip) MmDebugDescribeAddress((uintptr_t)frame->Rip);
|
||||
if (frame->Rsp) MmDebugDescribeAddress((uintptr_t)frame->Rsp);
|
||||
MmVadDebugDumpProcess(proc);
|
||||
}
|
||||
|
||||
if (vector == 14) {
|
||||
KePanic(KE_PANIC_CODE_FAULT, "PANIC: %s | RIP: %016llx | RSP: %016llx | Code: %04llx | CR2: %016llx\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->Rsp,
|
||||
(unsigned long long)frame->ErrorCode,
|
||||
(unsigned long long)frame->Cr2);
|
||||
} else if (KeExceptionVectorHasErrorCode((uint32_t)vector)) {
|
||||
const uint8_t* ip = (const uint8_t*)(uintptr_t)frame->Rip;
|
||||
KePanic(KE_PANIC_CODE_FAULT,
|
||||
"PANIC: %s | RIP: %016llx | Code: %04llx | CS=%04llx RFLAGS=%016llx RSP=%016llx | bytes=%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->ErrorCode,
|
||||
(unsigned long long)frame->Cs,
|
||||
(unsigned long long)frame->Rflags,
|
||||
(unsigned long long)frame->Rsp,
|
||||
ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]);
|
||||
} else {
|
||||
const uint8_t* ip = (const uint8_t*)(uintptr_t)frame->Rip;
|
||||
KePanic(KE_PANIC_CODE_FAULT,
|
||||
"PANIC: %s | RIP: %016llx | CS=%04llx RFLAGS=%016llx RSP=%016llx | bytes=%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->Cs,
|
||||
(unsigned long long)frame->Rflags,
|
||||
(unsigned long long)frame->Rsp,
|
||||
ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]);
|
||||
}
|
||||
}
|
||||
|
||||
// Terminates the current process after printing an unhandled user exception report.
|
||||
static _Noreturn void KiTerminateUserFault(PROCESS* proc, THREAD* thread, const KFAULT_FRAME* frame) {
|
||||
KiPrintCrashHeader(proc, (int)frame->Vector,
|
||||
(uintptr_t)frame->Rip,
|
||||
(uintptr_t)frame->ErrorCode,
|
||||
(uintptr_t)frame->Cr2);
|
||||
KiDumpFaultFrame(proc, frame);
|
||||
KiDumpModules(proc);
|
||||
|
||||
KiFinishFaultedProcess(proc, thread, KeExceptionProcessExitStatus((uint32_t)frame->Vector));
|
||||
}
|
||||
|
||||
// Dispatches a CPU fault frame and returns only when a page fault was repaired.
|
||||
__declspec(dllexport) KSTATUS KeFaultDispatchFrame(KFAULT_FRAME* frame) {
|
||||
// Panic NMIs are broadcast to stop all other CPUs. Do not try to decode
|
||||
// the interrupted context on a secondary CPU once another CPU owns panic.
|
||||
if (KiPanicIsActive())
|
||||
@@ -781,93 +771,42 @@ __declspec(dllexport) KSTATUS KeFaultDispatchFrame(const KFAULT_FRAME* frame) {
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
PROCESS* proc = thread ? thread->Owner : (PROCESS*)0;
|
||||
|
||||
if (!frame || frame->Magic != 0x3146544C5541464BULL) {
|
||||
if (!KeFaultFrameIsValid(frame)) {
|
||||
KePanic(KE_PANIC_CODE_FAULT, "PANIC: bad KFAULT_FRAME %016llx\n",
|
||||
(unsigned long long)(uintptr_t)frame);
|
||||
}
|
||||
|
||||
if (frame->Vector == 14) {
|
||||
KSTATUS handled = MmVadResolvePageFaultByAddress((uintptr_t)frame->Cr2, frame->ErrorCode);
|
||||
if (KSUCCESS(handled))
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
KSTATUS repaired = KeExceptionResolveRecoverableFault(frame);
|
||||
if (KSUCCESS(repaired))
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
if ((frame->Cs & 3) == 0) {
|
||||
KiBeginFatalReport();
|
||||
if (!KeFaultFrameFromUser(frame))
|
||||
KiPanicKernelFault(proc, thread, frame);
|
||||
|
||||
int vector = (int)frame->Vector;
|
||||
const char* name = KiFaultVectorName(vector);
|
||||
KSTATUS delivered = KeDeliverUserException(frame);
|
||||
if (KSUCCESS(delivered))
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
DbgPrint("FAULT: kernel exception vector=%d name=%s rip=%016llx rsp=%016llx err=%04llx cr2=%016llx thread=%p pid=%u proc=%s\n",
|
||||
vector,
|
||||
name,
|
||||
if (delivered != NTLSTATUS_NOT_FOUND)
|
||||
DbgPrint("USER/EXC: delivery failed vector=%llu rip=%016llx rsp=%016llx status=%u\n",
|
||||
frame->Vector,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->Rsp,
|
||||
(unsigned long long)frame->ErrorCode,
|
||||
(unsigned long long)frame->Cr2,
|
||||
thread,
|
||||
proc ? proc->ProcessId : 0,
|
||||
proc ? proc->Name : "<none>");
|
||||
KiDumpFaultFrame(proc, frame);
|
||||
if (vector == 14) {
|
||||
MmDebugDescribeAddress((uintptr_t)frame->Cr2);
|
||||
if (frame->Rip) MmDebugDescribeAddress((uintptr_t)frame->Rip);
|
||||
if (frame->Rsp) MmDebugDescribeAddress((uintptr_t)frame->Rsp);
|
||||
MmVadDebugDumpProcess(proc);
|
||||
}
|
||||
delivered);
|
||||
|
||||
if (vector == 14) {
|
||||
KePanic(KE_PANIC_CODE_FAULT, "PANIC: %s | RIP: %016llx | RSP: %016llx | Code: %04llx | CR2: %016llx\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->Rsp,
|
||||
(unsigned long long)frame->ErrorCode,
|
||||
(unsigned long long)frame->Cr2);
|
||||
} else if (KiFaultHasErrorCode(vector)) {
|
||||
const uint8_t* ip = (const uint8_t*)(uintptr_t)frame->Rip;
|
||||
KePanic(KE_PANIC_CODE_FAULT,
|
||||
"PANIC: %s | RIP: %016llx | Code: %04llx | CS=%04llx RFLAGS=%016llx RSP=%016llx | bytes=%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->ErrorCode,
|
||||
(unsigned long long)frame->Cs,
|
||||
(unsigned long long)frame->Rflags,
|
||||
(unsigned long long)frame->Rsp,
|
||||
ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]);
|
||||
} else {
|
||||
const uint8_t* ip = (const uint8_t*)(uintptr_t)frame->Rip;
|
||||
KePanic(KE_PANIC_CODE_FAULT,
|
||||
"PANIC: %s | RIP: %016llx | CS=%04llx RFLAGS=%016llx RSP=%016llx | bytes=%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->Cs,
|
||||
(unsigned long long)frame->Rflags,
|
||||
(unsigned long long)frame->Rsp,
|
||||
ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]);
|
||||
}
|
||||
}
|
||||
|
||||
KiPrintCrashHeader(proc, (int)frame->Vector,
|
||||
(uintptr_t)frame->Rip,
|
||||
(uintptr_t)frame->ErrorCode,
|
||||
(uintptr_t)frame->Cr2);
|
||||
KiDumpFaultFrame(proc, frame);
|
||||
KiDumpModules(proc);
|
||||
|
||||
KiFinishFaultedProcess(proc, thread, KiFaultExitStatus((int)frame->Vector));
|
||||
KiTerminateUserFault(proc, thread, frame);
|
||||
}
|
||||
|
||||
// KeFaultDispatch - single C entry point for all three IDT fault stubs.
|
||||
|
||||
// The asm stubs (ke_syscall.asm) collect the CPU exception frame values and
|
||||
// call here. We check the CS RPL to decide: kernel fault → panic and halt,
|
||||
// user fault → KeBugCheckProcess (kill process, resume scheduler).
|
||||
// The asm stubs collect the CPU exception frame values and call here.
|
||||
// KeFaultDispatchFrame owns the mode split and default unhandled policy.
|
||||
__declspec(dllexport) _Noreturn void KeFaultDispatch(int vector, uintptr_t rip,
|
||||
uintptr_t errCode, uintptr_t cr2,
|
||||
uintptr_t cs) {
|
||||
KFAULT_FRAME frame;
|
||||
memset(&frame, 0, sizeof(frame));
|
||||
frame.Magic = 0x3146544C5541464BULL;
|
||||
frame.Magic = KFAULT_FRAME_MAGIC_VALUE;
|
||||
frame.Vector = (uint64_t)vector;
|
||||
frame.ErrorCode = errCode;
|
||||
frame.Cr2 = cr2;
|
||||
|
||||
+91
-91
@@ -138,10 +138,10 @@ static KSTATUS KiDisplayAcquireProviderMutex(bool* acquired) {
|
||||
*acquired = false;
|
||||
|
||||
if (!gDisplayProviderMutex || !KiDisplayProviderCallbacksRequirePassive())
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
if (!KeCanWait())
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
if (KeGetDebugFlags() & KE_DEBUG_DISPLAY_ASSERTS)
|
||||
KeAssertIrql(PASSIVE_LEVEL);
|
||||
@@ -163,9 +163,9 @@ static KSTATUS KiDisplayFallbackPrintChar(char c, uint32_t fg, uint32_t bg) {
|
||||
const HAL_API* hal = gDisplayHal;
|
||||
if (hal && hal->Screen.PrintChar) {
|
||||
hal->Screen.PrintChar(c, fg, bg);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
}
|
||||
|
||||
static void KiDisplayQueueCursorWork(void) {
|
||||
@@ -259,7 +259,7 @@ static void KiDisplayCursorWorker(void* context) {
|
||||
bool positionCommitted = false;
|
||||
int newCommittedX = committedX;
|
||||
int newCommittedY = committedY;
|
||||
KSTATUS status = STATUS_SUCCESS;
|
||||
KSTATUS status = NTLSTATUS_SUCCESS;
|
||||
bool hasCursorOps = device && ops && ops->ShowCursor &&
|
||||
(caps & (DISPLAY_CAP_SOFTWARE_CURSOR | DISPLAY_CAP_HARDWARE_CURSOR));
|
||||
bool softwareCursor = hasCursorOps && (caps & DISPLAY_CAP_SOFTWARE_CURSOR) != 0;
|
||||
@@ -446,7 +446,7 @@ static void KiDisplayRecordCopyLocked(const DISPLAY_MODE* mode, int dstX, int ds
|
||||
|
||||
static KSTATUS KiDisplayFlushDirtyWithSnapshot(DISPLAY_DEVICE* device, const DISPLAY_DEVICE_OPS* ops) {
|
||||
if (!device || !ops || !ops->Present)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
DISPLAY_RECT localRects[DISPLAY_MAX_DIRTY_RECTS];
|
||||
DISPLAY_RECT fullRect;
|
||||
@@ -457,7 +457,7 @@ static KSTATUS KiDisplayFlushDirtyWithSnapshot(DISPLAY_DEVICE* device, const DIS
|
||||
uintptr_t flags = KeAcquireSpinlock(&gDisplayLock);
|
||||
if (device != gPrimaryDisplay || (!gDirtyAll && gDirtyRectCount == 0)) {
|
||||
KeReleaseSpinlock(&gDisplayLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
dirtyAll = gDirtyAll;
|
||||
@@ -473,7 +473,7 @@ static KSTATUS KiDisplayFlushDirtyWithSnapshot(DISPLAY_DEVICE* device, const DIS
|
||||
if (dirtyAll) {
|
||||
DISPLAY_MODE mode;
|
||||
if (!ops->GetMode)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
KSTATUS ms = ops->GetMode(device, &mode);
|
||||
if (!KSUCCESS(ms))
|
||||
return ms;
|
||||
@@ -578,9 +578,9 @@ static KSTATUS KiDisplayGetProviderSnapshot(DISPLAY_DEVICE** outDevice,
|
||||
uint32_t caps = 0;
|
||||
|
||||
if (!KiDisplaySnapshotPrimary(&device, &ops, &caps, 0) || !device || !ops)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
if (!ops->GetMode)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS s = ops->GetMode(device, outMode);
|
||||
if (!KSUCCESS(s))
|
||||
@@ -589,7 +589,7 @@ static KSTATUS KiDisplayGetProviderSnapshot(DISPLAY_DEVICE** outDevice,
|
||||
if (outDevice) *outDevice = device;
|
||||
if (outOps) *outOps = ops;
|
||||
if (outCaps) *outCaps = caps;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void KiDisplayBuildGlyphPixels(char c, uint32_t fg, uint32_t bg, uint32_t* outPixels) {
|
||||
@@ -610,7 +610,7 @@ static KSTATUS KiDisplayBlitGlyphSnapshot(DISPLAY_DEVICE* device,
|
||||
uint32_t fg,
|
||||
uint32_t bg) {
|
||||
if (!device || !ops || !ops->Blit || !mode)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
uint32_t glyphPixels[FONT_W * FONT_H];
|
||||
KiDisplayBuildGlyphPixels(c, fg, bg, glyphPixels);
|
||||
@@ -633,9 +633,9 @@ static KSTATUS KiDisplayDrawBlitSnapshot(DISPLAY_DEVICE* device,
|
||||
int h,
|
||||
const uint32_t* pixels) {
|
||||
if (!pixels || w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!device || !ops || !ops->Blit || !mode)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS s = ops->Blit(device, x, y, w, h, pixels);
|
||||
if (KSUCCESS(s)) {
|
||||
@@ -656,9 +656,9 @@ static KSTATUS KiDisplayFillRectSnapshot(DISPLAY_DEVICE* device,
|
||||
int h,
|
||||
uint32_t color) {
|
||||
if (w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!device || !ops || !ops->FillRect || !mode)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS s = ops->FillRect(device, x, y, w, h, color);
|
||||
if (KSUCCESS(s)) {
|
||||
@@ -680,9 +680,9 @@ static KSTATUS KiDisplayCopyRectSnapshot(DISPLAY_DEVICE* device,
|
||||
int w,
|
||||
int h) {
|
||||
if (w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!device || !ops || !ops->CopyRect || !mode)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS s = ops->CopyRect(device, dstX, dstY, srcX, srcY, w, h);
|
||||
if (KSUCCESS(s)) {
|
||||
@@ -698,7 +698,7 @@ static KSTATUS KiDisplayFinishProviderDraw(DISPLAY_DEVICE* device,
|
||||
const DISPLAY_DEVICE_OPS* ops,
|
||||
uint32_t caps,
|
||||
KSTATUS drawStatus) {
|
||||
KSTATUS presentStatus = STATUS_SUCCESS;
|
||||
KSTATUS presentStatus = NTLSTATUS_SUCCESS;
|
||||
if (KSUCCESS(drawStatus))
|
||||
presentStatus = KiDisplayFlushDirtyWithSnapshot(device, ops);
|
||||
KiDisplayRestoreCursorAfterDrawSnapshot(device, ops, caps);
|
||||
@@ -743,9 +743,9 @@ static void KiDisplayAddDirty(int x, int y, int w, int h) {
|
||||
// Implements the display Flush Dirty operation.
|
||||
static KSTATUS KiDisplayFlushDirty(void) {
|
||||
if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->Present)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
if (!gDirtyAll && gDirtyRectCount == 0)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
DISPLAY_RECT full;
|
||||
const DISPLAY_RECT* rects = gDirtyRects;
|
||||
@@ -803,7 +803,7 @@ static void KiDisplayBeginDraw(void) {
|
||||
|
||||
// Implements the display End Draw operation.
|
||||
static KSTATUS KiDisplayEndDraw(void) {
|
||||
KSTATUS s = STATUS_SUCCESS;
|
||||
KSTATUS s = NTLSTATUS_SUCCESS;
|
||||
if (gDrawDepth > 0)
|
||||
gDrawDepth--;
|
||||
|
||||
@@ -817,9 +817,9 @@ static KSTATUS KiDisplayEndDraw(void) {
|
||||
// Implements the display Draw Blit No Cursor operation.
|
||||
static KSTATUS KiDisplayDrawBlitNoCursor(int x, int y, int w, int h, const uint32_t* pixels) {
|
||||
if (!pixels || w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->Blit)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS s = gPrimaryDisplay->Ops->Blit(gPrimaryDisplay, x, y, w, h, pixels);
|
||||
if (KSUCCESS(s)) {
|
||||
@@ -833,9 +833,9 @@ static KSTATUS KiDisplayDrawBlitNoCursor(int x, int y, int w, int h, const uint3
|
||||
// Implements the display Fill Rect No Cursor operation.
|
||||
static KSTATUS KiDisplayFillRectNoCursor(int x, int y, int w, int h, uint32_t color) {
|
||||
if (w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->FillRect)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS s = gPrimaryDisplay->Ops->FillRect(gPrimaryDisplay, x, y, w, h, color);
|
||||
if (KSUCCESS(s)) {
|
||||
@@ -849,9 +849,9 @@ static KSTATUS KiDisplayFillRectNoCursor(int x, int y, int w, int h, uint32_t co
|
||||
// Implements the display Copy Rect No Cursor operation.
|
||||
static KSTATUS KiDisplayCopyRectNoCursor(int dstX, int dstY, int srcX, int srcY, int w, int h) {
|
||||
if (w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->CopyRect)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS s = gPrimaryDisplay->Ops->CopyRect(gPrimaryDisplay, dstX, dstY, srcX, srcY, w, h);
|
||||
if (KSUCCESS(s)) {
|
||||
@@ -1180,13 +1180,13 @@ void KeDisplayInitialize(const HAL_API* hal) {
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayRegisterDevice(DISPLAY_DEVICE* device) {
|
||||
if (!device || !device->Name || !device->Ops || !device->Ops->GetMode)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS result = STATUS_SUCCESS;
|
||||
KSTATUS result = NTLSTATUS_SUCCESS;
|
||||
uintptr_t flags = KeAcquireSpinlock(&gDisplayLock);
|
||||
for (DISPLAY_DEVICE* it = gDisplayList; it; it = it->Next) {
|
||||
if (it == device) {
|
||||
result = STATUS_ALREADY_EXISTS;
|
||||
result = NTLSTATUS_ALREADY_EXISTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1205,10 +1205,10 @@ DISPLAY_API KSTATUS KeDisplayRegisterDevice(DISPLAY_DEVICE* device) {
|
||||
// Implements the display Seed New Primary operation.
|
||||
static KSTATUS KiDisplaySeedNewPrimary(DISPLAY_DEVICE* oldDevice, DISPLAY_DEVICE* newDevice) {
|
||||
if (!oldDevice || !newDevice || oldDevice == newDevice)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
if (!oldDevice->Ops || !oldDevice->Ops->ReadRect ||
|
||||
!newDevice->Ops || !newDevice->Ops->GetMode || !newDevice->Ops->Blit)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
DISPLAY_MODE oldMode;
|
||||
DISPLAY_MODE newMode;
|
||||
@@ -1221,11 +1221,11 @@ static KSTATUS KiDisplaySeedNewPrimary(DISPLAY_DEVICE* oldDevice, DISPLAY_DEVICE
|
||||
if (oldMode.Format != DisplayPixelFormatX8R8G8B8 ||
|
||||
newMode.Format != DisplayPixelFormatX8R8G8B8 ||
|
||||
oldMode.Width != newMode.Width || oldMode.Height != newMode.Height)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
uint32_t* row = (uint32_t*)MmAllocatePool((size_t)newMode.Width * sizeof(uint32_t));
|
||||
if (!row)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
for (uint32_t y = 0; y < newMode.Height; y++) {
|
||||
s = oldDevice->Ops->ReadRect(oldDevice, 0, (int)y, (int)newMode.Width, 1, row, newMode.Width);
|
||||
@@ -1251,7 +1251,7 @@ static bool KiDisplayOutputSuspended(void) {
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplaySetPrimary(DISPLAY_DEVICE* device) {
|
||||
if (!device || !device->Ops || !device->Ops->GetMode)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
const char* name = device->Name ? device->Name : "?";
|
||||
|
||||
@@ -1265,7 +1265,7 @@ DISPLAY_API KSTATUS KeDisplaySetPrimary(DISPLAY_DEVICE* device) {
|
||||
}
|
||||
if (!found) {
|
||||
KeReleaseSpinlock(&gDisplayLock, flags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
DISPLAY_DEVICE* oldDevice = gPrimaryDisplay;
|
||||
@@ -1342,7 +1342,7 @@ DISPLAY_API KSTATUS KeDisplaySetPrimary(DISPLAY_DEVICE* device) {
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayGetMode(DISPLAY_MODE* outMode) {
|
||||
if (!outMode)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
bool providerHeld = false;
|
||||
KSTATUS s = KiDisplayAcquireProviderMutex(&providerHeld);
|
||||
@@ -1355,7 +1355,7 @@ DISPLAY_API KSTATUS KeDisplayGetMode(DISPLAY_MODE* outMode) {
|
||||
KeReleaseSpinlock(&gDisplayLock, flags);
|
||||
|
||||
s = (!device || !ops || !ops->GetMode)
|
||||
? STATUS_INVALID_PARAMETER
|
||||
? NTLSTATUS_INVALID_PARAMETER
|
||||
: ops->GetMode(device, outMode);
|
||||
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
@@ -1369,7 +1369,7 @@ DISPLAY_API KSTATUS KeDisplayGetSize(int* outWidth, int* outHeight) {
|
||||
return s;
|
||||
if (outWidth) *outWidth = (int)mode.Width;
|
||||
if (outHeight) *outHeight = (int)mode.Height;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplaySync(void) {
|
||||
@@ -1385,7 +1385,7 @@ DISPLAY_API KSTATUS KeDisplaySync(void) {
|
||||
|
||||
if (!device || !ops || !ops->Sync) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
s = ops->Sync(device);
|
||||
@@ -1401,7 +1401,7 @@ DISPLAY_API KSTATUS KeDisplaySync(void) {
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayQueryInfo(KE_DISPLAY_INFO* outInfo) {
|
||||
if (!outInfo)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
bool providerHeld = false;
|
||||
KSTATUS s = KiDisplayAcquireProviderMutex(&providerHeld);
|
||||
@@ -1435,7 +1435,7 @@ DISPLAY_API KSTATUS KeDisplayQueryInfo(KE_DISPLAY_INFO* outInfo) {
|
||||
|
||||
if (!device || !ops) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (ops->GetMode) {
|
||||
@@ -1451,7 +1451,7 @@ DISPLAY_API KSTATUS KeDisplayQueryInfo(KE_DISPLAY_INFO* outInfo) {
|
||||
|
||||
*outInfo = info;
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayBlit(int x, int y, int w, int h, const uint32_t* pixels) {
|
||||
@@ -1477,7 +1477,7 @@ DISPLAY_API KSTATUS KeDisplayBlit(int x, int y, int w, int h, const uint32_t* pi
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayBlitRows(int x, int y, int w, int h, KE_DISPLAY_ROW_SOURCE source, void* context, uint32_t* scratch) {
|
||||
if (!source || !scratch || w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
bool providerHeld = false;
|
||||
KSTATUS s = KiDisplayAcquireProviderMutex(&providerHeld);
|
||||
@@ -1580,7 +1580,7 @@ DISPLAY_API KSTATUS KeDisplayCopyRect(int dstX, int dstY, int srcX, int srcY, in
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayScroll(int lines) {
|
||||
if (lines <= 0)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
bool providerHeld = false;
|
||||
KSTATUS s = KiDisplayAcquireProviderMutex(&providerHeld);
|
||||
@@ -1646,7 +1646,7 @@ static KSTATUS KiDisplayPrintCharInternal(char c, uint32_t fg, uint32_t bg) {
|
||||
if (KiDisplayOutputSuspended()) {
|
||||
if (!KeCanWait())
|
||||
return KiDisplayFallbackPrintChar(c, fg, bg);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Once the scheduler/work-queue era begins, display provider callbacks are
|
||||
@@ -1677,7 +1677,7 @@ static KSTATUS KiDisplayPrintCharInternal(char c, uint32_t fg, uint32_t bg) {
|
||||
int rows = 0;
|
||||
if (!KiDisplayConsoleGridFromMode(&mode, &cols, &rows)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_DEVICE_ERROR;
|
||||
return NTLSTATUS_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
(void)KiDisplayHideCursorForDrawSnapshot(device, ops, caps);
|
||||
@@ -1726,7 +1726,7 @@ static KSTATUS KiDisplayPrintCharInternal(char c, uint32_t fg, uint32_t bg) {
|
||||
KeReleaseSpinlock(&gDisplayLock, flags);
|
||||
}
|
||||
} else {
|
||||
s = STATUS_SUCCESS;
|
||||
s = NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (KSUCCESS(s) && needScroll) {
|
||||
@@ -1760,7 +1760,7 @@ DISPLAY_API KSTATUS KeDisplayPrintChar(char c, uint32_t fg, uint32_t bg) {
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayGetConsoleInfo(KE_CONSOLE_INFO* outInfo) {
|
||||
if (!outInfo)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
bool providerHeld = false;
|
||||
KSTATUS s = KiDisplayAcquireProviderMutex(&providerHeld);
|
||||
@@ -1775,14 +1775,14 @@ DISPLAY_API KSTATUS KeDisplayGetConsoleInfo(KE_CONSOLE_INFO* outInfo) {
|
||||
s = KiDisplayGetProviderSnapshot(&device, &ops, &caps, &mode);
|
||||
if (!KSUCCESS(s)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int cols = 0;
|
||||
int rows = 0;
|
||||
if (!KiDisplayConsoleGridFromMode(&mode, &cols, &rows)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gDisplayLock);
|
||||
@@ -1794,7 +1794,7 @@ DISPLAY_API KSTATUS KeDisplayGetConsoleInfo(KE_CONSOLE_INFO* outInfo) {
|
||||
KeReleaseSpinlock(&gDisplayLock, flags);
|
||||
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplaySetConsoleCursor(int col, int row) {
|
||||
@@ -1811,18 +1811,18 @@ DISPLAY_API KSTATUS KeDisplaySetConsoleCursor(int col, int row) {
|
||||
s = KiDisplayGetProviderSnapshot(&device, &ops, &caps, &mode);
|
||||
if (!KSUCCESS(s)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int cols = 0;
|
||||
int rows = 0;
|
||||
if (!KiDisplayConsoleGridFromMode(&mode, &cols, &rows)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
if (col < 0 || row < 0 || col >= cols || row >= rows) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gDisplayLock);
|
||||
@@ -1831,7 +1831,7 @@ DISPLAY_API KSTATUS KeDisplaySetConsoleCursor(int col, int row) {
|
||||
KeReleaseSpinlock(&gDisplayLock, flags);
|
||||
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayFillConsoleChars(char c, int col, int row, size_t length, size_t* writtenOut) {
|
||||
@@ -1849,18 +1849,18 @@ DISPLAY_API KSTATUS KeDisplayFillConsoleChars(char c, int col, int row, size_t l
|
||||
s = KiDisplayGetProviderSnapshot(&device, &ops, &caps, &mode);
|
||||
if (!KSUCCESS(s)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int cols = 0;
|
||||
int rows = 0;
|
||||
if (!KiDisplayConsoleGridFromMode(&mode, &cols, &rows)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
if (col < 0 || row < 0 || col >= cols || row >= rows) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
(void)KiDisplayHideCursorForDrawSnapshot(device, ops, caps);
|
||||
@@ -1918,18 +1918,18 @@ DISPLAY_API KSTATUS KeDisplayFillConsoleAttrs(uint16_t attr, int col, int row, s
|
||||
s = KiDisplayGetProviderSnapshot(&device, &ops, &caps, &mode);
|
||||
if (!KSUCCESS(s)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int cols = 0;
|
||||
int rows = 0;
|
||||
if (!KiDisplayConsoleGridFromMode(&mode, &cols, &rows)) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
if (col < 0 || row < 0 || col >= cols || row >= rows) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
(void)KiDisplayHideCursorForDrawSnapshot(device, ops, caps);
|
||||
@@ -1989,7 +1989,7 @@ DISPLAY_API KSTATUS KeDisplayPresent(const DISPLAY_RECT* rects, size_t rectCount
|
||||
}
|
||||
if (!ops->Present) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
(void)KiDisplayHideCursorForDrawSnapshot(device, ops, caps);
|
||||
@@ -2024,7 +2024,7 @@ DISPLAY_API KSTATUS KeDisplaySetCursorImage(int width, int height, int hotX, int
|
||||
|
||||
if (!device || !ops || !ops->SetCursorImage) {
|
||||
KiDisplayReleaseProviderMutex(providerHeld);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
s = ops->SetCursorImage(device, width, height, hotX, hotY, argbPixels);
|
||||
@@ -2049,7 +2049,7 @@ DISPLAY_API KSTATUS KeDisplaySetCursorPosition(int x, int y) {
|
||||
|
||||
if (shouldQueue)
|
||||
KiDisplayQueueCursorWork();
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DISPLAY_API KSTATUS KeDisplayShowCursor(bool show) {
|
||||
@@ -2071,7 +2071,7 @@ DISPLAY_API KSTATUS KeDisplayShowCursor(bool show) {
|
||||
|
||||
if (shouldQueue)
|
||||
KiDisplayQueueCursorWork();
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Context operation.
|
||||
@@ -2083,20 +2083,20 @@ static BOOTFB_CONTEXT* BootFbContext(DISPLAY_DEVICE* device) {
|
||||
static KSTATUS BootFbGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMode) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (!fb || !fb->Framebuffer || !outMode)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
outMode->Width = fb->Width;
|
||||
outMode->Height = fb->Height;
|
||||
outMode->Stride = fb->Stride;
|
||||
outMode->Format = DisplayPixelFormatX8R8G8B8;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Blit operation.
|
||||
static KSTATUS BootFbBlit(DISPLAY_DEVICE* device, int x, int y, int w, int h, const uint32_t* pixels) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (!fb || !fb->Framebuffer || !pixels || w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint32_t* dstBase = fb->Backbuffer ? fb->Backbuffer : fb->Framebuffer;
|
||||
|
||||
@@ -2105,7 +2105,7 @@ static KSTATUS BootFbBlit(DISPLAY_DEVICE* device, int x, int y, int w, int h, co
|
||||
int endX = x + w > (int)fb->Width ? (int)fb->Width : x + w;
|
||||
int endY = y + h > (int)fb->Height ? (int)fb->Height : y + h;
|
||||
if (startX >= endX || startY >= endY)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
int srcOffsetX = startX - x;
|
||||
int srcOffsetY = startY - y;
|
||||
@@ -2119,14 +2119,14 @@ static KSTATUS BootFbBlit(DISPLAY_DEVICE* device, int x, int y, int w, int h, co
|
||||
const uint32_t* src = pixels + ((size_t)(srcOffsetY + row) * (size_t)w) + srcOffsetX;
|
||||
memcpy(dst, src, bytesPerRow);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Fill Rect operation.
|
||||
static KSTATUS BootFbFillRect(DISPLAY_DEVICE* device, int x, int y, int w, int h, uint32_t color) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (!fb || !fb->Framebuffer || w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint32_t* dstBase = fb->Backbuffer ? fb->Backbuffer : fb->Framebuffer;
|
||||
|
||||
@@ -2135,7 +2135,7 @@ static KSTATUS BootFbFillRect(DISPLAY_DEVICE* device, int x, int y, int w, int h
|
||||
int endX = x + w > (int)fb->Width ? (int)fb->Width : x + w;
|
||||
int endY = y + h > (int)fb->Height ? (int)fb->Height : y + h;
|
||||
if (startX >= endX || startY >= endY)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
fb->Stats.FillRectCount++;
|
||||
fb->Stats.BytesCopied += (uint64_t)(endX - startX) * (uint64_t)(endY - startY) * sizeof(uint32_t);
|
||||
@@ -2145,14 +2145,14 @@ static KSTATUS BootFbFillRect(DISPLAY_DEVICE* device, int x, int y, int w, int h
|
||||
for (int xx = startX; xx < endX; xx++)
|
||||
*dst++ = color;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Copy Rect operation.
|
||||
static KSTATUS BootFbCopyRect(DISPLAY_DEVICE* device, int dstX, int dstY, int srcX, int srcY, int w, int h) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (!fb || !fb->Framebuffer || w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint32_t* base = fb->Backbuffer ? fb->Backbuffer : fb->Framebuffer;
|
||||
|
||||
@@ -2165,7 +2165,7 @@ static KSTATUS BootFbCopyRect(DISPLAY_DEVICE* device, int dstX, int dstY, int sr
|
||||
if (srcY + h > (int)fb->Height) h = (int)fb->Height - srcY;
|
||||
if (dstY + h > (int)fb->Height) h = (int)fb->Height - dstY;
|
||||
if (w <= 0 || h <= 0)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
fb->Stats.CopyRectCount++;
|
||||
fb->Stats.BytesCopied += (uint64_t)(uint32_t)w * (uint64_t)(uint32_t)h * sizeof(uint32_t);
|
||||
@@ -2184,20 +2184,20 @@ static KSTATUS BootFbCopyRect(DISPLAY_DEVICE* device, int dstX, int dstY, int sr
|
||||
memmove(dst, src, rowBytes);
|
||||
}
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Read Rect operation.
|
||||
static KSTATUS BootFbReadRect(DISPLAY_DEVICE* device, int x, int y, int w, int h, uint32_t* outPixels, uint32_t outStride) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (!fb || !fb->Framebuffer || !outPixels || outStride == 0 || w <= 0 || h <= 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint32_t* srcBase = fb->Backbuffer ? fb->Backbuffer : fb->Framebuffer;
|
||||
DISPLAY_MODE mode = { fb->Width, fb->Height, fb->Stride, DisplayPixelFormatX8R8G8B8 };
|
||||
DISPLAY_RECT r = { x, y, w, h };
|
||||
if (!KiDisplayClipRect(&mode, &r))
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
fb->Stats.ReadRectCount++;
|
||||
fb->Stats.BytesCopied += (uint64_t)(uint32_t)r.W * (uint64_t)(uint32_t)r.H * sizeof(uint32_t);
|
||||
@@ -2209,16 +2209,16 @@ static KSTATUS BootFbReadRect(DISPLAY_DEVICE* device, int x, int y, int w, int h
|
||||
uint32_t* dst = outPixels + ((size_t)(dstOffsetY + row) * outStride) + dstOffsetX;
|
||||
memcpy(dst, src, (size_t)r.W * sizeof(uint32_t));
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Present operation.
|
||||
static KSTATUS BootFbPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, size_t rectCount) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (!fb || !fb->Framebuffer)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!fb->Backbuffer || !rects || rectCount == 0)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
DISPLAY_MODE mode;
|
||||
KSTATUS s = BootFbGetMode(device, &mode);
|
||||
@@ -2240,14 +2240,14 @@ static KSTATUS BootFbPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects,
|
||||
memcpy(dst, src, bytesPerRow);
|
||||
}
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Sync operation.
|
||||
static KSTATUS BootFbSync(DISPLAY_DEVICE* device) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (fb) fb->Stats.SyncCount++;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Set Cursor Image operation.
|
||||
@@ -2258,7 +2258,7 @@ static KSTATUS BootFbSetCursorImage(DISPLAY_DEVICE* device, int width, int heigh
|
||||
(void)hotX;
|
||||
(void)hotY;
|
||||
(void)argbPixels;
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Set Cursor Position operation.
|
||||
@@ -2267,7 +2267,7 @@ static KSTATUS BootFbSetCursorPosition(DISPLAY_DEVICE* device, int x, int y) {
|
||||
if (fb) fb->Stats.CursorMoveCount++;
|
||||
(void)x;
|
||||
(void)y;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the display Blend Pixel operation.
|
||||
@@ -2338,7 +2338,7 @@ static void BootFbDrawCursor(BOOTFB_CONTEXT* fb, int x, int y) {
|
||||
static KSTATUS BootFbShowCursor(DISPLAY_DEVICE* device, bool show) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (!fb || !fb->Framebuffer || !fb->Backbuffer)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
if (show) {
|
||||
fb->Stats.CursorShowCount++;
|
||||
@@ -2347,14 +2347,14 @@ static KSTATUS BootFbShowCursor(DISPLAY_DEVICE* device, bool show) {
|
||||
fb->Stats.CursorHideCount++;
|
||||
BootFbRestoreCursor(fb);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the boot Fb Query Stats operation.
|
||||
static KSTATUS BootFbQueryStats(DISPLAY_DEVICE* device, DISPLAY_STATS* outStats) {
|
||||
BOOTFB_CONTEXT* fb = BootFbContext(device);
|
||||
if (!fb || !outStats)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*outStats = fb->Stats;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
+25
-25
@@ -49,9 +49,9 @@ static void KiCompleteMultiWaitBlockLocked(KE_EVENT_WAIT_BLOCK* block) {
|
||||
if (_InterlockedCompareExchange(&ctx->Completed, 1, 0) != 0)
|
||||
return;
|
||||
|
||||
ctx->Status = STATUS_SUCCESS;
|
||||
ctx->Status = NTLSTATUS_SUCCESS;
|
||||
ctx->SelectedIndex = block->Index;
|
||||
KeUnblockThreadFromWaitListWithStatus(ctx->Thread, STATUS_SUCCESS);
|
||||
KeUnblockThreadFromWaitListWithStatus(ctx->Thread, NTLSTATUS_SUCCESS);
|
||||
}
|
||||
|
||||
// Removes any wait blocks that are still linked after the wait completed.
|
||||
@@ -96,9 +96,9 @@ static void KiRundownMultiWait(THREAD* thread, void* context, KSTATUS status) {
|
||||
|
||||
// Creates event.
|
||||
__declspec(dllexport) KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
EVENT* e = (EVENT *)ObAllocateObject(ObjectTypeEvent, sizeof(EVENT));
|
||||
if (!e) return STATUS_NO_MEMORY;
|
||||
if (!e) return NTLSTATUS_NO_MEMORY;
|
||||
e->Header.Destroy = KiEventDestroy;
|
||||
e->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
e->Type = type;
|
||||
@@ -106,7 +106,7 @@ __declspec(dllexport) KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialSta
|
||||
LIST_INIT(&e->WaitList);
|
||||
LIST_INIT(&e->MultiWaitList);
|
||||
*out = e;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Signals event.
|
||||
@@ -121,7 +121,7 @@ __declspec(dllexport) void KeSignalEvent(EVENT* event) {
|
||||
THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink);
|
||||
KeSetThreadWaitList(t, (LIST_ENTRY*)0);
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
KeUnblockThreadWithStatus(t, STATUS_SUCCESS);
|
||||
KeUnblockThreadWithStatus(t, NTLSTATUS_SUCCESS);
|
||||
flags = KeAcquireSpinlock(&event->Lock);
|
||||
}
|
||||
while (!LIST_IS_EMPTY(&event->MultiWaitList)) {
|
||||
@@ -136,7 +136,7 @@ __declspec(dllexport) void KeSignalEvent(EVENT* event) {
|
||||
THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink);
|
||||
KeSetThreadWaitList(t, (LIST_ENTRY*)0);
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
KeUnblockThreadWithStatus(t, STATUS_SUCCESS);
|
||||
KeUnblockThreadWithStatus(t, NTLSTATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -167,31 +167,31 @@ __declspec(dllexport) void KeClearEvent(EVENT* event) {
|
||||
|
||||
// Attempts to consume an event signal without blocking.
|
||||
__declspec(dllexport) KSTATUS KeTryWaitEvent(EVENT* event) {
|
||||
if (!event) return STATUS_INVALID_PARAMETER;
|
||||
if (!event) return NTLSTATUS_INVALID_PARAMETER;
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
if (!event->Signaled) {
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
return STATUS_TIMEOUT;
|
||||
return NTLSTATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
if (event->Type == EventAutoReset)
|
||||
event->Signaled = 0;
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Waits for Event.
|
||||
__declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event, uint8_t alertable) {
|
||||
if (!event) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (alertable && KeAreKernelApcsDisabled()) return STATUS_INVALID_PARAMETER;
|
||||
if (!event) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
if (alertable && KeAreKernelApcsDisabled()) return NTLSTATUS_INVALID_PARAMETER;
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
if (event->Signaled) {
|
||||
if (event->Type == EventAutoReset) event->Signaled = 0;
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KePrepareBlockThread(self, &event->Header, alertable);
|
||||
@@ -206,21 +206,21 @@ __declspec(dllexport) KSTATUS KeWaitForMultipleEvents(EVENT** events, uint32_t c
|
||||
uint8_t alertable, uint64_t timeoutMs,
|
||||
uint32_t* signaledIndexOut) {
|
||||
if (!events || count == 0 || count > SYS_WAIT_MANY_MAX_HANDLES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (alertable && KeAreKernelApcsDisabled()) return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
if (alertable && KeAreKernelApcsDisabled()) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (!events[i]) return STATUS_INVALID_PARAMETER;
|
||||
if (!events[i]) return NTLSTATUS_INVALID_PARAMETER;
|
||||
KSTATUS s = KeTryWaitEvent(events[i]);
|
||||
if (KSUCCESS(s)) {
|
||||
if (signaledIndexOut) *signaledIndexOut = i;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeoutMs == 0)
|
||||
return STATUS_TIMEOUT;
|
||||
return NTLSTATUS_TIMEOUT;
|
||||
|
||||
KE_EVENT_WAIT_BLOCK stackBlocks[SYS_WAIT_MANY_MAX_HANDLES];
|
||||
KE_EVENT_MULTI_WAIT_CONTEXT ctx;
|
||||
@@ -228,7 +228,7 @@ __declspec(dllexport) KSTATUS KeWaitForMultipleEvents(EVENT** events, uint32_t c
|
||||
ctx.Blocks = stackBlocks;
|
||||
ctx.Count = count;
|
||||
ctx.Completed = 0;
|
||||
ctx.Status = STATUS_PENDING;
|
||||
ctx.Status = NTLSTATUS_PENDING;
|
||||
ctx.SelectedIndex = 0;
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
@@ -243,7 +243,7 @@ __declspec(dllexport) KSTATUS KeWaitForMultipleEvents(EVENT** events, uint32_t c
|
||||
KeSetThreadWaitRundown(ctx.Thread, KiRundownMultiWait, &ctx);
|
||||
|
||||
if (timeoutMs != SYS_WAIT_TIMEOUT_INFINITE) {
|
||||
KSTATUS ts = KeArmCurrentThreadTimeout(timeoutMs, STATUS_TIMEOUT);
|
||||
KSTATUS ts = KeArmCurrentThreadTimeout(timeoutMs, NTLSTATUS_TIMEOUT);
|
||||
if (!KSUCCESS(ts)) {
|
||||
KeClearThreadWaitRundown(ctx.Thread);
|
||||
KeUnblockThreadFromWaitListWithStatus(ctx.Thread, ts);
|
||||
@@ -257,11 +257,11 @@ __declspec(dllexport) KSTATUS KeWaitForMultipleEvents(EVENT** events, uint32_t c
|
||||
if (_InterlockedCompareExchange(&ctx.Completed, 0, 0) == 0 && event->Signaled) {
|
||||
if (event->Type == EventAutoReset)
|
||||
event->Signaled = 0;
|
||||
ctx.Status = STATUS_SUCCESS;
|
||||
ctx.Status = NTLSTATUS_SUCCESS;
|
||||
ctx.SelectedIndex = i;
|
||||
_InterlockedExchange(&ctx.Completed, 1);
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
KeUnblockThreadFromWaitListWithStatus(ctx.Thread, STATUS_SUCCESS);
|
||||
KeUnblockThreadFromWaitListWithStatus(ctx.Thread, NTLSTATUS_SUCCESS);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ __declspec(dllexport) KSTATUS KeWaitForMultipleEvents(EVENT** events, uint32_t c
|
||||
KiCleanupMultiWaitBlocks(&ctx);
|
||||
KeClearThreadWaitRundown(ctx.Thread);
|
||||
|
||||
if (ctx.Status == STATUS_SUCCESS && signaledIndexOut)
|
||||
if (ctx.Status == NTLSTATUS_SUCCESS && signaledIndexOut)
|
||||
*signaledIndexOut = ctx.SelectedIndex;
|
||||
return ctx.Status;
|
||||
}
|
||||
@@ -0,0 +1,801 @@
|
||||
// Kernel exception classification and recoverable fault policy.
|
||||
|
||||
#include <kernel/ke_exception.h>
|
||||
#include <kernel/ke_process.h>
|
||||
#include <kernel/ke_thread.h>
|
||||
#include <kernel/ke_sched.h>
|
||||
#include <kernel/ke_trap.h>
|
||||
#include <kernel/mm_virt.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define KI_EXCEPTION_MAX_DISPATCH_DEPTH KE_USER_EXCEPTION_MAX_DEPTH
|
||||
#define KI_EXCEPTION_USER_ENTRY_SHADOW 40u
|
||||
#define KI_EXCEPTION_FRAME_ALIGNMENT 16u
|
||||
#define KI_USER_CS 0x1BULL
|
||||
#define KI_USER_SS 0x23ULL
|
||||
#define KI_RFLAGS_FIXED 0x2ULL
|
||||
#define KI_RFLAGS_IOPL 0x3000ULL
|
||||
#define KI_RFLAGS_NT 0x4000ULL
|
||||
#define KI_RFLAGS_VM 0x20000ULL
|
||||
|
||||
// Returns whether one user address can be used as a control-flow target or pointer.
|
||||
static bool KiExceptionUserAddressValid(uintptr_t address) {
|
||||
return address >= USER_BASE && address < USER_LIMIT;
|
||||
}
|
||||
|
||||
// Returns whether one byte range stays wholly inside user address space.
|
||||
static bool KiExceptionUserRangeValid(uintptr_t base, size_t size) {
|
||||
if (size == 0)
|
||||
return false;
|
||||
if (base < USER_BASE || base >= USER_LIMIT)
|
||||
return false;
|
||||
if (size > (size_t)(USER_LIMIT - base))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns whether a saved user RFLAGS value can be restored safely.
|
||||
static bool KiExceptionUserRflagsValid(uint64_t rflags) {
|
||||
if ((rflags & KI_RFLAGS_FIXED) == 0)
|
||||
return false;
|
||||
if ((rflags & (KI_RFLAGS_IOPL | KI_RFLAGS_NT | KI_RFLAGS_VM)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rounds an address down to the alignment required by the user-mode ABI.
|
||||
static uintptr_t KiExceptionAlignDown(uintptr_t value, uintptr_t alignment) {
|
||||
return value & ~(alignment - 1u);
|
||||
}
|
||||
|
||||
// Terminates the current process from exception-return policy code.
|
||||
static _Noreturn void KiTerminateCurrentExceptionProcess(KSTATUS exitStatus) {
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
PROCESS* process = thread ? thread->Owner : (PROCESS*)0;
|
||||
int32_t exitCode = (int32_t)exitStatus;
|
||||
|
||||
if (process)
|
||||
(void)KeTerminateProcess(process, exitCode);
|
||||
if (thread)
|
||||
KeExitThread(thread, exitCode);
|
||||
|
||||
for (;;) {
|
||||
KeYield();
|
||||
}
|
||||
}
|
||||
|
||||
// Records a delivered exception against the process that owns user policy.
|
||||
static void KiRecordExceptionDelivery(PROCESS* process, const SYS_EXCEPTION_RECORD* record,
|
||||
uint32_t nestedDepth, bool userRaised) {
|
||||
if (!process || !record)
|
||||
return;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ExceptionLock);
|
||||
process->ExceptionDeliveredCount++;
|
||||
if (userRaised)
|
||||
process->ExceptionUserRaisedCount++;
|
||||
if (nestedDepth > process->ExceptionMaxNestedDispatch)
|
||||
process->ExceptionMaxNestedDispatch = nestedDepth;
|
||||
process->LastExceptionCode = record->Code;
|
||||
process->LastExceptionAddress = record->ExceptionAddress;
|
||||
process->LastExceptionFaultAddress = record->FaultAddress;
|
||||
KeReleaseSpinlock(&process->ExceptionLock, flags);
|
||||
}
|
||||
|
||||
// Records one completed exception continuation.
|
||||
static void KiRecordExceptionContinued(PROCESS* process) {
|
||||
if (!process)
|
||||
return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ExceptionLock);
|
||||
process->ExceptionContinuedCount++;
|
||||
KeReleaseSpinlock(&process->ExceptionLock, flags);
|
||||
}
|
||||
|
||||
// Records that user policy declined or failed to handle an exception.
|
||||
static void KiRecordExceptionUnhandled(PROCESS* process) {
|
||||
if (!process)
|
||||
return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ExceptionLock);
|
||||
process->ExceptionUnhandledCount++;
|
||||
KeReleaseSpinlock(&process->ExceptionLock, flags);
|
||||
}
|
||||
|
||||
// Records a malformed or forbidden exception continuation request.
|
||||
static void KiRecordExceptionInvalidContinue(PROCESS* process) {
|
||||
if (!process)
|
||||
return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ExceptionLock);
|
||||
process->ExceptionInvalidContinueCount++;
|
||||
KeReleaseSpinlock(&process->ExceptionLock, flags);
|
||||
}
|
||||
|
||||
|
||||
// Returns the process exit status for one unhandled native exception record.
|
||||
static KSTATUS KiExceptionUnhandledExitStatus(const SYS_EXCEPTION_RECORD* record) {
|
||||
if (!record)
|
||||
return NTLSTATUS_PROCESS_UNKNOWN_FAULT;
|
||||
|
||||
switch (record->Code) {
|
||||
case SYS_EXCEPTION_CODE_INT_DIVIDE_BY_ZERO:
|
||||
return NTLSTATUS_PROCESS_DIVIDE_BY_ZERO;
|
||||
case SYS_EXCEPTION_CODE_BREAKPOINT:
|
||||
return NTLSTATUS_PROCESS_BREAKPOINT;
|
||||
case SYS_EXCEPTION_CODE_ILLEGAL_INSTRUCTION:
|
||||
return NTLSTATUS_PROCESS_ILLEGAL_OPCODE;
|
||||
case SYS_EXCEPTION_CODE_PRIVILEGED_INSTRUCTION:
|
||||
return NTLSTATUS_PROCESS_GENERAL_PROTECTION;
|
||||
case SYS_EXCEPTION_CODE_ACCESS_VIOLATION:
|
||||
return NTLSTATUS_PROCESS_PAGE_FAULT;
|
||||
case SYS_EXCEPTION_CODE_DATATYPE_MISALIGNMENT:
|
||||
return NTLSTATUS_PROCESS_ALIGNMENT_FAULT;
|
||||
default:
|
||||
return (KSTATUS)record->Code;
|
||||
}
|
||||
}
|
||||
|
||||
// Maps an architectural vector to the native structured-exception code.
|
||||
static uint32_t KiExceptionCodeFromVector(uint32_t vector) {
|
||||
switch (vector) {
|
||||
case 0: return SYS_EXCEPTION_CODE_INT_DIVIDE_BY_ZERO;
|
||||
case 1: return SYS_EXCEPTION_CODE_SINGLE_STEP;
|
||||
case 3: return SYS_EXCEPTION_CODE_BREAKPOINT;
|
||||
case 4: return SYS_EXCEPTION_CODE_INT_OVERFLOW;
|
||||
case 5: return SYS_EXCEPTION_CODE_ARRAY_BOUNDS_EXCEEDED;
|
||||
case 6: return SYS_EXCEPTION_CODE_ILLEGAL_INSTRUCTION;
|
||||
case 13: return SYS_EXCEPTION_CODE_PRIVILEGED_INSTRUCTION;
|
||||
case 14: return SYS_EXCEPTION_CODE_ACCESS_VIOLATION;
|
||||
case 17: return SYS_EXCEPTION_CODE_DATATYPE_MISALIGNMENT;
|
||||
default: return SYS_EXCEPTION_CODE_NTLITE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Fills the user-mode context record from a captured CPU fault frame.
|
||||
static void KiCaptureUserContextFromFault(const KFAULT_FRAME* frame, SYS_USER_CONTEXT* context) {
|
||||
memset(context, 0, sizeof(*context));
|
||||
context->Size = sizeof(*context);
|
||||
context->Version = SYS_EXCEPTION_ABI_VERSION;
|
||||
context->Flags = SYS_CONTEXT_FLAG_ALL;
|
||||
context->Rip = frame->Rip;
|
||||
context->Rsp = frame->Rsp;
|
||||
context->Rflags = frame->Rflags;
|
||||
context->Rax = frame->Rax;
|
||||
context->Rcx = frame->Rcx;
|
||||
context->Rdx = frame->Rdx;
|
||||
context->Rbx = frame->Rbx;
|
||||
context->Rbp = frame->Rbp;
|
||||
context->Rsi = frame->Rsi;
|
||||
context->Rdi = frame->Rdi;
|
||||
context->R8 = frame->R8;
|
||||
context->R9 = frame->R9;
|
||||
context->R10 = frame->R10;
|
||||
context->R11 = frame->R11;
|
||||
context->R12 = frame->R12;
|
||||
context->R13 = frame->R13;
|
||||
context->R14 = frame->R14;
|
||||
context->R15 = frame->R15;
|
||||
context->SegCs = (uint32_t)frame->Cs;
|
||||
context->SegSs = (uint32_t)frame->Ss;
|
||||
}
|
||||
|
||||
// Fills the user-mode context record from the current syscall return frame.
|
||||
static void KiCaptureUserContextFromTrap(const KTRAP_FRAME* frame, SYS_USER_CONTEXT* context) {
|
||||
memset(context, 0, sizeof(*context));
|
||||
context->Size = sizeof(*context);
|
||||
context->Version = SYS_EXCEPTION_ABI_VERSION;
|
||||
context->Flags = SYS_CONTEXT_FLAG_ALL;
|
||||
context->Rip = frame->Rip;
|
||||
context->Rsp = frame->Rsp;
|
||||
context->Rflags = frame->Rflags;
|
||||
context->Rax = NTLSTATUS_SUCCESS;
|
||||
context->Rcx = frame->Rcx;
|
||||
context->Rdx = frame->Rdx;
|
||||
context->Rbx = frame->Rbx;
|
||||
context->Rbp = frame->Rbp;
|
||||
context->Rsi = frame->Rsi;
|
||||
context->Rdi = frame->Rdi;
|
||||
context->R8 = frame->R8;
|
||||
context->R9 = frame->R9;
|
||||
context->R10 = frame->R10;
|
||||
context->R11 = frame->R11;
|
||||
context->R12 = frame->R12;
|
||||
context->R13 = frame->R13;
|
||||
context->R14 = frame->R14;
|
||||
context->R15 = frame->R15;
|
||||
context->SegCs = (uint32_t)frame->Cs;
|
||||
context->SegSs = (uint32_t)frame->Ss;
|
||||
}
|
||||
|
||||
// Fills the native exception record from an architectural user fault.
|
||||
static void KiCaptureExceptionRecordFromFault(const KFAULT_FRAME* frame, SYS_EXCEPTION_RECORD* record) {
|
||||
memset(record, 0, sizeof(*record));
|
||||
record->Size = sizeof(*record);
|
||||
record->Version = SYS_EXCEPTION_ABI_VERSION;
|
||||
record->Code = KiExceptionCodeFromVector((uint32_t)frame->Vector);
|
||||
record->Flags = SYS_EXCEPTION_FLAG_FIRST_CHANCE;
|
||||
if ((frame->Vector == 8) || (frame->Vector == 18))
|
||||
record->Flags |= SYS_EXCEPTION_FLAG_NONCONTINUABLE;
|
||||
record->ExceptionAddress = (uintptr_t)frame->Rip;
|
||||
record->FaultAddress = frame->Vector == 14 ? (uintptr_t)frame->Cr2 : (uintptr_t)frame->Rip;
|
||||
record->ErrorCode = frame->ErrorCode;
|
||||
|
||||
if (frame->Vector == 14) {
|
||||
uint64_t accessKind = 0;
|
||||
if (frame->ErrorCode & 0x10u)
|
||||
accessKind = 8;
|
||||
else if (frame->ErrorCode & 0x2u)
|
||||
accessKind = 1;
|
||||
record->ParameterCount = 2;
|
||||
record->Parameters[0] = accessKind;
|
||||
record->Parameters[1] = frame->Cr2;
|
||||
}
|
||||
}
|
||||
|
||||
// Captures a stable process dispatcher snapshot outside the process lock.
|
||||
static KSTATUS KiSnapshotExceptionDispatcher(PROCESS* process,
|
||||
SYS_EXCEPTION_DISPATCHER_REQUEST* out) {
|
||||
if (!process || !out)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
out->Size = sizeof(*out);
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ExceptionLock);
|
||||
out->Flags = process->ExceptionDispatchFlags;
|
||||
out->DispatcherRoutine = (SYS_USER_EXCEPTION_DISPATCHER)process->ExceptionDispatcher;
|
||||
out->DispatcherContext = (void*)process->ExceptionDispatcherContext;
|
||||
out->ExceptionStackBase = (void*)process->ExceptionStackBase;
|
||||
out->ExceptionStackSize = process->ExceptionStackSize;
|
||||
KeReleaseSpinlock(&process->ExceptionLock, flags);
|
||||
|
||||
if (!out->DispatcherRoutine)
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Selects the stack top used to inject one exception dispatcher frame.
|
||||
static KSTATUS KiSelectExceptionStackTop(THREAD* thread,
|
||||
const SYS_EXCEPTION_DISPATCHER_REQUEST* dispatcher,
|
||||
const KFAULT_FRAME* fault,
|
||||
uintptr_t* stackTopOut) {
|
||||
if (!thread || !dispatcher || !fault || !stackTopOut)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
if (dispatcher->ExceptionStackBase) {
|
||||
uintptr_t base = (uintptr_t)dispatcher->ExceptionStackBase;
|
||||
uintptr_t top = base + dispatcher->ExceptionStackSize;
|
||||
uintptr_t stride = KiExceptionAlignDown(sizeof(SYS_EXCEPTION_FRAME) +
|
||||
KI_EXCEPTION_USER_ENTRY_SHADOW +
|
||||
KI_EXCEPTION_FRAME_ALIGNMENT - 1u,
|
||||
KI_EXCEPTION_FRAME_ALIGNMENT);
|
||||
uintptr_t needed = (uintptr_t)(thread->UserExceptionDepth + 1u) * stride;
|
||||
if (needed > dispatcher->ExceptionStackSize)
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
*stackTopOut = top - (uintptr_t)thread->UserExceptionDepth * stride;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!KiExceptionUserAddressValid((uintptr_t)fault->Rsp))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
*stackTopOut = (uintptr_t)fault->Rsp;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Selects an exception stack using an explicit user RSP.
|
||||
static KSTATUS KiSelectExceptionStackTopFromRsp(THREAD* thread,
|
||||
const SYS_EXCEPTION_DISPATCHER_REQUEST* dispatcher,
|
||||
uintptr_t rsp,
|
||||
uintptr_t* stackTopOut) {
|
||||
if (!thread || !dispatcher || !stackTopOut)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
if (dispatcher->ExceptionStackBase) {
|
||||
uintptr_t base = (uintptr_t)dispatcher->ExceptionStackBase;
|
||||
uintptr_t top = base + dispatcher->ExceptionStackSize;
|
||||
uintptr_t stride = KiExceptionAlignDown(sizeof(SYS_EXCEPTION_FRAME) +
|
||||
KI_EXCEPTION_USER_ENTRY_SHADOW +
|
||||
KI_EXCEPTION_FRAME_ALIGNMENT - 1u,
|
||||
KI_EXCEPTION_FRAME_ALIGNMENT);
|
||||
uintptr_t needed = (uintptr_t)(thread->UserExceptionDepth + 1u) * stride;
|
||||
if (needed > dispatcher->ExceptionStackSize)
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
*stackTopOut = top - (uintptr_t)thread->UserExceptionDepth * stride;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!KiExceptionUserAddressValid(rsp))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
*stackTopOut = rsp;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Copies the native exception delivery frame to the selected user stack.
|
||||
static KSTATUS KiBuildUserExceptionFrame(THREAD* thread,
|
||||
const SYS_EXCEPTION_DISPATCHER_REQUEST* dispatcher,
|
||||
KFAULT_FRAME* fault,
|
||||
uintptr_t* frameAddressOut,
|
||||
uintptr_t* entryRspOut) {
|
||||
uintptr_t stackTop = 0;
|
||||
KSTATUS status = KiSelectExceptionStackTop(thread, dispatcher, fault, &stackTop);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
uintptr_t frameAddress = KiExceptionAlignDown(stackTop - sizeof(SYS_EXCEPTION_FRAME),
|
||||
KI_EXCEPTION_FRAME_ALIGNMENT);
|
||||
uintptr_t entryRsp = frameAddress - KI_EXCEPTION_USER_ENTRY_SHADOW;
|
||||
if (!KiExceptionUserRangeValid(entryRsp,
|
||||
KI_EXCEPTION_USER_ENTRY_SHADOW + sizeof(SYS_EXCEPTION_FRAME)))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
SYS_EXCEPTION_FRAME userFrame;
|
||||
memset(&userFrame, 0, sizeof(userFrame));
|
||||
userFrame.Size = sizeof(userFrame);
|
||||
userFrame.Version = SYS_EXCEPTION_ABI_VERSION;
|
||||
KiCaptureExceptionRecordFromFault(fault, &userFrame.ExceptionRecord);
|
||||
KiCaptureUserContextFromFault(fault, &userFrame.ContextRecord);
|
||||
userFrame.DispatcherContext = dispatcher->DispatcherContext;
|
||||
|
||||
uint8_t shadow[KI_EXCEPTION_USER_ENTRY_SHADOW];
|
||||
memset(shadow, 0, sizeof(shadow));
|
||||
status = CopyToUser((void*)entryRsp, shadow, sizeof(shadow));
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
status = CopyToUser((void*)frameAddress, &userFrame, sizeof(userFrame));
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
*frameAddressOut = frameAddress;
|
||||
*entryRspOut = entryRsp;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Copies an already-classified user exception frame to the selected user stack.
|
||||
static KSTATUS KiBuildUserRaisedExceptionFrame(THREAD* thread,
|
||||
const SYS_EXCEPTION_DISPATCHER_REQUEST* dispatcher,
|
||||
const KTRAP_FRAME* trapFrame,
|
||||
const SYS_EXCEPTION_RECORD* record,
|
||||
uintptr_t* frameAddressOut,
|
||||
uintptr_t* entryRspOut) {
|
||||
uintptr_t stackTop = 0;
|
||||
KSTATUS status = KiSelectExceptionStackTopFromRsp(thread, dispatcher, trapFrame->Rsp, &stackTop);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
uintptr_t frameAddress = KiExceptionAlignDown(stackTop - sizeof(SYS_EXCEPTION_FRAME),
|
||||
KI_EXCEPTION_FRAME_ALIGNMENT);
|
||||
uintptr_t entryRsp = frameAddress - KI_EXCEPTION_USER_ENTRY_SHADOW;
|
||||
if (!KiExceptionUserRangeValid(entryRsp,
|
||||
KI_EXCEPTION_USER_ENTRY_SHADOW + sizeof(SYS_EXCEPTION_FRAME)))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
SYS_EXCEPTION_FRAME userFrame;
|
||||
memset(&userFrame, 0, sizeof(userFrame));
|
||||
userFrame.Size = sizeof(userFrame);
|
||||
userFrame.Version = SYS_EXCEPTION_ABI_VERSION;
|
||||
userFrame.ExceptionRecord = *record;
|
||||
KiCaptureUserContextFromTrap(trapFrame, &userFrame.ContextRecord);
|
||||
userFrame.DispatcherContext = dispatcher->DispatcherContext;
|
||||
|
||||
uint8_t shadow[KI_EXCEPTION_USER_ENTRY_SHADOW];
|
||||
memset(shadow, 0, sizeof(shadow));
|
||||
status = CopyToUser((void*)entryRsp, shadow, sizeof(shadow));
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
status = CopyToUser((void*)frameAddress, &userFrame, sizeof(userFrame));
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
*frameAddressOut = frameAddress;
|
||||
*entryRspOut = entryRsp;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Validates a user context before using it as an exception resume target.
|
||||
static KSTATUS KiValidateContinueContext(const SYS_USER_CONTEXT* context) {
|
||||
if (!context)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (context->Size != sizeof(*context) || context->Version != SYS_EXCEPTION_ABI_VERSION)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (context->Flags != SYS_CONTEXT_FLAG_ALL)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KiExceptionUserAddressValid((uintptr_t)context->Rip) ||
|
||||
!KiExceptionUserAddressValid((uintptr_t)context->Rsp))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
if (!KiExceptionUserRflagsValid(context->Rflags))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
if (context->SegCs != KI_USER_CS || context->SegSs != KI_USER_SS)
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Applies a validated user context to the current syscall return trap frame.
|
||||
static void KiApplyContinueContextToTrapFrame(KTRAP_FRAME* frame,
|
||||
const SYS_USER_CONTEXT* context) {
|
||||
frame->Rip = context->Rip;
|
||||
frame->Rsp = context->Rsp;
|
||||
frame->Rflags = context->Rflags;
|
||||
frame->Cs = context->SegCs;
|
||||
frame->Ss = context->SegSs;
|
||||
frame->Rax = context->Rax;
|
||||
frame->Rcx = context->Rcx;
|
||||
frame->Rdx = context->Rdx;
|
||||
frame->Rbx = context->Rbx;
|
||||
frame->Rbp = context->Rbp;
|
||||
frame->Rsi = context->Rsi;
|
||||
frame->Rdi = context->Rdi;
|
||||
frame->R8 = context->R8;
|
||||
frame->R9 = context->R9;
|
||||
frame->R10 = context->R10;
|
||||
frame->R11 = context->R11;
|
||||
frame->R12 = context->R12;
|
||||
frame->R13 = context->R13;
|
||||
frame->R14 = context->R14;
|
||||
frame->R15 = context->R15;
|
||||
}
|
||||
|
||||
// Redirects a captured user fault to the registered native exception dispatcher.
|
||||
KSTATUS KeDeliverUserException(KFAULT_FRAME* frame) {
|
||||
if (!frame || !KeFaultFrameIsValid(frame) || !KeFaultFrameFromUser(frame))
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
PROCESS* process = thread ? thread->Owner : (PROCESS*)0;
|
||||
if (!thread || !process)
|
||||
return NTLSTATUS_FAILURE;
|
||||
if (thread->UserExceptionDepth >= KI_EXCEPTION_MAX_DISPATCH_DEPTH)
|
||||
return NTLSTATUS_PROCESS_UNKNOWN_FAULT;
|
||||
|
||||
SYS_EXCEPTION_DISPATCHER_REQUEST dispatcher;
|
||||
KSTATUS status = KiSnapshotExceptionDispatcher(process, &dispatcher);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
uintptr_t frameAddress = 0;
|
||||
uintptr_t entryRsp = 0;
|
||||
status = KiBuildUserExceptionFrame(thread, &dispatcher, frame, &frameAddress, &entryRsp);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
SYS_EXCEPTION_RECORD deliveredRecord;
|
||||
KiCaptureExceptionRecordFromFault(frame, &deliveredRecord);
|
||||
|
||||
uint32_t depth = thread->UserExceptionDepth;
|
||||
if ((frame->Vector == 8) || (frame->Vector == 18))
|
||||
thread->UserExceptionNoncontinuableMask |= (1u << depth);
|
||||
thread->UserExceptionExitStatus[depth] = KiExceptionUnhandledExitStatus(&deliveredRecord);
|
||||
|
||||
KiRecordExceptionDelivery(process, &deliveredRecord, depth + 1u, false);
|
||||
thread->UserExceptionDepth = depth + 1u;
|
||||
thread->UserExceptionFrameUserAddress = frameAddress;
|
||||
|
||||
frame->Rip = (uint64_t)(uintptr_t)dispatcher.DispatcherRoutine;
|
||||
frame->Rsp = entryRsp;
|
||||
frame->Rcx = frameAddress;
|
||||
frame->Rdx = 0;
|
||||
frame->R8 = 0;
|
||||
frame->R9 = 0;
|
||||
frame->R10 = 0;
|
||||
frame->R11 = 0;
|
||||
frame->Rax = NTLSTATUS_SUCCESS;
|
||||
frame->Cs = KI_USER_CS;
|
||||
frame->Ss = KI_USER_SS;
|
||||
frame->Rflags |= KI_RFLAGS_FIXED;
|
||||
frame->Rflags &= ~(KI_RFLAGS_IOPL | KI_RFLAGS_NT | KI_RFLAGS_VM);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Raises a user-authored structured exception from the current syscall frame.
|
||||
uint64_t KeRaiseUserException(const SYS_RAISE_EXCEPTION_REQUEST* request, const uint64_t* parameters) {
|
||||
if (!request)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->Size != sizeof(*request))
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->Flags & ~SYS_RAISE_EXCEPTION_FLAG_NONCONTINUABLE)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->ParameterCount > SYS_EXCEPTION_MAXIMUM_PARAMETERS)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->ParameterCount && !parameters)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
PROCESS* process = thread ? thread->Owner : (PROCESS*)0;
|
||||
if (!thread || !process)
|
||||
return NTLSTATUS_FAILURE;
|
||||
if (thread->UserExceptionDepth >= KI_EXCEPTION_MAX_DISPATCH_DEPTH)
|
||||
return NTLSTATUS_PROCESS_UNKNOWN_FAULT;
|
||||
|
||||
KTRAP_FRAME* trapFrame = KeGetCurrentTrapFrame();
|
||||
if (!trapFrame || !KeTrapFrameFromUser(trapFrame) || trapFrame->Kind != KTRAP_KIND_SYSCALL)
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
SYS_EXCEPTION_DISPATCHER_REQUEST dispatcher;
|
||||
KSTATUS status = KiSnapshotExceptionDispatcher(process, &dispatcher);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
SYS_EXCEPTION_RECORD record;
|
||||
memset(&record, 0, sizeof(record));
|
||||
record.Size = sizeof(record);
|
||||
record.Version = SYS_EXCEPTION_ABI_VERSION;
|
||||
record.Code = request->Code;
|
||||
record.Flags = SYS_EXCEPTION_FLAG_FIRST_CHANCE;
|
||||
if (request->Flags & SYS_RAISE_EXCEPTION_FLAG_NONCONTINUABLE)
|
||||
record.Flags |= SYS_EXCEPTION_FLAG_NONCONTINUABLE;
|
||||
record.ExceptionAddress = (uintptr_t)trapFrame->Rip;
|
||||
record.FaultAddress = 0;
|
||||
record.ParameterCount = request->ParameterCount;
|
||||
for (uint32_t i = 0; i < request->ParameterCount; i++)
|
||||
record.Parameters[i] = parameters[i];
|
||||
|
||||
uintptr_t frameAddress = 0;
|
||||
uintptr_t entryRsp = 0;
|
||||
status = KiBuildUserRaisedExceptionFrame(thread, &dispatcher, trapFrame, &record,
|
||||
&frameAddress, &entryRsp);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
uint32_t depth = thread->UserExceptionDepth;
|
||||
if (record.Flags & SYS_EXCEPTION_FLAG_NONCONTINUABLE)
|
||||
thread->UserExceptionNoncontinuableMask |= (1u << depth);
|
||||
thread->UserExceptionExitStatus[depth] = KiExceptionUnhandledExitStatus(&record);
|
||||
|
||||
KiRecordExceptionDelivery(process, &record, depth + 1u, true);
|
||||
thread->UserExceptionDepth = depth + 1u;
|
||||
thread->UserExceptionFrameUserAddress = frameAddress;
|
||||
|
||||
trapFrame->Rip = (uint64_t)(uintptr_t)dispatcher.DispatcherRoutine;
|
||||
trapFrame->Rsp = entryRsp;
|
||||
trapFrame->Rcx = frameAddress;
|
||||
trapFrame->Rdx = 0;
|
||||
trapFrame->R8 = 0;
|
||||
trapFrame->R9 = 0;
|
||||
trapFrame->R10 = 0;
|
||||
trapFrame->R11 = 0;
|
||||
trapFrame->Rax = NTLSTATUS_SUCCESS;
|
||||
trapFrame->Cs = KI_USER_CS;
|
||||
trapFrame->Ss = KI_USER_SS;
|
||||
trapFrame->Rflags |= KI_RFLAGS_FIXED;
|
||||
trapFrame->Rflags &= ~(KI_RFLAGS_IOPL | KI_RFLAGS_NT | KI_RFLAGS_VM);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Completes native exception dispatch by applying the user-selected disposition.
|
||||
uint64_t KeContinueException(const SYS_CONTINUE_EXCEPTION_REQUEST* request) {
|
||||
if (!request)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->Size != sizeof(*request) || request->Flags != SYS_EXCEPTION_CONTINUE_FLAG_NONE)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
PROCESS* process = thread ? thread->Owner : (PROCESS*)0;
|
||||
if (!thread || thread->UserExceptionDepth == 0) {
|
||||
KiRecordExceptionInvalidContinue(process);
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uint32_t activeDepth = thread->UserExceptionDepth - 1u;
|
||||
uint32_t activeBit = 1u << activeDepth;
|
||||
KSTATUS activeExitStatus = thread->UserExceptionExitStatus[activeDepth];
|
||||
if (activeExitStatus == NTLSTATUS_SUCCESS)
|
||||
activeExitStatus = NTLSTATUS_PROCESS_UNKNOWN_FAULT;
|
||||
|
||||
if (request->Disposition == SYS_EXCEPTION_DISPOSITION_CONTINUE_SEARCH ||
|
||||
request->Disposition == SYS_EXCEPTION_DISPOSITION_TERMINATE_PROCESS) {
|
||||
KiRecordExceptionUnhandled(process);
|
||||
thread->UserExceptionDepth = activeDepth;
|
||||
thread->UserExceptionNoncontinuableMask &= ~activeBit;
|
||||
thread->UserExceptionFrameUserAddress = 0;
|
||||
thread->UserExceptionExitStatus[activeDepth] = NTLSTATUS_SUCCESS;
|
||||
KiTerminateCurrentExceptionProcess(activeExitStatus);
|
||||
}
|
||||
|
||||
if (request->Disposition != SYS_EXCEPTION_DISPOSITION_CONTINUE_EXECUTION) {
|
||||
KiRecordExceptionInvalidContinue(process);
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (thread->UserExceptionNoncontinuableMask & activeBit) {
|
||||
KiRecordExceptionInvalidContinue(process);
|
||||
thread->UserExceptionDepth = activeDepth;
|
||||
thread->UserExceptionNoncontinuableMask &= ~activeBit;
|
||||
thread->UserExceptionFrameUserAddress = 0;
|
||||
thread->UserExceptionExitStatus[activeDepth] = NTLSTATUS_SUCCESS;
|
||||
KiTerminateCurrentExceptionProcess(NTLSTATUS_PROCESS_UNKNOWN_FAULT);
|
||||
}
|
||||
if (!request->Context) {
|
||||
KiRecordExceptionInvalidContinue(process);
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
SYS_USER_CONTEXT context;
|
||||
KSTATUS status = CopyFromUser(&context, request->Context, sizeof(context));
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
status = KiValidateContinueContext(&context);
|
||||
if (!KSUCCESS(status)) {
|
||||
KiRecordExceptionInvalidContinue(process);
|
||||
KiTerminateCurrentExceptionProcess(status);
|
||||
}
|
||||
|
||||
KTRAP_FRAME* trapFrame = KeGetCurrentTrapFrame();
|
||||
if (!trapFrame || !KeTrapFrameFromUser(trapFrame) || trapFrame->Kind != KTRAP_KIND_SYSCALL) {
|
||||
KiRecordExceptionInvalidContinue(process);
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
KiApplyContinueContextToTrapFrame(trapFrame, &context);
|
||||
KiRecordExceptionContinued(process);
|
||||
thread->UserExceptionDepth = activeDepth;
|
||||
thread->UserExceptionNoncontinuableMask &= ~activeBit;
|
||||
thread->UserExceptionFrameUserAddress = 0;
|
||||
thread->UserExceptionExitStatus[activeDepth] = NTLSTATUS_SUCCESS;
|
||||
return context.Rax;
|
||||
}
|
||||
|
||||
// Returns whether a fault frame was initialized by the assembly stubs.
|
||||
bool KeFaultFrameIsValid(const KFAULT_FRAME* frame) {
|
||||
return frame && frame->Magic == KFAULT_FRAME_MAGIC_VALUE;
|
||||
}
|
||||
|
||||
// Returns whether a fault frame captured an interrupted user-mode context.
|
||||
bool KeFaultFrameFromUser(const KFAULT_FRAME* frame) {
|
||||
return KeFaultFrameIsValid(frame) && ((frame->Cs & 3u) == 3u);
|
||||
}
|
||||
|
||||
// Returns the short architectural name for one CPU exception vector.
|
||||
const char* KeExceptionVectorName(uint32_t vector) {
|
||||
switch (vector) {
|
||||
case 0: return "#DE Divide Error";
|
||||
case 1: return "#DB Debug";
|
||||
case 2: return "NMI Interrupt";
|
||||
case 3: return "#BP Breakpoint";
|
||||
case 4: return "#OF Overflow";
|
||||
case 5: return "#BR Bound Range Exceeded";
|
||||
case 6: return "#UD Invalid Opcode";
|
||||
case 7: return "#NM Device Not Available";
|
||||
case 8: return "#DF Double Fault";
|
||||
case 9: return "Coprocessor Segment Overrun";
|
||||
case 10: return "#TS Invalid TSS";
|
||||
case 11: return "#NP Segment Not Present";
|
||||
case 12: return "#SS Stack-Segment Fault";
|
||||
case 13: return "#GP General Protection";
|
||||
case 14: return "#PF Page Fault";
|
||||
case 15: return "Reserved Exception 15";
|
||||
case 16: return "#MF x87 Floating-Point Exception";
|
||||
case 17: return "#AC Alignment Check";
|
||||
case 18: return "#MC Machine Check";
|
||||
case 19: return "#XM SIMD Floating-Point Exception";
|
||||
case 20: return "#VE Virtualization Exception";
|
||||
case 21: return "#CP Control Protection Exception";
|
||||
case 22: return "Reserved Exception 22";
|
||||
case 23: return "Reserved Exception 23";
|
||||
case 24: return "Reserved Exception 24";
|
||||
case 25: return "Reserved Exception 25";
|
||||
case 26: return "Reserved Exception 26";
|
||||
case 27: return "Reserved Exception 27";
|
||||
case 28: return "#HV Hypervisor Injection Exception";
|
||||
case 29: return "#VC VMM Communication Exception";
|
||||
case 30: return "#SX Security Exception";
|
||||
case 31: return "Reserved Exception 31";
|
||||
default: return "Unknown Exception";
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether the CPU pushes an error code for one exception vector.
|
||||
bool KeExceptionVectorHasErrorCode(uint32_t vector) {
|
||||
switch (vector) {
|
||||
case 8:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 17:
|
||||
case 21:
|
||||
case 29:
|
||||
case 30:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Maps an unhandled user-mode CPU exception to the legacy process exit status.
|
||||
KSTATUS KeExceptionProcessExitStatus(uint32_t vector) {
|
||||
switch (vector) {
|
||||
case 0: return NTLSTATUS_PROCESS_DIVIDE_BY_ZERO;
|
||||
case 3: return NTLSTATUS_PROCESS_BREAKPOINT;
|
||||
case 6: return NTLSTATUS_PROCESS_ILLEGAL_OPCODE;
|
||||
case 13: return NTLSTATUS_PROCESS_GENERAL_PROTECTION;
|
||||
case 14: return NTLSTATUS_PROCESS_PAGE_FAULT;
|
||||
case 17: return NTLSTATUS_PROCESS_ALIGNMENT_FAULT;
|
||||
default: return NTLSTATUS_PROCESS_UNKNOWN_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
// Handles faults that are still kernel-owned repair cases, not user exceptions.
|
||||
KSTATUS KeExceptionResolveRecoverableFault(const KFAULT_FRAME* frame) {
|
||||
if (!KeFaultFrameIsValid(frame))
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (frame->Vector != 14)
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
return MmVadResolvePageFaultByAddress((uintptr_t)frame->Cr2, frame->ErrorCode);
|
||||
}
|
||||
|
||||
// Validates a user exception dispatcher registration before publishing it.
|
||||
static KSTATUS KiValidateExceptionDispatcherRequest(const SYS_EXCEPTION_DISPATCHER_REQUEST* request) {
|
||||
if (!request)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->Size != sizeof(*request))
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->Flags != SYS_EXCEPTION_DISPATCH_FLAG_NONE)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
if (!request->DispatcherRoutine) {
|
||||
if (request->ExceptionStackBase || request->ExceptionStackSize)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!KiExceptionUserAddressValid((uintptr_t)request->DispatcherRoutine))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
if ((request->ExceptionStackBase == 0) != (request->ExceptionStackSize == 0))
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->ExceptionStackBase) {
|
||||
if (!KiExceptionUserRangeValid((uintptr_t)request->ExceptionStackBase, request->ExceptionStackSize))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
if (request->ExceptionStackSize < sizeof(SYS_EXCEPTION_FRAME) + 64u)
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Registers or clears the current process's native user exception dispatcher.
|
||||
KSTATUS KeSetExceptionDispatcher(PROCESS* process, const SYS_EXCEPTION_DISPATCHER_REQUEST* request) {
|
||||
if (!process || !request)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = KiValidateExceptionDispatcherRequest(request);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ExceptionLock);
|
||||
if (!request->DispatcherRoutine) {
|
||||
process->ExceptionDispatcher = 0;
|
||||
process->ExceptionDispatcherContext = 0;
|
||||
process->ExceptionStackBase = 0;
|
||||
process->ExceptionStackSize = 0;
|
||||
process->ExceptionDispatchFlags = SYS_EXCEPTION_DISPATCH_FLAG_NONE;
|
||||
} else {
|
||||
process->ExceptionDispatcher = (uintptr_t)request->DispatcherRoutine;
|
||||
process->ExceptionDispatcherContext = (uintptr_t)request->DispatcherContext;
|
||||
process->ExceptionStackBase = (uintptr_t)request->ExceptionStackBase;
|
||||
process->ExceptionStackSize = request->ExceptionStackSize;
|
||||
process->ExceptionDispatchFlags = request->Flags;
|
||||
}
|
||||
KeReleaseSpinlock(&process->ExceptionLock, flags);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Copies a stable snapshot of the current process's exception dispatcher registration.
|
||||
KSTATUS KeGetExceptionDispatcher(PROCESS* process, SYS_EXCEPTION_DISPATCHER_REQUEST* request) {
|
||||
if (!process || !request)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
memset(request, 0, sizeof(*request));
|
||||
request->Size = sizeof(*request);
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ExceptionLock);
|
||||
request->Flags = process->ExceptionDispatchFlags;
|
||||
request->DispatcherRoutine = (SYS_USER_EXCEPTION_DISPATCHER)process->ExceptionDispatcher;
|
||||
request->DispatcherContext = (void*)process->ExceptionDispatcherContext;
|
||||
request->ExceptionStackBase = (void*)process->ExceptionStackBase;
|
||||
request->ExceptionStackSize = process->ExceptionStackSize;
|
||||
KeReleaseSpinlock(&process->ExceptionLock, flags);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
+11
-4
@@ -163,6 +163,9 @@ void KeSetCurrentTssRsp0(uintptr_t rsp0) {
|
||||
// IDT.
|
||||
#define IDT_ENTRIES 256
|
||||
|
||||
#define KI_IDT_TYPE_INTERRUPT_GATE 0x8Eu
|
||||
#define KI_IDT_TYPE_USER_INTERRUPT_GATE 0xEEu
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint16_t OffsetLow;
|
||||
@@ -211,9 +214,12 @@ void KeInitializeIdt(void) {
|
||||
};
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
KiIdtSetGate(i, (uintptr_t)faultStubs[i], 0x8E, 0);
|
||||
KiIdtSetGate(i, (uintptr_t)faultStubs[i], KI_IDT_TYPE_INTERRUPT_GATE, 0);
|
||||
|
||||
KiIdtSetGate(0x40, (uintptr_t)KeSyscallEntry, 0xEE, 0);
|
||||
// User-mode INT3 must enter #BP, not fail the gate-DPL check and become #GP.
|
||||
KiIdtSetGate(3, (uintptr_t)KeFaultBP, KI_IDT_TYPE_USER_INTERRUPT_GATE, 0);
|
||||
|
||||
KiIdtSetGate(0x40, (uintptr_t)KeSyscallEntry, KI_IDT_TYPE_USER_INTERRUPT_GATE, 0);
|
||||
|
||||
static void *irqStubs[NUM_IRQS] = {
|
||||
(void*)KeIrqStub0, (void*)KeIrqStub1, (void*)KeIrqStub2,
|
||||
@@ -226,9 +232,10 @@ void KeInitializeIdt(void) {
|
||||
(void*)KeIrqStub21, (void*)KeIrqStub22, (void*)KeIrqStub23,
|
||||
};
|
||||
for (int i = 0; i < NUM_IRQS; i++)
|
||||
KiIdtSetGate(0x20 + i, (uintptr_t)irqStubs[i], 0x8E, 0);
|
||||
KiIdtSetGate(0x20 + i, (uintptr_t)irqStubs[i], KI_IDT_TYPE_INTERRUPT_GATE, 0);
|
||||
|
||||
KiIdtSetGate(KE_VECTOR_RESCHEDULE_IPI, (uintptr_t)KeRescheduleIpiStub, 0x8E, 0);
|
||||
KiIdtSetGate(KE_VECTOR_RESCHEDULE_IPI, (uintptr_t)KeRescheduleIpiStub,
|
||||
KI_IDT_TYPE_INTERRUPT_GATE, 0);
|
||||
|
||||
KeLoadIdtForCurrentCpu();
|
||||
}
|
||||
|
||||
@@ -263,10 +263,10 @@ void KeInputInitialize(const HAL_API* hal) {
|
||||
__declspec(dllexport) KSTATUS KeInputRegisterDevice(const char* name, uint32_t flags, uint32_t* outDeviceId) {
|
||||
(void)flags;
|
||||
uint32_t id = gNextInputDeviceId++;
|
||||
if (id >= MAX_INPUT_DEVICES) return STATUS_NO_MEMORY;
|
||||
if (id >= MAX_INPUT_DEVICES) return NTLSTATUS_NO_MEMORY;
|
||||
if (outDeviceId) *outDeviceId = id;
|
||||
DbgPrint("Input: registered device %u (%s)\n", id, name ? name : "unnamed");
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the input Submit Key operation.
|
||||
@@ -378,9 +378,9 @@ INPUT_KEY KeInputKbPoll(void) {
|
||||
// Waits until at least one keyboard event is available or the timeout expires.
|
||||
KSTATUS KeInputWaitKey(uint8_t alertable, uint64_t timeoutMs) {
|
||||
if (KeInputKbPoll() != INPUT_KEY_NONE)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
if (!gKeyboardEvent)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
for (;;) {
|
||||
EVENT* event = gKeyboardEvent;
|
||||
@@ -389,7 +389,7 @@ KSTATUS KeInputWaitKey(uint8_t alertable, uint64_t timeoutMs) {
|
||||
if (!KSUCCESS(s))
|
||||
return s;
|
||||
if (KeInputKbPoll() != INPUT_KEY_NONE)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,17 +505,17 @@ static void KiInputQueueDestroy(OBJECT* object) {
|
||||
|
||||
// Opens the default keyboard input queue as a waitable object.
|
||||
KSTATUS KeInputOpenQueue(INPUT_QUEUE** out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*out = (INPUT_QUEUE*)0;
|
||||
if (!gKeyboardEvent) return STATUS_FAILURE;
|
||||
if (!gKeyboardEvent) return NTLSTATUS_FAILURE;
|
||||
|
||||
INPUT_QUEUE* queue = (INPUT_QUEUE*)ObAllocateObject(ObjectTypeInputQueue, sizeof(INPUT_QUEUE));
|
||||
if (!queue) return STATUS_NO_MEMORY;
|
||||
if (!queue) return NTLSTATUS_NO_MEMORY;
|
||||
queue->Header.Destroy = KiInputQueueDestroy;
|
||||
ObReferenceObject(&gKeyboardEvent->Header);
|
||||
queue->WaitEvent = gKeyboardEvent;
|
||||
*out = queue;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns the event that wakes when keyboard input can be read.
|
||||
|
||||
+16
-16
@@ -66,13 +66,13 @@ __declspec(dllexport) void IrpQueueCancelAll(IRP_QUEUE* q, KSTATUS status) {
|
||||
// Remove locks.
|
||||
|
||||
__declspec(dllexport) KSTATUS IoInitializeRemoveLock(IO_REMOVE_LOCK* lock) {
|
||||
if (!lock) return STATUS_INVALID_PARAMETER;
|
||||
if (!lock) return NTLSTATUS_INVALID_PARAMETER;
|
||||
memset(lock, 0, sizeof(*lock));
|
||||
lock->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
lock->IoCount = 1; // sentinel reference released by IoReleaseRemoveLockAndWait
|
||||
KSTATUS st = KeEventCreate(EventManualReset, 0, &lock->RemovedEvent);
|
||||
if (!KSUCCESS(st)) return st;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases remove Lock.
|
||||
@@ -87,15 +87,15 @@ __declspec(dllexport) void IoDestroyRemoveLock(IO_REMOVE_LOCK* lock) {
|
||||
// Implements the acquire Remove Lock operation.
|
||||
__declspec(dllexport) KSTATUS IoAcquireRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp) {
|
||||
(void)irp;
|
||||
if (!lock) return STATUS_INVALID_PARAMETER;
|
||||
if (!lock) return NTLSTATUS_INVALID_PARAMETER;
|
||||
uintptr_t flags = KeAcquireSpinlock(&lock->Lock);
|
||||
if (lock->Removing) {
|
||||
KeReleaseSpinlock(&lock->Lock, flags);
|
||||
return STATUS_OBJECT_DEAD;
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
}
|
||||
_InterlockedIncrement(&lock->IoCount);
|
||||
KeReleaseSpinlock(&lock->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases remove Lock.
|
||||
@@ -136,13 +136,13 @@ static size_t IoIrpSize(uint8_t stackCount) {
|
||||
|
||||
// Creates irp.
|
||||
__declspec(dllexport) KSTATUS IoAllocateIrp(uint8_t stackCount, IRP** outIrp) {
|
||||
if (!outIrp) return STATUS_INVALID_PARAMETER;
|
||||
if (!outIrp) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (stackCount == 0) stackCount = 1;
|
||||
IRP* irp = (IRP*)MmAllocatePoolTag(IoIrpSize(stackCount), MM_POOL_TAG('i', 'r', 'p', ' '));
|
||||
if (!irp) return STATUS_NO_MEMORY;
|
||||
if (!irp) return NTLSTATUS_NO_MEMORY;
|
||||
IoInitializeIrp(irp, stackCount);
|
||||
*outIrp = irp;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases irp.
|
||||
@@ -156,7 +156,7 @@ __declspec(dllexport) void IoInitializeIrp(IRP* irp, uint8_t stackCount) {
|
||||
if (stackCount == 0) stackCount = 1;
|
||||
memset(irp, 0, IoIrpSize(stackCount));
|
||||
LIST_INIT(&irp->Link);
|
||||
irp->Status = STATUS_FAILURE;
|
||||
irp->Status = NTLSTATUS_FAILURE;
|
||||
irp->Information = 0;
|
||||
irp->CancelLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
irp->StackCount = stackCount;
|
||||
@@ -276,9 +276,9 @@ __declspec(dllexport) void IoBuildDeviceIoControlIrp(IRP* irp,
|
||||
// Completion/submission.
|
||||
|
||||
__declspec(dllexport) KSTATUS IoCompleteRequest(IRP* irp, KSTATUS status, size_t information) {
|
||||
if (!irp) return STATUS_INVALID_PARAMETER;
|
||||
if (!irp) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (irp->Flags & IRP_FLAG_COMPLETED)
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
|
||||
irp->Flags |= IRP_FLAG_COMPLETED;
|
||||
irp->Status = status;
|
||||
@@ -299,13 +299,13 @@ __declspec(dllexport) KSTATUS IoCompleteRequest(IRP* irp, KSTATUS status, size_t
|
||||
if (irp->CompletionFn)
|
||||
irp->CompletionFn(irp, irp->CompletionCtx);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Submits irp.
|
||||
__declspec(dllexport) KSTATUS IoSubmitIrp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
if (!device || !irp) return STATUS_INVALID_PARAMETER;
|
||||
irp->Status = STATUS_FAILURE;
|
||||
if (!device || !irp) return NTLSTATUS_INVALID_PARAMETER;
|
||||
irp->Status = NTLSTATUS_FAILURE;
|
||||
irp->Information = 0;
|
||||
irp->Flags &= ~IRP_FLAG_COMPLETED;
|
||||
return IoCallDriver(device, irp);
|
||||
@@ -313,7 +313,7 @@ __declspec(dllexport) KSTATUS IoSubmitIrp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
|
||||
// Submits irp Sync.
|
||||
__declspec(dllexport) KSTATUS IoSubmitIrpSync(DEVICE_OBJECT* device, IRP* irp) {
|
||||
if (!device || !irp) return STATUS_INVALID_PARAMETER;
|
||||
if (!device || !irp) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
EVENT* ev = (EVENT*)0;
|
||||
KSTATUS st = KeEventCreate(EventAutoReset, 0, &ev);
|
||||
@@ -322,7 +322,7 @@ __declspec(dllexport) KSTATUS IoSubmitIrpSync(DEVICE_OBJECT* device, IRP* irp) {
|
||||
irp->CompletionEvent = ev;
|
||||
|
||||
st = IoSubmitIrp(device, irp);
|
||||
if (st == STATUS_PENDING) {
|
||||
if (st == NTLSTATUS_PENDING) {
|
||||
KeWaitForEvent(ev, 0);
|
||||
st = irp->Status;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ void KeIrqInitialize(const HAL_API *hal) {
|
||||
|
||||
// Implements the irq Allocate Msi Vector operation.
|
||||
__declspec(dllexport) KSTATUS KeIrqAllocateMsiVector(uint8_t* outIrq) {
|
||||
if (!outIrq) return STATUS_INVALID_PARAMETER;
|
||||
if (!outIrq) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
for (uint8_t irq = MSI_IRQ_FIRST; irq <= MSI_IRQ_LAST; irq++) {
|
||||
IRQ_HANDLER_LIST* list = &gIrqHandlers[irq];
|
||||
@@ -49,11 +49,11 @@ __declspec(dllexport) KSTATUS KeIrqAllocateMsiVector(uint8_t* outIrq) {
|
||||
*outIrq = irq;
|
||||
DbgPrint("KeIrq: allocated MSI vector slot IRQ %u vector 0x%02x\n",
|
||||
irq, 0x20u + irq);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
// Implements the irq Register operation.
|
||||
|
||||
+10
-10
@@ -13,28 +13,28 @@ static void KiMutexDestroy(OBJECT* obj) { (void)obj; }
|
||||
|
||||
// Implements the mutex Create operation.
|
||||
__declspec(dllexport) KSTATUS KeMutexCreate(MUTEX **out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
MUTEX* m = (MUTEX *)ObAllocateObject(ObjectTypeMutex, sizeof(MUTEX));
|
||||
if (!m) return STATUS_NO_MEMORY;
|
||||
if (!m) return NTLSTATUS_NO_MEMORY;
|
||||
m->Header.Destroy = KiMutexDestroy;
|
||||
m->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
m->Owner = (struct THREAD *)0;
|
||||
LIST_INIT(&m->WaitList);
|
||||
*out = m;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the acquire Mutex operation.
|
||||
__declspec(dllexport) KSTATUS KeAcquireMutex(MUTEX* mutex) {
|
||||
if (!mutex) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!mutex) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&mutex->Lock);
|
||||
if (!mutex->Owner) {
|
||||
mutex->Owner = self;
|
||||
KeReleaseSpinlock(&mutex->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KePrepareBlockThread(self, &mutex->Header, 0);
|
||||
@@ -46,16 +46,16 @@ __declspec(dllexport) KSTATUS KeAcquireMutex(MUTEX* mutex) {
|
||||
|
||||
// Implements the try Acquire Mutex operation.
|
||||
__declspec(dllexport) KSTATUS KeTryAcquireMutex(MUTEX* mutex) {
|
||||
if (!mutex) return STATUS_INVALID_PARAMETER;
|
||||
if (!mutex) return NTLSTATUS_INVALID_PARAMETER;
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
uintptr_t flags = KeAcquireSpinlock(&mutex->Lock);
|
||||
if (!mutex->Owner) {
|
||||
mutex->Owner = self;
|
||||
KeReleaseSpinlock(&mutex->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KeReleaseSpinlock(&mutex->Lock, flags);
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
// Releases mutex.
|
||||
@@ -71,7 +71,7 @@ __declspec(dllexport) void KeReleaseMutex(MUTEX* mutex) {
|
||||
// returns. Do not drop Owner to NULL, or another thread can steal it.
|
||||
mutex->Owner = waiter;
|
||||
KeReleaseSpinlock(&mutex->Lock, flags);
|
||||
KeUnblockThreadWithStatus(waiter, STATUS_SUCCESS);
|
||||
KeUnblockThreadWithStatus(waiter, NTLSTATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+125
-55
@@ -11,6 +11,7 @@
|
||||
#include <kernel/io_file.h>
|
||||
#include <kernel/mm_virt.h>
|
||||
#include <kernel/ob_object.h>
|
||||
#include <kernel/ke_named_queue.h>
|
||||
#include <kernel/ke_cpu.h>
|
||||
#include <kernel/hal/hal_apic.h>
|
||||
#include <ntlite/syscall.h>
|
||||
@@ -53,10 +54,10 @@ PROCESS* KeGetSystemProcess(void) {
|
||||
|
||||
// Creates system Process.
|
||||
KSTATUS KeCreateSystemProcess(PROCESS** out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (gSystemProcess) {
|
||||
*out = gSystemProcess;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PROCESS* proc = (PROCESS*)0;
|
||||
@@ -69,7 +70,7 @@ KSTATUS KeCreateSystemProcess(PROCESS** out) {
|
||||
proc->Flags |= KE_PROCESS_FLAG_SYSTEM | KE_PROCESS_FLAG_TERMINATION_PROTECTED;
|
||||
gSystemProcess = proc;
|
||||
*out = proc;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the count Process Handles Locked operation.
|
||||
@@ -96,6 +97,38 @@ static void KiCopyTruncatedString(char* dst, size_t dstSize, const char* src, si
|
||||
dst[n] = '\0';
|
||||
}
|
||||
|
||||
// Aggregates native structured-exception counters across all processes.
|
||||
void KeQueryExceptionStats(SYS_EXCEPTION_STATS* statsOut) {
|
||||
if (!statsOut)
|
||||
return;
|
||||
|
||||
memset(statsOut, 0, sizeof(*statsOut));
|
||||
statsOut->Size = sizeof(*statsOut);
|
||||
statsOut->Version = SYS_STATS_VERSION;
|
||||
|
||||
KiProcessInit();
|
||||
uintptr_t flags = KeAcquireSpinlock(&gProcessListLock);
|
||||
LIST_ENTRY* head = &gProcessList;
|
||||
for (LIST_ENTRY* node = head->Fwd; node != head; node = node->Fwd) {
|
||||
PROCESS* p = CONTAINING_RECORD(node, PROCESS, GlobalLink);
|
||||
uintptr_t exceptionFlags = KeAcquireSpinlock(&p->ExceptionLock);
|
||||
statsOut->Delivered += p->ExceptionDeliveredCount;
|
||||
statsOut->UserRaised += p->ExceptionUserRaisedCount;
|
||||
statsOut->Continued += p->ExceptionContinuedCount;
|
||||
statsOut->Unhandled += p->ExceptionUnhandledCount;
|
||||
statsOut->InvalidContinue += p->ExceptionInvalidContinueCount;
|
||||
if (p->ExceptionMaxNestedDispatch > statsOut->MaxNestedDispatch)
|
||||
statsOut->MaxNestedDispatch = p->ExceptionMaxNestedDispatch;
|
||||
if (p->LastExceptionCode) {
|
||||
statsOut->LastCode = p->LastExceptionCode;
|
||||
statsOut->LastExceptionAddress = p->LastExceptionAddress;
|
||||
statsOut->LastFaultAddress = p->LastExceptionFaultAddress;
|
||||
}
|
||||
KeReleaseSpinlock(&p->ExceptionLock, exceptionFlags);
|
||||
}
|
||||
KeReleaseSpinlock(&gProcessListLock, flags);
|
||||
}
|
||||
|
||||
// Copies process Info.
|
||||
size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount) {
|
||||
KiProcessInit();
|
||||
@@ -130,6 +163,18 @@ size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount) {
|
||||
info->HandleCount = handleCount;
|
||||
info->ExitCode = exitCode;
|
||||
|
||||
uintptr_t exceptionFlags = KeAcquireSpinlock(&p->ExceptionLock);
|
||||
info->ExceptionDelivered = p->ExceptionDeliveredCount;
|
||||
info->ExceptionUserRaised = p->ExceptionUserRaisedCount;
|
||||
info->ExceptionContinued = p->ExceptionContinuedCount;
|
||||
info->ExceptionUnhandled = p->ExceptionUnhandledCount;
|
||||
info->ExceptionInvalidContinue = p->ExceptionInvalidContinueCount;
|
||||
info->ExceptionMaxNestedDispatch = p->ExceptionMaxNestedDispatch;
|
||||
info->LastExceptionCode = p->LastExceptionCode;
|
||||
info->LastExceptionAddress = p->LastExceptionAddress;
|
||||
info->LastExceptionFaultAddress = p->LastExceptionFaultAddress;
|
||||
KeReleaseSpinlock(&p->ExceptionLock, exceptionFlags);
|
||||
|
||||
if (exited) {
|
||||
info->State = SYS_PROCESS_STATE_EXITED;
|
||||
info->Flags |= SYS_PROCESS_FLAG_EXITED;
|
||||
@@ -201,11 +246,11 @@ static uint32_t KiWaitObjectTypeToSys(OBJECT_TYPE type) {
|
||||
|
||||
// Copies one process's thread telemetry into caller-provided storage.
|
||||
KSTATUS KeCopyProcessThreadInfo(uint32_t pid, struct SYS_THREAD_INFO* infoOut, size_t maxCount, size_t* countOut) {
|
||||
if (!countOut) return STATUS_INVALID_PARAMETER;
|
||||
if (maxCount && !infoOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!countOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (maxCount && !infoOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
PROCESS* process = KeGetProcessById(pid);
|
||||
if (!process) return STATUS_NOT_FOUND;
|
||||
if (!process) return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
THREAD* current = KeGetCurrentThread();
|
||||
size_t count = 0;
|
||||
@@ -246,7 +291,7 @@ KSTATUS KeCopyProcessThreadInfo(uint32_t pid, struct SYS_THREAD_INFO* infoOut, s
|
||||
|
||||
*countOut = count;
|
||||
ObDereferenceObject(&process->Header);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases all kernel objects still reachable from a process handle table.
|
||||
@@ -268,8 +313,10 @@ static void KiProcessReleaseAllHandles(PROCESS* proc) {
|
||||
}
|
||||
KeReleaseSpinlock(&proc->HandleLock, flags);
|
||||
|
||||
if (obj)
|
||||
if (obj) {
|
||||
KeNamedQueueUnpublishHandle(proc, (uint32_t)i, obj);
|
||||
ObDereferenceObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,6 +348,13 @@ static void KiProcessRundownResources(PROCESS* proc) {
|
||||
proc->UserCmdlineSize = 0;
|
||||
proc->UserCwdBase = 0;
|
||||
proc->UserCwdSize = 0;
|
||||
uintptr_t exceptionFlags = KeAcquireSpinlock(&proc->ExceptionLock);
|
||||
proc->ExceptionDispatcher = 0;
|
||||
proc->ExceptionDispatcherContext = 0;
|
||||
proc->ExceptionStackBase = 0;
|
||||
proc->ExceptionStackSize = 0;
|
||||
proc->ExceptionDispatchFlags = SYS_EXCEPTION_DISPATCH_FLAG_NONE;
|
||||
KeReleaseSpinlock(&proc->ExceptionLock, exceptionFlags);
|
||||
}
|
||||
|
||||
// Destructor (called by ObDereferenceObject when RefCount hits zero).
|
||||
@@ -334,10 +388,10 @@ static void KiProcessDestroy(OBJECT* obj) {
|
||||
KSTATUS KeCreateProcess(const char* name, PROCESS **out) {
|
||||
KiProcessInit();
|
||||
|
||||
if (!name || !out) return STATUS_INVALID_PARAMETER;
|
||||
if (!name || !out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
PROCESS* proc = (PROCESS *)ObAllocateObject(ObjectTypeProcess, sizeof(PROCESS));
|
||||
if (!proc) return STATUS_NO_MEMORY;
|
||||
if (!proc) return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
proc->Header.Destroy = KiProcessDestroy;
|
||||
|
||||
@@ -365,6 +419,21 @@ KSTATUS KeCreateProcess(const char* name, PROCESS **out) {
|
||||
proc->UserCwdSize = 0;
|
||||
proc->ModuleCount = 0;
|
||||
proc->ModuleLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
proc->ExceptionDispatcher = 0;
|
||||
proc->ExceptionDispatcherContext = 0;
|
||||
proc->ExceptionStackBase = 0;
|
||||
proc->ExceptionStackSize = 0;
|
||||
proc->ExceptionDispatchFlags = SYS_EXCEPTION_DISPATCH_FLAG_NONE;
|
||||
proc->ExceptionDeliveredCount = 0;
|
||||
proc->ExceptionUserRaisedCount = 0;
|
||||
proc->ExceptionContinuedCount = 0;
|
||||
proc->ExceptionUnhandledCount = 0;
|
||||
proc->ExceptionInvalidContinueCount = 0;
|
||||
proc->ExceptionMaxNestedDispatch = 0;
|
||||
proc->LastExceptionCode = 0;
|
||||
proc->LastExceptionAddress = 0;
|
||||
proc->LastExceptionFaultAddress = 0;
|
||||
proc->ExceptionLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
proc->CurrentDirectory[0] = '\0';
|
||||
proc->CurrentDirectoryLength = 0;
|
||||
proc->CurrentDrive = KeGetSystemRootDrive();
|
||||
@@ -380,7 +449,7 @@ KSTATUS KeCreateProcess(const char* name, PROCESS **out) {
|
||||
// Create the manual-reset exit event (initially unsignaled).
|
||||
if (!KSUCCESS(KeEventCreate(EventManualReset, 0, &proc->ExitEvent))) {
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gProcessListLock);
|
||||
@@ -388,7 +457,7 @@ KSTATUS KeCreateProcess(const char* name, PROCESS **out) {
|
||||
KeReleaseSpinlock(&gProcessListLock, flags);
|
||||
|
||||
*out = proc;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// KeSetupUserProcessEnvironment.
|
||||
@@ -396,24 +465,24 @@ static KSTATUS KiCopyEnvironmentStringView(PROCESS* proc,
|
||||
SYS_STRING_VIEW src,
|
||||
uintptr_t* baseOut,
|
||||
size_t* sizeOut) {
|
||||
if (!baseOut || !sizeOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!baseOut || !sizeOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*baseOut = 0;
|
||||
*sizeOut = 0;
|
||||
|
||||
if (!SysSvIsValid(src)) return STATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(src, '\0')) return STATUS_INVALID_PARAMETER;
|
||||
if (src.Length == (size_t)-1) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (!SysSvIsValid(src)) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(src, '\0')) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (src.Length == (size_t)-1) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
size_t len = src.Length + 1;
|
||||
char* dst = (char*)MmAllocateUserMemoryForProcess(proc, len);
|
||||
if (!dst) return STATUS_NO_MEMORY;
|
||||
if (!dst) return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
if (src.Length) memcpy(dst, src.Data, src.Length);
|
||||
dst[src.Length] = '\0';
|
||||
|
||||
*baseOut = (uintptr_t)dst;
|
||||
*sizeOut = len;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static KSTATUS KiCopyEnvironmentStringViewFixed(PROCESS* proc,
|
||||
@@ -421,16 +490,16 @@ static KSTATUS KiCopyEnvironmentStringViewFixed(PROCESS* proc,
|
||||
size_t capacity,
|
||||
uintptr_t* baseOut,
|
||||
size_t* sizeOut) {
|
||||
if (!baseOut || !sizeOut || capacity == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!baseOut || !sizeOut || capacity == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*baseOut = 0;
|
||||
*sizeOut = 0;
|
||||
|
||||
if (!SysSvIsValid(src)) return STATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(src, '\0')) return STATUS_INVALID_PARAMETER;
|
||||
if (src.Length + 1 > capacity) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (!SysSvIsValid(src)) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(src, '\0')) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (src.Length + 1 > capacity) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
char* dst = (char*)MmAllocateUserMemoryForProcess(proc, capacity);
|
||||
if (!dst) return STATUS_NO_MEMORY;
|
||||
if (!dst) return NTLSTATUS_NO_MEMORY;
|
||||
memset(dst, 0, capacity);
|
||||
|
||||
if (src.Length) memcpy(dst, src.Data, src.Length);
|
||||
@@ -438,7 +507,7 @@ static KSTATUS KiCopyEnvironmentStringViewFixed(PROCESS* proc,
|
||||
|
||||
*baseOut = (uintptr_t)dst;
|
||||
*sizeOut = capacity;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases partial Process Environment.
|
||||
@@ -473,16 +542,16 @@ static KSTATUS KiFormatNativeCwdV(const PROCESS* proc,
|
||||
size_t outSize,
|
||||
size_t* lengthOut) {
|
||||
if (lengthOut) *lengthOut = 0;
|
||||
if (!out || outSize == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!out || outSize == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
out[0] = '\0';
|
||||
|
||||
if (!SysSvIsValid(currentDirectory)) return STATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(currentDirectory, '\0')) return STATUS_INVALID_PARAMETER;
|
||||
if (!SysSvIsValid(currentDirectory)) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(currentDirectory, '\0')) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint8_t drive = proc ? proc->CurrentDrive : 0;
|
||||
if (drive > 7) drive = 0;
|
||||
|
||||
if (currentDirectory.Length + 4 > outSize) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (currentDirectory.Length + 4 > outSize) return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
out[0] = (char)('0' + drive);
|
||||
out[1] = ':';
|
||||
@@ -492,20 +561,20 @@ static KSTATUS KiFormatNativeCwdV(const PROCESS* proc,
|
||||
out[3 + currentDirectory.Length] = '\0';
|
||||
|
||||
if (lengthOut) *lengthOut = 3 + currentDirectory.Length;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS KeSetupUserProcessEnvironment(PROCESS* proc,
|
||||
SYS_STRING_VIEW imagePath,
|
||||
SYS_STRING_VIEW commandLine,
|
||||
SYS_STRING_VIEW currentDirectory) {
|
||||
if (!proc || imagePath.Length == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!proc || imagePath.Length == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!SysSvIsValid(imagePath) || !SysSvIsValid(commandLine) || !SysSvIsValid(currentDirectory))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (SysSvContainsByte(imagePath, '\0') ||
|
||||
SysSvContainsByte(commandLine, '\0') ||
|
||||
SysSvContainsByte(currentDirectory, '\0'))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
SYS_STRING_VIEW finalCommandLine = commandLine.Length ? commandLine : imagePath;
|
||||
SYS_STRING_VIEW finalCwdRel = currentDirectory;
|
||||
@@ -533,7 +602,7 @@ KSTATUS KeSetupUserProcessEnvironment(PROCESS* proc,
|
||||
if (!KSUCCESS(s)) goto fail;
|
||||
|
||||
SYS_PEB* peb = (SYS_PEB*)MmAllocateUserMemoryForProcess(proc, sizeof(SYS_PEB));
|
||||
if (!peb) { s = STATUS_NO_MEMORY; goto fail; }
|
||||
if (!peb) { s = NTLSTATUS_NO_MEMORY; goto fail; }
|
||||
memset(peb, 0, sizeof(SYS_PEB));
|
||||
|
||||
peb->Magic = SYS_PEB_MAGIC;
|
||||
@@ -545,7 +614,7 @@ KSTATUS KeSetupUserProcessEnvironment(PROCESS* proc,
|
||||
|
||||
proc->UserPebBase = (uintptr_t)peb;
|
||||
proc->UserPebSize = sizeof(SYS_PEB);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
KiFreePartialProcessEnvironment(proc);
|
||||
@@ -568,8 +637,8 @@ void KeCompleteProcessExitIfLastThread(PROCESS* process) {
|
||||
|
||||
// Implements the exit Process operation.
|
||||
KSTATUS KeExitProcess(PROCESS* process, int32_t exitCode) {
|
||||
if (!process) return STATUS_INVALID_PARAMETER;
|
||||
if (KeIsProcessTerminationProtected(process)) return STATUS_ACCESS_DENIED;
|
||||
if (!process) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (KeIsProcessTerminationProtected(process)) return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
process->ExitCode = exitCode;
|
||||
_InterlockedExchange(&process->Terminating, 1);
|
||||
@@ -578,13 +647,13 @@ KSTATUS KeExitProcess(PROCESS* process, int32_t exitCode) {
|
||||
// not drop the process object here: each thread owns one process reference,
|
||||
// and KiThreadDestroy releases that reference after unlinking the thread.
|
||||
KeCompleteProcessExitIfLastThread(process);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the terminate Process operation.
|
||||
KSTATUS KeTerminateProcess(PROCESS* process, int32_t exitCode) {
|
||||
if (!process) return STATUS_INVALID_PARAMETER;
|
||||
if (KeIsProcessTerminationProtected(process)) return STATUS_ACCESS_DENIED;
|
||||
if (!process) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (KeIsProcessTerminationProtected(process)) return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
process->ExitCode = exitCode;
|
||||
_InterlockedExchange(&process->Terminating, 1);
|
||||
@@ -606,7 +675,7 @@ KSTATUS KeTerminateProcess(PROCESS* process, int32_t exitCode) {
|
||||
// thread crashes, those waiters would otherwise keep ThreadCount > 0
|
||||
// and prevent the process ExitEvent from waking the shell.
|
||||
if (t->State == ThreadWaiting)
|
||||
KeAbortThreadWait(t, STATUS_ALERTED);
|
||||
KeAbortThreadWait(t, NTLSTATUS_ALERTED);
|
||||
else
|
||||
(void)KeAlertThread(t);
|
||||
|
||||
@@ -621,7 +690,7 @@ KSTATUS KeTerminateProcess(PROCESS* process, int32_t exitCode) {
|
||||
KeReleaseSpinlock(&process->HandleLock, flags);
|
||||
|
||||
KeCompleteProcessExitIfLastThread(process);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Checks whether process Terminating.
|
||||
@@ -636,14 +705,14 @@ int KeIsProcessTerminationProtected(PROCESS* process) {
|
||||
|
||||
// Copies the recorded process exit code.
|
||||
KSTATUS KeGetProcessExitCode(PROCESS* process, int32_t* exitCodeOut) {
|
||||
if (!process || !exitCodeOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!process || !exitCodeOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*exitCodeOut = process->ExitCode;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Handle table.
|
||||
KSTATUS KeAllocateHandleWithRights(PROCESS* process, OBJECT* object, uint32_t rights, uint32_t* handleOut) {
|
||||
if (!process || !object || !handleOut || rights == 0) return STATUS_INVALID_PARAMETER;
|
||||
if (!process || !object || !handleOut || rights == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->HandleLock);
|
||||
|
||||
@@ -655,12 +724,12 @@ KSTATUS KeAllocateHandleWithRights(PROCESS* process, OBJECT* object, uint32_t ri
|
||||
process->Handles[i].Flags = 0;
|
||||
*handleOut = (uint32_t)i;
|
||||
KeReleaseSpinlock(&process->HandleLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseSpinlock(&process->HandleLock, flags);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
// Creates handle.
|
||||
@@ -681,6 +750,7 @@ void KeCloseHandle(PROCESS* process, uint32_t handle) {
|
||||
KeReleaseSpinlock(&process->HandleLock, flags);
|
||||
if (obj->Type == ObjectTypeFile)
|
||||
(void)IoFlushFile((FILE_OBJECT*)obj);
|
||||
KeNamedQueueUnpublishHandle(process, handle, obj);
|
||||
ObDereferenceObject(obj);
|
||||
return;
|
||||
}
|
||||
@@ -719,18 +789,18 @@ uint32_t KeGetHandleRights(PROCESS* process, uint32_t handle) {
|
||||
|
||||
// Duplicates a handle from one process table into another.
|
||||
KSTATUS KeDuplicateHandleToProcess(PROCESS* sourceProcess, uint32_t sourceHandle, PROCESS* targetProcess, uint32_t desiredRights, uint32_t duplicateFlags, uint32_t* targetHandleOut) {
|
||||
if (!sourceProcess || !targetProcess || !targetHandleOut) return STATUS_INVALID_PARAMETER;
|
||||
if (sourceHandle == 0 || sourceHandle >= HANDLE_TABLE_SIZE) return STATUS_INVALID_HANDLE;
|
||||
if (!sourceProcess || !targetProcess || !targetHandleOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (sourceHandle == 0 || sourceHandle >= HANDLE_TABLE_SIZE) return NTLSTATUS_INVALID_HANDLE;
|
||||
|
||||
const uint32_t validDuplicateFlags = SYS_DUPLICATE_HANDLE_FLAG_SAME_RIGHTS;
|
||||
const uint32_t publicHandleRights = SYS_HANDLE_RIGHT_ALL;
|
||||
|
||||
if ((duplicateFlags & ~validDuplicateFlags) != 0) return STATUS_INVALID_PARAMETER;
|
||||
if ((duplicateFlags & ~validDuplicateFlags) != 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if ((duplicateFlags & SYS_DUPLICATE_HANDLE_FLAG_SAME_RIGHTS) != 0 && desiredRights != 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if ((duplicateFlags & SYS_DUPLICATE_HANDLE_FLAG_SAME_RIGHTS) == 0) {
|
||||
if (desiredRights == 0) return STATUS_INVALID_PARAMETER;
|
||||
if ((desiredRights & ~publicHandleRights) != 0) return STATUS_INVALID_PARAMETER;
|
||||
if (desiredRights == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if ((desiredRights & ~publicHandleRights) != 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OBJECT* obj = NULL;
|
||||
@@ -740,11 +810,11 @@ KSTATUS KeDuplicateHandleToProcess(PROCESS* sourceProcess, uint32_t sourceHandle
|
||||
HANDLE_ENTRY* entry = &sourceProcess->Handles[sourceHandle];
|
||||
if (!entry->Object) {
|
||||
KeReleaseSpinlock(&sourceProcess->HandleLock, savedFlags);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
return NTLSTATUS_INVALID_HANDLE;
|
||||
}
|
||||
if ((entry->Rights & HANDLE_RIGHT_DUPLICATE) == 0) {
|
||||
KeReleaseSpinlock(&sourceProcess->HandleLock, savedFlags);
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
obj = entry->Object;
|
||||
@@ -756,7 +826,7 @@ KSTATUS KeDuplicateHandleToProcess(PROCESS* sourceProcess, uint32_t sourceHandle
|
||||
if ((duplicateFlags & SYS_DUPLICATE_HANDLE_FLAG_SAME_RIGHTS) == 0) {
|
||||
if ((desiredRights & ~sourceRights) != 0) {
|
||||
ObDereferenceObject(obj);
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
}
|
||||
targetRights = desiredRights;
|
||||
}
|
||||
|
||||
+15
-15
@@ -84,13 +84,13 @@ static uint64_t KiQueueRemainingMilliseconds(uint64_t deadlineTick) {
|
||||
// Waits for a queue state event using either an infinite or finite timeout.
|
||||
static KSTATUS KiQueueWaitForEvent(QUEUE* queue, EVENT* event, uint64_t timeoutMilliseconds, uint64_t deadlineTick) {
|
||||
if (!queue || !event)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t waitMilliseconds = timeoutMilliseconds;
|
||||
if (timeoutMilliseconds != QUEUE_TIMEOUT_INFINITE) {
|
||||
waitMilliseconds = KiQueueRemainingMilliseconds(deadlineTick);
|
||||
if (waitMilliseconds == 0)
|
||||
return STATUS_TIMEOUT;
|
||||
return NTLSTATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
EVENT* events[1] = { event };
|
||||
@@ -99,11 +99,11 @@ static KSTATUS KiQueueWaitForEvent(QUEUE* queue, EVENT* event, uint64_t timeoutM
|
||||
|
||||
// Creates a fixed-depth queue with waitable occupancy and capacity events.
|
||||
KSTATUS KeQueueCreate(QUEUE **out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*out = (QUEUE*)0;
|
||||
|
||||
QUEUE* q = (QUEUE *)ObAllocateObject(ObjectTypeQueue, sizeof(QUEUE));
|
||||
if (!q) return STATUS_NO_MEMORY;
|
||||
if (!q) return NTLSTATUS_NO_MEMORY;
|
||||
q->Header.Destroy = KiQueueDestroy;
|
||||
q->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
q->Head = q->Tail = q->Count = 0;
|
||||
@@ -121,13 +121,13 @@ KSTATUS KeQueueCreate(QUEUE **out) {
|
||||
}
|
||||
|
||||
*out = q;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Sends one fixed-size queue message, waiting according to the timeout contract.
|
||||
KSTATUS KeSendMessage(QUEUE* queue, const QUEUE_MESSAGE* msg, uint64_t timeoutMilliseconds) {
|
||||
if (!queue || !msg) return STATUS_INVALID_PARAMETER;
|
||||
if (timeoutMilliseconds != 0 && !KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!queue || !msg) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (timeoutMilliseconds != 0 && !KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
uint64_t deadlineTick = 0;
|
||||
if (timeoutMilliseconds != 0 && timeoutMilliseconds != QUEUE_TIMEOUT_INFINITE)
|
||||
@@ -142,24 +142,24 @@ KSTATUS KeSendMessage(QUEUE* queue, const QUEUE_MESSAGE* msg, uint64_t timeoutMi
|
||||
queue->Count++;
|
||||
KiQueueNoteInsertedLocked(queue, previousCount);
|
||||
KeReleaseSpinlock(&queue->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KeClearEvent(queue->NotFullEvent);
|
||||
KeReleaseSpinlock(&queue->Lock, flags);
|
||||
|
||||
if (timeoutMilliseconds == 0)
|
||||
return STATUS_WOULD_BLOCK;
|
||||
return NTLSTATUS_WOULD_BLOCK;
|
||||
|
||||
KSTATUS s = KiQueueWaitForEvent(queue, queue->NotFullEvent, timeoutMilliseconds, deadlineTick);
|
||||
if (s == STATUS_TIMEOUT || KFAILED(s))
|
||||
if (s == NTLSTATUS_TIMEOUT || KFAILED(s))
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
// Receives one fixed-size queue message, waiting according to the timeout contract.
|
||||
KSTATUS KeReceiveMessage(QUEUE* queue, QUEUE_MESSAGE* msg, uint64_t timeoutMilliseconds) {
|
||||
if (!queue || !msg) return STATUS_INVALID_PARAMETER;
|
||||
if (timeoutMilliseconds != 0 && !KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!queue || !msg) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (timeoutMilliseconds != 0 && !KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
uint64_t deadlineTick = 0;
|
||||
if (timeoutMilliseconds != 0 && timeoutMilliseconds != QUEUE_TIMEOUT_INFINITE)
|
||||
@@ -174,16 +174,16 @@ KSTATUS KeReceiveMessage(QUEUE* queue, QUEUE_MESSAGE* msg, uint64_t timeoutMilli
|
||||
queue->Count--;
|
||||
KiQueueNoteRemovedLocked(queue, previousCount);
|
||||
KeReleaseSpinlock(&queue->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KeClearEvent(queue->NotEmptyEvent);
|
||||
KeReleaseSpinlock(&queue->Lock, flags);
|
||||
|
||||
if (timeoutMilliseconds == 0)
|
||||
return STATUS_WOULD_BLOCK;
|
||||
return NTLSTATUS_WOULD_BLOCK;
|
||||
|
||||
KSTATUS s = KiQueueWaitForEvent(queue, queue->NotEmptyEvent, timeoutMilliseconds, deadlineTick);
|
||||
if (s == STATUS_TIMEOUT || KFAILED(s))
|
||||
if (s == NTLSTATUS_TIMEOUT || KFAILED(s))
|
||||
return s;
|
||||
}
|
||||
}
|
||||
+20
-20
@@ -322,13 +322,13 @@ void KiInitializeSchedulerGlobal(void) {
|
||||
// Creates idle Thread For Cpu.
|
||||
KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) {
|
||||
if (!cpu || !gIdleProcess)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (cpu->IdleThread)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
THREAD* idle = (THREAD *)ObAllocateObject(ObjectTypeThread, sizeof(THREAD));
|
||||
if (!idle)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
idle->Header.Destroy = (void *)0;
|
||||
idle->ThreadId = cpu->CpuIndex ? (0x80000000u | cpu->CpuIndex) : 0;
|
||||
@@ -347,11 +347,11 @@ KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) {
|
||||
idle->AffinityMask = (cpu->CpuIndex < 64) ? (1ULL << cpu->CpuIndex) : 0ULL;
|
||||
idle->Owner = gIdleProcess;
|
||||
idle->WaitObject = (OBJECT *)0;
|
||||
idle->WaitStatus = STATUS_SUCCESS;
|
||||
idle->WaitStatus = NTLSTATUS_SUCCESS;
|
||||
idle->WaitListHead = (LIST_ENTRY*)0;
|
||||
idle->AlertableWait = 0;
|
||||
idle->SleepUntilTick = 0;
|
||||
idle->TimeoutStatus = STATUS_SUCCESS;
|
||||
idle->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
idle->UserStackBase = (void*)0;
|
||||
idle->Teb = (void*)0;
|
||||
idle->TebSize = 0;
|
||||
@@ -364,7 +364,7 @@ KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) {
|
||||
void* kstack = MmAllocatePoolTag(KSTACK_SIZE, MM_POOL_TAG('k', 's', 't', 'k'));
|
||||
if (!kstack) {
|
||||
ObDereferenceObject(&idle->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
idle->KernelStackBase = kstack;
|
||||
idle->KernelStackTop = (uintptr_t)kstack + KSTACK_SIZE;
|
||||
@@ -391,7 +391,7 @@ KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) {
|
||||
cpu->CurrentThread = idle;
|
||||
cpu->OutgoingThread = (THREAD*)0;
|
||||
idle->SwitchLockCookie = 0x202ULL;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Initializes scheduler.
|
||||
@@ -639,7 +639,7 @@ static void KiWakeThreadLocked(THREAD* thread, KSTATUS status) {
|
||||
thread->WaitListHead = (LIST_ENTRY*)0;
|
||||
thread->AlertableWait = 0;
|
||||
thread->SleepUntilTick = 0;
|
||||
thread->TimeoutStatus = STATUS_SUCCESS;
|
||||
thread->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
|
||||
thread->CpuBurstTicks = 0;
|
||||
thread->QuantaConsumed = 0;
|
||||
@@ -669,7 +669,7 @@ void KeUnblockThreadFromWaitListWithStatus(THREAD* thread, KSTATUS status) {
|
||||
ListRemove(&thread->SchedulerLink);
|
||||
thread->WaitListHead = (LIST_ENTRY*)0;
|
||||
thread->SleepUntilTick = 0;
|
||||
thread->TimeoutStatus = STATUS_SUCCESS;
|
||||
thread->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KiWakeThreadLocked(thread, status);
|
||||
KeReleaseSpinlock(&gSchedLock, flags);
|
||||
@@ -787,13 +787,13 @@ void KeSchedulerTick(void) {
|
||||
// Arms a timeout for the current thread after a wait primitive has prepared it to block.
|
||||
KSTATUS KeArmCurrentThreadTimeout(uint64_t milliseconds, KSTATUS timeoutStatus) {
|
||||
if (milliseconds == 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait())
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
if (!self || self->IsIdleThread)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t ticks = milliseconds / SCHED_TICK_MS;
|
||||
if ((milliseconds % SCHED_TICK_MS) != 0)
|
||||
@@ -805,7 +805,7 @@ KSTATUS KeArmCurrentThreadTimeout(uint64_t milliseconds, KSTATUS timeoutStatus)
|
||||
if (self->State != ThreadWaiting || self->WaitListHead != (LIST_ENTRY*)0 ||
|
||||
self->RunningCpu != KeGetCurrentCpu()->CpuIndex) {
|
||||
KeReleaseSpinlock(&gSchedLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uint64_t now = gSchedStats.Ticks;
|
||||
@@ -818,22 +818,22 @@ KSTATUS KeArmCurrentThreadTimeout(uint64_t milliseconds, KSTATUS timeoutStatus)
|
||||
self->TimeoutStatus = timeoutStatus;
|
||||
ListInsertTail(&gSleepList, &self->SchedulerLink);
|
||||
KeReleaseSpinlock(&gSchedLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the delay Thread operation.
|
||||
__declspec(dllexport) KSTATUS KeDelayThread(uint64_t milliseconds) {
|
||||
if (milliseconds == 0) {
|
||||
KeYield();
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!KeCanWait())
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
if (!self || self->IsIdleThread)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t ticks = milliseconds / SCHED_TICK_MS;
|
||||
if ((milliseconds % SCHED_TICK_MS) != 0)
|
||||
@@ -846,7 +846,7 @@ __declspec(dllexport) KSTATUS KeDelayThread(uint64_t milliseconds) {
|
||||
if (self->Queued || self->State != ThreadRunning ||
|
||||
self->RunningCpu != KeGetCurrentCpu()->CpuIndex) {
|
||||
KeReleaseSpinlock(&gSchedLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uint64_t now = gSchedStats.Ticks;
|
||||
@@ -856,11 +856,11 @@ __declspec(dllexport) KSTATUS KeDelayThread(uint64_t milliseconds) {
|
||||
|
||||
self->State = ThreadWaiting;
|
||||
self->WaitObject = (OBJECT*)0;
|
||||
self->WaitStatus = STATUS_PENDING;
|
||||
self->WaitStatus = NTLSTATUS_PENDING;
|
||||
self->WaitListHead = &gSleepList;
|
||||
self->AlertableWait = 0;
|
||||
self->SleepUntilTick = wakeTick;
|
||||
self->TimeoutStatus = STATUS_SUCCESS;
|
||||
self->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
ListInsertTail(&gSleepList, &self->SchedulerLink);
|
||||
|
||||
KeReleaseSpinlock(&gSchedLock, flags);
|
||||
|
||||
+22
-22
@@ -152,7 +152,7 @@ static void KiApcAlertableSelfTestWorker(void* arg) {
|
||||
DbgPrint("APC selftest: alertable wait returned status=%u delivered=%d\n",
|
||||
s, st->ApcDelivered);
|
||||
|
||||
if (s != STATUS_KERNEL_APC)
|
||||
if (s != NTLSTATUS_KERNEL_APC)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "APC selftest: alertable wait returned wrong status=%u\n", s);
|
||||
|
||||
if (st->ApcDelivered != 1)
|
||||
@@ -298,7 +298,7 @@ static void KiRunKernelApcSelfTest(void) {
|
||||
KI_APC_ALERTABLE_SELFTEST_STATE st;
|
||||
KAPC apc;
|
||||
memset(&st, 0, sizeof(st));
|
||||
st.WaitStatus = STATUS_PENDING;
|
||||
st.WaitStatus = NTLSTATUS_PENDING;
|
||||
|
||||
KSTATUS s;
|
||||
s = KeEventCreate(EventAutoReset, 0, &st.ReadyEvent);
|
||||
@@ -336,7 +336,7 @@ static void KiRunKernelApcSelfTest(void) {
|
||||
if (!KSUCCESS(s))
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "APC selftest: alert finished wait failed %d\n", s);
|
||||
|
||||
if (st.WaitStatus != STATUS_KERNEL_APC || st.ApcDelivered != 1)
|
||||
if (st.WaitStatus != NTLSTATUS_KERNEL_APC || st.ApcDelivered != 1)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "APC selftest: alertable result bad status=%u delivered=%d\n",
|
||||
st.WaitStatus, st.ApcDelivered);
|
||||
|
||||
@@ -447,7 +447,7 @@ static void KiRunIrpKernelApcSelfTest(const HAL_API* hal) {
|
||||
|
||||
DbgPrint("IRP/APC selftest: submitting drive=0 lba=0 sectors=1\n");
|
||||
s = IoSubmitIrp(st.DiskDevice, &st.Irp);
|
||||
if (s != STATUS_PENDING)
|
||||
if (s != NTLSTATUS_PENDING)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "IRP/APC selftest: IoSubmitIrp returned %u\n", s);
|
||||
|
||||
s = KeWaitForEvent(st.CompletionEvent, 0);
|
||||
@@ -501,13 +501,13 @@ static void KiRunPfnDatabaseSelfTest(void) {
|
||||
|
||||
if (!KSUCCESS(MmPfnPin(frame)) || pfn->PinCount != 1)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "PFN selftest: pin failed pin=%u\n", pfn->PinCount);
|
||||
if (MmPfnFree(frame) != STATUS_ACCESS_DENIED)
|
||||
if (MmPfnFree(frame) != NTLSTATUS_ACCESS_DENIED)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "PFN selftest: pinned frame was freed\n");
|
||||
if (!KSUCCESS(MmPfnUnpin(frame)) || pfn->PinCount != 0)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "PFN selftest: unpin failed pin=%u\n", pfn->PinCount);
|
||||
if (!KSUCCESS(MmPfnAddMapping(frame)) || pfn->MappedCount != 1)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "PFN selftest: mapping add failed maps=%u\n", pfn->MappedCount);
|
||||
if (MmPfnFree(frame) != STATUS_ACCESS_DENIED)
|
||||
if (MmPfnFree(frame) != NTLSTATUS_ACCESS_DENIED)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "PFN selftest: mapped frame was freed\n");
|
||||
if (!KSUCCESS(MmPfnRemoveMapping(frame)) || pfn->MappedCount != 0)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "PFN selftest: mapping remove failed maps=%u\n", pfn->MappedCount);
|
||||
@@ -589,7 +589,7 @@ static void KiRunMemoryMappingSelfTest(void) {
|
||||
PHYSICAL_ADDRESS phys = 0;
|
||||
uint64_t flags = 0;
|
||||
KSTATUS s = MmPteQueryPageFor(MmPteQuerySelfTest, 0, &phys, &flags);
|
||||
if (s != STATUS_NOT_FOUND) {
|
||||
if (s != NTLSTATUS_NOT_FOUND) {
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "MM selftest: virtual page zero is mapped phys=%016llx flags=%016llx status=%u\n",
|
||||
(unsigned long long)phys,
|
||||
(unsigned long long)flags,
|
||||
@@ -598,7 +598,7 @@ static void KiRunMemoryMappingSelfTest(void) {
|
||||
|
||||
uintptr_t testVa = 0xFFFFA00000000000ULL;
|
||||
s = MmPteQueryPageFor(MmPteQuerySelfTest, testVa, &phys, &flags);
|
||||
if (s != STATUS_NOT_FOUND) {
|
||||
if (s != NTLSTATUS_NOT_FOUND) {
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "MM selftest: test VA already mapped va=%016llx phys=%016llx flags=%016llx\n",
|
||||
(unsigned long long)testVa,
|
||||
(unsigned long long)phys,
|
||||
@@ -643,7 +643,7 @@ static void KiRunMemoryMappingSelfTest(void) {
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "MM selftest: MmPteUnmapPage failed status=%u\n", s);
|
||||
|
||||
s = MmPteQueryPageFor(MmPteQuerySelfTest, testVa, &phys, &flags);
|
||||
if (s != STATUS_NOT_FOUND)
|
||||
if (s != NTLSTATUS_NOT_FOUND)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "MM selftest: test VA still mapped after unmap status=%u\n", s);
|
||||
|
||||
MmPfnFree(frame);
|
||||
@@ -688,11 +688,11 @@ static void KiRunVadSparseSelfTest(void) {
|
||||
uint64_t queryFlags = 0;
|
||||
s = MmVadQuery(process, p, &queryBase, &querySize, &queryFlags, (MM_VAD_TYPE*)0, (uint32_t*)0);
|
||||
if (!KSUCCESS(s) || queryBase != p || querySize != PAGE_SIZE || !(queryFlags & PAGE_WRITE))
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD selftest: first query failed status=%u base=%p size=%llu flags=%016llx\n",
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD selftest: first query failed status=%u base=0x%016llX size=%llu flags=%016llx\n",
|
||||
s, queryBase, (unsigned long long)querySize, (unsigned long long)queryFlags);
|
||||
|
||||
s = MmPteQueryPageFor(MmPteQuerySelfTest, (uintptr_t)p, (PHYSICAL_ADDRESS*)0, (uint64_t*)0);
|
||||
if (s != STATUS_NOT_FOUND)
|
||||
if (s != NTLSTATUS_NOT_FOUND)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD selftest: demand-zero page was mapped before access status=%u\n", s);
|
||||
|
||||
s = MmVadEnsureResident(process, p, PAGE_SIZE, PAGE_WRITE | PAGE_USER);
|
||||
@@ -703,7 +703,7 @@ static void KiRunVadSparseSelfTest(void) {
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD selftest: sparse demand-zero materialization failed %u\n", s);
|
||||
|
||||
s = MmVadQuery(process, p + PAGE_SIZE, &queryBase, &querySize, &queryFlags, (MM_VAD_TYPE*)0, (uint32_t*)0);
|
||||
if (s != STATUS_NOT_FOUND)
|
||||
if (s != NTLSTATUS_NOT_FOUND)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD selftest: uncommitted hole queried as committed status=%u\n", s);
|
||||
|
||||
p[0] = 0x5A;
|
||||
@@ -714,7 +714,7 @@ static void KiRunVadSparseSelfTest(void) {
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD selftest: NOACCESS protect failed %u\n", s);
|
||||
|
||||
s = MmPteQueryPageFor(MmPteQuerySelfTest, (uintptr_t)p, (PHYSICAL_ADDRESS*)0, (uint64_t*)0);
|
||||
if (s != STATUS_NOT_FOUND)
|
||||
if (s != NTLSTATUS_NOT_FOUND)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD selftest: NOACCESS page still had a PTE status=%u\n", s);
|
||||
|
||||
s = MmVadQuery(process, p, &queryBase, &querySize, &queryFlags, (MM_VAD_TYPE*)0, (uint32_t*)0);
|
||||
@@ -901,10 +901,10 @@ static void KiRunVadSwapSelfTest(void) {
|
||||
void* trimmed = (void*)0;
|
||||
s = MmVadTrimOnePageForTest(process, &trimmed);
|
||||
if (!KSUCCESS(s) || trimmed != base)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD swap selftest: trim failed status=%u trimmed=%p base=%p\n", s, trimmed, base);
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD swap selftest: trim failed status=%u trimmed=0x%016llX base=0x%016llX\n", s, trimmed, base);
|
||||
|
||||
s = MmPteQueryPageFor(MmPteQuerySelfTest, (uintptr_t)base, (PHYSICAL_ADDRESS*)0, (uint64_t*)0);
|
||||
if (s != STATUS_NOT_FOUND)
|
||||
if (s != NTLSTATUS_NOT_FOUND)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "VAD swap selftest: swapped page still had a PTE status=%u\n", s);
|
||||
|
||||
s = MmVadResolveUserPageFault(process, (uintptr_t)base, 0);
|
||||
@@ -944,7 +944,7 @@ static void KiRunStringViewSelfTest(void) {
|
||||
// accept embedded NUL bytes. This must fail before reaching any filesystem.
|
||||
FILE_OBJECT* f = (FILE_OBJECT*)0;
|
||||
KSTATUS s = IoOpenFile(SysSvFromParts("system/init.exe\0junk", 20), &f);
|
||||
if (s != STATUS_INVALID_PARAMETER)
|
||||
if (s != NTLSTATUS_INVALID_PARAMETER)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "STRINGVIEW selftest: embedded-NUL path status=%u\n", s);
|
||||
|
||||
DbgPrint("STRINGVIEW selftest: sample view='%v' len=%llu\n",
|
||||
@@ -1007,7 +1007,7 @@ static void KiRunAsyncFileIoSelfTest(void) {
|
||||
|
||||
KI_FILE_ASYNC_SELFTEST_STATE st;
|
||||
memset(&st, 0, sizeof(st));
|
||||
st.Iosb.Status = STATUS_FAILURE;
|
||||
st.Iosb.Status = NTLSTATUS_FAILURE;
|
||||
|
||||
KSTATUS s = IoOpenFile(SYS_SV_LITERAL("system/init.exe"), &st.File);
|
||||
if (!KSUCCESS(s)) {
|
||||
@@ -1042,14 +1042,14 @@ static void KiRunAsyncFileIoSelfTest(void) {
|
||||
(MM_LOCKED_USER_BUFFER*)0,
|
||||
(MM_LOCKED_USER_BUFFER*)0,
|
||||
&readReq);
|
||||
if (s != STATUS_PENDING)
|
||||
if (s != NTLSTATUS_PENDING)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "FILE/ASYNC selftest: submit returned %u\n", s);
|
||||
|
||||
s = KeWaitForEvent(st.CompletionEvent, 1);
|
||||
if (s != STATUS_SUCCESS && s != STATUS_KERNEL_APC)
|
||||
if (s != NTLSTATUS_SUCCESS && s != NTLSTATUS_KERNEL_APC)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "FILE/ASYNC selftest: wait returned %u\n", s);
|
||||
|
||||
if (st.Iosb.Status == STATUS_PENDING) {
|
||||
if (st.Iosb.Status == NTLSTATUS_PENDING) {
|
||||
s = KeWaitForEvent(st.CompletionEvent, 0);
|
||||
if (!KSUCCESS(s))
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "FILE/ASYNC selftest: final event wait returned %u\n", s);
|
||||
@@ -1088,7 +1088,7 @@ static void KiRunAsyncFileIoSelfTest(void) {
|
||||
size_t got = 0;
|
||||
|
||||
memset(verify, 0, sizeof(verify));
|
||||
wiosb.Status = STATUS_FAILURE;
|
||||
wiosb.Status = NTLSTATUS_FAILURE;
|
||||
wiosb.Information = 0;
|
||||
|
||||
(void)IoDeleteFile(SYS_SV_LITERAL("asyncio.tmp"));
|
||||
@@ -1114,7 +1114,7 @@ static void KiRunAsyncFileIoSelfTest(void) {
|
||||
(MM_LOCKED_USER_BUFFER*)0,
|
||||
(MM_LOCKED_USER_BUFFER*)0,
|
||||
&writeReq);
|
||||
if (s != STATUS_PENDING)
|
||||
if (s != NTLSTATUS_PENDING)
|
||||
KePanic(KE_PANIC_CODE_SELFTEST, "FILE/ASYNC selftest: write submit returned %u\n", s);
|
||||
|
||||
s = KeWaitForEvent(wev, 1);
|
||||
|
||||
+10
-10
@@ -13,29 +13,29 @@ static void KiSemaphoreDestroy(OBJECT* obj) { (void)obj; }
|
||||
// Implements the semaphore Create operation.
|
||||
__declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) {
|
||||
if (!out || initial < 0 || max < 1 || initial > max)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
SEMAPHORE* s = (SEMAPHORE *)ObAllocateObject(ObjectTypeSemaphore, sizeof(SEMAPHORE));
|
||||
if (!s) return STATUS_NO_MEMORY;
|
||||
if (!s) return NTLSTATUS_NO_MEMORY;
|
||||
s->Header.Destroy = KiSemaphoreDestroy;
|
||||
s->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
s->Count = initial;
|
||||
s->MaxCount = max;
|
||||
LIST_INIT(&s->WaitList);
|
||||
*out = s;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Waits for semaphore.
|
||||
__declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* sem) {
|
||||
if (!sem) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!sem) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
|
||||
if (sem->Count > 0) {
|
||||
sem->Count--;
|
||||
KeReleaseSpinlock(&sem->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KePrepareBlockThread(self, &sem->Header, 0);
|
||||
@@ -47,15 +47,15 @@ __declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* sem) {
|
||||
|
||||
// Implements the try Semaphore operation.
|
||||
__declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* sem) {
|
||||
if (!sem) return STATUS_INVALID_PARAMETER;
|
||||
if (!sem) return NTLSTATUS_INVALID_PARAMETER;
|
||||
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
|
||||
if (sem->Count > 0) {
|
||||
sem->Count--;
|
||||
KeReleaseSpinlock(&sem->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KeReleaseSpinlock(&sem->Lock, flags);
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
// Signals semaphore.
|
||||
@@ -70,7 +70,7 @@ __declspec(dllexport) void KeSignalSemaphore(SEMAPHORE* sem) {
|
||||
THREAD* waiter = CONTAINING_RECORD(node, THREAD, SchedulerLink);
|
||||
KeSetThreadWaitList(waiter, (LIST_ENTRY*)0);
|
||||
KeReleaseSpinlock(&sem->Lock, flags);
|
||||
KeUnblockThreadWithStatus(waiter, STATUS_SUCCESS);
|
||||
KeUnblockThreadWithStatus(waiter, NTLSTATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
if (sem->Count < sem->MaxCount) sem->Count++;
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef struct KE_FIND_SETTING_CTX {
|
||||
static void KeFindSettingCallback(const char* section, const char* key,
|
||||
const char* value, void* userdata) {
|
||||
KE_FIND_SETTING_CTX* ctx = (KE_FIND_SETTING_CTX*)userdata;
|
||||
if (!ctx || ctx->Status != STATUS_NOT_FOUND)
|
||||
if (!ctx || ctx->Status != NTLSTATUS_NOT_FOUND)
|
||||
return;
|
||||
if (!section || !key || !value)
|
||||
return;
|
||||
@@ -36,12 +36,12 @@ static void KeFindSettingCallback(const char* section, const char* key,
|
||||
if (len + 1 > ctx->BufferSize) {
|
||||
if (ctx->BufferSize)
|
||||
ctx->Buffer[0] = '\0';
|
||||
ctx->Status = STATUS_BUFFER_TOO_SMALL;
|
||||
ctx->Status = NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(ctx->Buffer, value, len + 1);
|
||||
ctx->Status = STATUS_SUCCESS;
|
||||
ctx->Status = NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS KeGetSettingString(const char* section,
|
||||
@@ -49,7 +49,7 @@ __declspec(dllexport) KSTATUS KeGetSettingString(const char* section,
|
||||
char* buffer,
|
||||
size_t bufferSize) {
|
||||
if (!section || !*section || !key || !*key || !buffer || bufferSize == 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
buffer[0] = '\0';
|
||||
|
||||
@@ -61,14 +61,14 @@ __declspec(dllexport) KSTATUS KeGetSettingString(const char* section,
|
||||
uint64_t fileSize64 = IoGetFileSize(file);
|
||||
if (fileSize64 >= KE_SETTINGS_MAX_FILE_BYTES) {
|
||||
IoCloseFile(file);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
size_t fileSize = (size_t)fileSize64;
|
||||
char* text = (char*)MmAllocatePool(fileSize + 1);
|
||||
if (!text) {
|
||||
IoCloseFile(file);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
size_t got = 0;
|
||||
@@ -86,7 +86,7 @@ __declspec(dllexport) KSTATUS KeGetSettingString(const char* section,
|
||||
ctx.Key = key;
|
||||
ctx.Buffer = buffer;
|
||||
ctx.BufferSize = bufferSize;
|
||||
ctx.Status = STATUS_NOT_FOUND;
|
||||
ctx.Status = NTLSTATUS_NOT_FOUND;
|
||||
|
||||
IniParse(text, KeFindSettingCallback, &ctx);
|
||||
MmFreePool(text);
|
||||
|
||||
+17
-17
@@ -120,7 +120,7 @@ void KeSetApplicationProcessorTrampoline(uint64_t trampolinePhys) {
|
||||
// Builds ap Trampoline.
|
||||
static KSTATUS KiBuildApTrampoline(void) {
|
||||
if (gApTrampolinePhys)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
PHYSICAL_ADDRESS frame = gReservedApTrampolinePhys;
|
||||
if (frame) {
|
||||
@@ -155,7 +155,7 @@ static KSTATUS KiBuildApTrampoline(void) {
|
||||
if (!frame) {
|
||||
DbgPrint("SMP: no free PMM frame available below 0x%016llX for AP trampoline\n",
|
||||
(uint64_t)AP_TRAMPOLINE_MAX_PHYS);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
DbgPrint("SMP: AP trampoline frame 0x%016llX selected\n", (uint64_t)frame);
|
||||
@@ -234,7 +234,7 @@ static KSTATUS KiBuildApTrampoline(void) {
|
||||
KiEmit32(&p, physBase + gdtOff);
|
||||
|
||||
if ((uintptr_t)(p - page) >= AP_TRAMPOLINE_BOOT_OFF)
|
||||
return STATUS_DEVICE_ERROR;
|
||||
return NTLSTATUS_DEVICE_ERROR;
|
||||
|
||||
AP_BOOT_BLOCK* boot = (AP_BOOT_BLOCK*)(page + AP_TRAMPOLINE_BOOT_OFF);
|
||||
memset(boot, 0, sizeof(*boot));
|
||||
@@ -248,7 +248,7 @@ static KSTATUS KiBuildApTrampoline(void) {
|
||||
|
||||
gApTrampolinePhys = frame;
|
||||
gApBootBlock = boot;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Noreturn void KiApKernelEntry(KCPU* cpu) {
|
||||
@@ -594,7 +594,7 @@ static KSTATUS KiAllocateApStack(KCPU* cpu) {
|
||||
if (!stack) {
|
||||
DbgPrint("SMP: AP%u stack allocation failed bytes=%llu\n",
|
||||
cpu ? cpu->CpuIndex : 0xFFFFFFFFu, (uint64_t)stackBytes);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
cpu->KernelStack = stack;
|
||||
@@ -604,7 +604,7 @@ static KSTATUS KiAllocateApStack(KCPU* cpu) {
|
||||
cpu->Tss.IoMapBase = sizeof(TSS64);
|
||||
cpu->Tss.RSP0 = cpu->KernelStackTop;
|
||||
KeInitializeGdtForCpu(cpu);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the ap Stage Name operation.
|
||||
@@ -641,7 +641,7 @@ KSTATUS KeStartApplicationProcessors(void) {
|
||||
if (!KSUCCESS(st)) return st;
|
||||
|
||||
if (topo.CpuCount == 0 || topo.CpuCount > KE_MAX_CPUS)
|
||||
return STATUS_DEVICE_ERROR;
|
||||
return NTLSTATUS_DEVICE_ERROR;
|
||||
|
||||
uint32_t bspLapic = HalGetBspLapicId();
|
||||
KCPU* bsp = KeGetCurrentCpu();
|
||||
@@ -683,14 +683,14 @@ KSTATUS KeStartApplicationProcessors(void) {
|
||||
DbgPrint("SMP: discovered %u addressable CPU(s), BSP LAPIC=%u\n", gCpuCount, bspLapic);
|
||||
if (gCpuCount <= 1) {
|
||||
DbgPrint("SMP: no application processors present\n");
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if ((__readcr3() >> 32) != 0) {
|
||||
DbgPrint("SMP: disabled; bootstrap CR3 is above 4GiB (cr3=0x%016llX), AP trampoline cannot load it yet\n",
|
||||
(uint64_t)__readcr3());
|
||||
gCpuCount = 1;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DbgPrint("SMP: bootloader AP trampoline phys=0x%016llX\n",
|
||||
@@ -699,7 +699,7 @@ KSTATUS KeStartApplicationProcessors(void) {
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("SMP: disabled; AP trampoline allocation/build failed status=0x%x\n", st);
|
||||
gCpuCount = 1;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t sipiVector = (uint8_t)(gApTrampolinePhys >> 12);
|
||||
@@ -771,14 +771,14 @@ KSTATUS KeStartApplicationProcessors(void) {
|
||||
|
||||
KeBuildProcessorTopology();
|
||||
DbgPrint("SMP: kernel claimed %u APs\n", claimed);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the admit Application Processors To Scheduler operation.
|
||||
KSTATUS KeAdmitApplicationProcessorsToScheduler(void) {
|
||||
if (gCpuCount <= 1) {
|
||||
DbgPrint("SMP: no AP scheduler admission needed\n");
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t admitted = 0;
|
||||
@@ -828,7 +828,7 @@ KSTATUS KeAdmitApplicationProcessorsToScheduler(void) {
|
||||
}
|
||||
|
||||
DbgPrint("SMP: scheduler admitted %u APs\n", admitted);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define SMP_AP_WORKER_ROUNDS 64u
|
||||
@@ -933,13 +933,13 @@ static int KiWaitForWorkerCounter(volatile long* counter, long expected, const c
|
||||
KSTATUS KeRunApplicationProcessorSchedulerSelfTests(void) {
|
||||
if (gCpuCount <= 1) {
|
||||
DbgPrint("SMP scheduler selftest: SKIP, no APs\n");
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DbgPrint("SMP scheduler selftest: begin AP-affine workers\n");
|
||||
|
||||
SMP_AP_WORK_TEST* test = (SMP_AP_WORK_TEST*)MmAllocatePool(sizeof(SMP_AP_WORK_TEST));
|
||||
if (!test) return STATUS_NO_MEMORY;
|
||||
if (!test) return NTLSTATUS_NO_MEMORY;
|
||||
memset(test, 0, sizeof(*test));
|
||||
test->Magic = SMP_AP_TEST_MAGIC;
|
||||
|
||||
@@ -982,7 +982,7 @@ KSTATUS KeRunApplicationProcessorSchedulerSelfTests(void) {
|
||||
if (workerCount == 0) {
|
||||
MmFreePool(test);
|
||||
DbgPrint("SMP scheduler selftest: SKIP, no online AP workers\n");
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!KiWaitForWorkerCounter(&test->ReadyCount, (long)workerCount, "AP worker ready")) {
|
||||
@@ -1041,5 +1041,5 @@ KSTATUS KeRunApplicationProcessorSchedulerSelfTests(void) {
|
||||
DbgPrint("SMP scheduler selftest: PASS workers=%u rounds=%u\n",
|
||||
workerCount, SMP_AP_WORKER_ROUNDS);
|
||||
MmFreePool(test);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
+140
-39
@@ -136,9 +136,25 @@ KeSyscallEntry PROC
|
||||
call KiExitTrapFrame
|
||||
add rsp, 32
|
||||
|
||||
; Restore the editable trap-frame register image. Normal syscalls only
|
||||
; require RAX, but exception continuation may redirect the IRET to an
|
||||
; arbitrary saved user context that needs the full GPR set.
|
||||
mov rax, [rbx + TF_Rax]
|
||||
add rsp, KTRAP_FRAME_SIZE
|
||||
pop rbx
|
||||
mov rcx, [rbx + TF_Rcx]
|
||||
mov rdx, [rbx + TF_Rdx]
|
||||
mov rbp, [rbx + TF_Rbp]
|
||||
mov rsi, [rbx + TF_Rsi]
|
||||
mov rdi, [rbx + TF_Rdi]
|
||||
mov r8, [rbx + TF_R8]
|
||||
mov r9, [rbx + TF_R9]
|
||||
mov r10, [rbx + TF_R10]
|
||||
mov r11, [rbx + TF_R11]
|
||||
mov r12, [rbx + TF_R12]
|
||||
mov r13, [rbx + TF_R13]
|
||||
mov r14, [rbx + TF_R14]
|
||||
mov r15, [rbx + TF_R15]
|
||||
lea rsp, [rbx + KTRAP_FRAME_SIZE + 8]
|
||||
mov rbx, [rbx + TF_Rbx]
|
||||
swapgs ; GS_BASE: KCPU -> user TEB before returning to ring 3
|
||||
iretq
|
||||
KeSyscallEntry ENDP
|
||||
@@ -152,7 +168,7 @@ KeSyscallEntry ENDP
|
||||
; also shows which register held the null target.
|
||||
;
|
||||
; KeFaultDispatchFrame signature (MS x64):
|
||||
; KSTATUS KeFaultDispatchFrame(const KFAULT_FRAME* frame) ; rcx
|
||||
; KSTATUS KeFaultDispatchFrame(KFAULT_FRAME* frame) ; rcx
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
KFAULT_MAGIC EQU 3146544C5541464Bh ; "KFAULTF1" little-ish
|
||||
@@ -185,6 +201,118 @@ KF_R15 EQU 0B8h
|
||||
|
||||
FAULT_CALL_SHADOW EQU 28h
|
||||
|
||||
FAULT_RESUME_NOERR MACRO
|
||||
LOCAL noerr_skip_user_slots, noerr_no_swapgs, noerr_unhandled_halt
|
||||
test eax, eax
|
||||
jnz noerr_unhandled_halt
|
||||
|
||||
mov rdx, rbx
|
||||
mov rax, [rdx + KF_Rip]
|
||||
mov [rdx + KFAULT_SIZE + 16], rax
|
||||
mov rax, [rdx + KF_Cs]
|
||||
mov [rdx + KFAULT_SIZE + 24], rax
|
||||
mov rax, [rdx + KF_Rflags]
|
||||
mov [rdx + KFAULT_SIZE + 32], rax
|
||||
|
||||
mov rax, [rdx + KF_Cs]
|
||||
test rax, 3
|
||||
jz noerr_skip_user_slots
|
||||
mov rax, [rdx + KF_Rsp]
|
||||
mov [rdx + KFAULT_SIZE + 40], rax
|
||||
mov rax, [rdx + KF_Ss]
|
||||
mov [rdx + KFAULT_SIZE + 48], rax
|
||||
|
||||
noerr_skip_user_slots:
|
||||
mov rcx, [rdx + KF_Rcx]
|
||||
mov r8, [rdx + KF_R8]
|
||||
mov r9, [rdx + KF_R9]
|
||||
mov rsi, [rdx + KF_Rsi]
|
||||
mov rdi, [rdx + KF_Rdi]
|
||||
mov rbp, [rdx + KF_Rbp]
|
||||
mov r12, [rdx + KF_R12]
|
||||
mov r13, [rdx + KF_R13]
|
||||
mov r14, [rdx + KF_R14]
|
||||
mov r15, [rdx + KF_R15]
|
||||
lea rsp, [rdx + KFAULT_SIZE + 16]
|
||||
mov rax, [rdx + KF_Rax]
|
||||
mov r11, [rdx + KF_R11]
|
||||
mov r10, [rdx + KF_Cs]
|
||||
test r10, 3
|
||||
jz noerr_no_swapgs
|
||||
mov r10, [rdx + KF_R10]
|
||||
mov rbx, [rdx + KF_Rbx]
|
||||
mov rdx, [rdx + KF_Rdx]
|
||||
swapgs
|
||||
iretq
|
||||
noerr_no_swapgs:
|
||||
mov r10, [rdx + KF_R10]
|
||||
mov rbx, [rdx + KF_Rbx]
|
||||
mov rdx, [rdx + KF_Rdx]
|
||||
iretq
|
||||
|
||||
noerr_unhandled_halt:
|
||||
cli
|
||||
@@:
|
||||
hlt
|
||||
jmp @B
|
||||
ENDM
|
||||
|
||||
FAULT_RESUME_ERR MACRO
|
||||
LOCAL err_skip_user_slots, err_no_swapgs, err_unhandled_halt
|
||||
test eax, eax
|
||||
jnz err_unhandled_halt
|
||||
|
||||
mov rdx, rbx
|
||||
mov rax, [rdx + KF_Rip]
|
||||
mov [rdx + KFAULT_SIZE + 24], rax
|
||||
mov rax, [rdx + KF_Cs]
|
||||
mov [rdx + KFAULT_SIZE + 32], rax
|
||||
mov rax, [rdx + KF_Rflags]
|
||||
mov [rdx + KFAULT_SIZE + 40], rax
|
||||
|
||||
mov rax, [rdx + KF_Cs]
|
||||
test rax, 3
|
||||
jz err_skip_user_slots
|
||||
mov rax, [rdx + KF_Rsp]
|
||||
mov [rdx + KFAULT_SIZE + 48], rax
|
||||
mov rax, [rdx + KF_Ss]
|
||||
mov [rdx + KFAULT_SIZE + 56], rax
|
||||
|
||||
err_skip_user_slots:
|
||||
mov rcx, [rdx + KF_Rcx]
|
||||
mov r8, [rdx + KF_R8]
|
||||
mov r9, [rdx + KF_R9]
|
||||
mov rsi, [rdx + KF_Rsi]
|
||||
mov rdi, [rdx + KF_Rdi]
|
||||
mov rbp, [rdx + KF_Rbp]
|
||||
mov r12, [rdx + KF_R12]
|
||||
mov r13, [rdx + KF_R13]
|
||||
mov r14, [rdx + KF_R14]
|
||||
mov r15, [rdx + KF_R15]
|
||||
lea rsp, [rdx + KFAULT_SIZE + 24]
|
||||
mov rax, [rdx + KF_Rax]
|
||||
mov r11, [rdx + KF_R11]
|
||||
mov r10, [rdx + KF_Cs]
|
||||
test r10, 3
|
||||
jz err_no_swapgs
|
||||
mov r10, [rdx + KF_R10]
|
||||
mov rbx, [rdx + KF_Rbx]
|
||||
mov rdx, [rdx + KF_Rdx]
|
||||
swapgs
|
||||
iretq
|
||||
err_no_swapgs:
|
||||
mov r10, [rdx + KF_R10]
|
||||
mov rbx, [rdx + KF_Rbx]
|
||||
mov rdx, [rdx + KF_Rdx]
|
||||
iretq
|
||||
|
||||
err_unhandled_halt:
|
||||
cli
|
||||
@@:
|
||||
hlt
|
||||
jmp @B
|
||||
ENDM
|
||||
|
||||
; ---------------------------------------------------------
|
||||
; Divide Error (#0) - NO error code pushed by CPU
|
||||
; User exception frame: [E]=RIP [E+8]=CS [E+16]=RFLAGS [E+24]=RSP [E+32]=SS
|
||||
@@ -246,8 +374,10 @@ de_kernel_frame:
|
||||
de_call:
|
||||
and rsp, -16
|
||||
sub rsp, FAULT_CALL_SHADOW
|
||||
mov rbx, rax
|
||||
mov rcx, rax
|
||||
call KeFaultDispatchFrame
|
||||
FAULT_RESUME_NOERR
|
||||
KeFaultDE ENDP
|
||||
|
||||
; ---------------------------------------------------------
|
||||
@@ -312,8 +442,10 @@ gp_kernel_frame:
|
||||
gp_call:
|
||||
and rsp, -16
|
||||
sub rsp, FAULT_CALL_SHADOW
|
||||
mov rbx, rax
|
||||
mov rcx, rax
|
||||
call KeFaultDispatchFrame
|
||||
FAULT_RESUME_ERR
|
||||
KeFaultGP ENDP
|
||||
|
||||
; ---------------------------------------------------------
|
||||
@@ -382,42 +514,7 @@ pf_call:
|
||||
mov rbx, rax ; Keep the KFAULT_FRAME pointer across C.
|
||||
mov rcx, rax
|
||||
call KeFaultDispatchFrame
|
||||
test eax, eax
|
||||
jnz pf_unhandled_return
|
||||
|
||||
mov rdx, rbx ; rdx = KFAULT_FRAME*.
|
||||
mov rcx, [rdx + KF_Rcx]
|
||||
mov r8, [rdx + KF_R8]
|
||||
mov r9, [rdx + KF_R9]
|
||||
mov rsi, [rdx + KF_Rsi]
|
||||
mov rdi, [rdx + KF_Rdi]
|
||||
mov rbp, [rdx + KF_Rbp]
|
||||
mov r12, [rdx + KF_R12]
|
||||
mov r13, [rdx + KF_R13]
|
||||
mov r14, [rdx + KF_R14]
|
||||
mov r15, [rdx + KF_R15]
|
||||
mov rbx, [rdx + KF_Rbx]
|
||||
|
||||
lea rsp, [rdx + KFAULT_SIZE + 24] ; Skip saved RAX/R11 and the CPU error code.
|
||||
mov rax, [rdx + KF_Rax]
|
||||
mov r11, [rdx + KF_R11]
|
||||
mov r10, [rdx + KF_Cs]
|
||||
test r10, 3
|
||||
jz pf_resume_no_swapgs
|
||||
mov r10, [rdx + KF_R10]
|
||||
mov rdx, [rdx + KF_Rdx]
|
||||
swapgs
|
||||
iretq
|
||||
pf_resume_no_swapgs:
|
||||
mov r10, [rdx + KF_R10]
|
||||
mov rdx, [rdx + KF_Rdx]
|
||||
iretq
|
||||
|
||||
pf_unhandled_return:
|
||||
cli
|
||||
pf_unhandled_halt:
|
||||
hlt
|
||||
jmp pf_unhandled_halt
|
||||
FAULT_RESUME_ERR
|
||||
KeFaultPF ENDP
|
||||
|
||||
; ---------------------------------------------------------
|
||||
@@ -484,8 +581,10 @@ noerr_kernel_frame:
|
||||
noerr_call:
|
||||
and rsp, -16
|
||||
sub rsp, FAULT_CALL_SHADOW
|
||||
mov rbx, rax
|
||||
mov rcx, rax
|
||||
call KeFaultDispatchFrame
|
||||
FAULT_RESUME_NOERR
|
||||
StubName ENDP
|
||||
ENDM
|
||||
|
||||
@@ -549,8 +648,10 @@ err_kernel_frame:
|
||||
err_call:
|
||||
and rsp, -16
|
||||
sub rsp, FAULT_CALL_SHADOW
|
||||
mov rbx, rax
|
||||
mov rcx, rax
|
||||
call KeFaultDispatchFrame
|
||||
FAULT_RESUME_ERR
|
||||
StubName ENDP
|
||||
ENDM
|
||||
|
||||
|
||||
+706
-466
File diff suppressed because it is too large.
Load diff
@@ -61,10 +61,10 @@ KSTATUS KeInitializeSystemRootVolume(void) {
|
||||
gSystemRootDrive = drive;
|
||||
gSystemRootReady = true;
|
||||
DbgPrint("System root: drive=%u\n", drive);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Returns whether the system root volume has been selected.
|
||||
@@ -87,11 +87,11 @@ bool KeBuildSystemRootPath(const char* relative, char* out, size_t outSize) {
|
||||
// Opens a file rooted at the selected system volume.
|
||||
KSTATUS KeOpenSystemRootFile(const char* relative, FILE_OBJECT** out) {
|
||||
if (!out)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*out = NULL;
|
||||
|
||||
char path[1024];
|
||||
if (!KeBuildSystemRootPath(relative, path, sizeof(path)))
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
return IoOpenFile(SysSvFromCstr(path), out);
|
||||
}
|
||||
+41
-33
@@ -41,7 +41,7 @@ static void KiThreadDestroy(OBJECT* obj) {
|
||||
// A wait that uses auxiliary stack wait blocks must be removed before the
|
||||
// kernel stack is released. A terminated thread may never return to the
|
||||
// wait syscall to run normal cleanup.
|
||||
KeRundownThreadWait(thread, STATUS_ALERTED);
|
||||
KeRundownThreadWait(thread, NTLSTATUS_ALERTED);
|
||||
|
||||
KiRundownApcState(thread);
|
||||
|
||||
@@ -94,11 +94,11 @@ static void KiThreadDestroy(OBJECT* obj) {
|
||||
|
||||
__declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg,
|
||||
THREAD_PRIORITY priority, THREAD** out) {
|
||||
if (!owner || !out) return STATUS_INVALID_PARAMETER;
|
||||
if (priority >= PriorityCount) return STATUS_INVALID_PARAMETER;
|
||||
if (!owner || !out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (priority >= PriorityCount) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
THREAD* thread = (THREAD *)ObAllocateObject(ObjectTypeThread, sizeof(THREAD));
|
||||
if (!thread) return STATUS_NO_MEMORY;
|
||||
if (!thread) return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
thread->Header.Destroy = KiThreadDestroy;
|
||||
thread->ThreadId = _InterlockedExchangeAdd((volatile long *)&gNextThreadId, 1);
|
||||
@@ -118,19 +118,23 @@ __declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, ui
|
||||
LIST_INIT(&thread->ProcessLink);
|
||||
LIST_INIT(&thread->SchedulerLink);
|
||||
thread->WaitObject = (OBJECT *)0;
|
||||
thread->WaitStatus = STATUS_SUCCESS;
|
||||
thread->WaitStatus = NTLSTATUS_SUCCESS;
|
||||
thread->WaitListHead = (LIST_ENTRY*)0;
|
||||
thread->AlertableWait = 0;
|
||||
thread->SleepUntilTick = 0;
|
||||
thread->TimeoutStatus = STATUS_SUCCESS;
|
||||
thread->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
thread->SwitchLockCookie = 0x202ULL;
|
||||
KiInitializeApcState(thread);
|
||||
thread->TrapFrame = (KTRAP_FRAME*)0;
|
||||
thread->UserExceptionDepth = 0;
|
||||
thread->UserExceptionNoncontinuableMask = 0;
|
||||
thread->UserExceptionFrameUserAddress = 0;
|
||||
memset(thread->UserExceptionExitStatus, 0, sizeof(thread->UserExceptionExitStatus));
|
||||
|
||||
void* kstack = MmAllocatePoolTag(KSTACK_SIZE, MM_POOL_TAG('k', 's', 't', 'k'));
|
||||
if (!kstack) {
|
||||
ObDereferenceObject(&thread->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
memset(kstack, 0, KSTACK_SIZE);
|
||||
thread->KernelStackBase = kstack;
|
||||
@@ -148,7 +152,7 @@ __declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, ui
|
||||
MmFreePool(kstack);
|
||||
thread->KernelStackBase = (void*)0;
|
||||
ObDereferenceObject(&thread->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
thread->UserStackBase = ustack;
|
||||
// Ring-3 starts at the image entry via IRET, not CALL. The MS x64 ABI
|
||||
@@ -172,7 +176,7 @@ __declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, ui
|
||||
MmFreePool(kstack);
|
||||
thread->KernelStackBase = (void*)0;
|
||||
ObDereferenceObject(&thread->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
memset(teb, 0, sizeof(SYS_TEB));
|
||||
teb->Peb = (SYS_PEB*)owner->UserPebBase;
|
||||
@@ -241,7 +245,7 @@ __declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, ui
|
||||
*out = thread;
|
||||
|
||||
KeReadyThread(thread);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the exit Thread operation.
|
||||
@@ -284,11 +288,11 @@ static KSTATUS KiCreateKernelThreadWithAffinity(uintptr_t fn, uintptr_t arg,
|
||||
THREAD* currentThread = KeGetCurrentThread();
|
||||
owner = currentThread ? currentThread->Owner : (PROCESS*)0;
|
||||
}
|
||||
if (!owner) return STATUS_INVALID_PARAMETER;
|
||||
if (priority >= PriorityCount) return STATUS_INVALID_PARAMETER;
|
||||
if (!owner) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (priority >= PriorityCount) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
THREAD* thread = (THREAD*)ObAllocateObject(ObjectTypeThread, sizeof(THREAD));
|
||||
if (!thread) return STATUS_NO_MEMORY;
|
||||
if (!thread) return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
thread->Header.Destroy = KiThreadDestroy;
|
||||
thread->ThreadId = _InterlockedExchangeAdd((volatile long*)&gNextThreadId, 1);
|
||||
@@ -308,14 +312,18 @@ static KSTATUS KiCreateKernelThreadWithAffinity(uintptr_t fn, uintptr_t arg,
|
||||
LIST_INIT(&thread->ProcessLink);
|
||||
LIST_INIT(&thread->SchedulerLink);
|
||||
thread->WaitObject = (OBJECT*)0;
|
||||
thread->WaitStatus = STATUS_SUCCESS;
|
||||
thread->WaitStatus = NTLSTATUS_SUCCESS;
|
||||
thread->WaitListHead = (LIST_ENTRY*)0;
|
||||
thread->AlertableWait = 0;
|
||||
thread->SleepUntilTick = 0;
|
||||
thread->TimeoutStatus = STATUS_SUCCESS;
|
||||
thread->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
thread->SwitchLockCookie = 0x202ULL;
|
||||
KiInitializeApcState(thread);
|
||||
thread->TrapFrame = (KTRAP_FRAME*)0;
|
||||
thread->UserExceptionDepth = 0;
|
||||
thread->UserExceptionNoncontinuableMask = 0;
|
||||
thread->UserExceptionFrameUserAddress = 0;
|
||||
memset(thread->UserExceptionExitStatus, 0, sizeof(thread->UserExceptionExitStatus));
|
||||
thread->UserStackBase = (void*)0; // no user stack
|
||||
thread->Teb = (void*)0; // no TEB; GS_BASE will be 0 in kernel ctx
|
||||
thread->TebSize = 0;
|
||||
@@ -323,7 +331,7 @@ static KSTATUS KiCreateKernelThreadWithAffinity(uintptr_t fn, uintptr_t arg,
|
||||
void* kstack = MmAllocatePoolTag(KSTACK_SIZE, MM_POOL_TAG('k', 's', 't', 'k'));
|
||||
if (!kstack) {
|
||||
ObDereferenceObject(&thread->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
memset(kstack, 0, KSTACK_SIZE);
|
||||
thread->KernelStackBase = kstack;
|
||||
@@ -363,7 +371,7 @@ static KSTATUS KiCreateKernelThreadWithAffinity(uintptr_t fn, uintptr_t arg,
|
||||
|
||||
KeInitThreadFpuContext(thread);
|
||||
KeReadyThread(thread);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
||||
@@ -388,7 +396,7 @@ void KePrepareBlockThread(THREAD* thread, OBJECT* waitObject, uint8_t alertable)
|
||||
KiSchedulerMarkThreadWaiting(thread);
|
||||
|
||||
thread->WaitObject = waitObject;
|
||||
thread->WaitStatus = STATUS_PENDING;
|
||||
thread->WaitStatus = NTLSTATUS_PENDING;
|
||||
thread->WaitListHead = (LIST_ENTRY*)0;
|
||||
thread->AlertableWait = alertable ? 1 : 0;
|
||||
thread->WaitRundownRoutine = (KE_WAIT_RUNDOWN_ROUTINE)0;
|
||||
@@ -436,13 +444,13 @@ static void KiFinishWait(THREAD* thread, KSTATUS status) {
|
||||
thread->WaitListHead = (LIST_ENTRY*)0;
|
||||
thread->AlertableWait = 0;
|
||||
thread->SleepUntilTick = 0;
|
||||
thread->TimeoutStatus = STATUS_SUCCESS;
|
||||
thread->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the commit Block Thread operation.
|
||||
KSTATUS KeCommitBlockThread(THREAD* thread, uint8_t alertable) {
|
||||
KeAssertIrql(PASSIVE_LEVEL);
|
||||
if (!thread) return STATUS_INVALID_PARAMETER;
|
||||
if (!thread) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
if (alertable)
|
||||
thread->AlertableWait = 1;
|
||||
@@ -455,7 +463,7 @@ KSTATUS KeCommitBlockThread(THREAD* thread, uint8_t alertable) {
|
||||
KSTATUS status = thread->WaitStatus;
|
||||
thread->AlertableWait = 0;
|
||||
thread->SleepUntilTick = 0;
|
||||
thread->TimeoutStatus = STATUS_SUCCESS;
|
||||
thread->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -464,21 +472,21 @@ KSTATUS KeCommitBlockThread(THREAD* thread, uint8_t alertable) {
|
||||
if (alertable && thread->UserApcPending && thread->UserApcDispatcher) {
|
||||
if (thread->WaitListHead)
|
||||
ListRemove(&thread->SchedulerLink);
|
||||
KiFinishWait(thread, STATUS_USER_APC);
|
||||
KiFinishWait(thread, NTLSTATUS_USER_APC);
|
||||
thread->State = ThreadRunning;
|
||||
return STATUS_USER_APC;
|
||||
return NTLSTATUS_USER_APC;
|
||||
}
|
||||
|
||||
KiSchedulerNoteVoluntaryBlock(thread);
|
||||
KeYield();
|
||||
|
||||
// Kernel APCs are delivered before an alertable wait returns
|
||||
// STATUS_KERNEL_APC to its caller.
|
||||
// NTLSTATUS_KERNEL_APC to its caller.
|
||||
KiDeliverKernelApcs();
|
||||
|
||||
thread->AlertableWait = 0;
|
||||
thread->SleepUntilTick = 0;
|
||||
thread->TimeoutStatus = STATUS_SUCCESS;
|
||||
thread->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
return thread->WaitStatus;
|
||||
}
|
||||
|
||||
@@ -517,7 +525,7 @@ static int KiRemoveThreadFromObjectWaitListLocked(THREAD* thread, LIST_ENTRY* wa
|
||||
ListRemove(&thread->SchedulerLink);
|
||||
thread->WaitListHead = (LIST_ENTRY*)0;
|
||||
thread->SleepUntilTick = 0;
|
||||
thread->TimeoutStatus = STATUS_SUCCESS;
|
||||
thread->TimeoutStatus = NTLSTATUS_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -582,36 +590,36 @@ void KeAbortThreadWait(THREAD* thread, KSTATUS status) {
|
||||
|
||||
// Implements the unblock Thread operation.
|
||||
void KeUnblockThread(THREAD* thread) {
|
||||
KeUnblockThreadWithStatus(thread, STATUS_SUCCESS);
|
||||
KeUnblockThreadWithStatus(thread, NTLSTATUS_SUCCESS);
|
||||
}
|
||||
|
||||
// Implements the alert Thread With Status operation.
|
||||
static KSTATUS KiAlertThreadWithStatus(THREAD* thread, KSTATUS status) {
|
||||
if (!thread) return STATUS_INVALID_PARAMETER;
|
||||
if (!thread) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
if (thread->State != ThreadWaiting || !thread->AlertableWait)
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_PENDING;
|
||||
|
||||
if (thread->WaitListHead)
|
||||
ListRemove(&thread->SchedulerLink);
|
||||
|
||||
KeUnblockThreadWithStatus(thread, status);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the alert Thread operation.
|
||||
KSTATUS KeAlertThread(THREAD* thread) {
|
||||
return KiAlertThreadWithStatus(thread, STATUS_ALERTED);
|
||||
return KiAlertThreadWithStatus(thread, NTLSTATUS_ALERTED);
|
||||
}
|
||||
|
||||
// Implements the wake Thread For Kernel Apc operation.
|
||||
void KiWakeThreadForKernelApc(THREAD* thread) {
|
||||
(void)KiAlertThreadWithStatus(thread, STATUS_KERNEL_APC);
|
||||
(void)KiAlertThreadWithStatus(thread, NTLSTATUS_KERNEL_APC);
|
||||
}
|
||||
|
||||
// Implements the wake Thread For User Apc operation.
|
||||
void KiWakeThreadForUserApc(THREAD* thread) {
|
||||
(void)KiAlertThreadWithStatus(thread, STATUS_USER_APC);
|
||||
(void)KiAlertThreadWithStatus(thread, NTLSTATUS_USER_APC);
|
||||
}
|
||||
|
||||
void KeInitThreadFpuContext(THREAD* thread)
|
||||
|
||||
@@ -335,7 +335,7 @@ void KeTimeInitialize(const BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
} else {
|
||||
HAL_RTC_TIME rtc;
|
||||
memset(&rtc, 0, sizeof(rtc));
|
||||
if (hal && hal->Rtc.QueryTime && hal->Rtc.QueryTime(&rtc) == STATUS_SUCCESS &&
|
||||
if (hal && hal->Rtc.QueryTime && hal->Rtc.QueryTime(&rtc) == NTLSTATUS_SUCCESS &&
|
||||
(rtc.Flags & HAL_RTC_TIME_FLAG_VALID) &&
|
||||
KiValidCalendar(rtc.Year, rtc.Month, rtc.Day, rtc.Hour, rtc.Minute,
|
||||
rtc.Second, rtc.Nanosecond)) {
|
||||
@@ -360,7 +360,7 @@ void KeTimeInitialize(const BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
KiRebaseUtcFromSource();
|
||||
|
||||
SYS_SYSTEM_TIME now;
|
||||
if (KeQuerySystemTime(&now) == STATUS_SUCCESS) {
|
||||
if (KeQuerySystemTime(&now) == NTLSTATUS_SUCCESS) {
|
||||
DbgPrint("time: initialized %04u-%02u-%02u %02u:%02u:%02u.%03u flags=0x%x tz=%d hw=%s epoch=%llu\n",
|
||||
now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second,
|
||||
now.Millisecond, now.Flags, now.TimeZoneMinutes,
|
||||
@@ -466,7 +466,7 @@ KSTATUS KeTimeReloadSettings(void) {
|
||||
KiRebaseUtcFromSource();
|
||||
|
||||
SYS_SYSTEM_TIME now;
|
||||
if (KeQuerySystemTime(&now) == STATUS_SUCCESS) {
|
||||
if (KeQuerySystemTime(&now) == NTLSTATUS_SUCCESS) {
|
||||
DbgPrint("time: settings timezone=%d dst=%s hw=%s now=%04u-%02u-%02u %02u:%02u:%02u flags=0x%x epoch=%llu\n",
|
||||
now.TimeZoneMinutes,
|
||||
(now.Flags & SYS_TIME_FLAG_DAYLIGHT) ? "on" : "off",
|
||||
@@ -474,12 +474,12 @@ KSTATUS KeTimeReloadSettings(void) {
|
||||
now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second,
|
||||
now.Flags, now.EpochSeconds);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns system Time.
|
||||
__declspec(dllexport) KSTATUS KeQuerySystemTime(SYS_SYSTEM_TIME* outTime) {
|
||||
if (!outTime) return STATUS_INVALID_PARAMETER;
|
||||
if (!outTime) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t nowTick = (gTimeHal && gTimeHal->Timer.QueryTicks)
|
||||
? gTimeHal->Timer.QueryTicks()
|
||||
@@ -516,13 +516,13 @@ __declspec(dllexport) KSTATUS KeQuerySystemTime(SYS_SYSTEM_TIME* outTime) {
|
||||
t.TickMicroseconds = nowTick;
|
||||
|
||||
*outTime = t;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns unix Time Seconds.
|
||||
__declspec(dllexport) uint64_t KeQueryUnixTimeSeconds(void) {
|
||||
SYS_SYSTEM_TIME t;
|
||||
if (KeQuerySystemTime(&t) != STATUS_SUCCESS)
|
||||
if (KeQuerySystemTime(&t) != NTLSTATUS_SUCCESS)
|
||||
return 0;
|
||||
return t.EpochSeconds;
|
||||
}
|
||||
@@ -80,14 +80,14 @@ static void KiTimerDestroy(OBJECT* obj) {
|
||||
// Creates an unset waitable timer object.
|
||||
KSTATUS KeTimerCreate(KTIMER** out) {
|
||||
if (!out)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*out = (KTIMER*)0;
|
||||
|
||||
KiTimerEnsureInitialized();
|
||||
|
||||
KTIMER* timer = (KTIMER*)ObAllocateObject(ObjectTypeTimer, sizeof(KTIMER));
|
||||
if (!timer)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
timer->Header.Destroy = KiTimerDestroy;
|
||||
LIST_INIT(&timer->Link);
|
||||
@@ -99,13 +99,13 @@ KSTATUS KeTimerCreate(KTIMER** out) {
|
||||
}
|
||||
|
||||
*out = timer;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Arms or rearms a timer with a relative due time and optional period.
|
||||
KSTATUS KeTimerSet(KTIMER* timer, uint64_t dueTimeMilliseconds, uint64_t periodMilliseconds) {
|
||||
if (!timer || !timer->Event)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KiTimerEnsureInitialized();
|
||||
|
||||
@@ -147,13 +147,13 @@ KSTATUS KeTimerSet(KTIMER* timer, uint64_t dueTimeMilliseconds, uint64_t periodM
|
||||
if (signalNow)
|
||||
KeSignalEvent(event);
|
||||
ObDereferenceObject(&event->Header);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Cancels a timer and clears any retained signal.
|
||||
KSTATUS KeTimerCancel(KTIMER* timer) {
|
||||
if (!timer || !timer->Event)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KiTimerEnsureInitialized();
|
||||
|
||||
@@ -164,7 +164,7 @@ KSTATUS KeTimerCancel(KTIMER* timer) {
|
||||
if (hadListReference)
|
||||
ObDereferenceObject(&timer->Header);
|
||||
KeClearEvent(timer->Event);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns the event that backs timer waits.
|
||||
|
||||
@@ -120,16 +120,16 @@ void KiValidateSyscallTrapFrame(uint64_t nr, uint64_t a0, uint64_t a1,
|
||||
|
||||
// Returns current Trap Frame.
|
||||
KSTATUS KeQueryCurrentTrapFrame(SYS_TRAP_FRAME_INFO_K* out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KTRAP_FRAME* f = KeGetCurrentTrapFrame();
|
||||
if (!f || f->Magic != KTRAP_FRAME_MAGIC)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
uint32_t size = out->Size;
|
||||
if (size < sizeof(SYS_TRAP_FRAME_INFO_K)) {
|
||||
out->Size = sizeof(SYS_TRAP_FRAME_INFO_K);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
@@ -149,5 +149,5 @@ KSTATUS KeQueryCurrentTrapFrame(SYS_TRAP_FRAME_INFO_K* out) {
|
||||
out->R9 = f->R9;
|
||||
out->R10 = f->R10;
|
||||
out->R11 = f->R11;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
@@ -86,11 +86,11 @@ bool KeQueueWorkItem(KWORK_ITEM* item) {
|
||||
KSTATUS KeStartWorkQueue(void) {
|
||||
long state = _InterlockedCompareExchange(&gWorkQueueStartState, 1, 0);
|
||||
if (state == 2)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
if (state == 1) {
|
||||
while (_InterlockedCompareExchange(&gWorkQueueStartState, 2, 2) == 1)
|
||||
KeYield();
|
||||
return KeIsWorkQueueStarted() ? STATUS_SUCCESS : STATUS_FAILURE;
|
||||
return KeIsWorkQueueStarted() ? NTLSTATUS_SUCCESS : NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
LIST_INIT(&gWorkQueueList);
|
||||
|
||||
+6
-6
@@ -242,7 +242,7 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
FILE_OBJECT* f;
|
||||
|
||||
s = KeInitializeSystemRootVolume();
|
||||
if (s != STATUS_SUCCESS) {
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "KiInitializeDrivers: Failed to find system root volume (status %d)\n", s);
|
||||
}
|
||||
|
||||
@@ -252,12 +252,12 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
root[2] = '/';
|
||||
root[3] = '\0';
|
||||
s = IoSetCwd(SysSvFromCstr(root));
|
||||
if (s != STATUS_SUCCESS) {
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "KiInitializeDrivers: Failed to set system CWD to %s (status %d)\n", root, s);
|
||||
}
|
||||
|
||||
s = KeOpenSystemRootFile("drivers\\drivers.ini", &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "KiInitializeDrivers: Failed to open drivers.ini on system root (status %d)\n", s);
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
}
|
||||
|
||||
s = IoOpenFile(SysSvFromCstr(path), &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
DbgPrint("KiInitializeDrivers: Failed to open runtime driver: %s (%s)\n", runtimeKeys[i], path);
|
||||
continue;
|
||||
}
|
||||
@@ -356,7 +356,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
|
||||
// Kernel-launched user images are rooted at the selected system volume.
|
||||
s = KeOpenSystemRootFile(filePath, &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
DbgPrint("Failed to load system file: \"%s\" (status %d)!\n", filePath, s);
|
||||
return 0;
|
||||
}
|
||||
@@ -469,7 +469,7 @@ void SystemInitThread(void* arg) {
|
||||
|
||||
if (args->bootInfo->Debug & (KE_DEBUG_CONSOLE | KE_DEBUG_FILE_LOG)) {
|
||||
char logPath[1024];
|
||||
KSTATUS logStatus = STATUS_NOT_FOUND;
|
||||
KSTATUS logStatus = NTLSTATUS_NOT_FOUND;
|
||||
if (KeBuildSystemRootPath("kernel.log", logPath, sizeof(logPath))) {
|
||||
logStatus = KeFlushDebugLogToFile(SysSvFromCstr(logPath));
|
||||
if (!KSUCCESS(logStatus))
|
||||
|
||||
+54
-54
@@ -97,7 +97,7 @@ static size_t KiAlignPeSize(size_t value) {
|
||||
|
||||
// Implements the compute Required Image Size operation.
|
||||
static KSTATUS KiComputeRequiredImageSize(const PE_HEADER* pe, size_t fileSize, size_t* outSize) {
|
||||
if (!pe || !outSize) return STATUS_INVALID_PARAMETER;
|
||||
if (!pe || !outSize) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
const OPT_HEADER64* opt = &pe->OptionalHeader;
|
||||
size_t required = KiAlignPeSize(opt->SizeOfImage);
|
||||
@@ -113,19 +113,19 @@ static KSTATUS KiComputeRequiredImageSize(const PE_HEADER* pe, size_t fileSize,
|
||||
if (raw > span) span = raw;
|
||||
if (!span) continue;
|
||||
|
||||
if (va > (size_t)-1 - span) return STATUS_NO_MEMORY;
|
||||
if (va > (size_t)-1 - span) return NTLSTATUS_NO_MEMORY;
|
||||
size_t end = KiAlignPeSize(va + span);
|
||||
if (end > required) required = end;
|
||||
|
||||
if (raw) {
|
||||
size_t rawBase = (size_t)sec[i].PointerToRawData;
|
||||
if (rawBase > fileSize || raw > fileSize - rawBase) return STATUS_FAILURE;
|
||||
if (rawBase > fileSize || raw > fileSize - rawBase) return NTLSTATUS_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!required) return STATUS_FAILURE;
|
||||
if (!required) return NTLSTATUS_FAILURE;
|
||||
*outSize = required;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@@ -178,7 +178,7 @@ static uint32_t gModuleCount = 0;
|
||||
|
||||
// Ensures a user image page is privately writable before the kernel patches it.
|
||||
static KSTATUS KiEnsureUserImageWrite(PROCESS* process, bool user, uintptr_t address, size_t size) {
|
||||
if (!user) return STATUS_SUCCESS;
|
||||
if (!user) return NTLSTATUS_SUCCESS;
|
||||
return MmVadMakeImageRangePrivate(process, (void*)address, size);
|
||||
}
|
||||
|
||||
@@ -395,27 +395,27 @@ static uint64_t KiSectionPageProtection(const SECTION_HEADER* section, bool user
|
||||
|
||||
// Applies final page protections to a mapped PE image.
|
||||
KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool user) {
|
||||
if (!imageBase) return STATUS_INVALID_PARAMETER;
|
||||
if (user && !process) return STATUS_INVALID_PARAMETER;
|
||||
if (!imageBase) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (user && !process) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
size_t mappedSize = user ? LdrGetMappedImageSize(process, imageBase) : LdrGetImageSize(imageBase);
|
||||
if (!mappedSize) return STATUS_FAILURE;
|
||||
if (!mappedSize) return NTLSTATUS_FAILURE;
|
||||
|
||||
uint32_t peOffset = *(uint32_t *)(imageBase + 0x3C);
|
||||
if ((size_t)peOffset > mappedSize || mappedSize - (size_t)peOffset < sizeof(uint32_t) + 20)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
PE_HEADER* pe = (PE_HEADER *)(imageBase + peOffset);
|
||||
if (pe->Signature != PE_SIGNATURE) return STATUS_FAILURE;
|
||||
if (pe->Signature != PE_SIGNATURE) return NTLSTATUS_FAILURE;
|
||||
|
||||
size_t sectionTableOffset = (size_t)peOffset + 24u + (size_t)pe->SizeOfOptionalHeader;
|
||||
size_t sectionTableSize = (size_t)pe->NumberOfSections * sizeof(SECTION_HEADER);
|
||||
if (sectionTableOffset > mappedSize || sectionTableSize > mappedSize - sectionTableOffset)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
size_t pageCount = (mappedSize + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
uint64_t* pageProt = (uint64_t*)MmAllocatePoolTag(pageCount * sizeof(uint64_t), MM_POOL_TAG('i', 'p', 'r', 't'));
|
||||
if (!pageProt) return STATUS_NO_MEMORY;
|
||||
if (!pageProt) return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
uint64_t headerProt = PAGE_PRESENT | (user ? PAGE_USER : 0) | PAGE_NX;
|
||||
for (size_t i = 0; i < pageCount; ++i)
|
||||
@@ -438,7 +438,7 @@ KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool us
|
||||
}
|
||||
if (secEnd < secBase) {
|
||||
MmFreePool(pageProt);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
if (secEnd > mapEnd) {
|
||||
LdrDbg("LDR: protect clamping section %d end=%016llx to mapEnd=%016llx\n",
|
||||
@@ -460,7 +460,7 @@ KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool us
|
||||
}
|
||||
|
||||
size_t runStart = 0;
|
||||
KSTATUS s = STATUS_SUCCESS;
|
||||
KSTATUS s = NTLSTATUS_SUCCESS;
|
||||
while (runStart < pageCount) {
|
||||
uint64_t prot = pageProt[runStart];
|
||||
size_t runEnd = runStart + 1;
|
||||
@@ -501,10 +501,10 @@ static KSTATUS LdrApplyRelocationsForProcess(PROCESS* process, uintptr_t base, u
|
||||
PE_HEADER* pe = (PE_HEADER *)(base + peOffset);
|
||||
OPT_HEADER64* opt = &pe->OptionalHeader;
|
||||
|
||||
if (opt->NumberOfRvaAndSizes < 6) return STATUS_SUCCESS;
|
||||
if (opt->NumberOfRvaAndSizes < 6) return NTLSTATUS_SUCCESS;
|
||||
uint32_t relocRva = opt->DataDirectory[5].VirtualAddress;
|
||||
uint32_t relocSize = opt->DataDirectory[5].Size;
|
||||
if (!relocRva || !relocSize) return STATUS_SUCCESS;
|
||||
if (!relocRva || !relocSize) return NTLSTATUS_SUCCESS;
|
||||
|
||||
BASE_RELOC* block = (BASE_RELOC *)(base + relocRva);
|
||||
uintptr_t end = (uintptr_t)block + relocSize;
|
||||
@@ -527,7 +527,7 @@ static KSTATUS LdrApplyRelocationsForProcess(PROCESS* process, uintptr_t base, u
|
||||
}
|
||||
block = (BASE_RELOC *)((uint8_t *)block + block->SizeOfBlock);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Import resolution.
|
||||
@@ -555,11 +555,11 @@ static KSTATUS LdrResolveImportsCommon(
|
||||
OPT_HEADER64* opt = &pe->OptionalHeader;
|
||||
|
||||
if (opt->NumberOfRvaAndSizes < 2)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
uint32_t impRva = opt->DataDirectory[1].VirtualAddress;
|
||||
if (!impRva)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
IMPORT_DESC* imp = (IMPORT_DESC *)(imageBase + impRva);
|
||||
|
||||
@@ -606,7 +606,7 @@ static KSTATUS LdrResolveImportsCommon(
|
||||
"LdrResolveImports: Ordinal imports not supported! (%s)\n",
|
||||
dllName
|
||||
);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
const char* funcName =
|
||||
@@ -621,7 +621,7 @@ static KSTATUS LdrResolveImportsCommon(
|
||||
dllName,
|
||||
funcName
|
||||
);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
KSTATUS ws = KiEnsureUserImageWrite(process, process != (PROCESS*)0, (uintptr_t)thunk, sizeof(*thunk));
|
||||
@@ -635,7 +635,7 @@ static KSTATUS LdrResolveImportsCommon(
|
||||
imp++;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the ldr Resolve Imports operation.
|
||||
@@ -661,7 +661,7 @@ KSTATUS LdrResolveImportsForProcess(PROCESS* process, uintptr_t imageBase) {
|
||||
// Loads a user image from an open file through the image-section object model.
|
||||
KSTATUS LdrLoadImageFileForProcess(PROCESS* process, FILE_OBJECT* file, uintptr_t* baseOut) {
|
||||
if (!process || !file || !baseOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*baseOut = 0;
|
||||
|
||||
IMAGE_SECTION_OBJECT* section = (IMAGE_SECTION_OBJECT*)0;
|
||||
@@ -690,7 +690,7 @@ KSTATUS LdrLoadImageFileForProcess(PROCESS* process, FILE_OBJECT* file, uintptr_
|
||||
|
||||
LdrDereferenceImageSection(section);
|
||||
*baseOut = imageBase;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Converts a process module entry into the public module ABI.
|
||||
@@ -743,7 +743,7 @@ static PROCESS_MODULE* KiFindProcessModuleByBaseLocked(PROCESS* process, uintptr
|
||||
|
||||
// Registers a mapped process module or records a reference to an existing one.
|
||||
static KSTATUS LdrRegisterProcessModule(PROCESS* process, const char* name, uintptr_t base, uint32_t loadFlags, uintptr_t* registeredBaseOut) {
|
||||
if (!process || !name || !base || !loadFlags) return STATUS_INVALID_PARAMETER;
|
||||
if (!process || !name || !base || !loadFlags) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (registeredBaseOut) *registeredBaseOut = 0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ModuleLock);
|
||||
@@ -752,12 +752,12 @@ static KSTATUS LdrRegisterProcessModule(PROCESS* process, const char* name, uint
|
||||
KiReferenceProcessModule(existing, loadFlags);
|
||||
if (registeredBaseOut) *registeredBaseOut = existing->Base;
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
if (process->ModuleCount >= PROCESS_MODULE_MAX) {
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
PROCESS_MODULE* mod = &process->Modules[process->ModuleCount++];
|
||||
@@ -770,12 +770,12 @@ static KSTATUS LdrRegisterProcessModule(PROCESS* process, const char* name, uint
|
||||
KiReferenceProcessModule(mod, loadFlags);
|
||||
if (registeredBaseOut) *registeredBaseOut = mod->Base;
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Loads a DLL-like user module into a process and records the requested reference.
|
||||
KSTATUS LdrLoadModuleForProcess(PROCESS* process, const char* filename, uint32_t loadFlags, uintptr_t* baseOut) {
|
||||
if (!process || !filename || !loadFlags) return STATUS_INVALID_PARAMETER;
|
||||
if (!process || !filename || !loadFlags) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
filename = KiCanonicalModuleName(filename);
|
||||
|
||||
@@ -785,7 +785,7 @@ KSTATUS LdrLoadModuleForProcess(PROCESS* process, const char* filename, uint32_t
|
||||
KiReferenceProcessModule(existing, loadFlags);
|
||||
if (baseOut) *baseOut = existing->Base;
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
|
||||
@@ -795,7 +795,7 @@ KSTATUS LdrLoadModuleForProcess(PROCESS* process, const char* filename, uint32_t
|
||||
char relative[260];
|
||||
size_t nameLen = strnlen(filename, sizeof(relative) - 8);
|
||||
if (nameLen + 8 >= sizeof(relative))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
memcpy(relative, "system/", 7);
|
||||
memcpy(relative + 7, filename, nameLen);
|
||||
relative[7 + nameLen] = '\0';
|
||||
@@ -834,10 +834,10 @@ KSTATUS LdrLoadModuleForProcess(PROCESS* process, const char* filename, uint32_t
|
||||
|
||||
uintptr_t registeredBase = 0;
|
||||
s = LdrRegisterProcessModule(process, filename, imageBase, loadFlags, ®isteredBase);
|
||||
if (s == STATUS_ALREADY_EXISTS) {
|
||||
if (s == NTLSTATUS_ALREADY_EXISTS) {
|
||||
KiFreeLoadedImageForProcess(process, imageBase, true);
|
||||
imageBase = registeredBase;
|
||||
s = STATUS_SUCCESS;
|
||||
s = NTLSTATUS_SUCCESS;
|
||||
}
|
||||
if (!KSUCCESS(s)) {
|
||||
KiFreeLoadedImageForProcess(process, imageBase, true);
|
||||
@@ -847,12 +847,12 @@ KSTATUS LdrLoadModuleForProcess(PROCESS* process, const char* filename, uint32_t
|
||||
LdrDbg("LDR: module registered pid=%u name=%s base=%016llx modules=%u\n",
|
||||
process->ProcessId, filename, (unsigned long long)imageBase, process->ModuleCount);
|
||||
if (baseOut) *baseOut = imageBase;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases one public module load reference and unmaps the image when no references remain.
|
||||
KSTATUS LdrUnloadModuleForProcess(PROCESS* process, uintptr_t imageBase) {
|
||||
if (!process || !imageBase) return STATUS_INVALID_PARAMETER;
|
||||
if (!process || !imageBase) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
char name[PROCESS_MODULE_NAME_MAX];
|
||||
uintptr_t base = 0;
|
||||
@@ -862,11 +862,11 @@ KSTATUS LdrUnloadModuleForProcess(PROCESS* process, uintptr_t imageBase) {
|
||||
PROCESS_MODULE* mod = KiFindProcessModuleByBaseLocked(process, imageBase);
|
||||
if (!mod) {
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
if (mod->PublicRefCount == 0) {
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
mod->PublicRefCount--;
|
||||
@@ -891,27 +891,27 @@ KSTATUS LdrUnloadModuleForProcess(PROCESS* process, uintptr_t imageBase) {
|
||||
KiFreeLoadedImageForProcess(process, base, true);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Queries one loaded process module by image base.
|
||||
KSTATUS LdrQueryModuleForProcess(PROCESS* process, uintptr_t imageBase, SYS_MODULE_INFO* infoOut) {
|
||||
if (!process || !imageBase || !infoOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!process || !imageBase || !infoOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ModuleLock);
|
||||
PROCESS_MODULE* mod = KiFindProcessModuleByBaseLocked(process, imageBase);
|
||||
if (!mod) {
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
KiFillProcessModuleInfo(mod, infoOut);
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Copies a bounded snapshot of the process module table.
|
||||
KSTATUS LdrCopyProcessModuleInfo(PROCESS* process, SYS_MODULE_INFO* infoOut, size_t maxCount, size_t* countOut) {
|
||||
if (!process || !countOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!process || !countOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->ModuleLock);
|
||||
size_t count = process->ModuleCount;
|
||||
@@ -920,44 +920,44 @@ KSTATUS LdrCopyProcessModuleInfo(PROCESS* process, SYS_MODULE_INFO* infoOut, siz
|
||||
if (toCopy > maxCount) toCopy = maxCount;
|
||||
if (toCopy && !infoOut) {
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
for (size_t i = 0; i < toCopy; i++)
|
||||
KiFillProcessModuleInfo(&process->Modules[i], &infoOut[i]);
|
||||
KeReleaseSpinlock(&process->ModuleLock, flags);
|
||||
return (maxCount < count) ? STATUS_BUFFER_TOO_SMALL : STATUS_SUCCESS;
|
||||
return (maxCount < count) ? NTLSTATUS_BUFFER_TOO_SMALL : NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Loads a boot/kernel PE image from a raw memory buffer into kernel space.
|
||||
static KSTATUS KiLdrLoadKernelImageFromBuffer(const void* buffer, size_t size, uintptr_t* baseOut) {
|
||||
if (!buffer || !size || !baseOut) return STATUS_INVALID_PARAMETER;
|
||||
if (size < 0x40) return STATUS_FAILURE;
|
||||
if (!buffer || !size || !baseOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (size < 0x40) return NTLSTATUS_FAILURE;
|
||||
|
||||
const uint8_t* bytes = (const uint8_t*)buffer;
|
||||
uint32_t peOffset = *(const uint32_t *)(bytes + 0x3C);
|
||||
if ((size_t)peOffset > size || size - (size_t)peOffset < 24) return STATUS_FAILURE;
|
||||
if ((size_t)peOffset > size || size - (size_t)peOffset < 24) return NTLSTATUS_FAILURE;
|
||||
|
||||
uint32_t signature = *(const uint32_t *)(bytes + peOffset);
|
||||
if (signature != PE_SIGNATURE) return STATUS_FAILURE;
|
||||
if (signature != PE_SIGNATURE) return NTLSTATUS_FAILURE;
|
||||
|
||||
uint16_t machine = *(const uint16_t *)(bytes + peOffset + 4);
|
||||
uint16_t optionalSize = *(const uint16_t *)(bytes + peOffset + 20);
|
||||
if (optionalSize < sizeof(OPT_HEADER64) ||
|
||||
(size_t)peOffset + 24 + optionalSize > size) {
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
uint16_t optionalMagic = *(const uint16_t *)(bytes + peOffset + 24);
|
||||
if (machine == IMAGE_FILE_MACHINE_I386 || optionalMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||
DbgPrint("LdrLoadKernelImage: hard error: 32-bit PE images are not supported (machine=0x%X magic=0x%X)\n",
|
||||
machine, optionalMagic);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (machine != IMAGE_FILE_MACHINE_AMD64 || optionalMagic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||
DbgPrint("LdrLoadKernelImage: unsupported PE image (machine=0x%X magic=0x%X)\n",
|
||||
machine, optionalMagic);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
PE_HEADER* pe = (PE_HEADER *)(bytes + peOffset);
|
||||
@@ -976,7 +976,7 @@ static KSTATUS KiLdrLoadKernelImageFromBuffer(const void* buffer, size_t size, u
|
||||
if (!mem) {
|
||||
DbgPrint("LDR: kernel image allocation failed required=%llx\n",
|
||||
(unsigned long long)imageSize);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
memset(mem, 0, imageSize);
|
||||
|
||||
@@ -1018,7 +1018,7 @@ static KSTATUS KiLdrLoadKernelImageFromBuffer(const void* buffer, size_t size, u
|
||||
}
|
||||
|
||||
*baseOut = (uintptr_t)mem;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Loads a kernel image from a bootloader or driver raw buffer.
|
||||
|
||||
+62
-62
@@ -134,7 +134,7 @@ static uint64_t KiImageSectionProtection(uint32_t characteristics) {
|
||||
|
||||
// Computes the required image mapping size after validating raw section extents.
|
||||
static KSTATUS KiImageSectionComputeSize(const LDR_PE_HEADER* pe, size_t fileSize, size_t* outSize) {
|
||||
if (!pe || !outSize) return STATUS_INVALID_PARAMETER;
|
||||
if (!pe || !outSize) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
const LDR_OPT_HEADER64* opt = &pe->OptionalHeader;
|
||||
size_t required = KiImageSectionAlignSize(opt->SizeOfImage);
|
||||
@@ -150,20 +150,20 @@ static KSTATUS KiImageSectionComputeSize(const LDR_PE_HEADER* pe, size_t fileSiz
|
||||
if (raw > span) span = raw;
|
||||
if (!span) continue;
|
||||
|
||||
if (va > (size_t)-1 - span) return STATUS_NO_MEMORY;
|
||||
if (va > (size_t)-1 - span) return NTLSTATUS_NO_MEMORY;
|
||||
size_t end = KiImageSectionAlignSize(va + span);
|
||||
if (end > required) required = end;
|
||||
|
||||
if (raw) {
|
||||
size_t rawBase = (size_t)sec[i].PointerToRawData;
|
||||
if (rawBase > fileSize || raw > fileSize - rawBase)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!required) return STATUS_FAILURE;
|
||||
if (!required) return NTLSTATUS_FAILURE;
|
||||
*outSize = required;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Parses and validates the PE header that backs an image section object.
|
||||
@@ -174,45 +174,45 @@ static KSTATUS KiImageSectionParseHeader(const void* buffer,
|
||||
const LDR_SECTION_HEADER** sectionsOut,
|
||||
size_t* imageSizeOut) {
|
||||
if (!buffer || !bufferSize || !peOut || !sectionsOut || !imageSizeOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (bufferSize < 0x40) return STATUS_FAILURE;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (bufferSize < 0x40) return NTLSTATUS_FAILURE;
|
||||
|
||||
const uint8_t* bytes = (const uint8_t*)buffer;
|
||||
uint32_t peOffset = *(const uint32_t*)(bytes + 0x3C);
|
||||
if ((size_t)peOffset > bufferSize || bufferSize - (size_t)peOffset < 24)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
const LDR_PE_HEADER* pe = (const LDR_PE_HEADER*)(bytes + peOffset);
|
||||
if (pe->Signature != PE_SIGNATURE)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
uint16_t optionalSize = pe->SizeOfOptionalHeader;
|
||||
if (optionalSize < sizeof(LDR_OPT_HEADER64) ||
|
||||
(size_t)peOffset + 24 + optionalSize > bufferSize) {
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
uint16_t optionalMagic = pe->OptionalHeader.Magic;
|
||||
if (pe->Machine == IMAGE_FILE_MACHINE_I386 || optionalMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||
DbgPrint("LdrImageSection: 32-bit PE images are not supported (machine=0x%X magic=0x%X)\n",
|
||||
pe->Machine, optionalMagic);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (pe->Machine != IMAGE_FILE_MACHINE_AMD64 || optionalMagic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||
DbgPrint("LdrImageSection: unsupported PE image (machine=0x%X magic=0x%X)\n",
|
||||
pe->Machine, optionalMagic);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!pe->NumberOfSections)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
const LDR_SECTION_HEADER* sections = (const LDR_SECTION_HEADER*)((const uint8_t*)&pe->OptionalHeader + pe->SizeOfOptionalHeader);
|
||||
size_t sectionTableOffset = (size_t)peOffset + 24u + (size_t)pe->SizeOfOptionalHeader;
|
||||
size_t sectionTableBytes = (size_t)pe->NumberOfSections * sizeof(LDR_SECTION_HEADER);
|
||||
if (sectionTableOffset > bufferSize || sectionTableBytes > bufferSize - sectionTableOffset)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
size_t imageSize = 0;
|
||||
KSTATUS s = KiImageSectionComputeSize(pe, fileSize, &imageSize);
|
||||
@@ -221,7 +221,7 @@ static KSTATUS KiImageSectionParseHeader(const void* buffer,
|
||||
*peOut = pe;
|
||||
*sectionsOut = sections;
|
||||
*imageSizeOut = imageSize;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases all resources owned by an image section object.
|
||||
@@ -271,7 +271,7 @@ static IMAGE_SECTION_OBJECT* KiFindImageSectionLocked(const IO_FILE_IDENTITY* id
|
||||
// Verifies that a cached image section is still backed by the same file generation.
|
||||
static KSTATUS KiValidateImageSectionBackingFile(IMAGE_SECTION_OBJECT* section) {
|
||||
if (!section || !section->BackingFile)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
IO_FILE_IDENTITY identity;
|
||||
KSTATUS s = IoQueryFileIdentity(section->BackingFile, &identity);
|
||||
@@ -282,10 +282,10 @@ static KSTATUS KiValidateImageSectionBackingFile(IMAGE_SECTION_OBJECT* section)
|
||||
identity.FileId != section->Metadata.FileId ||
|
||||
identity.Generation != section->Metadata.FileGeneration ||
|
||||
identity.Size != section->Metadata.RawSize) {
|
||||
return STATUS_CHECKSUM_MISMATCH;
|
||||
return NTLSTATUS_CHECKSUM_MISMATCH;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns true when a virtual image page has initialized bytes in the backing file.
|
||||
@@ -323,17 +323,17 @@ static KSTATUS KiReadImageSectionFileBytes(IMAGE_SECTION_OBJECT* section,
|
||||
void* dst,
|
||||
size_t size) {
|
||||
if (!section || !section->BackingFile || (!dst && size))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!size)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
size_t got = 0;
|
||||
KSTATUS s = IoReadFileAt(section->BackingFile, fileOffset, dst, size, &got);
|
||||
if (!KSUCCESS(s))
|
||||
return s;
|
||||
if (got != size)
|
||||
return STATUS_FAILURE;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_FAILURE;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Fills one prototype frame from the image backing file.
|
||||
@@ -341,11 +341,11 @@ static KSTATUS KiFillImageSectionFrameFromFile(IMAGE_SECTION_OBJECT* section,
|
||||
size_t pageIndex,
|
||||
PHYSICAL_ADDRESS frame) {
|
||||
if (!section || !frame || pageIndex >= section->Metadata.PageCount)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint8_t* page = (uint8_t*)MmPfnToVirtual(frame);
|
||||
if (!page)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
memset(page, 0, PAGE_SIZE);
|
||||
|
||||
size_t pageStart = pageIndex * PAGE_SIZE;
|
||||
@@ -375,7 +375,7 @@ static KSTATUS KiFillImageSectionFrameFromFile(IMAGE_SECTION_OBJECT* section,
|
||||
size_t sectionStart = desc->VirtualAddress;
|
||||
size_t sectionEnd = sectionStart + raw;
|
||||
if (sectionEnd < sectionStart)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
if (pageStart >= sectionEnd || pageEnd <= sectionStart)
|
||||
continue;
|
||||
|
||||
@@ -392,34 +392,34 @@ static KSTATUS KiFillImageSectionFrameFromFile(IMAGE_SECTION_OBJECT* section,
|
||||
return s;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Ensures a prototype page exists for initialized image bytes.
|
||||
static KSTATUS KiEnsureImageSectionFrame(IMAGE_SECTION_OBJECT* section, size_t pageIndex) {
|
||||
if (!section || pageIndex >= section->Metadata.PageCount)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(§ion->Lock);
|
||||
PHYSICAL_ADDRESS existing = section->Frames[pageIndex];
|
||||
KeReleaseSpinlock(§ion->Lock, flags);
|
||||
if (existing)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
if (section->BackingFile && !KiImageSectionPageHasFileBytes(section, pageIndex))
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
PHYSICAL_ADDRESS frame = MmPfnAllocate(MmPfnUseImage);
|
||||
if (!frame)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
void* va = MmPfnToVirtual(frame);
|
||||
if (!va) {
|
||||
MmPfnFree(frame);
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
KSTATUS s = STATUS_SUCCESS;
|
||||
KSTATUS s = NTLSTATUS_SUCCESS;
|
||||
if (section->BackingFile) {
|
||||
s = KiValidateImageSectionBackingFile(section);
|
||||
if (KSUCCESS(s))
|
||||
@@ -436,11 +436,11 @@ static KSTATUS KiEnsureImageSectionFrame(IMAGE_SECTION_OBJECT* section, size_t p
|
||||
if (section->Frames[pageIndex]) {
|
||||
KeReleaseSpinlock(§ion->Lock, flags);
|
||||
MmPfnFree(frame);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
section->Frames[pageIndex] = frame;
|
||||
KeReleaseSpinlock(§ion->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Builds an uncached image section object backed directly by an open file.
|
||||
@@ -451,7 +451,7 @@ static KSTATUS KiBuildImageSectionObjectFromFile(FILE_OBJECT* file,
|
||||
uint64_t key,
|
||||
IMAGE_SECTION_OBJECT** sectionOut) {
|
||||
if (!file || !headerBuffer || !headerBufferSize || !identity || !sectionOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*sectionOut = (IMAGE_SECTION_OBJECT*)0;
|
||||
|
||||
size_t fileSize = (size_t)identity->Size;
|
||||
@@ -469,19 +469,19 @@ static KSTATUS KiBuildImageSectionObjectFromFile(FILE_OBJECT* file,
|
||||
|
||||
size_t pageCount = (imageSize + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
if (!pageCount || pageCount > ((size_t)-1 / sizeof(PHYSICAL_ADDRESS)))
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
IMAGE_SECTION_OBJECT* section = (IMAGE_SECTION_OBJECT*)ObAllocateObject(ObjectTypeImageSection,
|
||||
sizeof(IMAGE_SECTION_OBJECT));
|
||||
if (!section)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
section->Header.Destroy = KiDestroyImageSectionObject;
|
||||
|
||||
PHYSICAL_ADDRESS* frames = (PHYSICAL_ADDRESS*)MmAllocatePoolTag(pageCount * sizeof(PHYSICAL_ADDRESS),
|
||||
MM_POOL_TAG('i', 's', 'f', 'r'));
|
||||
if (!frames) {
|
||||
ObDereferenceObject(§ion->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
memset(frames, 0, pageCount * sizeof(PHYSICAL_ADDRESS));
|
||||
|
||||
@@ -491,7 +491,7 @@ static KSTATUS KiBuildImageSectionObjectFromFile(FILE_OBJECT* file,
|
||||
if (!descriptors) {
|
||||
MmFreePool(frames);
|
||||
ObDereferenceObject(§ion->Header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
memset(descriptors, 0, (size_t)pe->NumberOfSections * sizeof(IMAGE_SECTION_DESCRIPTOR));
|
||||
|
||||
@@ -527,14 +527,14 @@ static KSTATUS KiBuildImageSectionObjectFromFile(FILE_OBJECT* file,
|
||||
}
|
||||
|
||||
*sectionOut = section;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Creates or references an image section object backed by an open file.
|
||||
KSTATUS LdrCreateImageSectionFromFile(FILE_OBJECT* file,
|
||||
IMAGE_SECTION_OBJECT** sectionOut) {
|
||||
if (!file || !sectionOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*sectionOut = (IMAGE_SECTION_OBJECT*)0;
|
||||
|
||||
IO_FILE_IDENTITY identity;
|
||||
@@ -544,32 +544,32 @@ KSTATUS LdrCreateImageSectionFromFile(FILE_OBJECT* file,
|
||||
|
||||
size_t fileSize = (size_t)identity.Size;
|
||||
if (!fileSize)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
size_t firstRead = fileSize < 4096u ? fileSize : 4096u;
|
||||
uint8_t stackHeader[4096];
|
||||
size_t got = 0;
|
||||
s = IoReadFileAt(file, 0, stackHeader, firstRead, &got);
|
||||
if (!KSUCCESS(s) || got != firstRead)
|
||||
return KSUCCESS(s) ? STATUS_FAILURE : s;
|
||||
return KSUCCESS(s) ? NTLSTATUS_FAILURE : s;
|
||||
if (firstRead < 0x40)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
uint32_t peOffset = *(const uint32_t*)(stackHeader + 0x3C);
|
||||
if ((size_t)peOffset > fileSize || fileSize - (size_t)peOffset < 24)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
size_t minimumHeader = (size_t)peOffset + 24u;
|
||||
if (minimumHeader > firstRead) {
|
||||
if (minimumHeader > 65536u || minimumHeader > fileSize)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
void* tmp = MmAllocatePoolTag(minimumHeader, MM_POOL_TAG('i', 's', 'h', 'd'));
|
||||
if (!tmp)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
s = IoReadFileAt(file, 0, tmp, minimumHeader, &got);
|
||||
if (!KSUCCESS(s) || got != minimumHeader) {
|
||||
MmFreePool(tmp);
|
||||
return KSUCCESS(s) ? STATUS_FAILURE : s;
|
||||
return KSUCCESS(s) ? NTLSTATUS_FAILURE : s;
|
||||
}
|
||||
uint16_t optSize = *(const uint16_t*)((const uint8_t*)tmp + peOffset + 20u);
|
||||
size_t fullHeader = (size_t)peOffset + 24u + (size_t)optSize;
|
||||
@@ -585,19 +585,19 @@ KSTATUS LdrCreateImageSectionFromFile(FILE_OBJECT* file,
|
||||
}
|
||||
|
||||
if (firstRead > fileSize || firstRead > 65536u)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
void* header = stackHeader;
|
||||
bool heapHeader = false;
|
||||
if (firstRead > sizeof(stackHeader)) {
|
||||
header = MmAllocatePoolTag(firstRead, MM_POOL_TAG('i', 's', 'h', 'd'));
|
||||
if (!header)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
heapHeader = true;
|
||||
s = IoReadFileAt(file, 0, header, firstRead, &got);
|
||||
if (!KSUCCESS(s) || got != firstRead) {
|
||||
MmFreePool(header);
|
||||
return KSUCCESS(s) ? STATUS_FAILURE : s;
|
||||
return KSUCCESS(s) ? NTLSTATUS_FAILURE : s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,18 +607,18 @@ KSTATUS LdrCreateImageSectionFromFile(FILE_OBJECT* file,
|
||||
if (tableEnd > firstRead) {
|
||||
if (tableEnd > fileSize || tableEnd > 65536u) {
|
||||
if (heapHeader) MmFreePool(header);
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
void* bigger = MmAllocatePoolTag(tableEnd, MM_POOL_TAG('i', 's', 'h', 'd'));
|
||||
if (!bigger) {
|
||||
if (heapHeader) MmFreePool(header);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
s = IoReadFileAt(file, 0, bigger, tableEnd, &got);
|
||||
if (heapHeader) MmFreePool(header);
|
||||
if (!KSUCCESS(s) || got != tableEnd) {
|
||||
MmFreePool(bigger);
|
||||
return KSUCCESS(s) ? STATUS_FAILURE : s;
|
||||
return KSUCCESS(s) ? NTLSTATUS_FAILURE : s;
|
||||
}
|
||||
header = bigger;
|
||||
firstRead = tableEnd;
|
||||
@@ -634,7 +634,7 @@ KSTATUS LdrCreateImageSectionFromFile(FILE_OBJECT* file,
|
||||
KeReleaseSpinlock(&gImageSectionCacheLock, flags);
|
||||
if (heapHeader) MmFreePool(header);
|
||||
*sectionOut = cached;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KeReleaseSpinlock(&gImageSectionCacheLock, flags);
|
||||
|
||||
@@ -651,7 +651,7 @@ KSTATUS LdrCreateImageSectionFromFile(FILE_OBJECT* file,
|
||||
KeReleaseSpinlock(&gImageSectionCacheLock, flags);
|
||||
ObDereferenceObject(&built->Header);
|
||||
*sectionOut = cached;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < LDR_IMAGE_SECTION_CACHE_MAX; ++i) {
|
||||
@@ -664,7 +664,7 @@ KSTATUS LdrCreateImageSectionFromFile(FILE_OBJECT* file,
|
||||
KeReleaseSpinlock(&gImageSectionCacheLock, flags);
|
||||
|
||||
*sectionOut = built;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Adds a reference to an existing image section object.
|
||||
@@ -697,10 +697,10 @@ const IMAGE_SECTION_DESCRIPTOR* LdrImageSectionDescriptors(const IMAGE_SECTION_O
|
||||
KSTATUS LdrRetainImageSectionPage(IMAGE_SECTION_OBJECT* section,
|
||||
size_t pageIndex,
|
||||
PHYSICAL_ADDRESS* frameOut) {
|
||||
if (!section || !frameOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!section || !frameOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*frameOut = 0;
|
||||
if (pageIndex >= section->Metadata.PageCount)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS es = KiEnsureImageSectionFrame(section, pageIndex);
|
||||
if (!KSUCCESS(es))
|
||||
@@ -710,21 +710,21 @@ KSTATUS LdrRetainImageSectionPage(IMAGE_SECTION_OBJECT* section,
|
||||
PHYSICAL_ADDRESS frame = section->Frames[pageIndex];
|
||||
KeReleaseSpinlock(§ion->Lock, flags);
|
||||
if (!frame)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
KSTATUS s = MmPfnRetain(frame);
|
||||
if (!KSUCCESS(s))
|
||||
return s;
|
||||
|
||||
*frameOut = frame;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Maps an image section into a process as an image-backed VAD.
|
||||
KSTATUS LdrMapImageSection(PROCESS* process,
|
||||
IMAGE_SECTION_OBJECT* section,
|
||||
void** baseOut) {
|
||||
if (!process || !section || !baseOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!process || !section || !baseOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*baseOut = (void*)0;
|
||||
|
||||
return MmVadCreateImageSectionMapping(process,
|
||||
|
||||
+66
-66
@@ -203,13 +203,13 @@ static KSTATUS KiFileCacheDemoteOnePage(FILE_OBJECT* skipFile, uint64_t skipOffs
|
||||
if (KSUCCESS(s)) {
|
||||
KiFileCacheMoveEntryToStandbyLocked(demote);
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
}
|
||||
}
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
static KSTATUS KiFileCacheDropOneStandbyPage(FILE_OBJECT* skipFile, uint64_t skipOffset) {
|
||||
@@ -229,28 +229,28 @@ static KSTATUS KiFileCacheDropOneStandbyPage(FILE_OBJECT* skipFile, uint64_t ski
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
if (victim) {
|
||||
KiFileCacheFreeEntry(victim);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
static KSTATUS KiFileCacheReclaimOnePage(FILE_OBJECT* skipFile, uint64_t skipOffset) {
|
||||
KSTATUS s = KiFileCacheDropOneStandbyPage(skipFile, skipOffset);
|
||||
if (KSUCCESS(s))
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
s = KiFileCacheDemoteOnePage(skipFile, skipOffset);
|
||||
if (KSUCCESS(s)) {
|
||||
s = KiFileCacheDropOneStandbyPage(skipFile, skipOffset);
|
||||
if (KSUCCESS(s))
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFileCacheLock);
|
||||
gFileCacheStats.DropFailures++;
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
static void KiFileCacheAddReadAheadStat(uint64_t* field, uint64_t value) {
|
||||
@@ -366,13 +366,13 @@ static KSTATUS KiFileCacheEnsureReadAheadStarted(void) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gReadAheadLock);
|
||||
if (gReadAheadStartState == 2) {
|
||||
KeReleaseSpinlock(&gReadAheadLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
if (gReadAheadStartState == 1) {
|
||||
KeReleaseSpinlock(&gReadAheadLock, flags);
|
||||
while (gReadAheadStartState == 1)
|
||||
KeYield();
|
||||
return gReadAheadStartState == 2 ? STATUS_SUCCESS : STATUS_FAILURE;
|
||||
return gReadAheadStartState == 2 ? NTLSTATUS_SUCCESS : NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
gReadAheadStartState = 1;
|
||||
@@ -408,7 +408,7 @@ static KSTATUS KiFileCacheFlushOneDirtyPage(FILE_OBJECT* file, int* didWork) {
|
||||
MM_FILE_CACHE_ENTRY* e = KiFileCacheFindLowestDirtyLocked(file);
|
||||
if (!e) {
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
KSTATUS rs = MmPfnRetain(e->Frame);
|
||||
@@ -430,11 +430,11 @@ static KSTATUS KiFileCacheFlushOneDirtyPage(FILE_OBJECT* file, int* didWork) {
|
||||
|
||||
void* page = MmPfnToVirtual(frame);
|
||||
size_t written = 0;
|
||||
KSTATUS s = STATUS_FAILURE;
|
||||
KSTATUS s = NTLSTATUS_FAILURE;
|
||||
if (page && target->Fs && target->Fs->Write)
|
||||
s = target->Fs->Write(target->Fs, target->FileCtx, offset, page, validBytes, &written);
|
||||
if (KSUCCESS(s) && written != validBytes)
|
||||
s = STATUS_FAILURE;
|
||||
s = NTLSTATUS_FAILURE;
|
||||
|
||||
flags = KeAcquireSpinlock(&gFileCacheLock);
|
||||
uint32_t bucket = KiFileCacheHash(target, offset);
|
||||
@@ -489,13 +489,13 @@ static KSTATUS KiFileCacheEnsureWritebackStarted(void) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gWritebackLock);
|
||||
if (gWritebackStartState == 2) {
|
||||
KeReleaseSpinlock(&gWritebackLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
if (gWritebackStartState == 1) {
|
||||
KeReleaseSpinlock(&gWritebackLock, flags);
|
||||
while (gWritebackStartState == 1)
|
||||
KeYield();
|
||||
return gWritebackStartState == 2 ? STATUS_SUCCESS : STATUS_FAILURE;
|
||||
return gWritebackStartState == 2 ? NTLSTATUS_SUCCESS : NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
gWritebackStartState = 1;
|
||||
@@ -536,14 +536,14 @@ static KSTATUS KiFileCacheTryHit(FILE_OBJECT* file, uint64_t aligned, MM_FILE_CA
|
||||
if (!hit) {
|
||||
gFileCacheStats.Misses++;
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (hit->Loading) {
|
||||
if (!waitForLoading) {
|
||||
gFileCacheStats.Misses++;
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_PENDING;
|
||||
}
|
||||
|
||||
gFileCacheStats.InflightWaits++;
|
||||
@@ -555,7 +555,7 @@ static KSTATUS KiFileCacheTryHit(FILE_OBJECT* file, uint64_t aligned, MM_FILE_CA
|
||||
if (hit->Invalidated || !hit->Frame) {
|
||||
gFileCacheStats.Misses++;
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (hit->Standby) {
|
||||
@@ -564,7 +564,7 @@ static KSTATUS KiFileCacheTryHit(FILE_OBJECT* file, uint64_t aligned, MM_FILE_CA
|
||||
KiFileCacheActivateEntryLocked(hit);
|
||||
}
|
||||
|
||||
KSTATUS rs = STATUS_SUCCESS;
|
||||
KSTATUS rs = NTLSTATUS_SUCCESS;
|
||||
if (outPage)
|
||||
rs = MmPfnRetain(hit->Frame);
|
||||
if (KSUCCESS(rs)) {
|
||||
@@ -577,7 +577,7 @@ static KSTATUS KiFileCacheTryHit(FILE_OBJECT* file, uint64_t aligned, MM_FILE_CA
|
||||
outPage->ValidBytes = hit->ValidBytes;
|
||||
}
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// A retained cache entry should never point at an invalid frame, but do not
|
||||
@@ -641,14 +641,14 @@ static KSTATUS KiFileCacheReserveLoadingPage(FILE_OBJECT* file, uint64_t aligned
|
||||
|
||||
MM_FILE_CACHE_ENTRY* entry = KiFileCacheAllocateLoadingEntry(file, aligned);
|
||||
if (!entry)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
uint32_t bucket = KiFileCacheHash(file, aligned);
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFileCacheLock);
|
||||
if (KiFileCacheFindLocked(file, aligned, bucket)) {
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
KiFileCacheFreeLoadingEntry(entry);
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
entry->Next = gFileCacheBuckets[bucket];
|
||||
@@ -657,7 +657,7 @@ static KSTATUS KiFileCacheReserveLoadingPage(FILE_OBJECT* file, uint64_t aligned
|
||||
|
||||
if (outEntry)
|
||||
*outEntry = entry;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void KiFileCacheCancelLoadingPage(MM_FILE_CACHE_ENTRY* entry) {
|
||||
@@ -678,7 +678,7 @@ static KSTATUS KiFileCacheCompleteLoadingPage(MM_FILE_CACHE_ENTRY* entry,
|
||||
MM_FILE_CACHE_PAGE* requestedPage,
|
||||
uint64_t* publishedCount) {
|
||||
if (!entry || !frame)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFileCacheLock);
|
||||
if (entry->Invalidated) {
|
||||
@@ -686,7 +686,7 @@ static KSTATUS KiFileCacheCompleteLoadingPage(MM_FILE_CACHE_ENTRY* entry,
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
(void)MmPfnRelease(frame);
|
||||
KiFileCacheFreeLoadingEntry(entry);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
entry->Frame = frame;
|
||||
@@ -715,7 +715,7 @@ static KSTATUS KiFileCacheCompleteLoadingPage(MM_FILE_CACHE_ENTRY* entry,
|
||||
}
|
||||
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint32_t KiFileCacheChooseForegroundBatchPages(void) {
|
||||
@@ -746,7 +746,7 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
if (loadedPagesOut)
|
||||
*loadedPagesOut = 0;
|
||||
if (!file || maxPages == 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (maxPages > MM_FILE_CACHE_BATCH_MAX_PAGES)
|
||||
maxPages = MM_FILE_CACHE_BATCH_MAX_PAGES;
|
||||
|
||||
@@ -759,7 +759,7 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
uint64_t fileSize = file->Size;
|
||||
KeReleaseSpinlock(&file->Lock, fileFlags);
|
||||
if (aligned >= fileSize)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
MM_FILE_CACHE_ENTRY* entries[MM_FILE_CACHE_BATCH_MAX_PAGES];
|
||||
PHYSICAL_ADDRESS frames[MM_FILE_CACHE_BATCH_MAX_PAGES];
|
||||
@@ -767,7 +767,7 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
memset(frames, 0, sizeof(frames));
|
||||
|
||||
uint32_t pages = 0;
|
||||
KSTATUS reserveStatus = STATUS_SUCCESS;
|
||||
KSTATUS reserveStatus = NTLSTATUS_SUCCESS;
|
||||
while (pages < maxPages) {
|
||||
uint64_t pageOffset = aligned + ((uint64_t)pages * PAGE_SIZE);
|
||||
if (pageOffset >= fileSize)
|
||||
@@ -782,7 +782,7 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
if (pages == 0) {
|
||||
if (requestedPage)
|
||||
return KiFileCacheTryHit(file, aligned, requestedPage, 1);
|
||||
return reserveStatus == STATUS_ALREADY_EXISTS ? STATUS_ALREADY_EXISTS : reserveStatus;
|
||||
return reserveStatus == NTLSTATUS_ALREADY_EXISTS ? NTLSTATUS_ALREADY_EXISTS : reserveStatus;
|
||||
}
|
||||
|
||||
uint8_t* readBuffer = (uint8_t*)MmAllocatePoolTag((size_t)pages * PAGE_SIZE, MM_POOL_TAG('f', 'c', 'b', 'l'));
|
||||
@@ -790,7 +790,7 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
for (uint32_t i = 0; i < pages; ++i)
|
||||
KiFileCacheCancelLoadingPage(entries[i]);
|
||||
KiFileCacheAddReadAheadStat(&gFileCacheStats.LoadFailures, 1);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
memset(readBuffer, 0, (size_t)pages * PAGE_SIZE);
|
||||
|
||||
@@ -803,13 +803,13 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
KiFileCacheCancelLoadingPage(entries[j]);
|
||||
MmFreePool(readBuffer);
|
||||
KiFileCacheAddReadAheadStat(&gFileCacheStats.LoadFailures, 1);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
size_t toRead = KiMinSize((size_t)pages * PAGE_SIZE, (size_t)(fileSize - aligned));
|
||||
size_t got = 0;
|
||||
KSTATUS s = STATUS_NOT_SUPPORTED;
|
||||
KSTATUS s = NTLSTATUS_NOT_SUPPORTED;
|
||||
if (file->Fs && file->Fs->Read)
|
||||
s = file->Fs->Read(file->Fs, file->FileCtx, aligned, readBuffer, toRead, &got);
|
||||
if (!KSUCCESS(s)) {
|
||||
@@ -826,7 +826,7 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
got = toRead;
|
||||
|
||||
uint64_t published = 0;
|
||||
KSTATUS requestedStatus = STATUS_NOT_FOUND;
|
||||
KSTATUS requestedStatus = NTLSTATUS_NOT_FOUND;
|
||||
for (uint32_t i = 0; i < pages; ++i) {
|
||||
uint64_t pageOffset = aligned + ((uint64_t)i * PAGE_SIZE);
|
||||
size_t pageBase = (size_t)i * PAGE_SIZE;
|
||||
@@ -859,7 +859,7 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
KSTATUS ps = KiFileCacheCompleteLoadingPage(entries[i], frames[i], validBytes, out, &published);
|
||||
if (KSUCCESS(ps)) {
|
||||
if (pageOffset == aligned)
|
||||
requestedStatus = STATUS_SUCCESS;
|
||||
requestedStatus = NTLSTATUS_SUCCESS;
|
||||
frames[i] = 0;
|
||||
} else {
|
||||
if (pageOffset == aligned)
|
||||
@@ -885,10 +885,10 @@ static KSTATUS KiFileCacheLoadSpan(FILE_OBJECT* file,
|
||||
|
||||
if (requestedPage) {
|
||||
if (KSUCCESS(requestedStatus))
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
return KiFileCacheTryHit(file, aligned, requestedPage, 1);
|
||||
}
|
||||
return published ? STATUS_SUCCESS : STATUS_NOT_FOUND;
|
||||
return published ? NTLSTATUS_SUCCESS : NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Returns a retained cache page suitable for in-place buffered writes.
|
||||
@@ -898,24 +898,24 @@ static KSTATUS KiFileCacheGetWritablePage(FILE_OBJECT* file,
|
||||
int needExistingBytes,
|
||||
MM_FILE_CACHE_PAGE* outPage) {
|
||||
if (!file || !outPage)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
memset(outPage, 0, sizeof(*outPage));
|
||||
|
||||
KSTATUS s = KiFileCacheTryHit(file, aligned, outPage, 1);
|
||||
if (KSUCCESS(s))
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
if (needExistingBytes && aligned < oldFileSize) {
|
||||
s = KiFileCacheLoadSpan(file, aligned, 1, outPage, (uint32_t*)0);
|
||||
if (KSUCCESS(s))
|
||||
return STATUS_SUCCESS;
|
||||
if (s != STATUS_NOT_FOUND)
|
||||
return NTLSTATUS_SUCCESS;
|
||||
if (s != NTLSTATUS_NOT_FOUND)
|
||||
return s;
|
||||
}
|
||||
|
||||
MM_FILE_CACHE_ENTRY* entry = (MM_FILE_CACHE_ENTRY*)0;
|
||||
s = KiFileCacheReserveLoadingPage(file, aligned, &entry);
|
||||
if (s == STATUS_ALREADY_EXISTS)
|
||||
if (s == NTLSTATUS_ALREADY_EXISTS)
|
||||
return KiFileCacheTryHit(file, aligned, outPage, 1);
|
||||
if (!KSUCCESS(s))
|
||||
return s;
|
||||
@@ -923,14 +923,14 @@ static KSTATUS KiFileCacheGetWritablePage(FILE_OBJECT* file,
|
||||
PHYSICAL_ADDRESS frame = MmPfnAllocate(MmPfnUseCleanFileCache);
|
||||
if (!frame) {
|
||||
KiFileCacheCancelLoadingPage(entry);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
void* page = MmPfnToVirtual(frame);
|
||||
if (!page) {
|
||||
(void)MmPfnRelease(frame);
|
||||
KiFileCacheCancelLoadingPage(entry);
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
memset(page, 0, PAGE_SIZE);
|
||||
|
||||
@@ -943,7 +943,7 @@ static KSTATUS KiFileCacheGetWritablePage(FILE_OBJECT* file,
|
||||
s = KiFileCacheCompleteLoadingPage(entry, frame, validBytes, outPage, (uint64_t*)0);
|
||||
if (!KSUCCESS(s))
|
||||
return s;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Marks one cache page dirty and updates its valid byte range.
|
||||
@@ -971,7 +971,7 @@ KSTATUS MmFileCacheGetWritablePage(FILE_OBJECT* file, uint64_t offset,
|
||||
uint64_t fileSizeBefore, int needExistingBytes,
|
||||
MM_FILE_CACHE_PAGE* outPage) {
|
||||
if (!outPage)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
uint64_t aligned = offset & ~(uint64_t)(PAGE_SIZE - 1);
|
||||
return KiFileCacheGetWritablePage(file, aligned, fileSizeBefore, needExistingBytes, outPage);
|
||||
}
|
||||
@@ -994,13 +994,13 @@ KSTATUS MmFileCacheWrite(FILE_OBJECT* file, uint64_t offset, const void* buf,
|
||||
size_t size, uint64_t fileSizeBefore, size_t* writtenOut) {
|
||||
if (writtenOut) *writtenOut = 0;
|
||||
if (!file || (!buf && size) || !writtenOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait())
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
if (!file->Fs || !file->Fs->Write)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
if (size == 0)
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
size_t total = 0;
|
||||
const uint8_t* src = (const uint8_t*)buf;
|
||||
@@ -1028,12 +1028,12 @@ KSTATUS MmFileCacheWrite(FILE_OBJECT* file, uint64_t offset, const void* buf,
|
||||
MM_FILE_CACHE_PAGE page;
|
||||
KSTATUS s = KiFileCacheGetWritablePage(file, aligned, fileSizeBefore, needExisting, &page);
|
||||
if (!KSUCCESS(s))
|
||||
return total ? STATUS_SUCCESS : s;
|
||||
return total ? NTLSTATUS_SUCCESS : s;
|
||||
|
||||
void* dst = MmPfnToVirtual(page.Frame);
|
||||
if (!dst) {
|
||||
MmFileCacheReleasePage(&page);
|
||||
return total ? STATUS_SUCCESS : STATUS_FAILURE;
|
||||
return total ? NTLSTATUS_SUCCESS : NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
memcpy((uint8_t*)dst + inPage, src + total, chunk);
|
||||
@@ -1049,20 +1049,20 @@ KSTATUS MmFileCacheWrite(FILE_OBJECT* file, uint64_t offset, const void* buf,
|
||||
}
|
||||
|
||||
*writtenOut = total;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS MmFileCacheFlushFile(FILE_OBJECT* file) {
|
||||
if (!file)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait())
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFileCacheLock);
|
||||
gFileCacheStats.FlushFileCalls++;
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
|
||||
KSTATUS firstError = STATUS_SUCCESS;
|
||||
KSTATUS firstError = NTLSTATUS_SUCCESS;
|
||||
for (;;) {
|
||||
int didWork = 0;
|
||||
KSTATUS s = KiFileCacheFlushOneDirtyPage(file, &didWork);
|
||||
@@ -1081,15 +1081,15 @@ KSTATUS MmFileCacheFlushFile(FILE_OBJECT* file) {
|
||||
}
|
||||
|
||||
KSTATUS MmFileCacheGetPage(FILE_OBJECT* file, uint64_t offset, MM_FILE_CACHE_PAGE* outPage) {
|
||||
if (!outPage) return STATUS_INVALID_PARAMETER;
|
||||
if (!outPage) return NTLSTATUS_INVALID_PARAMETER;
|
||||
memset(outPage, 0, sizeof(*outPage));
|
||||
if (!file) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (!file) return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
uint64_t aligned = offset & ~(uint64_t)(PAGE_SIZE - 1);
|
||||
KSTATUS s = KiFileCacheTryHit(file, aligned, outPage, 1);
|
||||
if (KSUCCESS(s))
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
return KiFileCacheLoadSpan(file, aligned, KiFileCacheChooseForegroundBatchPages(), outPage, (uint32_t*)0);
|
||||
}
|
||||
|
||||
@@ -1181,9 +1181,9 @@ KSTATUS MmFileCacheDropOnePageForPressure(void) {
|
||||
|
||||
KSTATUS MmFileCacheScheduleReadAhead(FILE_OBJECT* file, uint64_t offset, uint32_t pages) {
|
||||
if (!file || pages == 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait())
|
||||
return STATUS_INVALID_IRQL;
|
||||
return NTLSTATUS_INVALID_IRQL;
|
||||
|
||||
uint32_t requestedPages = pages;
|
||||
if (pages > MM_FILE_CACHE_READAHEAD_MAX_PAGES)
|
||||
@@ -1199,14 +1199,14 @@ KSTATUS MmFileCacheScheduleReadAhead(FILE_OBJECT* file, uint64_t offset, uint32_
|
||||
if (headroom <= MM_FILE_CACHE_READAHEAD_MIN_HEADROOM_PAGES) {
|
||||
gFileCacheStats.ReadAheadPagesThrottled += pages;
|
||||
KeReleaseSpinlock(&gFileCacheLock, cacheFlags);
|
||||
return STATUS_QUEUE_FULL;
|
||||
return NTLSTATUS_QUEUE_FULL;
|
||||
}
|
||||
headroom -= MM_FILE_CACHE_READAHEAD_MIN_HEADROOM_PAGES;
|
||||
if ((uint64_t)pages > headroom)
|
||||
pages = (uint32_t)headroom;
|
||||
KeReleaseSpinlock(&gFileCacheLock, cacheFlags);
|
||||
if (pages == 0)
|
||||
return STATUS_QUEUE_FULL;
|
||||
return NTLSTATUS_QUEUE_FULL;
|
||||
|
||||
KSTATUS s = KiFileCacheEnsureReadAheadStarted();
|
||||
if (!KSUCCESS(s)) {
|
||||
@@ -1218,7 +1218,7 @@ KSTATUS MmFileCacheScheduleReadAhead(FILE_OBJECT* file, uint64_t offset, uint32_
|
||||
(MM_FILE_CACHE_READAHEAD_REQUEST*)MmAllocatePoolTag(sizeof(*req), MM_POOL_TAG('r', 'd', 'a', 'h'));
|
||||
if (!req) {
|
||||
KiFileCacheAddReadAheadStat(&gFileCacheStats.ReadAheadFailures, 1);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
LIST_INIT(&req->Link);
|
||||
@@ -1235,7 +1235,7 @@ KSTATUS MmFileCacheScheduleReadAhead(FILE_OBJECT* file, uint64_t offset, uint32_
|
||||
ObDereferenceObject(&file->Header);
|
||||
MmFreePool(req);
|
||||
KiFileCacheAddReadAheadStat(&gFileCacheStats.ReadAheadPagesThrottled, pages);
|
||||
return STATUS_QUEUE_FULL;
|
||||
return NTLSTATUS_QUEUE_FULL;
|
||||
}
|
||||
uint32_t queueHeadroom = MM_FILE_CACHE_READAHEAD_QUEUE_PAGE_BUDGET - gReadAheadQueuedPages;
|
||||
if (pages > queueHeadroom)
|
||||
@@ -1253,7 +1253,7 @@ KSTATUS MmFileCacheScheduleReadAhead(FILE_OBJECT* file, uint64_t offset, uint32_
|
||||
KeReleaseSpinlock(&gFileCacheLock, flags);
|
||||
|
||||
KeSignalSemaphore(gReadAheadSemaphore);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void MmFileCacheQueryStats(MM_FILE_CACHE_STATS* out) {
|
||||
|
||||
+31
-31
@@ -522,49 +522,49 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmPfnAllocateContiguous(size_t count, MM_
|
||||
__declspec(dllexport) KSTATUS MmPfnRetain(PHYSICAL_ADDRESS frame) {
|
||||
size_t pfn = MmPfnIndex(frame);
|
||||
if (pfn == MM_PFN_INVALID_INDEX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gPfnLock);
|
||||
MM_PFN* entry = &gPfnDatabase[pfn];
|
||||
if (entry->State == MmPfnStateInvalid || entry->State == MmPfnStateFree || entry->State == MmPfnStateZeroed) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (entry->RefCount == UINT16_MAX) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
entry->RefCount++;
|
||||
gPfnRetains++;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases a reference and returns the frame to the free list when the last owner leaves.
|
||||
__declspec(dllexport) KSTATUS MmPfnRelease(PHYSICAL_ADDRESS frame) {
|
||||
size_t pfn = MmPfnIndex(frame);
|
||||
if (pfn == MM_PFN_INVALID_INDEX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gPfnLock);
|
||||
MM_PFN* entry = &gPfnDatabase[pfn];
|
||||
if (entry->State == MmPfnStateInvalid || entry->State == MmPfnStateFree || entry->State == MmPfnStateZeroed) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (entry->PinCount) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
}
|
||||
gPfnReleases++;
|
||||
if (entry->RefCount > 1) {
|
||||
entry->RefCount--;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
if (entry->MappedCount) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
entry->State = MmPfnStateFree;
|
||||
@@ -578,7 +578,7 @@ __declspec(dllexport) KSTATUS MmPfnRelease(PHYSICAL_ADDRESS frame) {
|
||||
gFreeFrames++;
|
||||
gPfnFrees++;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Frees a frame that is expected to have a single owner.
|
||||
@@ -590,119 +590,119 @@ __declspec(dllexport) KSTATUS MmPfnFree(PHYSICAL_ADDRESS frame) {
|
||||
__declspec(dllexport) KSTATUS MmPfnPin(PHYSICAL_ADDRESS frame) {
|
||||
size_t pfn = MmPfnIndex(frame);
|
||||
if (pfn == MM_PFN_INVALID_INDEX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gPfnLock);
|
||||
MM_PFN* entry = &gPfnDatabase[pfn];
|
||||
if (entry->State == MmPfnStateInvalid || entry->State == MmPfnStateFree || entry->State == MmPfnStateZeroed) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (entry->PinCount == UINT16_MAX) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
entry->PinCount++;
|
||||
gPfnPins++;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Removes one pin from a frame.
|
||||
__declspec(dllexport) KSTATUS MmPfnUnpin(PHYSICAL_ADDRESS frame) {
|
||||
size_t pfn = MmPfnIndex(frame);
|
||||
if (pfn == MM_PFN_INVALID_INDEX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gPfnLock);
|
||||
MM_PFN* entry = &gPfnDatabase[pfn];
|
||||
if (!entry->PinCount) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
entry->PinCount--;
|
||||
gPfnUnpins++;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Records that a VAD now maps this frame into a user address space.
|
||||
__declspec(dllexport) KSTATUS MmPfnAddMapping(PHYSICAL_ADDRESS frame) {
|
||||
size_t pfn = MmPfnIndex(frame);
|
||||
if (pfn == MM_PFN_INVALID_INDEX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gPfnLock);
|
||||
MM_PFN* entry = &gPfnDatabase[pfn];
|
||||
if (entry->State == MmPfnStateInvalid || entry->State == MmPfnStateFree || entry->State == MmPfnStateZeroed) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (entry->MappedCount == UINT32_MAX) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
entry->MappedCount++;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Removes one user VAD mapping reference from a frame.
|
||||
__declspec(dllexport) KSTATUS MmPfnRemoveMapping(PHYSICAL_ADDRESS frame) {
|
||||
size_t pfn = MmPfnIndex(frame);
|
||||
if (pfn == MM_PFN_INVALID_INDEX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gPfnLock);
|
||||
MM_PFN* entry = &gPfnDatabase[pfn];
|
||||
if (entry->State == MmPfnStateInvalid || entry->State == MmPfnStateFree || entry->State == MmPfnStateZeroed ||
|
||||
entry->MappedCount == 0) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
entry->MappedCount--;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Moves a clean, unshared frame to standby so pressure can reclaim it later.
|
||||
__declspec(dllexport) KSTATUS MmPfnMoveToStandby(PHYSICAL_ADDRESS frame) {
|
||||
size_t pfn = MmPfnIndex(frame);
|
||||
if (pfn == MM_PFN_INVALID_INDEX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gPfnLock);
|
||||
MM_PFN* entry = &gPfnDatabase[pfn];
|
||||
if (entry->State != MmPfnStateActive || entry->PinCount || entry->MappedCount || entry->RefCount != 1) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
}
|
||||
if (entry->Usage != MmPfnUseCleanFileCache && entry->Usage != MmPfnUseImage) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
entry->State = MmPfnStateStandby;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Reactivates a standby frame after a cache or image lookup found it still useful.
|
||||
__declspec(dllexport) KSTATUS MmPfnActivate(PHYSICAL_ADDRESS frame) {
|
||||
size_t pfn = MmPfnIndex(frame);
|
||||
if (pfn == MM_PFN_INVALID_INDEX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gPfnLock);
|
||||
MM_PFN* entry = &gPfnDatabase[pfn];
|
||||
if (entry->State != MmPfnStateStandby || !entry->RefCount) {
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
entry->State = MmPfnStateActive;
|
||||
KeReleaseSpinlock(&gPfnLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns the number of frames that are immediately available for allocation.
|
||||
|
||||
+23
-23
@@ -208,26 +208,26 @@ __declspec(dllexport) KSTATUS MmPteMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys
|
||||
if (!pdpt) {
|
||||
KiPteStatInc(&gPteStats.MapFailures);
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
PHYSICAL_ADDRESS pdt = KiEnsureTable(pdpt, PDPT_IDX(virt), userFlag);
|
||||
if (!pdt) {
|
||||
KiPteStatInc(&gPteStats.MapFailures);
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
PHYSICAL_ADDRESS pt = KiEnsureTable(pdt, PDT_IDX(virt), userFlag);
|
||||
if (!pt) {
|
||||
KiPteStatInc(&gPteStats.MapFailures);
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
uint64_t* pte = KiPtePtr(pt, PT_IDX(virt));
|
||||
if ((*pte & PAGE_PRESENT) && mode == MmPteMapFailIfPresent) {
|
||||
KiPteStatInc(&gPteStats.MapFailures);
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
}
|
||||
int wasPresent = ((*pte & PAGE_PRESENT) != 0);
|
||||
*pte = phys | flags;
|
||||
@@ -242,7 +242,7 @@ __declspec(dllexport) KSTATUS MmPteMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys
|
||||
KiPteStatInc(&gPteStats.ReplacedMappingFlushes);
|
||||
MmPteFlushKernelAddress(virt);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Removes one 4 KiB leaf PTE from the shared page tables.
|
||||
@@ -254,25 +254,25 @@ __declspec(dllexport) KSTATUS MmPteUnmapPage(uintptr_t virt) {
|
||||
if (!(*e4 & PAGE_PRESENT)) {
|
||||
KiPteStatInc(&gPteStats.UnmapFailures);
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
uint64_t* e3 = KiPtePtr(*e4 & PAGE_FRAME_4K_MASK, PDPT_IDX(virt));
|
||||
if (!(*e3 & PAGE_PRESENT)) {
|
||||
KiPteStatInc(&gPteStats.UnmapFailures);
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
uint64_t* e2 = KiPtePtr(*e3 & PAGE_FRAME_4K_MASK, PDT_IDX(virt));
|
||||
if (!(*e2 & PAGE_PRESENT)) {
|
||||
KiPteStatInc(&gPteStats.UnmapFailures);
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
uint64_t* pte = KiPtePtr(*e2 & PAGE_FRAME_4K_MASK, PT_IDX(virt));
|
||||
if (!(*pte & PAGE_PRESENT)) {
|
||||
KiPteStatInc(&gPteStats.UnmapFailures);
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
*pte = 0;
|
||||
if (gPteStats.CurrentLeafMappings)
|
||||
@@ -280,49 +280,49 @@ __declspec(dllexport) KSTATUS MmPteUnmapPage(uintptr_t virt) {
|
||||
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
MmPteFlushKernelAddress(virt);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Replaces leaf flags for a 4 KiB range and refuses huge pages instead of silently corrupting them.
|
||||
__declspec(dllexport) KSTATUS MmPteProtectRange(uintptr_t virt, size_t size, uint64_t flags) {
|
||||
KiPteStatInc(&gPteStats.ProtectCalls);
|
||||
if (!size) return STATUS_SUCCESS;
|
||||
if (!size) return NTLSTATUS_SUCCESS;
|
||||
|
||||
// The protection operation is page-granular even when callers pass an interior address.
|
||||
uintptr_t base = virt & PAGE_MASK;
|
||||
uintptr_t end = (virt + size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
|
||||
uintptr_t lockFlags = KeAcquireSpinlock(&gPageTableLock);
|
||||
KSTATUS status = STATUS_SUCCESS;
|
||||
KSTATUS status = NTLSTATUS_SUCCESS;
|
||||
uintptr_t flushEnd = base;
|
||||
|
||||
for (uintptr_t va = base; va < end; va += PAGE_SIZE) {
|
||||
uint64_t* e4 = KiPtePtr(gPml4Phys, PML4_IDX(va));
|
||||
if (!(*e4 & PAGE_PRESENT)) {
|
||||
status = STATUS_NOT_FOUND;
|
||||
status = NTLSTATUS_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
uint64_t* e3 = KiPtePtr(*e4 & PAGE_FRAME_4K_MASK, PDPT_IDX(va));
|
||||
if (!(*e3 & PAGE_PRESENT)) {
|
||||
status = STATUS_NOT_FOUND;
|
||||
status = NTLSTATUS_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
if (*e3 & PAGE_PS) {
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
status = NTLSTATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
uint64_t* e2 = KiPtePtr(*e3 & PAGE_FRAME_4K_MASK, PDT_IDX(va));
|
||||
if (!(*e2 & PAGE_PRESENT)) {
|
||||
status = STATUS_NOT_FOUND;
|
||||
status = NTLSTATUS_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
if (*e2 & PAGE_PS) {
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
status = NTLSTATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
uint64_t* pte = KiPtePtr(*e2 & PAGE_FRAME_4K_MASK, PT_IDX(va));
|
||||
if (!(*pte & PAGE_PRESENT)) {
|
||||
status = STATUS_NOT_FOUND;
|
||||
status = NTLSTATUS_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -474,10 +474,10 @@ KSTATUS MmPteQueryPageFor(MM_PTE_QUERY_PURPOSE purpose,
|
||||
if (!gPml4Phys) {
|
||||
KiPteStatInc(&gPteStats.QueryFailures);
|
||||
KiPteStatInc(&gPteStats.QueryFailuresByPurpose[purpose]);
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
KSTATUS status = STATUS_NOT_FOUND;
|
||||
KSTATUS status = NTLSTATUS_NOT_FOUND;
|
||||
uintptr_t lockFlags = KeAcquireSpinlock(&gPageTableLock);
|
||||
|
||||
uint64_t* pml4 = (uint64_t*)KiPhysToVirt(gPml4Phys);
|
||||
@@ -504,7 +504,7 @@ KSTATUS MmPteQueryPageFor(MM_PTE_QUERY_PURPOSE purpose,
|
||||
if (!effectiveUser) flags &= ~PAGE_USER;
|
||||
*flagsOut = flags;
|
||||
}
|
||||
status = STATUS_SUCCESS;
|
||||
status = NTLSTATUS_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -524,7 +524,7 @@ KSTATUS MmPteQueryPageFor(MM_PTE_QUERY_PURPOSE purpose,
|
||||
if (!effectiveUser) flags &= ~PAGE_USER;
|
||||
*flagsOut = flags;
|
||||
}
|
||||
status = STATUS_SUCCESS;
|
||||
status = NTLSTATUS_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ KSTATUS MmPteQueryPageFor(MM_PTE_QUERY_PURPOSE purpose,
|
||||
if (!effectiveUser) flags &= ~PAGE_USER;
|
||||
*flagsOut = flags;
|
||||
}
|
||||
status = STATUS_SUCCESS;
|
||||
status = NTLSTATUS_SUCCESS;
|
||||
|
||||
out:
|
||||
if (!KSUCCESS(status)) {
|
||||
|
||||
+21
-21
@@ -42,13 +42,13 @@ static void KiSwapSetSlot(uint32_t slot, int used) {
|
||||
|
||||
// Allocates one pagefile slot.
|
||||
static KSTATUS KiSwapAllocateSlot(uint32_t* slotOut) {
|
||||
if (!slotOut) return STATUS_INVALID_PARAMETER;
|
||||
if (!slotOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
*slotOut = 0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gSwap.Lock);
|
||||
if (!gSwap.Enabled || !gSwap.Bitmap || !gSwap.SlotCount) {
|
||||
KeReleaseSpinlock(&gSwap.Lock, flags);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
for (uint32_t slot = 0; slot < gSwap.SlotCount; ++slot) {
|
||||
@@ -60,26 +60,26 @@ static KSTATUS KiSwapAllocateSlot(uint32_t* slotOut) {
|
||||
gSwap.Stats.SlotAllocations++;
|
||||
*slotOut = slot;
|
||||
KeReleaseSpinlock(&gSwap.Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
gSwap.Stats.SlotAllocationFailures++;
|
||||
KeReleaseSpinlock(&gSwap.Lock, flags);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
// Initializes the fixed pagefile backend.
|
||||
KSTATUS MmSwapInitialize(SYS_STRING_VIEW path, uint64_t sizeBytes) {
|
||||
if (!path.Data || !path.Length || sizeBytes < PAGE_SIZE)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (sizeBytes & (PAGE_SIZE - 1))
|
||||
sizeBytes = (sizeBytes + PAGE_SIZE - 1) & ~(uint64_t)(PAGE_SIZE - 1);
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gSwap.Lock);
|
||||
if (gSwap.Enabled) {
|
||||
KeReleaseSpinlock(&gSwap.Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
KeReleaseSpinlock(&gSwap.Lock, flags);
|
||||
|
||||
@@ -105,7 +105,7 @@ KSTATUS MmSwapInitialize(SYS_STRING_VIEW path, uint64_t sizeBytes) {
|
||||
uint64_t slots64 = sizeBytes / PAGE_SIZE;
|
||||
if (!slots64 || slots64 > 0xFFFFFFFFull) {
|
||||
IoCloseFile(file);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uint32_t slotCount = (uint32_t)slots64;
|
||||
@@ -113,7 +113,7 @@ KSTATUS MmSwapInitialize(SYS_STRING_VIEW path, uint64_t sizeBytes) {
|
||||
uint8_t* bitmap = (uint8_t*)MmAllocatePoolTag(bitmapBytes, MM_POOL_TAG('s', 'w', 'a', 'p'));
|
||||
if (!bitmap) {
|
||||
IoCloseFile(file);
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
memset(bitmap, 0, bitmapBytes);
|
||||
|
||||
@@ -122,7 +122,7 @@ KSTATUS MmSwapInitialize(SYS_STRING_VIEW path, uint64_t sizeBytes) {
|
||||
KeReleaseSpinlock(&gSwap.Lock, flags);
|
||||
MmFreePool(bitmap);
|
||||
IoCloseFile(file);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
gSwap.File = file;
|
||||
@@ -141,7 +141,7 @@ KSTATUS MmSwapInitialize(SYS_STRING_VIEW path, uint64_t sizeBytes) {
|
||||
slotCount,
|
||||
(unsigned long long)(sizeBytes / 1024),
|
||||
path);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns whether swap is available for pageout.
|
||||
@@ -152,10 +152,10 @@ int MmSwapIsEnabled(void) {
|
||||
// Writes one physical page to a newly allocated swap slot.
|
||||
KSTATUS MmSwapPageOut(PHYSICAL_ADDRESS frame, uint32_t* slotOut) {
|
||||
if (!slotOut || !frame)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*slotOut = 0;
|
||||
if (!gSwap.Enabled || !gSwap.File)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
uint32_t slot = 0;
|
||||
KSTATUS s = KiSwapAllocateSlot(&slot);
|
||||
@@ -168,7 +168,7 @@ KSTATUS MmSwapPageOut(PHYSICAL_ADDRESS frame, uint32_t* slotOut) {
|
||||
if (!page) {
|
||||
MmSwapFreeSlot(slot);
|
||||
gSwap.Stats.PageOutFailures++;
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
size_t written = 0;
|
||||
@@ -176,44 +176,44 @@ KSTATUS MmSwapPageOut(PHYSICAL_ADDRESS frame, uint32_t* slotOut) {
|
||||
if (!KSUCCESS(s) || written != PAGE_SIZE) {
|
||||
MmSwapFreeSlot(slot);
|
||||
gSwap.Stats.PageOutFailures++;
|
||||
return KSUCCESS(s) ? STATUS_DEVICE_ERROR : s;
|
||||
return KSUCCESS(s) ? NTLSTATUS_DEVICE_ERROR : s;
|
||||
}
|
||||
|
||||
gSwap.Stats.PageOuts++;
|
||||
*slotOut = slot;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Reads one swap slot into an already allocated physical page.
|
||||
KSTATUS MmSwapPageIn(uint32_t slot, PHYSICAL_ADDRESS frame) {
|
||||
if (!frame)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!gSwap.Enabled || !gSwap.File)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gSwap.Lock);
|
||||
int valid = slot < gSwap.SlotCount && KiSwapTestSlot(slot);
|
||||
KeReleaseSpinlock(&gSwap.Lock, flags);
|
||||
if (!valid) {
|
||||
gSwap.Stats.PageInFailures++;
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
void* page = MmPfnToVirtual(frame);
|
||||
if (!page) {
|
||||
gSwap.Stats.PageInFailures++;
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
size_t read = 0;
|
||||
KSTATUS s = IoReadFileAt(gSwap.File, (uint64_t)slot * PAGE_SIZE, page, PAGE_SIZE, &read);
|
||||
if (!KSUCCESS(s) || read != PAGE_SIZE) {
|
||||
gSwap.Stats.PageInFailures++;
|
||||
return KSUCCESS(s) ? STATUS_DEVICE_ERROR : s;
|
||||
return KSUCCESS(s) ? NTLSTATUS_DEVICE_ERROR : s;
|
||||
}
|
||||
|
||||
gSwap.Stats.PageIns++;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases a swap slot after the owning VAD page no longer references it.
|
||||
|
||||
+188
-188
File diff suppressed because it is too large.
Load diff
+12
-12
@@ -56,18 +56,18 @@ static void NetLogHardwareAddress(const NET_DEVICE* device) {
|
||||
// Implements the net Register Device operation.
|
||||
__declspec(dllexport) KSTATUS NetRegisterDevice(NET_DEVICE* device) {
|
||||
if (!device || !device->SendFrame)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (device->HardwareAddressLength > NET_HWADDR_MAX)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gNetLock);
|
||||
if (NetIsDeviceRegisteredLocked(device)) {
|
||||
KeReleaseSpinlock(&gNetLock, flags);
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
}
|
||||
if (gNetDeviceCount >= NET_MAX_DEVICES) {
|
||||
KeReleaseSpinlock(&gNetLock, flags);
|
||||
return STATUS_QUEUE_FULL;
|
||||
return NTLSTATUS_QUEUE_FULL;
|
||||
}
|
||||
|
||||
uint32_t index = gNetDeviceCount;
|
||||
@@ -93,7 +93,7 @@ __declspec(dllexport) KSTATUS NetRegisterDevice(NET_DEVICE* device) {
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the net Get Device Count operation.
|
||||
@@ -115,16 +115,16 @@ __declspec(dllexport) NET_DEVICE* NetGetDevice(uint32_t index) {
|
||||
__declspec(dllexport) KSTATUS NetGetDeviceStats(uint32_t index,
|
||||
NET_DEVICE_STATS* stats) {
|
||||
if (!stats)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
NET_DEVICE* device = NetGetDevice(index);
|
||||
if (!device)
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gNetLock);
|
||||
memcpy(stats, &device->Stats, sizeof(*stats));
|
||||
KeReleaseSpinlock(&gNetLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS NetSendFrame(uint32_t index,
|
||||
@@ -132,11 +132,11 @@ __declspec(dllexport) KSTATUS NetSendFrame(uint32_t index,
|
||||
size_t length) {
|
||||
NET_DEVICE* device = NetGetDevice(index);
|
||||
if (!device || !device->SendFrame)
|
||||
return STATUS_NOT_FOUND;
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
if (!frame || length < NET_ETHERNET_HEADER_LENGTH)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (length > (size_t)device->Mtu + NET_ETHERNET_HEADER_LENGTH)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
KSTATUS st = device->SendFrame(device, frame, length);
|
||||
uintptr_t flags = KeAcquireSpinlock(&gNetLock);
|
||||
@@ -168,7 +168,7 @@ __declspec(dllexport) void NetReceiveFrame(NET_DEVICE* device,
|
||||
KeReleaseSpinlock(&gNetLock, flags);
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NetGetStackProvider();
|
||||
KSTATUS rxStatus = STATUS_NOT_SUPPORTED;
|
||||
KSTATUS rxStatus = NTLSTATUS_NOT_SUPPORTED;
|
||||
if (provider && provider->ReceiveFrame)
|
||||
rxStatus = provider->ReceiveFrame(device, frame, length);
|
||||
|
||||
|
||||
+46
-46
@@ -51,11 +51,11 @@ static void NetIrpStatsComplete(KSTATUS status, bool asynchronous) {
|
||||
else
|
||||
gNetIrpStats.CompletedSynchronously++;
|
||||
|
||||
if (status == STATUS_CANCELLED)
|
||||
if (status == NTLSTATUS_CANCELLED)
|
||||
gNetIrpStats.Cancelled++;
|
||||
else if (status == STATUS_WOULD_BLOCK)
|
||||
else if (status == NTLSTATUS_WOULD_BLOCK)
|
||||
gNetIrpStats.WouldBlock++;
|
||||
else if (status == STATUS_TIMEOUT)
|
||||
else if (status == NTLSTATUS_TIMEOUT)
|
||||
gNetIrpStats.Timeout++;
|
||||
else if (KFAILED(status))
|
||||
gNetIrpStats.Failed++;
|
||||
@@ -193,7 +193,7 @@ static void NetAsyncSocketRequestCleanup(IO_ASYNC_REQUEST_OBJECT* async, void* c
|
||||
static KSTATUS NetCancelAsyncSocketRequest(IO_ASYNC_REQUEST_OBJECT* async, void* context) {
|
||||
(void)context;
|
||||
if (!async)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
NetIrpStatsCancelRequested();
|
||||
|
||||
@@ -206,19 +206,19 @@ static KSTATUS NetCancelAsyncSocketRequest(IO_ASYNC_REQUEST_OBJECT* async, void*
|
||||
IoAsyncRequestSetState(async, IoAsyncRequestCancelled);
|
||||
KeReleaseSpinlock(&gAsyncSocketQueueLock, flags);
|
||||
|
||||
IoCompleteAsyncRequest(async, STATUS_CANCELLED, 0);
|
||||
IoCompleteAsyncRequest(async, NTLSTATUS_CANCELLED, 0);
|
||||
ObDereferenceObject(&async->Header);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (state == IoAsyncRequestRunning) {
|
||||
IoAsyncRequestRequestCancel(async);
|
||||
KeReleaseSpinlock(&gAsyncSocketQueueLock, flags);
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_PENDING;
|
||||
}
|
||||
|
||||
KeReleaseSpinlock(&gAsyncSocketQueueLock, flags);
|
||||
return STATUS_OBJECT_DEAD;
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
}
|
||||
|
||||
// Removes one queued async socket request for the worker.
|
||||
@@ -256,7 +256,7 @@ static size_t NetAsyncSocketPublishAddress(NET_ASYNC_SOCKET_REQUEST_OBJECT* req,
|
||||
static void NetAsyncSocketExecute(NET_ASYNC_SOCKET_REQUEST_OBJECT* req,
|
||||
KSTATUS* statusOut,
|
||||
size_t* informationOut) {
|
||||
KSTATUS status = STATUS_INVALID_PARAMETER;
|
||||
KSTATUS status = NTLSTATUS_INVALID_PARAMETER;
|
||||
size_t information = 0;
|
||||
|
||||
if (!req || !statusOut || !informationOut)
|
||||
@@ -351,7 +351,7 @@ static void NetAsyncSocketExecute(NET_ASYNC_SOCKET_REQUEST_OBJECT* req,
|
||||
status = NetSocketGetOption(req->Socket, req->Option, req->OptionValue, req->OptionValueSize, &actual);
|
||||
if (KSUCCESS(status) && actual && req->UserOptionValue)
|
||||
memcpy(req->UserOptionValue, req->OptionValue, actual);
|
||||
if ((KSUCCESS(status) || status == STATUS_BUFFER_TOO_SMALL) && req->OptionActualSizeOut)
|
||||
if ((KSUCCESS(status) || status == NTLSTATUS_BUFFER_TOO_SMALL) && req->OptionActualSizeOut)
|
||||
*req->OptionActualSizeOut = actual;
|
||||
information = actual;
|
||||
break;
|
||||
@@ -367,7 +367,7 @@ static void NetAsyncSocketExecute(NET_ASYNC_SOCKET_REQUEST_OBJECT* req,
|
||||
}
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
status = NTLSTATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ static void NetAsyncSocketWorker(void* arg) {
|
||||
if (!req)
|
||||
continue;
|
||||
|
||||
KSTATUS status = STATUS_CANCELLED;
|
||||
KSTATUS status = NTLSTATUS_CANCELLED;
|
||||
size_t information = 0;
|
||||
if (!IoAsyncRequestIsCancelRequested(&req->Async) &&
|
||||
IoAsyncRequestGetState(&req->Async) != IoAsyncRequestCancelled) {
|
||||
@@ -409,13 +409,13 @@ static KSTATUS NetEnsureAsyncSocketWorkerStarted(void) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gAsyncSocketInitLock);
|
||||
if (gAsyncSocketInitState == 2) {
|
||||
KeReleaseSpinlock(&gAsyncSocketInitLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
if (gAsyncSocketInitState == 1) {
|
||||
KeReleaseSpinlock(&gAsyncSocketInitLock, flags);
|
||||
while (gAsyncSocketInitState == 1)
|
||||
KeYield();
|
||||
return (gAsyncSocketInitState == 2) ? STATUS_SUCCESS : STATUS_FAILURE;
|
||||
return (gAsyncSocketInitState == 2) ? NTLSTATUS_SUCCESS : NTLSTATUS_FAILURE;
|
||||
}
|
||||
|
||||
gAsyncSocketInitState = 1;
|
||||
@@ -445,7 +445,7 @@ KSTATUS NetSocketSubmitAsyncKernel(const NET_ASYNC_SOCKET_SUBMIT* submit,
|
||||
if (requestOut)
|
||||
*requestOut = (NET_ASYNC_SOCKET_REQUEST_OBJECT*)0;
|
||||
if (!submit || !submit->OwnerProcess || !submit->Socket || !submit->Iosb)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = NetEnsureAsyncSocketWorkerStarted();
|
||||
if (!KSUCCESS(status))
|
||||
@@ -509,7 +509,7 @@ KSTATUS NetSocketSubmitAsyncKernel(const NET_ASYNC_SOCKET_SUBMIT* submit,
|
||||
*requestOut = req;
|
||||
else
|
||||
ObDereferenceObject(&req->Async.Header);
|
||||
return STATUS_PENDING;
|
||||
return NTLSTATUS_PENDING;
|
||||
}
|
||||
|
||||
// Returns the object header embedded in a socket async request.
|
||||
@@ -522,12 +522,12 @@ static KSTATUS NetSubmitSocketIrp(const NET_STACK_PROVIDER* provider,
|
||||
NET_SOCKET_IRP_REQUEST* request,
|
||||
IO_ASYNC_REQUEST_OBJECT* async) {
|
||||
if (!provider || !provider->StackDevice || !request)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->Size != sizeof(*request))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (request->Operation == NetSocketIrpInvalid ||
|
||||
request->Operation >= NetSocketIrpOperationCount)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
request->CancelRequested = async ? &async->CancelRequested : (volatile uint8_t*)0;
|
||||
|
||||
@@ -551,7 +551,7 @@ static KSTATUS NetSubmitSocketIrp(const NET_STACK_PROVIDER* provider,
|
||||
st = IoSubmitIrp(provider->StackDevice, &irp);
|
||||
|
||||
bool asynchronous = false;
|
||||
if (st == STATUS_PENDING) {
|
||||
if (st == NTLSTATUS_PENDING) {
|
||||
asynchronous = true;
|
||||
NetIrpStatsPending();
|
||||
(void)KeWaitForEvent(event, 0);
|
||||
@@ -594,11 +594,11 @@ static KSTATUS NetSocketAllocate(const NET_STACK_PROVIDER* provider,
|
||||
uint32_t protocol,
|
||||
SOCKET_OBJECT** out) {
|
||||
if (!provider || !providerSocket || !out)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
SOCKET_OBJECT* socket = (SOCKET_OBJECT*)ObAllocateObject(ObjectTypeSocket, sizeof(SOCKET_OBJECT));
|
||||
if (!socket)
|
||||
return STATUS_NO_MEMORY;
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
socket->Header.Destroy = NetSocketDestroy;
|
||||
socket->Provider = provider;
|
||||
@@ -607,7 +607,7 @@ static KSTATUS NetSocketAllocate(const NET_STACK_PROVIDER* provider,
|
||||
socket->Type = type;
|
||||
socket->Protocol = protocol;
|
||||
*out = socket;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns the provider and provider-private state behind a live socket object.
|
||||
@@ -615,24 +615,24 @@ static KSTATUS NetSocketGetProviderSocket(SOCKET_OBJECT* socket,
|
||||
const NET_STACK_PROVIDER** providerOut,
|
||||
void** providerSocketOut) {
|
||||
if (!socket || !providerOut || !providerSocketOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!socket->Provider || !socket->ProviderSocket)
|
||||
return STATUS_OBJECT_DEAD;
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
|
||||
*providerOut = socket->Provider;
|
||||
*providerSocketOut = socket->ProviderSocket;
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Creates a socket by submitting a create request to the active stack device.
|
||||
KSTATUS NetSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, SOCKET_OBJECT** out) {
|
||||
if (!out)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*out = NULL;
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NetGetStackProvider();
|
||||
if (!provider)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
void* providerSocket = NULL;
|
||||
NET_SOCKET_IRP_REQUEST request;
|
||||
@@ -648,7 +648,7 @@ KSTATUS NetSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, SOCKE
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
if (!providerSocket)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
st = NetSocketAllocate(provider, providerSocket, domain, type, protocol, out);
|
||||
if (!KSUCCESS(st))
|
||||
@@ -696,7 +696,7 @@ KSTATUS NetSocketAccept(SOCKET_OBJECT* socket, SOCKET_OBJECT** acceptedOut,
|
||||
SYS_SOCKET_ADDRESS_K* remoteOut,
|
||||
IO_ASYNC_REQUEST_OBJECT* async) {
|
||||
if (!acceptedOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*acceptedOut = NULL;
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NULL;
|
||||
@@ -718,7 +718,7 @@ KSTATUS NetSocketAccept(SOCKET_OBJECT* socket, SOCKET_OBJECT** acceptedOut,
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
if (!acceptedProviderSocket)
|
||||
return STATUS_FAILURE;
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
st = NetSocketAllocate(provider,
|
||||
acceptedProviderSocket,
|
||||
@@ -757,9 +757,9 @@ KSTATUS NetSocketSend(SOCKET_OBJECT* socket, const void* buffer, size_t length,
|
||||
if (sentOut)
|
||||
*sentOut = 0;
|
||||
if (!buffer && length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (length > NET_SOCKET_IO_MAX_BYTES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NULL;
|
||||
void* providerSocket = NULL;
|
||||
@@ -786,9 +786,9 @@ KSTATUS NetSocketReceive(SOCKET_OBJECT* socket, void* buffer, size_t length,
|
||||
if (receivedOut)
|
||||
*receivedOut = 0;
|
||||
if (!buffer && length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (length > NET_SOCKET_IO_MAX_BYTES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NULL;
|
||||
void* providerSocket = NULL;
|
||||
@@ -815,13 +815,13 @@ KSTATUS NetSocketSendTo(SOCKET_OBJECT* socket, const void* buffer, size_t length
|
||||
if (sentOut)
|
||||
*sentOut = 0;
|
||||
if (!buffer && length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (socket && socket->Type == SYS_SOCK_DGRAM && length > NET_SOCKET_UDP_MAX_BYTES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (socket && socket->Type == SYS_SOCK_RAW && length > NET_SOCKET_RAW_MAX_BYTES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (socket && socket->Type != SYS_SOCK_DGRAM && socket->Type != SYS_SOCK_RAW)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NULL;
|
||||
void* providerSocket = NULL;
|
||||
@@ -850,13 +850,13 @@ KSTATUS NetSocketReceiveFrom(SOCKET_OBJECT* socket, void* buffer, size_t length,
|
||||
if (receivedOut)
|
||||
*receivedOut = 0;
|
||||
if (!buffer && length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (socket && socket->Type == SYS_SOCK_DGRAM && length > NET_SOCKET_UDP_MAX_BYTES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (socket && socket->Type == SYS_SOCK_RAW && length > NET_SOCKET_RAW_MAX_BYTES)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (socket && socket->Type != SYS_SOCK_DGRAM && socket->Type != SYS_SOCK_RAW)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NULL;
|
||||
void* providerSocket = NULL;
|
||||
@@ -937,7 +937,7 @@ KSTATUS NetSocketGetOption(SOCKET_OBJECT* socket, uint32_t option, void* value,
|
||||
// Polls socket readiness through the stack device IRP path.
|
||||
KSTATUS NetSocketPoll(SOCKET_OBJECT* socket, uint32_t events, uint32_t* returnedEventsOut) {
|
||||
if (!returnedEventsOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*returnedEventsOut = 0;
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NULL;
|
||||
@@ -959,11 +959,11 @@ KSTATUS NetSocketPoll(SOCKET_OBJECT* socket, uint32_t events, uint32_t* returned
|
||||
// Resolves a host name through the stack device IRP path.
|
||||
KSTATUS NetResolveHost(const char* name, uint32_t family, SYS_SOCKET_ADDRESS_K* addressOut) {
|
||||
if (!name || !addressOut)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
const NET_STACK_PROVIDER* provider = NetGetStackProvider();
|
||||
if (!provider)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
NET_SOCKET_IRP_REQUEST request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
|
||||
@@ -14,16 +14,16 @@ static SPINLOCK gNetStackLock = SPINLOCK_INIT;
|
||||
// Implements the net Validate Stack Provider operation.
|
||||
static KSTATUS NetValidateStackProvider(const NET_STACK_PROVIDER* p) {
|
||||
if (!p || p->Version != NET_STACK_PROVIDER_VERSION || !p->Name)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
if (!p->StackDevice || !p->AttachDevice || !p->ReceiveFrame)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
if (!p->StackDevice->DriverObject ||
|
||||
!p->StackDevice->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL])
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the net Register Stack Provider operation.
|
||||
@@ -35,7 +35,7 @@ __declspec(dllexport) KSTATUS NetRegisterStackProvider(const NET_STACK_PROVIDER*
|
||||
uintptr_t flags = KeAcquireSpinlock(&gNetStackLock);
|
||||
if (gNetStackProvider) {
|
||||
KeReleaseSpinlock(&gNetStackLock, flags);
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
return NTLSTATUS_ALREADY_EXISTS;
|
||||
}
|
||||
gNetStackProvider = provider;
|
||||
KeReleaseSpinlock(&gNetStackLock, flags);
|
||||
@@ -56,7 +56,7 @@ __declspec(dllexport) KSTATUS NetRegisterStackProvider(const NET_STACK_PROVIDER*
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the net Get Stack Provider operation.
|
||||
|
||||
Reference in new issue
Block a user