10 #include <ntdll/ntdll.h>
12 #include <rosrtl/thread.h>
14 NTSTATUS NTAPI RtlRosCreateStack
16 IN HANDLE ProcessHandle,
17 OUT PUSER_STACK UserStack,
18 IN LONG StackZeroBits,
19 IN OUT PULONG StackReserve OPTIONAL,
20 IN OUT PULONG StackCommit OPTIONAL
23 /* FIXME: read the defaults from the executable image */
24 ULONG_PTR nStackReserve = 0x100000;
25 /* FIXME: when we finally have exception handling, make this PAGE_SIZE */
26 ULONG_PTR nStackCommit = 0x100000;
29 if(StackReserve == NULL) StackReserve = &nStackReserve;
30 else *StackReserve = ROUNDUP(*StackReserve, PAGE_SIZE);
32 if(StackCommit == NULL) StackCommit = &nStackCommit;
33 else *StackCommit = ROUNDUP(*StackCommit, PAGE_SIZE);
36 /* the stack commit size must be equal to or less than the reserve size */
37 if(*StackCommit > *StackReserve) *StackCommit = *StackReserve;
39 /* FIXME: no SEH, no guard pages */
40 *StackCommit = *StackReserve;
43 /* FIXME: this code assumes a stack growing downwards */
45 if(*StackCommit == *StackReserve)
47 UserStack->ExpandableStackBase = NULL;
48 UserStack->ExpandableStackLimit = NULL;
49 UserStack->ExpandableStackBottom = NULL;
51 UserStack->FixedStackLimit = NULL;
53 /* allocate the stack */
54 nErrCode = NtAllocateVirtualMemory
57 &(UserStack->FixedStackLimit),
60 MEM_RESERVE | MEM_COMMIT,
65 if(!NT_SUCCESS(nErrCode)) goto l_Fail;
67 /* store the highest (first) address of the stack */
68 UserStack->FixedStackBase =
69 (PUCHAR)(UserStack->FixedStackLimit) + *StackReserve;
71 *StackCommit = *StackReserve;
73 /* expandable stack */
76 ULONG_PTR nGuardSize = PAGE_SIZE;
79 DPRINT("Expandable stack\n");
81 UserStack->FixedStackBase = NULL;
82 UserStack->FixedStackLimit = NULL;
84 UserStack->ExpandableStackBottom = NULL;
86 /* reserve the stack */
87 nErrCode = NtAllocateVirtualMemory
90 &(UserStack->ExpandableStackBottom),
98 if(!NT_SUCCESS(nErrCode)) goto l_Fail;
100 DPRINT("Reserved %08X bytes\n", *StackReserve);
102 /* expandable stack base - the highest address of the stack */
103 UserStack->ExpandableStackBase =
104 (PUCHAR)(UserStack->ExpandableStackBottom) + *StackReserve;
106 /* expandable stack limit - the lowest committed address of the stack */
107 UserStack->ExpandableStackLimit =
108 (PUCHAR)(UserStack->ExpandableStackBase) - *StackCommit;
110 DPRINT("Stack base %p\n", UserStack->ExpandableStackBase);
111 DPRINT("Stack limit %p\n", UserStack->ExpandableStackLimit);
112 DPRINT("Stack bottom %p\n", UserStack->ExpandableStackBottom);
114 /* commit as much stack as requested */
115 nErrCode = NtAllocateVirtualMemory
118 &(UserStack->ExpandableStackLimit),
126 if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
128 assert((*StackReserve - *StackCommit) >= PAGE_SIZE);
129 assert((*StackReserve - *StackCommit) % PAGE_SIZE == 0);
131 pGuardBase = (PUCHAR)(UserStack->ExpandableStackLimit) - PAGE_SIZE;
133 DPRINT("Guard base %p\n", UserStack->ExpandableStackBase);
135 /* set up the guard page */
136 nErrCode = NtAllocateVirtualMemory
143 PAGE_READWRITE | PAGE_GUARD
147 if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
149 DPRINT("Guard base %p\n", UserStack->ExpandableStackBase);
154 return STATUS_SUCCESS;
156 /* deallocate the stack */
158 RtlRosDeleteStack(ProcessHandle, UserStack);
162 assert(!NT_SUCCESS(nErrCode));
166 NTSTATUS NTAPI RtlRosDeleteStack
168 IN HANDLE ProcessHandle,
169 IN PUSER_STACK UserStack
172 PVOID pStackLowest = NULL;
175 if(UserStack->FixedStackLimit)
176 pStackLowest = UserStack->FixedStackLimit;
177 else if(UserStack->ExpandableStackBottom)
178 pStackLowest = UserStack->ExpandableStackBottom;
180 /* free the stack, if it was allocated */
181 if(pStackLowest != NULL)
182 return NtFreeVirtualMemory(ProcessHandle, &pStackLowest, &nSize, MEM_RELEASE);
184 return STATUS_SUCCESS;
188 NTSTATUS NTAPI RtlpRosGetStackLimits
190 IN PUSER_STACK UserStack,
191 OUT PVOID * StackBase,
192 OUT PVOID * StackLimit
195 /* fixed-size stack */
196 if(UserStack->FixedStackBase && UserStack->FixedStackLimit)
198 *StackBase = UserStack->FixedStackBase;
199 *StackLimit = UserStack->FixedStackLimit;
201 /* expandable stack */
202 else if(UserStack->ExpandableStackBase && UserStack->ExpandableStackLimit)
204 *StackBase = UserStack->ExpandableStackBase;
205 *StackLimit = UserStack->ExpandableStackLimit;
207 /* can't determine the type of stack: failure */
210 DPRINT("Invalid user-mode stack\n");
211 return STATUS_BAD_INITIAL_STACK;
215 return STATUS_SUCCESS;