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