1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Functions for mapping files and sections 5 * FILE: win32ss/gdi/eng/mapping.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 HANDLE ghSystem32Directory; 15 HANDLE ghRootDirectory; 16 17 PVOID 18 NTAPI 19 EngMapSectionView( 20 _In_ HANDLE hSection, 21 _In_ SIZE_T cjSize, 22 _In_ ULONG cjOffset, 23 _Out_ PHANDLE phSecure) 24 { 25 LARGE_INTEGER liSectionOffset; 26 PVOID pvBaseAddress; 27 NTSTATUS Status; 28 29 /* Check if the size is ok (for 64 bit) */ 30 if (cjSize > ULONG_MAX) 31 { 32 DPRINT1("chSize out of range: 0x%Id\n", cjSize); 33 return NULL; 34 } 35 36 /* Align the offset at allocation granularity and compensate for the size */ 37 liSectionOffset.QuadPart = cjOffset & ~(MM_ALLOCATION_GRANULARITY - 1); 38 cjSize += cjOffset & (MM_ALLOCATION_GRANULARITY - 1); 39 40 /* Map the section */ 41 Status = ZwMapViewOfSection(hSection, 42 NtCurrentProcess(), 43 &pvBaseAddress, 44 0, 45 cjSize, 46 &liSectionOffset, 47 &cjSize, 48 ViewShare, 49 0, 50 PAGE_READWRITE); 51 if (!NT_SUCCESS(Status)) 52 { 53 DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status); 54 return NULL; 55 } 56 57 /* Secure the section memory */ 58 *phSecure = EngSecureMem(pvBaseAddress, (ULONG)cjSize); 59 if (!*phSecure) 60 { 61 ZwUnmapViewOfSection(NtCurrentProcess(), pvBaseAddress); 62 return NULL; 63 } 64 65 /* Return the address where the requested data starts */ 66 return (PUCHAR)pvBaseAddress + (cjOffset & (MM_ALLOCATION_GRANULARITY - 1)); 67 } 68 69 VOID 70 NTAPI 71 EngUnmapSectionView( 72 _In_ PVOID pvBits, 73 _In_ ULONG cjOffset, 74 _In_ HANDLE hSecure) 75 { 76 NTSTATUS Status; 77 78 /* Unsecure the memory */ 79 EngUnsecureMem(hSecure); 80 81 /* Calculate the real start of the section view */ 82 pvBits = (PUCHAR)pvBits - (cjOffset & (MM_ALLOCATION_GRANULARITY - 1)); 83 84 /* Unmap the section view */ 85 Status = MmUnmapViewOfSection(PsGetCurrentProcess(), pvBits); 86 ASSERT(NT_SUCCESS(Status)); 87 } 88 89 PVOID 90 NTAPI 91 EngCreateSection( 92 _In_ ULONG fl, 93 _In_ SIZE_T cjSize, 94 _In_ ULONG ulTag) 95 { 96 NTSTATUS Status; 97 PENGSECTION pSection; 98 PVOID pvSectionObject; 99 LARGE_INTEGER liSize; 100 101 /* Allocate a section object */ 102 pSection = EngAllocMem(0, sizeof(ENGSECTION), 'stsU'); 103 if (!pSection) return NULL; 104 105 liSize.QuadPart = cjSize; 106 Status = MmCreateSection(&pvSectionObject, 107 SECTION_ALL_ACCESS, 108 NULL, 109 &liSize, 110 PAGE_READWRITE, 111 SEC_COMMIT, 112 NULL, 113 NULL); 114 if (!NT_SUCCESS(Status)) 115 { 116 DPRINT1("Failed to create a section Status=0x%x\n", Status); 117 EngFreeMem(pSection); 118 return NULL; 119 } 120 121 /* Set the fields of the section */ 122 pSection->ulTag = ulTag; 123 pSection->pvSectionObject = pvSectionObject; 124 pSection->pvMappedBase = NULL; 125 pSection->cjViewSize = cjSize; 126 127 return pSection; 128 } 129 130 PVOID 131 NTAPI 132 EngCreateSectionHack( 133 _In_ ULONG fl, 134 _In_ SIZE_T cjSize, 135 _In_ ULONG ulTag) 136 { 137 NTSTATUS Status; 138 PENGSECTION pSection; 139 PVOID pvSectionObject; 140 LARGE_INTEGER liSize; 141 142 /* Allocate a section object */ 143 pSection = EngAllocMem(0, sizeof(ENGSECTION), 'stsU'); 144 if (!pSection) return NULL; 145 146 liSize.QuadPart = cjSize; 147 Status = MmCreateSection(&pvSectionObject, 148 SECTION_ALL_ACCESS, 149 NULL, 150 &liSize, 151 PAGE_READWRITE, 152 SEC_COMMIT | 1, 153 NULL, 154 NULL); 155 if (!NT_SUCCESS(Status)) 156 { 157 DPRINT1("Failed to create a section Status=0x%x\n", Status); 158 EngFreeMem(pSection); 159 return NULL; 160 } 161 162 /* Set the fields of the section */ 163 pSection->ulTag = ulTag; 164 pSection->pvSectionObject = pvSectionObject; 165 pSection->pvMappedBase = NULL; 166 pSection->cjViewSize = cjSize; 167 168 return pSection; 169 } 170 171 _Success_(return!=FALSE) 172 BOOL 173 APIENTRY 174 EngMapSection( 175 _In_ PVOID pvSection, 176 _In_ BOOL bMap, 177 _In_ HANDLE hProcess, 178 _When_(bMap, _Outptr_) PVOID* pvBaseAddress) 179 { 180 NTSTATUS Status; 181 PENGSECTION pSection = pvSection; 182 PEPROCESS pepProcess; 183 184 /* Get a pointer to the process */ 185 Status = ObReferenceObjectByHandle(hProcess, 186 PROCESS_VM_OPERATION, 187 NULL, 188 KernelMode, 189 (PVOID*)&pepProcess, 190 NULL); 191 if (!NT_SUCCESS(Status)) 192 { 193 DPRINT1("Could not access process %p, Status=0x%lx\n", hProcess, Status); 194 return FALSE; 195 } 196 197 if (bMap) 198 { 199 /* Make sure the section isn't already mapped */ 200 ASSERT(pSection->pvMappedBase == NULL); 201 202 /* Map the section into the process address space */ 203 Status = MmMapViewOfSection(pSection->pvSectionObject, 204 pepProcess, 205 &pSection->pvMappedBase, 206 0, 207 pSection->cjViewSize, 208 NULL, 209 &pSection->cjViewSize, 210 ViewUnmap, 211 0, 212 PAGE_READWRITE); 213 if (!NT_SUCCESS(Status)) 214 { 215 DPRINT1("Failed to map a section Status=0x%x\n", Status); 216 } 217 } 218 else 219 { 220 /* Make sure the section is mapped */ 221 ASSERT(pSection->pvMappedBase); 222 223 /* Unmap the section from the process address space */ 224 Status = MmUnmapViewOfSection(pepProcess, pSection->pvMappedBase); 225 if (NT_SUCCESS(Status)) 226 { 227 pSection->pvMappedBase = NULL; 228 } 229 else 230 { 231 DPRINT1("Failed to unmap a section @ %p Status=0x%x\n", 232 pSection->pvMappedBase, Status); 233 } 234 } 235 236 /* Dereference the process */ 237 ObDereferenceObject(pepProcess); 238 239 /* Set the new mapping base and return bool status */ 240 *pvBaseAddress = pSection->pvMappedBase; 241 return NT_SUCCESS(Status); 242 } 243 244 BOOL 245 APIENTRY 246 EngFreeSectionMem( 247 _In_opt_ PVOID pvSection, 248 _In_opt_ PVOID pvMappedBase) 249 { 250 NTSTATUS Status; 251 PENGSECTION pSection = pvSection; 252 BOOL bResult = TRUE; 253 254 /* Did the caller give us a mapping base? */ 255 if (pvMappedBase) 256 { 257 Status = MmUnmapViewInSessionSpace(pvMappedBase); 258 if (!NT_SUCCESS(Status)) 259 { 260 DPRINT1("MmUnmapViewInSessionSpace failed: 0x%lx\n", Status); 261 bResult = FALSE; 262 } 263 } 264 265 /* Check if we should free the section as well */ 266 if (pSection) 267 { 268 /* Dereference the kernel section */ 269 ObDereferenceObject(pSection->pvSectionObject); 270 271 /* Finally free the section memory itself */ 272 EngFreeMem(pSection); 273 } 274 275 return bResult; 276 } 277 278 _Check_return_ 279 _Success_(return!=NULL) 280 __drv_allocatesMem(Mem) 281 _Post_writable_byte_size_(cjSize) 282 PVOID 283 APIENTRY 284 EngAllocSectionMem( 285 _Outptr_ PVOID *ppvSection, 286 _In_ ULONG fl, 287 _In_ SIZE_T cjSize, 288 _In_ ULONG ulTag) 289 { 290 NTSTATUS Status; 291 PENGSECTION pSection; 292 293 /* Check parameter */ 294 if (cjSize == 0) return NULL; 295 296 /* Allocate a section object */ 297 pSection = EngCreateSectionHack(fl, cjSize, ulTag); 298 if (!pSection) 299 { 300 *ppvSection = NULL; 301 return NULL; 302 } 303 304 /* Map the section in session space */ 305 Status = MmMapViewInSessionSpace(pSection->pvSectionObject, 306 &pSection->pvMappedBase, 307 &pSection->cjViewSize); 308 if (!NT_SUCCESS(Status)) 309 { 310 DPRINT1("Failed to map a section Status=0x%x\n", Status); 311 *ppvSection = NULL; 312 EngFreeSectionMem(pSection, NULL); 313 return NULL; 314 } 315 316 if (fl & FL_ZERO_MEMORY) 317 { 318 RtlZeroMemory(pSection->pvMappedBase, cjSize); 319 } 320 321 /* Set section pointer and return base address */ 322 *ppvSection = pSection; 323 return pSection->pvMappedBase; 324 } 325 326 _Check_return_ 327 PFILEVIEW 328 NTAPI 329 EngLoadModuleEx( 330 _In_z_ LPWSTR pwsz, 331 _In_ ULONG cjSizeOfModule, 332 _In_ FLONG fl) 333 { 334 PFILEVIEW pFileView = NULL; 335 OBJECT_ATTRIBUTES ObjectAttributes; 336 HANDLE hRootDir; 337 UNICODE_STRING ustrFileName; 338 IO_STATUS_BLOCK IoStatusBlock; 339 FILE_BASIC_INFORMATION FileInformation; 340 HANDLE hFile; 341 NTSTATUS Status; 342 LARGE_INTEGER liSize; 343 344 if (fl & FVF_FONTFILE) 345 { 346 pFileView = EngAllocMem(0, sizeof(FONTFILEVIEW), 'vffG'); 347 } 348 else 349 { 350 pFileView = EngAllocMem(0, sizeof(FILEVIEW), 'liFg'); 351 } 352 353 /* Check for success */ 354 if (!pFileView) return NULL; 355 356 /* Check if the file is relative to system32 */ 357 if (fl & FVF_SYSTEMROOT) 358 { 359 hRootDir = ghSystem32Directory; 360 } 361 else 362 { 363 hRootDir = ghRootDirectory; 364 } 365 366 /* Initialize unicode string and object attributes */ 367 RtlInitUnicodeString(&ustrFileName, pwsz); 368 InitializeObjectAttributes(&ObjectAttributes, 369 &ustrFileName, 370 OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, 371 hRootDir, 372 NULL); 373 374 /* Now open the file */ 375 Status = ZwCreateFile(&hFile, 376 FILE_READ_DATA, 377 &ObjectAttributes, 378 &IoStatusBlock, 379 NULL, 380 FILE_ATTRIBUTE_NORMAL, 381 0, 382 FILE_OPEN, 383 FILE_NON_DIRECTORY_FILE, 384 NULL, 385 0); 386 if (!NT_SUCCESS(Status)) 387 { 388 DPRINT1("Failed to open file, hFile=%p, Status=0x%x\n", hFile, Status); 389 EngFreeMem(pFileView); 390 return NULL; 391 } 392 393 Status = ZwQueryInformationFile(hFile, 394 &IoStatusBlock, 395 &FileInformation, 396 sizeof(FILE_BASIC_INFORMATION), 397 FileBasicInformation); 398 if (NT_SUCCESS(Status)) 399 { 400 pFileView->LastWriteTime = FileInformation.LastWriteTime; 401 } 402 403 /* Create a section from the file */ 404 liSize.QuadPart = cjSizeOfModule; 405 Status = MmCreateSection(&pFileView->pSection, 406 SECTION_ALL_ACCESS, 407 NULL, 408 &liSize, 409 fl & FVF_READONLY ? PAGE_EXECUTE_READ : PAGE_EXECUTE_READWRITE, 410 SEC_COMMIT, 411 hFile, 412 NULL); 413 414 /* Close the file handle */ 415 ZwClose(hFile); 416 417 if (!NT_SUCCESS(Status)) 418 { 419 DPRINT1("Failed to create a section Status=0x%x\n", Status); 420 EngFreeMem(pFileView); 421 return NULL; 422 } 423 424 425 pFileView->pvKView = NULL; 426 pFileView->pvViewFD = NULL; 427 pFileView->cjView = 0; 428 429 return pFileView; 430 } 431 432 HANDLE 433 APIENTRY 434 EngLoadModule( 435 _In_ LPWSTR pwsz) 436 { 437 /* Forward to EngLoadModuleEx */ 438 return (HANDLE)EngLoadModuleEx(pwsz, 0, FVF_READONLY | FVF_SYSTEMROOT); 439 } 440 441 HANDLE 442 APIENTRY 443 EngLoadModuleForWrite( 444 _In_ LPWSTR pwsz, 445 _In_ ULONG cjSizeOfModule) 446 { 447 /* Forward to EngLoadModuleEx */ 448 return (HANDLE)EngLoadModuleEx(pwsz, cjSizeOfModule, FVF_SYSTEMROOT); 449 } 450 451 _Check_return_ 452 _Success_(return!=NULL) 453 _Post_writable_byte_size_(*pulSize) 454 PVOID 455 APIENTRY 456 EngMapModule( 457 _In_ HANDLE h, 458 _Out_ PULONG pulSize) 459 { 460 PFILEVIEW pFileView = (PFILEVIEW)h; 461 NTSTATUS Status; 462 463 pFileView->cjView = 0; 464 465 /* FIXME: Use system space because ARM3 doesn't support executable sections yet */ 466 Status = MmMapViewInSystemSpace(pFileView->pSection, 467 &pFileView->pvKView, 468 &pFileView->cjView); 469 if (!NT_SUCCESS(Status)) 470 { 471 DPRINT1("Failed to map a section Status=0x%x\n", Status); 472 *pulSize = 0; 473 return NULL; 474 } 475 476 *pulSize = (ULONG)pFileView->cjView; 477 return pFileView->pvKView; 478 } 479 480 VOID 481 APIENTRY 482 EngFreeModule( 483 _In_ _Post_invalid_ HANDLE h) 484 { 485 PFILEVIEW pFileView = (PFILEVIEW)h; 486 NTSTATUS Status; 487 488 /* FIXME: Use system space because ARM3 doesn't support executable sections yet */ 489 Status = MmUnmapViewInSystemSpace(pFileView->pvKView); 490 if (!NT_SUCCESS(Status)) 491 { 492 DPRINT1("MmUnmapViewInSessionSpace failed: 0x%lx\n", Status); 493 ASSERT(FALSE); 494 } 495 496 /* Dereference the section */ 497 ObDereferenceObject(pFileView->pSection); 498 499 /* Free the file view memory */ 500 EngFreeMem(pFileView); 501 } 502 503 _Success_(return != 0) 504 _When_(cjSize != 0, _At_(return, _Out_writes_bytes_(cjSize))) 505 PVOID 506 APIENTRY 507 EngMapFile( 508 _In_ LPWSTR pwsz, 509 _In_ ULONG cjSize, 510 _Out_ ULONG_PTR *piFile) 511 { 512 HANDLE hModule; 513 PVOID pvBase; 514 515 /* Load the file */ 516 hModule = EngLoadModuleEx(pwsz, 0, 0); 517 if (!hModule) 518 { 519 *piFile = 0; 520 return NULL; 521 } 522 523 /* Map the file */ 524 pvBase = EngMapModule(hModule, &cjSize); 525 if (!pvBase) 526 { 527 EngFreeModule(hModule); 528 hModule = NULL; 529 } 530 531 /* Set iFile and return mapped base */ 532 *piFile = (ULONG_PTR)hModule; 533 return pvBase; 534 } 535 536 BOOL 537 APIENTRY 538 EngUnmapFile( 539 _In_ ULONG_PTR iFile) 540 { 541 HANDLE hModule = (HANDLE)iFile; 542 543 EngFreeModule(hModule); 544 545 return TRUE; 546 } 547 548 _Check_return_ 549 _Success_(return!=FALSE) 550 BOOL 551 APIENTRY 552 EngMapFontFileFD( 553 _In_ ULONG_PTR iFile, 554 _Outptr_result_bytebuffer_(*pcjBuf) PULONG *ppjBuf, 555 _Out_ ULONG *pcjBuf) 556 { 557 // www.osr.com/ddk/graphics/gdifncs_0co7.htm 558 UNIMPLEMENTED; 559 return FALSE; 560 } 561 562 VOID 563 APIENTRY 564 EngUnmapFontFileFD( 565 _In_ ULONG_PTR iFile) 566 { 567 // http://www.osr.com/ddk/graphics/gdifncs_6wbr.htm 568 UNIMPLEMENTED; 569 } 570 571 __drv_preferredFunction("EngMapFontFileFD", "Obsolete") 572 _Check_return_ 573 _Success_(return!=FALSE) 574 BOOL 575 APIENTRY 576 EngMapFontFile( 577 _In_ ULONG_PTR iFile, 578 _Outptr_result_bytebuffer_(*pcjBuf) PULONG *ppjBuf, 579 _Out_ ULONG *pcjBuf) 580 { 581 // www.osr.com/ddk/graphics/gdifncs_3up3.htm 582 return EngMapFontFileFD(iFile, ppjBuf, pcjBuf); 583 } 584 585 VOID 586 APIENTRY 587 EngUnmapFontFile( 588 _In_ ULONG_PTR iFile) 589 { 590 // www.osr.com/ddk/graphics/gdifncs_09wn.htm 591 EngUnmapFontFileFD(iFile); 592 } 593