X-Git-Url: http://git.jankratochvil.net/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fldr%2Finit.c;fp=ntoskrnl%2Fldr%2Finit.c;h=6e9d3a1b4c9bae27674a6786e0d5230391f7e310;hp=80599c75772da12d61ddcbcadfde04f2fd9fc3c0;hb=7c0db166f81fbe8c8b913d7f26048e337d383605;hpb=e3ed2d773259cc445c7ff8181ebd934931365328 diff --git a/ntoskrnl/ldr/init.c b/ntoskrnl/ldr/init.c index 80599c7..6e9d3a1 100644 --- a/ntoskrnl/ldr/init.c +++ b/ntoskrnl/ldr/init.c @@ -224,79 +224,156 @@ LdrpCreateProcessEnvironment(HANDLE ProcessHandle, return(STATUS_SUCCESS); } - -static NTSTATUS -LdrpCreateStack(HANDLE ProcessHandle, - PINITIAL_TEB InitialTeb) +/* + FIXME: this sucks. Sucks sucks sucks. This code was duplicated, if you can + believe it, in four different places - excluding this, and twice in the two + DLLs that contained it (kernel32.dll and ntdll.dll). As much as I'd like to + rip the whole RTL out of ntdll.dll and ntoskrnl.exe and into its own static + library, ntoskrnl.exe is built separatedly from the rest of ReactOS, coming + with its own linker scripts and specifications, and, save for changes and fixes + to make it at least compile, I'm not going to touch any of it. If you feel + brave enough, you're welcome [KJK::Hyperion] +*/ +static NTSTATUS LdrpCreateStack +( + HANDLE ProcessHandle, + PUSER_STACK UserStack, + PULONG_PTR StackReserve, + PULONG_PTR StackCommit +) { - ULONG OldPageProtection; - NTSTATUS Status; - - InitialTeb->StackAllocate = NULL; - - /* Allocate the reserved stack space */ - Status = NtAllocateVirtualMemory(ProcessHandle, - &InitialTeb->StackAllocate, - 0, - &InitialTeb->StackReserve, - MEM_RESERVE, - PAGE_READWRITE); - if (!NT_SUCCESS(Status)) - { - DPRINT("Stack allocation failed (Status %x)", Status); - return(Status); - } - - DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n", - InitialTeb->StackAllocate, InitialTeb->StackReserve); - - InitialTeb->StackBase = (PVOID)((ULONG)InitialTeb->StackAllocate + InitialTeb->StackReserve); - InitialTeb->StackLimit = (PVOID)((ULONG)InitialTeb->StackBase - InitialTeb->StackCommit); - - DPRINT("StackBase: %p StackCommit: 0x%lX\n", - InitialTeb->StackBase, InitialTeb->StackCommit); - - /* Commit stack */ - Status = NtAllocateVirtualMemory(ProcessHandle, - &InitialTeb->StackLimit, - 0, - &InitialTeb->StackCommit, - MEM_COMMIT, - PAGE_READWRITE); - if (!NT_SUCCESS(Status)) - { - DPRINT("Error comitting stack page!\n"); - /* release the stack space */ - NtFreeVirtualMemory(ProcessHandle, - InitialTeb->StackAllocate, - &InitialTeb->StackReserve, - MEM_RELEASE); - return(Status); - } - - DPRINT("StackLimit: %p\nStackCommit: 0x%lX\n", - InitialTeb->StackLimit, - InitialTeb->StackCommit); - - /* Protect guard page */ - Status = NtProtectVirtualMemory(ProcessHandle, - InitialTeb->StackLimit, - PAGE_SIZE, - PAGE_GUARD | PAGE_READWRITE, - &OldPageProtection); - if (!NT_SUCCESS(Status)) - { - DPRINT("Error protecting guard page!\n"); - - /* release the stack space */ - NtFreeVirtualMemory(ProcessHandle, - InitialTeb->StackAllocate, - &InitialTeb->StackReserve, - MEM_RELEASE); - return(Status); - } - - return(STATUS_SUCCESS); + PVOID pStackLowest = NULL; + ULONG_PTR nSize = 0; + NTSTATUS nErrCode; + + if(StackReserve == NULL || StackCommit == NULL) + return STATUS_INVALID_PARAMETER; + + /* FIXME: no SEH, no guard pages */ + *StackCommit = *StackReserve; + + UserStack->FixedStackBase = NULL; + UserStack->FixedStackLimit = NULL; + UserStack->ExpandableStackBase = NULL; + UserStack->ExpandableStackLimit = NULL; + UserStack->ExpandableStackBottom = NULL; + + /* FIXME: this code assumes a stack growing downwards */ + /* fixed stack */ + if(*StackCommit == *StackReserve) + { + DPRINT("Fixed stack\n"); + + UserStack->FixedStackLimit = NULL; + + /* allocate the stack */ + nErrCode = NtAllocateVirtualMemory + ( + ProcessHandle, + &(UserStack->FixedStackLimit), + 0, + StackReserve, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE + ); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) return nErrCode; + + /* store the highest (first) address of the stack */ + UserStack->FixedStackBase = + (PUCHAR)(UserStack->FixedStackLimit) + *StackReserve; + } + /* expandable stack */ + else + { + ULONG_PTR nGuardSize = PAGE_SIZE; + PVOID pGuardBase; + + DPRINT("Expandable stack\n"); + + UserStack->FixedStackLimit = NULL; + UserStack->FixedStackBase = NULL; + UserStack->ExpandableStackBottom = NULL; + + /* reserve the stack */ + nErrCode = NtAllocateVirtualMemory + ( + ProcessHandle, + &(UserStack->ExpandableStackBottom), + 0, + StackReserve, + MEM_RESERVE, + PAGE_READWRITE + ); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) return nErrCode; + + DPRINT("Reserved %08X bytes\n", *StackReserve); + + /* expandable stack base - the highest address of the stack */ + UserStack->ExpandableStackBase = + (PUCHAR)(UserStack->ExpandableStackBottom) + *StackReserve; + + /* expandable stack limit - the lowest committed address of the stack */ + UserStack->ExpandableStackLimit = + (PUCHAR)(UserStack->ExpandableStackBase) - *StackCommit; + + DPRINT("Stack base %p\n", UserStack->ExpandableStackBase); + DPRINT("Stack limit %p\n", UserStack->ExpandableStackLimit); + + /* commit as much stack as requested */ + nErrCode = NtAllocateVirtualMemory + ( + ProcessHandle, + &(UserStack->ExpandableStackLimit), + 0, + StackCommit, + MEM_COMMIT, + PAGE_READWRITE + ); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + DPRINT("Stack limit %p\n", UserStack->ExpandableStackLimit); + + pGuardBase = (PUCHAR)(UserStack->ExpandableStackLimit) - PAGE_SIZE; + + DPRINT("Guard base %p\n", UserStack->ExpandableStackBase); + + /* set up the guard page */ + nErrCode = NtAllocateVirtualMemory + ( + ProcessHandle, + &pGuardBase, + 0, + &nGuardSize, + MEM_COMMIT, + PAGE_READWRITE | PAGE_GUARD + ); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + DPRINT("Guard base %p\n", UserStack->ExpandableStackBase); + } + + return STATUS_SUCCESS; + + /* cleanup in case of failure */ +l_Cleanup: + if(UserStack->FixedStackLimit) + pStackLowest = UserStack->FixedStackLimit; + else if(UserStack->ExpandableStackBottom) + pStackLowest = UserStack->ExpandableStackBottom; + + /* free the stack, if it was allocated */ + if(pStackLowest != NULL) + NtFreeVirtualMemory(ProcessHandle, &pStackLowest, &nSize, MEM_RELEASE); + + return nErrCode; } @@ -308,7 +385,11 @@ LdrLoadInitialProcess(PHANDLE ProcessHandle, UNICODE_STRING ImagePath; HANDLE SectionHandle; CONTEXT Context; - INITIAL_TEB InitialTeb; + USER_STACK UserStack; + ULONG_PTR nStackReserve = 0; + ULONG_PTR nStackCommit = 0; + PVOID pStackLowest; + PVOID pStackBase; ULONG ResultLength; PVOID ImageBaseAddress; ULONG InitialStack[5]; @@ -373,28 +454,32 @@ LdrLoadInitialProcess(PHANDLE ProcessHandle, /* Calculate initial stack sizes */ if (Sii.StackReserve > 0x100000) - InitialTeb.StackReserve = Sii.StackReserve; + nStackReserve = Sii.StackReserve; else - InitialTeb.StackReserve = 0x100000; /* 1MByte */ + nStackReserve = 0x100000; /* 1MByte */ /* FIXME */ #if 0 if (Sii.StackCommit > PAGE_SIZE) - InitialTeb.StackCommit = Sii.StackCommit; + nStackCommit = Sii.StackCommit; else - InitialTeb.StackCommit = PAGE_SIZE; + nStackCommit = PAGE_SIZE; #endif - InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE; + nStackCommit = nStackReserve - PAGE_SIZE; - /* add guard page size */ - InitialTeb.StackCommit += PAGE_SIZE; DPRINT("StackReserve 0x%lX StackCommit 0x%lX\n", - InitialTeb.StackReserve, InitialTeb.StackCommit); + nStackReserve, nStackCommit); /* Create the process stack */ - Status = LdrpCreateStack(*ProcessHandle, - &InitialTeb); + Status = LdrpCreateStack + ( + *ProcessHandle, + &UserStack, + &nStackReserve, + &nStackCommit + ); + if (!NT_SUCCESS(Status)) { DPRINT("Failed to write initial stack.\n"); @@ -402,12 +487,31 @@ LdrLoadInitialProcess(PHANDLE ProcessHandle, return(Status); } + if(UserStack.FixedStackBase && UserStack.FixedStackLimit) + { + pStackBase = UserStack.FixedStackBase; + pStackLowest = UserStack.FixedStackLimit; + } + else + { + pStackBase = UserStack.ExpandableStackBase; + pStackLowest = UserStack.ExpandableStackBottom; + } + + DPRINT("pStackBase = %p\n", pStackBase); + DPRINT("pStackLowest = %p\n", pStackLowest); /* * Initialize context to point to LdrStartup */ +#if defined(_M_IX86) memset(&Context,0,sizeof(CONTEXT)); - Context.Eip = (ULONG)(ImageBaseAddress + (ULONG)Sii.EntryPoint); + Context.ContextFlags = CONTEXT_FULL; + Context.FloatSave.ControlWord = 0xffff037f; + Context.FloatSave.StatusWord = 0xffff0000; + Context.FloatSave.TagWord = 0xffffffff; + Context.FloatSave.DataSelector = 0xffff0000; + Context.Eip = (ULONG_PTR)(ImageBaseAddress + (ULONG_PTR)Sii.EntryPoint); Context.SegCs = USER_CS; Context.SegDs = USER_DS; Context.SegEs = USER_DS; @@ -415,7 +519,10 @@ LdrLoadInitialProcess(PHANDLE ProcessHandle, Context.SegGs = USER_DS; Context.SegSs = USER_DS; Context.EFlags = 0x202; - Context.Esp = (ULONG)InitialTeb.StackBase - 20; + Context.Esp = (ULONG_PTR)pStackBase - 20; +#else +#error Unsupported architecture +#endif /* * Write in the initial stack. @@ -429,11 +536,13 @@ LdrLoadInitialProcess(PHANDLE ProcessHandle, &ResultLength); if (!NT_SUCCESS(Status)) { + ULONG_PTR nSize = 0; + DPRINT("Failed to write initial stack.\n"); NtFreeVirtualMemory(*ProcessHandle, - InitialTeb.StackAllocate, - &InitialTeb.StackReserve, + pStackLowest, + &nSize, MEM_RELEASE); NtClose(*ProcessHandle); return(Status); @@ -447,15 +556,17 @@ LdrLoadInitialProcess(PHANDLE ProcessHandle, *ProcessHandle, NULL, &Context, - &InitialTeb, + &UserStack, FALSE); if (!NT_SUCCESS(Status)) { + ULONG_PTR nSize = 0; + DPRINT("NtCreateThread() failed (Status %lx)\n", Status); NtFreeVirtualMemory(*ProcessHandle, - InitialTeb.StackAllocate, - &InitialTeb.StackReserve, + pStackLowest, + &nSize, MEM_RELEASE); NtClose(*ProcessHandle);