2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
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.
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.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 HANDLE GlobalUserHeap
= NULL
;
26 PVOID GlobalUserHeapSection
= NULL
;
29 _Function_class_(RTL_HEAP_COMMIT_ROUTINE
)
34 IntUserHeapCommitRoutine(
36 _Inout_ PVOID
*CommitAddress
,
37 _Inout_ PSIZE_T CommitSize
)
39 PPROCESSINFO W32Process
;
40 PW32HEAP_USER_MAPPING Mapping
;
41 PVOID UserBase
= NULL
;
44 PVOID UserCommitAddress
;
46 W32Process
= PsGetCurrentProcessWin32Process();
48 if (W32Process
!= NULL
)
50 /* Search for the mapping */
51 Mapping
= &W32Process
->HeapMappings
;
52 while (Mapping
!= NULL
)
54 if (Mapping
->KernelMapping
== Base
)
56 UserBase
= Mapping
->UserMapping
;
60 Mapping
= Mapping
->Next
;
63 ASSERT(UserBase
!= NULL
);
70 /* HACK: This needs to be handled during startup only... */
71 ASSERT(Base
== (PVOID
)GlobalUserHeap
);
73 /* Temporarily map it into user space */
75 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
76 PsGetCurrentProcess(),
84 PAGE_EXECUTE_READ
); /* Would prefer PAGE_READONLY, but thanks to RTL heaps... */
86 if (!NT_SUCCESS(Status
))
90 /* Apply the commit address offset to the user base address */
91 Delta
= (SIZE_T
)((ULONG_PTR
)(*CommitAddress
) - (ULONG_PTR
)Base
);
92 UserCommitAddress
= (PVOID
)((ULONG_PTR
)UserBase
+ Delta
);
94 /* Perform the actual commit */
95 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
102 if (NT_SUCCESS(Status
))
104 /* Determine the address to return */
105 Delta
= (SIZE_T
)((ULONG_PTR
)UserCommitAddress
- (ULONG_PTR
)UserBase
);
106 *CommitAddress
= (PVOID
)((ULONG_PTR
)Base
+ Delta
);
109 if (W32Process
== NULL
)
111 MmUnmapViewOfSection(PsGetCurrentProcess(),
119 IntUserHeapCreate(IN PVOID SectionObject
,
120 IN PVOID
*SystemMappedBase
,
123 PVOID MappedView
= NULL
;
124 LARGE_INTEGER Offset
;
125 SIZE_T ViewSize
= PAGE_SIZE
;
126 RTL_HEAP_PARAMETERS Parameters
= {0};
132 /* Commit the first page before creating the heap! */
133 Status
= MmMapViewOfSection(SectionObject
,
134 PsGetCurrentProcess(),
142 PAGE_EXECUTE_READ
); /* Would prefer PAGE_READONLY, but thanks to RTL heaps... */
143 if (!NT_SUCCESS(Status
))
146 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
151 PAGE_EXECUTE_READ
); /* Would prefer PAGE_READONLY, but thanks to RTL heaps... */
153 MmUnmapViewOfSection(PsGetCurrentProcess(),
156 if (!NT_SUCCESS(Status
))
159 /* Create the heap, don't serialize in kmode! The caller is responsible
160 to synchronize the heap! */
161 Parameters
.Length
= sizeof(Parameters
);
162 Parameters
.InitialCommit
= ViewSize
;
163 Parameters
.InitialReserve
= (SIZE_T
)HeapSize
;
164 Parameters
.CommitRoutine
= IntUserHeapCommitRoutine
;
166 pHeap
= RtlCreateHeap(HEAP_ZERO_MEMORY
| HEAP_NO_SERIALIZE
,
177 UserCreateHeap(OUT PVOID
*SectionObject
,
178 IN OUT PVOID
*SystemBase
,
181 LARGE_INTEGER SizeHeap
;
182 PWIN32HEAP pHeap
= NULL
;
185 SizeHeap
.QuadPart
= HeapSize
;
187 /* Create the section and map it into session space */
188 Status
= MmCreateSection((PVOID
*)SectionObject
,
192 PAGE_EXECUTE_READWRITE
, /* Would prefer PAGE_READWRITE, but thanks to RTL heaps... */
197 if (!NT_SUCCESS(Status
))
199 SetLastNtError(Status
);
203 Status
= MmMapViewInSessionSpace(*SectionObject
,
206 if (!NT_SUCCESS(Status
))
208 ObDereferenceObject(*SectionObject
);
209 *SectionObject
= NULL
;
211 SetLastNtError(Status
);
215 /* Create the heap */
216 pHeap
= IntUserHeapCreate(*SectionObject
,
222 ObDereferenceObject(*SectionObject
);
223 *SectionObject
= NULL
;
225 SetLastNtError(STATUS_UNSUCCESSFUL
);
232 UnmapGlobalUserHeap(IN PEPROCESS Process
)
234 NTSTATUS Status
= STATUS_SUCCESS
;
235 PPROCESSINFO W32Process
;
236 PW32HEAP_USER_MAPPING HeapMapping
;
238 TRACE_CH(UserProcess
, "IntUnmapDesktopView called for process 0x%p\n", Process
);
240 W32Process
= PsGetProcessWin32Process(Process
);
241 if (W32Process
== NULL
)
243 ERR_CH(UserProcess
, "UnmapGlobalUserHeap - We don't have a Win32 process!\n");
247 /* The first mapping entry must be the global user heap */
248 HeapMapping
= &W32Process
->HeapMappings
;
249 ASSERT(HeapMapping
->KernelMapping
== (PVOID
)GlobalUserHeap
);
251 /* Unmap if we're the last thread using the global user heap */
252 if (--HeapMapping
->Count
== 0)
254 TRACE_CH(UserProcess
, "UnmapGlobalUserHeap - Unmapping\n");
255 Status
= MmUnmapViewOfSection(Process
, HeapMapping
->UserMapping
);
262 MapGlobalUserHeap(IN PEPROCESS Process
,
263 OUT PVOID
* KernelMapping
,
264 OUT PVOID
* UserMapping
)
267 PPROCESSINFO W32Process
;
268 PW32HEAP_USER_MAPPING HeapMapping
;
269 PVOID UserBase
= NULL
;
272 LARGE_INTEGER Offset
;
274 TRACE_CH(UserProcess
, "MapGlobalUserHeap called for process 0x%p\n", Process
);
276 W32Process
= PsGetProcessWin32Process(Process
);
277 if (W32Process
== NULL
)
279 ERR_CH(UserProcess
, "MapGlobalUserHeap - We don't have a Win32 process!\n");
283 TRACE_CH(UserProcess
, "MapGlobalUserHeap - We got a Win32 process, find for existing global user heap mapping...\n");
285 /* The first mapping entry must be the global user heap */
286 HeapMapping
= &W32Process
->HeapMappings
;
288 /* Find out if another thread already mapped the global user heap */
289 if (HeapMapping
->KernelMapping
== (PVOID
)GlobalUserHeap
)
291 HeapMapping
->Count
++;
293 TRACE_CH(UserProcess
, "MapGlobalUserHeap - A mapping was found, return it.\n");
295 *KernelMapping
= HeapMapping
->KernelMapping
;
296 *UserMapping
= HeapMapping
->UserMapping
;
298 return STATUS_SUCCESS
;
301 TRACE_CH(UserProcess
, "MapGlobalUserHeap - No mapping was found, let's map...\n");
303 /* We're the first, map the global heap into the process */
305 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
314 PAGE_EXECUTE_READ
); /* Would prefer PAGE_READONLY, but thanks to RTL heaps... */
315 if (!NT_SUCCESS(Status
))
317 ERR_CH(UserProcess
, "MapGlobalUserHeap - Failed to map the global heap! 0x%x\n", Status
);
321 TRACE_CH(UserProcess
, "MapGlobalUserHeap -- Mapped kernel global heap 0x%p to user space at 0x%p\n",
322 GlobalUserHeap
, UserBase
);
324 /* Add the mapping */
325 HeapMapping
->Next
= NULL
;
326 HeapMapping
->KernelMapping
= (PVOID
)GlobalUserHeap
;
327 HeapMapping
->UserMapping
= UserBase
;
328 HeapMapping
->Limit
= ViewSize
;
329 HeapMapping
->Count
= 1;
331 *KernelMapping
= HeapMapping
->KernelMapping
;
332 *UserMapping
= HeapMapping
->UserMapping
;
334 return STATUS_SUCCESS
;