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