remove weird double spaces, remove /EXPORT from build.bat in favor of __declspec(dllexport)

This commit is contained in:
maksw committed 2026-05-03 19:54:51 +02:00
1 parent 9fa2a7e0db
commit 83d48e09bb
41 files changed
+156 -170

No files matched your search

+6 -6
View File
@@ -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);
}
+6 -6
View File
@@ -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);
+1 -1
View 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};
+1 -1
View File
@@ -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
+4 -4
View File
@@ -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();
+4 -4
View File
@@ -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);
+7 -7
View File
@@ -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;
+8 -8
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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
+1 -1
View File
@@ -152,7 +152,7 @@ void KeSchedulerTick(void) {
KeSchedulerPostSwitch();
}
void KeYield(void) {
__declspec(dllexport) void KeYield(void) {
THREAD* cur = gCurrentThread;
if (!cur) return;
+5 -5
View File
@@ -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);
+4 -4
View File
@@ -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)) {
+4 -4
View File
@@ -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);
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
+4 -4
View File
@@ -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.
// ---------------------------------------------------------------------------
+4 -4
View File
@@ -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;
+6 -6
View File
@@ -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);
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+3 -3
View File
@@ -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.
// ---------------------------------------------------------------------------