remove weird double spaces, remove /EXPORT from build.bat in favor of __declspec(dllexport)
This commit is contained in:
1 parent
9fa2a7e0db
commit
83d48e09bb
41 files changed
+156
-170
No files matched your search
@@ -17,7 +17,7 @@ static VOLUME_ENTRY gVolumes[MAX_DRIVES];
|
||||
// ---------------------------------------------------------------------------
|
||||
// Registration
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS IoRegisterFilesystem(uint8_t volumeIndex,
|
||||
__declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t volumeIndex,
|
||||
IO_FILESYSTEM *fs,
|
||||
const IO_VOLUME_PARAMS *vol) {
|
||||
if (volumeIndex >= MAX_DRIVES || !fs || !vol)
|
||||
@@ -54,7 +54,7 @@ static void FileDestroy(OBJECT* obj) {
|
||||
// ---------------------------------------------------------------------------
|
||||
// IoOpenFile
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out) {
|
||||
__declspec(dllexport) KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out) {
|
||||
if (!path || !out) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
const char* relPath;
|
||||
@@ -83,7 +83,7 @@ KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out) {
|
||||
// ---------------------------------------------------------------------------
|
||||
// IoReadFile - sequential read at current offset
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead) {
|
||||
__declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead) {
|
||||
if (!file || !buf) return STATUS_INVALID_PARAMETER;
|
||||
if (file->Offset >= file->Size) { *bytesRead = 0; return STATUS_SUCCESS; }
|
||||
|
||||
@@ -98,16 +98,16 @@ KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) {
|
||||
__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) {
|
||||
if (!file) return STATUS_INVALID_PARAMETER;
|
||||
file->Offset = offset;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t IoGetFileSize(FILE_OBJECT* file) {
|
||||
__declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file) {
|
||||
return file ? file->Size : 0;
|
||||
}
|
||||
|
||||
void IoCloseFile(FILE_OBJECT* file) {
|
||||
__declspec(dllexport) void IoCloseFile(FILE_OBJECT* file) {
|
||||
if (file) ObDereferenceObject(&file->Header);
|
||||
}
|
||||
@@ -53,14 +53,14 @@ typedef struct IO_VOLUME_PARAMS {
|
||||
// Registration - called by fat32.sys from DriverEntry
|
||||
// ---------------------------------------------------------------------------
|
||||
// driveIndex matches the index passed to IoRegisterDisk.
|
||||
KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol);
|
||||
__declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel-side API
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out);
|
||||
KSTATUS IoReadFile(FILE_OBJECT* file, void* buf,
|
||||
__declspec(dllexport) KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out);
|
||||
__declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf,
|
||||
size_t size, size_t* bytesRead);
|
||||
KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset);
|
||||
uint64_t IoGetFileSize(FILE_OBJECT* file);
|
||||
void IoCloseFile(FILE_OBJECT* file);
|
||||
__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset);
|
||||
__declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file);
|
||||
__declspec(dllexport) void IoCloseFile(FILE_OBJECT* file);
|
||||
@@ -14,7 +14,7 @@ void kernel_putchar(char c) {
|
||||
PrintChar(c, 0x00FF00, 0x000000);
|
||||
}
|
||||
|
||||
void DbgPrint(const char* fmt, ...) {
|
||||
__declspec(dllexport) void DbgPrint(const char* fmt, ...) {
|
||||
if (!gDebugEnabled) return;
|
||||
|
||||
static SPINLOCK sl = {0};
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), int v);
|
||||
void DbgPrint(const char* fmt, ...);
|
||||
__declspec(dllexport) void DbgPrint(const char* fmt, ...);
|
||||
|
||||
#endif // KE_DEBUG_H
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
static void EventDestroy(OBJECT* obj) { (void)obj; }
|
||||
|
||||
KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) {
|
||||
__declspec(dllexport) KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
EVENT* e = (EVENT *)ObAllocateObject(ObjectTypeEvent, sizeof(EVENT));
|
||||
if (!e) return STATUS_NO_MEMORY;
|
||||
@@ -20,7 +20,7 @@ KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void KeSignalEvent(EVENT* event) {
|
||||
__declspec(dllexport) void KeSignalEvent(EVENT* event) {
|
||||
if (!event) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
|
||||
@@ -46,14 +46,14 @@ void KeSignalEvent(EVENT* event) {
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
}
|
||||
|
||||
void KeClearEvent(EVENT* event) {
|
||||
__declspec(dllexport) void KeClearEvent(EVENT* event) {
|
||||
if (!event) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
event->Signaled = 0;
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
}
|
||||
|
||||
KSTATUS KeWaitForEvent(EVENT* event) {
|
||||
__declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event) {
|
||||
if (!event) return STATUS_INVALID_PARAMETER;
|
||||
THREAD* self = KeCurrentThread();
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ typedef struct EVENT {
|
||||
LIST_ENTRY WaitList;
|
||||
} EVENT;
|
||||
|
||||
KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out);
|
||||
void KeSignalEvent(EVENT* event);
|
||||
void KeClearEvent(EVENT* event);
|
||||
KSTATUS KeWaitForEvent(EVENT* event);
|
||||
__declspec(dllexport) KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out);
|
||||
__declspec(dllexport) void KeSignalEvent(EVENT* event);
|
||||
__declspec(dllexport) void KeClearEvent(EVENT* event);
|
||||
__declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event);
|
||||
@@ -1,7 +1,7 @@
|
||||
// ke_irp.c - I/O Request Packet dispatch and queue helpers
|
||||
//
|
||||
// This file lives in the kernel layer and is the ONLY place that bridges the
|
||||
// IRP abstraction to kernel sync objects. All calls to KeEventCreate,
|
||||
// IRP abstraction to kernel sync objects. All calls to KeEventCreate,
|
||||
// KeSignalEvent, KeWaitForEvent, KeSignalSemaphore, and ObDereferenceObject
|
||||
// are confined here; hal_disk.c and io_driver.h remain free of those symbols.
|
||||
//
|
||||
@@ -26,13 +26,13 @@
|
||||
// ke_irp.h can avoid including ke_semaphore.h, keeping the header safe
|
||||
// for inclusion from the HAL layer.
|
||||
|
||||
void IrpQueueInit(IRP_QUEUE *q, struct SEMAPHORE *sem) {
|
||||
__declspec(dllexport) void IrpQueueInit(IRP_QUEUE *q, struct SEMAPHORE *sem) {
|
||||
q->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
q->Semaphore = sem;
|
||||
LIST_INIT(&q->Head);
|
||||
}
|
||||
|
||||
void IrpQueueEnqueue(IRP_QUEUE *q, IRP *irp) {
|
||||
__declspec(dllexport) void IrpQueueEnqueue(IRP_QUEUE *q, IRP *irp) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&q->Lock);
|
||||
if (irp->Flags & IRP_FLAG_PRIORITY)
|
||||
ListInsertHead(&q->Head, &irp->Link);
|
||||
@@ -43,7 +43,7 @@ void IrpQueueEnqueue(IRP_QUEUE *q, IRP *irp) {
|
||||
KeSignalSemaphore((SEMAPHORE *)q->Semaphore);
|
||||
}
|
||||
|
||||
IRP *IrpQueueDequeue(IRP_QUEUE *q) {
|
||||
__declspec(dllexport) IRP *IrpQueueDequeue(IRP_QUEUE *q) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&q->Lock);
|
||||
LIST_ENTRY *node = ListPopHead(&q->Head);
|
||||
KeReleaseSpinlock(&q->Lock, flags);
|
||||
@@ -58,7 +58,7 @@ IRP *IrpQueueDequeue(IRP_QUEUE *q) {
|
||||
// If the dispatch ran inline (sync fallback), we fire the completion hooks
|
||||
// here in the kernel layer where we can legally call KeSignalEvent.
|
||||
|
||||
KSTATUS IoSubmitIrp(IRP *irp) {
|
||||
__declspec(dllexport) KSTATUS IoSubmitIrp(IRP *irp) {
|
||||
if (!irp) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS st = HalDiskDispatch(irp->DriveIndex, irp);
|
||||
@@ -84,10 +84,10 @@ KSTATUS IoSubmitIrp(IRP *irp) {
|
||||
// IoSubmitIrpSync
|
||||
// -------------------------------------------------------------------------
|
||||
// Creates a stack-allocated auto-reset event, attaches it to the IRP,
|
||||
// submits, and blocks. Callers that already provided a CompletionEvent
|
||||
// submits, and blocks. Callers that already provided a CompletionEvent
|
||||
// should use IoSubmitIrp() directly and wait on their own event instead.
|
||||
|
||||
KSTATUS IoSubmitIrpSync(IRP *irp) {
|
||||
__declspec(dllexport) KSTATUS IoSubmitIrpSync(IRP *irp) {
|
||||
if (!irp) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
EVENT *ev = (EVENT *)0;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// This header intentionally includes only ke_list.h, ke_spinlock.h, and
|
||||
// ke_status.h — all of which are pure-inline / macro headers with no
|
||||
// external symbol references. ke_event.h and ke_semaphore.h are forward-
|
||||
// external symbol references. ke_event.h and ke_semaphore.h are forward-
|
||||
// declared here so the HAL layer (hal_disk.c, io_driver.h) can include this
|
||||
// header without dragging in kernel sync-object link dependencies.
|
||||
//
|
||||
@@ -80,16 +80,16 @@ typedef struct IRP_QUEUE {
|
||||
} IRP_QUEUE;
|
||||
|
||||
// Non-inline: defined in ke_irp.c, which can pull in ke_semaphore.h safely.
|
||||
void IrpQueueInit (IRP_QUEUE *q, struct SEMAPHORE *sem);
|
||||
void IrpQueueEnqueue (IRP_QUEUE *q, IRP *irp);
|
||||
IRP *IrpQueueDequeue (IRP_QUEUE *q);
|
||||
__declspec(dllexport) void IrpQueueInit (IRP_QUEUE *q, struct SEMAPHORE *sem);
|
||||
__declspec(dllexport) void IrpQueueEnqueue (IRP_QUEUE *q, IRP *irp);
|
||||
__declspec(dllexport) IRP *IrpQueueDequeue (IRP_QUEUE *q);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public dispatch API — implemented in kernel/ke_irp.c
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Submit asynchronously. Returns STATUS_PENDING on success.
|
||||
KSTATUS IoSubmitIrp (IRP *irp);
|
||||
// Submit asynchronously. Returns STATUS_PENDING on success.
|
||||
__declspec(dllexport) KSTATUS IoSubmitIrp (IRP *irp);
|
||||
|
||||
// Submit and block until complete. Returns irp->Status.
|
||||
KSTATUS IoSubmitIrpSync(IRP *irp);
|
||||
// Submit and block until complete. Returns irp->Status.
|
||||
__declspec(dllexport) KSTATUS IoSubmitIrpSync(IRP *irp);
|
||||
@@ -11,7 +11,7 @@ void KeIrqInitialize(const HAL_API *hal) {
|
||||
gHal = hal;
|
||||
}
|
||||
|
||||
void KeIrqRegister(uint8_t irq, void (*handler)(void)) {
|
||||
__declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void)) {
|
||||
if (irq >= MAX_IRQS || !handler) return;
|
||||
gIrqHandlers[irq] = handler;
|
||||
gHal->Intc.RouteIrq(irq);
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
#include <hal_api.h>
|
||||
|
||||
void KeIrqInitialize(const HAL_API *hal);
|
||||
void KeIrqRegister(uint8_t irq, void (*handler)(void));
|
||||
__declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void));
|
||||
void KeIrqDispatch(uint8_t irq); // called from ke_syscall.asm
|
||||
@@ -152,7 +152,7 @@ void KeSchedulerTick(void) {
|
||||
KeSchedulerPostSwitch();
|
||||
}
|
||||
|
||||
void KeYield(void) {
|
||||
__declspec(dllexport) void KeYield(void) {
|
||||
THREAD* cur = gCurrentThread;
|
||||
if (!cur) return;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
// ke_sched.h - Multi-Level Feedback Queue scheduler
|
||||
// Three run queues (Low / Normal / High). IRQ 0 drives KeSchedulerTick.
|
||||
// Three run queues (Low / Normal / High). IRQ 0 drives KeSchedulerTick.
|
||||
#include <ke_thread.h>
|
||||
|
||||
#define QUANTUM_MS 10 /* base time slice in milliseconds */
|
||||
#define QUANTUM_MS 10 // base time slice in milliseconds
|
||||
|
||||
// Called once by KernelMain before any threads are created.
|
||||
void KeInitializeScheduler(void);
|
||||
@@ -15,11 +15,11 @@ void KeUnreadyThread(THREAD* thread);
|
||||
// Called from the timer ISR every QUANTUM_MS.
|
||||
void KeSchedulerTick(void);
|
||||
|
||||
// Voluntarily yield the CPU. Picks the next runnable thread immediately.
|
||||
void KeYield(void);
|
||||
// Voluntarily yield the CPU. Picks the next runnable thread immediately.
|
||||
__declspec(dllexport) void KeYield(void);
|
||||
|
||||
// Returns the thread currently running on this CPU (reads GS:[0]).
|
||||
THREAD* KeCurrentThread(void);
|
||||
|
||||
// Set the current-thread GS slot. Called once per CPU at boot.
|
||||
// Set the current-thread GS slot. Called once per CPU at boot.
|
||||
void KeSetCurrentThread(THREAD* thread);
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
static void SemDestroy(OBJECT* obj) { (void)obj; }
|
||||
|
||||
KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) {
|
||||
__declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) {
|
||||
if (!out || initial < 0 || max < 1 || initial > max)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
SEMAPHORE* s = (SEMAPHORE *)ObAllocateObject(ObjectTypeSemaphore, sizeof(SEMAPHORE));
|
||||
@@ -21,7 +21,7 @@ KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS KeWaitSemaphore(SEMAPHORE* sem) {
|
||||
__declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* sem) {
|
||||
if (!sem) return STATUS_INVALID_PARAMETER;
|
||||
THREAD* self = KeCurrentThread();
|
||||
|
||||
@@ -38,7 +38,7 @@ KSTATUS KeWaitSemaphore(SEMAPHORE* sem) {
|
||||
}
|
||||
}
|
||||
|
||||
KSTATUS KeTrySemaphore(SEMAPHORE* sem) {
|
||||
__declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* sem) {
|
||||
if (!sem) return STATUS_INVALID_PARAMETER;
|
||||
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
|
||||
if (sem->Count > 0) {
|
||||
@@ -50,7 +50,7 @@ KSTATUS KeTrySemaphore(SEMAPHORE* sem) {
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
void KeSignalSemaphore(SEMAPHORE* sem) {
|
||||
__declspec(dllexport) void KeSignalSemaphore(SEMAPHORE* sem) {
|
||||
if (!sem) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
|
||||
if (!LIST_IS_EMPTY(&sem->WaitList)) {
|
||||
|
||||
@@ -14,7 +14,7 @@ typedef struct SEMAPHORE {
|
||||
LIST_ENTRY WaitList;
|
||||
} SEMAPHORE;
|
||||
|
||||
KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out);
|
||||
KSTATUS KeWaitSemaphore(SEMAPHORE* semaphore);
|
||||
KSTATUS KeTrySemaphore(SEMAPHORE* semaphore);
|
||||
void KeSignalSemaphore(SEMAPHORE* semaphore);
|
||||
__declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out);
|
||||
__declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* semaphore);
|
||||
__declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* semaphore);
|
||||
__declspec(dllexport) void KeSignalSemaphore(SEMAPHORE* semaphore);
|
||||
@@ -89,7 +89,7 @@ KeThreadEntry ENDP
|
||||
|
||||
; -------------------------------------------------------------------------
|
||||
; KeKernelThreadEntry - landing pad for kernel-mode threads created by
|
||||
; KeCreateKernelThread. Never touches ring 3; no IRETQ.
|
||||
; KeCreateKernelThread. Never touches ring 3; no IRETQ.
|
||||
;
|
||||
; Stack layout when we arrive here (above the KCONTEXT already popped by
|
||||
; KeSwitchContext's ret):
|
||||
@@ -97,7 +97,7 @@ KeThreadEntry ENDP
|
||||
; [rsp+08] arg ptr
|
||||
;
|
||||
; We pop both into non-volatile registers so KeSchedulerPostSwitch can
|
||||
; clobber volatile ones freely, then call fn(arg). On return we call
|
||||
; clobber volatile ones freely, then call fn(arg). On return we call
|
||||
; KeExitThread so the thread is cleanly destroyed.
|
||||
; -------------------------------------------------------------------------
|
||||
KeKernelThreadEntry PROC
|
||||
|
||||
@@ -37,7 +37,7 @@ KeSyscallEntry PROC
|
||||
KeSyscallEntry ENDP
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Fault stubs - print a message and halt. A real kernel would do a bugcheck.
|
||||
; Fault stubs - print a message and halt. A real kernel would do a bugcheck.
|
||||
; ---------------------------------------------------------------------------
|
||||
EXTERN DbgPrint:PROC
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// -> obj->Destroy(obj) [type-specific cleanup, e.g. FileDestroy]
|
||||
// -> MmFreePool(obj)
|
||||
//
|
||||
// There is no separate SyscallCloseFile. Removing that stub was the right
|
||||
// There is no separate SyscallCloseFile. Removing that stub was the right
|
||||
// call: the object model already handled it; the dedicated syscall was only
|
||||
// adding a footgun where callers could bypass the unified refcount path.
|
||||
|
||||
@@ -288,7 +288,7 @@ static uint64_t SyscallSemCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
if (!a2) return STATUS_INVALID_PARAMETER;
|
||||
SEMAPHORE* sem = NULL;
|
||||
KSTATUS s = SemaphoreCreate((int32_t)a0, (int32_t)a1, &sem);
|
||||
KSTATUS s = KeSemaphoreCreate((int32_t)a0, (int32_t)a1, &sem);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
uint32_t h = 0;
|
||||
s = AllocHandleForCurrent(&sem->Header, &h);
|
||||
@@ -440,8 +440,8 @@ static uint64_t SyscallQueueRecv(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_CLOSE_HANDLE (26) a0 = handle
|
||||
//
|
||||
// The one and only close path. KeCloseHandle drops the handle-table reference
|
||||
// on 'obj'. If that was the last reference, ObDereferenceObject runs the
|
||||
// The one and only close path. KeCloseHandle drops the handle-table reference
|
||||
// on 'obj'. If that was the last reference, ObDereferenceObject runs the
|
||||
// type-specific Destroy callback (FileDestroy, etc.) and frees the pool memory.
|
||||
// No per-type close syscall needed or wanted.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -33,7 +33,7 @@ static void ThreadDestroy(OBJECT* obj) {
|
||||
}
|
||||
}
|
||||
|
||||
KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg,
|
||||
__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;
|
||||
@@ -110,7 +110,7 @@ KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void KeExitThread(THREAD* thread, int code) {
|
||||
__declspec(dllexport) void KeExitThread(THREAD* thread, int code) {
|
||||
(void)code;
|
||||
if (!thread) return;
|
||||
|
||||
@@ -133,9 +133,9 @@ void KeExitThread(THREAD* thread, int code) {
|
||||
// ---------------------------------------------------------------------------
|
||||
extern void KeKernelThreadEntry(void);
|
||||
|
||||
KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
||||
__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
||||
THREAD_PRIORITY priority, THREAD **out) {
|
||||
// Kernel threads are owned by the idle process. We need a PROCESS* for
|
||||
// Kernel threads are owned by the idle process. We need a PROCESS* for
|
||||
// the owner field; grab it from the idle/init thread that already exists.
|
||||
THREAD* idleThread = KeCurrentThread(); // safe to call before scheduler starts
|
||||
PROCESS* owner = idleThread ? idleThread->Owner : (PROCESS*)0;
|
||||
|
||||
@@ -69,18 +69,18 @@ typedef struct THREAD {
|
||||
void* UserStackBase; // Tracks user stack allocation to prevent memory leaks
|
||||
} THREAD;
|
||||
|
||||
KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg,
|
||||
__declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg,
|
||||
THREAD_PRIORITY priority, THREAD **out);
|
||||
|
||||
// Create a kernel-mode-only thread. fn is called directly in ring 0 with
|
||||
// arg; when fn returns the thread exits automatically. No user stack or TEB
|
||||
// is allocated. The thread is owned by the idle process and runs at the
|
||||
// Create a kernel-mode-only thread. fn is called directly in ring 0 with
|
||||
// arg; when fn returns the thread exits automatically. No user stack or TEB
|
||||
// is allocated. The thread is owned by the idle process and runs at the
|
||||
// given priority.
|
||||
KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
||||
__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
||||
THREAD_PRIORITY priority, THREAD **out);
|
||||
|
||||
// Mark a thread dead and deschedule it permanently.
|
||||
void KeExitThread(THREAD* thread, int code);
|
||||
__declspec(dllexport) void KeExitThread(THREAD* thread, int code);
|
||||
|
||||
// Block / unblock primitives used by sync objects.
|
||||
void KeBlockThread(THREAD* thread, OBJECT* waitObject);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// mm_phys.c - physical memory manager
|
||||
//
|
||||
// The free-frame stack is a flat array of PHYSICAL_ADDRESS values carved out of
|
||||
// the first suitable usable region before any allocation is served. All access
|
||||
// the first suitable usable region before any allocation is served. All access
|
||||
// to physical memory goes through the direct physical window established by the
|
||||
// bootloader at PhysicalWindowBase (always 0xFFFF880000000000).
|
||||
//
|
||||
@@ -124,7 +124,7 @@ void MmFreeFrame(PHYSICAL_ADDRESS frame) {
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
}
|
||||
|
||||
PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) {
|
||||
__declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) {
|
||||
if (!count) return (PHYSICAL_ADDRESS)0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
|
||||
|
||||
@@ -20,8 +20,8 @@ PHYSICAL_ADDRESS MmAllocateFrame(void);
|
||||
void MmFreeFrame(PHYSICAL_ADDRESS frame);
|
||||
|
||||
// Allocate 'count' physically contiguous 4 KB frames.
|
||||
// Returns 0 on failure. Use sparingly (DMA, page tables).
|
||||
PHYSICAL_ADDRESS MmAllocateContiguous(size_t count);
|
||||
// Returns 0 on failure. Use sparingly (DMA, page tables).
|
||||
__declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count);
|
||||
|
||||
size_t MmFreeFrameCount(void);
|
||||
size_t MmTotalFrameCount(void);
|
||||
+12
-12
@@ -11,7 +11,7 @@
|
||||
//
|
||||
// User heap:
|
||||
// A single best-fit free list in the lower half.
|
||||
// Backed on demand from the PMM. No per-process heaps.
|
||||
// Backed on demand from the PMM. No per-process heaps.
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <mm_virt.h>
|
||||
@@ -60,7 +60,7 @@ static PHYSICAL_ADDRESS EnsureTable(PHYSICAL_ADDRESS parentPhys,
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public mapping
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) {
|
||||
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) {
|
||||
unsigned userFlag = (flags & PAGE_USER) ? PAGE_USER : 0;
|
||||
|
||||
PHYSICAL_ADDRESS pdpt = EnsureTable(gPml4Phys, PML4_IDX(virt), userFlag);
|
||||
@@ -76,7 +76,7 @@ KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS MmUnmapPage(uintptr_t virt) {
|
||||
__declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt) {
|
||||
uint64_t* e4 = PtePtr(gPml4Phys, PML4_IDX(virt));
|
||||
if (!(*e4 & PAGE_PRESENT)) return STATUS_NOT_FOUND;
|
||||
uint64_t* e3 = PtePtr(*e4 & ~0xFFFULL, PDPT_IDX(virt));
|
||||
@@ -89,7 +89,7 @@ KSTATUS MmUnmapPage(uintptr_t virt) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) {
|
||||
__declspec(dllexport) KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) {
|
||||
if (!size) return STATUS_SUCCESS;
|
||||
|
||||
// Round down to page boundary, round size up.
|
||||
@@ -115,7 +115,7 @@ KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) {
|
||||
__declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) {
|
||||
if (!gPml4Phys) return 0; // Not initialized
|
||||
|
||||
uint64_t pml4_idx = (virt >> 39) & 0x1FF;
|
||||
@@ -153,7 +153,7 @@ PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) {
|
||||
// Boundary-tag allocator (used for both pool and user heap)
|
||||
// ---------------------------------------------------------------------------
|
||||
// Each allocation has a BLOCK_HDR immediately before the user data, and a
|
||||
// BLOCK_FTR immediately after. Both carry the block size and a 'free' flag.
|
||||
// BLOCK_FTR immediately after. Both carry the block size and a 'free' flag.
|
||||
// This allows O(1) coalescing of adjacent free blocks.
|
||||
|
||||
#define BLOCK_MAGIC 0xB10CB10CUL
|
||||
@@ -433,16 +433,16 @@ void MmActivate(void) {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public pool API
|
||||
// ---------------------------------------------------------------------------
|
||||
void* MmAllocatePool(size_t size) { return HeapAlloc(&gPoolHeap, size); }
|
||||
void MmFreePool(void* ptr) { HeapFree(&gPoolHeap, ptr); }
|
||||
void* MmReallocatePool(void* ptr, size_t newSize) { return HeapRealloc(&gPoolHeap, ptr, newSize); }
|
||||
__declspec(dllexport) void* MmAllocatePool(size_t size) { return HeapAlloc(&gPoolHeap, size); }
|
||||
__declspec(dllexport) void MmFreePool(void* ptr) { HeapFree(&gPoolHeap, ptr); }
|
||||
__declspec(dllexport) void* MmReallocatePool(void* ptr, size_t newSize) { return HeapRealloc(&gPoolHeap, ptr, newSize); }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public user heap API
|
||||
// ---------------------------------------------------------------------------
|
||||
void* MmAllocateUserMemory(size_t size) { return HeapAlloc(&gUserHeap, size); }
|
||||
void MmFreeUserMemory(void* ptr, size_t size) { (void)size; HeapFree(&gUserHeap, ptr); }
|
||||
void* MmReallocateUserMemory(void* ptr, size_t newSize) { return HeapRealloc(&gUserHeap, ptr, newSize); }
|
||||
__declspec(dllexport) void* MmAllocateUserMemory(size_t size) { return HeapAlloc(&gUserHeap, size); }
|
||||
__declspec(dllexport) void MmFreeUserMemory(void* ptr, size_t size) { (void)size; HeapFree(&gUserHeap, ptr); }
|
||||
__declspec(dllexport) void* MmReallocateUserMemory(void* ptr, size_t newSize) { return HeapRealloc(&gUserHeap, ptr, newSize); }
|
||||
|
||||
size_t MmGetKernelPoolUsage(void) {
|
||||
// Returns bytes committed to the kernel pool
|
||||
|
||||
+10
-10
@@ -40,34 +40,34 @@ void MmActivate(void);
|
||||
// ---------------------------------------------------------------------------
|
||||
// Page mapping
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags);
|
||||
KSTATUS MmUnmapPage(uintptr_t virt);
|
||||
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags);
|
||||
__declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt);
|
||||
|
||||
// Modify protection flags on an already-mapped virtual range.
|
||||
// 'flags' is the complete new set of PAGE_* bits - it replaces the old flags
|
||||
// entirely (except the physical address, which is preserved).
|
||||
// Returns STATUS_NOT_FOUND if any page in the range is not mapped.
|
||||
KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags);
|
||||
__declspec(dllexport) KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags);
|
||||
|
||||
// Walk the page tables to translate a virtual address to physical.
|
||||
// Returns 0 if the address is not mapped.
|
||||
PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt);
|
||||
__declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel pool - ring 0 only, never PAGE_USER.
|
||||
// Best-fit free-list allocator, thread-safe via spinlock.
|
||||
// ---------------------------------------------------------------------------
|
||||
void* MmAllocatePool(size_t size);
|
||||
void MmFreePool(void* ptr);
|
||||
void* MmReallocatePool(void* ptr, size_t newSize);
|
||||
__declspec(dllexport) void* MmAllocatePool(size_t size);
|
||||
__declspec(dllexport) void MmFreePool(void* ptr);
|
||||
__declspec(dllexport) void* MmReallocatePool(void* ptr, size_t newSize);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// User heap - shared flat space, ring 3 accessible.
|
||||
// All allocations are PAGE_PRESENT | PAGE_WRITE | PAGE_USER.
|
||||
// ---------------------------------------------------------------------------
|
||||
void* MmAllocateUserMemory(size_t size);
|
||||
void MmFreeUserMemory(void* ptr, size_t size);
|
||||
void* MmReallocateUserMemory(void* ptr, size_t newSize);
|
||||
__declspec(dllexport) void* MmAllocateUserMemory(size_t size);
|
||||
__declspec(dllexport) void MmFreeUserMemory(void* ptr, size_t size);
|
||||
__declspec(dllexport) void* MmReallocateUserMemory(void* ptr, size_t newSize);
|
||||
|
||||
size_t MmGetKernelPoolUsage(void);
|
||||
size_t MmGetUserHeapUsage(void);
|
||||
@@ -11,10 +11,10 @@
|
||||
//
|
||||
// Handle semantics:
|
||||
// Every kernel object (file, mutex, semaphore, event, queue) is reference-
|
||||
// counted. SYS_CLOSE_HANDLE is the ONE way to close any handle regardless
|
||||
// of the object type behind it. KeCloseHandle calls ObDereferenceObject,
|
||||
// counted. SYS_CLOSE_HANDLE is the ONE way to close any handle regardless
|
||||
// of the object type behind it. KeCloseHandle calls ObDereferenceObject,
|
||||
// which fires the type-specific Destroy callback (e.g. FileDestroy)
|
||||
// automatically when the refcount reaches zero. There is no separate
|
||||
// automatically when the refcount reaches zero. There is no separate
|
||||
// SYS_CLOSE_FILE - that was redundant.
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user