ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

windc.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Win32k subsystem
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            subsystems/win32/win32k/ntuser/windc.c
00005  * PURPOSE:         Window DC management
00006  * COPYRIGHT:       Copyright 2007 ReactOS Team
00007  */
00008 
00009 #include <win32k.h>
00010 DBG_DEFAULT_CHANNEL(UserDce);
00011 
00012 /* GLOBALS *******************************************************************/
00013 
00014 /* NOTE: I think we should store this per window station (including GDI objects) */
00015 /* Answer: No, use the DCE pMonitor to compare with! */
00016 
00017 static LIST_ENTRY LEDce;
00018 static INT DCECount = 0; // Count of DCE in system.
00019 
00020 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
00021                               DCX_NORESETATTRS | DCX_LOCKWINDOWUPDATE | \
00022                               DCX_LAYEREDWIN | DCX_CACHE | DCX_WINDOW | \
00023                               DCX_PARENTCLIP)
00024 
00025 /* FUNCTIONS *****************************************************************/
00026 
00027 INIT_FUNCTION
00028 NTSTATUS
00029 NTAPI
00030 InitDCEImpl(VOID)
00031 {
00032     InitializeListHead(&LEDce);
00033     return STATUS_SUCCESS;
00034 }
00035 
00036 //
00037 // This should be moved to dc.c or dcutil.c.
00038 //
00039 HDC FASTCALL
00040 DceCreateDisplayDC(VOID)
00041 {
00042   UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY");
00043 
00044   co_IntGraphicsCheck(TRUE);
00045 
00046   return IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
00047 }
00048 
00049 static
00050 HRGN FASTCALL
00051 DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
00052 {
00053   HRGN VisRgn;
00054 
00055   VisRgn = VIS_ComputeVisibleRegion( Window,
00056                                      0 == (Flags & DCX_WINDOW),
00057                                      0 != (Flags & DCX_CLIPCHILDREN),
00058                                      0 != (Flags & DCX_CLIPSIBLINGS));
00059 
00060   if (VisRgn == NULL)
00061       VisRgn = IntSysCreateRectRgn(0, 0, 0, 0);
00062 
00063   return VisRgn;
00064 }
00065 
00066 PDCE FASTCALL
00067 DceAllocDCE(PWND Window OPTIONAL, DCE_TYPE Type)
00068 {
00069   PDCE pDce;
00070 
00071   pDce = ExAllocatePoolWithTag(PagedPool, sizeof(DCE), USERTAG_DCE);
00072   if(!pDce)
00073         return NULL;
00074 
00075   pDce->hDC = DceCreateDisplayDC();
00076   if (!pDce->hDC)
00077   {
00078       ExFreePoolWithTag(pDce, USERTAG_DCE);
00079       return NULL;
00080   }
00081   DCECount++;
00082   TRACE("Alloc DCE's! %d\n",DCECount);
00083   pDce->hwndCurrent = (Window ? Window->head.h : NULL);
00084   pDce->pwndOrg  = Window;
00085   pDce->pwndClip = Window;
00086   pDce->hrgnClip = NULL;
00087   pDce->hrgnClipPublic = NULL;
00088   pDce->hrgnSavedVis = NULL;
00089   pDce->ppiOwner = NULL;
00090 
00091   InsertTailList(&LEDce, &pDce->List);
00092 
00093   DCU_SetDcUndeletable(pDce->hDC);
00094 
00095   if (Type == DCE_WINDOW_DC || Type == DCE_CLASS_DC) // Window DCE have ownership.
00096   {
00097      pDce->ptiOwner = GetW32ThreadInfo();
00098   }
00099   else
00100   {
00101      TRACE("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %x\n", pDce->hDC);
00102      GreSetDCOwner(pDce->hDC, GDI_OBJ_HMGR_NONE);
00103      pDce->ptiOwner = NULL;
00104   }
00105 
00106   if (Type == DCE_CACHE_DC)
00107   {
00108      pDce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY;
00109   }
00110   else
00111   {
00112      pDce->DCXFlags = DCX_DCEBUSY;
00113      if (Window)
00114      {
00115         if (Type == DCE_WINDOW_DC)
00116         {
00117           if (Window->style & WS_CLIPCHILDREN) pDce->DCXFlags |= DCX_CLIPCHILDREN;
00118           if (Window->style & WS_CLIPSIBLINGS) pDce->DCXFlags |= DCX_CLIPSIBLINGS;
00119         }
00120      }
00121   }
00122   return(pDce);
00123 }
00124 
00125 static VOID APIENTRY
00126 DceSetDrawable( PWND Window OPTIONAL,
00127                 HDC hDC,
00128                 ULONG Flags,
00129                 BOOL SetClipOrigin)
00130 {
00131   DC *dc = DC_LockDc(hDC);
00132   if(!dc)
00133       return;
00134 
00135   if (Window == NULL)
00136   {
00137       dc->ptlDCOrig.x = 0;
00138       dc->ptlDCOrig.y = 0;
00139   }
00140   else
00141   {
00142       if (Flags & DCX_WINDOW)
00143       {
00144          dc->ptlDCOrig.x = Window->rcWindow.left;
00145          dc->ptlDCOrig.y = Window->rcWindow.top;
00146       }
00147       else
00148       {
00149          dc->ptlDCOrig.x = Window->rcClient.left;
00150          dc->ptlDCOrig.y = Window->rcClient.top;
00151       }
00152   }
00153   DC_UnlockDc(dc);
00154 }
00155 
00156 
00157 static VOID FASTCALL
00158 DceDeleteClipRgn(DCE* Dce)
00159 {
00160    Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN);
00161 
00162    if (Dce->DCXFlags & DCX_KEEPCLIPRGN )
00163    {
00164       Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
00165    }
00166    else if (Dce->hrgnClip != NULL)
00167    {
00168       GreDeleteObject(Dce->hrgnClip);
00169    }
00170 
00171    Dce->hrgnClip = NULL;
00172 
00173    /* Make it dirty so that the vis rgn gets recomputed next time */
00174    Dce->DCXFlags |= DCX_DCEDIRTY;
00175 }
00176 
00177 static INT FASTCALL
00178 DceReleaseDC(DCE* dce, BOOL EndPaint)
00179 {
00180    if (DCX_DCEBUSY != (dce->DCXFlags & (DCX_INDESTROY | DCX_DCEEMPTY | DCX_DCEBUSY)))
00181    {
00182       return 0;
00183    }
00184 
00185    /* Restore previous visible region */
00186    if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&
00187          ((dce->DCXFlags & DCX_CACHE) || EndPaint))
00188    {
00189       DceDeleteClipRgn(dce);
00190    }
00191 
00192    if (dce->DCXFlags & DCX_CACHE)
00193    {
00194       if (!(dce->DCXFlags & DCX_NORESETATTRS))
00195       {
00196          /* Make the DC clean so that SetDCState doesn't try to update the vis rgn */
00197          IntGdiSetHookFlags(dce->hDC, DCHF_VALIDATEVISRGN);
00198 
00199          // Clean the DC
00200          if (!IntGdiCleanDC(dce->hDC)) return 0;
00201 
00202          if (dce->DCXFlags & DCX_DCEDIRTY)
00203          {
00204            /* Don't keep around invalidated entries
00205             * because SetDCState() disables hVisRgn updates
00206             * by removing dirty bit. */
00207            dce->hwndCurrent = 0;
00208            dce->DCXFlags &= DCX_CACHE;
00209            dce->DCXFlags |= DCX_DCEEMPTY;
00210          }
00211       }
00212       dce->DCXFlags &= ~DCX_DCEBUSY;
00213       TRACE("Exit!!!!! DCX_CACHE!!!!!!   hDC-> %x \n", dce->hDC);
00214       if (!GreSetDCOwner(dce->hDC, GDI_OBJ_HMGR_NONE))
00215          return 0;
00216       dce->ptiOwner = NULL; // Reset ownership.
00217       dce->ppiOwner = NULL;
00218 
00219 #if 0 // Need to research and fix before this is a "growing" issue.
00220       if (++DCECache > 32)
00221       {
00222          pLE = LEDce.Flink;
00223          pDCE = CONTAINING_RECORD(pLE, DCE, List);
00224          do
00225          {
00226             if (!(pDCE->DCXFlags & DCX_DCEBUSY))
00227             {  /* Free the unused cache DCEs. */
00228                pDCE = DceFreeDCE(pDCE, TRUE);
00229                if (!pDCE) break;
00230                continue;
00231             }
00232          }
00233          while (pLE != &LEDce );
00234       }
00235 #endif
00236    }
00237    return 1; // Released!
00238 }
00239 
00240 static VOID FASTCALL
00241 DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
00242 {
00243    HANDLE hRgnVisible = NULL;
00244    ULONG DcxFlags;
00245    PWND DesktopWindow;
00246 
00247    if (Flags & DCX_PARENTCLIP)
00248    {
00249       PWND Parent;
00250 
00251       Parent = Window->spwndParent;
00252       if(!Parent)
00253       {
00254          hRgnVisible = NULL;
00255          goto noparent;
00256       }
00257 
00258       if (Parent->style & WS_CLIPSIBLINGS)
00259       {
00260          DcxFlags = DCX_CLIPSIBLINGS |
00261                     (Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
00262       }
00263       else
00264       {
00265          DcxFlags = Flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
00266       }
00267       hRgnVisible = DceGetVisRgn(Parent, DcxFlags, Window->head.h, Flags);
00268    }
00269    else if (Window == NULL)
00270    {
00271       DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
00272       if (NULL != DesktopWindow)
00273       {
00274          hRgnVisible = IntSysCreateRectRgnIndirect(&DesktopWindow->rcWindow);
00275       }
00276       else
00277       {
00278          hRgnVisible = NULL;
00279       }
00280    }
00281    else
00282    {
00283       hRgnVisible = DceGetVisRgn(Window, Flags, 0, 0);
00284    }
00285 
00286 noparent:
00287    if (Flags & DCX_INTERSECTRGN)
00288    {
00289       if(Dce->hrgnClip != NULL)
00290       {
00291          NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hrgnClip, RGN_AND);
00292       }
00293       else
00294       {
00295          if(hRgnVisible != NULL)
00296          {
00297             GreDeleteObject(hRgnVisible);
00298          }
00299          hRgnVisible = IntSysCreateRectRgn(0, 0, 0, 0);
00300       }
00301    }
00302    else if (Flags & DCX_EXCLUDERGN && Dce->hrgnClip != NULL)
00303    {
00304       NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hrgnClip, RGN_DIFF);
00305    }
00306 
00307    Dce->DCXFlags &= ~DCX_DCEDIRTY;
00308    GdiSelectVisRgn(Dce->hDC, hRgnVisible);
00309 
00310    if (Window != NULL)
00311    {
00312       IntEngWindowChanged(Window, WOC_RGN_CLIENT);
00313    }
00314 
00315    if (hRgnVisible != NULL)
00316    {
00317       GreDeleteObject(hRgnVisible);
00318    }
00319 }
00320 
00321 HDC FASTCALL
00322 UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
00323 {
00324    PWND Parent;
00325    ULONG DcxFlags;
00326    DCE* Dce = NULL;
00327    BOOL UpdateClipOrigin = FALSE;
00328    HDC hDC = NULL;
00329    PPROCESSINFO ppi;
00330    PLIST_ENTRY pLE;
00331 
00332    if (NULL == Wnd)
00333    {
00334       Flags &= ~DCX_USESTYLE;
00335       Flags |= DCX_CACHE;
00336    }
00337 
00338    if (Flags & (DCX_WINDOW | DCX_PARENTCLIP)) Flags |= DCX_CACHE;
00339 
00340    // When GetDC is called with hWnd nz, DCX_CACHE & _WINDOW are clear w _USESTYLE set.
00341    if (Flags & DCX_USESTYLE)
00342    {
00343       Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP);
00344       if (!(Flags & DCX_WINDOW)) // Not window rectangle
00345       {
00346          if (Wnd->pcls->style & CS_PARENTDC)
00347          {
00348             Flags |= DCX_PARENTCLIP;
00349          }
00350 
00351          if (!(Flags & DCX_CACHE) && // Not on the cheap wine list.
00352              !(Wnd->pcls->style & CS_OWNDC) )
00353          {
00354             if (!(Wnd->pcls->style & CS_CLASSDC))
00355             // The window is not POWNED or has any CLASS, so we are looking for cheap wine.
00356                Flags |= DCX_CACHE;
00357             else
00358             {
00359                if (Wnd->pcls->pdce) hDC = ((PDCE)Wnd->pcls->pdce)->hDC;
00360                TRACE("We have CLASS!!\n");
00361             }
00362          }
00363 /*         else // For Testing!
00364          {
00365             DPRINT1("We have POWNER!!\n");
00366             if (Window->Dce) DPRINT1("We have POWNER with DCE!!\n");
00367          }
00368 */
00369          if (Wnd->style & WS_CLIPSIBLINGS)
00370          {
00371             Flags |= DCX_CLIPSIBLINGS;
00372          }
00373 
00374          if (Wnd->style & WS_CLIPCHILDREN &&
00375              !(Wnd->style & WS_MINIMIZE))
00376          {
00377             Flags |= DCX_CLIPCHILDREN;
00378          }
00379          /* If minized with icon in the set, we are forced to be cheap! */
00380          if (Wnd->style & WS_MINIMIZE &&
00381              Wnd->pcls->hIcon)
00382          {
00383             Flags |= DCX_CACHE;
00384          }
00385       }
00386       else
00387       {
00388          if (Wnd->style & WS_CLIPSIBLINGS) Flags |= DCX_CLIPSIBLINGS;
00389          Flags |= DCX_CACHE;
00390       }
00391    }
00392 
00393    if (Flags & DCX_WINDOW) Flags &= ~DCX_CLIPCHILDREN;
00394 
00395    if (Flags & DCX_NOCLIPCHILDREN)
00396    {
00397       Flags |= DCX_CACHE;
00398       Flags &= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN);
00399    }
00400 
00401    Parent = (Wnd ? Wnd->spwndParent : NULL);
00402 
00403    if (NULL == Wnd || !(Wnd->style & WS_CHILD) || NULL == Parent)
00404    {
00405       Flags &= ~DCX_PARENTCLIP;
00406       Flags |= DCX_CLIPSIBLINGS;
00407    }
00408 
00409    /* It seems parent clip is ignored when clipping siblings or children */
00410    if (Flags & (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN)) Flags &= ~DCX_PARENTCLIP;
00411 
00412    if (Flags & DCX_PARENTCLIP)
00413    {
00414       if ((Wnd->style & WS_VISIBLE) &&
00415           (Parent->style & WS_VISIBLE))
00416       {
00417          Flags &= ~DCX_CLIPCHILDREN;
00418          if (Parent->style & WS_CLIPSIBLINGS)
00419          {
00420             Flags |= DCX_CLIPSIBLINGS;
00421          }
00422       }
00423    }
00424 
00425    // Window nz, check to see if we still own this or it is just cheap wine tonight.
00426    if (!(Flags & DCX_CACHE))
00427    {
00428       if ( Wnd->head.pti != GetW32ThreadInfo())
00429          Flags |= DCX_CACHE; // Ah~ Not Powned! Forced to be cheap~
00430    }
00431 
00432    DcxFlags = Flags & DCX_CACHECOMPAREMASK;
00433 
00434    if (Flags & DCX_CACHE)
00435    { // Scan the cheap wine list for our match.
00436       DCE* DceEmpty = NULL;
00437       DCE* DceUnused = NULL;
00438       KeEnterCriticalRegion();
00439       pLE = LEDce.Flink;
00440       Dce = CONTAINING_RECORD(pLE, DCE, List);
00441       do
00442       {
00443 // The reason for this you may ask?
00444 // Well, it seems ReactOS calls GetDC with out first creating a desktop DC window!
00445 // Need to test for null here. Not sure if this is a bug or a feature.
00446 // First time use hax, need to use DceAllocDCE during window display init.
00447          if (!Dce) break;
00448 //
00449 // The way I understand this, you can have more than one DC per window.
00450 // Only one Owned if one was requested and saved and one Cached.
00451 //
00452          if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE)
00453          {
00454             DceUnused = Dce;
00455             if (Dce->DCXFlags & DCX_DCEEMPTY)
00456             {
00457                DceEmpty = Dce;
00458             }
00459             else if (Dce->hwndCurrent == (Wnd ? Wnd->head.h : NULL) &&
00460                      ((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags))
00461             {
00462                UpdateClipOrigin = TRUE;
00463                break;
00464             }
00465          }
00466          pLE = Dce->List.Flink;
00467          Dce = CONTAINING_RECORD(pLE, DCE, List);
00468       }
00469       while (pLE != &LEDce);
00470       KeLeaveCriticalRegion();
00471 
00472       Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty;
00473 
00474       if (Dce == NULL)
00475       {
00476          Dce = DceAllocDCE(NULL, DCE_CACHE_DC);
00477       }
00478       if (!Dce) return NULL;
00479 
00480       Dce->hwndCurrent = (Wnd ? Wnd->head.h : NULL);
00481    }
00482    else // If we are here, we are POWNED or having CLASS.
00483    {
00484       KeEnterCriticalRegion();
00485       pLE = LEDce.Flink;
00486       Dce = CONTAINING_RECORD(pLE, DCE, List);
00487       do
00488       {   // Check for Window handle than HDC match for CLASS.
00489           if ((Dce->hwndCurrent == Wnd->head.h) ||
00490               (Dce->hDC == hDC))
00491              break;
00492           pLE = Dce->List.Flink;
00493           Dce = CONTAINING_RECORD(pLE, DCE, List);
00494       }
00495       while (pLE != &LEDce);
00496       KeLeaveCriticalRegion();
00497 
00498       if ( (Flags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) &&
00499            (Dce->DCXFlags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) )
00500       {
00501           DceDeleteClipRgn(Dce);
00502       }
00503    }
00504 // First time use hax, need to use DceAllocDCE during window display init.
00505    if (NULL == Dce)
00506    {
00507       return(NULL);
00508    }
00509 
00510    if (!GreIsHandleValid(Dce->hDC))
00511    {
00512       ERR("FIXME: Got DCE with invalid hDC! 0x%x\n", Dce->hDC);
00513       Dce->hDC = DceCreateDisplayDC();
00514       /* FIXME: Handle error */
00515    }
00516 
00517    Dce->DCXFlags = Flags | DCX_DCEBUSY;
00518 
00519    /*
00520     * Bump it up! This prevents the random errors in wine dce tests and with
00521     * proper bits set in DCX_CACHECOMPAREMASK.
00522     * Reference:
00523     *   http://www.reactos.org/archives/public/ros-dev/2008-July/010498.html
00524     *   http://www.reactos.org/archives/public/ros-dev/2008-July/010499.html
00525     */
00526    if (pLE != &LEDce)
00527    {
00528       RemoveEntryList(&Dce->List);
00529       InsertHeadList(&LEDce, &Dce->List);
00530    }
00531 
00532    /* Introduced in rev 6691 and modified later. */
00533    if ( (Flags & DCX_INTERSECTUPDATE) && !ClipRegion )
00534    {
00535       Flags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN;
00536       Dce->DCXFlags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN;
00537       ClipRegion = Wnd->hrgnUpdate;
00538    }
00539 
00540    if (ClipRegion == HRGN_WINDOW)
00541    {
00542       if (!(Flags & DCX_WINDOW))
00543       {
00544          Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
00545       }
00546       else
00547       {
00548          Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
00549       }
00550       Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
00551    }
00552    else if (ClipRegion != NULL)
00553    {
00554       if (Dce->hrgnClip != NULL)
00555       {
00556          ERR("Should not be called!!\n");
00557          GreDeleteObject(Dce->hrgnClip);
00558          Dce->hrgnClip = NULL;
00559       }
00560       Dce->hrgnClip = ClipRegion;
00561    }
00562 
00563    DceSetDrawable(Wnd, Dce->hDC, Flags, UpdateClipOrigin);
00564 
00565    DceUpdateVisRgn(Dce, Wnd, Flags);
00566 
00567    if (Dce->DCXFlags & DCX_CACHE)
00568    {
00569       TRACE("ENTER!!!!!! DCX_CACHE!!!!!!   hDC-> %x\n", Dce->hDC);
00570       // Need to set ownership so Sync dcattr will work.
00571       GreSetDCOwner(Dce->hDC, GDI_OBJ_HMGR_POWNED);
00572       Dce->ptiOwner = GetW32ThreadInfo(); // Set the temp owning
00573    }
00574 
00575    if ( Wnd &&
00576         Wnd->ExStyle & WS_EX_LAYOUTRTL &&
00577        !(Flags & DCX_KEEPLAYOUT) )
00578    {
00579       NtGdiSetLayout(Dce->hDC, -1, LAYOUT_RTL);
00580    }
00581 
00582    if (Dce->DCXFlags & DCX_PROCESSOWNED)
00583    {
00584       ppi = PsGetCurrentProcessWin32Process();
00585       ppi->W32PF_flags |= W32PF_OWNDCCLEANUP;
00586       Dce->ptiOwner = NULL;
00587       Dce->ppiOwner = ppi;
00588    }
00589 
00590    return(Dce->hDC);
00591 }
00592 
00593 /***********************************************************************
00594  *           DceFreeDCE
00595  */
00596 PDCE FASTCALL
00597 DceFreeDCE(PDCE pdce, BOOLEAN Force)
00598 {
00599   DCE *ret;
00600   PLIST_ENTRY pLE;
00601   BOOL Hit = FALSE;
00602 
00603   if (NULL == pdce) return NULL;
00604 
00605   pLE = pdce->List.Flink;
00606   ret = CONTAINING_RECORD(pLE, DCE, List);
00607 
00608   pdce->DCXFlags |= DCX_INDESTROY;
00609 
00610   if (Force &&
00611       GreGetObjectOwner(pdce->hDC) != GDI_OBJ_HMGR_POWNED)
00612   {
00613      TRACE("Change ownership for DCE! -> %x\n" , pdce);
00614      // NOTE: Windows sets W32PF_OWNDCCLEANUP and moves on.
00615      if (GreIsHandleValid(pdce->hDC))
00616      {
00617          GreSetDCOwner(pdce->hDC, GDI_OBJ_HMGR_POWNED);
00618      }
00619      else
00620      {
00621          ERR("Attempted to change ownership of an DCEhDC 0x%x currently being destroyed!!!\n",pdce->hDC);
00622          Hit = TRUE;
00623      }
00624   }
00625   else
00626   {
00627      if (GreGetObjectOwner(pdce->hDC) == GDI_OBJ_HMGR_PUBLIC)
00628         GreSetDCOwner(pdce->hDC, GDI_OBJ_HMGR_POWNED);
00629   }
00630 
00631   if (!Hit) IntGdiDeleteDC(pdce->hDC, TRUE);
00632 
00633   if (pdce->hrgnClip && !(pdce->DCXFlags & DCX_KEEPCLIPRGN))
00634   {
00635       GreDeleteObject(pdce->hrgnClip);
00636       pdce->hrgnClip = NULL;
00637   }
00638 
00639   RemoveEntryList(&pdce->List);
00640 
00641   if (IsListEmpty(&pdce->List))
00642   {
00643       ERR("List is Empty! DCE! -> %x\n" , pdce);
00644       return NULL;
00645   }
00646 
00647   ExFreePoolWithTag(pdce, USERTAG_DCE);
00648 
00649   DCECount--;
00650   TRACE("Freed DCE's! %d \n", DCECount);
00651 
00652   return ret;
00653 }
00654 
00655 /***********************************************************************
00656  *           DceFreeWindowDCE
00657  *
00658  * Remove owned DCE and reset unreleased cache DCEs.
00659  */
00660 void FASTCALL
00661 DceFreeWindowDCE(PWND Window)
00662 {
00663   PDCE pDCE;
00664   PLIST_ENTRY pLE;
00665 
00666   if (DCECount <= 0)
00667   {
00668      ERR("FreeWindowDCE No Entry! %d\n",DCECount);
00669      return;
00670   }
00671 
00672   pLE = LEDce.Flink;
00673   pDCE = CONTAINING_RECORD(pLE, DCE, List);
00674   do
00675   {
00676      if (!pDCE)
00677      {
00678         ERR("FreeWindowDCE No DCE Pointer!\n");
00679         break;
00680      }
00681      if (IsListEmpty(&pDCE->List))
00682      {
00683         ERR("FreeWindowDCE List is Empty!!!!\n");
00684         break;
00685      }
00686      if ( pDCE->hwndCurrent == Window->head.h &&
00687           !(pDCE->DCXFlags & DCX_DCEEMPTY) )
00688      {
00689         if (!(pDCE->DCXFlags & DCX_CACHE)) /* Owned or Class DCE */
00690         {
00691            if (Window->pcls->style & CS_CLASSDC) /* Test Class first */
00692            {
00693               if (pDCE->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) /* Class DCE */
00694                  DceDeleteClipRgn(pDCE);
00695               // Update and reset Vis Rgn and clear the dirty bit.
00696               // Should release VisRgn than reset it to default.
00697               DceUpdateVisRgn(pDCE, Window, pDCE->DCXFlags);
00698               pDCE->DCXFlags = DCX_DCEEMPTY|DCX_CACHE;
00699               pDCE->hwndCurrent = 0;
00700 
00701               TRACE("POWNED DCE going Cheap!! DCX_CACHE!! hDC-> %x \n", pDCE->hDC);
00702               if (!GreSetDCOwner( pDCE->hDC, GDI_OBJ_HMGR_NONE))
00703               {
00704                   ERR("Fail Owner Switch hDC-> %x \n", pDCE->hDC);
00705                   break;
00706               }
00707               /* Do not change owner so thread can clean up! */
00708            }
00709            else if (Window->pcls->style & CS_OWNDC) /* Owned DCE */
00710            {
00711               pDCE = DceFreeDCE(pDCE, FALSE);
00712               if (!pDCE) break;
00713               continue;
00714            }
00715            else
00716            {
00717               ERR("Not POWNED or CLASSDC hwndCurrent -> %x \n", pDCE->hwndCurrent);
00718               // ASSERT(FALSE); /* bug 5320 */
00719            }
00720         }
00721         else
00722         {
00723            if (pDCE->DCXFlags & DCX_DCEBUSY) /* Shared cache DCE */
00724            {
00725               /* FIXME: AFAICS we are doing the right thing here so
00726                * this should be a TRACE. But this is best left as an ERR
00727                * because the 'application error' is likely to come from
00728                * another part of Wine (i.e. it's our fault after all).
00729                * We should change this to TRACE when ReactOS is more stable
00730                * (for 1.0?).
00731                */
00732               ERR("[%p] GetDC() without ReleaseDC()!\n", Window->head.h);
00733               DceReleaseDC(pDCE, FALSE);
00734            }
00735            pDCE->DCXFlags |= DCX_DCEEMPTY;
00736            pDCE->hwndCurrent = 0;
00737         }
00738      }
00739      pLE = pDCE->List.Flink;
00740      pDCE = CONTAINING_RECORD(pLE, DCE, List);
00741   }
00742   while (pLE != &LEDce);
00743 }
00744 
00745 void FASTCALL
00746 DceFreeClassDCE(HDC hDC)
00747 {
00748    PDCE pDCE;
00749    PLIST_ENTRY pLE;
00750    pLE = LEDce.Flink;
00751    pDCE = CONTAINING_RECORD(pLE, DCE, List);
00752 
00753    do
00754    {
00755        if(!pDCE) break;
00756        if (pDCE->hDC == hDC)
00757        {
00758           pDCE = DceFreeDCE(pDCE, TRUE); // Might have gone cheap!
00759           if (!pDCE) break;
00760           continue;
00761        }
00762        pLE = pDCE->List.Flink;
00763        pDCE = CONTAINING_RECORD(pLE, DCE, List);
00764    }
00765    while (pLE != &LEDce);
00766 }
00767 
00768 void FASTCALL
00769 DceFreeThreadDCE(PTHREADINFO pti)
00770 {
00771    PDCE pDCE;
00772    PLIST_ENTRY pLE;
00773    pLE = LEDce.Flink;
00774    pDCE = CONTAINING_RECORD(pLE, DCE, List);
00775 
00776    do
00777    {
00778        if(!pDCE) break;
00779        if (pDCE->ptiOwner == pti)
00780        {
00781           if (pDCE->DCXFlags & DCX_CACHE)
00782           {
00783              pDCE = DceFreeDCE(pDCE, TRUE);
00784              if (!pDCE) break;
00785              continue;
00786           }
00787        }
00788        pLE = pDCE->List.Flink;
00789        pDCE = CONTAINING_RECORD(pLE, DCE, List);
00790    }
00791    while (pLE != &LEDce);
00792 }
00793 
00794 VOID FASTCALL
00795 DceEmptyCache(VOID)
00796 {
00797    PDCE pDCE;
00798    PLIST_ENTRY pLE;
00799    pLE = LEDce.Flink;
00800    pDCE = CONTAINING_RECORD(pLE, DCE, List);
00801 
00802    do
00803    {
00804       if(!pDCE) break;
00805       pDCE = DceFreeDCE(pDCE, TRUE);
00806       if(!pDCE) break;
00807    }
00808    while (pLE != &LEDce);
00809 }
00810 
00811 VOID FASTCALL
00812 DceResetActiveDCEs(PWND Window)
00813 {
00814    DCE *pDCE;
00815    PDC dc;
00816    PWND CurrentWindow;
00817    INT DeltaX;
00818    INT DeltaY;
00819    PLIST_ENTRY pLE;
00820 
00821    if (NULL == Window)
00822    {
00823       return;
00824    }
00825    pLE = LEDce.Flink;
00826    pDCE = CONTAINING_RECORD(pLE, DCE, List);
00827 
00828    do
00829    {
00830       if(!pDCE) break;
00831       if(pLE == &LEDce) break;
00832       if (0 == (pDCE->DCXFlags & (DCX_DCEEMPTY|DCX_INDESTROY)))
00833       {
00834          if (Window->head.h == pDCE->hwndCurrent)
00835          {
00836             CurrentWindow = Window;
00837          }
00838          else
00839          {
00840             CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent);
00841             if (NULL == CurrentWindow)
00842             {
00843                pLE = pDCE->List.Flink;
00844                pDCE = CONTAINING_RECORD(pLE, DCE, List);
00845                continue;
00846             }
00847          }
00848 
00849          if (!GreIsHandleValid(pDCE->hDC) ||
00850              (dc = DC_LockDc(pDCE->hDC)) == NULL)
00851          {
00852             pLE = pDCE->List.Flink;
00853             pDCE = CONTAINING_RECORD(pLE, DCE, List);
00854             continue;
00855          }
00856          if (Window == CurrentWindow || IntIsChildWindow(Window, CurrentWindow))
00857          {
00858             if (pDCE->DCXFlags & DCX_WINDOW)
00859             {
00860                DeltaX = CurrentWindow->rcWindow.left - dc->ptlDCOrig.x;
00861                DeltaY = CurrentWindow->rcWindow.top - dc->ptlDCOrig.y;
00862                dc->ptlDCOrig.x = CurrentWindow->rcWindow.left;
00863                dc->ptlDCOrig.y = CurrentWindow->rcWindow.top;
00864             }
00865             else
00866             {
00867                DeltaX = CurrentWindow->rcClient.left - dc->ptlDCOrig.x;
00868                DeltaY = CurrentWindow->rcClient.top - dc->ptlDCOrig.y;
00869                dc->ptlDCOrig.x = CurrentWindow->rcClient.left;
00870                dc->ptlDCOrig.y = CurrentWindow->rcClient.top;
00871             }
00872             if (NULL != dc->rosdc.hClipRgn)
00873             {
00874                NtGdiOffsetRgn(dc->rosdc.hClipRgn, DeltaX, DeltaY);
00875                CLIPPING_UpdateGCRegion(dc);
00876             }
00877             if (NULL != pDCE->hrgnClip)
00878             {
00879                NtGdiOffsetRgn(pDCE->hrgnClip, DeltaX, DeltaY);
00880             }
00881          }
00882          DC_UnlockDc(dc);
00883 
00884          DceUpdateVisRgn(pDCE, CurrentWindow, pDCE->DCXFlags);
00885 
00886          if (Window->head.h != pDCE->hwndCurrent)
00887          {
00888 //            IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT);
00889 //            UserDerefObject(CurrentWindow);
00890          }
00891       }
00892       pLE = pDCE->List.Flink;
00893       pDCE = CONTAINING_RECORD(pLE, DCE, List);
00894    }
00895    while (pLE != &LEDce);
00896 }
00897 
00898 HWND FASTCALL
00899 IntWindowFromDC(HDC hDc)
00900 {
00901   DCE *Dce;
00902   PLIST_ENTRY pLE;
00903   HWND Ret = NULL;
00904 
00905   pLE = LEDce.Flink;
00906   Dce = CONTAINING_RECORD(pLE, DCE, List);
00907   do
00908   {
00909       if (Dce->hDC == hDc)
00910       {
00911          if (Dce->DCXFlags & DCX_INDESTROY)
00912             Ret = NULL;
00913          else
00914             Ret = Dce->hwndCurrent;
00915          break;
00916       }
00917       pLE = Dce->List.Flink;
00918       Dce = CONTAINING_RECORD(pLE, DCE, List);
00919   }
00920   while (pLE != &LEDce);
00921   return Ret;
00922 }
00923 
00924 INT FASTCALL
00925 UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
00926 {
00927   PDCE dce;
00928   PLIST_ENTRY pLE;
00929   INT nRet = 0;
00930   BOOL Hit = FALSE;
00931 
00932   TRACE("%p %p\n", Window, hDc);
00933   pLE = LEDce.Flink;
00934   dce = CONTAINING_RECORD(pLE, DCE, List);
00935   do
00936   {
00937      if(!dce) break;
00938      if (dce->hDC == hDc)
00939      {
00940         Hit = TRUE;
00941         break;
00942      }
00943      pLE = dce->List.Flink;
00944      dce = CONTAINING_RECORD(pLE, DCE, List);
00945   }
00946   while (pLE != &LEDce );
00947 
00948   if ( Hit && (dce->DCXFlags & DCX_DCEBUSY))
00949   {
00950      nRet = DceReleaseDC(dce, EndPaint);
00951   }
00952 
00953   return nRet;
00954 }
00955 
00956 HDC FASTCALL
00957 UserGetWindowDC(PWND Wnd)
00958 {
00959   return UserGetDCEx(Wnd, 0, DCX_USESTYLE | DCX_WINDOW);
00960 }
00961 
00962 HWND FASTCALL
00963 UserGethWnd( HDC hdc, PWNDOBJ *pwndo)
00964 {
00965   PWNDGDI pWndgdi;
00966   PWND Wnd;
00967   HWND hWnd;
00968   PPROPERTY pprop;
00969 
00970   hWnd = IntWindowFromDC(hdc);
00971 
00972   if (hWnd && !(Wnd = UserGetWindowObject(hWnd)))
00973   {
00974      pprop = IntGetProp(Wnd, AtomWndObj);
00975 
00976      pWndgdi = (WNDGDI *)pprop->Data;
00977 
00978      if ( pWndgdi && pWndgdi->Hwnd == hWnd )
00979      {
00980         if (pwndo) *pwndo = (PWNDOBJ)pWndgdi;
00981      }
00982   }
00983   return hWnd;
00984 }
00985 
00986 HDC APIENTRY
00987 NtUserGetDCEx(HWND hWnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
00988 {
00989   PWND Wnd=NULL;
00990   DECLARE_RETURN(HDC);
00991 
00992   TRACE("Enter NtUserGetDCEx\n");
00993   UserEnterExclusive();
00994 
00995   if (hWnd && !(Wnd = UserGetWindowObject(hWnd)))
00996   {
00997       RETURN(NULL);
00998   }
00999   RETURN( UserGetDCEx(Wnd, ClipRegion, Flags));
01000 
01001 CLEANUP:
01002   TRACE("Leave NtUserGetDCEx, ret=%i\n",_ret_);
01003   UserLeave();
01004   END_CLEANUP;
01005 }
01006 
01007 /*
01008  * NtUserGetWindowDC
01009  *
01010  * The NtUserGetWindowDC function retrieves the device context (DC) for the
01011  * entire window, including title bar, menus, and scroll bars. A window device
01012  * context permits painting anywhere in a window, because the origin of the
01013  * device context is the upper-left corner of the window instead of the client
01014  * area.
01015  *
01016  * Status
01017  *    @implemented
01018  */
01019 HDC APIENTRY
01020 NtUserGetWindowDC(HWND hWnd)
01021 {
01022   return NtUserGetDCEx(hWnd, 0, DCX_USESTYLE | DCX_WINDOW);
01023 }
01024 
01025 HDC APIENTRY
01026 NtUserGetDC(HWND hWnd)
01027 {
01028  TRACE("NtUGetDC -> %x:%x\n", hWnd, !hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE );
01029 
01030   return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
01031 }
01032 
01044 HPALETTE
01045 APIENTRY
01046 NtUserSelectPalette(HDC  hDC,
01047               HPALETTE  hpal,
01048        BOOL  ForceBackground)
01049 {
01050     HPALETTE oldPal;
01051     UserEnterExclusive();
01052     // Implement window checks
01053     oldPal = GdiSelectPalette( hDC, hpal, ForceBackground);
01054     UserLeave();
01055     return oldPal;
01056 }
01057 
01058 /* EOF */

Generated on Sun May 27 2012 04:38:36 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.