// ke_process.c - process model #include "ke_process.h" #include "ke_thread.h" #include "mm_virt.h" #include "ob_object.h" #include #include // --------------------------------------------------------------------------- // Global process list // --------------------------------------------------------------------------- static LIST_ENTRY gProcessList; static SPINLOCK gProcessListLock; static uint32_t gNextProcessId = 1; static void ProcessInit(void) { static int inited = 0; if (!inited) { LIST_INIT(&gProcessList); gProcessListLock = (SPINLOCK)SPINLOCK_INIT; inited = 1; } } LIST_ENTRY* KeGetProcessList(void) { return &gProcessList; } // --------------------------------------------------------------------------- // Destructor (called by ObDereferenceObject when RefCount hits zero) // --------------------------------------------------------------------------- static void ProcessDestroy(OBJECT* obj) { PROCESS* proc = CONTAINING_RECORD(obj, PROCESS, Header); // Release all remaining handles. for (int i = 1; i < HANDLE_TABLE_SIZE; i++) { if (proc->Handles[i]) { ObDereferenceObject(proc->Handles[i]); proc->Handles[i] = (OBJECT *)0; } } // Remove from global list. uintptr_t flags = KeAcquireSpinlock(&gProcessListLock); ListRemove(&proc->GlobalLink); KeReleaseSpinlock(&gProcessListLock, flags); // Memory for the struct itself is freed by ObDereferenceObject after // Destroy returns. } // --------------------------------------------------------------------------- // KeCreateProcess // --------------------------------------------------------------------------- KSTATUS KeCreateProcess(const char* name, PROCESS **out) { ProcessInit(); if (!name || !out) return STATUS_INVALID_PARAMETER; PROCESS* proc = (PROCESS *)ObAllocateObject(ObjectTypeProcess, sizeof(PROCESS)); if (!proc) return STATUS_NO_MEMORY; proc->Header.Destroy = ProcessDestroy; proc->ProcessId = _InterlockedExchangeAdd((volatile long *)&gNextProcessId, 1); strncpy(proc->Name, name, PROCESS_NAME_MAX - 1); proc->Name[PROCESS_NAME_MAX - 1] = '\0'; LIST_INIT(&proc->ThreadList); proc->ThreadCount = 0; proc->HandleLock = (SPINLOCK)SPINLOCK_INIT; proc->ExitCode = 0; // Slot 0 is the invalid handle - leave it NULL. memset(proc->Handles, 0, sizeof(proc->Handles)); LIST_INIT(&proc->GlobalLink); uintptr_t flags = KeAcquireSpinlock(&gProcessListLock); ListInsertTail(&gProcessList, &proc->GlobalLink); KeReleaseSpinlock(&gProcessListLock, flags); *out = proc; return STATUS_SUCCESS; } // --------------------------------------------------------------------------- // KeExitProcess // --------------------------------------------------------------------------- void KeExitProcess(PROCESS* process, int exitCode) { if (!process) return; process->ExitCode = exitCode; // The last thread exiting via KeExitThread will drop the process refcount. // This function is a policy hook; actual cleanup is in ProcessDestroy. ObDereferenceObject(&process->Header); } // --------------------------------------------------------------------------- // Handle table // --------------------------------------------------------------------------- KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut) { if (!process || !object || !handleOut) return STATUS_INVALID_PARAMETER; uintptr_t flags = KeAcquireSpinlock(&process->HandleLock); for (int i = 1; i < HANDLE_TABLE_SIZE; i++) { if (!process->Handles[i]) { ObReferenceObject(object); process->Handles[i] = object; *handleOut = (uint32_t)i; KeReleaseSpinlock(&process->HandleLock, flags); return STATUS_SUCCESS; } } KeReleaseSpinlock(&process->HandleLock, flags); return STATUS_NO_MEMORY; } void KeCloseHandle(PROCESS* process, uint32_t handle) { if (!process || handle == 0 || handle >= HANDLE_TABLE_SIZE) return; uintptr_t flags = KeAcquireSpinlock(&process->HandleLock); OBJECT* obj = process->Handles[handle]; if (obj) { process->Handles[handle] = (OBJECT *)0; KeReleaseSpinlock(&process->HandleLock, flags); ObDereferenceObject(obj); return; } KeReleaseSpinlock(&process->HandleLock, flags); } OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle) { if (!process || handle == 0 || handle >= HANDLE_TABLE_SIZE) return (OBJECT *)0; uintptr_t flags = KeAcquireSpinlock(&process->HandleLock); OBJECT* obj = process->Handles[handle]; if (obj) ObReferenceObject(obj); KeReleaseSpinlock(&process->HandleLock, flags); return obj; }