ReactOS  0.4.13-dev-39-g8b6696f
dcstate.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Win32k subsystem
4  * PURPOSE: Functions for saving and restoring dc states
5  * FILE: win32ss/gdi/ntgdi/dcstate.c
6  * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
7  */
8 
9 #include <win32k.h>
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 VOID
16 DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To)
17 {
18  DPRINT("DC_vCopyState(%p, %p)\n", pdcSrc->BaseObject.hHmgr, pdcDst->BaseObject.hHmgr);
19 
20  /* Copy full DC attribute */
21  *pdcDst->pdcattr = *pdcSrc->pdcattr;
22 
23  /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
24  /* The VisRectRegion field needs to be set to a valid state */
25 
26  /* Mark some fields as dirty */
27  pdcDst->pdcattr->ulDirty_ |= (DIRTY_FILL|DIRTY_LINE|DIRTY_TEXT|DIRTY_BACKGROUND|DIRTY_CHARSET|DC_ICM_NOT_CALIBRATED|DC_ICM_NOT_SET); // Note: Use if, To is FALSE....
28 
29  /* Copy DC level */
30  pdcDst->dclevel.pColorSpace = pdcSrc->dclevel.pColorSpace;
31  pdcDst->dclevel.laPath = pdcSrc->dclevel.laPath;
32  pdcDst->dclevel.ca = pdcSrc->dclevel.ca;
33  pdcDst->dclevel.mxWorldToDevice = pdcSrc->dclevel.mxWorldToDevice;
34  pdcDst->dclevel.mxDeviceToWorld = pdcSrc->dclevel.mxDeviceToWorld;
35  pdcDst->dclevel.mxWorldToPage = pdcSrc->dclevel.mxWorldToPage;
36  pdcDst->dclevel.efM11PtoD = pdcSrc->dclevel.efM11PtoD;
37  pdcDst->dclevel.efM22PtoD = pdcSrc->dclevel.efM22PtoD;
38  pdcDst->dclevel.sizl = pdcSrc->dclevel.sizl;
39  pdcDst->dclevel.hpal = pdcSrc->dclevel.hpal;
40 
41  /* Handle references here correctly */
42  DC_vSelectFillBrush(pdcDst, pdcSrc->dclevel.pbrFill);
43  DC_vSelectLineBrush(pdcDst, pdcSrc->dclevel.pbrLine);
44  DC_vSelectPalette(pdcDst, pdcSrc->dclevel.ppal);
45 
46  /* Dereference the old font, reference the new one */
47  if (pdcDst->dclevel.plfnt) LFONT_ShareUnlockFont(pdcDst->dclevel.plfnt);
48  GDIOBJ_vReferenceObjectByPointer(&pdcSrc->dclevel.plfnt->BaseObject);
49  pdcDst->dclevel.plfnt = pdcSrc->dclevel.plfnt;
50 
51  /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
52  if (!To)
53  {
54  IntGdiExtSelectClipRgn(pdcDst, pdcSrc->dclevel.prgnClip, RGN_COPY);
55  if (pdcDst->dclevel.prgnMeta)
56  {
57  REGION_Delete(pdcDst->dclevel.prgnMeta);
58  pdcDst->dclevel.prgnMeta = NULL;
59  }
60  if (pdcSrc->dclevel.prgnMeta)
61  {
62  pdcDst->dclevel.prgnMeta = IntSysCreateRectpRgn(0, 0, 0, 0);
63  IntGdiCombineRgn(pdcDst->dclevel.prgnMeta, pdcSrc->dclevel.prgnMeta, NULL, RGN_COPY);
64  }
65  pdcDst->fs |= DC_FLAG_DIRTY_RAO;
66  }
67 }
68 
69 
70 BOOL
73 {
74  PDC dc;
75  if (!hDC) return FALSE;
76  dc = DC_LockDc(hDC);
77  if (!dc) return FALSE;
78  // Clean the DC
79  if (defaultDCstate)
80  {
82  /* Update the brushes now, because they reference some objects (the DC palette)
83  * Which belong to the current process, and this DC might be used for another process
84  * after being cleaned up (for GetDC(0) for instance) */
89  }
90 
91  // Remove Path and reset flags.
92  if (dc->dclevel.hPath)
93  {
94  DPRINT("Clean DC Remove Path\n");
95  if (!PATH_Delete(dc->dclevel.hPath))
96  {
97  DPRINT1("Failed to remove Path\n");
98  }
99  dc->dclevel.hPath = 0;
100  dc->dclevel.flPath = 0;
101  }
102 
103  /* DC_vCopyState frees the Clip rgn and the Meta rgn. Take care of the other ones
104  * There is no need to clear prgnVis, as UserGetDC updates it immediately. */
105  if (dc->prgnRao)
106  REGION_Delete(dc->prgnRao);
107  if (dc->prgnAPI)
108  REGION_Delete(dc->prgnAPI);
109  dc->prgnRao = dc->prgnAPI = NULL;
110 
111  dc->fs |= DC_FLAG_DIRTY_RAO;
112 
113  DC_UnlockDc(dc);
114 
115  return TRUE;
116 }
117 
119 BOOL
120 APIENTRY
122  _In_ HDC hdc,
123  _In_ LPDEVMODEW pdm,
124  _Out_ PBOOL pbBanding,
125  _In_opt_ DRIVER_INFO_2W *pDriverInfo2,
126  _At_((PUMDHPDEV*)ppUMdhpdev, _Out_) PVOID ppUMdhpdev)
127 {
128  /* According to a comment in Windows SDK the size of the buffer for
129  pdm is (pdm->dmSize + pdm->dmDriverExtra) */
131  return FALSE;
132 }
133 
134 
135 VOID
136 NTAPI
138  IN PDC pdc,
139  INT iSaveLevel)
140 {
141  HDC hdcSave;
142  PDC pdcSave;
143 
144  NT_ASSERT(iSaveLevel > 0);
145  DPRINT("DC_vRestoreDC(%p, %ld)\n", pdc->BaseObject.hHmgr, iSaveLevel);
146 
147  /* Loop the save levels */
148  while (pdc->dclevel.lSaveDepth > iSaveLevel)
149  {
150  hdcSave = pdc->dclevel.hdcSave;
151  DPRINT("RestoreDC = %p\n", hdcSave);
152 
153  /* Set us as the owner */
154  if (!GreSetObjectOwner(hdcSave, GDI_OBJ_HMGR_POWNED))
155  {
156  /* Could not get ownership. That's bad! */
157  DPRINT1("Could not get ownership of saved DC (%p) for hdc %p!\n",
158  hdcSave, pdc->BaseObject.hHmgr);
159  NT_ASSERT(FALSE);
160  return;// FALSE;
161  }
162 
163  /* Lock the saved dc */
164  pdcSave = DC_LockDc(hdcSave);
165  if (!pdcSave)
166  {
167  /* WTF? Internal error! */
168  DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
169  hdcSave, pdc->BaseObject.hHmgr);
170  NT_ASSERT(FALSE);
171  return;// FALSE;
172  }
173 
174  /* Remove the saved dc from the queue */
175  pdc->dclevel.hdcSave = pdcSave->dclevel.hdcSave;
176 
177  /* Decrement save level */
178  pdc->dclevel.lSaveDepth--;
179 
180  /* Is this the state we want? */
181  if (pdc->dclevel.lSaveDepth == iSaveLevel)
182  {
183  /* Copy the state back */
184  DC_vCopyState(pdcSave, pdc, FALSE);
185 
186  /* Only memory DC's change their surface */
187  if (pdc->dctype == DCTYPE_MEMORY)
188  DC_vSelectSurface(pdc, pdcSave->dclevel.pSurface);
189 
190  if (pdcSave->dclevel.hPath)
191  {
192  PATH_RestorePath( pdc, pdcSave );
193  }
194  }
195 
196  /* Prevent save dc from being restored */
197  pdcSave->dclevel.lSaveDepth = 1;
198 
199  /* Unlock it */
200  DC_UnlockDc(pdcSave);
201  /* Delete the saved dc */
202  GreDeleteObject(hdcSave);
203  }
204 
205  DPRINT("Leave DC_vRestoreDC()\n");
206 }
207 
208 
209 
210 BOOL
211 APIENTRY
213  HDC hdc,
214  INT iSaveLevel)
215 {
216  PDC pdc;
217 
218  DPRINT("NtGdiRestoreDC(%p, %d)\n", hdc, iSaveLevel);
219 
220  /* Lock the original DC */
221  pdc = DC_LockDc(hdc);
222  if (!pdc)
223  {
225  return FALSE;
226  }
227 
228  ASSERT(pdc->dclevel.lSaveDepth > 0);
229 
230  /* Negative values are relative to the stack top */
231  if (iSaveLevel < 0)
232  iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
233 
234  /* Check if we have a valid instance */
235  if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
236  {
237  DPRINT("Illegal save level, requested: %ld, current: %ld\n",
238  iSaveLevel, pdc->dclevel.lSaveDepth);
239  DC_UnlockDc(pdc);
241  return FALSE;
242  }
243 
244  /* Call the internal function */
245  DC_vRestoreDC(pdc, iSaveLevel);
246 
247  DC_UnlockDc(pdc);
248 
249  DPRINT("Leave NtGdiRestoreDC\n");
250  return TRUE;
251 }
252 
253 
254 INT
255 APIENTRY
257  HDC hDC)
258 {
259  HDC hdcSave;
260  PDC pdc, pdcSave;
261  INT lSaveDepth;
262 
263  DPRINT("NtGdiSaveDC(%p)\n", hDC);
264 
265  /* Lock the original dc */
266  pdc = DC_LockDc(hDC);
267  if (pdc == NULL)
268  {
269  DPRINT("Could not lock DC\n");
271  return 0;
272  }
273 
274  /* Allocate a new dc */
276  if (pdcSave == NULL)
277  {
278  DPRINT("Could not allocate a new DC\n");
279  DC_UnlockDc(pdc);
280  return 0;
281  }
282  hdcSave = pdcSave->BaseObject.hHmgr;
283 
284  InterlockedIncrement(&pdc->ppdev->cPdevRefs);
285  DC_vInitDc(pdcSave, DCTYPE_MEMORY, pdc->ppdev);
286 
287  /* Handle references here correctly */
288  //pdcSrc->dclevel.pSurface = NULL;
289  //pdcSrc->dclevel.pbrFill = NULL;
290  //pdcSrc->dclevel.pbrLine = NULL;
291  //pdcSrc->dclevel.ppal = NULL;
292 
293  /* Make it a kernel handle
294  (FIXME: Windows handles this differently, see Wiki) */
295  GDIOBJ_vSetObjectOwner(&pdcSave->BaseObject, GDI_OBJ_HMGR_PUBLIC);
296 
297  /* Copy the current state */
298  DC_vCopyState(pdc, pdcSave, FALSE);
299 
300  /* Only memory DC's change their surface */
301  if (pdc->dctype == DCTYPE_MEMORY)
302  DC_vSelectSurface(pdcSave, pdc->dclevel.pSurface);
303 
304  /* Copy path */
305  if (pdc->dclevel.hPath)
306  {
307  PATH_SavePath( pdcSave, pdc );
308  }
309  pdcSave->dclevel.flPath = pdc->dclevel.flPath | DCPATH_SAVESTATE;
310 
311  /* Set new dc as save dc */
312  pdcSave->dclevel.hdcSave = pdc->dclevel.hdcSave;
313  pdc->dclevel.hdcSave = hdcSave;
314 
315  /* Increase save depth, return old value */
316  lSaveDepth = pdc->dclevel.lSaveDepth++;
317 
318  /* Cleanup and return */
319  DC_UnlockDc(pdcSave);
320  DC_UnlockDc(pdc);
321 
322  DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth, hdcSave);
323  return lSaveDepth;
324 }
325 
326 /* EOF */
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define IN
Definition: typedefs.h:38
BOOL APIENTRY NtGdiRestoreDC(HDC hdc, INT iSaveLevel)
Definition: dcstate.c:212
BOOL NTAPI GreSetObjectOwner(HGDIOBJ hobj, ULONG ulOwner)
Definition: gdiobj.c:1250
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1153
#define TRUE
Definition: types.h:120
VOID FASTCALL DC_vUpdateLineBrush(PDC pdc)
Definition: dcobjs.c:62
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:219
FORCEINLINE VOID DC_vSelectSurface(PDC pdc, PSURFACE psurfNew)
Definition: dc.h:247
BOOL PATH_RestorePath(DC *dst, DC *src)
Definition: path.c:210
VOID FASTCALL DC_vUpdateBackgroundBrush(PDC pdc)
Definition: dcobjs.c:126
FORCEINLINE VOID DC_vSelectPalette(PDC pdc, PPALETTE ppal)
Definition: dc.h:286
#define DIRTY_CHARSET
Definition: ntgdihdl.h:149
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
#define LFONT_ShareUnlockFont(plfnt)
Definition: text.h:78
static HDC
Definition: imagelist.c:92
BOOL FASTCALL IntGdiCleanDC(HDC hDC)
Definition: dcstate.c:72
HDC dc
Definition: cylfrac.c:34
int FASTCALL IntGdiExtSelectClipRgn(PDC dc, PREGION prgn, int fnMode)
Definition: cliprgn.c:68
BOOL PATH_SavePath(DC *dst, DC *src)
Definition: path.c:188
FORCEINLINE VOID DC_vSelectFillBrush(PDC pdc, PBRUSH pbrFill)
Definition: dc.h:262
#define FASTCALL
Definition: nt_native.h:50
int32_t INT
Definition: typedefs.h:56
#define _In_opt_
Definition: no_sal2.h:213
#define DIRTY_BACKGROUND
Definition: ntgdihdl.h:148
__kernel_entry BOOL APIENTRY NtGdiResetDC(_In_ HDC hdc, _In_ LPDEVMODEW pdm, _Out_ PBOOL pbBanding, _In_opt_ DRIVER_INFO_2W *pDriverInfo2, _At_((PUMDHPDEV *) ppUMdhpdev, _Out_) PVOID ppUMdhpdev)
Definition: dcstate.c:121
PREGION FASTCALL IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
Definition: region.c:2429
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
#define _Out_
Definition: no_sal2.h:323
#define _At_(target, annos)
Definition: no_sal2.h:11
void DPRINT(...)
Definition: polytest.cpp:61
BOOL * PBOOL
Definition: windef.h:161
VOID NTAPI DC_vInitDc(PDC pdc, DCTYPE dctype, PPDEVOBJ ppdev)
Definition: dclife.c:124
INT FASTCALL IntGdiCombineRgn(PREGION prgnDest, PREGION prgnSrc1, PREGION prgnSrc2, INT iCombineMode)
Definition: region.c:2509
VOID FASTCALL DC_vUpdateTextBrush(PDC pdc)
Definition: dcobjs.c:108
Definition: polytest.cpp:40
PDC defaultDCstate
Definition: device.c:14
#define __kernel_entry
Definition: specstrings.h:50
PDC NTAPI DC_AllocDcWithHandle(GDILOOBJTYPE eDcObjType)
Definition: dclife.c:69
#define DC_FLAG_DIRTY_RAO
Definition: ntgdihdl.h:132
VOID NTAPI DC_vRestoreDC(IN PDC pdc, INT iSaveLevel)
Definition: dcstate.c:137
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define DIRTY_TEXT
Definition: ntgdihdl.h:147
#define DC_ICM_NOT_CALIBRATED
Definition: ntgdihdl.h:162
#define DIRTY_FILL
Definition: ntgdihdl.h:145
HDC hdc
Definition: main.c:9
INT APIENTRY NtGdiSaveDC(HDC hDC)
Definition: dcstate.c:256
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
#define RGN_COPY
Definition: wingdi.h:356
#define _In_
Definition: no_sal2.h:204
static HDC hDC
Definition: 3dtext.c:33
#define InterlockedIncrement
Definition: armddk.h:53
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:237
#define GDI_OBJ_HMGR_PUBLIC
Definition: ntgdihdl.h:116
VOID NTAPI GDIOBJ_vReferenceObjectByPointer(POBJ pobj)
Definition: gdiobj.c:729
#define DPRINT1
Definition: precomp.h:8
#define UNIMPLEMENTED
Definition: debug.h:114
#define DIRTY_LINE
Definition: ntgdihdl.h:146
VOID NTAPI GDIOBJ_vSetObjectOwner(POBJ pobj, ULONG ulNewOwner)
Definition: gdiobj.c:960
VOID FASTCALL DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To)
Definition: dcstate.c:16
#define DC_ICM_NOT_SET
Definition: ntgdihdl.h:165
VOID FASTCALL REGION_Delete(PREGION pRgn)
Definition: region.c:2471
FORCEINLINE VOID DC_vSelectLineBrush(PDC pdc, PBRUSH pbrLine)
Definition: dc.h:274
BOOL FASTCALL PATH_Delete(HPATH hPath)
Definition: path.c:91
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
#define APIENTRY
Definition: api.h:79
VOID FASTCALL DC_vUpdateFillBrush(PDC pdc)
Definition: dcobjs.c:16
#define NT_ASSERT
Definition: rtlfuncs.h:3312