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