[WIN32K]
[reactos.git] / subsystems / win32 / win32k / objects / dclife.c
index ba5b7f1..45851f3 100644 (file)
@@ -79,7 +79,7 @@ DC_AllocDcWithHandle()
 {
     PDC pdc;
     pdc = (PDC)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_DC_TYPE);
-    
+
     pdc->pdcattr = &pdc->dcattr;
 
     return pdc;
@@ -105,9 +105,7 @@ DC_InitHack(PDC pdc)
     ASSERT(hVisRgn);
     GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
     GreDeleteObject(hVisRgn);
-    ASSERT(pdc->rosdc.hVisRgn);
-    pdc->rosdc.bitsPerPixel = pdc->ppdev->gdiinfo.cBitsPixel *
-                              pdc->ppdev->gdiinfo.cPlanes;
+    ASSERT(pdc->prgnVis);
 }
 
 VOID
@@ -117,6 +115,11 @@ DC_vInitDc(
     DCTYPE dctype,
     PPDEVOBJ ppdev)
 {
+    if (dctype == DCTYPE_DIRECT)
+    {
+        /* Lock ppdev exclusively */
+        EngAcquireSemaphore(ppdev->hsemDevLock);
+    }
 
     /* Setup some basic fields */
     pdc->dctype = dctype;
@@ -156,9 +159,55 @@ DC_vInitDc(
 
     if (dctype == DCTYPE_DIRECT)
     {
+        PDC pdcTmp;
         /* Direct DCs get the surface from the PDEV */
         pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
 
+        /* Maintain a list of DC attached to this device */
+        /* We must sort them so when locking them one after the other we don't risk deadlocks */
+        /* The greatest the first, as in GDIOBJ_LockMultiplObjs */
+        if((ULONG_PTR)pdc->dclevel.pSurface->hDC < (ULONG_PTR)pdc->BaseObject.hHmgr)
+        {
+            /* Insert it at the head of the list */
+            pdc->hdcNext = pdc->dclevel.pSurface->hDC ;
+            pdc->dclevel.pSurface->hDC = pdc->BaseObject.hHmgr ;
+            pdcTmp = DC_LockDc(pdc->hdcNext);
+            if(pdcTmp)
+            {
+                pdcTmp->hdcPrev = pdc->BaseObject.hHmgr ;
+                DC_UnlockDc(pdcTmp);
+            }
+        }
+        else
+        {
+            HDC hdcTmp = pdc->dclevel.pSurface->hDC;
+            HDC hdcNext = NULL ;
+            HDC hdcPrev = NULL ;
+            /* Find its place */
+            while((ULONG_PTR)hdcTmp > (ULONG_PTR)pdc->BaseObject.hHmgr)
+            {
+                pdcTmp = DC_LockDc(hdcTmp);
+                hdcNext = hdcTmp ;
+                hdcPrev = pdcTmp->hdcPrev ;
+                hdcTmp = pdcTmp->hdcNext ;
+                DC_UnlockDc(pdcTmp);
+            }
+            pdc->hdcPrev = hdcPrev;
+            pdc->hdcNext = hdcNext;
+            /* Insert it */
+            pdcTmp = DC_LockDc(hdcPrev);
+            ASSERT(pdcTmp) ; /* There should always be a previous */
+            pdcTmp->hdcNext = pdc->BaseObject.hHmgr ;
+            DC_UnlockDc(pdcTmp) ;
+
+            pdcTmp = DC_LockDc(hdcNext);
+            if(pdcTmp) /* Last one is NULL */
+            {
+                pdcTmp->hdcPrev = pdc->BaseObject.hHmgr;
+                DC_UnlockDc(pdcTmp);
+            }
+        }
+
         pdc->erclBounds.left = 0x7fffffff;
         pdc->erclBounds.top = 0x7fffffff;
         pdc->erclBounds.right = 0x80000000;
@@ -302,7 +351,7 @@ DC_vInitDc(
     pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f
        pdc->dclevel.pColorSpace = NULL; // FIXME
     pdc->pClrxFormLnk = NULL;
-//     pdc->dclevel.ca = 
+//     pdc->dclevel.ca =
 
        /* Setup font data */
     pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8
@@ -321,8 +370,6 @@ DC_vInitDc(
 //     pdc->dclevel.pFont = LFONT_ShareLockFont(pdc->dcattr.hlfntNew);
 
     /* Other stuff */
-    pdc->hdcNext = NULL;
-    pdc->hdcPrev = NULL;
     pdc->ipfdDevMax = 0x0000ffff;
     pdc->ulCopyCount = -1;
     pdc->ptlDoBanding.x = 0;
@@ -333,8 +380,6 @@ DC_vInitDc(
        pdc->dcattr.iCS_CP = 0;
     pdc->pSurfInfo = NULL;
 
-    /* FIXME: HACK! */
-    DC_InitHack(pdc);
 }
 
 BOOL
@@ -364,8 +409,8 @@ DC_Cleanup(PVOID ObjectBody)
     /*  Free regions */
     if (pdc->rosdc.hClipRgn)
         GreDeleteObject(pdc->rosdc.hClipRgn);
-    if (pdc->rosdc.hVisRgn)
-        GreDeleteObject(pdc->rosdc.hVisRgn);
+    if (pdc->prgnVis)
+        REGION_FreeRgnByHandle(pdc->prgnVis->BaseObject.hHmgr);
 ASSERT(pdc->rosdc.hGCClipRgn);
     if (pdc->rosdc.hGCClipRgn)
         GreDeleteObject(pdc->rosdc.hGCClipRgn);
@@ -374,6 +419,36 @@ ASSERT(pdc->rosdc.hGCClipRgn);
 
     PATH_Delete(pdc->dclevel.hPath);
 
+    if(pdc->dctype == DCTYPE_DIRECT)
+    {
+        EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
+        /* Remove it from the list of DC attached to the Device */
+        PDC tmpDC = DC_LockDc(pdc->hdcNext);
+        if(tmpDC != NULL)
+        {
+            tmpDC->hdcPrev = pdc->hdcPrev ;
+            DC_UnlockDc(tmpDC);
+        }
+        tmpDC = DC_LockDc(pdc->hdcPrev);
+        if(tmpDC != NULL)
+        {
+            tmpDC->hdcNext = pdc->hdcNext ;
+            DC_UnlockDc(tmpDC);
+        }
+        /* Reassign list head if needed */
+        if(pdc->BaseObject.hHmgr == pdc->dclevel.pSurface->hDC)
+        {
+            /* Sanity check */
+            ASSERT(pdc->hdcPrev == NULL);
+            pdc->dclevel.pSurface->hDC = pdc->hdcNext;
+        }
+        EngReleaseSemaphore(pdc->ppdev->hsemDevLock) ;
+    }
+
+    if(pdc->dclevel.pSurface)
+        SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
+    PDEVOBJ_vRelease(pdc->ppdev) ;
+
     return TRUE;
 }
 
@@ -384,6 +459,7 @@ DC_SetOwnership(HDC hDC, PEPROCESS Owner)
     INT Index;
     PGDI_TABLE_ENTRY Entry;
     PDC pDC;
+    BOOL ret = FALSE;
 
     /* FIXME: This function has broken error handling */
 
@@ -405,40 +481,43 @@ DC_SetOwnership(HDC hDC, PEPROCESS Owner)
           These regions do not use attribute sections and when allocated, use
           gdiobj level functions.
     */
-        if (pDC->rosdc.hClipRgn)
-        {   // FIXME! HAX!!!
-            Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
-            Entry = &GdiHandleTable->Entries[Index];
-            if (Entry->UserData) FreeObjectAttr(Entry->UserData);
-            Entry->UserData = NULL;
-            //
-            if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE;
-        }
-        if (pDC->rosdc.hVisRgn)
-        {   // FIXME! HAX!!!
-            Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hVisRgn);
-            Entry = &GdiHandleTable->Entries[Index];
-            if (Entry->UserData) FreeObjectAttr(Entry->UserData);
-            Entry->UserData = NULL;
-            //
-            if (!GDIOBJ_SetOwnership(pDC->rosdc.hVisRgn, Owner)) return FALSE;
-        }
-        if (pDC->rosdc.hGCClipRgn)
-        {   // FIXME! HAX!!!
-            Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
-            Entry = &GdiHandleTable->Entries[Index];
-            if (Entry->UserData) FreeObjectAttr(Entry->UserData);
-            Entry->UserData = NULL;
-            //
-            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);
+    if (pDC->rosdc.hClipRgn)
+    {   // FIXME! HAX!!!
+        Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
+        Entry = &GdiHandleTable->Entries[Index];
+        if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+        Entry->UserData = NULL;
+        //
+        if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) goto leave;
+    }
+    if (pDC->prgnVis)
+    {   // FIXME! HAX!!!
+        Index = GDI_HANDLE_GET_INDEX(pDC->prgnVis->BaseObject.hHmgr);
+        Entry = &GdiHandleTable->Entries[Index];
+        if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+        Entry->UserData = NULL;
+        //
+        if (!GDIOBJ_SetOwnership(pDC->prgnVis->BaseObject.hHmgr, Owner)) goto leave;
+    }
+    if (pDC->rosdc.hGCClipRgn)
+    {   // FIXME! HAX!!!
+        Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
+        Entry = &GdiHandleTable->Entries[Index];
+        if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+        Entry->UserData = NULL;
+        //
+        if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) goto leave;
+    }
+    if (pDC->dclevel.hPath)
+    {
+        if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) goto leave;
+    }
+    ret = TRUE;
 
