9ca4311a604da1576de04c73c304b65a78ab03e3
[reactos.git] / subsystems / win32 / win32k / eng / pdevobj.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Support for physical devices
5 * FILE: subsystems/win32/win32k/eng/pdevobj.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 #include <win32k.h>
10
11 #include <intrin.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 static PPDEVOBJ gppdevList = NULL;
17 PPDEVOBJ gppdevPrimary = NULL;
18 static HSEMAPHORE ghsemPDEV;
19
20 BOOL
21 NTAPI
22 InitPDEVImpl()
23 {
24 ghsemPDEV = EngCreateSemaphore();
25 return TRUE;
26 }
27
28
29 PPDEVOBJ
30 PDEVOBJ_AllocPDEV()
31 {
32 PPDEVOBJ ppdev;
33
34 ppdev = ExAllocatePoolWithTag(PagedPool, sizeof(PDEVOBJ), GDITAG_PDEV);
35 if (!ppdev)
36 return NULL;
37
38 RtlZeroMemory(ppdev, sizeof(PDEVOBJ));
39
40 ppdev->cPdevRefs = 1;
41
42 return ppdev;
43 }
44
45 VOID
46 NTAPI
47 PDEVOBJ_vRelease(PPDEVOBJ ppdev)
48 {
49 /* Lock loader */
50 EngAcquireSemaphore(ghsemPDEV);
51
52 /* Decrease reference count */
53 --ppdev->cPdevRefs;
54
55 ASSERT(ppdev->cPdevRefs >= 0) ;
56
57 /* Check if references are left */
58 if (ppdev->cPdevRefs == 0)
59 {
60 /* Do we have a surface? */
61 if(ppdev->pSurface)
62 {
63 /* Release the surface and let the driver free it */
64 SURFACE_ShareUnlockSurface(ppdev->pSurface);
65 ppdev->pfn.DisableSurface(ppdev->dhpdev);
66 }
67
68 /* Do we have a palette? */
69 if(ppdev->ppalSurf)
70 {
71 PALETTE_ShareUnlockPalette(ppdev->ppalSurf);
72 }
73
74 /* Disable PDEV */
75 ppdev->pfn.DisablePDEV(ppdev->dhpdev);
76
77 /* Remove it from list */
78 if( ppdev == gppdevList )
79 gppdevList = ppdev->ppdevNext ;
80 else
81 {
82 PPDEVOBJ ppdevCurrent = gppdevList;
83 BOOL found = FALSE ;
84 while (!found && ppdevCurrent->ppdevNext)
85 {
86 if (ppdevCurrent->ppdevNext == ppdev)
87 found = TRUE;
88 else
89 ppdevCurrent = ppdevCurrent->ppdevNext ;
90 }
91 if(found)
92 ppdevCurrent->ppdevNext = ppdev->ppdevNext;
93 }
94
95 /* Is this the primary one ? */
96 if (ppdev == gppdevPrimary)
97 gppdevPrimary = NULL;
98
99 /* Free it */
100 ExFreePoolWithTag(ppdev, GDITAG_PDEV );
101 }
102
103 /* Unlock loader */
104 EngReleaseSemaphore(ghsemPDEV);
105
106 }
107
108 BOOL
109 NTAPI
110 PDEVOBJ_bEnablePDEV(
111 PPDEVOBJ ppdev,
112 PDEVMODEW pdevmode,
113 PWSTR pwszLogAddress)
114 {
115 PFN_DrvEnablePDEV pfnEnablePDEV;
116
117 DPRINT1("PDEVOBJ_bEnablePDEV()\n");
118
119 /* Get the DrvEnablePDEV function */
120 pfnEnablePDEV = ppdev->pldev->pfn.EnablePDEV;
121
122 /* Call the drivers DrvEnablePDEV function */
123 ppdev->dhpdev = pfnEnablePDEV(pdevmode,
124 pwszLogAddress,
125 HS_DDI_MAX,
126 ppdev->ahsurf,
127 sizeof(GDIINFO),
128 &ppdev->gdiinfo,
129 sizeof(DEVINFO),
130 &ppdev->devinfo,
131 (HDEV)ppdev,
132 ppdev->pGraphicsDevice->pwszDescription,
133 ppdev->pGraphicsDevice->DeviceObject);
134
135 /* Fix up some values */
136 if (ppdev->gdiinfo.ulLogPixelsX == 0)
137 ppdev->gdiinfo.ulLogPixelsX = 96;
138
139 if (ppdev->gdiinfo.ulLogPixelsY == 0)
140 ppdev->gdiinfo.ulLogPixelsY = 96;
141
142 /* Setup Palette */
143 GDIOBJ_SetOwnership(ppdev->devinfo.hpalDefault, NULL);
144 ppdev->ppalSurf = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
145
146 DPRINT1("PDEVOBJ_bEnablePDEV - dhpdev = %p\n", ppdev->dhpdev);
147
148 return TRUE;
149 }
150
151 VOID
152 NTAPI
153 PDEVOBJ_vCompletePDEV(
154 PPDEVOBJ ppdev)
155 {
156 /* Call the drivers DrvCompletePDEV function */
157 ppdev->pldev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev);
158 }
159
160 PSURFACE
161 NTAPI
162 PDEVOBJ_pSurface(
163 PPDEVOBJ ppdev)
164 {
165 HSURF hsurf;
166
167 /* Check if we already have a surface */
168 if (ppdev->pSurface)
169 {
170 /* Increment reference count */
171 GDIOBJ_IncrementShareCount(&ppdev->pSurface->BaseObject);
172 }
173 else
174 {
175 /* Call the drivers DrvEnableSurface */
176 hsurf = ppdev->pldev->pfn.EnableSurface(ppdev->dhpdev);
177
178 /* Lock the surface */
179 ppdev->pSurface = SURFACE_ShareLockSurface(hsurf);
180 }
181
182 DPRINT("PDEVOBJ_pSurface() returning %p\n", ppdev->pSurface);
183 return ppdev->pSurface;
184 }
185
186 PDEVMODEW
187 NTAPI
188 PDEVOBJ_pdmMatchDevMode(
189 PPDEVOBJ ppdev,
190 PDEVMODEW pdm)
191 {
192 PGRAPHICS_DEVICE pGraphicsDevice;
193 PDEVMODEW pdmCurrent;
194 INT i;
195
196 pGraphicsDevice = ppdev->pGraphicsDevice;
197
198 for (i = 0; i < pGraphicsDevice->cDevModes; i++)
199 {
200 pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
201
202 /* Compare DEVMODE fields */
203 if (pdmCurrent->dmBitsPerPel == pdm->dmBitsPerPel &&
204 pdmCurrent->dmPelsWidth == pdm->dmPelsWidth &&
205 pdmCurrent->dmPelsHeight == pdm->dmPelsHeight &&
206 pdmCurrent->dmDisplayFrequency == pdm->dmDisplayFrequency)
207 {
208 /* Match! Return the DEVMODE */
209 return pdmCurrent;
210 }
211 }
212
213 /* Nothing found */
214 return NULL;
215 }
216
217
218 static
219 PPDEVOBJ
220 EngpCreatePDEV(
221 PUNICODE_STRING pustrDeviceName,
222 PDEVMODEW pdm)
223 {
224 PGRAPHICS_DEVICE pGraphicsDevice;
225 PPDEVOBJ ppdev;
226
227 /* Try to find the GRAPHICS_DEVICE */
228 pGraphicsDevice = EngpFindGraphicsDevice(pustrDeviceName, 0, 0);
229 if (!pGraphicsDevice)
230 {
231 DPRINT1("No GRAPHICS_DEVICE found for %ls!\n",
232 pustrDeviceName ? pustrDeviceName->Buffer : 0);
233 return NULL;
234 }
235
236 /* Allocate a new PDEVOBJ */
237 ppdev = PDEVOBJ_AllocPDEV();
238 if (!ppdev)
239 {
240 DPRINT1("failed to allocate a PDEV\n");
241 return NULL;
242 }
243
244 /* If no DEVMODEW is given, ... */
245 if (!pdm)
246 {
247 /* ... use the device's default one */
248 pdm = pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm;
249 DPRINT1("Using iDefaultMode = %ld\n", pGraphicsDevice->iDefaultMode);
250 }
251
252 /* Try to get a diplay driver */
253 ppdev->pldev = EngLoadDriver(pdm->dmDeviceName, LDEV_DEVICE_DISPLAY);
254 if (!ppdev->pldev)
255 {
256 DPRINT1("Could not load display driver '%ls'\n",
257 pGraphicsDevice->pDiplayDrivers);
258 ExFreePoolWithTag(ppdev, GDITAG_PDEV);
259 return NULL;
260 }
261
262 /* Copy the function table */
263 ppdev->pfn = ppdev->pldev->pfn;
264
265 /* Set MovePointer function */
266 ppdev->pfnMovePointer = ppdev->pfn.MovePointer;
267 if (!ppdev->pfnMovePointer)
268 ppdev->pfnMovePointer = EngMovePointer;
269
270 ppdev->pGraphicsDevice = pGraphicsDevice;
271 ppdev->hsemDevLock = EngCreateSemaphore();
272 // Should we change the ative mode of pGraphicsDevice ?
273 ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, pdm) ;
274
275 /* FIXME! */
276 ppdev->flFlags = PDEV_DISPLAY;
277
278 /* HACK: Don't use the pointer */
279 ppdev->Pointer.Exclude.right = -1;
280
281 /* Call the driver to enable the PDEV */
282 if (!PDEVOBJ_bEnablePDEV(ppdev, pdm, NULL))
283 {
284 DPRINT1("Failed to enable PDEV!\n");
285 ASSERT(FALSE);
286 }
287
288 /* FIXME: this must be done in a better way */
289 pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
290
291 /* Tell the driver that the PDEV is ready */
292 PDEVOBJ_vCompletePDEV(ppdev);
293
294 /* Return the PDEV */
295 return ppdev;
296 }
297
298 VOID
299 NTAPI
300 PDEVOBJ_vSwitchPdev(
301 PPDEVOBJ ppdev,
302 PPDEVOBJ ppdev2)
303 {
304 PDEVOBJ pdevTmp;
305
306 /* Exchange data */
307 pdevTmp = *ppdev;
308
309 /* Exchange driver functions */
310 ppdev->pfn = ppdev2->pfn;
311 ppdev2->pfn = pdevTmp.pfn;
312
313 /* Exchange LDEVs */
314 ppdev->pldev = ppdev2->pldev;
315 ppdev2->pldev = pdevTmp.pldev;
316
317 /* Exchange DHPDEV */
318 ppdev->dhpdev = ppdev2->dhpdev;
319 ppdev2->dhpdev = pdevTmp.dhpdev;
320
321 /* Exchange surfaces and associate them with their new PDEV */
322 ppdev->pSurface = ppdev2->pSurface;
323 ppdev2->pSurface = pdevTmp.pSurface;
324 ppdev->pSurface->SurfObj.hdev = (HDEV)ppdev;
325 ppdev2->pSurface->SurfObj.hdev = (HDEV)ppdev2;
326
327 /* Exchange devinfo */
328 ppdev->devinfo = ppdev2->devinfo;
329 ppdev2->devinfo = pdevTmp.devinfo;
330
331 /* Exchange gdiinfo */
332 ppdev->gdiinfo = ppdev2->gdiinfo;
333 ppdev2->gdiinfo = pdevTmp.gdiinfo;
334
335 /* Exchange DEVMODE */
336 ppdev->pdmwDev = ppdev2->pdmwDev;
337 ppdev2->pdmwDev = pdevTmp.pdmwDev ;
338
339 /* Notify each driver instance of its new HDEV association */
340 ppdev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev);
341 ppdev2->pfn.CompletePDEV(ppdev2->dhpdev, (HDEV)ppdev2);
342 }
343
344
345 BOOL
346 NTAPI
347 PDEVOBJ_bSwitchMode(
348 PPDEVOBJ ppdev,
349 PDEVMODEW pdm)
350 {
351 UNICODE_STRING ustrDevice;
352 PPDEVOBJ ppdevTmp;
353 PSURFACE pSurface;
354 BOOL retval = FALSE;
355
356 /* Lock the PDEV */
357 EngAcquireSemaphore(ppdev->hsemDevLock);
358 /* And everything else */
359 EngAcquireSemaphore(ghsemPDEV);
360
361 DPRINT1("PDEVOBJ_bSwitchMode, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface);
362
363 // Lookup the GraphicsDevice + select DEVMODE
364 // pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
365
366 /* 1. Temporarily disable the current PDEV */
367 if (!ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE))
368 {
369 DPRINT1("DrvAssertMode failed\n");
370 goto leave;
371 }
372
373 /* 2. Create new PDEV */
374 RtlInitUnicodeString(&ustrDevice, ppdev->pGraphicsDevice->szWinDeviceName);
375 ppdevTmp = EngpCreatePDEV(&ustrDevice, pdm);
376 if (!ppdevTmp)
377 {
378 DPRINT1("Failed to create a new PDEV\n");
379 goto leave;
380 }
381
382 /* 3. Create a new surface */
383 pSurface = PDEVOBJ_pSurface(ppdevTmp);
384 if (!pSurface)
385 {
386 DPRINT1("DrvEnableSurface failed\n");
387 goto leave;
388 }
389
390 /* 4. Get DirectDraw information */
391 /* 5. Enable DirectDraw Not traced */
392 /* 6. Copy old PDEV state to new PDEV instance */
393
394 /* 7. Switch the PDEVs */
395 PDEVOBJ_vSwitchPdev(ppdev, ppdevTmp);
396
397 /* 8. Disable DirectDraw */
398
399 PDEVOBJ_vRelease(ppdevTmp);
400
401 /* Update primary display capabilities */
402 if(ppdev == gppdevPrimary)
403 {
404 PDEVOBJ_vGetDeviceCaps(ppdev, &GdiHandleTable->DevCaps);
405 }
406
407 /* Success! */
408 retval = TRUE;
409 leave:
410 /* Unlock PDEV */
411 EngReleaseSemaphore(ppdev->hsemDevLock);
412 EngReleaseSemaphore(ghsemPDEV);
413
414 DPRINT1("leave, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface);
415
416 return retval;
417 }
418
419
420 PPDEVOBJ
421 NTAPI
422 EngpGetPDEV(
423 PUNICODE_STRING pustrDeviceName)
424 {
425 UNICODE_STRING ustrCurrent;
426 PPDEVOBJ ppdev;
427 PGRAPHICS_DEVICE pGraphicsDevice;
428
429 /* Acquire PDEV lock */
430 EngAcquireSemaphore(ghsemPDEV);
431
432 /* If no device name is given, ... */
433 if (!pustrDeviceName && gppdevPrimary)
434 {
435 /* ... use the primary PDEV */
436 ppdev = gppdevPrimary;
437
438 /* Reference the pdev */
439 InterlockedIncrement(&ppdev->cPdevRefs);
440 goto leave;
441 }
442
443 /* Loop all present PDEVs */
444 for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext)
445 {
446 /* Get a pointer to the GRAPHICS_DEVICE */
447 pGraphicsDevice = ppdev->pGraphicsDevice;
448
449 /* Compare the name */
450 RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
451 if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE))
452 {
453 /* Found! Reference the PDEV */
454 InterlockedIncrement(&ppdev->cPdevRefs);
455 break;
456 }
457 }
458
459 /* Did we find one? */
460 if (!ppdev)
461 {
462 /* No, create a new PDEV */
463 ppdev = EngpCreatePDEV(pustrDeviceName, NULL);
464 if (ppdev)
465 {
466 /* Insert the PDEV into the list */
467 ppdev->ppdevNext = gppdevList;
468 gppdevList = ppdev;
469
470 /* Set as primary PDEV, if we don't have one yet */
471 if (!gppdevPrimary)
472 {
473 gppdevPrimary = ppdev;
474 }
475 }
476 }
477
478 leave:
479 /* Release PDEV lock */
480 EngReleaseSemaphore(ghsemPDEV);
481
482 return ppdev;
483 }
484
485 INT
486 NTAPI
487 PDEVOBJ_iGetColorManagementCaps(PPDEVOBJ ppdev)
488 {
489 INT ret = CM_NONE;
490
491 if (ppdev->flFlags & PDEV_DISPLAY)
492 {
493 if (ppdev->devinfo.iDitherFormat == BMF_8BPP ||
494 ppdev->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP)
495 ret = CM_GAMMA_RAMP;
496 }
497
498 if (ppdev->devinfo.flGraphicsCaps & GCAPS_CMYKCOLOR)
499 ret |= CM_CMYK_COLOR;
500 if (ppdev->devinfo.flGraphicsCaps & GCAPS_ICM)
501 ret |= CM_DEVICE_ICM;
502
503 return ret;
504 }
505
506 VOID
507 NTAPI
508 PDEVOBJ_vGetDeviceCaps(
509 IN PPDEVOBJ ppdev,
510 OUT PDEVCAPS pDevCaps)
511 {
512 PGDIINFO pGdiInfo = &ppdev->gdiinfo;
513
514 pDevCaps->ulVersion = pGdiInfo->ulVersion;
515 pDevCaps->ulTechnology = pGdiInfo->ulTechnology;
516 pDevCaps->ulHorzSizeM = (pGdiInfo->ulHorzSize + 500) / 1000;
517 pDevCaps->ulVertSizeM = (pGdiInfo->ulVertSize + 500) / 1000;
518 pDevCaps->ulHorzSize = pGdiInfo->ulHorzSize;
519 pDevCaps->ulVertSize = pGdiInfo->ulVertSize;
520 pDevCaps->ulHorzRes = pGdiInfo->ulHorzRes;
521 pDevCaps->ulVertRes = pGdiInfo->ulVertRes;
522 pDevCaps->ulBitsPixel = pGdiInfo->cBitsPixel;
523 if (pDevCaps->ulBitsPixel == 15) pDevCaps->ulBitsPixel = 16;
524 pDevCaps->ulPlanes = pGdiInfo->cPlanes;
525 pDevCaps->ulNumPens = pGdiInfo->ulNumColors;
526 if (pDevCaps->ulNumPens != -1) pDevCaps->ulNumPens *= 5;
527 pDevCaps->ulNumFonts = 0; // PDEVOBJ_cFonts(ppdev);
528 pDevCaps->ulNumColors = pGdiInfo->ulNumColors;
529 pDevCaps->ulRasterCaps = pGdiInfo->flRaster;
530 pDevCaps->ulAspectX = pGdiInfo->ulAspectX;
531 pDevCaps->ulAspectY = pGdiInfo->ulAspectY;
532 pDevCaps->ulAspectXY = pGdiInfo->ulAspectXY;
533 pDevCaps->ulLogPixelsX = pGdiInfo->ulLogPixelsX;
534 pDevCaps->ulLogPixelsY = pGdiInfo->ulLogPixelsY;
535 pDevCaps->ulSizePalette = pGdiInfo->ulNumPalReg;
536 pDevCaps->ulColorRes = pGdiInfo->ulDACRed +
537 pGdiInfo->ulDACGreen +
538 pGdiInfo->ulDACBlue;
539 pDevCaps->ulPhysicalWidth = pGdiInfo->szlPhysSize.cx;
540 pDevCaps->ulPhysicalHeight = pGdiInfo->szlPhysSize.cy;
541 pDevCaps->ulPhysicalOffsetX = pGdiInfo->ptlPhysOffset.x;
542 pDevCaps->ulPhysicalOffsetY = pGdiInfo->ptlPhysOffset.y;
543 pDevCaps->ulTextCaps = pGdiInfo->flTextCaps;
544 pDevCaps->ulTextCaps |= (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER);
545 if (pGdiInfo->ulTechnology != DT_PLOTTER)
546 pDevCaps->ulTextCaps |= TC_VA_ABLE;
547 pDevCaps->ulVRefresh = pGdiInfo->ulVRefresh;
548 pDevCaps->ulDesktopHorzRes = pGdiInfo->ulHorzRes;
549 pDevCaps->ulDesktopVertRes = pGdiInfo->ulVertRes;
550 pDevCaps->ulBltAlignment = pGdiInfo->ulBltAlignment;
551 pDevCaps->ulPanningHorzRes = pGdiInfo->ulPanningHorzRes;
552 pDevCaps->ulPanningVertRes = pGdiInfo->ulPanningVertRes;
553 pDevCaps->xPanningAlignment = pGdiInfo->xPanningAlignment;
554 pDevCaps->yPanningAlignment = pGdiInfo->yPanningAlignment;
555 pDevCaps->ulShadeBlend = pGdiInfo->flShadeBlend;
556 pDevCaps->ulColorMgmtCaps = PDEVOBJ_iGetColorManagementCaps(ppdev);
557 }
558
559
560 /** Exported functions ********************************************************/
561
562 LPWSTR
563 APIENTRY
564 EngGetDriverName(IN HDEV hdev)
565 {
566 PPDEVOBJ ppdev = (PPDEVOBJ)hdev;
567 PLDEVOBJ pldev;
568
569 if (!hdev)
570 return NULL;
571
572 pldev = ppdev->pldev;
573 ASSERT(pldev);
574
575 if (!pldev->pGdiDriverInfo)
576 return NULL;
577
578 return pldev->pGdiDriverInfo->DriverName.Buffer;
579 }
580
581
582 INT
583 APIENTRY
584 NtGdiGetDeviceCaps(
585 HDC hdc,
586 INT Index)
587 {
588 PDC pdc;
589 DEVCAPS devcaps;
590
591 /* Lock the given DC */
592 pdc = DC_LockDc(hdc);
593 if (!pdc)
594 {
595 SetLastWin32Error(ERROR_INVALID_HANDLE);
596 return 0;
597 }
598
599 /* Get the data */
600 PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps);
601
602 /* Unlock the DC */
603 DC_UnlockDc(pdc);
604
605 /* Return capability */
606 switch (Index)
607 {
608 case DRIVERVERSION:
609 return devcaps.ulVersion;
610
611 case TECHNOLOGY:
612 return devcaps.ulTechnology;
613
614 case HORZSIZE:
615 return devcaps.ulHorzSize;
616
617 case VERTSIZE:
618 return devcaps.ulVertSize;
619
620 case HORZRES:
621 return devcaps.ulHorzRes;
622
623 case VERTRES:
624 return devcaps.ulVertRes;
625
626 case LOGPIXELSX:
627 return devcaps.ulLogPixelsX;
628
629 case LOGPIXELSY:
630 return devcaps.ulLogPixelsY;
631
632 case BITSPIXEL:
633 return devcaps.ulBitsPixel;
634
635 case PLANES:
636 return devcaps.ulPlanes;
637
638 case NUMBRUSHES:
639 return -1;
640
641 case NUMPENS:
642 return devcaps.ulNumPens;
643
644 case NUMFONTS:
645 return devcaps.ulNumFonts;
646
647 case NUMCOLORS:
648 return devcaps.ulNumColors;
649
650 case ASPECTX:
651 return devcaps.ulAspectX;
652
653 case ASPECTY:
654 return devcaps.ulAspectY;
655
656 case ASPECTXY:
657 return devcaps.ulAspectXY;
658
659 case CLIPCAPS:
660 return CP_RECTANGLE;
661
662 case SIZEPALETTE:
663 return devcaps.ulSizePalette;
664
665 case NUMRESERVED:
666 return 20;
667
668 case COLORRES:
669 return devcaps.ulColorRes;
670
671 case DESKTOPVERTRES:
672 return devcaps.ulVertRes;
673
674 case DESKTOPHORZRES:
675 return devcaps.ulHorzRes;
676
677 case BLTALIGNMENT:
678 return devcaps.ulBltAlignment;
679
680 case SHADEBLENDCAPS:
681 return devcaps.ulShadeBlend;
682
683 case COLORMGMTCAPS:
684 return devcaps.ulColorMgmtCaps;
685
686 case PHYSICALWIDTH:
687 return devcaps.ulPhysicalWidth;
688
689 case PHYSICALHEIGHT:
690 return devcaps.ulPhysicalHeight;
691
692 case PHYSICALOFFSETX:
693 return devcaps.ulPhysicalOffsetX;
694
695 case PHYSICALOFFSETY:
696 return devcaps.ulPhysicalOffsetY;
697
698 case VREFRESH:
699 return devcaps.ulVRefresh;
700
701 case RASTERCAPS:
702 return devcaps.ulRasterCaps;
703
704 case CURVECAPS:
705 return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
706 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
707
708 case LINECAPS:
709 return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
710 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
711
712 case POLYGONALCAPS:
713 return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
714 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
715
716 case TEXTCAPS:
717 return devcaps.ulTextCaps;
718
719 case CAPS1:
720 case PDEVICESIZE:
721 case SCALINGFACTORX:
722 case SCALINGFACTORY:
723 default:
724 return 0;
725 }
726
727 return 0;
728 }
729
730
731 BOOL
732 APIENTRY
733 NtGdiGetDeviceCapsAll(
734 IN HDC hDC,
735 OUT PDEVCAPS pDevCaps)
736 {
737 PDC pdc;
738 DEVCAPS devcaps;
739 BOOL bResult = TRUE;
740
741 /* Lock the given DC */
742 pdc = DC_LockDc(hDC);
743 if (!pdc)
744 {
745 SetLastWin32Error(ERROR_INVALID_HANDLE);
746 return FALSE;
747 }
748
749 /* Get the data */
750 PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps);
751
752 /* Unlock the DC */
753 DC_UnlockDc(pdc);
754
755 /* Copy data to caller */
756 _SEH2_TRY
757 {
758 ProbeForWrite(pDevCaps, sizeof(DEVCAPS), 1);
759 RtlCopyMemory(pDevCaps, &devcaps, sizeof(DEVCAPS));
760 }
761 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
762 {
763 SetLastNtError(_SEH2_GetExceptionCode());
764 bResult = FALSE;
765 }
766 _SEH2_END;
767
768 return bResult;
769 }
770
771 DHPDEV
772 APIENTRY
773 NtGdiGetDhpdev(
774 IN HDEV hdev)
775 {
776 PPDEVOBJ ppdev;
777 DHPDEV dhpdev = NULL;
778
779 /* Check parameter */
780 if (!hdev || (PCHAR)hdev < (PCHAR)MmSystemRangeStart)
781 return NULL;
782
783 /* Lock PDEV list */
784 EngAcquireSemaphore(ghsemPDEV);
785
786 /* Walk through the list of PDEVs */
787 for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext)
788 {
789 /* Compare with the given HDEV */
790 if (ppdev == hdev)
791 {
792 /* Found the PDEV! Get it's dhpdev and break */
793 dhpdev = ppdev->dhpdev;
794 break;
795 }
796 }
797
798 /* Unlock PDEV list */
799 EngReleaseSemaphore(ghsemPDEV);
800
801 return dhpdev;
802 }
803
804 PSIZEL
805 FASTCALL
806 PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl)
807 {
808 if (ppdev->flFlags & PDEV_META_DEVICE)
809 {
810 psizl->cx = ppdev->ulHorzRes;
811 psizl->cy = ppdev->ulVertRes;
812 }
813 else
814 {
815 psizl->cx = ppdev->gdiinfo.ulHorzRes;
816 psizl->cy = ppdev->gdiinfo.ulVertRes;
817 }
818 return psizl;
819 }