8c18e9de0ac5935ed351d9374d1fb374d1ded37e
[reactos.git] / reactos / subsys / win32k / ntuser / ssec.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998 - 2005 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 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * PURPOSE: shared sections support
23 * FILE: subsys/win32k/misc/ssec.c
24 * PROGRAMER: Thomas Weidenmueller <w3seek@reactos.com>
25 */
26
27 #include <w32k.h>
28
29 #define NDEBUG
30 #include <debug.h>
31
32 /*
33 * FIXME - instead of mapping the memory into system space using
34 * MmMapViewInSystemSpace() we should rather use
35 * MmMapViewInSessionSpace() to map it into session space!
36 */
37
38 NTSTATUS INTERNAL_CALL
39 IntUserCreateSharedSectionPool(IN ULONG MaximumPoolSize,
40 IN PSHARED_SECTION_POOL *SharedSectionPool)
41 {
42 PSHARED_SECTION_POOL Pool;
43 ULONG PoolStructSize;
44
45 ASSERT(SharedSectionPool);
46
47 PoolStructSize = ROUND_UP(sizeof(SHARED_SECTION_POOL), PAGE_SIZE);
48 Pool = ExAllocatePoolWithTag(NonPagedPool,
49 PoolStructSize,
50 TAG_SSECTPOOL);
51 if(Pool != NULL)
52 {
53 RtlZeroMemory(Pool, PoolStructSize);
54
55 /* initialize the session heap */
56 ExInitializeFastMutex(&Pool->Lock);
57 Pool->PoolSize = ROUND_UP(MaximumPoolSize, PAGE_SIZE);
58 Pool->PoolFree = Pool->PoolSize;
59 Pool->SharedSectionCount = 0;
60 Pool->SectionsArray.Next = NULL;
61 Pool->SectionsArray.nEntries = ((PoolStructSize - sizeof(SHARED_SECTION_POOL)) /
62 sizeof(SHARED_SECTION)) - 1;
63
64 ASSERT(Pool->SectionsArray.nEntries > 0);
65
66 *SharedSectionPool = Pool;
67
68 return STATUS_SUCCESS;
69 }
70
71 return STATUS_INSUFFICIENT_RESOURCES;
72 }
73
74
75 VOID INTERNAL_CALL
76 IntUserFreeSharedSectionPool(IN PSHARED_SECTION_POOL SharedSectionPool)
77 {
78 PSHARED_SECTIONS_ARRAY Array, OldArray;
79 PSHARED_SECTION SharedSection, LastSharedSection;
80
81 ASSERT(SharedSectionPool);
82
83 Array = &SharedSectionPool->SectionsArray;
84
85 ExAcquireFastMutex(&SharedSectionPool->Lock);
86 while(SharedSectionPool->SharedSectionCount > 0 && Array != NULL)
87 {
88 for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
89 SharedSection != LastSharedSection && SharedSectionPool->SharedSectionCount > 0;
90 SharedSection++)
91 {
92 if(SharedSection->SectionObject != NULL)
93 {
94 ASSERT(SharedSection->SystemMappedBase);
95
96 /* FIXME - use MmUnmapViewInSessionSpace() once implemented! */
97 MmUnmapViewInSystemSpace(SharedSection->SystemMappedBase);
98 /* dereference the keep-alive reference so the section get's deleted */
99 ObDereferenceObject(SharedSection->SectionObject);
100
101 SharedSectionPool->SharedSectionCount--;
102 }
103 }
104
105 OldArray = Array;
106 Array = Array->Next;
107
108 /* all shared sections in this array were freed, link the following array to
109 the main session heap and free this array */
110 SharedSectionPool->SectionsArray.Next = Array;
111 ExFreePool(OldArray);
112 }
113
114 ASSERT(SharedSectionPool->SectionsArray.Next == NULL);
115 ASSERT(SharedSectionPool->SharedSectionCount == 0);
116
117 ExReleaseFastMutex(&SharedSectionPool->Lock);
118 }
119
120
121 NTSTATUS INTERNAL_CALL
122 IntUserCreateSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
123 IN OUT PVOID *SystemMappedBase,
124 IN OUT ULONG *SharedSectionSize)
125 {
126 PSHARED_SECTIONS_ARRAY Array, LastArray;
127 PSHARED_SECTION FreeSharedSection, SharedSection, LastSharedSection;
128 LARGE_INTEGER SectionSize;
129 ULONG Size;
130 NTSTATUS Status;
131
132 ASSERT(SharedSectionPool && SharedSectionSize && (*SharedSectionSize) > 0 && SystemMappedBase);
133
134 FreeSharedSection = NULL;
135
136 Size = ROUND_UP(*SharedSectionSize, PAGE_SIZE);
137
138 ExAcquireFastMutex(&SharedSectionPool->Lock);
139
140 if(Size > SharedSectionPool->PoolFree)
141 {
142 ExReleaseFastMutex(&SharedSectionPool->Lock);
143 DPRINT1("Shared Section Pool limit (0x%x KB) reached, attempted to allocate a 0x%x KB shared section!\n",
144 SharedSectionPool->PoolSize / 1024, (*SharedSectionSize) / 1024);
145 return STATUS_INSUFFICIENT_RESOURCES;
146 }
147
148 /* walk the array to find a free entry */
149 for(Array = &SharedSectionPool->SectionsArray, LastArray = Array;
150 Array != NULL && FreeSharedSection == NULL;
151 Array = Array->Next)
152 {
153 LastArray = Array;
154
155 for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
156 SharedSection != LastSharedSection;
157 SharedSection++)
158 {
159 if(SharedSection->SectionObject == NULL)
160 {
161 FreeSharedSection = SharedSection;
162 break;
163 }
164 }
165
166 if(Array->Next != NULL)
167 {
168 LastArray = Array;
169 }
170 }
171
172 ASSERT(LastArray);
173
174 if(FreeSharedSection == NULL)
175 {
176 ULONG nNewEntries;
177 PSHARED_SECTIONS_ARRAY NewArray;
178
179 ASSERT(LastArray->Next == NULL);
180
181 /* couldn't find a free entry in the array, extend the array */
182
183 nNewEntries = ((PAGE_SIZE - sizeof(SHARED_SECTIONS_ARRAY)) / sizeof(SHARED_SECTION)) + 1;
184 NewArray = ExAllocatePoolWithTag(NonPagedPool,
185 sizeof(SHARED_SECTIONS_ARRAY) + ((nNewEntries - 1) *
186 sizeof(SHARED_SECTION)),
187 TAG_SSECTPOOL);
188 if(NewArray == NULL)
189 {
190 ExReleaseFastMutex(&SharedSectionPool->Lock);
191 DPRINT1("Failed to allocate new array for shared sections!\n");
192 return STATUS_INSUFFICIENT_RESOURCES;
193 }
194
195 NewArray->nEntries = nNewEntries;
196 NewArray->Next = NULL;
197 LastArray->Next = NewArray;
198
199 Array = NewArray;
200 FreeSharedSection = &Array->SharedSection[0];
201 }
202
203 ASSERT(FreeSharedSection);
204
205 /* now allocate a real section */
206
207 SectionSize.QuadPart = Size;
208 Status = MmCreateSection(&FreeSharedSection->SectionObject,
209 SECTION_ALL_ACCESS,
210 NULL,
211 &SectionSize,
212 PAGE_EXECUTE_READWRITE,
213 SEC_COMMIT,
214 NULL,
215 NULL);
216 if(NT_SUCCESS(Status))
217 {
218 Status = MmMapViewInSystemSpace(FreeSharedSection->SectionObject,
219 &FreeSharedSection->SystemMappedBase,
220 &FreeSharedSection->ViewSize);
221 if(NT_SUCCESS(Status))
222 {
223 (*SharedSectionSize) -= Size;
224 SharedSectionPool->SharedSectionCount++;
225
226 *SystemMappedBase = FreeSharedSection->SystemMappedBase;
227 *SharedSectionSize = FreeSharedSection->ViewSize;
228 }
229 else
230 {
231 ObDereferenceObject(FreeSharedSection->SectionObject);
232 FreeSharedSection->SectionObject = NULL;
233 DPRINT1("Failed to map the shared section into system space! Status 0x%x\n", Status);
234 }
235 }
236
237 ExReleaseFastMutex(&SharedSectionPool->Lock);
238
239 return Status;
240 }
241
242
243 NTSTATUS INTERNAL_CALL
244 InUserDeleteSharedSection(PSHARED_SECTION_POOL SharedSectionPool,
245 PVOID SystemMappedBase)
246 {
247 PSHARED_SECTIONS_ARRAY Array;
248 PSECTION_OBJECT SectionObject;
249 PSHARED_SECTION SharedSection, LastSharedSection;
250 NTSTATUS Status;
251
252 ASSERT(SharedSectionPool && SystemMappedBase);
253
254 SectionObject = NULL;
255
256 ExAcquireFastMutex(&SharedSectionPool->Lock);
257
258 for(Array = &SharedSectionPool->SectionsArray;
259 Array != NULL && SectionObject == NULL;
260 Array = Array->Next)
261 {
262 for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
263 SharedSection != LastSharedSection;
264 SharedSection++)
265 {
266 if(SharedSection->SystemMappedBase == SystemMappedBase)
267 {
268 SectionObject = SharedSection->SectionObject;
269 SharedSection->SectionObject = NULL;
270 SharedSection->SystemMappedBase = NULL;
271
272 ASSERT(SharedSectionPool->SharedSectionCount > 0);
273 SharedSectionPool->SharedSectionCount--;
274 break;
275 }
276 }
277 }
278
279 ExReleaseFastMutex(&SharedSectionPool->Lock);
280
281 if(SectionObject != NULL)
282 {
283 Status = MmUnmapViewInSystemSpace(SystemMappedBase);
284 ObDereferenceObject(SectionObject);
285 }
286 else
287 {
288 DPRINT1("Couldn't find and delete a shared section with SystemMappedBase=0x%x!\n", SystemMappedBase);
289 Status = STATUS_UNSUCCESSFUL;
290 }
291
292 return Status;
293 }
294
295
296 NTSTATUS INTERNAL_CALL
297 IntUserMapSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
298 IN PEPROCESS Process,
299 IN PVOID SystemMappedBase,
300 IN PLARGE_INTEGER SectionOffset OPTIONAL,
301 IN OUT PVOID *UserMappedBase,
302 IN PULONG ViewSize OPTIONAL,
303 IN BOOLEAN ReadOnly)
304 {
305 PSHARED_SECTIONS_ARRAY Array;
306 PSECTION_OBJECT SectionObject;
307 PSHARED_SECTION SharedSection, LastSharedSection;
308 NTSTATUS Status;
309
310 ASSERT(SharedSectionPool && Process && SystemMappedBase && UserMappedBase);
311
312 SectionObject = NULL;
313 SharedSection = NULL;
314
315 ExAcquireFastMutex(&SharedSectionPool->Lock);
316
317 for(Array = &SharedSectionPool->SectionsArray;
318 Array != NULL && SectionObject == NULL;
319 Array = Array->Next)
320 {
321 for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
322 SharedSection != LastSharedSection;
323 SharedSection++)
324 {
325 if(SharedSection->SystemMappedBase == SystemMappedBase)
326 {
327 SectionObject = SharedSection->SectionObject;
328 break;
329 }
330 }
331 }
332
333 if(SectionObject != NULL)
334 {
335 ULONG RealViewSize = (ViewSize ? min(*ViewSize, SharedSection->ViewSize) : SharedSection->ViewSize);
336
337 ObReferenceObjectByPointer(SectionObject,
338 (ReadOnly ? SECTION_MAP_READ : SECTION_MAP_READ | SECTION_MAP_WRITE),
339 NULL,
340 KernelMode);
341
342 Status = MmMapViewOfSection(SectionObject,
343 Process,
344 UserMappedBase,
345 0,
346 0,
347 SectionOffset,
348 &RealViewSize,
349 ViewUnmap, /* not sure if we should inherit it... */
350 MEM_COMMIT,
351 (ReadOnly ? PAGE_READONLY : PAGE_READWRITE));
352 if(!NT_SUCCESS(Status))
353 {
354 DPRINT1("Failed to map shared section (readonly=%d) into user memory! Status: 0x%x\n", ReadOnly, Status);
355 }
356 }
357 else
358 {
359 DPRINT1("Couldn't find and map a shared section with SystemMappedBase=0x%x!\n", SystemMappedBase);
360 Status = STATUS_UNSUCCESSFUL;
361 }
362
363 ExReleaseFastMutex(&SharedSectionPool->Lock);
364
365 return Status;
366 }
367
368
369 NTSTATUS INTERNAL_CALL
370 IntUserUnMapSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
371 IN PEPROCESS Process,
372 IN PVOID SystemMappedBase,
373 IN PVOID UserMappedBase)
374 {
375 PSHARED_SECTIONS_ARRAY Array;
376 PSECTION_OBJECT SectionObject;
377 PSHARED_SECTION SharedSection, LastSharedSection;
378 NTSTATUS Status;
379
380 ASSERT(SharedSectionPool && Process && SystemMappedBase && UserMappedBase);
381
382 SectionObject = NULL;
383
384 ExAcquireFastMutex(&SharedSectionPool->Lock);
385
386 for(Array = &SharedSectionPool->SectionsArray;
387 Array != NULL && SectionObject == NULL;
388 Array = Array->Next)
389 {
390 for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
391 SharedSection != LastSharedSection;
392 SharedSection++)
393 {
394 if(SharedSection->SystemMappedBase == SystemMappedBase)
395 {
396 SectionObject = SharedSection->SectionObject;
397 break;
398 }
399 }
400 }
401
402 ExReleaseFastMutex(&SharedSectionPool->Lock);
403
404 if(SectionObject != NULL)
405 {
406 Status = MmUnmapViewOfSection(Process,
407 UserMappedBase);
408 ObDereferenceObject(SectionObject);
409 if(!NT_SUCCESS(Status))
410 {
411 DPRINT1("Failed to unmap shared section UserMappedBase=0x%x! Status: 0x%x\n", UserMappedBase, Status);
412 }
413 }
414 else
415 {
416 DPRINT1("Couldn't find and unmap a shared section with SystemMappedBase=0x%x!\n", SystemMappedBase);
417 Status = STATUS_UNSUCCESSFUL;
418 }
419
420 return Status;
421 }