/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Support for physical devices * FILE: win32ss/gdi/eng/pdevobj.c * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org) */ #include #define NDEBUG #include PPDEVOBJ gppdevPrimary = NULL; static PPDEVOBJ gppdevList = NULL; static HSEMAPHORE ghsemPDEV; INIT_FUNCTION NTSTATUS NTAPI InitPDEVImpl(VOID) { ghsemPDEV = EngCreateSemaphore(); if (!ghsemPDEV) return STATUS_INSUFFICIENT_RESOURCES; return STATUS_SUCCESS; } #if DBG PPDEVOBJ NTAPI DbgLookupDHPDEV(DHPDEV dhpdev) { PPDEVOBJ ppdev; /* Lock PDEV list */ EngAcquireSemaphoreShared(ghsemPDEV); /* Walk through the list of PDEVs */ for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext) { /* Compare with the given DHPDEV */ if (ppdev->dhpdev == dhpdev) break; } /* Unlock PDEV list */ EngReleaseSemaphore(ghsemPDEV); return ppdev; } #endif PPDEVOBJ PDEVOBJ_AllocPDEV(VOID) { PPDEVOBJ ppdev; ppdev = ExAllocatePoolWithTag(PagedPool, sizeof(PDEVOBJ), GDITAG_PDEV); if (!ppdev) return NULL; RtlZeroMemory(ppdev, sizeof(PDEVOBJ)); ppdev->hsemDevLock = EngCreateSemaphore(); if (ppdev->hsemDevLock == NULL) { ExFreePoolWithTag(ppdev, GDITAG_PDEV); return NULL; } /* Allocate EDD_DIRECTDRAW_GLOBAL for our ReactX driver */ ppdev->pEDDgpl = ExAllocatePoolWithTag(PagedPool, sizeof(EDD_DIRECTDRAW_GLOBAL), GDITAG_PDEV); if (ppdev->pEDDgpl) RtlZeroMemory(ppdev->pEDDgpl, sizeof(EDD_DIRECTDRAW_GLOBAL)); ppdev->cPdevRefs = 1; return ppdev; } static VOID PDEVOBJ_vDeletePDEV( PPDEVOBJ ppdev) { EngDeleteSemaphore(ppdev->hsemDevLock); if (ppdev->pEDDgpl) ExFreePoolWithTag(ppdev->pEDDgpl, GDITAG_PDEV); ExFreePoolWithTag(ppdev, GDITAG_PDEV); } VOID NTAPI PDEVOBJ_vRelease(PPDEVOBJ ppdev) { /* Lock loader */ EngAcquireSemaphore(ghsemPDEV); /* Decrease reference count */ --ppdev->cPdevRefs; ASSERT(ppdev->cPdevRefs >= 0) ; /* Check if references are left */ if (ppdev->cPdevRefs == 0) { /* Do we have a surface? */ if (ppdev->pSurface) { /* Release the surface and let the driver free it */ SURFACE_ShareUnlockSurface(ppdev->pSurface); ppdev->pfn.DisableSurface(ppdev->dhpdev); } /* Do we have a palette? */ if(ppdev->ppalSurf) { PALETTE_ShareUnlockPalette(ppdev->ppalSurf); } /* Check if the PDEV was enabled */ if (ppdev->dhpdev != NULL) { /* Disable the PDEV */ ppdev->pfn.DisablePDEV(ppdev->dhpdev); } /* Remove it from list */ if( ppdev == gppdevList ) gppdevList = ppdev->ppdevNext ; else { PPDEVOBJ ppdevCurrent = gppdevList; BOOL found = FALSE ; while (!found && ppdevCurrent->ppdevNext) { if (ppdevCurrent->ppdevNext == ppdev) found = TRUE; else ppdevCurrent = ppdevCurrent->ppdevNext ; } if(found) ppdevCurrent->ppdevNext = ppdev->ppdevNext; } /* Is this the primary one ? */ if (ppdev == gppdevPrimary) gppdevPrimary = NULL; /* Free it */ PDEVOBJ_vDeletePDEV(ppdev); } /* Unlock loader */ EngReleaseSemaphore(ghsemPDEV); } BOOL NTAPI PDEVOBJ_bEnablePDEV( PPDEVOBJ ppdev, PDEVMODEW pdevmode, PWSTR pwszLogAddress) { PFN_DrvEnablePDEV pfnEnablePDEV; ULONG i; DPRINT("PDEVOBJ_bEnablePDEV()\n"); /* Get the DrvEnablePDEV function */ pfnEnablePDEV = ppdev->pldev->pfn.EnablePDEV; /* Call the drivers DrvEnablePDEV function */ ppdev->dhpdev = pfnEnablePDEV(pdevmode, pwszLogAddress, HS_DDI_MAX, ppdev->ahsurf, sizeof(GDIINFO), (PULONG)&ppdev->gdiinfo, sizeof(DEVINFO), &ppdev->devinfo, (HDEV)ppdev, ppdev->pGraphicsDevice->pwszDescription, ppdev->pGraphicsDevice->DeviceObject); if (ppdev->dhpdev == NULL) { DPRINT1("Failed to enable PDEV\n"); return FALSE; } /* Fix up some values */ if (ppdev->gdiinfo.ulLogPixelsX == 0) ppdev->gdiinfo.ulLogPixelsX = 96; if (ppdev->gdiinfo.ulLogPixelsY == 0) ppdev->gdiinfo.ulLogPixelsY = 96; /* Set raster caps */ ppdev->gdiinfo.flRaster = RC_OP_DX_OUTPUT | RC_GDI20_OUTPUT | RC_BIGFONT; if ((ppdev->gdiinfo.ulTechnology != DT_PLOTTER) && (ppdev->gdiinfo.ulTechnology != DT_CHARSTREAM)) ppdev->gdiinfo.flRaster |= RC_STRETCHDIB | RC_STRETCHBLT | RC_DIBTODEV | RC_DI_BITMAP | RC_BITMAP64 | RC_BITBLT; if (ppdev->gdiinfo.ulTechnology == DT_RASDISPLAY) ppdev->gdiinfo.flRaster |= RC_FLOODFILL; if (ppdev->devinfo.flGraphicsCaps & GCAPS_PALMANAGED) ppdev->gdiinfo.flRaster |= RC_PALETTE; /* Setup Palette */ ppdev->ppalSurf = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault); /* Setup hatch brushes */ for (i = 0; i < HS_DDI_MAX; i++) { if (ppdev->ahsurf[i] == NULL) ppdev->ahsurf[i] = gahsurfHatch[i]; } DPRINT("PDEVOBJ_bEnablePDEV - dhpdev = %p\n", ppdev->dhpdev); return TRUE; } VOID NTAPI PDEVOBJ_vCompletePDEV( PPDEVOBJ ppdev) { /* Call the drivers DrvCompletePDEV function */ ppdev->pldev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev); } PSURFACE NTAPI PDEVOBJ_pSurface( PPDEVOBJ ppdev) { HSURF hsurf; /* Check if there is no surface for this PDEV yet */ if (ppdev->pSurface == NULL) { /* Call the drivers DrvEnableSurface */ hsurf = ppdev->pldev->pfn.EnableSurface(ppdev->dhpdev); if (hsurf== NULL) { DPRINT1("Failed to create PDEV surface!\n"); return NULL; } /* Get a reference to the surface */ ppdev->pSurface = SURFACE_ShareLockSurface(hsurf); NT_ASSERT(ppdev->pSurface != NULL); } /* Increment reference count */ GDIOBJ_vReferenceObjectByPointer(&ppdev->pSurface->BaseObject); DPRINT("PDEVOBJ_pSurface() returning %p\n", ppdev->pSurface); return ppdev->pSurface; } VOID NTAPI PDEVOBJ_vRefreshModeList( PPDEVOBJ ppdev) { PGRAPHICS_DEVICE pGraphicsDevice; PDEVMODEINFO pdminfo, pdmiNext; DEVMODEW dmDefault; DEVMODEW dmCurrent; /* Lock the PDEV */ EngAcquireSemaphore(ppdev->hsemDevLock); pGraphicsDevice = ppdev->pGraphicsDevice; /* Remember our default mode */ dmDefault = *pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm; dmCurrent = *ppdev->pdmwDev; /* Clear out the modes */ for (pdminfo = pGraphicsDevice->pdevmodeInfo; pdminfo; pdminfo = pdmiNext) { pdmiNext = pdminfo->pdmiNext; ExFreePoolWithTag(pdminfo, GDITAG_DEVMODE); } pGraphicsDevice->pdevmodeInfo = NULL; ExFreePoolWithTag(pGraphicsDevice->pDevModeList, GDITAG_GDEVICE); pGraphicsDevice->pDevModeList = NULL; /* Now re-populate the list */ if (!EngpPopulateDeviceModeList(pGraphicsDevice, &dmDefault)) { DPRINT1("FIXME: EngpPopulateDeviceModeList failed, we just destroyed a perfectly good mode list\n"); } ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, &dmCurrent); /* Unlock PDEV */ EngReleaseSemaphore(ppdev->hsemDevLock); } PDEVMODEW NTAPI PDEVOBJ_pdmMatchDevMode( PPDEVOBJ ppdev, PDEVMODEW pdm) { PGRAPHICS_DEVICE pGraphicsDevice; PDEVMODEW pdmCurrent; ULONG i; DWORD dwFields; pGraphicsDevice = ppdev->pGraphicsDevice; for (i = 0; i < pGraphicsDevice->cDevModes; i++) { pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm; /* Compare asked DEVMODE fields * Only compare those that are valid in both DEVMODE structs */ dwFields = pdmCurrent->dmFields & pdm->dmFields ; /* For now, we only need those */ if ((dwFields & DM_BITSPERPEL) && (pdmCurrent->dmBitsPerPel != pdm->dmBitsPerPel)) continue; if ((dwFields & DM_PELSWIDTH) && (pdmCurrent->dmPelsWidth != pdm->dmPelsWidth)) continue; if ((dwFields & DM_PELSHEIGHT) && (pdmCurrent->dmPelsHeight != pdm->dmPelsHeight)) continue; if ((dwFields & DM_DISPLAYFREQUENCY) && (pdmCurrent->dmDisplayFrequency != pdm->dmDisplayFrequency)) continue; /* Match! Return the DEVMODE */ return pdmCurrent; } /* Nothing found */ return NULL; } static PPDEVOBJ EngpCreatePDEV( PUNICODE_STRING pustrDeviceName, PDEVMODEW pdm) { PGRAPHICS_DEVICE pGraphicsDevice; PPDEVOBJ ppdev; DPRINT("EngpCreatePDEV(%wZ, %p)\n", pustrDeviceName, pdm); /* Try to find the GRAPHICS_DEVICE */ if (pustrDeviceName) { pGraphicsDevice = EngpFindGraphicsDevice(pustrDeviceName, 0, 0); if (!pGraphicsDevice) { DPRINT1("No GRAPHICS_DEVICE found for %ls!\n", pustrDeviceName ? pustrDeviceName->Buffer : 0); return NULL; } } else { pGraphicsDevice = gpPrimaryGraphicsDevice; } /* Allocate a new PDEVOBJ */ ppdev = PDEVOBJ_AllocPDEV(); if (!ppdev) { DPRINT1("failed to allocate a PDEV\n"); return NULL; } /* If no DEVMODEW is given, ... */ if (!pdm) { /* ... use the device's default one */ pdm = pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm; DPRINT("Using iDefaultMode = %lu\n", pGraphicsDevice->iDefaultMode); } /* Try to get a diplay driver */ ppdev->pldev = EngLoadImageEx(pdm->dmDeviceName, LDEV_DEVICE_DISPLAY); if (!ppdev->pldev) { DPRINT1("Could not load display driver '%ls', '%ls'\n", pGraphicsDevice->pDiplayDrivers, pdm->dmDeviceName); PDEVOBJ_vRelease(ppdev); return NULL; } /* Copy the function table */ ppdev->pfn = ppdev->pldev->pfn; /* Set MovePointer function */ ppdev->pfnMovePointer = ppdev->pfn.MovePointer; if (!ppdev->pfnMovePointer) ppdev->pfnMovePointer = EngMovePointer; ppdev->pGraphicsDevice = pGraphicsDevice; // DxEngGetHdevData asks for Graphics DeviceObject in hSpooler field ppdev->hSpooler = ppdev->pGraphicsDevice->DeviceObject; // Should we change the ative mode of pGraphicsDevice ? ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, pdm) ; /* FIXME! */ ppdev->flFlags = PDEV_DISPLAY; /* HACK: Don't use the pointer */ ppdev->Pointer.Exclude.right = -1; /* Call the driver to enable the PDEV */ if (!PDEVOBJ_bEnablePDEV(ppdev, pdm, NULL)) { DPRINT1("Failed to enable PDEV!\n"); PDEVOBJ_vRelease(ppdev); return NULL; } /* FIXME: this must be done in a better way */ pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP; /* Tell the driver that the PDEV is ready */ PDEVOBJ_vCompletePDEV(ppdev); /* Return the PDEV */ return ppdev; } FORCEINLINE VOID SwitchPointer( _Inout_ PVOID pvPointer1, _Inout_ PVOID pvPointer2) { PVOID *ppvPointer1 = pvPointer1; PVOID *ppvPointer2 = pvPointer2; PVOID pvTemp; pvTemp = *ppvPointer1; *ppvPointer1 = *ppvPointer2; *ppvPointer2 = pvTemp; } VOID NTAPI PDEVOBJ_vSwitchPdev( PPDEVOBJ ppdev, PPDEVOBJ ppdev2) { union { DRIVER_FUNCTIONS pfn; GDIINFO gdiinfo; DEVINFO devinfo; DWORD StateFlags; } temp; /* Exchange driver functions */ temp.pfn = ppdev->pfn; ppdev->pfn = ppdev2->pfn; ppdev2->pfn = temp.pfn; /* Exchange LDEVs */ SwitchPointer(&ppdev->pldev, &ppdev2->pldev); /* Exchange DHPDEV */ SwitchPointer(&ppdev->dhpdev, &ppdev2->dhpdev); /* Exchange surfaces and associate them with their new PDEV */ SwitchPointer(&ppdev->pSurface, &ppdev2->pSurface); ppdev->pSurface->SurfObj.hdev = (HDEV)ppdev; ppdev2->pSurface->SurfObj.hdev = (HDEV)ppdev2; /* Exchange devinfo */ temp.devinfo = ppdev->devinfo; ppdev->devinfo = ppdev2->devinfo; ppdev2->devinfo = temp.devinfo; /* Exchange gdiinfo */ temp.gdiinfo = ppdev->gdiinfo; ppdev->gdiinfo = ppdev2->gdiinfo; ppdev2->gdiinfo = temp.gdiinfo; /* Exchange DEVMODE */ SwitchPointer(&ppdev->pdmwDev, &ppdev2->pdmwDev); /* Exchange state flags */ temp.StateFlags = ppdev->pGraphicsDevice->StateFlags; ppdev->pGraphicsDevice->StateFlags = ppdev2->pGraphicsDevice->StateFlags; ppdev2->pGraphicsDevice->StateFlags = temp.StateFlags; /* Notify each driver instance of its new HDEV association */ ppdev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev); ppdev2->pfn.CompletePDEV(ppdev2->dhpdev, (HDEV)ppdev2); } BOOL NTAPI PDEVOBJ_bSwitchMode( PPDEVOBJ ppdev, PDEVMODEW pdm) { UNICODE_STRING ustrDevice; PPDEVOBJ ppdevTmp; PSURFACE pSurface; BOOL retval = FALSE; /* Lock the PDEV */ EngAcquireSemaphore(ppdev->hsemDevLock); /* And everything else */ EngAcquireSemaphore(ghsemPDEV); DPRINT1("PDEVOBJ_bSwitchMode, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface); // Lookup the GraphicsDevice + select DEVMODE // pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm); /* 1. Temporarily disable the current PDEV and reset video to its default mode */ if (!ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE)) { DPRINT1("DrvAssertMode(FALSE) failed\n"); goto leave; } /* 2. Create new PDEV */ RtlInitUnicodeString(&ustrDevice, ppdev->pGraphicsDevice->szWinDeviceName); ppdevTmp = EngpCreatePDEV(&ustrDevice, pdm); if (!ppdevTmp) { DPRINT1("Failed to create a new PDEV\n"); goto leave2; } /* 3. Create a new surface */ pSurface = PDEVOBJ_pSurface(ppdevTmp); if (!pSurface) { DPRINT1("PDEVOBJ_pSurface failed\n"); PDEVOBJ_vRelease(ppdevTmp); goto leave2; } /* 4. Get DirectDraw information */ /* 5. Enable DirectDraw Not traced */ /* 6. Copy old PDEV state to new PDEV instance */ /* 7. Switch the PDEVs */ PDEVOBJ_vSwitchPdev(ppdev, ppdevTmp); /* 8. Disable DirectDraw */ PDEVOBJ_vRelease(ppdevTmp); /* Update primary display capabilities */ if(ppdev == gppdevPrimary) { PDEVOBJ_vGetDeviceCaps(ppdev, &GdiHandleTable->DevCaps); } /* Success! */ retval = TRUE; leave2: /* Set the new video mode, or restore the original one in case of failure */ if (!ppdev->pfn.AssertMode(ppdev->dhpdev, TRUE)) { DPRINT1("DrvAssertMode(TRUE) failed\n"); } leave: /* Unlock everything else */ EngReleaseSemaphore(ghsemPDEV); /* Unlock the PDEV */ EngReleaseSemaphore(ppdev->hsemDevLock); DPRINT1("leave, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface); return retval; } PPDEVOBJ NTAPI EngpGetPDEV( _In_opt_ PUNICODE_STRING pustrDeviceName) { UNICODE_STRING ustrCurrent; PPDEVOBJ ppdev; PGRAPHICS_DEVICE pGraphicsDevice; /* Acquire PDEV lock */ EngAcquireSemaphore(ghsemPDEV); /* Did the caller pass a device name? */ if (pustrDeviceName) { /* Loop all present PDEVs */ for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext) { /* Get a pointer to the GRAPHICS_DEVICE */ pGraphicsDevice = ppdev->pGraphicsDevice; /* Compare the name */ RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName); if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE)) { /* Found! */ break; } } } else { /* Otherwise use the primary PDEV */ ppdev = gppdevPrimary; } /* Did we find one? */ if (ppdev) { /* Yes, reference the PDEV */ InterlockedIncrement(&ppdev->cPdevRefs); } else { /* No, create a new PDEV for the given device */ ppdev = EngpCreatePDEV(pustrDeviceName, NULL); if (ppdev) { /* Insert the PDEV into the list */ ppdev->ppdevNext = gppdevList; gppdevList = ppdev; /* Set as primary PDEV, if we don't have one yet */ if (!gppdevPrimary) { gppdevPrimary = ppdev; ppdev->pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE; } } } /* Release PDEV lock */ EngReleaseSemaphore(ghsemPDEV); return ppdev; } INT NTAPI PDEVOBJ_iGetColorManagementCaps(PPDEVOBJ ppdev) { INT ret = CM_NONE; if (ppdev->flFlags & PDEV_DISPLAY) { if (ppdev->devinfo.iDitherFormat == BMF_8BPP || ppdev->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP) ret = CM_GAMMA_RAMP; } if (ppdev->devinfo.flGraphicsCaps & GCAPS_CMYKCOLOR) ret |= CM_CMYK_COLOR; if (ppdev->devinfo.flGraphicsCaps & GCAPS_ICM) ret |= CM_DEVICE_ICM; return ret; } VOID NTAPI PDEVOBJ_vGetDeviceCaps( IN PPDEVOBJ ppdev, OUT PDEVCAPS pDevCaps) { PGDIINFO pGdiInfo = &ppdev->gdiinfo; pDevCaps->ulVersion = pGdiInfo->ulVersion; pDevCaps->ulTechnology = pGdiInfo->ulTechnology; pDevCaps->ulHorzSizeM = (pGdiInfo->ulHorzSize + 500) / 1000; pDevCaps->ulVertSizeM = (pGdiInfo->ulVertSize + 500) / 1000; pDevCaps->ulHorzSize = pGdiInfo->ulHorzSize; pDevCaps->ulVertSize = pGdiInfo->ulVertSize; pDevCaps->ulHorzRes = pGdiInfo->ulHorzRes; pDevCaps->ulVertRes = pGdiInfo->ulVertRes; pDevCaps->ulBitsPixel = pGdiInfo->cBitsPixel; if (pDevCaps->ulBitsPixel == 15) pDevCaps->ulBitsPixel = 16; pDevCaps->ulPlanes = pGdiInfo->cPlanes; pDevCaps->ulNumPens = pGdiInfo->ulNumColors; if (pDevCaps->ulNumPens != -1) pDevCaps->ulNumPens *= 5; pDevCaps->ulNumFonts = 0; // PDEVOBJ_cFonts(ppdev); pDevCaps->ulNumColors = pGdiInfo->ulNumColors; pDevCaps->ulRasterCaps = pGdiInfo->flRaster; pDevCaps->ulAspectX = pGdiInfo->ulAspectX; pDevCaps->ulAspectY = pGdiInfo->ulAspectY; pDevCaps->ulAspectXY = pGdiInfo->ulAspectXY; pDevCaps->ulLogPixelsX = pGdiInfo->ulLogPixelsX; pDevCaps->ulLogPixelsY = pGdiInfo->ulLogPixelsY; pDevCaps->ulSizePalette = pGdiInfo->ulNumPalReg; pDevCaps->ulColorRes = pGdiInfo->ulDACRed + pGdiInfo->ulDACGreen + pGdiInfo->ulDACBlue; pDevCaps->ulPhysicalWidth = pGdiInfo->szlPhysSize.cx; pDevCaps->ulPhysicalHeight = pGdiInfo->szlPhysSize.cy; pDevCaps->ulPhysicalOffsetX = pGdiInfo->ptlPhysOffset.x; pDevCaps->ulPhysicalOffsetY = pGdiInfo->ptlPhysOffset.y; pDevCaps->ulTextCaps = pGdiInfo->flTextCaps; pDevCaps->ulTextCaps |= (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER); if (pGdiInfo->ulTechnology != DT_PLOTTER) pDevCaps->ulTextCaps |= TC_VA_ABLE; pDevCaps->ulVRefresh = pGdiInfo->ulVRefresh; pDevCaps->ulDesktopHorzRes = pGdiInfo->ulHorzRes; pDevCaps->ulDesktopVertRes = pGdiInfo->ulVertRes; pDevCaps->ulBltAlignment = pGdiInfo->ulBltAlignment; pDevCaps->ulPanningHorzRes = pGdiInfo->ulPanningHorzRes; pDevCaps->ulPanningVertRes = pGdiInfo->ulPanningVertRes; pDevCaps->xPanningAlignment = pGdiInfo->xPanningAlignment; pDevCaps->yPanningAlignment = pGdiInfo->yPanningAlignment; pDevCaps->ulShadeBlend = pGdiInfo->flShadeBlend; pDevCaps->ulColorMgmtCaps = PDEVOBJ_iGetColorManagementCaps(ppdev); } /** Exported functions ********************************************************/ _Must_inspect_result_ _Ret_z_ LPWSTR APIENTRY EngGetDriverName(_In_ HDEV hdev) { PPDEVOBJ ppdev = (PPDEVOBJ)hdev; ASSERT(ppdev); ASSERT(ppdev->pldev); ASSERT(ppdev->pldev->pGdiDriverInfo); ASSERT(ppdev->pldev->pGdiDriverInfo->DriverName.Buffer); return ppdev->pldev->pGdiDriverInfo->DriverName.Buffer; } INT APIENTRY NtGdiGetDeviceCaps( HDC hdc, INT Index) { PDC pdc; DEVCAPS devcaps; /* Lock the given DC */ pdc = DC_LockDc(hdc); if (!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return 0; } /* Get the data */ PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps); /* Unlock the DC */ DC_UnlockDc(pdc); /* Return capability */ switch (Index) { case DRIVERVERSION: return devcaps.ulVersion; case TECHNOLOGY: return devcaps.ulTechnology; case HORZSIZE: return devcaps.ulHorzSize; case VERTSIZE: return devcaps.ulVertSize; case HORZRES: return devcaps.ulHorzRes; case VERTRES: return devcaps.ulVertRes; case LOGPIXELSX: return devcaps.ulLogPixelsX; case LOGPIXELSY: return devcaps.ulLogPixelsY; case BITSPIXEL: return devcaps.ulBitsPixel; case PLANES: return devcaps.ulPlanes; case NUMBRUSHES: return -1; case NUMPENS: return devcaps.ulNumPens; case NUMFONTS: return devcaps.ulNumFonts; case NUMCOLORS: return devcaps.ulNumColors; case ASPECTX: return devcaps.ulAspectX; case ASPECTY: return devcaps.ulAspectY; case ASPECTXY: return devcaps.ulAspectXY; case CLIPCAPS: return CP_RECTANGLE; case SIZEPALETTE: return devcaps.ulSizePalette; case NUMRESERVED: return 20; case COLORRES: return devcaps.ulColorRes; case DESKTOPVERTRES: return devcaps.ulVertRes; case DESKTOPHORZRES: return devcaps.ulHorzRes; case BLTALIGNMENT: return devcaps.ulBltAlignment; case SHADEBLENDCAPS: return devcaps.ulShadeBlend; case COLORMGMTCAPS: return devcaps.ulColorMgmtCaps; case PHYSICALWIDTH: return devcaps.ulPhysicalWidth; case PHYSICALHEIGHT: return devcaps.ulPhysicalHeight; case PHYSICALOFFSETX: return devcaps.ulPhysicalOffsetX; case PHYSICALOFFSETY: return devcaps.ulPhysicalOffsetY; case VREFRESH: return devcaps.ulVRefresh; case RASTERCAPS: return devcaps.ulRasterCaps; case CURVECAPS: return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE | CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT); case LINECAPS: return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE | LC_STYLED | LC_WIDESTYLED | LC_INTERIORS); case POLYGONALCAPS: return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE | PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS); case TEXTCAPS: return devcaps.ulTextCaps; case CAPS1: case PDEVICESIZE: case SCALINGFACTORX: case SCALINGFACTORY: default: return 0; } return 0; } _Success_(return!=FALSE) BOOL APIENTRY NtGdiGetDeviceCapsAll( IN HDC hDC, OUT PDEVCAPS pDevCaps) { PDC pdc; DEVCAPS devcaps; BOOL bResult = TRUE; /* Lock the given DC */ pdc = DC_LockDc(hDC); if (!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } /* Get the data */ PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps); /* Unlock the DC */ DC_UnlockDc(pdc); /* Copy data to caller */ _SEH2_TRY { ProbeForWrite(pDevCaps, sizeof(DEVCAPS), 1); RtlCopyMemory(pDevCaps, &devcaps, sizeof(DEVCAPS)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); bResult = FALSE; } _SEH2_END; return bResult; } DHPDEV APIENTRY NtGdiGetDhpdev( IN HDEV hdev) { PPDEVOBJ ppdev; DHPDEV dhpdev = NULL; /* Check parameter */ if (!hdev || (PCHAR)hdev < (PCHAR)MmSystemRangeStart) return NULL; /* Lock PDEV list */ EngAcquireSemaphoreShared(ghsemPDEV); /* Walk through the list of PDEVs */ for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext) { /* Compare with the given HDEV */ if (ppdev == (PPDEVOBJ)hdev) { /* Found the PDEV! Get it's dhpdev and break */ dhpdev = ppdev->dhpdev; break; } } /* Unlock PDEV list */ EngReleaseSemaphore(ghsemPDEV); return dhpdev; } PSIZEL FASTCALL PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl) { if (ppdev->flFlags & PDEV_META_DEVICE) { psizl->cx = ppdev->ulHorzRes; psizl->cy = ppdev->ulVertRes; } else { psizl->cx = ppdev->gdiinfo.ulHorzRes; psizl->cy = ppdev->gdiinfo.ulVertRes; } return psizl; }