#pragma once // ke_process.h - process model // A process owns a handle table and a list of threads. // There is one shared address space - processes do not own one. #include #include #include #include #include #include #include #define PROCESS_NAME_MAX 64 #define HANDLE_TABLE_SIZE 256 #define PROCESS_MODULE_MAX 16 #define PROCESS_CWD_MAX 512 #define HANDLE_RIGHT_READ 0x00000001u #define HANDLE_RIGHT_WRITE 0x00000002u #define HANDLE_RIGHT_WAIT 0x00000004u #define HANDLE_RIGHT_SIGNAL 0x00000008u #define HANDLE_RIGHT_DUPLICATE 0x00000010u #define HANDLE_RIGHT_QUERY 0x00000020u #define HANDLE_RIGHT_TERMINATE 0x00000040u #define HANDLE_RIGHT_ALL 0xFFFFFFFFu typedef struct HANDLE_ENTRY { OBJECT* Object; uint32_t Rights; uint32_t Flags; } HANDLE_ENTRY; typedef struct PROCESS_MODULE { char Name[32]; uintptr_t Base; size_t Size; } PROCESS_MODULE; typedef struct PROCESS { OBJECT Header; /* must be first */ uint32_t ProcessId; char Name[PROCESS_NAME_MAX]; /* UTF-8 */ char CurrentDirectory[PROCESS_CWD_MAX]; size_t CurrentDirectoryLength; uint8_t CurrentDrive; SPINLOCK CwdLock; /* Thread list. */ LIST_ENTRY ThreadList; /* links THREAD.ProcessLink */ uint32_t ThreadCount; /* Handle table. Index 0 is always empty (the invalid handle). Each live entry holds one object reference plus rights metadata. */ HANDLE_ENTRY Handles[HANDLE_TABLE_SIZE]; SPINLOCK HandleLock; int ExitCode; volatile long Terminating; volatile long Exited; /* Main executable image. Used for cleanup. */ uintptr_t ImageBase; size_t ImageSize; /* User-mode process environment. The initial thread sees this through GS->TEB->PEB. */ uintptr_t UserPebBase; size_t UserPebSize; uintptr_t UserImagePathBase; size_t UserImagePathSize; uintptr_t UserCmdlineBase; size_t UserCmdlineSize; uintptr_t UserCwdBase; size_t UserCwdSize; /* Per-process loaded modules (user processes only). */ PROCESS_MODULE Modules[PROCESS_MODULE_MAX]; uint32_t ModuleCount; /* Signaled (manual-reset) when the process exits. Waiters block on this via KeWaitForEvent. */ EVENT* ExitEvent; LIST_ENTRY GlobalLink; /* node in the global process list */ } PROCESS; KSTATUS KeCreateProcess(const char* name, PROCESS **out); KSTATUS KeCreateSystemProcess(PROCESS** out); KSTATUS KeSetupUserProcessEnvironment(PROCESS* process, SYS_STRING_VIEW imagePath, SYS_STRING_VIEW commandLine, SYS_STRING_VIEW currentDirectory); void KeExitProcess(PROCESS* process, int exitCode); KSTATUS KeTerminateProcess(PROCESS* process, int exitCode); int KeIsProcessTerminating(PROCESS* process); KSTATUS KeGetProcessExitCode(PROCESS* process, int* exitCodeOut); /* Handle table operations. */ KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut); KSTATUS KeAllocateHandleWithRights(PROCESS* process, OBJECT* object, uint32_t rights, uint32_t* handleOut); void KeCloseHandle(PROCESS* process, uint32_t handle); OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle); OBJECT* KeLookupHandleWithRights(PROCESS* process, uint32_t handle, uint32_t requiredRights); uint32_t KeGetHandleRights(PROCESS* process, uint32_t handle); /* Return the global process list head (kernel-internal). */ LIST_ENTRY* KeGetProcessList(void); PROCESS* KeGetCurrentProcess(void); PROCESS* KeGetSystemProcess(void); /* Copy a snapshot of process IDs into caller-provided storage. */ size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount); /* Find a live process by its ProcessId. Bumps refcount; caller must ObDereferenceObject. */ PROCESS* KeGetProcessById(uint32_t pid);