mirror of
https://github.com/reactos/reactos.git
synced 2024-07-12 23:55:07 +00:00
[KERNEL32]: Fix multiple issues in BaseCreateStack:
- StackLimit was set incorrectly. - Code was not using BaseStaticServerdata, but querying NT instead. - Fix memory leak in failure case. - StackCommit and StackReserved values were not aligned correctly. - Windows Server 2003+ feature of "Guaranteed Stack Commit Size" was not respected. - Some math was screwy. - Failure to get NT headers was not handled. svn path=/trunk/; revision=54285
This commit is contained in:
parent
e5f31ab0a9
commit
4ba4fdcb2c
|
@ -201,7 +201,7 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
|
|||
}
|
||||
|
||||
/* Create the stack for the fiber */
|
||||
Status = BasepCreateStack(NtCurrentProcess(),
|
||||
Status = BaseCreateStack(NtCurrentProcess(),
|
||||
dwStackCommitSize,
|
||||
dwStackReserveSize,
|
||||
&InitialTeb);
|
||||
|
|
|
@ -187,7 +187,7 @@ BasepCreateFirstThread(HANDLE ProcessHandle,
|
|||
DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle);
|
||||
|
||||
/* Create the Thread's Stack */
|
||||
BasepCreateStack(ProcessHandle,
|
||||
BaseCreateStack(ProcessHandle,
|
||||
SectionImageInfo->MaximumStackSize,
|
||||
SectionImageInfo->CommittedStackSize,
|
||||
&InitialTeb);
|
||||
|
|
|
@ -137,7 +137,7 @@ CreateRemoteThread(HANDLE hProcess,
|
|||
ClientId.UniqueProcess = hProcess;
|
||||
|
||||
/* Create the Stack */
|
||||
Status = BasepCreateStack(hProcess,
|
||||
Status = BaseCreateStack(hProcess,
|
||||
dwStackSize,
|
||||
dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
|
||||
dwStackSize : 0,
|
||||
|
|
|
@ -247,60 +247,64 @@ BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes,
|
|||
*/
|
||||
NTSTATUS
|
||||
WINAPI
|
||||
BasepCreateStack(HANDLE hProcess,
|
||||
BaseCreateStack(HANDLE hProcess,
|
||||
SIZE_T StackReserve,
|
||||
SIZE_T StackCommit,
|
||||
PINITIAL_TEB InitialTeb)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
SYSTEM_BASIC_INFORMATION SystemBasicInfo;
|
||||
PIMAGE_NT_HEADERS Headers;
|
||||
ULONG_PTR Stack = 0;
|
||||
BOOLEAN UseGuard = FALSE;
|
||||
|
||||
DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
|
||||
ULONG_PTR Stack;
|
||||
BOOLEAN UseGuard;
|
||||
ULONG PageSize, Dummy, AllocationGranularity;
|
||||
SIZE_T StackReserveHeader, StackCommitHeader, GuardPageSize, GuaranteedStackCommit;
|
||||
DPRINT("BaseCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
|
||||
hProcess, StackReserve, StackCommit);
|
||||
|
||||
/* Get some memory information */
|
||||
Status = NtQuerySystemInformation(SystemBasicInformation,
|
||||
&SystemBasicInfo,
|
||||
sizeof(SYSTEM_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
/* Read page size */
|
||||
PageSize = BaseStaticServerData->SysInfo.PageSize;
|
||||
AllocationGranularity = BaseStaticServerData->SysInfo.AllocationGranularity;
|
||||
|
||||
/* Get the Image Headers */
|
||||
Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
|
||||
if (!Headers) return STATUS_INVALID_IMAGE_FORMAT;
|
||||
|
||||
StackCommitHeader = Headers->OptionalHeader.SizeOfStackCommit;
|
||||
StackReserveHeader = Headers->OptionalHeader.SizeOfStackReserve;
|
||||
|
||||
if (!StackReserve) StackReserve = StackReserveHeader;
|
||||
|
||||
if (!StackCommit)
|
||||
{
|
||||
DPRINT1("Failure to query system info\n");
|
||||
return Status;
|
||||
StackCommit = StackCommitHeader;
|
||||
}
|
||||
else if (StackCommit >= StackReserve)
|
||||
{
|
||||
StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
|
||||
}
|
||||
|
||||
StackCommit = ROUND_UP(StackCommit, PageSize);
|
||||
StackReserve = ROUND_UP(StackReserve, AllocationGranularity);
|
||||
|
||||
GuaranteedStackCommit = NtCurrentTeb()->GuaranteedStackBytes;
|
||||
if ((GuaranteedStackCommit) && (StackCommit < GuaranteedStackCommit))
|
||||
{
|
||||
StackCommit = GuaranteedStackCommit;
|
||||
}
|
||||
|
||||
/* Use the Image Settings if we are dealing with the current Process */
|
||||
if (hProcess == NtCurrentProcess())
|
||||
if (StackCommit >= StackReserve)
|
||||
{
|
||||
/* Get the Image Headers */
|
||||
Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
|
||||
|
||||
/* If we didn't get the parameters, find them ourselves */
|
||||
StackReserve = (StackReserve) ?
|
||||
StackReserve : Headers->OptionalHeader.SizeOfStackReserve;
|
||||
StackCommit = (StackCommit) ?
|
||||
StackCommit : Headers->OptionalHeader.SizeOfStackCommit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the System Settings if needed */
|
||||
StackReserve = (StackReserve) ? StackReserve :
|
||||
SystemBasicInfo.AllocationGranularity;
|
||||
StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize;
|
||||
StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
|
||||
}
|
||||
|
||||
/* Align everything to Page Size */
|
||||
StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity);
|
||||
StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize);
|
||||
#if 1 // FIXME: Remove once Guard Page support is here
|
||||
StackCommit = ROUND_UP(StackCommit, PageSize);
|
||||
StackReserve = ROUND_UP(StackReserve, AllocationGranularity);
|
||||
|
||||
/* ROS Hack until we support guard page stack expansion */
|
||||
StackCommit = StackReserve;
|
||||
#endif
|
||||
DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit);
|
||||
|
||||
/* Reserve memory for the stack */
|
||||
Stack = 0;
|
||||
Status = ZwAllocateVirtualMemory(hProcess,
|
||||
(PVOID*)&Stack,
|
||||
0,
|
||||
|
@ -309,7 +313,7 @@ BasepCreateStack(HANDLE hProcess,
|
|||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to reserve stack\n");
|
||||
DPRINT1("Failure to reserve stack: %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -325,11 +329,15 @@ BasepCreateStack(HANDLE hProcess,
|
|||
/* Check if we will need a guard page */
|
||||
if (StackReserve > StackCommit)
|
||||
{
|
||||
Stack -= SystemBasicInfo.PageSize;
|
||||
StackCommit += SystemBasicInfo.PageSize;
|
||||
Stack -= PageSize;
|
||||
StackCommit += PageSize;
|
||||
UseGuard = TRUE;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
UseGuard = FALSE;
|
||||
}
|
||||
|
||||
/* Allocate memory for the stack */
|
||||
Status = ZwAllocateVirtualMemory(hProcess,
|
||||
(PVOID*)&Stack,
|
||||
|
@ -340,6 +348,8 @@ BasepCreateStack(HANDLE hProcess,
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to allocate stack\n");
|
||||
GuardPageSize = 0;
|
||||
ZwFreeVirtualMemory(hProcess, (PVOID*)&Stack, &GuardPageSize, MEM_RELEASE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -349,10 +359,8 @@ BasepCreateStack(HANDLE hProcess,
|
|||
/* Create a guard page */
|
||||
if (UseGuard)
|
||||
{
|
||||
SIZE_T GuardPageSize = SystemBasicInfo.PageSize;
|
||||
ULONG Dummy;
|
||||
|
||||
/* Attempt maximum space possible */
|
||||
/* Set the guard page */
|
||||
GuardPageSize = PAGE_SIZE;
|
||||
Status = ZwProtectVirtualMemory(hProcess,
|
||||
(PVOID*)&Stack,
|
||||
&GuardPageSize,
|
||||
|
@ -360,12 +368,13 @@ BasepCreateStack(HANDLE hProcess,
|
|||
&Dummy);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to create guard page\n");
|
||||
DPRINT1("Failure to set guard page\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Update the Stack Limit keeping in mind the Guard Page */
|
||||
InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit - GuardPageSize);
|
||||
InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit +
|
||||
GuardPageSize);
|
||||
}
|
||||
|
||||
/* We are done! */
|
||||
|
|
|
@ -173,7 +173,7 @@ BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes,
|
|||
|
||||
NTSTATUS
|
||||
WINAPI
|
||||
BasepCreateStack(HANDLE hProcess,
|
||||
BaseCreateStack(HANDLE hProcess,
|
||||
SIZE_T StackReserve,
|
||||
SIZE_T StackCommit,
|
||||
PINITIAL_TEB InitialTeb);
|
||||
|
|
Loading…
Reference in a new issue