Sync with trunk (r49303)
[reactos.git] / subsystems / win32 / win32k / eng / mapping.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for mapping files and sections
5 * FILE: subsys/win32k/eng/device.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 // HACK!!!
15 #define MmMapViewInSessionSpace MmMapViewInSystemSpace
16 #define MmUnmapViewInSessionSpace MmUnmapViewInSystemSpace
17
18 typedef struct _ENGSECTION
19 {
20 PVOID pvSectionObject;
21 PVOID pvMappedBase;
22 SIZE_T cjViewSize;
23 ULONG ulTag;
24 } ENGSECTION, *PENGSECTION;
25
26 typedef struct _FILEVIEW
27 {
28 LARGE_INTEGER LastWriteTime;
29 PVOID pvKView;
30 PVOID pvViewFD;
31 SIZE_T cjView;
32 PVOID pSection;
33 } FILEVIEW, *PFILEVIEW;
34
35 typedef struct _FONTFILEVIEW
36 {
37 FILEVIEW;
38 DWORD reserved[2];
39 PWSTR pwszPath;
40 SIZE_T ulRegionSize;
41 ULONG cKRefCount;
42 ULONG cRefCountFD;
43 PVOID pvSpoolerBase;
44 DWORD dwSpoolerPid;
45 } FONTFILEVIEW, *PFONTFILEVIEW;
46
47 enum
48 {
49 FVF_SYSTEMROOT = 1,
50 FVF_READONLY = 2,
51 FVF_FONTFILE = 4,
52 };
53
54 HANDLE ghSystem32Directory;
55 HANDLE ghRootDirectory;
56
57
58 PVOID
59 NTAPI
60 EngCreateSection(
61 IN ULONG fl,
62 IN SIZE_T cjSize,
63 IN ULONG ulTag)
64 {
65 NTSTATUS Status;
66 PENGSECTION pSection;
67 PVOID pvSectionObject;
68 LARGE_INTEGER liSize;
69
70 /* Allocate a section object */
71 pSection = EngAllocMem(0, sizeof(ENGSECTION), 'stsU');
72 if (!pSection) return NULL;
73
74 liSize.QuadPart = cjSize;
75 Status = MmCreateSection(&pvSectionObject,
76 SECTION_ALL_ACCESS,
77 NULL,
78 &liSize,
79 PAGE_READWRITE,
80 SEC_COMMIT,
81 NULL,
82 NULL);
83 if (!NT_SUCCESS(Status))
84 {
85 DPRINT1("Failed to create a section Status=0x%x\n", Status);
86 EngFreeMem(pSection);
87 return NULL;
88 }
89
90 /* Set the fields of the section */
91 pSection->ulTag = ulTag;
92 pSection->pvSectionObject = pvSectionObject;
93 pSection->pvMappedBase = NULL;
94 pSection->cjViewSize = cjSize;
95
96 return pSection;
97 }
98
99
100 BOOL
101 APIENTRY
102 EngMapSection(
103 IN PVOID pvSection,
104 IN BOOL bMap,
105 IN HANDLE hProcess,
106 OUT PVOID* pvBaseAddress)
107 {
108 NTSTATUS Status;
109 PENGSECTION pSection = pvSection;
110 PEPROCESS pepProcess;
111
112 /* Get a pointer to the process */
113 Status = ObReferenceObjectByHandle(hProcess,
114 PROCESS_VM_OPERATION,
115 NULL,
116 KernelMode,
117 (PVOID*)&pepProcess,
118 NULL);
119 if (!NT_SUCCESS(Status))
120 {
121 DPRINT1("Could not access process %p, Status=0x%lx\n", hProcess, Status);
122 return FALSE;
123 }
124
125 if (bMap)
126 {
127 /* Make sure the section isn't already mapped */
128 ASSERT(pSection->pvMappedBase == NULL);
129
130 /* Map the section into the process address space */
131 Status = MmMapViewOfSection(pSection->pvSectionObject,
132 pepProcess,
133 &pSection->pvMappedBase,
134 0,
135 pSection->cjViewSize,
136 NULL,
137 &pSection->cjViewSize,
138 0,
139 0,
140 PAGE_READWRITE);
141 if (!NT_SUCCESS(Status))
142 {
143 DPRINT1("Failed to map a section Status=0x%x\n", Status);
144 }
145 }
146 else
147 {
148 /* Make sure the section is mapped */
149 ASSERT(pSection->pvMappedBase);
150
151 /* Unmap the section from the process address space */
152 Status = MmUnmapViewOfSection(pepProcess, pSection->pvMappedBase);
153 if (NT_SUCCESS(Status))
154 {
155 pSection->pvMappedBase = NULL;
156 }
157 else
158 {
159 DPRINT1("Failed to unmap a section @ &p Status=0x%x\n",
160 pSection->pvMappedBase, Status);
161 }
162 }
163
164 /* Dereference the process */
165 ObDereferenceObject(pepProcess);
166
167 /* Set the new mapping base and return bool status */
168 *pvBaseAddress = pSection->pvMappedBase;
169 return NT_SUCCESS(Status);
170 }
171
172 BOOL
173 APIENTRY
174 EngFreeSectionMem(
175 IN PVOID pvSection OPTIONAL,
176 IN PVOID pvMappedBase OPTIONAL)
177 {
178 NTSTATUS Status;
179 PENGSECTION pSection = pvSection;
180 BOOL bResult = TRUE;
181
182 /* Did the caller give us a mapping base? */
183 if (pvMappedBase)
184 {
185 Status = MmUnmapViewInSessionSpace(pvMappedBase);
186 if (!NT_SUCCESS(Status))
187 {
188 DPRINT1("MmUnmapViewInSessionSpace failed: 0x%lx\n", Status);
189 bResult = FALSE;
190 }
191 }
192
193 /* Check if we should free the section as well */
194 if (pSection)
195 {
196 /* Dereference the kernel section */
197 ObDereferenceObject(pSection->pvSectionObject);
198
199 /* Finally free the section memory itself */
200 EngFreeMem(pSection);
201 }
202
203 return bResult;
204 }
205
206 PVOID
207 APIENTRY
208 EngAllocSectionMem(
209 OUT PVOID *ppvSection,
210 IN ULONG fl,
211 IN SIZE_T cjSize,
212 IN ULONG ulTag)
213 {
214 NTSTATUS Status;
215 PENGSECTION pSection;
216
217 /* Check parameter */
218 if (cjSize == 0) return NULL;
219
220 /* Allocate a section object */
221 pSection = EngCreateSection(fl, cjSize, ulTag);
222 if (!pSection)
223 {
224 *ppvSection = NULL;
225 return NULL;
226 }
227
228 /* Map the section in session space */
229 Status = MmMapViewInSessionSpace(pSection->pvSectionObject,
230 &pSection->pvMappedBase,
231 &pSection->cjViewSize);
232 if (!NT_SUCCESS(Status))
233 {
234 DPRINT1("Failed to map a section Status=0x%x\n", Status);
235 *ppvSection = NULL;
236 EngFreeSectionMem(pSection, NULL);
237 return NULL;
238 }
239
240 if (fl & FL_ZERO_MEMORY)
241 {
242 RtlZeroMemory(pSection->pvMappedBase, cjSize);
243 }
244
245 /* Set section pointer and return base address */
246 *ppvSection = pSection;
247 return pSection->pvMappedBase;
248 }
249
250
251 PFILEVIEW
252 NTAPI
253 EngLoadModuleEx(
254 LPWSTR pwsz,
255 ULONG cjSizeOfModule,
256 FLONG fl)
257 {
258 PFILEVIEW pFileView = NULL;
259 OBJECT_ATTRIBUTES ObjectAttributes;
260 HANDLE hRootDir;
261 UNICODE_STRING ustrFileName;
262 IO_STATUS_BLOCK IoStatusBlock;
263 FILE_BASIC_INFORMATION FileInformation;
264 HANDLE hFile;
265 NTSTATUS Status;
266 LARGE_INTEGER liSize;
267
268 if (fl & FVF_FONTFILE)
269 {
270 pFileView = EngAllocMem(0, sizeof(FONTFILEVIEW), 'vffG');
271 }
272 else
273 {
274 pFileView = EngAllocMem(0, sizeof(FILEVIEW), 'liFg');
275 }
276
277 /* Check for success */
278 if (!pFileView) return NULL;
279
280 /* Check if the file is relative to system32 */
281 if (fl & FVF_SYSTEMROOT)
282 {
283 hRootDir = ghSystem32Directory;
284 }
285 else
286 {
287 hRootDir = ghRootDirectory;
288 }
289
290 /* Initialize unicode string and object attributes */
291 RtlInitUnicodeString(&ustrFileName, pwsz);
292 InitializeObjectAttributes(&ObjectAttributes,
293 &ustrFileName,
294 OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
295 hRootDir,
296 NULL);
297
298 /* Now open the file */
299 Status = ZwCreateFile(&hFile,
300 FILE_READ_DATA,
301 &ObjectAttributes,
302 &IoStatusBlock,
303 NULL,
304 FILE_ATTRIBUTE_NORMAL,
305 0,
306 FILE_OPEN,
307 FILE_NON_DIRECTORY_FILE,
308 NULL,
309 0);
310
311 Status = ZwQueryInformationFile(hFile,
312 &IoStatusBlock,
313 &FileInformation,
314 sizeof(FILE_BASIC_INFORMATION),
315 FileBasicInformation);
316 if (NT_SUCCESS(Status))
317 {
318 pFileView->LastWriteTime = FileInformation.LastWriteTime;
319 }
320
321 /* Create a section from the file */
322 liSize.QuadPart = cjSizeOfModule;
323 Status = MmCreateSection(&pFileView->pSection,
324 SECTION_ALL_ACCESS,
325 NULL,
326 cjSizeOfModule ? &liSize : NULL,
327 fl & FVF_READONLY ? PAGE_EXECUTE_READ : PAGE_EXECUTE_READWRITE,
328 SEC_COMMIT,
329 hFile,
330 NULL);
331
332 /* Close the file handle */
333 ZwClose(hFile);
334
335 if (!NT_SUCCESS(Status))
336 {
337 DPRINT1("Failed to create a section Status=0x%x\n", Status);
338 EngFreeMem(pFileView);
339 return NULL;
340 }
341
342
343 pFileView->pvKView = NULL;
344 pFileView->pvViewFD = NULL;
345 pFileView->cjView = 0;
346
347 return pFileView;
348 }
349
350 HANDLE
351 APIENTRY
352 EngLoadModule(LPWSTR pwsz)
353 {
354 /* Forward to EngLoadModuleEx */
355 return (HANDLE)EngLoadModuleEx(pwsz, 0, FVF_READONLY | FVF_SYSTEMROOT);
356 }
357
358 HANDLE
359 APIENTRY
360 EngLoadModuleForWrite(
361 IN LPWSTR pwsz,
362 IN ULONG cjSizeOfModule)
363 {
364 /* Forward to EngLoadModuleEx */
365 return (HANDLE)EngLoadModuleEx(pwsz, cjSizeOfModule, FVF_SYSTEMROOT);
366 }
367
368 PVOID
369 APIENTRY
370 EngMapModule(
371 IN HANDLE h,
372 OUT PULONG pulSize)
373 {
374 PFILEVIEW pFileView = (PFILEVIEW)h;
375 NTSTATUS Status;
376
377 pFileView->cjView = 0;
378
379 /* Map the section in session space */
380 Status = MmMapViewInSessionSpace(pFileView->pSection,
381 &pFileView->pvKView,
382 &pFileView->cjView);
383 if (!NT_SUCCESS(Status))
384 {
385 DPRINT1("Failed to map a section Status=0x%x\n", Status);
386 *pulSize = 0;
387 return NULL;
388 }
389
390 *pulSize = pFileView->cjView;
391 return pFileView->pvKView;
392 }
393
394 VOID
395 APIENTRY
396 EngFreeModule(IN HANDLE h)
397 {
398 PFILEVIEW pFileView = (PFILEVIEW)h;
399 NTSTATUS Status;
400
401 /* Unmap the section */
402 Status = MmUnmapViewInSessionSpace(pFileView->pvKView);
403 if (!NT_SUCCESS(Status))
404 {
405 DPRINT1("MmUnmapViewInSessionSpace failed: 0x%lx\n", Status);
406 ASSERT(FALSE);
407 }
408
409 /* Dereference the section */
410 ObDereferenceObject(pFileView->pSection);
411
412 /* Free the file view memory */
413 EngFreeMem(pFileView);
414 }
415
416 PVOID
417 APIENTRY
418 EngMapFile(
419 IN LPWSTR pwsz,
420 IN ULONG cjSize,
421 OUT ULONG_PTR *piFile)
422 {
423 HANDLE hModule;
424 PVOID pvBase;
425
426 /* Load the file */
427 hModule = EngLoadModuleEx(pwsz, 0, 0);
428 if (!hModule)
429 {
430 *piFile = 0;
431 return NULL;
432 }
433
434 /* Map the file */
435 pvBase = EngMapModule(hModule, &cjSize);
436 if (!pvBase)
437 {
438 EngFreeModule(hModule);
439 hModule = NULL;
440 }
441
442 /* Set iFile and return mapped base */
443 *piFile = (ULONG_PTR)hModule;
444 return pvBase;
445 }
446
447 BOOL
448 APIENTRY
449 EngUnmapFile(
450 IN ULONG_PTR iFile)
451 {
452 HANDLE hModule = (HANDLE)iFile;
453
454 EngFreeModule(hModule);
455
456 return TRUE;
457 }
458
459
460 BOOL
461 APIENTRY
462 EngMapFontFileFD(
463 IN ULONG_PTR iFile,
464 OUT PULONG *ppjBuf,
465 OUT ULONG *pcjBuf)
466 {
467 // www.osr.com/ddk/graphics/gdifncs_0co7.htm
468 UNIMPLEMENTED;
469 return FALSE;
470 }
471
472 VOID
473 APIENTRY
474 EngUnmapFontFileFD(
475 IN ULONG_PTR iFile)
476 {
477 // http://www.osr.com/ddk/graphics/gdifncs_6wbr.htm
478 UNIMPLEMENTED;
479 }
480
481 BOOL
482 APIENTRY
483 EngMapFontFile(
484 ULONG_PTR iFile,
485 PULONG *ppjBuf,
486 ULONG *pcjBuf)
487 {
488 // www.osr.com/ddk/graphics/gdifncs_3up3.htm
489 return EngMapFontFileFD(iFile, ppjBuf, pcjBuf);
490 }
491
492 VOID
493 APIENTRY
494 EngUnmapFontFile(
495 IN ULONG_PTR iFile)
496 {
497 // www.osr.com/ddk/graphics/gdifncs_09wn.htm
498 EngUnmapFontFileFD(iFile);
499 }