set most of trunk svn property eol-style:native
[reactos.git] / reactos / subsystems / win32 / win32k / misc / usrheap.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <w32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25
26 static NTSTATUS NTAPI
27 IntUserHeapCommitRoutine(IN PVOID Base,
28 IN OUT PVOID *CommitAddress,
29 IN OUT PSIZE_T CommitSize)
30 {
31 PW32PROCESS W32Process;
32 PW32HEAP_USER_MAPPING Mapping;
33 PVOID UserBase = NULL;
34 NTSTATUS Status;
35 SIZE_T Delta = (SIZE_T)((ULONG_PTR)(*CommitAddress) - (ULONG_PTR)Base);
36
37 W32Process = PsGetCurrentProcessWin32Process();
38
39 if (W32Process != NULL)
40 {
41 /* search for the mapping */
42 Mapping = &W32Process->HeapMappings;
43 while (Mapping != NULL)
44 {
45 if (Mapping->KernelMapping == Base)
46 {
47 UserBase = Mapping->UserMapping;
48 break;
49 }
50
51 Mapping = Mapping->Next;
52 }
53
54 ASSERT(UserBase != NULL);
55 }
56 else
57 {
58 ULONG ViewSize = 0;
59 LARGE_INTEGER Offset;
60 extern PSECTION_OBJECT GlobalUserHeapSection;
61
62 /* HACK: This needs to be handled during startup only... */
63 ASSERT(Base == (PVOID)GlobalUserHeap);
64
65 /* temporarily map it into user space */
66 Offset.QuadPart = 0;
67 Status = MmMapViewOfSection(GlobalUserHeapSection,
68 PsGetCurrentProcess(),
69 &UserBase,
70 0,
71 0,
72 &Offset,
73 &ViewSize,
74 ViewUnmap,
75 SEC_NO_CHANGE,
76 PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
77
78 if (!NT_SUCCESS(Status))
79 return Status;
80 }
81
82 /* commit! */
83 UserBase = (PVOID)((ULONG_PTR)UserBase + Delta);
84
85 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
86 &UserBase,
87 0,
88 CommitSize,
89 MEM_COMMIT,
90 PAGE_EXECUTE_READ);
91 if (NT_SUCCESS(Status))
92 {
93 *CommitAddress = (PVOID)((ULONG_PTR)UserBase + Delta);
94 }
95
96 if (W32Process == NULL)
97 {
98 MmUnmapViewOfSection(PsGetCurrentProcess(),
99 UserBase);
100 }
101
102 return Status;
103 }
104
105 static HANDLE
106 IntUserHeapCreate(IN PSECTION_OBJECT SectionObject,
107 IN PVOID *SystemMappedBase,
108 IN ULONG HeapSize)
109 {
110 PVOID MappedView = NULL;
111 LARGE_INTEGER Offset;
112 ULONG ViewSize = PAGE_SIZE;
113 RTL_HEAP_PARAMETERS Parameters = {0};
114 HANDLE hHeap;
115 NTSTATUS Status;
116
117 Offset.QuadPart = 0;
118
119 /* Commit the first page before creating the heap! */
120 Status = MmMapViewOfSection(SectionObject,
121 PsGetCurrentProcess(),
122 &MappedView,
123 0,
124 0,
125 &Offset,
126 &ViewSize,
127 ViewUnmap,
128 SEC_NO_CHANGE,
129 PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
130 if (!NT_SUCCESS(Status))
131 return NULL;
132
133 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
134 &MappedView,
135 0,
136 &ViewSize,
137 MEM_COMMIT,
138 PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
139
140 MmUnmapViewOfSection(PsGetCurrentProcess(),
141 MappedView);
142
143 if (!NT_SUCCESS(Status))
144 return NULL;
145
146 /* Create the heap, don't serialize in kmode! The caller is responsible
147 to synchronize the heap! */
148 Parameters.Length = sizeof(Parameters);
149 Parameters.InitialCommit = PAGE_SIZE;
150 Parameters.InitialReserve = (SIZE_T)HeapSize;
151 Parameters.CommitRoutine = IntUserHeapCommitRoutine;
152
153 hHeap = RtlCreateHeap(HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE,
154 *SystemMappedBase,
155 (SIZE_T)HeapSize,
156 PAGE_SIZE,
157 NULL,
158 &Parameters);
159
160 return hHeap;
161 }
162
163 HANDLE
164 UserCreateHeap(OUT PSECTION_OBJECT *SectionObject,
165 IN OUT PVOID *SystemBase,
166 IN ULONG HeapSize)
167 {
168 LARGE_INTEGER SizeHeap;
169 HANDLE hHeap = NULL;
170 NTSTATUS Status;
171
172 SizeHeap.QuadPart = HeapSize;
173
174 /* create the section and map it into session space */
175 Status = MmCreateSection((PVOID*)SectionObject,
176 SECTION_ALL_ACCESS,
177 NULL,
178 &SizeHeap,
179 PAGE_EXECUTE_READWRITE, /* would prefer PAGE_READWRITE, but thanks to RTL heaps... */
180 SEC_RESERVE,
181 NULL,
182 NULL);
183
184 if (!NT_SUCCESS(Status))
185 {
186 SetLastNtError(Status);
187 return FALSE;
188 }
189
190 Status = MmMapViewInSystemSpace(*SectionObject,
191 SystemBase,
192 &HeapSize);
193 if (!NT_SUCCESS(Status))
194 {
195 ObDereferenceObject(*SectionObject);
196 *SectionObject = NULL;
197
198 SetLastNtError(Status);
199 return FALSE;
200 }
201
202 /* create the heap */
203 hHeap = IntUserHeapCreate(*SectionObject,
204 SystemBase,
205 HeapSize);
206
207 if (hHeap == NULL)
208 {
209 ObDereferenceObject(*SectionObject);
210 *SectionObject = NULL;
211
212 SetLastNtError(STATUS_UNSUCCESSFUL);
213 }
214
215 return hHeap;
216 }