1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Support for physical devices 5 * FILE: win32ss/gdi/eng/pdevobj.c 6 * PROGRAMERS: Timo Kreuzer (timo.kreuzer@reactos.org) 7 * Oleg Dubinskiy (oleg.dubinskij30@gmail.com) 8 */ 9 10 #include <win32k.h> 11 #define NDEBUG 12 #include <debug.h> 13 DBG_DEFAULT_CHANNEL(EngPDev); 14 15 static PPDEVOBJ gppdevList = NULL; 16 static HSEMAPHORE ghsemPDEV; 17 18 BOOL 19 APIENTRY 20 MultiEnableDriver( 21 _In_ ULONG iEngineVersion, 22 _In_ ULONG cj, 23 _Inout_bytecount_(cj) PDRVENABLEDATA pded); 24 25 extern DRVFN gPanDispDrvFn[]; 26 extern ULONG gPanDispDrvCount; 27 28 CODE_SEG("INIT") 29 NTSTATUS 30 NTAPI 31 InitPDEVImpl(VOID) 32 { 33 ghsemPDEV = EngCreateSemaphore(); 34 if (!ghsemPDEV) return STATUS_INSUFFICIENT_RESOURCES; 35 return STATUS_SUCCESS; 36 } 37 38 #if DBG 39 PPDEVOBJ 40 NTAPI 41 DbgLookupDHPDEV(DHPDEV dhpdev) 42 { 43 PPDEVOBJ ppdev; 44 45 /* Lock PDEV list */ 46 EngAcquireSemaphoreShared(ghsemPDEV); 47 48 /* Walk through the list of PDEVs */ 49 for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext) 50 { 51 /* Compare with the given DHPDEV */ 52 if (ppdev->dhpdev == dhpdev) break; 53 } 54 55 /* Unlock PDEV list */ 56 EngReleaseSemaphore(ghsemPDEV); 57 58 return ppdev; 59 } 60 #endif 61 62 PPDEVOBJ 63 PDEVOBJ_AllocPDEV(VOID) 64 { 65 PPDEVOBJ ppdev; 66 67 ppdev = ExAllocatePoolWithTag(PagedPool, sizeof(PDEVOBJ), GDITAG_PDEV); 68 if (!ppdev) 69 return NULL; 70 71 RtlZeroMemory(ppdev, sizeof(PDEVOBJ)); 72 73 ppdev->hsemDevLock = EngCreateSemaphore(); 74 if (ppdev->hsemDevLock == NULL) 75 { 76 ExFreePoolWithTag(ppdev, GDITAG_PDEV); 77 return NULL; 78 } 79 80 /* Allocate EDD_DIRECTDRAW_GLOBAL for our ReactX driver */ 81 ppdev->pEDDgpl = ExAllocatePoolWithTag(PagedPool, sizeof(EDD_DIRECTDRAW_GLOBAL), GDITAG_PDEV); 82 if (ppdev->pEDDgpl) 83 RtlZeroMemory(ppdev->pEDDgpl, sizeof(EDD_DIRECTDRAW_GLOBAL)); 84 85 ppdev->cPdevRefs = 1; 86 87 return ppdev; 88 } 89 90 static 91 VOID 92 PDEVOBJ_vDeletePDEV( 93 PPDEVOBJ ppdev) 94 { 95 EngDeleteSemaphore(ppdev->hsemDevLock); 96 if (ppdev->pdmwDev) 97 ExFreePoolWithTag(ppdev->pdmwDev, GDITAG_DEVMODE); 98 if (ppdev->pEDDgpl) 99 ExFreePoolWithTag(ppdev->pEDDgpl, GDITAG_PDEV); 100 ExFreePoolWithTag(ppdev, GDITAG_PDEV); 101 } 102 103 VOID 104 NTAPI 105 PDEVOBJ_vRelease( 106 _Inout_ PPDEVOBJ ppdev) 107 { 108 /* Lock loader */ 109 EngAcquireSemaphore(ghsemPDEV); 110 111 /* Decrease reference count */ 112 InterlockedDecrement(&ppdev->cPdevRefs); 113 ASSERT(ppdev->cPdevRefs >= 0); 114 115 /* Check if references are left */ 116 if (ppdev->cPdevRefs == 0) 117 { 118 /* Do we have a surface? */ 119 if (ppdev->pSurface) 120 { 121 /* Release the surface and let the driver free it */ 122 SURFACE_ShareUnlockSurface(ppdev->pSurface); 123 TRACE("DrvDisableSurface(dhpdev %p)\n", ppdev->dhpdev); 124 ppdev->pfn.DisableSurface(ppdev->dhpdev); 125 } 126 127 /* Do we have a palette? */ 128 if (ppdev->ppalSurf) 129 { 130 PALETTE_ShareUnlockPalette(ppdev->ppalSurf); 131 } 132 133 /* Check if the PDEV was enabled */ 134 if (ppdev->dhpdev != NULL) 135 { 136 /* Disable the PDEV */ 137 TRACE("DrvDisablePDEV(dhpdev %p)\n", ppdev->dhpdev); 138 ppdev->pfn.DisablePDEV(ppdev->dhpdev); 139 } 140 141 /* Remove it from list */ 142 if (ppdev == gppdevList) 143 { 144 gppdevList = ppdev->ppdevNext; 145 } 146 else if (gppdevList) 147 { 148 PPDEVOBJ ppdevCurrent = gppdevList; 149 BOOL found = FALSE; 150 while (!found && ppdevCurrent->ppdevNext) 151 { 152 if (ppdevCurrent->ppdevNext == ppdev) 153 found = TRUE; 154 else 155 ppdevCurrent = ppdevCurrent->ppdevNext; 156 } 157 if (found) 158 ppdevCurrent->ppdevNext = ppdev->ppdevNext; 159 } 160 161 /* Unload display driver */ 162 EngUnloadImage(ppdev->pldev); 163 164 /* Free it */ 165 PDEVOBJ_vDeletePDEV(ppdev); 166 } 167 168 /* Unlock loader */ 169 EngReleaseSemaphore(ghsemPDEV); 170 } 171 172 BOOL 173 NTAPI 174 PDEVOBJ_bEnablePDEV( 175 _In_ PPDEVOBJ ppdev, 176 _In_ PDEVMODEW pdevmode, 177 _In_ PWSTR pwszLogAddress) 178 { 179 PFN_DrvEnablePDEV pfnEnablePDEV; 180 ULONG i; 181 182 /* Get the DrvEnablePDEV function */ 183 pfnEnablePDEV = ppdev->pfn.EnablePDEV; 184 185 /* Call the drivers DrvEnablePDEV function */ 186 TRACE("DrvEnablePDEV(pdevmode %p (%dx%dx%d %d Hz) hdev %p (%S))\n", 187 pdevmode, 188 ppdev->pGraphicsDevice ? pdevmode->dmPelsWidth : 0, 189 ppdev->pGraphicsDevice ? pdevmode->dmPelsHeight : 0, 190 ppdev->pGraphicsDevice ? pdevmode->dmBitsPerPel : 0, 191 ppdev->pGraphicsDevice ? pdevmode->dmDisplayFrequency : 0, 192 ppdev, 193 ppdev->pGraphicsDevice ? ppdev->pGraphicsDevice->szNtDeviceName : L""); 194 ppdev->dhpdev = pfnEnablePDEV(pdevmode, 195 pwszLogAddress, 196 HS_DDI_MAX, 197 ppdev->ahsurf, 198 sizeof(GDIINFO), 199 (PULONG)&ppdev->gdiinfo, 200 sizeof(DEVINFO), 201 &ppdev->devinfo, 202 (HDEV)ppdev, 203 ppdev->pGraphicsDevice ? ppdev->pGraphicsDevice->pwszDescription : NULL, 204 ppdev->pGraphicsDevice ? ppdev->pGraphicsDevice->DeviceObject : NULL); 205 TRACE("DrvEnablePDEV(pdevmode %p hdev %p) => dhpdev %p\n", pdevmode, ppdev, ppdev->dhpdev); 206 if (ppdev->dhpdev == NULL) 207 { 208 ERR("Failed to enable PDEV\n"); 209 return FALSE; 210 } 211 212 /* Fix up some values */ 213 if (ppdev->gdiinfo.ulLogPixelsX == 0) 214 ppdev->gdiinfo.ulLogPixelsX = 96; 215 216 if (ppdev->gdiinfo.ulLogPixelsY == 0) 217 ppdev->gdiinfo.ulLogPixelsY = 96; 218 219 /* Set raster caps */ 220 ppdev->gdiinfo.flRaster = RC_OP_DX_OUTPUT | RC_GDI20_OUTPUT | RC_BIGFONT; 221 if ((ppdev->gdiinfo.ulTechnology != DT_PLOTTER) && (ppdev->gdiinfo.ulTechnology != DT_CHARSTREAM)) 222 ppdev->gdiinfo.flRaster |= RC_STRETCHDIB | RC_STRETCHBLT | RC_DIBTODEV | RC_DI_BITMAP | RC_BITMAP64 | RC_BITBLT; 223 if (ppdev->gdiinfo.ulTechnology == DT_RASDISPLAY) 224 ppdev->gdiinfo.flRaster |= RC_FLOODFILL; 225 if (ppdev->devinfo.flGraphicsCaps & GCAPS_PALMANAGED) 226 ppdev->gdiinfo.flRaster |= RC_PALETTE; 227 228 /* Setup Palette */ 229 ppdev->ppalSurf = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault); 230 231 /* Setup hatch brushes */ 232 for (i = 0; i < HS_DDI_MAX; i++) 233 { 234 if (ppdev->ahsurf[i] == NULL) 235 ppdev->ahsurf[i] = gahsurfHatch[i]; 236 } 237 238 TRACE("PDEVOBJ_bEnablePDEV - dhpdev = %p\n", ppdev->dhpdev); 239 240 return TRUE; 241 } 242 243 VOID 244 NTAPI 245 PDEVOBJ_vCompletePDEV( 246 PPDEVOBJ ppdev) 247 { 248 /* Call the drivers DrvCompletePDEV function */ 249 TRACE("DrvCompletePDEV(dhpdev %p hdev %p)\n", ppdev->dhpdev, ppdev); 250 ppdev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev); 251 } 252 253 static 254 VOID 255 PDEVOBJ_vFilterDriverHooks( 256 _In_ PPDEVOBJ ppdev) 257 { 258 PLDEVOBJ pldev = ppdev->pldev; 259 ULONG dwAccelerationLevel = ppdev->dwAccelerationLevel; 260 261 if (!pldev->pGdiDriverInfo) 262 return; 263 if (pldev->ldevtype != LDEV_DEVICE_DISPLAY) 264 return; 265 266 if (dwAccelerationLevel >= 1) 267 { 268 ppdev->apfn[INDEX_DrvSetPointerShape] = NULL; 269 ppdev->apfn[INDEX_DrvCreateDeviceBitmap] = NULL; 270 } 271 272 if (dwAccelerationLevel >= 2) 273 { 274 /* Remove sophisticated display accelerations */ 275 ppdev->pSurface->flags &= ~(HOOK_STRETCHBLT | 276 HOOK_FILLPATH | 277 HOOK_GRADIENTFILL | 278 HOOK_LINETO | 279 HOOK_ALPHABLEND | 280 HOOK_TRANSPARENTBLT); 281 } 282 283 if (dwAccelerationLevel >= 3) 284 { 285 /* Disable DirectDraw and Direct3D accelerations */ 286 /* FIXME: need to call DxDdSetAccelLevel */ 287 UNIMPLEMENTED; 288 } 289 290 if (dwAccelerationLevel >= 4) 291 { 292 /* Remove almost all display accelerations */ 293 ppdev->pSurface->flags &= ~HOOK_FLAGS | 294 HOOK_BITBLT | 295 HOOK_COPYBITS | 296 HOOK_TEXTOUT | 297 HOOK_STROKEPATH | 298 HOOK_SYNCHRONIZE; 299 300 } 301 302 if (dwAccelerationLevel >= 5) 303 { 304 /* Disable all display accelerations */ 305 /* (nothing to do. Already handled in PDEVOBJ_Create) */ 306 } 307 } 308 309 PSURFACE 310 NTAPI 311 PDEVOBJ_pSurface( 312 PPDEVOBJ ppdev) 313 { 314 HSURF hsurf; 315 316 /* Check if there is no surface for this PDEV yet */ 317 if (ppdev->pSurface == NULL) 318 { 319 /* Call the drivers DrvEnableSurface */ 320 TRACE("DrvEnableSurface(dhpdev %p)\n", ppdev->dhpdev); 321 hsurf = ppdev->pfn.EnableSurface(ppdev->dhpdev); 322 TRACE("DrvEnableSurface(dhpdev %p) => hsurf %p\n", ppdev->dhpdev, hsurf); 323 if (hsurf== NULL) 324 { 325 ERR("Failed to create PDEV surface!\n"); 326 return NULL; 327 } 328 329 /* Get a reference to the surface */ 330 ppdev->pSurface = SURFACE_ShareLockSurface(hsurf); 331 NT_ASSERT(ppdev->pSurface != NULL); 332 } 333 334 /* Increment reference count */ 335 GDIOBJ_vReferenceObjectByPointer(&ppdev->pSurface->BaseObject); 336 337 return ppdev->pSurface; 338 } 339 340 #ifdef NATIVE_REACTX 341 BOOL 342 PDEVOBJ_bEnableDirectDraw( 343 _Inout_ PPDEVOBJ ppdev) 344 { 345 PGD_DXDDENABLEDIRECTDRAW pfnDdEnableDirectDraw = (PGD_DXDDENABLEDIRECTDRAW)gpDxFuncs[DXG_INDEX_DxDdEnableDirectDraw].pfn; 346 BOOL Success; 347 348 /* Enable DirectDraw */ 349 TRACE("DxDdEnableDirectDraw(ppdev %p)\n", ppdev); 350 Success = pfnDdEnableDirectDraw((HDEV)ppdev, TRUE); 351 TRACE("DxDdEnableDirectDraw(ppdev %p) => %d\n", ppdev, Success); 352 353 return Success; 354 } 355 356 VOID 357 PDEVOBJ_vResumeDirectDraw( 358 _Inout_ PPDEVOBJ ppdev) 359 { 360 PGD_DXDDRESUMEDIRECTDRAW pfnDdResumeDirectDraw = (PGD_DXDDRESUMEDIRECTDRAW)gpDxFuncs[DXG_INDEX_DxDdResumeDirectDraw].pfn; 361 362 /* Resume DirectDraw after mode change */ 363 TRACE("DxDdResumeDirectDraw(ppdev %p)\n", ppdev); 364 pfnDdResumeDirectDraw((HDEV)ppdev, 0); 365 } 366 367 VOID 368 PDEVOBJ_vSuspendDirectDraw( 369 _Inout_ PPDEVOBJ ppdev) 370 { 371 PGD_DXDDSUSPENDDIRECTDRAW pfnDdSuspendDirectDraw = (PGD_DXDDSUSPENDDIRECTDRAW)gpDxFuncs[DXG_INDEX_DxDdSuspendDirectDraw].pfn; 372 373 /* Suspend DirectDraw for mode change */ 374 TRACE("DxDdSuspendDirectDraw(ppdev %p)\n", ppdev); 375 pfnDdSuspendDirectDraw((HDEV)ppdev, 0); 376 } 377 378 VOID 379 PDEVOBJ_vSwitchDirectDraw( 380 _Inout_ PPDEVOBJ ppdev, 381 _Inout_ PPDEVOBJ ppdev2) 382 { 383 PGD_DXDDDYNAMICMODECHANGE pfnDdDynamicModeChange = (PGD_DXDDDYNAMICMODECHANGE)gpDxFuncs[DXG_INDEX_DxDdDynamicModeChange].pfn; 384 385 /* Switch DirectDraw instances between the PDEVs */ 386 TRACE("DxDdDynamicModeChange(ppdev %p, ppdev2 %p)\n", ppdev, ppdev2); 387 pfnDdDynamicModeChange((HDEV)ppdev, (HDEV)ppdev2, 0); 388 } 389 #endif 390 391 VOID 392 PDEVOBJ_vEnableDisplay( 393 _Inout_ PPDEVOBJ ppdev) 394 { 395 BOOL assertVal; 396 397 if (!(ppdev->flFlags & PDEV_DISABLED)) 398 return; 399 400 /* Try to enable display until success */ 401 do 402 { 403 TRACE("DrvAssertMode(dhpdev %p, TRUE)\n", ppdev->dhpdev); 404 assertVal = ppdev->pfn.AssertMode(ppdev->dhpdev, TRUE); 405 TRACE("DrvAssertMode(dhpdev %p, TRUE) => %d\n", ppdev->dhpdev, assertVal); 406 } while (!assertVal); 407 408 ppdev->flFlags &= ~PDEV_DISABLED; 409 } 410 411 BOOL 412 PDEVOBJ_bDisableDisplay( 413 _Inout_ PPDEVOBJ ppdev) 414 { 415 BOOL assertVal; 416 417 if (ppdev->flFlags & PDEV_DISABLED) 418 return TRUE; 419 420 #ifdef NATIVE_REACTX 421 PDEVOBJ_vSuspendDirectDraw(ppdev); 422 #endif 423 424 TRACE("DrvAssertMode(dhpdev %p, FALSE)\n", ppdev->dhpdev); 425 assertVal = ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE); 426 TRACE("DrvAssertMode(dhpdev %p, FALSE) => %d\n", ppdev->dhpdev, assertVal); 427 428 if (assertVal) 429 ppdev->flFlags |= PDEV_DISABLED; 430 431 return assertVal; 432 } 433 434 VOID 435 NTAPI 436 PDEVOBJ_vRefreshModeList( 437 PPDEVOBJ ppdev) 438 { 439 PGRAPHICS_DEVICE pGraphicsDevice; 440 PDEVMODEINFO pdminfo, pdmiNext; 441 442 /* Lock the PDEV */ 443 EngAcquireSemaphore(ppdev->hsemDevLock); 444 445 pGraphicsDevice = ppdev->pGraphicsDevice; 446 447 /* Clear out the modes */ 448 for (pdminfo = pGraphicsDevice->pdevmodeInfo; 449 pdminfo; 450 pdminfo = pdmiNext) 451 { 452 pdmiNext = pdminfo->pdmiNext; 453 ExFreePoolWithTag(pdminfo, GDITAG_DEVMODE); 454 } 455 pGraphicsDevice->pdevmodeInfo = NULL; 456 ExFreePoolWithTag(pGraphicsDevice->pDevModeList, GDITAG_GDEVICE); 457 pGraphicsDevice->pDevModeList = NULL; 458 459 /* Update available display mode list */ 460 LDEVOBJ_bBuildDevmodeList(pGraphicsDevice); 461 462 /* Unlock PDEV */ 463 EngReleaseSemaphore(ppdev->hsemDevLock); 464 } 465 466 PPDEVOBJ 467 PDEVOBJ_Create( 468 _In_opt_ PGRAPHICS_DEVICE pGraphicsDevice, 469 _In_opt_ PDEVMODEW pdm, 470 _In_ ULONG dwAccelerationLevel, 471 _In_ ULONG ldevtype) 472 { 473 PPDEVOBJ ppdev, ppdevMatch = NULL; 474 PLDEVOBJ pldev; 475 PSURFACE pSurface; 476 477 TRACE("PDEVOBJ_Create(%p %p %d)\n", pGraphicsDevice, pdm, ldevtype); 478 479 if (ldevtype != LDEV_DEVICE_META) 480 { 481 ASSERT(pGraphicsDevice); 482 ASSERT(pdm); 483 /* Search if we already have a PPDEV with the required characteristics. 484 * We will compare the graphics device, the devmode and the desktop 485 */ 486 for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext) 487 { 488 if (ppdev->pGraphicsDevice == pGraphicsDevice) 489 { 490 PDEVOBJ_vReference(ppdev); 491 492 if (RtlEqualMemory(pdm, ppdev->pdmwDev, sizeof(DEVMODEW)) && 493 ppdev->dwAccelerationLevel == dwAccelerationLevel) 494 { 495 PDEVOBJ_vReference(ppdev); 496 ppdevMatch = ppdev; 497 } 498 else 499 { 500 PDEVOBJ_bDisableDisplay(ppdev); 501 } 502 503 PDEVOBJ_vRelease(ppdev); 504 } 505 } 506 507 if (ppdevMatch) 508 { 509 PDEVOBJ_vEnableDisplay(ppdevMatch); 510 511 return ppdevMatch; 512 } 513 } 514 515 /* Try to get a display driver */ 516 if (ldevtype == LDEV_DEVICE_META) 517 pldev = LDEVOBJ_pLoadInternal(MultiEnableDriver, ldevtype); 518 else 519 pldev = LDEVOBJ_pLoadDriver(pdm->dmDeviceName, ldevtype); 520 if (!pldev) 521 { 522 ERR("Could not load display driver '%S'\n", 523 (ldevtype == LDEV_DEVICE_META) ? L"" : pdm->dmDeviceName); 524 return NULL; 525 } 526 527 /* Allocate a new PDEVOBJ */ 528 ppdev = PDEVOBJ_AllocPDEV(); 529 if (!ppdev) 530 { 531 ERR("failed to allocate a PDEV\n"); 532 return NULL; 533 } 534 535 if (ldevtype != LDEV_DEVICE_META) 536 { 537 ppdev->pGraphicsDevice = pGraphicsDevice; 538 539 // DxEngGetHdevData asks for Graphics DeviceObject in hSpooler field 540 ppdev->hSpooler = ppdev->pGraphicsDevice->DeviceObject; 541 542 /* Keep selected resolution */ 543 if (ppdev->pdmwDev) 544 ExFreePoolWithTag(ppdev->pdmwDev, GDITAG_DEVMODE); 545 ppdev->pdmwDev = ExAllocatePoolWithTag(PagedPool, pdm->dmSize + pdm->dmDriverExtra, GDITAG_DEVMODE); 546 if (ppdev->pdmwDev) 547 { 548 RtlCopyMemory(ppdev->pdmwDev, pdm, pdm->dmSize + pdm->dmDriverExtra); 549 /* FIXME: this must be done in a better way */ 550 pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_ATTACHED_TO_DESKTOP; 551 } 552 } 553 554 /* FIXME! */ 555 ppdev->flFlags = PDEV_DISPLAY; 556 557 /* HACK: Don't use the pointer */ 558 ppdev->Pointer.Exclude.right = -1; 559 560 /* Initialize PDEV */ 561 ppdev->pldev = pldev; 562 ppdev->dwAccelerationLevel = dwAccelerationLevel; 563 564 /* Copy the function table */ 565 if ((ldevtype == LDEV_DEVICE_DISPLAY && dwAccelerationLevel >= 5) || 566 pdm->dmFields & (DM_PANNINGWIDTH | DM_PANNINGHEIGHT)) 567 { 568 ULONG i; 569 570 /* Initialize missing fields */ 571 if (!(pdm->dmFields & DM_PANNINGWIDTH)) 572 pdm->dmPanningWidth = pdm->dmPelsWidth; 573 if (!(pdm->dmFields & DM_PANNINGHEIGHT)) 574 pdm->dmPanningHeight = pdm->dmPelsHeight; 575 576 /* Replace vtable by panning vtable */ 577 for (i = 0; i < gPanDispDrvCount; i++) 578 ppdev->apfn[gPanDispDrvFn[i].iFunc] = gPanDispDrvFn[i].pfn; 579 } 580 else 581 { 582 ppdev->pfn = ppdev->pldev->pfn; 583 } 584 585 /* Call the driver to enable the PDEV */ 586 if (!PDEVOBJ_bEnablePDEV(ppdev, pdm, NULL)) 587 { 588 ERR("Failed to enable PDEV!\n"); 589 PDEVOBJ_vRelease(ppdev); 590 EngUnloadImage(pldev); 591 return NULL; 592 } 593 594 /* Tell the driver that the PDEV is ready */ 595 PDEVOBJ_vCompletePDEV(ppdev); 596 597 /* Create the initial surface */ 598 pSurface = PDEVOBJ_pSurface(ppdev); 599 if (!pSurface) 600 { 601 ERR("Failed to create surface\n"); 602 PDEVOBJ_vRelease(ppdev); 603 EngUnloadImage(pldev); 604 return NULL; 605 } 606 607 #ifdef NATIVE_REACTX 608 /* Enable DirectDraw */ 609 if (!PDEVOBJ_bEnableDirectDraw(ppdev)) 610 { 611 ERR("Failed to enable DirectDraw\n"); 612 PDEVOBJ_vRelease(ppdev); 613 EngUnloadImage(pldev); 614 return NULL; 615 } 616 #endif 617 618 /* Remove some acceleration capabilities from driver */ 619 PDEVOBJ_vFilterDriverHooks(ppdev); 620 621 /* Set MovePointer function */ 622 ppdev->pfnMovePointer = ppdev->pfn.MovePointer; 623 if (!ppdev->pfnMovePointer) 624 ppdev->pfnMovePointer = EngMovePointer; 625 626 /* Insert the PDEV into the list */ 627 ppdev->ppdevNext = gppdevList; 628 gppdevList = ppdev; 629 630 /* Return the PDEV */ 631 return ppdev; 632 } 633 634 FORCEINLINE 635 VOID 636 SwitchPointer( 637 _Inout_ PVOID pvPointer1, 638 _Inout_ PVOID pvPointer2) 639 { 640 PVOID *ppvPointer1 = pvPointer1; 641 PVOID *ppvPointer2 = pvPointer2; 642 PVOID pvTemp; 643 644 pvTemp = *ppvPointer1; 645 *ppvPointer1 = *ppvPointer2; 646 *ppvPointer2 = pvTemp; 647 } 648 649 BOOL 650 NTAPI 651 PDEVOBJ_bDynamicModeChange( 652 PPDEVOBJ ppdev, 653 PPDEVOBJ ppdev2) 654 { 655 union 656 { 657 DRIVER_FUNCTIONS pfn; 658 GDIINFO gdiinfo; 659 DEVINFO devinfo; 660 DWORD StateFlags; 661 } temp; 662 663 /* Exchange driver functions */ 664 temp.pfn = ppdev->pfn; 665 ppdev->pfn = ppdev2->pfn; 666 ppdev2->pfn = temp.pfn; 667 668 /* Exchange LDEVs */ 669 SwitchPointer(&ppdev->pldev, &ppdev2->pldev); 670 671 /* Exchange DHPDEV */ 672 SwitchPointer(&ppdev->dhpdev, &ppdev2->dhpdev); 673 674 /* Exchange surfaces and associate them with their new PDEV */ 675 SwitchPointer(&ppdev->pSurface, &ppdev2->pSurface); 676 ppdev->pSurface->SurfObj.hdev = (HDEV)ppdev; 677 ppdev2->pSurface->SurfObj.hdev = (HDEV)ppdev2; 678 679 /* Exchange devinfo */ 680 temp.devinfo = ppdev->devinfo; 681 ppdev->devinfo = ppdev2->devinfo; 682 ppdev2->devinfo = temp.devinfo; 683 684 /* Exchange gdiinfo */ 685 temp.gdiinfo = ppdev->gdiinfo; 686 ppdev->gdiinfo = ppdev2->gdiinfo; 687 ppdev2->gdiinfo = temp.gdiinfo; 688 689 /* Exchange DEVMODE */ 690 SwitchPointer(&ppdev->pdmwDev, &ppdev2->pdmwDev); 691 692 /* Exchange state flags */ 693 temp.StateFlags = ppdev->pGraphicsDevice->StateFlags; 694 ppdev->pGraphicsDevice->StateFlags = ppdev2->pGraphicsDevice->StateFlags; 695 ppdev2->pGraphicsDevice->StateFlags = temp.StateFlags; 696 697 /* Notify each driver instance of its new HDEV association */ 698 ppdev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev); 699 ppdev2->pfn.CompletePDEV(ppdev2->dhpdev, (HDEV)ppdev2); 700 701 #ifdef NATIVE_REACTX 702 /* Switch DirectDraw mode */ 703 PDEVOBJ_vSwitchDirectDraw(ppdev, ppdev2); 704 #endif 705 706 return TRUE; 707 } 708 709 710 BOOL 711 NTAPI 712 PDEVOBJ_bSwitchMode( 713 PPDEVOBJ ppdev, 714 PDEVMODEW pdm) 715 { 716 PPDEVOBJ ppdevTmp; 717 PSURFACE pSurface; 718 BOOL retval = FALSE; 719 720 /* Lock the PDEV */ 721 EngAcquireSemaphore(ppdev->hsemDevLock); 722 723 /* And everything else */ 724 EngAcquireSemaphore(ghsemPDEV); 725 726 DPRINT1("PDEVOBJ_bSwitchMode, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface); 727 728 // Lookup the GraphicsDevice + select DEVMODE 729 // pdm = LDEVOBJ_bProbeAndCaptureDevmode(ppdev, pdm); 730 731 /* 1. Temporarily disable the current PDEV and reset video to its default mode */ 732 if (!PDEVOBJ_bDisableDisplay(ppdev)) 733 { 734 DPRINT1("PDEVOBJ_bDisableDisplay() failed\n"); 735 #ifdef NATIVE_REACTX 736 /* Resume DirectDraw in case of failure */ 737 PDEVOBJ_vResumeDirectDraw(ppdev); 738 #endif 739 goto leave; 740 } 741 742 /* 2. Create new PDEV */ 743 ppdevTmp = PDEVOBJ_Create(ppdev->pGraphicsDevice, pdm, 0, LDEV_DEVICE_DISPLAY); 744 if (!ppdevTmp) 745 { 746 DPRINT1("Failed to create a new PDEV\n"); 747 goto leave2; 748 } 749 750 /* 3. Create a new surface */ 751 pSurface = PDEVOBJ_pSurface(ppdevTmp); 752 if (!pSurface) 753 { 754 DPRINT1("PDEVOBJ_pSurface failed\n"); 755 PDEVOBJ_vRelease(ppdevTmp); 756 goto leave2; 757 } 758 759 #ifdef NATIVE_REACTX 760 /* 4. Temporarily suspend DirectDraw for mode change */ 761 PDEVOBJ_vSuspendDirectDraw(ppdev); 762 PDEVOBJ_vSuspendDirectDraw(ppdevTmp); 763 #endif 764 765 /* 5. Switch the PDEVs */ 766 if (!PDEVOBJ_bDynamicModeChange(ppdev, ppdevTmp)) 767 { 768 DPRINT1("PDEVOBJ_bDynamicModeChange() failed\n"); 769 PDEVOBJ_vRelease(ppdevTmp); 770 goto leave2; 771 } 772 773 #ifdef NATIVE_REACTX 774 /* 6. Resume DirectDraw */ 775 PDEVOBJ_vResumeDirectDraw(ppdev); 776 PDEVOBJ_vResumeDirectDraw(ppdevTmp); 777 #endif 778 779 /* Release temp PDEV */ 780 PDEVOBJ_vRelease(ppdevTmp); 781 782 #ifdef NATIVE_REACTX 783 /* Re-initialize DirectDraw data */ 784 ppdev->pEDDgpl->hDev = (HDEV)ppdev; 785 ppdev->pEDDgpl->dhpdev = ppdev->dhpdev; 786 #endif 787 788 /* Update primary display capabilities */ 789 if (ppdev == gpmdev->ppdevGlobal) 790 { 791 PDEVOBJ_vGetDeviceCaps(ppdev, &GdiHandleTable->DevCaps); 792 } 793 794 /* Success! */ 795 retval = TRUE; 796 797 leave2: 798 /* Set the new video mode, or restore the original one in case of failure */ 799 PDEVOBJ_vEnableDisplay(ppdev); 800 801 leave: 802 /* Unlock everything else */ 803 EngReleaseSemaphore(ghsemPDEV); 804 /* Unlock the PDEV */ 805 EngReleaseSemaphore(ppdev->hsemDevLock); 806 807 DPRINT1("leave, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface); 808 809 return retval; 810 } 811 812 813 PPDEVOBJ 814 NTAPI 815 EngpGetPDEV( 816 _In_opt_ PUNICODE_STRING pustrDeviceName) 817 { 818 UNICODE_STRING ustrCurrent; 819 PPDEVOBJ ppdev = NULL; 820 PGRAPHICS_DEVICE pGraphicsDevice; 821 ULONG i; 822 823 /* Acquire PDEV lock */ 824 EngAcquireSemaphore(ghsemPDEV); 825 826 /* Did the caller pass a device name? */ 827 if (pustrDeviceName) 828 { 829 /* Loop all present PDEVs */ 830 for (i = 0; i < gpmdev->cDev; i++) 831 { 832 /* Get a pointer to the GRAPHICS_DEVICE */ 833 pGraphicsDevice = gpmdev->dev[i].ppdev->pGraphicsDevice; 834 835 /* Compare the name */ 836 RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName); 837 if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE)) 838 { 839 /* Found! */ 840 ppdev = gpmdev->dev[i].ppdev; 841 break; 842 } 843 } 844 } 845 else if (gpmdev) 846 { 847 /* Otherwise use the primary PDEV */ 848 ppdev = gpmdev->ppdevGlobal; 849 } 850 851 /* Did we find one? */ 852 if (ppdev) 853 { 854 /* Yes, reference the PDEV */ 855 PDEVOBJ_vReference(ppdev); 856 } 857 858 /* Release PDEV lock */ 859 EngReleaseSemaphore(ghsemPDEV); 860 861 return ppdev; 862 } 863 864 LONG 865 PDEVOBJ_lChangeDisplaySettings( 866 _In_opt_ PUNICODE_STRING pustrDeviceName, 867 _In_opt_ PDEVMODEW RequestedMode, 868 _In_opt_ PMDEVOBJ pmdevOld, 869 _Out_ PMDEVOBJ *ppmdevNew, 870 _In_ BOOL bSearchClosestMode) 871 { 872 PGRAPHICS_DEVICE pGraphicsDevice = NULL; 873 PMDEVOBJ pmdev = NULL; 874 PDEVMODEW pdm = NULL; 875 ULONG lRet = DISP_CHANGE_SUCCESSFUL; 876 ULONG i, j; 877 878 TRACE("PDEVOBJ_lChangeDisplaySettings('%wZ' '%dx%dx%d (%d Hz)' %p %p)\n", 879 pustrDeviceName, 880 RequestedMode ? RequestedMode->dmPelsWidth : 0, 881 RequestedMode ? RequestedMode->dmPelsHeight : 0, 882 RequestedMode ? RequestedMode->dmBitsPerPel : 0, 883 RequestedMode ? RequestedMode->dmDisplayFrequency : 0, 884 pmdevOld, ppmdevNew); 885 886 if (pustrDeviceName) 887 { 888 pGraphicsDevice = EngpFindGraphicsDevice(pustrDeviceName, 0); 889 if (!pGraphicsDevice) 890 { 891 ERR("Wrong device name provided: '%wZ'\n", pustrDeviceName); 892 lRet = DISP_CHANGE_BADPARAM; 893 goto cleanup; 894 } 895 } 896 else if (RequestedMode) 897 { 898 pGraphicsDevice = gpPrimaryGraphicsDevice; 899 if (!pGraphicsDevice) 900 { 901 ERR("Wrong device'\n"); 902 lRet = DISP_CHANGE_BADPARAM; 903 goto cleanup; 904 } 905 } 906 907 if (pGraphicsDevice) 908 { 909 if (!LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, RequestedMode, &pdm, bSearchClosestMode)) 910 { 911 ERR("DrvProbeAndCaptureDevmode() failed\n"); 912 lRet = DISP_CHANGE_BADMODE; 913 goto cleanup; 914 } 915 } 916 917 /* Here, we know that input parameters were correct */ 918 919 { 920 /* Create new MDEV. Note that if we provide a device name, 921 * MDEV will only contain one device. 922 * */ 923 924 if (pmdevOld) 925 { 926 /* Disable old MDEV */ 927 if (MDEVOBJ_bDisable(pmdevOld)) 928 { 929 /* Create new MDEV. On failure, reenable old MDEV */ 930 pmdev = MDEVOBJ_Create(pustrDeviceName, pdm); 931 if (!pmdev) 932 MDEVOBJ_vEnable(pmdevOld); 933 } 934 } 935 else 936 { 937 pmdev = MDEVOBJ_Create(pustrDeviceName, pdm); 938 } 939 940 if (!pmdev) 941 { 942 ERR("Failed to create new MDEV\n"); 943 lRet = DISP_CHANGE_FAILED; 944 goto cleanup; 945 } 946 947 lRet = DISP_CHANGE_SUCCESSFUL; 948 *ppmdevNew = pmdev; 949 950 /* We now have to do the mode switch */ 951 952 if (pustrDeviceName && pmdevOld) 953 { 954 /* We changed settings of one device. Add other devices which were already present */ 955 for (i = 0; i < pmdevOld->cDev; i++) 956 { 957 for (j = 0; j < pmdev->cDev; j++) 958 { 959 if (pmdev->dev[j].ppdev->pGraphicsDevice == pmdevOld->dev[i].ppdev->pGraphicsDevice) 960 { 961 if (PDEVOBJ_bDynamicModeChange(pmdevOld->dev[i].ppdev, pmdev->dev[j].ppdev)) 962 { 963 PPDEVOBJ tmp = pmdevOld->dev[i].ppdev; 964 pmdevOld->dev[i].ppdev = pmdev->dev[j].ppdev; 965 pmdev->dev[j].ppdev = tmp; 966 } 967 else 968 { 969 ERR("Failed to apply new settings\n"); 970 UNIMPLEMENTED; 971 ASSERT(FALSE); 972 } 973 break; 974 } 975 } 976 if (j == pmdev->cDev) 977 { 978 PDEVOBJ_vReference(pmdevOld->dev[i].ppdev); 979 pmdev->dev[pmdev->cDev].ppdev = pmdevOld->dev[i].ppdev; 980 pmdev->cDev++; 981 } 982 } 983 } 984 985 if (pmdev->cDev == 1) 986 { 987 pmdev->ppdevGlobal = pmdev->dev[0].ppdev; 988 } 989 else 990 { 991 /* Enable MultiDriver */ 992 pmdev->ppdevGlobal = PDEVOBJ_Create(NULL, (PDEVMODEW)pmdev, 0, LDEV_DEVICE_META); 993 if (!pmdev->ppdevGlobal) 994 { 995 WARN("Failed to create meta-device. Using only first display\n"); 996 PDEVOBJ_vReference(pmdev->dev[0].ppdev); 997 pmdev->ppdevGlobal = pmdev->dev[0].ppdev; 998 } 999 } 1000 1001 if (pmdevOld) 1002 { 1003 /* Search PDEVs which were in pmdevOld, but are not anymore in pmdev, and disable them */ 1004 for (i = 0; i < pmdevOld->cDev; i++) 1005 { 1006 for (j = 0; j < pmdev->cDev; j++) 1007 { 1008 if (pmdev->dev[j].ppdev->pGraphicsDevice == pmdevOld->dev[i].ppdev->pGraphicsDevice) 1009 break; 1010 } 1011 if (j == pmdev->cDev) 1012 PDEVOBJ_bDisableDisplay(pmdevOld->dev[i].ppdev); 1013 } 1014 } 1015 } 1016 1017 cleanup: 1018 if (lRet != DISP_CHANGE_SUCCESSFUL) 1019 { 1020 *ppmdevNew = NULL; 1021 if (pmdev) 1022 MDEVOBJ_vDestroy(pmdev); 1023 if (pdm && pdm != RequestedMode) 1024 ExFreePoolWithTag(pdm, GDITAG_DEVMODE); 1025 } 1026 1027 return lRet; 1028 } 1029 1030 INT 1031 NTAPI 1032 PDEVOBJ_iGetColorManagementCaps(PPDEVOBJ ppdev) 1033 { 1034 INT ret = CM_NONE; 1035 1036 if (ppdev->flFlags & PDEV_DISPLAY) 1037 { 1038 if (ppdev->devinfo.iDitherFormat == BMF_8BPP || 1039 ppdev->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP) 1040 ret = CM_GAMMA_RAMP; 1041 } 1042 1043 if (ppdev->devinfo.flGraphicsCaps & GCAPS_CMYKCOLOR) 1044 ret |= CM_CMYK_COLOR; 1045 if (ppdev->devinfo.flGraphicsCaps & GCAPS_ICM) 1046 ret |= CM_DEVICE_ICM; 1047 1048 return ret; 1049 } 1050 1051 VOID 1052 NTAPI 1053 PDEVOBJ_vGetDeviceCaps( 1054 IN PPDEVOBJ ppdev, 1055 OUT PDEVCAPS pDevCaps) 1056 { 1057 PGDIINFO pGdiInfo = &ppdev->gdiinfo; 1058 1059 pDevCaps->ulVersion = pGdiInfo->ulVersion; 1060 pDevCaps->ulTechnology = pGdiInfo->ulTechnology; 1061 pDevCaps->ulHorzSizeM = (pGdiInfo->ulHorzSize + 500) / 1000; 1062 pDevCaps->ulVertSizeM = (pGdiInfo->ulVertSize + 500) / 1000; 1063 pDevCaps->ulHorzSize = pGdiInfo->ulHorzSize; 1064 pDevCaps->ulVertSize = pGdiInfo->ulVertSize; 1065 pDevCaps->ulHorzRes = pGdiInfo->ulHorzRes; 1066 pDevCaps->ulVertRes = pGdiInfo->ulVertRes; 1067 pDevCaps->ulBitsPixel = pGdiInfo->cBitsPixel; 1068 if (pDevCaps->ulBitsPixel == 15) pDevCaps->ulBitsPixel = 16; 1069 pDevCaps->ulPlanes = pGdiInfo->cPlanes; 1070 pDevCaps->ulNumPens = pGdiInfo->ulNumColors; 1071 if (pDevCaps->ulNumPens != -1) pDevCaps->ulNumPens *= 5; 1072 pDevCaps->ulNumFonts = 0; // PDEVOBJ_cFonts(ppdev); 1073 pDevCaps->ulNumColors = pGdiInfo->ulNumColors; 1074 pDevCaps->ulRasterCaps = pGdiInfo->flRaster; 1075 pDevCaps->ulAspectX = pGdiInfo->ulAspectX; 1076 pDevCaps->ulAspectY = pGdiInfo->ulAspectY; 1077 pDevCaps->ulAspectXY = pGdiInfo->ulAspectXY; 1078 pDevCaps->ulLogPixelsX = pGdiInfo->ulLogPixelsX; 1079 pDevCaps->ulLogPixelsY = pGdiInfo->ulLogPixelsY; 1080 pDevCaps->ulSizePalette = pGdiInfo->ulNumPalReg; 1081 pDevCaps->ulColorRes = pGdiInfo->ulDACRed + 1082 pGdiInfo->ulDACGreen + 1083 pGdiInfo->ulDACBlue; 1084 pDevCaps->ulPhysicalWidth = pGdiInfo->szlPhysSize.cx; 1085 pDevCaps->ulPhysicalHeight = pGdiInfo->szlPhysSize.cy; 1086 pDevCaps->ulPhysicalOffsetX = pGdiInfo->ptlPhysOffset.x; 1087 pDevCaps->ulPhysicalOffsetY = pGdiInfo->ptlPhysOffset.y; 1088 pDevCaps->ulTextCaps = pGdiInfo->flTextCaps; 1089 pDevCaps->ulTextCaps |= (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER); 1090 if (pGdiInfo->ulTechnology != DT_PLOTTER) 1091 pDevCaps->ulTextCaps |= TC_VA_ABLE; 1092 pDevCaps->ulVRefresh = pGdiInfo->ulVRefresh; 1093 pDevCaps->ulDesktopHorzRes = pGdiInfo->ulHorzRes; 1094 pDevCaps->ulDesktopVertRes = pGdiInfo->ulVertRes; 1095 pDevCaps->ulBltAlignment = pGdiInfo->ulBltAlignment; 1096 pDevCaps->ulPanningHorzRes = pGdiInfo->ulPanningHorzRes; 1097 pDevCaps->ulPanningVertRes = pGdiInfo->ulPanningVertRes; 1098 pDevCaps->xPanningAlignment = pGdiInfo->xPanningAlignment; 1099 pDevCaps->yPanningAlignment = pGdiInfo->yPanningAlignment; 1100 pDevCaps->ulShadeBlend = pGdiInfo->flShadeBlend; 1101 pDevCaps->ulColorMgmtCaps = PDEVOBJ_iGetColorManagementCaps(ppdev); 1102 } 1103 1104 1105 /** Exported functions ********************************************************/ 1106 1107 /* 1108 * @implemented 1109 */ 1110 BOOL 1111 APIENTRY 1112 EngQueryDeviceAttribute( 1113 _In_ HDEV hdev, 1114 _In_ ENG_DEVICE_ATTRIBUTE devAttr, 1115 _In_reads_bytes_(cjInSize) PVOID pvIn, 1116 _In_ ULONG cjInSize, 1117 _Out_writes_bytes_(cjOutSize) PVOID pvOut, 1118 _In_ ULONG cjOutSize) 1119 { 1120 PPDEVOBJ ppdev = (PPDEVOBJ)hdev; 1121 1122 if (devAttr != QDA_ACCELERATION_LEVEL) 1123 return FALSE; 1124 1125 if (cjOutSize >= sizeof(DWORD)) 1126 { 1127 /* Set all Accelerations Level Key to enabled Full 0 to 5 turned off. */ 1128 *(DWORD*)pvOut = ppdev->dwAccelerationLevel; 1129 return TRUE; 1130 } 1131 1132 return FALSE; 1133 } 1134 1135 _Must_inspect_result_ _Ret_z_ 1136 LPWSTR 1137 APIENTRY 1138 EngGetDriverName(_In_ HDEV hdev) 1139 { 1140 PPDEVOBJ ppdev = (PPDEVOBJ)hdev; 1141 1142 ASSERT(ppdev); 1143 ASSERT(ppdev->pldev); 1144 ASSERT(ppdev->pldev->pGdiDriverInfo); 1145 ASSERT(ppdev->pldev->pGdiDriverInfo->DriverName.Buffer); 1146 1147 return ppdev->pldev->pGdiDriverInfo->DriverName.Buffer; 1148 } 1149 1150 1151 INT 1152 APIENTRY 1153 NtGdiGetDeviceCaps( 1154 HDC hdc, 1155 INT Index) 1156 { 1157 PDC pdc; 1158 DEVCAPS devcaps; 1159 1160 /* Lock the given DC */ 1161 pdc = DC_LockDc(hdc); 1162 if (!pdc) 1163 { 1164 EngSetLastError(ERROR_INVALID_HANDLE); 1165 return 0; 1166 } 1167 1168 /* Get the data */ 1169 PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps); 1170 1171 /* Unlock the DC */ 1172 DC_UnlockDc(pdc); 1173 1174 /* Return capability */ 1175 switch (Index) 1176 { 1177 case DRIVERVERSION: 1178 return devcaps.ulVersion; 1179 1180 case TECHNOLOGY: 1181 return devcaps.ulTechnology; 1182 1183 case HORZSIZE: 1184 return devcaps.ulHorzSize; 1185 1186 case VERTSIZE: 1187 return devcaps.ulVertSize; 1188 1189 case HORZRES: 1190 return devcaps.ulHorzRes; 1191 1192 case VERTRES: 1193 return devcaps.ulVertRes; 1194 1195 case LOGPIXELSX: 1196 return devcaps.ulLogPixelsX; 1197 1198 case LOGPIXELSY: 1199 return devcaps.ulLogPixelsY; 1200 1201 case BITSPIXEL: 1202 return devcaps.ulBitsPixel; 1203 1204 case PLANES: 1205 return devcaps.ulPlanes; 1206 1207 case NUMBRUSHES: 1208 return -1; 1209 1210 case NUMPENS: 1211 return devcaps.ulNumPens; 1212 1213 case NUMFONTS: 1214 return devcaps.ulNumFonts; 1215 1216 case NUMCOLORS: 1217 return devcaps.ulNumColors; 1218 1219 case ASPECTX: 1220 return devcaps.ulAspectX; 1221 1222 case ASPECTY: 1223 return devcaps.ulAspectY; 1224 1225 case ASPECTXY: 1226 return devcaps.ulAspectXY; 1227 1228 case CLIPCAPS: 1229 return CP_RECTANGLE; 1230 1231 case SIZEPALETTE: 1232 return devcaps.ulSizePalette; 1233 1234 case NUMRESERVED: 1235 return 20; 1236 1237 case COLORRES: 1238 return devcaps.ulColorRes; 1239 1240 case DESKTOPVERTRES: 1241 return devcaps.ulVertRes; 1242 1243 case DESKTOPHORZRES: 1244 return devcaps.ulHorzRes; 1245 1246 case BLTALIGNMENT: 1247 return devcaps.ulBltAlignment; 1248 1249 case SHADEBLENDCAPS: 1250 return devcaps.ulShadeBlend; 1251 1252 case COLORMGMTCAPS: 1253 return devcaps.ulColorMgmtCaps; 1254 1255 case PHYSICALWIDTH: 1256 return devcaps.ulPhysicalWidth; 1257 1258 case PHYSICALHEIGHT: 1259 return devcaps.ulPhysicalHeight; 1260 1261 case PHYSICALOFFSETX: 1262 return devcaps.ulPhysicalOffsetX; 1263 1264 case PHYSICALOFFSETY: 1265 return devcaps.ulPhysicalOffsetY; 1266 1267 case VREFRESH: 1268 return devcaps.ulVRefresh; 1269 1270 case RASTERCAPS: 1271 return devcaps.ulRasterCaps; 1272 1273 case CURVECAPS: 1274 return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE | 1275 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT); 1276 1277 case LINECAPS: 1278 return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE | 1279 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS); 1280 1281 case POLYGONALCAPS: 1282 return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE | 1283 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS); 1284 1285 case TEXTCAPS: 1286 return devcaps.ulTextCaps; 1287 1288 case CAPS1: 1289 case PDEVICESIZE: 1290 case SCALINGFACTORX: 1291 case SCALINGFACTORY: 1292 default: 1293 return 0; 1294 } 1295 1296 return 0; 1297 } 1298 1299 _Success_(return!=FALSE) 1300 BOOL 1301 APIENTRY 1302 NtGdiGetDeviceCapsAll( 1303 IN HDC hDC, 1304 OUT PDEVCAPS pDevCaps) 1305 { 1306 PDC pdc; 1307 DEVCAPS devcaps; 1308 BOOL bResult = TRUE; 1309 1310 /* Lock the given DC */ 1311 pdc = DC_LockDc(hDC); 1312 if (!pdc) 1313 { 1314 EngSetLastError(ERROR_INVALID_HANDLE); 1315 return FALSE; 1316 } 1317 1318 /* Get the data */ 1319 PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps); 1320 1321 /* Unlock the DC */ 1322 DC_UnlockDc(pdc); 1323 1324 /* Copy data to caller */ 1325 _SEH2_TRY 1326 { 1327 ProbeForWrite(pDevCaps, sizeof(DEVCAPS), 1); 1328 RtlCopyMemory(pDevCaps, &devcaps, sizeof(DEVCAPS)); 1329 } 1330 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1331 { 1332 SetLastNtError(_SEH2_GetExceptionCode()); 1333 bResult = FALSE; 1334 } 1335 _SEH2_END; 1336 1337 return bResult; 1338 } 1339 1340 DHPDEV 1341 APIENTRY 1342 NtGdiGetDhpdev( 1343 IN HDEV hdev) 1344 { 1345 PPDEVOBJ ppdev; 1346 DHPDEV dhpdev = NULL; 1347 1348 /* Check parameter */ 1349 if (!hdev || (PCHAR)hdev < (PCHAR)MmSystemRangeStart) 1350 return NULL; 1351 1352 /* Lock PDEV list */ 1353 EngAcquireSemaphoreShared(ghsemPDEV); 1354 1355 /* Walk through the list of PDEVs */ 1356 for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext) 1357 { 1358 /* Compare with the given HDEV */ 1359 if (ppdev == (PPDEVOBJ)hdev) 1360 { 1361 /* Found the PDEV! Get it's dhpdev and break */ 1362 dhpdev = ppdev->dhpdev; 1363 break; 1364 } 1365 } 1366 1367 /* Unlock PDEV list */ 1368 EngReleaseSemaphore(ghsemPDEV); 1369 1370 return dhpdev; 1371 } 1372 1373 PSIZEL 1374 FASTCALL 1375 PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl) 1376 { 1377 if (ppdev->flFlags & PDEV_META_DEVICE) 1378 { 1379 *psizl = ppdev->szlMetaRes; 1380 } 1381 else 1382 { 1383 psizl->cx = ppdev->gdiinfo.ulHorzRes; 1384 psizl->cy = ppdev->gdiinfo.ulVertRes; 1385 } 1386 return psizl; 1387 } 1388