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