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