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:
maksw committed 2026-06-27 20:38:43 +02:00
1 parent 1f5477cf66
commit b7fcfce6f7
140 files changed
+7649 -3943

No files matched your search

+3 -3
View File
@@ -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.
+5 -5
View File
@@ -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.
+6 -6
View File
@@ -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.
+4 -4
View File
@@ -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);
+2 -2
View File
@@ -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.
+2 -2
View File
@@ -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;
}
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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,
+26
View File
@@ -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);
+21
View File
@@ -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);
+9
View File
@@ -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
+126 -121
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+801
View File
@@ -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
View File
@@ -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();
}
+9 -9
View File
@@ -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
View File
@@ -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;
}
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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++;
+7 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+4 -4
View File
@@ -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
View File
@@ -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)
+7 -7
View File
@@ -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;
}
+7 -7
View File
@@ -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.
+4 -4
View File
@@ -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;
}
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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, &registeredBase);
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
View File
@@ -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(&section->Lock);
PHYSICAL_ADDRESS existing = section->Frames[pageIndex];
KeReleaseSpinlock(&section->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(&section->Lock, flags);
MmPfnFree(frame);
return STATUS_SUCCESS;
return NTLSTATUS_SUCCESS;
}
section->Frames[pageIndex] = frame;
KeReleaseSpinlock(&section->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(&section->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(&section->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(&section->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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+12 -12
View File
@@ -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
View File
@@ -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));
+6 -6
View File
@@ -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.