-    return TRUE;
+leave:
+    DC_UnlockDc(pDC);
+
+    return ret;
 }
 
 HDC
@@ -457,7 +536,7 @@ GreOpenDCW(
     PDC pdc;
     HDC hdc;
 
-    DPRINT("GreOpenDCW(%S, iType=%ld)\n", 
+    DPRINT("GreOpenDCW(%S, iType=%ld)\n",
            pustrDevice ? pustrDevice->Buffer : NULL, iType);
 
     /* Get a PDEVOBJ for the device */
@@ -479,7 +558,11 @@ GreOpenDCW(
     }
     hdc = pdc->BaseObject.hHmgr;
 
+    /* Lock ppdev and initialize the new DC */
     DC_vInitDc(pdc, iType, ppdev);
+    /* FIXME: HACK! */
+    DC_InitHack(pdc);
+
     DC_AllocDcAttr(pdc);
 
     DC_UnlockDc(pdc);
@@ -637,14 +720,14 @@ NtGdiCreateCompatibleDC(HDC hdc)
     }
     hdcNew = pdcNew->BaseObject.hHmgr;
 
-    /* Initialize the new DC */
+    /* Lock ppdev and initialize the new DC */
     DC_vInitDc(pdcNew, DCTYPE_MEMORY, ppdev);
+    /* FIXME: HACK! */
+    DC_InitHack(pdcNew);
 
     /* Allocate a dc attribute */
     DC_AllocDcAttr(pdcNew);
 
-    PDEVOBJ_vRelease(ppdev);
-
     // HACK!
     DC_vSelectSurface(pdcNew, psurfDefaultBitmap);
 
@@ -678,7 +761,7 @@ IntGdiDeleteDC(HDC hDC, BOOL Force)
     }
 
     DC_UnlockDc(DCToDelete);
