build.bat can create the image if missing, split the shell into native, posix and win32, clean up the build by moving executables into directories, the bootloader is no longer responsible to resolve drivers, fix ResolvePath, every process gets a copy of a module (dll), the child always inherits the cwd, fix function exports in posix, add unlink and exit to posix, add path translator to win32, first bugcheck.

This commit is contained in:
maksw committed 2026-05-13 09:24:16 +02:00
1 parent 0c7f461c6d
commit f80e66ecde
38 files changed
+1620 -462

No files matched your search

+26 -3
View File
@@ -769,6 +769,15 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
s = KeCreateProcess(path, &proc);
if (!KSUCCESS(s)) { MmFreeUserMemory(mem, size); return s; }
// Inherit CWD from parent
PROCESS* parent = KeGetCurrentProcess();
if (parent) {
uintptr_t flags = KeAcquireSpinlock(&parent->CwdLock);
strncpy(proc->CurrentDirectory, parent->CurrentDirectory, sizeof(proc->CurrentDirectory) - 1);
proc->CurrentDirectory[sizeof(proc->CurrentDirectory) - 1] = '\0';
KeReleaseSpinlock(&parent->CwdLock, flags);
}
// Store the command line in the process so _start can pick it up.
// If no cmdline was supplied default to just the image path.
if (cmdline && cmdline[0])
@@ -781,8 +790,10 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
// Copy into user memory so the initial thread can access it directly.
size_t cmdlineLen = strlen(proc->Cmdline) + 1;
char* userCmdline = (char*)MmAllocateUserMemory(cmdlineLen);
if (!userCmdline) { ObDereferenceObject(&proc->Header); return STATUS_NO_MEMORY; }
if (!userCmdline) { MmFreeUserMemory(mem, size); ObDereferenceObject(&proc->Header); return STATUS_NO_MEMORY; }
memcpy(userCmdline, proc->Cmdline, cmdlineLen);
proc->UserCmdlineBase = (uintptr_t)userCmdline;
proc->UserCmdlineSize = cmdlineLen;
// Map the PE image into memory.
uintptr_t imageBase = 0;
@@ -790,13 +801,26 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
MmFreeUserMemory(mem, size);
if (!KSUCCESS(s)) { ObDereferenceObject(&proc->Header); return s; }
s = LdrResolveImportsForProcess(proc, imageBase);
if (!KSUCCESS(s)) {
MmFreeUserMemory((void*)imageBase, LdrGetImageSize(imageBase));
ObDereferenceObject(&proc->Header);
return s;
}
// Spin up the initial thread. Pass userCmdline as UserArg so _start
// receives it directly in RCX without an extra syscall.
THREAD* thread;
uintptr_t entryPoint = LdrGetEntryPoint(imageBase);
s = KeCreateThread(proc, entryPoint, (uintptr_t)userCmdline,
PriorityNormal, &thread);
if (!KSUCCESS(s)) { ObDereferenceObject(&proc->Header); return s; }
if (!KSUCCESS(s)) {
MmFreeUserMemory((void*)imageBase, LdrGetImageSize(imageBase));
ObDereferenceObject(&proc->Header);
return s;
}
proc->ImageBase = imageBase;
proc->ImageSize = LdrGetImageSize(imageBase);
// Give the caller a handle to the new process so they can wait on it.
PROCESS* caller = KeGetCurrentProcess();
@@ -809,7 +833,6 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
*handleOut = handle;
return STATUS_SUCCESS;
}
// ---------------------------------------------------------------------------
// SYS_WAIT_FOR_PROCESS (51) a0=handle
// Blocks until the target process signals its ExitEvent.