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