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