diff --git a/reactos/subsystems/win32/win32k/include/dc.h b/reactos/subsystems/win32/win32k/include/dc.h index d6da1862953..39c4c94a5ee 100644 --- a/reactos/subsystems/win32/win32k/include/dc.h +++ b/reactos/subsystems/win32/win32k/include/dc.h @@ -130,8 +130,8 @@ typedef struct _DCLEVEL DWORD unk1_00000000; HGDIOBJ hdcSave; POINTL ptlBrushOrigin; - PBRUSH pbrFill; - PBRUSH pbrLine; + PBRUSH pbrFill; + PBRUSH pbrLine; PVOID plfnt; /* LFONTOBJ* (TEXTOBJ*) */ HGDIOBJ hPath; /* HPATH */ FLONG flPath; @@ -278,4 +278,8 @@ INT FASTCALL IntGdiGetDeviceCaps(PDC,INT); extern PPDEVOBJ pPrimarySurface; +BOOL FASTCALL +IntPrepareDriverIfNeeded(); +extern PDEVOBJ PrimarySurface; + #endif /* not __WIN32K_DC_H */ diff --git a/reactos/subsystems/win32/win32k/objects/coord.c b/reactos/subsystems/win32/win32k/objects/coord.c index 84109b5a583..cc0a7e9f7db 100644 --- a/reactos/subsystems/win32/win32k/objects/coord.c +++ b/reactos/subsystems/win32/win32k/objects/coord.c @@ -66,6 +66,7 @@ IntFixIsotropicMapping(PDC dc) } } +// FIXME: don't use floating point in the kernel! use XFORMOBJ function BOOL FASTCALL IntGdiCombineTransform(LPXFORM XFormResult, LPXFORM xform1, @@ -115,7 +116,7 @@ BOOL APIENTRY NtGdiCombineTransform(LPXFORM UnsafeXFormResult, return Ret; } - +// FIXME: remove me! int FASTCALL IntGetGraphicsMode(PDC dc) @@ -1016,4 +1017,278 @@ NtGdiSetVirtualResolution( return TRUE; } + +// FIXME: Don't use floating point in the kernel! +BOOL FASTCALL +DC_InvertXform(const XFORM *xformSrc, + XFORM *xformDest) +{ + FLOAT determinant; + + determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21; + if (determinant > -1e-12 && determinant < 1e-12) + { + return FALSE; + } + + xformDest->eM11 = xformSrc->eM22 / determinant; + xformDest->eM12 = -xformSrc->eM12 / determinant; + xformDest->eM21 = -xformSrc->eM21 / determinant; + xformDest->eM22 = xformSrc->eM11 / determinant; + xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21; + xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22; + + return TRUE; +} + + +// FIXME: Don't use floating point in the kernel! +VOID FASTCALL +DC_UpdateXforms(PDC dc) +{ + XFORM xformWnd2Vport; + FLOAT scaleX, scaleY; + PDC_ATTR pdcattr = dc->pdcattr; + XFORM xformWorld2Vport, xformWorld2Wnd, xformVport2World; + + /* Construct a transformation to do the window-to-viewport conversion */ + scaleX = (pdcattr->szlWindowExt.cx ? (FLOAT)pdcattr->szlViewportExt.cx / (FLOAT)pdcattr->szlWindowExt.cx : 0.0f); + scaleY = (pdcattr->szlWindowExt.cy ? (FLOAT)pdcattr->szlViewportExt.cy / (FLOAT)pdcattr->szlWindowExt.cy : 0.0f); + xformWnd2Vport.eM11 = scaleX; + xformWnd2Vport.eM12 = 0.0; + xformWnd2Vport.eM21 = 0.0; + xformWnd2Vport.eM22 = scaleY; + xformWnd2Vport.eDx = (FLOAT)pdcattr->ptlViewportOrg.x - scaleX * (FLOAT)pdcattr->ptlWindowOrg.x; + xformWnd2Vport.eDy = (FLOAT)pdcattr->ptlViewportOrg.y - scaleY * (FLOAT)pdcattr->ptlWindowOrg.y; + + /* Combine with the world transformation */ + MatrixS2XForm(&xformWorld2Vport, &dc->dclevel.mxWorldToDevice); + MatrixS2XForm(&xformWorld2Wnd, &dc->dclevel.mxWorldToPage); + IntGdiCombineTransform(&xformWorld2Vport, &xformWorld2Wnd, &xformWnd2Vport); + + /* Create inverse of world-to-viewport transformation */ + MatrixS2XForm(&xformVport2World, &dc->dclevel.mxDeviceToWorld); + if (DC_InvertXform(&xformWorld2Vport, &xformVport2World)) + { + pdcattr->flXform &= ~DEVICE_TO_WORLD_INVALID; + } + else + { + pdcattr->flXform |= DEVICE_TO_WORLD_INVALID; + } + + XForm2MatrixS(&dc->dclevel.mxWorldToDevice, &xformWorld2Vport); + +} + + + + +LONG FASTCALL +IntCalcFillOrigin(PDC pdc) +{ + pdc->ptlFillOrigin.x = pdc->dclevel.ptlBrushOrigin.x + pdc->ptlDCOrig.x; + pdc->ptlFillOrigin.y = pdc->dclevel.ptlBrushOrigin.y + pdc->ptlDCOrig.y; + + return pdc->ptlFillOrigin.y; +} + +VOID +APIENTRY +GdiSetDCOrg(HDC hDC, LONG Left, LONG Top, PRECTL prc) +{ + PDC pdc; + + pdc = DC_LockDc(hDC); + if (!pdc) return; + + pdc->ptlDCOrig.x = Left; + pdc->ptlDCOrig.y = Top; + + IntCalcFillOrigin(pdc); + + if (prc) pdc->erclWindow = *prc; + + DC_UnlockDc(pdc); +} + + +BOOL FASTCALL +IntGdiGetDCOrg(PDC pDc, PPOINTL ppt) +{ + *ppt = pDc->ptlDCOrig; + return TRUE; +} + +BOOL APIENTRY +GdiGetDCOrgEx(HDC hDC, PPOINTL ppt, PRECTL prc) +{ + PDC pdc; + + pdc = DC_LockDc(hDC); + if (!pdc) return FALSE; + + *prc = pdc->erclWindow; + *ppt = pdc->ptlDCOrig; + + DC_UnlockDc(pdc); + return TRUE; +} + +BOOL FASTCALL +IntGetAspectRatioFilter(PDC pDC, + LPSIZE AspectRatio) +{ + PDC_ATTR pdcattr; + + pdcattr = pDC->pdcattr; + + if ( pdcattr->flFontMapper & 1 ) // TRUE assume 1. + { + // "This specifies that Windows should only match fonts that have the + // same aspect ratio as the display.", Programming Windows, Fifth Ed. + AspectRatio->cx = pDC->ppdev->GDIInfo.ulLogPixelsX; + AspectRatio->cy = pDC->ppdev->GDIInfo.ulLogPixelsY; + } + else + { + AspectRatio->cx = 0; + AspectRatio->cy = 0; + } + return TRUE; +} + +VOID +FASTCALL +IntGetViewportExtEx(PDC pdc, LPSIZE pSize) +{ + PDC_ATTR pdcattr; + + /* Get a pointer to the dc attribute */ + pdcattr = pdc->pdcattr; + + /* Check if we need to recalculate */ + if (pdcattr->flXform & PAGE_EXTENTS_CHANGED) + { + /* Check if we need to do isotropic fixup */ + if (pdcattr->iMapMode == MM_ISOTROPIC) + { + IntFixIsotropicMapping(pdc); + } + + /* Update xforms, CHECKME: really done here? */ + DC_UpdateXforms(pdc); + } + + /* Copy the viewport extension */ + *pSize = pdcattr->szlViewportExt; +} + +BOOL APIENTRY +NtGdiGetDCPoint( HDC hDC, UINT iPoint, PPOINTL Point) +{ + BOOL Ret = TRUE; + DC *dc; + POINTL SafePoint; + SIZE Size; + NTSTATUS Status = STATUS_SUCCESS; + + if(!Point) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + + RtlZeroMemory(&SafePoint, sizeof(POINT)); + + dc = DC_LockDc(hDC); + if(!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + switch (iPoint) + { + case GdiGetViewPortExt: + IntGetViewportExtEx(dc, &Size); + SafePoint.x = Size.cx; + SafePoint.y = Size.cy; + break; + case GdiGetWindowExt: + IntGetWindowExtEx(dc, &Size); + SafePoint.x = Size.cx; + SafePoint.y = Size.cy; + break; + case GdiGetViewPortOrg: + IntGetViewportOrgEx(dc, &SafePoint); + break; + case GdiGetWindowOrg: + IntGetWindowOrgEx(dc, &SafePoint); + break; + case GdiGetDCOrg: + Ret = IntGdiGetDCOrg(dc, &SafePoint); + break; + case GdiGetAspectRatioFilter: + Ret = IntGetAspectRatioFilter(dc, &Size); + SafePoint.x = Size.cx; + SafePoint.y = Size.cy; + break; + default: + SetLastWin32Error(ERROR_INVALID_PARAMETER); + Ret = FALSE; + break; + } + + if (Ret) + { + _SEH2_TRY + { + ProbeForWrite(Point, + sizeof(POINT), + 1); + *Point = SafePoint; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + } + + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + DC_UnlockDc(dc); + return FALSE; + } + + DC_UnlockDc(dc); + return Ret; +} + + +DWORD +APIENTRY +NtGdiGetBoundsRect( + IN HDC hdc, + OUT LPRECT prc, + IN DWORD f) +{ + DPRINT1("stub\n"); + return DCB_RESET; /* bounding rectangle always empty */ +} + +DWORD +APIENTRY +NtGdiSetBoundsRect( + IN HDC hdc, + IN LPRECT prc, + IN DWORD f) +{ + DPRINT1("stub\n"); + return DCB_DISABLE; /* bounding rectangle always empty */ +} + + /* EOF */ diff --git a/reactos/subsystems/win32/win32k/objects/dcattr.c b/reactos/subsystems/win32/win32k/objects/dcattr.c new file mode 100644 index 00000000000..a7e1a3393c7 --- /dev/null +++ b/reactos/subsystems/win32/win32k/objects/dcattr.c @@ -0,0 +1,138 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Functions for creation and destruction of DCs + * FILE: subsystem/win32/win32k/objects/dcattr.c + * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org) + */ + +#include + +#define NDEBUG +#include + + +VOID +FASTCALL +DC_AllocateDcAttr(HDC hDC) +{ + PVOID NewMem = NULL; + PDC pDC; + HANDLE Pid = NtCurrentProcess(); + ULONG MemSize = sizeof(DC_ATTR); //PAGE_SIZE it will allocate that size + + NTSTATUS Status = ZwAllocateVirtualMemory(Pid, + &NewMem, + 0, + &MemSize, + MEM_COMMIT|MEM_RESERVE, + PAGE_READWRITE); + KeEnterCriticalRegion(); + { + INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hDC); + PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index]; + // FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData + if (NT_SUCCESS(Status)) + { + RtlZeroMemory(NewMem, MemSize); + Entry->UserData = NewMem; + DPRINT("DC_ATTR allocated! 0x%x\n",NewMem); + } + else + { + DPRINT("DC_ATTR not allocated!\n"); + } + } + KeLeaveCriticalRegion(); + pDC = DC_LockDc(hDC); + ASSERT(pDC->pdcattr == &pDC->dcattr); + if(NewMem) + { + pDC->pdcattr = NewMem; // Store pointer + } + DC_UnlockDc(pDC); +} + +VOID +FASTCALL +DC_FreeDcAttr(HDC DCToFree ) +{ + HANDLE Pid = NtCurrentProcess(); + PDC pDC = DC_LockDc(DCToFree); + if (pDC->pdcattr == &pDC->dcattr) return; // Internal DC object! + pDC->pdcattr = &pDC->dcattr; + DC_UnlockDc(pDC); + + KeEnterCriticalRegion(); + { + INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)DCToFree); + PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index]; + if(Entry->UserData) + { + ULONG MemSize = sizeof(DC_ATTR); //PAGE_SIZE; + NTSTATUS Status = ZwFreeVirtualMemory(Pid, + &Entry->UserData, + &MemSize, + MEM_RELEASE); + if (NT_SUCCESS(Status)) + { + DPRINT("DC_FreeDC DC_ATTR 0x%x\n", Entry->UserData); + Entry->UserData = NULL; + } + } + } + KeLeaveCriticalRegion(); +} + + +static +VOID +CopytoUserDcAttr(PDC dc, PDC_ATTR pdcattr) +{ + NTSTATUS Status = STATUS_SUCCESS; + dc->dcattr.mxWorldToDevice = dc->dclevel.mxWorldToDevice; + dc->dcattr.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld; + dc->dcattr.mxWorldToPage = dc->dclevel.mxWorldToPage; + + _SEH2_TRY + { + ProbeForWrite( pdcattr, + sizeof(DC_ATTR), + 1); + RtlCopyMemory( pdcattr, + &dc->dcattr, + sizeof(DC_ATTR)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + ASSERT(FALSE); + } + _SEH2_END; +} + +// FIXME: wtf? 2 functions, where one has a typo in the name???? +BOOL +FASTCALL +DCU_SyncDcAttrtoUser(PDC dc) +{ + PDC_ATTR pdcattr = dc->pdcattr; + + if (pdcattr == &dc->dcattr) return TRUE; // No need to copy self. + ASSERT(pdcattr); + CopytoUserDcAttr( dc, pdcattr); + return TRUE; +} + +BOOL +FASTCALL +DCU_SynchDcAttrtoUser(HDC hDC) +{ + BOOL Ret; + PDC pDC = DC_LockDc ( hDC ); + if (!pDC) return FALSE; + Ret = DCU_SyncDcAttrtoUser(pDC); + DC_UnlockDc( pDC ); + return Ret; +} + diff --git a/reactos/subsystems/win32/win32k/objects/dclife.c b/reactos/subsystems/win32/win32k/objects/dclife.c new file mode 100644 index 00000000000..9a3fadb120a --- /dev/null +++ b/reactos/subsystems/win32/win32k/objects/dclife.c @@ -0,0 +1,680 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Functions for creation and destruction of DCs + * FILE: subsystem/win32/win32k/objects/dclife.c + * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org) + */ + +#include +#include + +#define NDEBUG +#include + +/** Internal functions ********************************************************/ + +HDC FASTCALL +DC_AllocDC(PUNICODE_STRING Driver) +{ + PDC NewDC; + PDC_ATTR pdcattr; + HDC hDC; + PWSTR Buf = NULL; + XFORM xformTemplate; + + if (Driver != NULL) + { + Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC); + if(!Buf) + { + DPRINT1("ExAllocatePoolWithTag failed\n"); + return NULL; + } + RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength); + } + + NewDC = (PDC)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC); + if(!NewDC) + { + if(Buf) + { + ExFreePoolWithTag(Buf, TAG_DC); + } + DPRINT1("GDIOBJ_AllocObjWithHandle failed\n"); + return NULL; + } + + hDC = NewDC->BaseObject.hHmgr; + + NewDC->pdcattr = &NewDC->dcattr; + DC_AllocateDcAttr(hDC); + + if (Driver != NULL) + { + RtlCopyMemory(&NewDC->rosdc.DriverName, Driver, sizeof(UNICODE_STRING)); + NewDC->rosdc.DriverName.Buffer = Buf; + } + pdcattr = NewDC->pdcattr; + + xformTemplate.eM11 = 1.0f; + xformTemplate.eM12 = 0.0f; + xformTemplate.eM21 = 0.0f; + xformTemplate.eM22 = 1.0f; + xformTemplate.eDx = 0.0f; + xformTemplate.eDy = 0.0f; + XForm2MatrixS(&NewDC->dclevel.mxWorldToDevice, &xformTemplate); + XForm2MatrixS(&NewDC->dclevel.mxDeviceToWorld, &xformTemplate); + XForm2MatrixS(&NewDC->dclevel.mxWorldToPage, &xformTemplate); + +// Setup syncing bits for the dcattr data packets. + pdcattr->flXform = DEVICE_TO_PAGE_INVALID; + + pdcattr->ulDirty_ = 0; // Server side + + pdcattr->iMapMode = MM_TEXT; + pdcattr->iGraphicsMode = GM_COMPATIBLE; + pdcattr->jFillMode = ALTERNATE; + + pdcattr->szlWindowExt.cx = 1; // Float to Int,,, WRONG! + pdcattr->szlWindowExt.cy = 1; + pdcattr->szlViewportExt.cx = 1; + pdcattr->szlViewportExt.cy = 1; + + pdcattr->crForegroundClr = 0; + pdcattr->ulForegroundClr = 0; + + pdcattr->ulBackgroundClr = 0xffffff; + pdcattr->crBackgroundClr = 0xffffff; + + pdcattr->ulPenClr = RGB( 0, 0, 0 ); + pdcattr->crPenClr = RGB( 0, 0, 0 ); + + pdcattr->ulBrushClr = RGB( 255, 255, 255 ); // Do this way too. + pdcattr->crBrushClr = RGB( 255, 255, 255 ); + +//// This fixes the default brush and pen settings. See DC_InitDC. + + /* Create the default fill brush */ + pdcattr->hbrush = NtGdiGetStockObject( WHITE_BRUSH ); + NewDC->dclevel.pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush); + EBRUSHOBJ_vInit(&NewDC->eboFill, NewDC->dclevel.pbrFill, NULL); + + /* Create the default pen / line brush */ + pdcattr->hpen = NtGdiGetStockObject( BLACK_PEN ); + NewDC->dclevel.pbrLine = PEN_ShareLockPen(pdcattr->hpen); + EBRUSHOBJ_vInit(&NewDC->eboLine, NewDC->dclevel.pbrFill, NULL); + + + pdcattr->hlfntNew = NtGdiGetStockObject(SYSTEM_FONT); + TextIntRealizeFont(pdcattr->hlfntNew,NULL); + + NewDC->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE); + NewDC->dclevel.laPath.eMiterLimit = 10.0; + + DC_UnlockDc(NewDC); + + return hDC; +} + +VOID FASTCALL +DC_FreeDC(HDC DCToFree) +{ + DC_FreeDcAttr(DCToFree); + if(!IsObjectDead( DCToFree )) + { + if (!GDIOBJ_FreeObjByHandle(DCToFree, GDI_OBJECT_TYPE_DC)) + { + DPRINT1("DC_FreeDC failed\n"); + } + } + else + { + DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n",DCToFree); + } +} + +BOOL INTERNAL_CALL +DC_Cleanup(PVOID ObjectBody) +{ + PDC pDC = (PDC)ObjectBody; + if (pDC->rosdc.DriverName.Buffer) + ExFreePoolWithTag(pDC->rosdc.DriverName.Buffer, TAG_DC); + return TRUE; +} + +BOOL +FASTCALL +DC_SetOwnership(HDC hDC, PEPROCESS Owner) +{ + PDC pDC; + + if(!GDIOBJ_SetOwnership(hDC, Owner)) return FALSE; + pDC = DC_LockDc(hDC); + if (pDC) + { + if (pDC->rosdc.hClipRgn) + { + if(!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE; + } + if (pDC->rosdc.hVisRgn) + { + if(!GDIOBJ_SetOwnership(pDC->rosdc.hVisRgn, Owner)) return FALSE; + } + if (pDC->rosdc.hGCClipRgn) + { + if(!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) return FALSE; + } + if (pDC->dclevel.hPath) + { + if(!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) return FALSE; + } + DC_UnlockDc(pDC); + } + return TRUE; +} + + +HDC FASTCALL +IntGdiCreateDC(PUNICODE_STRING Driver, + PUNICODE_STRING Device, + PVOID pUMdhpdev, + CONST PDEVMODEW InitData, + BOOL CreateAsIC) +{ + HDC hdc; + PDC pdc; + PDC_ATTR pdcattr; + HRGN hVisRgn; + UNICODE_STRING StdDriver; + BOOL calledFromUser; + + RtlInitUnicodeString(&StdDriver, L"DISPLAY"); + + DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver, Device); + + if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE)) + { + if (CreateAsIC) + { + if (! IntPrepareDriverIfNeeded()) + { + /* Here, we have two possibilities: + * a) return NULL, and hope that the caller + * won't call us in a loop + * b) bugcheck, but caller is unable to + * react on the problem + */ + /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n"); + return NULL;*/ + KeBugCheck(VIDEO_DRIVER_INIT_FAILURE); + } + } + else + { + calledFromUser = UserIsEntered(); + if (!calledFromUser){ + UserEnterExclusive(); + } + + if (! co_IntGraphicsCheck(TRUE)) + { + if (!calledFromUser){ + UserLeave(); + } + DPRINT1("Unable to initialize graphics, returning NULL dc\n"); + return NULL; + } + + if (!calledFromUser){ + UserLeave(); + } + + } + } + + /* Check for existing DC object */ + if ((hdc = DC_FindOpenDC(Driver)) != NULL) + { + hdc = NtGdiCreateCompatibleDC(hdc); + if (!hdc) + DPRINT1("NtGdiCreateCompatibleDC() failed\n"); + return hdc; + } + + /* Allocate a DC object */ + if ((hdc = DC_AllocDC(Driver)) == NULL) + { + DPRINT1("DC_AllocDC() failed\n"); + return NULL; + } + + pdc = DC_LockDc( hdc ); + if ( !pdc ) + { + DC_FreeDC( hdc ); + DPRINT1("DC_LockDc() failed\n"); + return NULL; + } + + pdcattr = pdc->pdcattr; + + pdc->dctype = DC_TYPE_DIRECT; + + pdc->dhpdev = PrimarySurface.hPDev; + if(pUMdhpdev) pUMdhpdev = pdc->dhpdev; // set DHPDEV for device. + pdc->ppdev = (PVOID)&PrimarySurface; + pdc->rosdc.hBitmap = (HBITMAP)PrimarySurface.pSurface; + // ATM we only have one display. + pdcattr->ulDirty_ |= DC_PRIMARY_DISPLAY; + + pdc->rosdc.bitsPerPixel = pdc->ppdev->GDIInfo.cBitsPixel * + pdc->ppdev->GDIInfo.cPlanes; + DPRINT("Bits per pel: %u\n", pdc->rosdc.bitsPerPixel); + + pdc->flGraphicsCaps = PrimarySurface.DevInfo.flGraphicsCaps; + pdc->flGraphicsCaps2 = PrimarySurface.DevInfo.flGraphicsCaps2; + + pdc->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE); + + pdcattr->jROP2 = R2_COPYPEN; + + pdc->erclWindow.top = pdc->erclWindow.left = 0; + pdc->erclWindow.right = pdc->ppdev->GDIInfo.ulHorzRes; + pdc->erclWindow.bottom = pdc->ppdev->GDIInfo.ulVertRes; + pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE; // Default is CCW. + + pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0); + + hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->ppdev->GDIInfo.ulHorzRes, + pdc->ppdev->GDIInfo.ulVertRes); + + if (!CreateAsIC) + { + pdc->pSurfInfo = NULL; +// pdc->dclevel.pSurface = + DC_UnlockDc( pdc ); + + /* Initialize the DC state */ + DC_InitDC(hdc); + IntGdiSetTextColor(hdc, RGB(0, 0, 0)); + IntGdiSetBkColor(hdc, RGB(255, 255, 255)); + } + else + { + /* From MSDN2: + The CreateIC function creates an information context for the specified device. + The information context provides a fast way to get information about the + device without creating a device context (DC). However, GDI drawing functions + cannot accept a handle to an information context. + */ + pdc->dctype = DC_TYPE_INFO; +// pdc->pSurfInfo = + pdc->dclevel.pSurface = NULL; + pdcattr->crBackgroundClr = pdcattr->ulBackgroundClr = RGB(255, 255, 255); + pdcattr->crForegroundClr = RGB(0, 0, 0); + DC_UnlockDc( pdc ); + } + + if (hVisRgn) + { + GdiSelectVisRgn(hdc, hVisRgn); + NtGdiDeleteObject(hVisRgn); + } + + IntGdiSetTextAlign(hdc, TA_TOP); + IntGdiSetBkMode(hdc, OPAQUE); + + return hdc; +} + + +HDC APIENTRY +NtGdiOpenDCW( PUNICODE_STRING Device, + DEVMODEW *InitData, + PUNICODE_STRING pustrLogAddr, + ULONG iType, + HANDLE hspool, + VOID *pDriverInfo2, + VOID *pUMdhpdev ) +{ + UNICODE_STRING SafeDevice; + DEVMODEW SafeInitData; + PVOID Dhpdev; + HDC Ret; + NTSTATUS Status = STATUS_SUCCESS; + + if(InitData) + { + _SEH2_TRY + { + if (pUMdhpdev) + { + ProbeForWrite(pUMdhpdev, + sizeof(PVOID), + 1); + } + ProbeForRead(InitData, + sizeof(DEVMODEW), + 1); + RtlCopyMemory(&SafeInitData, + InitData, + sizeof(DEVMODEW)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return NULL; + } + /* FIXME - InitData can have some more bytes! */ + } + + if(Device) + { + Status = IntSafeCopyUnicodeString(&SafeDevice, Device); + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return NULL; + } + } + + Ret = IntGdiCreateDC(Device ? &SafeDevice : NULL, + NULL, + pUMdhpdev ? &Dhpdev : NULL, + InitData ? &SafeInitData : NULL, + (BOOL) iType); // FALSE 0 DCW, TRUE 1 ICW + + if (pUMdhpdev) pUMdhpdev = Dhpdev; + + return Ret; + +} + +HDC FASTCALL +IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC) +{ + HDC hDC; + UNICODE_STRING DriverName; + RtlInitUnicodeString(&DriverName, L"DISPLAY"); + + if (DcType != DC_TYPE_MEMORY) + hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, (DcType == DC_TYPE_INFO)); + else + hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth! +// +// There is room to grow here~ +// + +// +// If NULL, first time through! Build the default (was window) dc! +// + if (hDC && !defaultDCstate) // Ultra HAX! Dedicated to GvG! + { // This is a cheesy way to do this. + PDC dc = DC_LockDc ( hDC ); + defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC); + if (!defaultDCstate) + { + DC_UnlockDc( dc ); + return NULL; + } + RtlZeroMemory(defaultDCstate, sizeof(DC)); + defaultDCstate->pdcattr = &defaultDCstate->dcattr; + IntGdiCopyToSaveState(dc, defaultDCstate); + DC_UnlockDc( dc ); + } + return hDC; +} + +BOOL +FASTCALL +IntGdiDeleteDC(HDC hDC, BOOL Force) +{ + PDC DCToDelete = DC_LockDc(hDC); + + if (DCToDelete == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + if(!Force) + { + if (DCToDelete->fs & DC_FLAG_PERMANENT) + { + DPRINT1("No! You Naughty Application!\n"); + DC_UnlockDc( DCToDelete ); + return UserReleaseDC(NULL, hDC, FALSE); + } + } + + /* First delete all saved DCs */ + while (DCToDelete->dclevel.lSaveDepth) + { + PDC savedDC; + HDC savedHDC; + + savedHDC = DC_GetNextDC (DCToDelete); + savedDC = DC_LockDc (savedHDC); + if (savedDC == NULL) + { + break; + } + DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC)); + DCToDelete->dclevel.lSaveDepth--; + DC_UnlockDc( savedDC ); + IntGdiDeleteDC(savedHDC, Force); + } + + /* Free GDI resources allocated to this DC */ + if (!(DCToDelete->dclevel.flPath & DCPATH_SAVESTATE)) + { + /* + NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN); + NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH); + NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT); + DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */ + if (DCToDelete->rosdc.XlateBrush != NULL) + EngDeleteXlate(DCToDelete->rosdc.XlateBrush); + if (DCToDelete->rosdc.XlatePen != NULL) + EngDeleteXlate(DCToDelete->rosdc.XlatePen); + } + if (DCToDelete->rosdc.hClipRgn) + { + NtGdiDeleteObject (DCToDelete->rosdc.hClipRgn); + } + if (DCToDelete->rosdc.hVisRgn) + { + NtGdiDeleteObject (DCToDelete->rosdc.hVisRgn); + } + if (NULL != DCToDelete->rosdc.CombinedClip) + { + IntEngDeleteClipRegion(DCToDelete->rosdc.CombinedClip); + } + if (DCToDelete->rosdc.hGCClipRgn) + { + NtGdiDeleteObject (DCToDelete->rosdc.hGCClipRgn); + } + PATH_Delete(DCToDelete->dclevel.hPath); + + DC_UnlockDc( DCToDelete ); + DC_FreeDC ( hDC ); + return TRUE; +} + +HDC FASTCALL +DC_FindOpenDC(PUNICODE_STRING Driver) +{ + return NULL; +} + +/*! + * Initialize some common fields in the Device Context structure. +*/ +VOID FASTCALL +DC_InitDC(HDC DCHandle) +{ +// NtGdiRealizeDefaultPalette(DCHandle); + +//// Removed for now.. See above brush and pen. +// NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH )); +// NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN )); +//// + //NtGdiSelectFont(DCHandle, hFont); + +/* + { + int res; + res = CLIPPING_UpdateGCRegion(DCToInit); + ASSERT ( res != ERROR ); + } +*/ +} + + /* + * @unimplemented + */ +BOOL +APIENTRY +NtGdiMakeInfoDC( + IN HDC hdc, + IN BOOL bSet) +{ + UNIMPLEMENTED; + return FALSE; +} + +HDC APIENTRY +NtGdiCreateCompatibleDC(HDC hDC) +{ + PDC NewDC, OrigDC; + PDC_ATTR pdcattrNew, pdcattrOld; + HDC hNewDC, DisplayDC = NULL; + HRGN hVisRgn; + UNICODE_STRING DriverName; + DWORD Layout = 0; + + if (hDC == NULL) + { + RtlInitUnicodeString(&DriverName, L"DISPLAY"); + DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE); + if (NULL == DisplayDC) + { + DPRINT1("Failed to create DisplayDC\n"); + return NULL; + } + hDC = DisplayDC; + } + + /* Allocate a new DC based on the original DC's device */ + OrigDC = DC_LockDc(hDC); + if (NULL == OrigDC) + { + if (NULL != DisplayDC) + { + NtGdiDeleteObjectApp(DisplayDC); + } + DPRINT1("Failed to lock hDC\n"); + return NULL; + } + hNewDC = DC_AllocDC(&OrigDC->rosdc.DriverName); + if (NULL == hNewDC) + { + DPRINT1("Failed to create hNewDC\n"); + DC_UnlockDc(OrigDC); + if (NULL != DisplayDC) + { + NtGdiDeleteObjectApp(DisplayDC); + } + return NULL; + } + NewDC = DC_LockDc( hNewDC ); + + if(!NewDC) + { + DPRINT1("Failed to lock hNewDC\n"); + NtGdiDeleteObjectApp(hNewDC); + return NULL; + } + + pdcattrOld = OrigDC->pdcattr; + pdcattrNew = NewDC->pdcattr; + + /* Copy information from original DC to new DC */ + NewDC->dclevel.hdcSave = hNewDC; + + NewDC->dhpdev = OrigDC->dhpdev; + + NewDC->rosdc.bitsPerPixel = OrigDC->rosdc.bitsPerPixel; + + /* DriverName is copied in the AllocDC routine */ + pdcattrNew->ptlWindowOrg = pdcattrOld->ptlWindowOrg; + pdcattrNew->szlWindowExt = pdcattrOld->szlWindowExt; + pdcattrNew->ptlViewportOrg = pdcattrOld->ptlViewportOrg; + pdcattrNew->szlViewportExt = pdcattrOld->szlViewportExt; + + NewDC->dctype = DC_TYPE_MEMORY; // Always! + NewDC->rosdc.hBitmap = NtGdiGetStockObject(DEFAULT_BITMAP); + NewDC->ppdev = OrigDC->ppdev; + NewDC->dclevel.hpal = OrigDC->dclevel.hpal; + + pdcattrNew->lTextAlign = pdcattrOld->lTextAlign; + pdcattrNew->lBkMode = pdcattrOld->lBkMode; + pdcattrNew->jBkMode = pdcattrOld->jBkMode; + pdcattrNew->jROP2 = pdcattrOld->jROP2; + pdcattrNew->dwLayout = pdcattrOld->dwLayout; + if (pdcattrOld->dwLayout & LAYOUT_ORIENTATIONMASK) Layout = pdcattrOld->dwLayout; + NewDC->dclevel.flPath = OrigDC->dclevel.flPath; + pdcattrNew->ulDirty_ = pdcattrOld->ulDirty_; + pdcattrNew->iCS_CP = pdcattrOld->iCS_CP; + + NewDC->erclWindow = (RECTL){0,0,1,1}; + + DC_UnlockDc(NewDC); + DC_UnlockDc(OrigDC); + if (NULL != DisplayDC) + { + NtGdiDeleteObjectApp(DisplayDC); + } + + hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1); + if (hVisRgn) + { + GdiSelectVisRgn(hNewDC, hVisRgn); + NtGdiDeleteObject(hVisRgn); + } + if (Layout) NtGdiSetLayout( hNewDC, -1, Layout); + + DC_InitDC(hNewDC); + return hNewDC; +} + + +BOOL +APIENTRY +NtGdiDeleteObjectApp(HANDLE DCHandle) +{ + /* Complete all pending operations */ + NtGdiFlushUserBatch(); + + if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE; + + if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC) + return NtGdiDeleteObject((HGDIOBJ) DCHandle); + + if(IsObjectDead((HGDIOBJ)DCHandle)) return TRUE; + + if (!GDIOBJ_OwnedByCurrentProcess(DCHandle)) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + return IntGdiDeleteDC(DCHandle, FALSE); +} + diff --git a/reactos/subsystems/win32/win32k/objects/dcobjs.c b/reactos/subsystems/win32/win32k/objects/dcobjs.c new file mode 100644 index 00000000000..7d2ccac115a --- /dev/null +++ b/reactos/subsystems/win32/win32k/objects/dcobjs.c @@ -0,0 +1,281 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Functions for creation and destruction of DCs + * FILE: subsystem/win32/win32k/objects/dcobjs.c + * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org) + */ + +#include + +#define NDEBUG +#include + + +VOID +FASTCALL +DC_vUpdateFillBrush(PDC pdc) +{ + PDC_ATTR pdcattr = pdc->pdcattr; + PBRUSH pbrFill; + XLATEOBJ *pxlo; + ULONG iSolidColor; + + /* Check if update of eboFill is needed */ + if (pdcattr->ulDirty_ & DIRTY_FILL) + { + /* ROS HACK, should use surf xlate */ + pxlo = pdc->rosdc.XlatePen; + + /* Check if the brush handle has changed */ + if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr) + { + /* Try to lock the new brush */ + pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush); + if (pbrFill) + { + /* Unlock old brush, set new brush */ + BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill); + pdc->dclevel.pbrFill = pbrFill; + + /* Update eboFill, realizing it, if needed */ + EBRUSHOBJ_vUpdate(&pdc->eboFill, pbrFill, pxlo); + } + else + { + /* Invalid brush handle, restore old one */ + pdcattr->hbrush = pdc->dclevel.pbrFill->BaseObject.hHmgr; + } + } + + /* Check for DC brush */ + if (pdcattr->hbrush == StockObjects[DC_BRUSH]) + { + /* Translate the color to the target format */ + iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crPenClr); + + /* Update the eboFill's solid color */ + EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, iSolidColor); + } + + /* Clear flag */ + pdcattr->ulDirty_ &= ~DIRTY_FILL; + } +} + +VOID +FASTCALL +DC_vUpdateLineBrush(PDC pdc) +{ + PDC_ATTR pdcattr = pdc->pdcattr; + PBRUSH pbrLine; + XLATEOBJ *pxlo; + ULONG iSolidColor; + + /* Check if update of eboLine is needed */ + if (pdcattr->ulDirty_ & DIRTY_LINE) + { + /* ROS HACK, should use surf xlate */ + pxlo = pdc->rosdc.XlatePen; + + /* Check if the pen handle has changed */ + if (pdcattr->hpen != pdc->dclevel.pbrLine->BaseObject.hHmgr) + { + /* Try to lock the new pen */ + pbrLine = BRUSH_ShareLockBrush(pdcattr->hpen); + if (pbrLine) + { + /* Unlock old brush, set new brush */ + BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine); + pdc->dclevel.pbrLine = pbrLine; + + /* Update eboLine, realizing it, if needed */ + EBRUSHOBJ_vUpdate(&pdc->eboLine, pbrLine, pxlo); + } + else + { + /* Invalid pen handle, restore old one */ + pdcattr->hpen = pdc->dclevel.pbrLine->BaseObject.hHmgr; + } + } + + /* Check for DC pen */ + if (pdcattr->hpen == StockObjects[DC_PEN]) + { + /* Translate the color to the target format */ + iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crPenClr); + + /* Update the eboLine's solid color */ + EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboLine, iSolidColor); + } + + /* Clear flag */ + pdcattr->ulDirty_ &= ~DIRTY_LINE; + } +} + +VOID +FASTCALL +DC_vUpdateTextBrush(PDC pdc) +{ + PDC_ATTR pdcattr = pdc->pdcattr; + XLATEOBJ *pxlo; + ULONG iSolidColor; + + /* Check if update of eboText is needed */ + if (pdcattr->ulDirty_ & DIRTY_TEXT) + { + /* ROS HACK, should use surf xlate */ + pxlo = pdc->rosdc.XlatePen; + + /* Translate the color to the target format */ + iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crForegroundClr); + + /* Update the eboText's solid color */ + EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, iSolidColor); + + /* Clear flag */ + pdcattr->ulDirty_ &= ~DIRTY_TEXT; + } +} + +VOID +FASTCALL +DC_vUpdateBackgroundBrush(PDC pdc) +{ + PDC_ATTR pdcattr = pdc->pdcattr; + XLATEOBJ *pxlo; + ULONG iSolidColor; + + /* Check if update of eboBackground is needed */ + if (pdcattr->ulDirty_ & DIRTY_BACKGROUND) + { + /* ROS HACK, should use surf xlate */ + pxlo = pdc->rosdc.XlatePen; + + /* Translate the color to the target format */ + iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crBackgroundClr); + + /* Update the eboBackground's solid color */ + EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, iSolidColor); + + /* Clear flag */ + pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND; + } +} + + + + +ULONG +APIENTRY +NtGdiEnumObjects( + IN HDC hdc, + IN INT iObjectType, + IN ULONG cjBuf, + OUT OPTIONAL PVOID pvBuf) +{ + UNIMPLEMENTED; + return 0; +} + +HANDLE +APIENTRY +NtGdiGetDCObject(HDC hDC, INT ObjectType) +{ + HGDIOBJ SelObject; + DC *dc; + PDC_ATTR pdcattr; + + /* From Wine: GetCurrentObject does not SetLastError() on a null object */ + if(!hDC) return NULL; + + if(!(dc = DC_LockDc(hDC))) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return NULL; + } + pdcattr = dc->pdcattr; + + if (pdcattr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,pdcattr->hbrush); + + if (pdcattr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,pdcattr->hpen); + + switch(ObjectType) + { + case GDI_OBJECT_TYPE_EXTPEN: + case GDI_OBJECT_TYPE_PEN: + SelObject = pdcattr->hpen; + break; + case GDI_OBJECT_TYPE_BRUSH: + SelObject = pdcattr->hbrush; + break; + case GDI_OBJECT_TYPE_PALETTE: + SelObject = dc->dclevel.hpal; + break; + case GDI_OBJECT_TYPE_FONT: + SelObject = pdcattr->hlfntNew; + break; + case GDI_OBJECT_TYPE_BITMAP: + SelObject = dc->rosdc.hBitmap; + break; + case GDI_OBJECT_TYPE_COLORSPACE: + DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n"); + // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ? + SelObject = NULL; + break; + default: + SelObject = NULL; + SetLastWin32Error(ERROR_INVALID_PARAMETER); + break; + } + + DC_UnlockDc(dc); + return SelObject; +} + +HPALETTE +FASTCALL +GdiSelectPalette(HDC hDC, + HPALETTE hpal, + BOOL ForceBackground) +{ + PDC dc; + HPALETTE oldPal = NULL; + PPALGDI PalGDI; + + // FIXME: mark the palette as a [fore\back]ground pal + dc = DC_LockDc(hDC); + if (!dc) + { + return NULL; + } + + /* Check if this is a valid palette handle */ + PalGDI = PALETTE_LockPalette(hpal); + if (!PalGDI) + { + DC_UnlockDc(dc); + return NULL; + } + + /* Is this a valid palette for this depth? */ + if ((dc->rosdc.bitsPerPixel <= 8 && PalGDI->Mode == PAL_INDEXED) || + (dc->rosdc.bitsPerPixel > 8 && PalGDI->Mode != PAL_INDEXED)) + { + oldPal = dc->dclevel.hpal; + dc->dclevel.hpal = hpal; + } + else if (8 < dc->rosdc.bitsPerPixel && PAL_INDEXED == PalGDI->Mode) + { + oldPal = dc->dclevel.hpal; + dc->dclevel.hpal = hpal; + } + + PALETTE_UnlockPalette(PalGDI); + DC_UnlockDc(dc); + + return oldPal; +} diff --git a/reactos/subsystems/win32/win32k/objects/dcstate.c b/reactos/subsystems/win32/win32k/objects/dcstate.c new file mode 100644 index 00000000000..d6241dfddbd --- /dev/null +++ b/reactos/subsystems/win32/win32k/objects/dcstate.c @@ -0,0 +1,384 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Functions for creation and destruction of DCs + * FILE: subsystem/win32/win32k/objects/dcstate.c + * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org) + */ + +#include + +#define NDEBUG +#include + + +VOID +FASTCALL +IntGdiCopyToSaveState(PDC dc, PDC newdc) +{ + PDC_ATTR pdcattr, nDc_Attr; + + pdcattr = dc->pdcattr; + nDc_Attr = newdc->pdcattr; + + newdc->dclevel.flPath = dc->dclevel.flPath | DCPATH_SAVESTATE; + + nDc_Attr->dwLayout = pdcattr->dwLayout; + nDc_Attr->hpen = pdcattr->hpen; + nDc_Attr->hbrush = pdcattr->hbrush; + nDc_Attr->hlfntNew = pdcattr->hlfntNew; + newdc->rosdc.hBitmap = dc->rosdc.hBitmap; + newdc->dclevel.hpal = dc->dclevel.hpal; + newdc->rosdc.bitsPerPixel = dc->rosdc.bitsPerPixel; + nDc_Attr->jROP2 = pdcattr->jROP2; + nDc_Attr->jFillMode = pdcattr->jFillMode; + nDc_Attr->jStretchBltMode = pdcattr->jStretchBltMode; + nDc_Attr->lRelAbs = pdcattr->lRelAbs; + nDc_Attr->jBkMode = pdcattr->jBkMode; + nDc_Attr->lBkMode = pdcattr->lBkMode; + nDc_Attr->crBackgroundClr = pdcattr->crBackgroundClr; + nDc_Attr->crForegroundClr = pdcattr->crForegroundClr; + nDc_Attr->ulBackgroundClr = pdcattr->ulBackgroundClr; + nDc_Attr->ulForegroundClr = pdcattr->ulForegroundClr; + nDc_Attr->ptlBrushOrigin = pdcattr->ptlBrushOrigin; + nDc_Attr->lTextAlign = pdcattr->lTextAlign; + nDc_Attr->lTextExtra = pdcattr->lTextExtra; + nDc_Attr->cBreak = pdcattr->cBreak; + nDc_Attr->lBreakExtra = pdcattr->lBreakExtra; + nDc_Attr->iMapMode = pdcattr->iMapMode; + nDc_Attr->iGraphicsMode = pdcattr->iGraphicsMode; +#if 0 + /* Apparently, the DC origin is not changed by [GS]etDCState */ + newdc->ptlDCOrig.x = dc->ptlDCOrig.x; + newdc->ptlDCOrig.y = dc->ptlDCOrig.y; +#endif + nDc_Attr->ptlCurrent = pdcattr->ptlCurrent; + nDc_Attr->ptfxCurrent = pdcattr->ptfxCurrent; + newdc->dclevel.mxWorldToDevice = dc->dclevel.mxWorldToDevice; + newdc->dclevel.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld; + newdc->dclevel.mxWorldToPage = dc->dclevel.mxWorldToPage; + nDc_Attr->flXform = pdcattr->flXform; + nDc_Attr->ptlWindowOrg = pdcattr->ptlWindowOrg; + nDc_Attr->szlWindowExt = pdcattr->szlWindowExt; + nDc_Attr->ptlViewportOrg = pdcattr->ptlViewportOrg; + nDc_Attr->szlViewportExt = pdcattr->szlViewportExt; + + newdc->dclevel.lSaveDepth = 0; + newdc->dctype = dc->dctype; + +#if 0 + PATH_InitGdiPath( &newdc->dclevel.hPath ); +#endif + + /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */ + + newdc->rosdc.hGCClipRgn = newdc->rosdc.hVisRgn = 0; + if (dc->rosdc.hClipRgn) + { + newdc->rosdc.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + NtGdiCombineRgn( newdc->rosdc.hClipRgn, dc->rosdc.hClipRgn, 0, RGN_COPY ); + } +} + +// FIXME: why 2 different functions that do the same? +VOID +FASTCALL +IntGdiCopyFromSaveState(PDC dc, PDC dcs, HDC hDC) +{ + PDC_ATTR pdcattr, sDc_Attr; + + pdcattr = dc->pdcattr; + sDc_Attr = dcs->pdcattr; + + dc->dclevel.flPath = dcs->dclevel.flPath & ~DCPATH_SAVESTATE; + + pdcattr->dwLayout = sDc_Attr->dwLayout; + pdcattr->jROP2 = sDc_Attr->jROP2; + pdcattr->jFillMode = sDc_Attr->jFillMode; + pdcattr->jStretchBltMode = sDc_Attr->jStretchBltMode; + pdcattr->lRelAbs = sDc_Attr->lRelAbs; + pdcattr->jBkMode = sDc_Attr->jBkMode; + pdcattr->crBackgroundClr = sDc_Attr->crBackgroundClr; + pdcattr->crForegroundClr = sDc_Attr->crForegroundClr; + pdcattr->lBkMode = sDc_Attr->lBkMode; + pdcattr->ulBackgroundClr = sDc_Attr->ulBackgroundClr; + pdcattr->ulForegroundClr = sDc_Attr->ulForegroundClr; + pdcattr->ptlBrushOrigin = sDc_Attr->ptlBrushOrigin; + + pdcattr->lTextAlign = sDc_Attr->lTextAlign; + pdcattr->lTextExtra = sDc_Attr->lTextExtra; + pdcattr->cBreak = sDc_Attr->cBreak; + pdcattr->lBreakExtra = sDc_Attr->lBreakExtra; + pdcattr->iMapMode = sDc_Attr->iMapMode; + pdcattr->iGraphicsMode = sDc_Attr->iGraphicsMode; +#if 0 +/* Apparently, the DC origin is not changed by [GS]etDCState */ + dc->ptlDCOrig.x = dcs->ptlDCOrig.x; + dc->ptlDCOrig.y = dcs->ptlDCOrig.y; +#endif + pdcattr->ptlCurrent = sDc_Attr->ptlCurrent; + pdcattr->ptfxCurrent = sDc_Attr->ptfxCurrent; + dc->dclevel.mxWorldToDevice = dcs->dclevel.mxWorldToDevice; + dc->dclevel.mxDeviceToWorld = dcs->dclevel.mxDeviceToWorld; + dc->dclevel.mxWorldToPage = dcs->dclevel.mxWorldToPage; + pdcattr->flXform = sDc_Attr->flXform; + pdcattr->ptlWindowOrg = sDc_Attr->ptlWindowOrg; + pdcattr->szlWindowExt = sDc_Attr->szlWindowExt; + pdcattr->ptlViewportOrg = sDc_Attr->ptlViewportOrg; + pdcattr->szlViewportExt = sDc_Attr->szlViewportExt; + + if (dc->dctype != DC_TYPE_MEMORY) + { + dc->rosdc.bitsPerPixel = dcs->rosdc.bitsPerPixel; + } + +#if 0 + if (dcs->rosdc.hClipRgn) + { + if (!dc->rosdc.hClipRgn) + { + dc->rosdc.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + } + NtGdiCombineRgn( dc->rosdc.hClipRgn, dcs->rosdc.hClipRgn, 0, RGN_COPY ); + } + else + { + if (dc->rosdc.hClipRgn) + { + NtGdiDeleteObject( dc->rosdc.hClipRgn ); + } + dc->rosdc.hClipRgn = 0; + } + { + int res; + res = CLIPPING_UpdateGCRegion( dc ); + ASSERT ( res != ERROR ); + } + DC_UnlockDc ( dc ); +#else + GdiExtSelectClipRgn(dc, dcs->rosdc.hClipRgn, RGN_COPY); + DC_UnlockDc ( dc ); +#endif + if(!hDC) return; // Not a MemoryDC or SaveLevel DC, return. + + NtGdiSelectBitmap( hDC, dcs->rosdc.hBitmap ); + NtGdiSelectBrush( hDC, sDc_Attr->hbrush ); + NtGdiSelectFont( hDC, sDc_Attr->hlfntNew ); + NtGdiSelectPen( hDC, sDc_Attr->hpen ); + + IntGdiSetBkColor( hDC, sDc_Attr->crBackgroundClr); + IntGdiSetTextColor( hDC, sDc_Attr->crForegroundClr); + + GdiSelectPalette( hDC, dcs->dclevel.hpal, FALSE ); + +#if 0 + GDISelectPalette16( hDC, dcs->dclevel.hpal, FALSE ); +#endif +} + +HDC APIENTRY +IntGdiGetDCState(HDC hDC) +{ + PDC newdc, dc; + HDC hnewdc; + + dc = DC_LockDc(hDC); + if (dc == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + + hnewdc = DC_AllocDC(NULL); + if (hnewdc == NULL) + { + DC_UnlockDc(dc); + return 0; + } + newdc = DC_LockDc( hnewdc ); + /* FIXME - newdc can be NULL!!!! Don't assert here!!! */ + ASSERT( newdc ); + + newdc->dclevel.hdcSave = hnewdc; + IntGdiCopyToSaveState( dc, newdc); + + DC_UnlockDc( newdc ); + DC_UnlockDc( dc ); + return hnewdc; +} + +VOID +APIENTRY +IntGdiSetDCState ( HDC hDC, HDC hDCSave ) +{ + PDC dc, dcs; + + dc = DC_LockDc ( hDC ); + if ( dc ) + { + dcs = DC_LockDc ( hDCSave ); + if ( dcs ) + { + if ( dcs->dclevel.flPath & DCPATH_SAVESTATE ) + { + IntGdiCopyFromSaveState( dc, dcs, dc->dclevel.hdcSave); + } + else + { + DC_UnlockDc(dc); + } + DC_UnlockDc ( dcs ); + } + else + { + DC_UnlockDc ( dc ); + SetLastWin32Error(ERROR_INVALID_HANDLE); + } + } + else + SetLastWin32Error(ERROR_INVALID_HANDLE); +} + + + +BOOL +APIENTRY +NtGdiResetDC( + IN HDC hdc, + IN LPDEVMODEW pdm, + OUT PBOOL pbBanding, + IN OPTIONAL VOID *pDriverInfo2, + OUT VOID *ppUMdhpdev) +{ + UNIMPLEMENTED; + return 0; +} + +BOOL APIENTRY +NtGdiRestoreDC(HDC hDC, INT SaveLevel) +{ + PDC dc, dcs; + BOOL success; + + DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC, SaveLevel); + + dc = DC_LockDc(hDC); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (SaveLevel < 0) + SaveLevel = dc->dclevel.lSaveDepth + SaveLevel + 1; + + if(SaveLevel < 0 || dc->dclevel.lSaveDepthdclevel.lSaveDepth >= SaveLevel) + { + HDC hdcs = DC_GetNextDC (dc); + + dcs = DC_LockDc (hdcs); + if (dcs == NULL) + { + DC_UnlockDc(dc); + return FALSE; + } + + DC_SetNextDC (dc, DC_GetNextDC (dcs)); + dcs->hdcNext = 0; + + if (--dc->dclevel.lSaveDepth < SaveLevel) + { + DC_UnlockDc( dc ); + DC_UnlockDc( dcs ); + + IntGdiSetDCState(hDC, hdcs); + + dc = DC_LockDc(hDC); + if(!dc) + { + return FALSE; + } + // Restore Path by removing it, if the Save flag is set. + // BeginPath will takecare of the rest. + if ( dc->dclevel.hPath && dc->dclevel.flPath & DCPATH_SAVE) + { + PATH_Delete(dc->dclevel.hPath); + dc->dclevel.hPath = 0; + dc->dclevel.flPath &= ~DCPATH_SAVE; + } + } + else + { + DC_UnlockDc( dcs ); + } + NtGdiDeleteObjectApp (hdcs); + } + DC_UnlockDc( dc ); + return success; +} + + +INT APIENTRY +NtGdiSaveDC(HDC hDC) +{ + HDC hdcs; + PDC dc, dcs; + INT ret; + + DPRINT("NtGdiSaveDC(%lx)\n", hDC); + + if (!(hdcs = IntGdiGetDCState(hDC))) + { + return 0; + } + + dcs = DC_LockDc (hdcs); + if (dcs == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + dc = DC_LockDc (hDC); + if (dc == NULL) + { + DC_UnlockDc(dcs); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + + /* + * Copy path. + */ + dcs->dclevel.hPath = dc->dclevel.hPath; + if (dcs->dclevel.hPath) dcs->dclevel.flPath |= DCPATH_SAVE; + + DC_SetNextDC (dcs, DC_GetNextDC (dc)); + DC_SetNextDC (dc, hdcs); + ret = ++dc->dclevel.lSaveDepth; + DC_UnlockDc( dcs ); + DC_UnlockDc( dc ); + + return ret; +} + + + +BOOL FASTCALL +IntGdiCleanDC(HDC hDC) +{ + PDC dc; + if (!hDC) return FALSE; + dc = DC_LockDc ( hDC ); + if (!dc) return FALSE; + // Clean the DC + if (defaultDCstate) IntGdiCopyFromSaveState(dc, defaultDCstate, hDC ); + return TRUE; +} + diff --git a/reactos/subsystems/win32/win32k/objects/dcutil.c b/reactos/subsystems/win32/win32k/objects/dcutil.c index 88adb267234..f75ba8953aa 100644 --- a/reactos/subsystems/win32/win32k/objects/dcutil.c +++ b/reactos/subsystems/win32/win32k/objects/dcutil.c @@ -105,58 +105,6 @@ INT APIENTRY func_name( HDC hdc, INT mode ) \ } -static -VOID -CopytoUserDcAttr(PDC dc, PDC_ATTR pdcattr) -{ - NTSTATUS Status = STATUS_SUCCESS; - dc->dcattr.mxWorldToDevice = dc->dclevel.mxWorldToDevice; - dc->dcattr.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld; - dc->dcattr.mxWorldToPage = dc->dclevel.mxWorldToPage; - - _SEH2_TRY - { - ProbeForWrite( pdcattr, - sizeof(DC_ATTR), - 1); - RtlCopyMemory( pdcattr, - &dc->dcattr, - sizeof(DC_ATTR)); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - ASSERT(FALSE); - } - _SEH2_END; -} - - -BOOL -FASTCALL -DCU_SyncDcAttrtoUser(PDC dc) -{ - PDC_ATTR pdcattr = dc->pdcattr; - - if (pdcattr == &dc->dcattr) return TRUE; // No need to copy self. - ASSERT(pdcattr); - CopytoUserDcAttr( dc, pdcattr); - return TRUE; -} - -BOOL -FASTCALL -DCU_SynchDcAttrtoUser(HDC hDC) -{ - BOOL Ret; - PDC pDC = DC_LockDc ( hDC ); - if (!pDC) return FALSE; - Ret = DCU_SyncDcAttrtoUser(pDC); - DC_UnlockDc( pDC ); - return Ret; -} - - DC_GET_VAL( INT, IntGdiGetMapMode, iMapMode ) DC_GET_VAL( INT, IntGdiGetPolyFillMode, jFillMode ) DC_GET_VAL( COLORREF, IntGdiGetBkColor, crBackgroundClr ) @@ -283,3 +231,293 @@ DCU_SetDcUndeletable(HDC hDC) DC_UnlockDc( dc ); return; } + +#if 0 +BOOL FASTCALL +IntIsPrimarySurface(SURFOBJ *SurfObj) +{ + if (PrimarySurface.pSurface == NULL) + { + return FALSE; + } + return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF? +} +#endif + +// FIXME: remove me +HDC FASTCALL +DC_GetNextDC (PDC pDC) +{ + return pDC->hdcNext; +} + +VOID FASTCALL +DC_SetNextDC (PDC pDC, HDC hNextDC) +{ + pDC->hdcNext = hNextDC; +} + + +BOOL APIENTRY +NtGdiCancelDC(HDC hDC) +{ + UNIMPLEMENTED; + return FALSE; +} + + + + +WORD APIENTRY +IntGdiSetHookFlags(HDC hDC, WORD Flags) +{ + WORD wRet; + DC *dc = DC_LockDc(hDC); + + if (NULL == dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + + wRet = dc->fs & DC_FLAG_DIRTY_RAO; // Fixme wrong flag! + + /* "Undocumented Windows" info is slightly confusing. + */ + + DPRINT("DC %p, Flags %04x\n", hDC, Flags); + + if (Flags & DCHF_INVALIDATEVISRGN) + { /* hVisRgn has to be updated */ + dc->fs |= DC_FLAG_DIRTY_RAO; + } + else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags) + { + dc->fs &= ~DC_FLAG_DIRTY_RAO; + } + + DC_UnlockDc(dc); + + return wRet; +} + + +BOOL +APIENTRY +NtGdiGetDCDword( + HDC hDC, + UINT u, + DWORD *Result + ) +{ + BOOL Ret = TRUE; + PDC dc; + PDC_ATTR pdcattr; + + DWORD SafeResult = 0; + NTSTATUS Status = STATUS_SUCCESS; + + if(!Result) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + + dc = DC_LockDc(hDC); + if(!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + pdcattr = dc->pdcattr; + + switch (u) + { + case GdiGetJournal: + break; + case GdiGetRelAbs: + SafeResult = pdcattr->lRelAbs; + break; + case GdiGetBreakExtra: + SafeResult = pdcattr->lBreakExtra; + break; + case GdiGerCharBreak: + SafeResult = pdcattr->cBreak; + break; + case GdiGetArcDirection: + if (pdcattr->dwLayout & LAYOUT_RTL) + SafeResult = AD_CLOCKWISE - ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0); + else + SafeResult = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE; + break; + case GdiGetEMFRestorDc: + break; + case GdiGetFontLanguageInfo: + SafeResult = IntGetFontLanguageInfo(dc); + break; + case GdiGetIsMemDc: + SafeResult = dc->dctype; + break; + case GdiGetMapMode: + SafeResult = pdcattr->iMapMode; + break; + case GdiGetTextCharExtra: + SafeResult = pdcattr->lTextExtra; + break; + default: + SetLastWin32Error(ERROR_INVALID_PARAMETER); + Ret = FALSE; + break; + } + + if (Ret) + { + _SEH2_TRY + { + ProbeForWrite(Result, + sizeof(DWORD), + 1); + *Result = SafeResult; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + } + + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + DC_UnlockDc(dc); + return FALSE; + } + + DC_UnlockDc(dc); + return Ret; +} + +BOOL +APIENTRY +NtGdiGetAndSetDCDword( + HDC hDC, + UINT u, + DWORD dwIn, + DWORD *Result + ) +{ + BOOL Ret = TRUE; + PDC dc; + PDC_ATTR pdcattr; + + DWORD SafeResult = 0; + NTSTATUS Status = STATUS_SUCCESS; + + if(!Result) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + + dc = DC_LockDc(hDC); + if(!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + pdcattr = dc->pdcattr; + + switch (u) + { + case GdiGetSetCopyCount: + SafeResult = dc->ulCopyCount; + dc->ulCopyCount = dwIn; + break; + case GdiGetSetTextAlign: + SafeResult = pdcattr->lTextAlign; + pdcattr->lTextAlign = dwIn; + // pdcattr->flTextAlign = dwIn; // Flags! + break; + case GdiGetSetRelAbs: + SafeResult = pdcattr->lRelAbs; + pdcattr->lRelAbs = dwIn; + break; + case GdiGetSetTextCharExtra: + SafeResult = pdcattr->lTextExtra; + pdcattr->lTextExtra = dwIn; + break; + case GdiGetSetSelectFont: + break; + case GdiGetSetMapperFlagsInternal: + if (dwIn & ~1) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + Ret = FALSE; + break; + } + SafeResult = pdcattr->flFontMapper; + pdcattr->flFontMapper = dwIn; + break; + case GdiGetSetMapMode: + SafeResult = IntGdiSetMapMode( dc, dwIn); + break; + case GdiGetSetArcDirection: + if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + Ret = FALSE; + break; + } + if ( pdcattr->dwLayout & LAYOUT_RTL ) // Right to Left + { + SafeResult = AD_CLOCKWISE - ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0); + if ( dwIn == AD_CLOCKWISE ) + { + dc->dclevel.flPath &= ~DCPATH_CLOCKWISE; + break; + } + dc->dclevel.flPath |= DCPATH_CLOCKWISE; + } + else // Left to Right + { + SafeResult = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE; + if ( dwIn == AD_COUNTERCLOCKWISE) + { + dc->dclevel.flPath &= ~DCPATH_CLOCKWISE; + break; + } + dc->dclevel.flPath |= DCPATH_CLOCKWISE; + } + break; + default: + SetLastWin32Error(ERROR_INVALID_PARAMETER); + Ret = FALSE; + break; + } + + if (Ret) + { + _SEH2_TRY + { + ProbeForWrite(Result, + sizeof(DWORD), + 1); + *Result = SafeResult; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + } + + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + DC_UnlockDc(dc); + return FALSE; + } + + DC_UnlockDc(dc); + return Ret; +} diff --git a/reactos/subsystems/win32/win32k/objects/dc.c b/reactos/subsystems/win32/win32k/objects/device.c similarity index 50% rename from reactos/subsystems/win32/win32k/objects/dc.c rename to reactos/subsystems/win32/win32k/objects/device.c index 732e7809e19..cd7cb75133c 100644 --- a/reactos/subsystems/win32/win32k/objects/dc.c +++ b/reactos/subsystems/win32/win32k/objects/device.c @@ -1,35 +1,19 @@ -/* - * ReactOS W32 Subsystem - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * DC.C - Device context functions - * +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Functions for creation and destruction of DCs + * FILE: subsystem/win32/win32k/objects/device.c + * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org) */ #include -#include #define NDEBUG #include -// --------------------------------------------------------- File Statics +// TODO: proper implementation of LDEVOBJ and PDEVOBJ interface -static PDEVOBJ PrimarySurface; +/*static*/ PDEVOBJ PrimarySurface; PPDEVOBJ pPrimarySurface = &PrimarySurface; static KEVENT VideoDriverNeedsPreparation; static KEVENT VideoDriverPrepared; @@ -44,121 +28,6 @@ InitDcImpl(VOID) return STATUS_SUCCESS; } -/* FIXME: DCs should probably be thread safe */ - -// ----------------------------------------------------- Public Functions - -BOOL APIENTRY -NtGdiCancelDC(HDC hDC) -{ - UNIMPLEMENTED; - return FALSE; -} - -HDC APIENTRY -NtGdiCreateCompatibleDC(HDC hDC) -{ - PDC NewDC, OrigDC; - PDC_ATTR pdcattrNew, pdcattrOld; - HDC hNewDC, DisplayDC = NULL; - HRGN hVisRgn; - UNICODE_STRING DriverName; - DWORD Layout = 0; - - if (hDC == NULL) - { - RtlInitUnicodeString(&DriverName, L"DISPLAY"); - DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE); - if (NULL == DisplayDC) - { - DPRINT1("Failed to create DisplayDC\n"); - return NULL; - } - hDC = DisplayDC; - } - - /* Allocate a new DC based on the original DC's device */ - OrigDC = DC_LockDc(hDC); - if (NULL == OrigDC) - { - if (NULL != DisplayDC) - { - NtGdiDeleteObjectApp(DisplayDC); - } - DPRINT1("Failed to lock hDC\n"); - return NULL; - } - hNewDC = DC_AllocDC(&OrigDC->rosdc.DriverName); - if (NULL == hNewDC) - { - DPRINT1("Failed to create hNewDC\n"); - DC_UnlockDc(OrigDC); - if (NULL != DisplayDC) - { - NtGdiDeleteObjectApp(DisplayDC); - } - return NULL; - } - NewDC = DC_LockDc( hNewDC ); - - if(!NewDC) - { - DPRINT1("Failed to lock hNewDC\n"); - NtGdiDeleteObjectApp(hNewDC); - return NULL; - } - - pdcattrOld = OrigDC->pdcattr; - pdcattrNew = NewDC->pdcattr; - - /* Copy information from original DC to new DC */ - NewDC->dclevel.hdcSave = hNewDC; - - NewDC->dhpdev = OrigDC->dhpdev; - - NewDC->rosdc.bitsPerPixel = OrigDC->rosdc.bitsPerPixel; - - /* DriverName is copied in the AllocDC routine */ - pdcattrNew->ptlWindowOrg = pdcattrOld->ptlWindowOrg; - pdcattrNew->szlWindowExt = pdcattrOld->szlWindowExt; - pdcattrNew->ptlViewportOrg = pdcattrOld->ptlViewportOrg; - pdcattrNew->szlViewportExt = pdcattrOld->szlViewportExt; - - NewDC->dctype = DC_TYPE_MEMORY; // Always! - NewDC->rosdc.hBitmap = NtGdiGetStockObject(DEFAULT_BITMAP); - NewDC->ppdev = OrigDC->ppdev; - NewDC->dclevel.hpal = OrigDC->dclevel.hpal; - - pdcattrNew->lTextAlign = pdcattrOld->lTextAlign; - pdcattrNew->lBkMode = pdcattrOld->lBkMode; - pdcattrNew->jBkMode = pdcattrOld->jBkMode; - pdcattrNew->jROP2 = pdcattrOld->jROP2; - pdcattrNew->dwLayout = pdcattrOld->dwLayout; - if (pdcattrOld->dwLayout & LAYOUT_ORIENTATIONMASK) Layout = pdcattrOld->dwLayout; - NewDC->dclevel.flPath = OrigDC->dclevel.flPath; - pdcattrNew->ulDirty_ = pdcattrOld->ulDirty_; - pdcattrNew->iCS_CP = pdcattrOld->iCS_CP; - - NewDC->erclWindow = (RECTL){0,0,1,1}; - - DC_UnlockDc(NewDC); - DC_UnlockDc(OrigDC); - if (NULL != DisplayDC) - { - NtGdiDeleteObjectApp(DisplayDC); - } - - hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1); - if (hVisRgn) - { - GdiSelectVisRgn(hNewDC, hVisRgn); - NtGdiDeleteObject(hVisRgn); - } - if (Layout) NtGdiSetLayout( hNewDC, -1, Layout); - - DC_InitDC(hNewDC); - return hNewDC; -} static BOOLEAN FASTCALL GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber) @@ -225,6 +94,7 @@ FindDriverFileNames(PUNICODE_STRING DriverFileNames, ULONG DisplayNumber) return TRUE; } + static NTSTATUS APIENTRY DevModeCallback(IN PWSTR ValueName, IN ULONG ValueType, @@ -273,6 +143,7 @@ DevModeCallback(IN PWSTR ValueName, return STATUS_SUCCESS; } + static BOOL FASTCALL SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber) { @@ -565,7 +436,7 @@ cleanup: return ret; } -static BOOL FASTCALL +BOOL FASTCALL IntPrepareDriverIfNeeded() { return (PrimarySurface.PreparedDriver ? TRUE : IntPrepareDriver()); @@ -731,868 +602,6 @@ IntDestroyPrimarySurface() ObDereferenceObject(PrimarySurface.VideoFileObject); } -HDC FASTCALL -IntGdiCreateDC(PUNICODE_STRING Driver, - PUNICODE_STRING Device, - PVOID pUMdhpdev, - CONST PDEVMODEW InitData, - BOOL CreateAsIC) -{ - HDC hdc; - PDC pdc; - PDC_ATTR pdcattr; - HRGN hVisRgn; - UNICODE_STRING StdDriver; - BOOL calledFromUser; - - RtlInitUnicodeString(&StdDriver, L"DISPLAY"); - - DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver, Device); - - if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE)) - { - if (CreateAsIC) - { - if (! IntPrepareDriverIfNeeded()) - { - /* Here, we have two possibilities: - * a) return NULL, and hope that the caller - * won't call us in a loop - * b) bugcheck, but caller is unable to - * react on the problem - */ - /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n"); - return NULL;*/ - KeBugCheck(VIDEO_DRIVER_INIT_FAILURE); - } - } - else - { - calledFromUser = UserIsEntered(); - if (!calledFromUser){ - UserEnterExclusive(); - } - - if (! co_IntGraphicsCheck(TRUE)) - { - if (!calledFromUser){ - UserLeave(); - } - DPRINT1("Unable to initialize graphics, returning NULL dc\n"); - return NULL; - } - - if (!calledFromUser){ - UserLeave(); - } - - } - } - - /* Check for existing DC object */ - if ((hdc = DC_FindOpenDC(Driver)) != NULL) - { - hdc = NtGdiCreateCompatibleDC(hdc); - if (!hdc) - DPRINT1("NtGdiCreateCompatibleDC() failed\n"); - return hdc; - } - - /* Allocate a DC object */ - if ((hdc = DC_AllocDC(Driver)) == NULL) - { - DPRINT1("DC_AllocDC() failed\n"); - return NULL; - } - - pdc = DC_LockDc( hdc ); - if ( !pdc ) - { - DC_FreeDC( hdc ); - DPRINT1("DC_LockDc() failed\n"); - return NULL; - } - - pdcattr = pdc->pdcattr; - - pdc->dctype = DC_TYPE_DIRECT; - - pdc->dhpdev = PrimarySurface.hPDev; - if(pUMdhpdev) pUMdhpdev = pdc->dhpdev; // set DHPDEV for device. - pdc->ppdev = (PVOID)&PrimarySurface; - pdc->rosdc.hBitmap = (HBITMAP)PrimarySurface.pSurface; - // ATM we only have one display. - pdcattr->ulDirty_ |= DC_PRIMARY_DISPLAY; - - pdc->rosdc.bitsPerPixel = pdc->ppdev->GDIInfo.cBitsPixel * - pdc->ppdev->GDIInfo.cPlanes; - DPRINT("Bits per pel: %u\n", pdc->rosdc.bitsPerPixel); - - pdc->flGraphicsCaps = PrimarySurface.DevInfo.flGraphicsCaps; - pdc->flGraphicsCaps2 = PrimarySurface.DevInfo.flGraphicsCaps2; - - pdc->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE); - - pdcattr->jROP2 = R2_COPYPEN; - - pdc->erclWindow.top = pdc->erclWindow.left = 0; - pdc->erclWindow.right = pdc->ppdev->GDIInfo.ulHorzRes; - pdc->erclWindow.bottom = pdc->ppdev->GDIInfo.ulVertRes; - pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE; // Default is CCW. - - pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0); - - hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->ppdev->GDIInfo.ulHorzRes, - pdc->ppdev->GDIInfo.ulVertRes); - - if (!CreateAsIC) - { - pdc->pSurfInfo = NULL; -// pdc->dclevel.pSurface = - DC_UnlockDc( pdc ); - - /* Initialize the DC state */ - DC_InitDC(hdc); - IntGdiSetTextColor(hdc, RGB(0, 0, 0)); - IntGdiSetBkColor(hdc, RGB(255, 255, 255)); - } - else - { - /* From MSDN2: - The CreateIC function creates an information context for the specified device. - The information context provides a fast way to get information about the - device without creating a device context (DC). However, GDI drawing functions - cannot accept a handle to an information context. - */ - pdc->dctype = DC_TYPE_INFO; -// pdc->pSurfInfo = - pdc->dclevel.pSurface = NULL; - pdcattr->crBackgroundClr = pdcattr->ulBackgroundClr = RGB(255, 255, 255); - pdcattr->crForegroundClr = RGB(0, 0, 0); - DC_UnlockDc( pdc ); - } - - if (hVisRgn) - { - GdiSelectVisRgn(hdc, hVisRgn); - NtGdiDeleteObject(hVisRgn); - } - - IntGdiSetTextAlign(hdc, TA_TOP); - IntGdiSetBkMode(hdc, OPAQUE); - - return hdc; -} - -HDC APIENTRY -NtGdiOpenDCW( PUNICODE_STRING Device, - DEVMODEW *InitData, - PUNICODE_STRING pustrLogAddr, - ULONG iType, - HANDLE hspool, - VOID *pDriverInfo2, - VOID *pUMdhpdev ) -{ - UNICODE_STRING SafeDevice; - DEVMODEW SafeInitData; - PVOID Dhpdev; - HDC Ret; - NTSTATUS Status = STATUS_SUCCESS; - - if(InitData) - { - _SEH2_TRY - { - if (pUMdhpdev) - { - ProbeForWrite(pUMdhpdev, - sizeof(PVOID), - 1); - } - ProbeForRead(InitData, - sizeof(DEVMODEW), - 1); - RtlCopyMemory(&SafeInitData, - InitData, - sizeof(DEVMODEW)); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END; - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return NULL; - } - /* FIXME - InitData can have some more bytes! */ - } - - if(Device) - { - Status = IntSafeCopyUnicodeString(&SafeDevice, Device); - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return NULL; - } - } - - Ret = IntGdiCreateDC(Device ? &SafeDevice : NULL, - NULL, - pUMdhpdev ? &Dhpdev : NULL, - InitData ? &SafeInitData : NULL, - (BOOL) iType); // FALSE 0 DCW, TRUE 1 ICW - - if (pUMdhpdev) pUMdhpdev = Dhpdev; - - return Ret; - -} - - -HDC FASTCALL -IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC) -{ - HDC hDC; - UNICODE_STRING DriverName; - RtlInitUnicodeString(&DriverName, L"DISPLAY"); - - if (DcType != DC_TYPE_MEMORY) - hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, (DcType == DC_TYPE_INFO)); - else - hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth! -// -// There is room to grow here~ -// - -// -// If NULL, first time through! Build the default (was window) dc! -// - if (hDC && !defaultDCstate) // Ultra HAX! Dedicated to GvG! - { // This is a cheesy way to do this. - PDC dc = DC_LockDc ( hDC ); - defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC); - if (!defaultDCstate) - { - DC_UnlockDc( dc ); - return NULL; - } - RtlZeroMemory(defaultDCstate, sizeof(DC)); - defaultDCstate->pdcattr = &defaultDCstate->dcattr; - IntGdiCopyToSaveState(dc, defaultDCstate); - DC_UnlockDc( dc ); - } - return hDC; -} - -BOOL FASTCALL -IntGdiCleanDC(HDC hDC) -{ - PDC dc; - if (!hDC) return FALSE; - dc = DC_LockDc ( hDC ); - if (!dc) return FALSE; - // Clean the DC - if (defaultDCstate) IntGdiCopyFromSaveState(dc, defaultDCstate, hDC ); - return TRUE; -} - -// -// -// -BOOL -FASTCALL -IntGdiDeleteDC(HDC hDC, BOOL Force) -{ - PDC DCToDelete = DC_LockDc(hDC); - - if (DCToDelete == NULL) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - if(!Force) - { - if (DCToDelete->fs & DC_FLAG_PERMANENT) - { - DPRINT1("No! You Naughty Application!\n"); - DC_UnlockDc( DCToDelete ); - return UserReleaseDC(NULL, hDC, FALSE); - } - } - - /* First delete all saved DCs */ - while (DCToDelete->dclevel.lSaveDepth) - { - PDC savedDC; - HDC savedHDC; - - savedHDC = DC_GetNextDC (DCToDelete); - savedDC = DC_LockDc (savedHDC); - if (savedDC == NULL) - { - break; - } - DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC)); - DCToDelete->dclevel.lSaveDepth--; - DC_UnlockDc( savedDC ); - IntGdiDeleteDC(savedHDC, Force); - } - - /* Free GDI resources allocated to this DC */ - if (!(DCToDelete->dclevel.flPath & DCPATH_SAVESTATE)) - { - /* - NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN); - NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH); - NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT); - DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */ - if (DCToDelete->rosdc.XlateBrush != NULL) - EngDeleteXlate(DCToDelete->rosdc.XlateBrush); - if (DCToDelete->rosdc.XlatePen != NULL) - EngDeleteXlate(DCToDelete->rosdc.XlatePen); - } - if (DCToDelete->rosdc.hClipRgn) - { - NtGdiDeleteObject (DCToDelete->rosdc.hClipRgn); - } - if (DCToDelete->rosdc.hVisRgn) - { - NtGdiDeleteObject (DCToDelete->rosdc.hVisRgn); - } - if (NULL != DCToDelete->rosdc.CombinedClip) - { - IntEngDeleteClipRegion(DCToDelete->rosdc.CombinedClip); - } - if (DCToDelete->rosdc.hGCClipRgn) - { - NtGdiDeleteObject (DCToDelete->rosdc.hGCClipRgn); - } - PATH_Delete(DCToDelete->dclevel.hPath); - - DC_UnlockDc( DCToDelete ); - DC_FreeDC ( hDC ); - return TRUE; -} - -BOOL -APIENTRY -NtGdiDeleteObjectApp(HANDLE DCHandle) -{ - /* Complete all pending operations */ - NtGdiFlushUserBatch(); - - if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE; - - if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC) - return NtGdiDeleteObject((HGDIOBJ) DCHandle); - - if(IsObjectDead((HGDIOBJ)DCHandle)) return TRUE; - - if (!GDIOBJ_OwnedByCurrentProcess(DCHandle)) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - return IntGdiDeleteDC(DCHandle, FALSE); -} - -INT -APIENTRY -NtGdiDrawEscape( - IN HDC hdc, - IN INT iEsc, - IN INT cjIn, - IN OPTIONAL LPSTR pjIn) -{ - UNIMPLEMENTED; - return 0; -} - -ULONG -APIENTRY -NtGdiEnumObjects( - IN HDC hdc, - IN INT iObjectType, - IN ULONG cjBuf, - OUT OPTIONAL PVOID pvBuf) -{ - UNIMPLEMENTED; - return 0; -} - -HANDLE -APIENTRY -NtGdiGetDCObject(HDC hDC, INT ObjectType) -{ - HGDIOBJ SelObject; - DC *dc; - PDC_ATTR pdcattr; - - /* From Wine: GetCurrentObject does not SetLastError() on a null object */ - if(!hDC) return NULL; - - if(!(dc = DC_LockDc(hDC))) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return NULL; - } - pdcattr = dc->pdcattr; - - if (pdcattr->ulDirty_ & DC_BRUSH_DIRTY) - IntGdiSelectBrush(dc,pdcattr->hbrush); - - if (pdcattr->ulDirty_ & DC_PEN_DIRTY) - IntGdiSelectPen(dc,pdcattr->hpen); - - switch(ObjectType) - { - case GDI_OBJECT_TYPE_EXTPEN: - case GDI_OBJECT_TYPE_PEN: - SelObject = pdcattr->hpen; - break; - case GDI_OBJECT_TYPE_BRUSH: - SelObject = pdcattr->hbrush; - break; - case GDI_OBJECT_TYPE_PALETTE: - SelObject = dc->dclevel.hpal; - break; - case GDI_OBJECT_TYPE_FONT: - SelObject = pdcattr->hlfntNew; - break; - case GDI_OBJECT_TYPE_BITMAP: - SelObject = dc->rosdc.hBitmap; - break; - case GDI_OBJECT_TYPE_COLORSPACE: - DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n"); - // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ? - SelObject = NULL; - break; - default: - SelObject = NULL; - SetLastWin32Error(ERROR_INVALID_PARAMETER); - break; - } - - DC_UnlockDc(dc); - return SelObject; -} - -LONG FASTCALL -IntCalcFillOrigin(PDC pdc) -{ - pdc->ptlFillOrigin.x = pdc->dclevel.ptlBrushOrigin.x + pdc->ptlDCOrig.x; - pdc->ptlFillOrigin.y = pdc->dclevel.ptlBrushOrigin.y + pdc->ptlDCOrig.y; - - return pdc->ptlFillOrigin.y; -} - -VOID -APIENTRY -GdiSetDCOrg(HDC hDC, LONG Left, LONG Top, PRECTL prc) -{ - PDC pdc; - - pdc = DC_LockDc(hDC); - if (!pdc) return; - - pdc->ptlDCOrig.x = Left; - pdc->ptlDCOrig.y = Top; - - IntCalcFillOrigin(pdc); - - if (prc) pdc->erclWindow = *prc; - - DC_UnlockDc(pdc); -} - - -BOOL FASTCALL -IntGdiGetDCOrg(PDC pDc, PPOINTL ppt) -{ - *ppt = pDc->ptlDCOrig; - return TRUE; -} - -BOOL APIENTRY -GdiGetDCOrgEx(HDC hDC, PPOINTL ppt, PRECTL prc) -{ - PDC pdc; - - pdc = DC_LockDc(hDC); - if (!pdc) return FALSE; - - *prc = pdc->erclWindow; - *ppt = pdc->ptlDCOrig; - - DC_UnlockDc(pdc); - return TRUE; -} - -BOOL FASTCALL -IntGetAspectRatioFilter(PDC pDC, - LPSIZE AspectRatio) -{ - PDC_ATTR pdcattr; - - pdcattr = pDC->pdcattr; - - if ( pdcattr->flFontMapper & 1 ) // TRUE assume 1. - { - // "This specifies that Windows should only match fonts that have the - // same aspect ratio as the display.", Programming Windows, Fifth Ed. - AspectRatio->cx = pDC->ppdev->GDIInfo.ulLogPixelsX; - AspectRatio->cy = pDC->ppdev->GDIInfo.ulLogPixelsY; - } - else - { - AspectRatio->cx = 0; - AspectRatio->cy = 0; - } - return TRUE; -} - -VOID -FASTCALL -IntGetViewportExtEx(PDC pdc, LPSIZE pSize) -{ - PDC_ATTR pdcattr; - - /* Get a pointer to the dc attribute */ - pdcattr = pdc->pdcattr; - - /* Check if we need to recalculate */ - if (pdcattr->flXform & PAGE_EXTENTS_CHANGED) - { - /* Check if we need to do isotropic fixup */ - if (pdcattr->iMapMode == MM_ISOTROPIC) - { - IntFixIsotropicMapping(pdc); - } - - /* Update xforms, CHECKME: really done here? */ - DC_UpdateXforms(pdc); - } - - /* Copy the viewport extension */ - *pSize = pdcattr->szlViewportExt; -} - -BOOL APIENTRY -NtGdiGetDCPoint( HDC hDC, UINT iPoint, PPOINTL Point) -{ - BOOL Ret = TRUE; - DC *dc; - POINTL SafePoint; - SIZE Size; - NTSTATUS Status = STATUS_SUCCESS; - - if(!Point) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - - RtlZeroMemory(&SafePoint, sizeof(POINT)); - - dc = DC_LockDc(hDC); - if(!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - switch (iPoint) - { - case GdiGetViewPortExt: - IntGetViewportExtEx(dc, &Size); - SafePoint.x = Size.cx; - SafePoint.y = Size.cy; - break; - case GdiGetWindowExt: - IntGetWindowExtEx(dc, &Size); - SafePoint.x = Size.cx; - SafePoint.y = Size.cy; - break; - case GdiGetViewPortOrg: - IntGetViewportOrgEx(dc, &SafePoint); - break; - case GdiGetWindowOrg: - IntGetWindowOrgEx(dc, &SafePoint); - break; - case GdiGetDCOrg: - Ret = IntGdiGetDCOrg(dc, &SafePoint); - break; - case GdiGetAspectRatioFilter: - Ret = IntGetAspectRatioFilter(dc, &Size); - SafePoint.x = Size.cx; - SafePoint.y = Size.cy; - break; - default: - SetLastWin32Error(ERROR_INVALID_PARAMETER); - Ret = FALSE; - break; - } - - if (Ret) - { - _SEH2_TRY - { - ProbeForWrite(Point, - sizeof(POINT), - 1); - *Point = SafePoint; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END; - } - - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - DC_UnlockDc(dc); - return FALSE; - } - - DC_UnlockDc(dc); - return Ret; -} - -VOID -FASTCALL -IntGdiCopyToSaveState(PDC dc, PDC newdc) -{ - PDC_ATTR pdcattr, nDc_Attr; - - pdcattr = dc->pdcattr; - nDc_Attr = newdc->pdcattr; - - newdc->dclevel.flPath = dc->dclevel.flPath | DCPATH_SAVESTATE; - - nDc_Attr->dwLayout = pdcattr->dwLayout; - nDc_Attr->hpen = pdcattr->hpen; - nDc_Attr->hbrush = pdcattr->hbrush; - nDc_Attr->hlfntNew = pdcattr->hlfntNew; - newdc->rosdc.hBitmap = dc->rosdc.hBitmap; - newdc->dclevel.hpal = dc->dclevel.hpal; - newdc->rosdc.bitsPerPixel = dc->rosdc.bitsPerPixel; - nDc_Attr->jROP2 = pdcattr->jROP2; - nDc_Attr->jFillMode = pdcattr->jFillMode; - nDc_Attr->jStretchBltMode = pdcattr->jStretchBltMode; - nDc_Attr->lRelAbs = pdcattr->lRelAbs; - nDc_Attr->jBkMode = pdcattr->jBkMode; - nDc_Attr->lBkMode = pdcattr->lBkMode; - nDc_Attr->crBackgroundClr = pdcattr->crBackgroundClr; - nDc_Attr->crForegroundClr = pdcattr->crForegroundClr; - nDc_Attr->ulBackgroundClr = pdcattr->ulBackgroundClr; - nDc_Attr->ulForegroundClr = pdcattr->ulForegroundClr; - nDc_Attr->ptlBrushOrigin = pdcattr->ptlBrushOrigin; - nDc_Attr->lTextAlign = pdcattr->lTextAlign; - nDc_Attr->lTextExtra = pdcattr->lTextExtra; - nDc_Attr->cBreak = pdcattr->cBreak; - nDc_Attr->lBreakExtra = pdcattr->lBreakExtra; - nDc_Attr->iMapMode = pdcattr->iMapMode; - nDc_Attr->iGraphicsMode = pdcattr->iGraphicsMode; -#if 0 - /* Apparently, the DC origin is not changed by [GS]etDCState */ - newdc->ptlDCOrig.x = dc->ptlDCOrig.x; - newdc->ptlDCOrig.y = dc->ptlDCOrig.y; -#endif - nDc_Attr->ptlCurrent = pdcattr->ptlCurrent; - nDc_Attr->ptfxCurrent = pdcattr->ptfxCurrent; - newdc->dclevel.mxWorldToDevice = dc->dclevel.mxWorldToDevice; - newdc->dclevel.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld; - newdc->dclevel.mxWorldToPage = dc->dclevel.mxWorldToPage; - nDc_Attr->flXform = pdcattr->flXform; - nDc_Attr->ptlWindowOrg = pdcattr->ptlWindowOrg; - nDc_Attr->szlWindowExt = pdcattr->szlWindowExt; - nDc_Attr->ptlViewportOrg = pdcattr->ptlViewportOrg; - nDc_Attr->szlViewportExt = pdcattr->szlViewportExt; - - newdc->dclevel.lSaveDepth = 0; - newdc->dctype = dc->dctype; - -#if 0 - PATH_InitGdiPath( &newdc->dclevel.hPath ); -#endif - - /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */ - - newdc->rosdc.hGCClipRgn = newdc->rosdc.hVisRgn = 0; - if (dc->rosdc.hClipRgn) - { - newdc->rosdc.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - NtGdiCombineRgn( newdc->rosdc.hClipRgn, dc->rosdc.hClipRgn, 0, RGN_COPY ); - } -} - - -VOID -FASTCALL -IntGdiCopyFromSaveState(PDC dc, PDC dcs, HDC hDC) -{ - PDC_ATTR pdcattr, sDc_Attr; - - pdcattr = dc->pdcattr; - sDc_Attr = dcs->pdcattr; - - dc->dclevel.flPath = dcs->dclevel.flPath & ~DCPATH_SAVESTATE; - - pdcattr->dwLayout = sDc_Attr->dwLayout; - pdcattr->jROP2 = sDc_Attr->jROP2; - pdcattr->jFillMode = sDc_Attr->jFillMode; - pdcattr->jStretchBltMode = sDc_Attr->jStretchBltMode; - pdcattr->lRelAbs = sDc_Attr->lRelAbs; - pdcattr->jBkMode = sDc_Attr->jBkMode; - pdcattr->crBackgroundClr = sDc_Attr->crBackgroundClr; - pdcattr->crForegroundClr = sDc_Attr->crForegroundClr; - pdcattr->lBkMode = sDc_Attr->lBkMode; - pdcattr->ulBackgroundClr = sDc_Attr->ulBackgroundClr; - pdcattr->ulForegroundClr = sDc_Attr->ulForegroundClr; - pdcattr->ptlBrushOrigin = sDc_Attr->ptlBrushOrigin; - - pdcattr->lTextAlign = sDc_Attr->lTextAlign; - pdcattr->lTextExtra = sDc_Attr->lTextExtra; - pdcattr->cBreak = sDc_Attr->cBreak; - pdcattr->lBreakExtra = sDc_Attr->lBreakExtra; - pdcattr->iMapMode = sDc_Attr->iMapMode; - pdcattr->iGraphicsMode = sDc_Attr->iGraphicsMode; -#if 0 -/* Apparently, the DC origin is not changed by [GS]etDCState */ - dc->ptlDCOrig.x = dcs->ptlDCOrig.x; - dc->ptlDCOrig.y = dcs->ptlDCOrig.y; -#endif - pdcattr->ptlCurrent = sDc_Attr->ptlCurrent; - pdcattr->ptfxCurrent = sDc_Attr->ptfxCurrent; - dc->dclevel.mxWorldToDevice = dcs->dclevel.mxWorldToDevice; - dc->dclevel.mxDeviceToWorld = dcs->dclevel.mxDeviceToWorld; - dc->dclevel.mxWorldToPage = dcs->dclevel.mxWorldToPage; - pdcattr->flXform = sDc_Attr->flXform; - pdcattr->ptlWindowOrg = sDc_Attr->ptlWindowOrg; - pdcattr->szlWindowExt = sDc_Attr->szlWindowExt; - pdcattr->ptlViewportOrg = sDc_Attr->ptlViewportOrg; - pdcattr->szlViewportExt = sDc_Attr->szlViewportExt; - - if (dc->dctype != DC_TYPE_MEMORY) - { - dc->rosdc.bitsPerPixel = dcs->rosdc.bitsPerPixel; - } - -#if 0 - if (dcs->rosdc.hClipRgn) - { - if (!dc->rosdc.hClipRgn) - { - dc->rosdc.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - } - NtGdiCombineRgn( dc->rosdc.hClipRgn, dcs->rosdc.hClipRgn, 0, RGN_COPY ); - } - else - { - if (dc->rosdc.hClipRgn) - { - NtGdiDeleteObject( dc->rosdc.hClipRgn ); - } - dc->rosdc.hClipRgn = 0; - } - { - int res; - res = CLIPPING_UpdateGCRegion( dc ); - ASSERT ( res != ERROR ); - } - DC_UnlockDc ( dc ); -#else - GdiExtSelectClipRgn(dc, dcs->rosdc.hClipRgn, RGN_COPY); - DC_UnlockDc ( dc ); -#endif - if(!hDC) return; // Not a MemoryDC or SaveLevel DC, return. - - NtGdiSelectBitmap( hDC, dcs->rosdc.hBitmap ); - NtGdiSelectBrush( hDC, sDc_Attr->hbrush ); - NtGdiSelectFont( hDC, sDc_Attr->hlfntNew ); - NtGdiSelectPen( hDC, sDc_Attr->hpen ); - - IntGdiSetBkColor( hDC, sDc_Attr->crBackgroundClr); - IntGdiSetTextColor( hDC, sDc_Attr->crForegroundClr); - - GdiSelectPalette( hDC, dcs->dclevel.hpal, FALSE ); - -#if 0 - GDISelectPalette16( hDC, dcs->dclevel.hpal, FALSE ); -#endif -} - -HDC APIENTRY -IntGdiGetDCState(HDC hDC) -{ - PDC newdc, dc; - HDC hnewdc; - - dc = DC_LockDc(hDC); - if (dc == NULL) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return 0; - } - - hnewdc = DC_AllocDC(NULL); - if (hnewdc == NULL) - { - DC_UnlockDc(dc); - return 0; - } - newdc = DC_LockDc( hnewdc ); - /* FIXME - newdc can be NULL!!!! Don't assert here!!! */ - ASSERT( newdc ); - - newdc->dclevel.hdcSave = hnewdc; - IntGdiCopyToSaveState( dc, newdc); - - DC_UnlockDc( newdc ); - DC_UnlockDc( dc ); - return hnewdc; -} - - -VOID -APIENTRY -IntGdiSetDCState ( HDC hDC, HDC hDCSave ) -{ - PDC dc, dcs; - - dc = DC_LockDc ( hDC ); - if ( dc ) - { - dcs = DC_LockDc ( hDCSave ); - if ( dcs ) - { - if ( dcs->dclevel.flPath & DCPATH_SAVESTATE ) - { - IntGdiCopyFromSaveState( dc, dcs, dc->dclevel.hdcSave); - } - else - { - DC_UnlockDc(dc); - } - DC_UnlockDc ( dcs ); - } - else - { - DC_UnlockDc ( dc ); - SetLastWin32Error(ERROR_INVALID_HANDLE); - } - } - else - SetLastWin32Error(ERROR_INVALID_HANDLE); -} - INT FASTCALL IntcFonts(PPDEVOBJ pDevObj) @@ -1612,6 +621,72 @@ IntcFonts(PPDEVOBJ pDevObj) return pDevObj->DevInfo.cFonts; } +// +// Support multi display/device locks. +// +VOID +FASTCALL +DC_LockDisplay(HDC hDC) +{ + PERESOURCE Resource; + PDC dc = DC_LockDc(hDC); + if (!dc) return; + Resource = dc->ppdev->hsemDevLock; + DC_UnlockDc(dc); + if (!Resource) return; + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite( Resource , TRUE); +} + +VOID +FASTCALL +DC_UnlockDisplay(HDC hDC) +{ + PERESOURCE Resource; + PDC dc = DC_LockDc(hDC); + if (!dc) return; + Resource = dc->ppdev->hsemDevLock; + DC_UnlockDc(dc); + if (!Resource) return; + ExReleaseResourceLite( Resource ); + KeLeaveCriticalRegion(); +} + +// +// Enumerate HDev +// +PPDEVOBJ FASTCALL +IntEnumHDev(VOID) +{ +// I guess we will soon have more than one primary surface. +// This will do for now. + return &PrimarySurface; +} + + +VOID FASTCALL +IntGdiReferencePdev(PPDEVOBJ ppdev) +{ + if(!hsemDriverMgmt) hsemDriverMgmt = EngCreateSemaphore(); // Hax, should be in dllmain.c + IntGdiAcquireSemaphore(hsemDriverMgmt); + ppdev->cPdevRefs++; + IntGdiReleaseSemaphore(hsemDriverMgmt); +} + +VOID FASTCALL +IntGdiUnreferencePdev(PPDEVOBJ ppdev, DWORD CleanUpType) +{ + IntGdiAcquireSemaphore(hsemDriverMgmt); + ppdev->cPdevRefs--; + if (!ppdev->cPdevRefs) + { + // Handle the destruction of ppdev or PDEVOBJ or PDEVOBJ or PDEV etc. + } + IntGdiReleaseSemaphore(hsemDriverMgmt); +} + + + INT FASTCALL IntGetColorManagementCaps(PPDEVOBJ pDevObj) @@ -1950,841 +1025,353 @@ NtGdiGetDeviceCapsAll ( } - -BOOL -APIENTRY -NtGdiResetDC( - IN HDC hdc, - IN LPDEVMODEW pdm, - OUT PBOOL pbBanding, - IN OPTIONAL VOID *pDriverInfo2, - OUT VOID *ppUMdhpdev) -{ - UNIMPLEMENTED; - return 0; -} - -BOOL APIENTRY -NtGdiRestoreDC(HDC hDC, INT SaveLevel) -{ - PDC dc, dcs; - BOOL success; - - DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC, SaveLevel); - - dc = DC_LockDc(hDC); - if (!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - if (SaveLevel < 0) - SaveLevel = dc->dclevel.lSaveDepth + SaveLevel + 1; - - if(SaveLevel < 0 || dc->dclevel.lSaveDepthdclevel.lSaveDepth >= SaveLevel) - { - HDC hdcs = DC_GetNextDC (dc); - - dcs = DC_LockDc (hdcs); - if (dcs == NULL) - { - DC_UnlockDc(dc); - return FALSE; - } - - DC_SetNextDC (dc, DC_GetNextDC (dcs)); - dcs->hdcNext = 0; - - if (--dc->dclevel.lSaveDepth < SaveLevel) - { - DC_UnlockDc( dc ); - DC_UnlockDc( dcs ); - - IntGdiSetDCState(hDC, hdcs); - - dc = DC_LockDc(hDC); - if(!dc) - { - return FALSE; - } - // Restore Path by removing it, if the Save flag is set. - // BeginPath will takecare of the rest. - if ( dc->dclevel.hPath && dc->dclevel.flPath & DCPATH_SAVE) - { - PATH_Delete(dc->dclevel.hPath); - dc->dclevel.hPath = 0; - dc->dclevel.flPath &= ~DCPATH_SAVE; - } - } - else - { - DC_UnlockDc( dcs ); - } - NtGdiDeleteObjectApp (hdcs); - } - DC_UnlockDc( dc ); - return success; -} - - -INT APIENTRY -NtGdiSaveDC(HDC hDC) -{ - HDC hdcs; - PDC dc, dcs; - INT ret; - - DPRINT("NtGdiSaveDC(%lx)\n", hDC); - - if (!(hdcs = IntGdiGetDCState(hDC))) - { - return 0; - } - - dcs = DC_LockDc (hdcs); - if (dcs == NULL) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return 0; - } - dc = DC_LockDc (hDC); - if (dc == NULL) - { - DC_UnlockDc(dcs); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return 0; - } - - /* - * Copy path. - */ - dcs->dclevel.hPath = dc->dclevel.hPath; - if (dcs->dclevel.hPath) dcs->dclevel.flPath |= DCPATH_SAVE; - - DC_SetNextDC (dcs, DC_GetNextDC (dc)); - DC_SetNextDC (dc, hdcs); - ret = ++dc->dclevel.lSaveDepth; - DC_UnlockDc( dcs ); - DC_UnlockDc( dc ); - - return ret; -} - - -HPALETTE -FASTCALL -GdiSelectPalette(HDC hDC, - HPALETTE hpal, - BOOL ForceBackground) -{ - PDC dc; - HPALETTE oldPal = NULL; - PPALGDI PalGDI; - - // FIXME: mark the palette as a [fore\back]ground pal - dc = DC_LockDc(hDC); - if (!dc) - { - return NULL; - } - - /* Check if this is a valid palette handle */ - PalGDI = PALETTE_LockPalette(hpal); - if (!PalGDI) - { - DC_UnlockDc(dc); - return NULL; - } - - /* Is this a valid palette for this depth? */ - if ((dc->rosdc.bitsPerPixel <= 8 && PalGDI->Mode == PAL_INDEXED) || - (dc->rosdc.bitsPerPixel > 8 && PalGDI->Mode != PAL_INDEXED)) - { - oldPal = dc->dclevel.hpal; - dc->dclevel.hpal = hpal; - } - else if (8 < dc->rosdc.bitsPerPixel && PAL_INDEXED == PalGDI->Mode) - { - oldPal = dc->dclevel.hpal; - dc->dclevel.hpal = hpal; - } - - PALETTE_UnlockPalette(PalGDI); - DC_UnlockDc(dc); - - return oldPal; -} - -WORD APIENTRY -IntGdiSetHookFlags(HDC hDC, WORD Flags) -{ - WORD wRet; - DC *dc = DC_LockDc(hDC); - - if (NULL == dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return 0; - } - - wRet = dc->fs & DC_FLAG_DIRTY_RAO; // Fixme wrong flag! - - /* "Undocumented Windows" info is slightly confusing. - */ - - DPRINT("DC %p, Flags %04x\n", hDC, Flags); - - if (Flags & DCHF_INVALIDATEVISRGN) - { /* hVisRgn has to be updated */ - dc->fs |= DC_FLAG_DIRTY_RAO; - } - else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags) - { - dc->fs &= ~DC_FLAG_DIRTY_RAO; - } - - DC_UnlockDc(dc); - - return wRet; -} - - -BOOL -APIENTRY -NtGdiGetDCDword( - HDC hDC, - UINT u, - DWORD *Result - ) -{ - BOOL Ret = TRUE; - PDC dc; - PDC_ATTR pdcattr; - - DWORD SafeResult = 0; - NTSTATUS Status = STATUS_SUCCESS; - - if(!Result) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - - dc = DC_LockDc(hDC); - if(!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - pdcattr = dc->pdcattr; - - switch (u) - { - case GdiGetJournal: - break; - case GdiGetRelAbs: - SafeResult = pdcattr->lRelAbs; - break; - case GdiGetBreakExtra: - SafeResult = pdcattr->lBreakExtra; - break; - case GdiGerCharBreak: - SafeResult = pdcattr->cBreak; - break; - case GdiGetArcDirection: - if (pdcattr->dwLayout & LAYOUT_RTL) - SafeResult = AD_CLOCKWISE - ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0); - else - SafeResult = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE; - break; - case GdiGetEMFRestorDc: - break; - case GdiGetFontLanguageInfo: - SafeResult = IntGetFontLanguageInfo(dc); - break; - case GdiGetIsMemDc: - SafeResult = dc->dctype; - break; - case GdiGetMapMode: - SafeResult = pdcattr->iMapMode; - break; - case GdiGetTextCharExtra: - SafeResult = pdcattr->lTextExtra; - break; - default: - SetLastWin32Error(ERROR_INVALID_PARAMETER); - Ret = FALSE; - break; - } - - if (Ret) - { - _SEH2_TRY - { - ProbeForWrite(Result, - sizeof(DWORD), - 1); - *Result = SafeResult; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END; - } - - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - DC_UnlockDc(dc); - return FALSE; - } - - DC_UnlockDc(dc); - return Ret; -} - -BOOL -APIENTRY -NtGdiGetAndSetDCDword( - HDC hDC, - UINT u, - DWORD dwIn, - DWORD *Result - ) -{ - BOOL Ret = TRUE; - PDC dc; - PDC_ATTR pdcattr; - - DWORD SafeResult = 0; - NTSTATUS Status = STATUS_SUCCESS; - - if(!Result) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - - dc = DC_LockDc(hDC); - if(!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - pdcattr = dc->pdcattr; - - switch (u) - { - case GdiGetSetCopyCount: - SafeResult = dc->ulCopyCount; - dc->ulCopyCount = dwIn; - break; - case GdiGetSetTextAlign: - SafeResult = pdcattr->lTextAlign; - pdcattr->lTextAlign = dwIn; - // pdcattr->flTextAlign = dwIn; // Flags! - break; - case GdiGetSetRelAbs: - SafeResult = pdcattr->lRelAbs; - pdcattr->lRelAbs = dwIn; - break; - case GdiGetSetTextCharExtra: - SafeResult = pdcattr->lTextExtra; - pdcattr->lTextExtra = dwIn; - break; - case GdiGetSetSelectFont: - break; - case GdiGetSetMapperFlagsInternal: - if (dwIn & ~1) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - Ret = FALSE; - break; - } - SafeResult = pdcattr->flFontMapper; - pdcattr->flFontMapper = dwIn; - break; - case GdiGetSetMapMode: - SafeResult = IntGdiSetMapMode( dc, dwIn); - break; - case GdiGetSetArcDirection: - if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - Ret = FALSE; - break; - } - if ( pdcattr->dwLayout & LAYOUT_RTL ) // Right to Left - { - SafeResult = AD_CLOCKWISE - ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0); - if ( dwIn == AD_CLOCKWISE ) - { - dc->dclevel.flPath &= ~DCPATH_CLOCKWISE; - break; - } - dc->dclevel.flPath |= DCPATH_CLOCKWISE; - } - else // Left to Right - { - SafeResult = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE; - if ( dwIn == AD_COUNTERCLOCKWISE) - { - dc->dclevel.flPath &= ~DCPATH_CLOCKWISE; - break; - } - dc->dclevel.flPath |= DCPATH_CLOCKWISE; - } - break; - default: - SetLastWin32Error(ERROR_INVALID_PARAMETER); - Ret = FALSE; - break; - } - - if (Ret) - { - _SEH2_TRY - { - ProbeForWrite(Result, - sizeof(DWORD), - 1); - *Result = SafeResult; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END; - } - - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - DC_UnlockDc(dc); - return FALSE; - } - - DC_UnlockDc(dc); - return Ret; -} - -// ---------------------------------------------------- Private Interface - -HDC FASTCALL -DC_AllocDC(PUNICODE_STRING Driver) -{ - PDC NewDC; - PDC_ATTR pdcattr; - HDC hDC; - PWSTR Buf = NULL; - XFORM xformTemplate; - - if (Driver != NULL) - { - Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC); - if(!Buf) - { - DPRINT1("ExAllocatePoolWithTag failed\n"); - return NULL; - } - RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength); - } - - NewDC = (PDC)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC); - if(!NewDC) - { - if(Buf) - { - ExFreePoolWithTag(Buf, TAG_DC); - } - DPRINT1("GDIOBJ_AllocObjWithHandle failed\n"); - return NULL; - } - - hDC = NewDC->BaseObject.hHmgr; - - NewDC->pdcattr = &NewDC->dcattr; - DC_AllocateDcAttr(hDC); - - if (Driver != NULL) - { - RtlCopyMemory(&NewDC->rosdc.DriverName, Driver, sizeof(UNICODE_STRING)); - NewDC->rosdc.DriverName.Buffer = Buf; - } - pdcattr = NewDC->pdcattr; - - xformTemplate.eM11 = 1.0f; - xformTemplate.eM12 = 0.0f; - xformTemplate.eM21 = 0.0f; - xformTemplate.eM22 = 1.0f; - xformTemplate.eDx = 0.0f; - xformTemplate.eDy = 0.0f; - XForm2MatrixS(&NewDC->dclevel.mxWorldToDevice, &xformTemplate); - XForm2MatrixS(&NewDC->dclevel.mxDeviceToWorld, &xformTemplate); - XForm2MatrixS(&NewDC->dclevel.mxWorldToPage, &xformTemplate); - -// Setup syncing bits for the dcattr data packets. - pdcattr->flXform = DEVICE_TO_PAGE_INVALID; - - pdcattr->ulDirty_ = 0; // Server side - - pdcattr->iMapMode = MM_TEXT; - pdcattr->iGraphicsMode = GM_COMPATIBLE; - pdcattr->jFillMode = ALTERNATE; - - pdcattr->szlWindowExt.cx = 1; // Float to Int,,, WRONG! - pdcattr->szlWindowExt.cy = 1; - pdcattr->szlViewportExt.cx = 1; - pdcattr->szlViewportExt.cy = 1; - - pdcattr->crForegroundClr = 0; - pdcattr->ulForegroundClr = 0; - - pdcattr->ulBackgroundClr = 0xffffff; - pdcattr->crBackgroundClr = 0xffffff; - - pdcattr->ulPenClr = RGB( 0, 0, 0 ); - pdcattr->crPenClr = RGB( 0, 0, 0 ); - - pdcattr->ulBrushClr = RGB( 255, 255, 255 ); // Do this way too. - pdcattr->crBrushClr = RGB( 255, 255, 255 ); - -//// This fixes the default brush and pen settings. See DC_InitDC. - - /* Create the default fill brush */ - pdcattr->hbrush = NtGdiGetStockObject( WHITE_BRUSH ); - NewDC->dclevel.pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush); - EBRUSHOBJ_vInit(&NewDC->eboFill, NewDC->dclevel.pbrFill, NULL); - - /* Create the default pen / line brush */ - pdcattr->hpen = NtGdiGetStockObject( BLACK_PEN ); - NewDC->dclevel.pbrLine = PEN_ShareLockPen(pdcattr->hpen); - EBRUSHOBJ_vInit(&NewDC->eboLine, NewDC->dclevel.pbrFill, NULL); - - - pdcattr->hlfntNew = NtGdiGetStockObject(SYSTEM_FONT); - TextIntRealizeFont(pdcattr->hlfntNew,NULL); - - NewDC->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE); - NewDC->dclevel.laPath.eMiterLimit = 10.0; - - DC_UnlockDc(NewDC); - - return hDC; -} - -HDC FASTCALL -DC_FindOpenDC(PUNICODE_STRING Driver) -{ - return NULL; -} - -/*! - * Initialize some common fields in the Device Context structure. -*/ -VOID FASTCALL -DC_InitDC(HDC DCHandle) -{ -// NtGdiRealizeDefaultPalette(DCHandle); - -//// Removed for now.. See above brush and pen. -// NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH )); -// NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN )); -//// - //NtGdiSelectFont(DCHandle, hFont); - /* + * @implemented + */ +DHPDEV +APIENTRY +NtGdiGetDhpdev( + IN HDEV hdev) +{ + PPDEVOBJ ppdev, pGdiDevice = (PPDEVOBJ) hdev; + if (!pGdiDevice) return NULL; + if ( pGdiDevice < (PPDEVOBJ)MmSystemRangeStart) return NULL; + ppdev = pPrimarySurface; + IntGdiAcquireSemaphore(hsemDriverMgmt); + do { - int res; - res = CLIPPING_UpdateGCRegion(DCToInit); - ASSERT ( res != ERROR ); - } -*/ + if (pGdiDevice == ppdev) break; + else + ppdev = ppdev->ppdevNext; + } while (ppdev != NULL); + IntGdiReleaseSemaphore(hsemDriverMgmt); + if (!ppdev) return NULL; + return pGdiDevice->hPDev; } -VOID -FASTCALL -DC_AllocateDcAttr(HDC hDC) +static NTSTATUS FASTCALL +GetVideoRegistryKey( + OUT PUNICODE_STRING RegistryPath, + IN PCUNICODE_STRING DeviceName) /* ex: "\Device\Video0" */ { - PVOID NewMem = NULL; - PDC pDC; - HANDLE Pid = NtCurrentProcess(); - ULONG MemSize = sizeof(DC_ATTR); //PAGE_SIZE it will allocate that size + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; - NTSTATUS Status = ZwAllocateVirtualMemory(Pid, - &NewMem, - 0, - &MemSize, - MEM_COMMIT|MEM_RESERVE, - PAGE_READWRITE); - KeEnterCriticalRegion(); - { - INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hDC); - PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index]; - // FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData - if (NT_SUCCESS(Status)) + RtlInitUnicodeString(RegistryPath, NULL); + RtlZeroMemory(QueryTable, sizeof(QueryTable)); + QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].Name = DeviceName->Buffer; + QueryTable[0].EntryContext = RegistryPath; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP, + L"VIDEO", + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) { - RtlZeroMemory(NewMem, MemSize); - Entry->UserData = NewMem; - DPRINT("DC_ATTR allocated! 0x%x\n",NewMem); + DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName, Status); + return STATUS_NO_SUCH_DEVICE; } + + DPRINT("RegistryPath %wZ\n", RegistryPath); + return STATUS_SUCCESS; +} + + +static NTSTATUS FASTCALL +GetVideoDeviceName( + OUT PUNICODE_STRING VideoDeviceName, + IN PCUNICODE_STRING DisplayDevice) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */ +{ + UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\??\\"); + UNICODE_STRING ObjectName; + UNICODE_STRING KernelModeName = { 0, }; + OBJECT_ATTRIBUTES ObjectAttributes; + USHORT LastSlash; + ULONG Length; + HANDLE LinkHandle = NULL; + NTSTATUS Status; + + RtlInitUnicodeString(VideoDeviceName, NULL); + + /* Get device name (DisplayDevice is "\.\xxx") */ + for (LastSlash = DisplayDevice->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--) + { + if (DisplayDevice->Buffer[LastSlash - 1] == L'\\') + break; + } + + if (LastSlash == 0) + { + DPRINT1("Invalid device name '%wZ'\n", DisplayDevice); + Status = STATUS_OBJECT_NAME_INVALID; + goto cleanup; + } + ObjectName = *DisplayDevice; + ObjectName.Length -= LastSlash * sizeof(WCHAR); + ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR); + ObjectName.Buffer += LastSlash; + + /* Create "\??\xxx" (ex: "\??\DISPLAY1") */ + KernelModeName.MaximumLength = Prefix.Length + ObjectName.Length + sizeof(UNICODE_NULL); + KernelModeName.Buffer = ExAllocatePoolWithTag(PagedPool, + KernelModeName.MaximumLength, + TAG_DC); + if (!KernelModeName.Buffer) + { + Status = STATUS_NO_MEMORY; + goto cleanup; + } + RtlCopyUnicodeString(&KernelModeName, &Prefix); + Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName); + if (!NT_SUCCESS(Status)) + goto cleanup; + + /* Open \??\xxx (ex: "\??\DISPLAY1") */ + InitializeObjectAttributes(&ObjectAttributes, + &KernelModeName, + OBJ_KERNEL_HANDLE, + NULL, + NULL); + Status = ZwOpenSymbolicLinkObject(&LinkHandle, + GENERIC_READ, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status); + Status = STATUS_NO_SUCH_DEVICE; + goto cleanup; + } + + Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, &Length); + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) + { + DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status); + Status = STATUS_NO_SUCH_DEVICE; + goto cleanup; + } + VideoDeviceName->MaximumLength = Length; + VideoDeviceName->Buffer = ExAllocatePoolWithTag(PagedPool, + VideoDeviceName->MaximumLength + sizeof(UNICODE_NULL), + TAG_DC); + if (!VideoDeviceName->Buffer) + { + Status = STATUS_NO_MEMORY; + goto cleanup; + } + Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, NULL); + VideoDeviceName->Buffer[VideoDeviceName->MaximumLength / sizeof(WCHAR) - 1] = UNICODE_NULL; + if (!NT_SUCCESS(Status)) + { + DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status); + Status = STATUS_NO_SUCH_DEVICE; + goto cleanup; + } + Status = STATUS_SUCCESS; + +cleanup: + if (!NT_SUCCESS(Status) && VideoDeviceName->Buffer) + ExFreePoolWithTag(VideoDeviceName->Buffer, TAG_DC); + if (KernelModeName.Buffer) + ExFreePoolWithTag(KernelModeName.Buffer, TAG_DC); + if (LinkHandle) + ZwClose(LinkHandle); + return Status; +} + +LONG +FASTCALL +IntChangeDisplaySettings( + IN PUNICODE_STRING pDeviceName OPTIONAL, + IN LPDEVMODEW DevMode, + IN DWORD dwflags, + IN PVOID lParam OPTIONAL) +{ + BOOLEAN Global = FALSE; + BOOLEAN NoReset = FALSE; + BOOLEAN Reset = FALSE; + BOOLEAN SetPrimary = FALSE; + LONG Ret=0; + NTSTATUS Status ; + + DPRINT1("display flags : %x\n",dwflags); + + if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY) + { + /* Check global, reset and noreset flags */ + if ((dwflags & CDS_GLOBAL) == CDS_GLOBAL) + Global = TRUE; + if ((dwflags & CDS_NORESET) == CDS_NORESET) + NoReset = TRUE; + dwflags &= ~(CDS_GLOBAL | CDS_NORESET); + } + if ((dwflags & CDS_RESET) == CDS_RESET) + Reset = TRUE; + if ((dwflags & CDS_SET_PRIMARY) == CDS_SET_PRIMARY) + SetPrimary = TRUE; + dwflags &= ~(CDS_RESET | CDS_SET_PRIMARY); + + if (Reset && NoReset) + return DISP_CHANGE_BADFLAGS; + + if (dwflags == 0) + { + /* Dynamically change graphics mode */ + DPRINT1("flag 0 UNIMPLEMENTED\n"); + return DISP_CHANGE_FAILED; + } + + if ((dwflags & CDS_TEST) == CDS_TEST) + { + /* Test reslution */ + dwflags &= ~CDS_TEST; + DPRINT1("flag CDS_TEST UNIMPLEMENTED\n"); + Ret = DISP_CHANGE_FAILED; + } + + if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN) + { + DEVMODEW lpDevMode; + /* Full Screen */ + dwflags &= ~CDS_FULLSCREEN; + DPRINT1("flag CDS_FULLSCREEN partially implemented\n"); + Ret = DISP_CHANGE_FAILED; + + RtlZeroMemory(&lpDevMode, sizeof(DEVMODEW)); + lpDevMode.dmSize = sizeof(DEVMODEW); + + if (!IntEnumDisplaySettings(pDeviceName, ENUM_CURRENT_SETTINGS, &lpDevMode, 0)) + return DISP_CHANGE_FAILED; + + DPRINT1("Req Mode : %d x %d x %d\n", DevMode->dmPelsWidth,DevMode->dmPelsHeight,DevMode->dmBitsPerPel); + DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode.dmPelsWidth,lpDevMode.dmPelsHeight, lpDevMode.dmBitsPerPel); + + + if ((lpDevMode.dmBitsPerPel == DevMode->dmBitsPerPel) && + (lpDevMode.dmPelsWidth == DevMode->dmPelsWidth) && + (lpDevMode.dmPelsHeight == DevMode->dmPelsHeight)) + Ret = DISP_CHANGE_SUCCESSFUL; + } + + if ((dwflags & CDS_VIDEOPARAMETERS) == CDS_VIDEOPARAMETERS) + { + dwflags &= ~CDS_VIDEOPARAMETERS; + if (lParam == NULL) + Ret=DISP_CHANGE_BADPARAM; else { - DPRINT("DC_ATTR not allocated!\n"); + DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENTED\n"); + Ret = DISP_CHANGE_FAILED; } - } - KeLeaveCriticalRegion(); - pDC = DC_LockDc(hDC); - ASSERT(pDC->pdcattr == &pDC->dcattr); - if(NewMem) - { - pDC->pdcattr = NewMem; // Store pointer - } - DC_UnlockDc(pDC); -} -VOID -FASTCALL -DC_FreeDcAttr(HDC DCToFree ) -{ - HANDLE Pid = NtCurrentProcess(); - PDC pDC = DC_LockDc(DCToFree); - if (pDC->pdcattr == &pDC->dcattr) return; // Internal DC object! - pDC->pdcattr = &pDC->dcattr; - DC_UnlockDc(pDC); + } - KeEnterCriticalRegion(); + if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY) { - INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)DCToFree); - PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index]; - if(Entry->UserData) + + UNICODE_STRING DeviceName; + UNICODE_STRING RegistryKey; + UNICODE_STRING InDeviceName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE DevInstRegKey; + ULONG NewValue; + + DPRINT1("set CDS_UPDATEREGISTRY\n"); + + dwflags &= ~CDS_UPDATEREGISTRY; + + /* Check if pDeviceName is NULL, we need to retrieve it */ + if (pDeviceName == NULL) { - ULONG MemSize = sizeof(DC_ATTR); //PAGE_SIZE; - NTSTATUS Status = ZwFreeVirtualMemory(Pid, - &Entry->UserData, - &MemSize, - MEM_RELEASE); - if (NT_SUCCESS(Status)) + WCHAR szBuffer[MAX_DRIVER_NAME]; + PDC DC; + PWINDOW_OBJECT Wnd=NULL; + HWND hWnd; + HDC hDC; + + hWnd = IntGetDesktopWindow(); + if (!(Wnd = UserGetWindowObject(hWnd))) { - DPRINT("DC_FreeDC DC_ATTR 0x%x\n", Entry->UserData); - Entry->UserData = NULL; + return FALSE; } - } - } - KeLeaveCriticalRegion(); -} -VOID FASTCALL -DC_FreeDC(HDC DCToFree) -{ - DC_FreeDcAttr(DCToFree); - if(!IsObjectDead( DCToFree )) - { - if (!GDIOBJ_FreeObjByHandle(DCToFree, GDI_OBJECT_TYPE_DC)) + hDC = UserGetWindowDC(Wnd); + + DC = DC_LockDc(hDC); + if (NULL == DC) + { + return FALSE; + } + swprintf (szBuffer, L"\\\\.\\DISPLAY%lu", DC->ppdev->DisplayNumber); + DC_UnlockDc(DC); + + RtlInitUnicodeString(&InDeviceName, szBuffer); + pDeviceName = &InDeviceName; + } + + Status = GetVideoDeviceName(&DeviceName, pDeviceName); + if (!NT_SUCCESS(Status)) { - DPRINT1("DC_FreeDC failed\n"); + DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName, Status); + return DISP_CHANGE_FAILED; } - } - else - { - DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n",DCToFree); - } -} - -BOOL INTERNAL_CALL -DC_Cleanup(PVOID ObjectBody) -{ - PDC pDC = (PDC)ObjectBody; - if (pDC->rosdc.DriverName.Buffer) - ExFreePoolWithTag(pDC->rosdc.DriverName.Buffer, TAG_DC); - return TRUE; -} - -HDC FASTCALL -DC_GetNextDC (PDC pDC) -{ - return pDC->hdcNext; -} - -VOID FASTCALL -DC_SetNextDC (PDC pDC, HDC hNextDC) -{ - pDC->hdcNext = hNextDC; -} - -VOID FASTCALL -DC_UpdateXforms(PDC dc) -{ - XFORM xformWnd2Vport; - FLOAT scaleX, scaleY; - PDC_ATTR pdcattr = dc->pdcattr; - XFORM xformWorld2Vport, xformWorld2Wnd, xformVport2World; - - /* Construct a transformation to do the window-to-viewport conversion */ - scaleX = (pdcattr->szlWindowExt.cx ? (FLOAT)pdcattr->szlViewportExt.cx / (FLOAT)pdcattr->szlWindowExt.cx : 0.0f); - scaleY = (pdcattr->szlWindowExt.cy ? (FLOAT)pdcattr->szlViewportExt.cy / (FLOAT)pdcattr->szlWindowExt.cy : 0.0f); - xformWnd2Vport.eM11 = scaleX; - xformWnd2Vport.eM12 = 0.0; - xformWnd2Vport.eM21 = 0.0; - xformWnd2Vport.eM22 = scaleY; - xformWnd2Vport.eDx = (FLOAT)pdcattr->ptlViewportOrg.x - scaleX * (FLOAT)pdcattr->ptlWindowOrg.x; - xformWnd2Vport.eDy = (FLOAT)pdcattr->ptlViewportOrg.y - scaleY * (FLOAT)pdcattr->ptlWindowOrg.y; - - /* Combine with the world transformation */ - MatrixS2XForm(&xformWorld2Vport, &dc->dclevel.mxWorldToDevice); - MatrixS2XForm(&xformWorld2Wnd, &dc->dclevel.mxWorldToPage); - IntGdiCombineTransform(&xformWorld2Vport, &xformWorld2Wnd, &xformWnd2Vport); - - /* Create inverse of world-to-viewport transformation */ - MatrixS2XForm(&xformVport2World, &dc->dclevel.mxDeviceToWorld); - if (DC_InvertXform(&xformWorld2Vport, &xformVport2World)) - { - pdcattr->flXform &= ~DEVICE_TO_WORLD_INVALID; - } - else - { - pdcattr->flXform |= DEVICE_TO_WORLD_INVALID; - } - - XForm2MatrixS(&dc->dclevel.mxWorldToDevice, &xformWorld2Vport); - -} - -BOOL FASTCALL -DC_InvertXform(const XFORM *xformSrc, - XFORM *xformDest) -{ - FLOAT determinant; - - determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21; - if (determinant > -1e-12 && determinant < 1e-12) - { - return FALSE; - } - - xformDest->eM11 = xformSrc->eM22 / determinant; - xformDest->eM12 = -xformSrc->eM12 / determinant; - xformDest->eM21 = -xformSrc->eM21 / determinant; - xformDest->eM22 = xformSrc->eM11 / determinant; - xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21; - xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22; - - return TRUE; -} - -BOOL -FASTCALL -DC_SetOwnership(HDC hDC, PEPROCESS Owner) -{ - PDC pDC; - - if(!GDIOBJ_SetOwnership(hDC, Owner)) return FALSE; - pDC = DC_LockDc(hDC); - if (pDC) + Status = GetVideoRegistryKey(&RegistryKey, &DeviceName); + if (!NT_SUCCESS(Status)) { - if (pDC->rosdc.hClipRgn) - { - if(!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE; - } - if (pDC->rosdc.hVisRgn) - { - if(!GDIOBJ_SetOwnership(pDC->rosdc.hVisRgn, Owner)) return FALSE; - } - if (pDC->rosdc.hGCClipRgn) - { - if(!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) return FALSE; - } - if (pDC->dclevel.hPath) - { - if(!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) return FALSE; - } - DC_UnlockDc(pDC); + DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName, Status); + ExFreePoolWithTag(DeviceName.Buffer, TAG_DC); + return DISP_CHANGE_FAILED; } - return TRUE; + ExFreePoolWithTag(DeviceName.Buffer, TAG_DC); + + InitializeObjectAttributes(&ObjectAttributes, &RegistryKey, + OBJ_CASE_INSENSITIVE, NULL, NULL); + Status = ZwOpenKey(&DevInstRegKey, KEY_SET_VALUE, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey, Status); + ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY); + return DISP_CHANGE_FAILED; + } + ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY); + + /* Update needed fields */ + if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL) + { + RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.BitsPerPel"); + NewValue = DevMode->dmBitsPerPel; + Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue)); + } + + if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSWIDTH) + { + RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.XResolution"); + NewValue = DevMode->dmPelsWidth; + Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue)); + } + + if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSHEIGHT) + { + RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.YResolution"); + NewValue = DevMode->dmPelsHeight; + Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue)); + } + + ZwClose(DevInstRegKey); + if (NT_SUCCESS(Status)) + Ret = DISP_CHANGE_RESTART; + else + /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */ + Ret = DISP_CHANGE_NOTUPDATED; + } + + if (dwflags != 0) + Ret = DISP_CHANGE_BADFLAGS; + + return Ret; } -// -// Support multi display/device locks. -// -VOID -FASTCALL -DC_LockDisplay(HDC hDC) -{ - PERESOURCE Resource; - PDC dc = DC_LockDc(hDC); - if (!dc) return; - Resource = dc->ppdev->hsemDevLock; - DC_UnlockDc(dc); - if (!Resource) return; - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite( Resource , TRUE); -} - -VOID -FASTCALL -DC_UnlockDisplay(HDC hDC) -{ - PERESOURCE Resource; - PDC dc = DC_LockDc(hDC); - if (!dc) return; - Resource = dc->ppdev->hsemDevLock; - DC_UnlockDc(dc); - if (!Resource) return; - ExReleaseResourceLite( Resource ); - KeLeaveCriticalRegion(); -} - -BOOL FASTCALL -IntIsPrimarySurface(SURFOBJ *SurfObj) -{ - if (PrimarySurface.pSurface == NULL) - { - return FALSE; - } - return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF? -} - -// -// Enumerate HDev -// -PPDEVOBJ FASTCALL -IntEnumHDev(VOID) -{ -// I guess we will soon have more than one primary surface. -// This will do for now. - return &PrimarySurface; -} - - -VOID FASTCALL -IntGdiReferencePdev(PPDEVOBJ ppdev) -{ - if(!hsemDriverMgmt) hsemDriverMgmt = EngCreateSemaphore(); // Hax, should be in dllmain.c - IntGdiAcquireSemaphore(hsemDriverMgmt); - ppdev->cPdevRefs++; - IntGdiReleaseSemaphore(hsemDriverMgmt); -} - -VOID FASTCALL -IntGdiUnreferencePdev(PPDEVOBJ ppdev, DWORD CleanUpType) -{ - IntGdiAcquireSemaphore(hsemDriverMgmt); - ppdev->cPdevRefs--; - if (!ppdev->cPdevRefs) - { - // Handle the destruction of ppdev or PDEVOBJ or PDEVOBJ or PDEV etc. - } - IntGdiReleaseSemaphore(hsemDriverMgmt); -} #define SIZEOF_DEVMODEW_300 188 @@ -3092,538 +1679,15 @@ IntEnumDisplaySettings( return STATUS_SUCCESS; } -static NTSTATUS FASTCALL -GetVideoDeviceName( - OUT PUNICODE_STRING VideoDeviceName, - IN PCUNICODE_STRING DisplayDevice) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */ -{ - UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\??\\"); - UNICODE_STRING ObjectName; - UNICODE_STRING KernelModeName = { 0, }; - OBJECT_ATTRIBUTES ObjectAttributes; - USHORT LastSlash; - ULONG Length; - HANDLE LinkHandle = NULL; - NTSTATUS Status; - - RtlInitUnicodeString(VideoDeviceName, NULL); - - /* Get device name (DisplayDevice is "\.\xxx") */ - for (LastSlash = DisplayDevice->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--) - { - if (DisplayDevice->Buffer[LastSlash - 1] == L'\\') - break; - } - - if (LastSlash == 0) - { - DPRINT1("Invalid device name '%wZ'\n", DisplayDevice); - Status = STATUS_OBJECT_NAME_INVALID; - goto cleanup; - } - ObjectName = *DisplayDevice; - ObjectName.Length -= LastSlash * sizeof(WCHAR); - ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR); - ObjectName.Buffer += LastSlash; - - /* Create "\??\xxx" (ex: "\??\DISPLAY1") */ - KernelModeName.MaximumLength = Prefix.Length + ObjectName.Length + sizeof(UNICODE_NULL); - KernelModeName.Buffer = ExAllocatePoolWithTag(PagedPool, - KernelModeName.MaximumLength, - TAG_DC); - if (!KernelModeName.Buffer) - { - Status = STATUS_NO_MEMORY; - goto cleanup; - } - RtlCopyUnicodeString(&KernelModeName, &Prefix); - Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName); - if (!NT_SUCCESS(Status)) - goto cleanup; - - /* Open \??\xxx (ex: "\??\DISPLAY1") */ - InitializeObjectAttributes(&ObjectAttributes, - &KernelModeName, - OBJ_KERNEL_HANDLE, - NULL, - NULL); - Status = ZwOpenSymbolicLinkObject(&LinkHandle, - GENERIC_READ, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status); - Status = STATUS_NO_SUCH_DEVICE; - goto cleanup; - } - - Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, &Length); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status); - Status = STATUS_NO_SUCH_DEVICE; - goto cleanup; - } - VideoDeviceName->MaximumLength = Length; - VideoDeviceName->Buffer = ExAllocatePoolWithTag(PagedPool, - VideoDeviceName->MaximumLength + sizeof(UNICODE_NULL), - TAG_DC); - if (!VideoDeviceName->Buffer) - { - Status = STATUS_NO_MEMORY; - goto cleanup; - } - Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, NULL); - VideoDeviceName->Buffer[VideoDeviceName->MaximumLength / sizeof(WCHAR) - 1] = UNICODE_NULL; - if (!NT_SUCCESS(Status)) - { - DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status); - Status = STATUS_NO_SUCH_DEVICE; - goto cleanup; - } - Status = STATUS_SUCCESS; - -cleanup: - if (!NT_SUCCESS(Status) && VideoDeviceName->Buffer) - ExFreePoolWithTag(VideoDeviceName->Buffer, TAG_DC); - if (KernelModeName.Buffer) - ExFreePoolWithTag(KernelModeName.Buffer, TAG_DC); - if (LinkHandle) - ZwClose(LinkHandle); - return Status; -} - -static NTSTATUS FASTCALL -GetVideoRegistryKey( - OUT PUNICODE_STRING RegistryPath, - IN PCUNICODE_STRING DeviceName) /* ex: "\Device\Video0" */ -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - NTSTATUS Status; - - RtlInitUnicodeString(RegistryPath, NULL); - RtlZeroMemory(QueryTable, sizeof(QueryTable)); - QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT; - QueryTable[0].Name = DeviceName->Buffer; - QueryTable[0].EntryContext = RegistryPath; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP, - L"VIDEO", - QueryTable, - NULL, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName, Status); - return STATUS_NO_SUCH_DEVICE; - } - - DPRINT("RegistryPath %wZ\n", RegistryPath); - return STATUS_SUCCESS; -} - -LONG -FASTCALL -IntChangeDisplaySettings( - IN PUNICODE_STRING pDeviceName OPTIONAL, - IN LPDEVMODEW DevMode, - IN DWORD dwflags, - IN PVOID lParam OPTIONAL) -{ - BOOLEAN Global = FALSE; - BOOLEAN NoReset = FALSE; - BOOLEAN Reset = FALSE; - BOOLEAN SetPrimary = FALSE; - LONG Ret=0; - NTSTATUS Status ; - - DPRINT1("display flags : %x\n",dwflags); - - if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY) - { - /* Check global, reset and noreset flags */ - if ((dwflags & CDS_GLOBAL) == CDS_GLOBAL) - Global = TRUE; - if ((dwflags & CDS_NORESET) == CDS_NORESET) - NoReset = TRUE; - dwflags &= ~(CDS_GLOBAL | CDS_NORESET); - } - if ((dwflags & CDS_RESET) == CDS_RESET) - Reset = TRUE; - if ((dwflags & CDS_SET_PRIMARY) == CDS_SET_PRIMARY) - SetPrimary = TRUE; - dwflags &= ~(CDS_RESET | CDS_SET_PRIMARY); - - if (Reset && NoReset) - return DISP_CHANGE_BADFLAGS; - - if (dwflags == 0) - { - /* Dynamically change graphics mode */ - DPRINT1("flag 0 UNIMPLEMENTED\n"); - return DISP_CHANGE_FAILED; - } - - if ((dwflags & CDS_TEST) == CDS_TEST) - { - /* Test reslution */ - dwflags &= ~CDS_TEST; - DPRINT1("flag CDS_TEST UNIMPLEMENTED\n"); - Ret = DISP_CHANGE_FAILED; - } - - if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN) - { - DEVMODEW lpDevMode; - /* Full Screen */ - dwflags &= ~CDS_FULLSCREEN; - DPRINT1("flag CDS_FULLSCREEN partially implemented\n"); - Ret = DISP_CHANGE_FAILED; - - RtlZeroMemory(&lpDevMode, sizeof(DEVMODEW)); - lpDevMode.dmSize = sizeof(DEVMODEW); - - if (!IntEnumDisplaySettings(pDeviceName, ENUM_CURRENT_SETTINGS, &lpDevMode, 0)) - return DISP_CHANGE_FAILED; - - DPRINT1("Req Mode : %d x %d x %d\n", DevMode->dmPelsWidth,DevMode->dmPelsHeight,DevMode->dmBitsPerPel); - DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode.dmPelsWidth,lpDevMode.dmPelsHeight, lpDevMode.dmBitsPerPel); - - - if ((lpDevMode.dmBitsPerPel == DevMode->dmBitsPerPel) && - (lpDevMode.dmPelsWidth == DevMode->dmPelsWidth) && - (lpDevMode.dmPelsHeight == DevMode->dmPelsHeight)) - Ret = DISP_CHANGE_SUCCESSFUL; - } - - if ((dwflags & CDS_VIDEOPARAMETERS) == CDS_VIDEOPARAMETERS) - { - dwflags &= ~CDS_VIDEOPARAMETERS; - if (lParam == NULL) - Ret=DISP_CHANGE_BADPARAM; - else - { - DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENTED\n"); - Ret = DISP_CHANGE_FAILED; - } - - } - - if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY) - { - - UNICODE_STRING DeviceName; - UNICODE_STRING RegistryKey; - UNICODE_STRING InDeviceName; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE DevInstRegKey; - ULONG NewValue; - - DPRINT1("set CDS_UPDATEREGISTRY\n"); - - dwflags &= ~CDS_UPDATEREGISTRY; - - /* Check if pDeviceName is NULL, we need to retrieve it */ - if (pDeviceName == NULL) - { - WCHAR szBuffer[MAX_DRIVER_NAME]; - PDC DC; - PWINDOW_OBJECT Wnd=NULL; - HWND hWnd; - HDC hDC; - - hWnd = IntGetDesktopWindow(); - if (!(Wnd = UserGetWindowObject(hWnd))) - { - return FALSE; - } - - hDC = UserGetWindowDC(Wnd); - - DC = DC_LockDc(hDC); - if (NULL == DC) - { - return FALSE; - } - swprintf (szBuffer, L"\\\\.\\DISPLAY%lu", DC->ppdev->DisplayNumber); - DC_UnlockDc(DC); - - RtlInitUnicodeString(&InDeviceName, szBuffer); - pDeviceName = &InDeviceName; - } - - Status = GetVideoDeviceName(&DeviceName, pDeviceName); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName, Status); - return DISP_CHANGE_FAILED; - } - Status = GetVideoRegistryKey(&RegistryKey, &DeviceName); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName, Status); - ExFreePoolWithTag(DeviceName.Buffer, TAG_DC); - return DISP_CHANGE_FAILED; - } - ExFreePoolWithTag(DeviceName.Buffer, TAG_DC); - - InitializeObjectAttributes(&ObjectAttributes, &RegistryKey, - OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = ZwOpenKey(&DevInstRegKey, KEY_SET_VALUE, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey, Status); - ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY); - return DISP_CHANGE_FAILED; - } - ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY); - - /* Update needed fields */ - if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL) - { - RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.BitsPerPel"); - NewValue = DevMode->dmBitsPerPel; - Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue)); - } - - if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSWIDTH) - { - RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.XResolution"); - NewValue = DevMode->dmPelsWidth; - Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue)); - } - - if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSHEIGHT) - { - RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.YResolution"); - NewValue = DevMode->dmPelsHeight; - Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue)); - } - - ZwClose(DevInstRegKey); - if (NT_SUCCESS(Status)) - Ret = DISP_CHANGE_RESTART; - else - /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */ - Ret = DISP_CHANGE_NOTUPDATED; - } - - if (dwflags != 0) - Ret = DISP_CHANGE_BADFLAGS; - - return Ret; -} - -DWORD +INT APIENTRY -NtGdiGetBoundsRect( +NtGdiDrawEscape( IN HDC hdc, - OUT LPRECT prc, - IN DWORD f) + IN INT iEsc, + IN INT cjIn, + IN OPTIONAL LPSTR pjIn) { - DPRINT1("stub\n"); - return DCB_RESET; /* bounding rectangle always empty */ + UNIMPLEMENTED; + return 0; } -DWORD -APIENTRY -NtGdiSetBoundsRect( - IN HDC hdc, - IN LPRECT prc, - IN DWORD f) -{ - DPRINT1("stub\n"); - return DCB_DISABLE; /* bounding rectangle always empty */ -} - -/* - * @implemented - */ -DHPDEV -APIENTRY -NtGdiGetDhpdev( - IN HDEV hdev) -{ - PPDEVOBJ ppdev, pGdiDevice = (PPDEVOBJ) hdev; - if (!pGdiDevice) return NULL; - if ( pGdiDevice < (PPDEVOBJ)MmSystemRangeStart) return NULL; - ppdev = pPrimarySurface; - IntGdiAcquireSemaphore(hsemDriverMgmt); - do - { - if (pGdiDevice == ppdev) break; - else - ppdev = ppdev->ppdevNext; - } while (ppdev != NULL); - IntGdiReleaseSemaphore(hsemDriverMgmt); - if (!ppdev) return NULL; - return pGdiDevice->hPDev; -} - - /* - * @unimplemented - */ -BOOL -APIENTRY -NtGdiMakeInfoDC( - IN HDC hdc, - IN BOOL bSet) -{ - UNIMPLEMENTED; - return FALSE; -} - -VOID -FASTCALL -DC_vUpdateFillBrush(PDC pdc) -{ - PDC_ATTR pdcattr = pdc->pdcattr; - PBRUSH pbrFill; - XLATEOBJ *pxlo; - ULONG iSolidColor; - - /* Check if update of eboFill is needed */ - if (pdcattr->ulDirty_ & DIRTY_FILL) - { - /* ROS HACK, should use surf xlate */ - pxlo = pdc->rosdc.XlatePen; - - /* Check if the brush handle has changed */ - if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr) - { - /* Try to lock the new brush */ - pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush); - if (pbrFill) - { - /* Unlock old brush, set new brush */ - BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill); - pdc->dclevel.pbrFill = pbrFill; - - /* Update eboFill, realizing it, if needed */ - EBRUSHOBJ_vUpdate(&pdc->eboFill, pbrFill, pxlo); - } - else - { - /* Invalid brush handle, restore old one */ - pdcattr->hbrush = pdc->dclevel.pbrFill->BaseObject.hHmgr; - } - } - - /* Check for DC brush */ - if (pdcattr->hbrush == StockObjects[DC_BRUSH]) - { - /* Translate the color to the target format */ - iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crPenClr); - - /* Update the eboFill's solid color */ - EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, iSolidColor); - } - - /* Clear flag */ - pdcattr->ulDirty_ &= ~DIRTY_FILL; - } -} - -VOID -FASTCALL -DC_vUpdateLineBrush(PDC pdc) -{ - PDC_ATTR pdcattr = pdc->pdcattr; - PBRUSH pbrLine; - XLATEOBJ *pxlo; - ULONG iSolidColor; - - /* Check if update of eboLine is needed */ - if (pdcattr->ulDirty_ & DIRTY_LINE) - { - /* ROS HACK, should use surf xlate */ - pxlo = pdc->rosdc.XlatePen; - - /* Check if the pen handle has changed */ - if (pdcattr->hpen != pdc->dclevel.pbrLine->BaseObject.hHmgr) - { - /* Try to lock the new pen */ - pbrLine = BRUSH_ShareLockBrush(pdcattr->hpen); - if (pbrLine) - { - /* Unlock old brush, set new brush */ - BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine); - pdc->dclevel.pbrLine = pbrLine; - - /* Update eboLine, realizing it, if needed */ - EBRUSHOBJ_vUpdate(&pdc->eboLine, pbrLine, pxlo); - } - else - { - /* Invalid pen handle, restore old one */ - pdcattr->hpen = pdc->dclevel.pbrLine->BaseObject.hHmgr; - } - } - - /* Check for DC pen */ - if (pdcattr->hpen == StockObjects[DC_PEN]) - { - /* Translate the color to the target format */ - iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crPenClr); - - /* Update the eboLine's solid color */ - EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboLine, iSolidColor); - } - - /* Clear flag */ - pdcattr->ulDirty_ &= ~DIRTY_LINE; - } -} - -VOID -FASTCALL -DC_vUpdateTextBrush(PDC pdc) -{ - PDC_ATTR pdcattr = pdc->pdcattr; - XLATEOBJ *pxlo; - ULONG iSolidColor; - - /* Check if update of eboText is needed */ - if (pdcattr->ulDirty_ & DIRTY_TEXT) - { - /* ROS HACK, should use surf xlate */ - pxlo = pdc->rosdc.XlatePen; - - /* Translate the color to the target format */ - iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crForegroundClr); - - /* Update the eboText's solid color */ - EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, iSolidColor); - - /* Clear flag */ - pdcattr->ulDirty_ &= ~DIRTY_TEXT; - } -} - -VOID -FASTCALL -DC_vUpdateBackgroundBrush(PDC pdc) -{ - PDC_ATTR pdcattr = pdc->pdcattr; - XLATEOBJ *pxlo; - ULONG iSolidColor; - - /* Check if update of eboBackground is needed */ - if (pdcattr->ulDirty_ & DIRTY_BACKGROUND) - { - /* ROS HACK, should use surf xlate */ - pxlo = pdc->rosdc.XlatePen; - - /* Translate the color to the target format */ - iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crBackgroundClr); - - /* Update the eboBackground's solid color */ - EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, iSolidColor); - - /* Clear flag */ - pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND; - } -} - - -/* EOF */ diff --git a/reactos/subsystems/win32/win32k/win32k.rbuild b/reactos/subsystems/win32/win32k/win32k.rbuild index 5f1d2085478..2ce23d3f3ab 100644 --- a/reactos/subsystems/win32/win32k/win32k.rbuild +++ b/reactos/subsystems/win32/win32k/win32k.rbuild @@ -160,8 +160,12 @@ cliprgn.c color.c coord.c - dc.c + dcattr.c + dclife.c + dcobjs.c + dcstate.c dcutil.c + device.c dibobj.c drawing.c fillshap.c