first PID is 0, separate idle to system
This commit is contained in:
1 parent
0d7f71b693
commit
db175ab20a
7 files changed
+84
-25
No files matched your search
Binary file not shown.
@@ -14,7 +14,8 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
static LIST_ENTRY gProcessList;
|
||||
static SPINLOCK gProcessListLock;
|
||||
static uint32_t gNextProcessId = 1;
|
||||
static uint32_t gNextProcessId = 0;
|
||||
static PROCESS* gSystemProcess = (PROCESS*)0;
|
||||
|
||||
static void KiProcessInit(void) {
|
||||
static int inited = 0;
|
||||
@@ -38,6 +39,29 @@ PROCESS* KeGetCurrentProcess(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PROCESS* KeGetSystemProcess(void) {
|
||||
return gSystemProcess;
|
||||
}
|
||||
|
||||
KSTATUS KeCreateSystemProcess(PROCESS** out) {
|
||||
if (!out) return STATUS_INVALID_PARAMETER;
|
||||
if (gSystemProcess) {
|
||||
*out = gSystemProcess;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PROCESS* proc = (PROCESS*)0;
|
||||
KSTATUS s = KeCreateProcess("system", &proc);
|
||||
if (!KSUCCESS(s)) {
|
||||
*out = (PROCESS*)0;
|
||||
return s;
|
||||
}
|
||||
|
||||
gSystemProcess = proc;
|
||||
*out = proc;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount) {
|
||||
KiProcessInit();
|
||||
|
||||
@@ -59,6 +83,9 @@ size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount) {
|
||||
static void KiProcessDestroy(OBJECT* obj) {
|
||||
PROCESS* proc = CONTAINING_RECORD(obj, PROCESS, Header);
|
||||
|
||||
if (proc == gSystemProcess)
|
||||
gSystemProcess = (PROCESS*)0;
|
||||
|
||||
// Release all remaining handles.
|
||||
for (int i = 1; i < HANDLE_TABLE_SIZE; i++) {
|
||||
if (proc->Handles[i]) {
|
||||
|
||||
@@ -69,6 +69,7 @@ typedef struct PROCESS {
|
||||
} PROCESS;
|
||||
|
||||
KSTATUS KeCreateProcess(const char* name, PROCESS **out);
|
||||
KSTATUS KeCreateSystemProcess(PROCESS** out);
|
||||
KSTATUS KeSetupUserProcessEnvironment(PROCESS* process, const char* imagePath, const char* commandLine, const char* currentDirectory);
|
||||
void KeExitProcess(PROCESS* process, int exitCode);
|
||||
KSTATUS KeGetProcessExitCode(PROCESS* process, int* exitCodeOut);
|
||||
@@ -81,6 +82,7 @@ OBJECT* KeLookupHandle(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. */
|
||||
|
||||
+24
-1
@@ -33,7 +33,13 @@ void KeInitializeScheduler(void) {
|
||||
gSchedLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
|
||||
PROCESS* idleProc;
|
||||
KeCreateProcess("idle", &idleProc);
|
||||
KSTATUS s = KeCreateProcess("idle", &idleProc);
|
||||
if (!KSUCCESS(s)) return;
|
||||
|
||||
PROCESS* systemProc;
|
||||
s = KeCreateSystemProcess(&systemProc);
|
||||
if (!KSUCCESS(s)) return;
|
||||
(void)systemProc;
|
||||
|
||||
THREAD* idle = (THREAD *)ObAllocateObject(ObjectTypeThread, sizeof(THREAD));
|
||||
idle->Header.Destroy = (void *)0;
|
||||
@@ -44,9 +50,17 @@ void KeInitializeScheduler(void) {
|
||||
idle->Owner = idleProc;
|
||||
idle->WaitObject = (OBJECT *)0;
|
||||
idle->WaitStatus = STATUS_SUCCESS;
|
||||
idle->WaitListHead = (LIST_ENTRY*)0;
|
||||
idle->AlertableWait = 0;
|
||||
idle->SchedLockFlags = 0x202ULL; // IF=1
|
||||
idle->UserStackBase = (void*)0;
|
||||
idle->Teb = (void*)0;
|
||||
idle->TebSize = 0;
|
||||
idle->ExitEvent = (EVENT*)0;
|
||||
KiInitializeApcState(idle);
|
||||
idle->TrapFrame = (KTRAP_FRAME*)0;
|
||||
LIST_INIT(&idle->ProcessLink);
|
||||
LIST_INIT(&idle->SchedulerLink);
|
||||
|
||||
void* kstack = MmAllocatePool(KSTACK_SIZE);
|
||||
idle->KernelStackBase = kstack;
|
||||
@@ -61,6 +75,15 @@ void KeInitializeScheduler(void) {
|
||||
idle->SavedContext = ctx;
|
||||
KeInitThreadFpuContext(idle);
|
||||
|
||||
// The hand-built CPU idle thread is not created through KeCreateThread(),
|
||||
// so register it manually with the idle process. This keeps PID 0 visible
|
||||
// as the real idle process while kernel worker threads live under PID 1.
|
||||
ObReferenceObject(&idleProc->Header);
|
||||
uintptr_t idleFlags = KeAcquireSpinlock(&idleProc->HandleLock);
|
||||
ListInsertTail(&idleProc->ThreadList, &idle->ProcessLink);
|
||||
idleProc->ThreadCount++;
|
||||
KeReleaseSpinlock(&idleProc->HandleLock, idleFlags);
|
||||
|
||||
gIdleThread = idle;
|
||||
gCurrentThread = idle;
|
||||
}
|
||||
|
||||
@@ -211,10 +211,14 @@ extern void KeKernelThreadEntry(void);
|
||||
|
||||
__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
|
||||
// the owner field; grab it from the idle/init thread that already exists.
|
||||
THREAD* idleThread = KeGetCurrentThread(); // safe to call before scheduler starts
|
||||
PROCESS* owner = idleThread ? idleThread->Owner : (PROCESS*)0;
|
||||
// Kernel worker threads are owned by the system process. The scheduler's
|
||||
// hand-built CPU idle thread stays attached to PID 0 (idle), while driver,
|
||||
// async I/O, and init worker threads are grouped under PID 1 (system).
|
||||
PROCESS* owner = KeGetSystemProcess();
|
||||
if (!owner) {
|
||||
THREAD* currentThread = KeGetCurrentThread();
|
||||
owner = currentThread ? currentThread->Owner : (PROCESS*)0;
|
||||
}
|
||||
if (!owner) return STATUS_INVALID_PARAMETER;
|
||||
if (priority >= PriorityCount) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ __declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, ui
|
||||
|
||||
// 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
|
||||
// is allocated. The thread is owned by the system process and runs at the
|
||||
// given priority.
|
||||
__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
||||
THREAD_PRIORITY priority, THREAD** out);
|
||||
|
||||
+21
-18
@@ -370,24 +370,6 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
// Caller owns the reference returned by KeCreateProcess.
|
||||
return proc;
|
||||
}
|
||||
static void KiPrintProcessList() {
|
||||
LIST_ENTRY* listHead = KeGetProcessList();
|
||||
LIST_ENTRY* current;
|
||||
|
||||
DbgPrint("\nPID | Name | Threads | ExitCode\n");
|
||||
DbgPrint("---------------------------------------------\n");
|
||||
|
||||
for (current = listHead->Fwd; current != listHead; current = current->Fwd) {
|
||||
// Translate the list entry back to the PROCESS structure
|
||||
PROCESS* proc = CONTAINING_RECORD(current, PROCESS, GlobalLink);
|
||||
|
||||
DbgPrint("%-5u | %-16s | %-7u | %d\n",
|
||||
proc->ProcessId,
|
||||
proc->Name,
|
||||
proc->ThreadCount,
|
||||
proc->ExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemInitThread(void* arg) {
|
||||
SYSTEM_INIT_ARGS* args = (SYSTEM_INIT_ARGS*)arg;
|
||||
@@ -487,6 +469,27 @@ uint64_t KeCatchAllDebugBucket(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a
|
||||
return status;
|
||||
}
|
||||
|
||||
if (a0 == 2) {
|
||||
LIST_ENTRY* listHead = KeGetProcessList();
|
||||
LIST_ENTRY* current;
|
||||
|
||||
DbgPrint("\nPID | Name | Threads | ExitCode\n");
|
||||
DbgPrint("---------------------------------------------\n");
|
||||
|
||||
for (current = listHead->Fwd; current != listHead; current = current->Fwd) {
|
||||
// Translate the list entry back to the PROCESS structure
|
||||
PROCESS* proc = CONTAINING_RECORD(current, PROCESS, GlobalLink);
|
||||
|
||||
DbgPrint("%-5u | %-16s | %-7u | %d\n",
|
||||
proc->ProcessId,
|
||||
proc->Name,
|
||||
proc->ThreadCount,
|
||||
proc->ExitCode);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DbgPrint("DebugBucket: unknown command %llu\n", a0);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user