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