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