-    
+
     if (!IsObjectDead(hDC))
     {
         if (!GDIOBJ_FreeObjByHandle(hDC, GDI_OBJECT_TYPE_DC))
@@ -717,14 +800,74 @@ NtGdiDeleteObjectApp(HANDLE DCHandle)
     return IntGdiDeleteDC(DCHandle, FALSE);
 }
 
+BOOL
+FASTCALL
+MakeInfoDC(PDC pdc, BOOL bSet)
+{
+    PSURFACE pSurface;
+    SIZEL sizl;
+
+    /* Can not be a display DC. */
+    if (pdc->fs & DC_FLAG_DISPLAY) return FALSE;
+    if (bSet)
+    {
+        if (pdc->fs & DC_FLAG_TEMPINFODC || pdc->dctype == DC_TYPE_DIRECT)
+            return FALSE;
+
+        pSurface = pdc->dclevel.pSurface;
+        pdc->fs |= DC_FLAG_TEMPINFODC;
+        pdc->pSurfInfo = pSurface;
+        pdc->dctype = DC_TYPE_INFO;
+        pdc->dclevel.pSurface = NULL;
+
+        PDEVOBJ_sizl(pdc->ppdev, &sizl);
+
+        if ( sizl.cx == pdc->dclevel.sizl.cx &&
+             sizl.cy == pdc->dclevel.sizl.cy )
+            return TRUE;
+
+        pdc->dclevel.sizl.cx = sizl.cx;
+        pdc->dclevel.sizl.cy = sizl.cy;
+    }
+    else
+    {
+        if (!(pdc->fs & DC_FLAG_TEMPINFODC) || pdc->dctype != DC_TYPE_INFO)
+            return FALSE;
+
+        pSurface = pdc->pSurfInfo;
+        pdc->fs &= ~DC_FLAG_TEMPINFODC;
+        pdc->dclevel.pSurface = pSurface;
+        pdc->dctype = DC_TYPE_DIRECT;
+        pdc->pSurfInfo = NULL;
+
+        if ( !pSurface ||
+             (pSurface->SurfObj.sizlBitmap.cx == pdc->dclevel.sizl.cx &&
+              pSurface->SurfObj.sizlBitmap.cy == pdc->dclevel.sizl.cy) )
+            return TRUE;
+
+        pdc->dclevel.sizl.cx = pSurface->SurfObj.sizlBitmap.cx;
+        pdc->dclevel.sizl.cy = pSurface->SurfObj.sizlBitmap.cy;
+    }
+    return IntSetDefaultRegion(pdc);
+}
+
+/*
+* @implemented
+*/
 BOOL
 APIENTRY
 NtGdiMakeInfoDC(
     IN HDC hdc,
     IN BOOL bSet)
 {
-    UNIMPLEMENTED;
-    ASSERT(FALSE);
+    BOOL Ret;
+    PDC pdc = DC_LockDc(hdc);
+    if (pdc)
+    {
+        Ret = MakeInfoDC(pdc, bSet);
+        DC_UnlockDc(pdc);
+        return Ret;
+    }
     return FALSE;
 }
 
@@ -742,7 +885,7 @@ IntGdiCreateDC(
     hdc = GreOpenDCW(pustrDevice,
                      pdmInit,
                      NULL,
-                     CreateAsIC ? DCTYPE_INFO : 
+                     CreateAsIC ? DCTYPE_INFO :
                           (Driver ? DC_TYPE_DIRECT : DC_TYPE_DIRECT),
                      TRUE,
                      NULL,