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