diff --git a/reactos/subsystems/win32/win32k/include/dc.h b/reactos/subsystems/win32/win32k/include/dc.h index 5b5d97fca39..3c2828b43c4 100644 --- a/reactos/subsystems/win32/win32k/include/dc.h +++ b/reactos/subsystems/win32/win32k/include/dc.h @@ -108,12 +108,14 @@ VOID FASTCALL DC_LockDisplay(HDC); VOID FASTCALL DC_UnlockDisplay(HDC); VOID FASTCALL IntGdiCopyFromSaveState(PDC, PDC, HDC); VOID FASTCALL IntGdiCopyToSaveState(PDC, PDC); +BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL); VOID FASTCALL DC_UpdateXforms(PDC dc); BOOL FASTCALL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest); BOOL FASTCALL DCU_SyncDcAttrtoUser(PDC); BOOL FASTCALL DCU_SynchDcAttrtoUser(HDC); +VOID FASTCALL DCU_SetDcUndeletable(HDC); VOID FASTCALL IntGetViewportExtEx(PDC dc, LPSIZE pt); VOID FASTCALL IntGetViewportOrgEx(PDC dc, LPPOINT pt); diff --git a/reactos/subsystems/win32/win32k/include/dce.h b/reactos/subsystems/win32/win32k/include/dce.h index d94e94ff56a..5bc091696b9 100644 --- a/reactos/subsystems/win32/win32k/include/dce.h +++ b/reactos/subsystems/win32/win32k/include/dce.h @@ -40,6 +40,7 @@ typedef struct tagDCE #define DCX_DCEEMPTY 0x00000800 #define DCX_DCEBUSY 0x00001000 #define DCX_DCEDIRTY 0x00002000 +#define DCX_DCOWNED 0x00008000 #define DCX_USESTYLE 0x00010000 #define DCX_KEEPCLIPRGN 0x00040000 #define DCX_NOCLIPCHILDREN 0x00080000 diff --git a/reactos/subsystems/win32/win32k/ntuser/windc.c b/reactos/subsystems/win32/win32k/ntuser/windc.c index a8f03a5de01..b39ec06487f 100644 --- a/reactos/subsystems/win32/win32k/ntuser/windc.c +++ b/reactos/subsystems/win32/win32k/ntuser/windc.c @@ -161,6 +161,8 @@ DceAllocDCE(PWINDOW_OBJECT Window OPTIONAL, DCE_TYPE Type) FirstDce = pDce; KeLeaveCriticalRegion(); + DCU_SetDcUndeletable(pDce->hDC); + if (Type == DCE_WINDOW_DC) //Window DCE have ownership. { // Process should already own it. pDce->pProcess = PsGetCurrentProcess(); @@ -403,8 +405,11 @@ UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags) PWINDOW Wnd = NULL; if (NULL == Window) - { - Flags &= ~DCX_USESTYLE; + { // Do the same as GetDC with a NULL. + Window = UserGetWindowObject(IntGetDesktopWindow()); + if (Window) Wnd = Window->Wnd; + else + Flags &= ~DCX_USESTYLE; } else Wnd = Window->Wnd; @@ -723,7 +728,8 @@ DceFreeDCE(PDCE pdce, BOOLEAN Force) } } - NtGdiDeleteObjectApp(pdce->hDC); + IntGdiDeleteDC(pdce->hDC, TRUE); + if (pdce->hClipRgn && ! (pdce->DCXFlags & DCX_KEEPCLIPRGN)) { NtGdiDeleteObject(pdce->hClipRgn); diff --git a/reactos/subsystems/win32/win32k/objects/dc.c b/reactos/subsystems/win32/win32k/objects/dc.c index 0f712df597d..02f5f379523 100644 --- a/reactos/subsystems/win32/win32k/objects/dc.c +++ b/reactos/subsystems/win32/win32k/objects/dc.c @@ -910,30 +910,33 @@ NtGdiOpenDCW( PUNICODE_STRING Device, } +// +// +// BOOL -STDCALL -NtGdiDeleteObjectApp(HANDLE DCHandle) +FASTCALL +IntGdiDeleteDC(HDC hDC, BOOL Force) { - PDC DCToDelete; + BOOL Ret = FALSE; + PDC DCToDelete = DC_LockDc(hDC); - if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC) - return NtGdiDeleteObject((HGDIOBJ) DCHandle); - - if(IsObjectDead((HGDIOBJ)DCHandle)) return TRUE; - - if (!GDIOBJ_OwnedByCurrentProcess(GdiHandleTable, DCHandle)) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - DCToDelete = DC_LockDc(DCHandle); if (DCToDelete == NULL) { SetLastWin32Error(ERROR_INVALID_HANDLE); return FALSE; } + if(!Force) + { + if (DCToDelete->DC_Flags & DC_FLAG_PERMANENT) + { + DPRINT1("No! You Naughty Application!\n"); +// if(!UserReleaseDC(NULL, hDC, FALSE)) Ret = FALSE; + } + DC_UnlockDc( DCToDelete ); + return Ret; + } + /* First delete all saved DCs */ while (DCToDelete->saveLevel) { @@ -995,10 +998,31 @@ NtGdiDeleteObjectApp(HANDLE DCHandle) } DC_UnlockDc( DCToDelete ); - DC_FreeDC ( DCHandle ); + DC_FreeDC ( hDC ); return TRUE; } +BOOL +STDCALL +NtGdiDeleteObjectApp(HANDLE DCHandle) +{ + + 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(GdiHandleTable, DCHandle)) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + return IntGdiDeleteDC(DCHandle, FALSE); +} + INT APIENTRY NtGdiDrawEscape( diff --git a/reactos/subsystems/win32/win32k/objects/dcutil.c b/reactos/subsystems/win32/win32k/objects/dcutil.c index 3dd30daee7d..2510b1f863a 100644 --- a/reactos/subsystems/win32/win32k/objects/dcutil.c +++ b/reactos/subsystems/win32/win32k/objects/dcutil.c @@ -257,3 +257,19 @@ NtGdiSetTextColor(HDC hDC, NtGdiSelectBrush(hDC, hBrush); return oldColor; } + +VOID +FASTCALL +DCU_SetDcUndeletable(HDC hDC) +{ + PDC dc = DC_LockDc(hDC); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return; + } + + dc->DC_Flags |= DC_FLAG_PERMANENT; + DC_UnlockDc( dc ); + return; +}