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