562d75473d6b9b66d2a4343945e4c7b54af3dc62
[reactos.git] / subsystems / win32 / win32k / objects / dcattr.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for creation and destruction of DCs
5 * FILE: subsystem/win32/win32k/objects/dcattr.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
7 */
8
9 #include <w32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 #define GDIDCATTRFREE 8
15
16 typedef struct _GDI_DC_ATTR_FREELIST
17 {
18 LIST_ENTRY Entry;
19 DWORD nEntries;
20 PVOID AttrList[GDIDCATTRFREE];
21 } GDI_DC_ATTR_FREELIST, *PGDI_DC_ATTR_FREELIST;
22
23 typedef struct _GDI_DC_ATTR_ENTRY
24 {
25 DC_ATTR Attr[GDIDCATTRFREE];
26 } GDI_DC_ATTR_ENTRY, *PGDI_DC_ATTR_ENTRY;
27
28
29 PDC_ATTR
30 FASTCALL
31 AllocateDcAttr(VOID)
32 {
33 PTHREADINFO pti;
34 PPROCESSINFO ppi;
35 PDC_ATTR pDc_Attr;
36 PGDI_DC_ATTR_FREELIST pGdiDcAttrFreeList;
37 PGDI_DC_ATTR_ENTRY pGdiDcAttrEntry;
38 int i;
39
40 pti = PsGetCurrentThreadWin32Thread();
41 if (pti->pgdiDcattr)
42 {
43 pDc_Attr = pti->pgdiDcattr; // Get the free one.
44 pti->pgdiDcattr = NULL;
45 return pDc_Attr;
46 }
47
48 ppi = PsGetCurrentProcessWin32Process();
49
50 if (!ppi->pDCAttrList) // If set point is null, allocate new group.
51 {
52 pGdiDcAttrEntry = EngAllocUserMem(sizeof(GDI_DC_ATTR_ENTRY), 0);
53
54 if (!pGdiDcAttrEntry)
55 {
56 DPRINT1("DcAttr Failed User Allocation!\n");
57 return NULL;
58 }
59
60 DPRINT("AllocDcAttr User 0x%x\n",pGdiDcAttrEntry);
61
62 pGdiDcAttrFreeList = ExAllocatePoolWithTag( PagedPool,
63 sizeof(GDI_DC_ATTR_FREELIST),
64 GDITAG_DC_FREELIST);
65 if ( !pGdiDcAttrFreeList )
66 {
67 EngFreeUserMem(pGdiDcAttrEntry);
68 return NULL;
69 }
70
71 RtlZeroMemory(pGdiDcAttrFreeList, sizeof(GDI_DC_ATTR_FREELIST));
72
73 DPRINT("AllocDcAttr Ex 0x%x\n",pGdiDcAttrFreeList);
74
75 InsertHeadList( &ppi->GDIDcAttrFreeList, &pGdiDcAttrFreeList->Entry);
76
77 pGdiDcAttrFreeList->nEntries = GDIDCATTRFREE;
78 // Start at the bottom up and set end of free list point.
79 ppi->pDCAttrList = &pGdiDcAttrEntry->Attr[GDIDCATTRFREE-1];
80 // Build the free attr list.
81 for ( i = 0; i < GDIDCATTRFREE; i++)
82 {
83 pGdiDcAttrFreeList->AttrList[i] = &pGdiDcAttrEntry->Attr[i];
84 }
85 }
86
87 pDc_Attr = ppi->pDCAttrList;
88 pGdiDcAttrFreeList = (PGDI_DC_ATTR_FREELIST)ppi->GDIDcAttrFreeList.Flink;
89
90 // Free the list when it is full!
91 if ( pGdiDcAttrFreeList->nEntries-- == 1)
92 { // No more free entries, so yank the list.
93 RemoveEntryList( &pGdiDcAttrFreeList->Entry );
94
95 ExFreePoolWithTag( pGdiDcAttrFreeList, GDITAG_DC_FREELIST );
96
97 if ( IsListEmpty( &ppi->GDIDcAttrFreeList ) )
98 {
99 ppi->pDCAttrList = NULL;
100 return pDc_Attr;
101 }
102
103 pGdiDcAttrFreeList = (PGDI_DC_ATTR_FREELIST)ppi->GDIDcAttrFreeList.Flink;
104 }
105
106 ppi->pDCAttrList = pGdiDcAttrFreeList->AttrList[pGdiDcAttrFreeList->nEntries-1];
107
108 return pDc_Attr;
109 }
110
111 VOID
112 FASTCALL
113 FreeDcAttr(PDC_ATTR pDc_Attr)
114 {
115 PTHREADINFO pti;
116 PPROCESSINFO ppi;
117 PGDI_DC_ATTR_FREELIST pGdiDcAttrFreeList;
118
119 pti = PsGetCurrentThreadWin32Thread();
120
121 if (!pti) return;
122
123 if (!pti->pgdiDcattr)
124 { // If it is null, just cache it for the next time.
125 pti->pgdiDcattr = pDc_Attr;
126 return;
127 }
128
129 ppi = PsGetCurrentProcessWin32Process();
130
131 pGdiDcAttrFreeList = (PGDI_DC_ATTR_FREELIST)ppi->GDIDcAttrFreeList.Flink;
132
133 // We add to the list of free entries, so this will grows!
134 if ( IsListEmpty(&ppi->GDIDcAttrFreeList) ||
135 pGdiDcAttrFreeList->nEntries == GDIDCATTRFREE )
136 {
137 pGdiDcAttrFreeList = ExAllocatePoolWithTag( PagedPool,
138 sizeof(GDI_DC_ATTR_FREELIST),
139 GDITAG_DC_FREELIST);
140 if ( !pGdiDcAttrFreeList )
141 {
142 return;
143 }
144 InsertHeadList( &ppi->GDIDcAttrFreeList, &pGdiDcAttrFreeList->Entry);
145 pGdiDcAttrFreeList->nEntries = 0;
146 }
147 // Up count, save the entry and set end of free list point.
148 ++pGdiDcAttrFreeList->nEntries; // Top Down...
149 pGdiDcAttrFreeList->AttrList[pGdiDcAttrFreeList->nEntries-1] = pDc_Attr;
150 ppi->pDCAttrList = pDc_Attr;
151
152 return;
153 }
154
155 VOID
156 FASTCALL
157 DC_AllocateDcAttr(HDC hDC)
158 {
159 PVOID NewMem = NULL;
160 PDC pDC;
161
162 {
163 INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hDC);
164 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
165
166 NewMem = AllocateDcAttr();
167
168 // FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData
169
170 if (NewMem)
171 {
172 RtlZeroMemory(NewMem, sizeof(DC_ATTR));
173 Entry->UserData = NewMem;
174 DPRINT("DC_ATTR allocated! 0x%x\n",NewMem);
175 }
176 else
177 {
178 DPRINT1("DC_ATTR not allocated!\n");
179 }
180 }
181 pDC = DC_LockDc(hDC);
182 ASSERT(pDC->pdcattr == &pDC->dcattr);
183 if (NewMem)
184 {
185 pDC->pdcattr = NewMem; // Store pointer
186 }
187 DC_UnlockDc(pDC);
188 }
189
190 VOID
191 FASTCALL
192 DC_FreeDcAttr(HDC DCToFree )
193 {
194 PDC pDC = DC_LockDc(DCToFree);
195 if (pDC->pdcattr == &pDC->dcattr) return; // Internal DC object!
196 pDC->pdcattr = &pDC->dcattr;
197 DC_UnlockDc(pDC);
198
199 {
200 INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)DCToFree);
201 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
202 if (Entry->UserData)
203 {
204 FreeDcAttr(Entry->UserData);
205 Entry->UserData = NULL;
206 }
207 }
208 }
209
210
211 static
212 VOID
213 CopytoUserDcAttr(PDC dc, PDC_ATTR pdcattr)
214 {
215 NTSTATUS Status = STATUS_SUCCESS;
216 dc->dcattr.mxWorldToDevice = dc->dclevel.mxWorldToDevice;
217 dc->dcattr.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld;
218 dc->dcattr.mxWorldToPage = dc->dclevel.mxWorldToPage;
219
220 _SEH2_TRY
221 {
222 ProbeForWrite( pdcattr,
223 sizeof(DC_ATTR),
224 1);
225 RtlCopyMemory( pdcattr,
226 &dc->dcattr,
227 sizeof(DC_ATTR));
228 }
229 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
230 {
231 Status = _SEH2_GetExceptionCode();
232 ASSERT(FALSE);
233 }
234 _SEH2_END;
235 }
236
237 // FIXME: wtf? 2 functions, where one has a typo in the name????
238 BOOL
239 FASTCALL
240 DCU_SyncDcAttrtoUser(PDC dc)
241 {
242 PDC_ATTR pdcattr = dc->pdcattr;
243
244 if (pdcattr == &dc->dcattr) return TRUE; // No need to copy self.
245 ASSERT(pdcattr);
246 CopytoUserDcAttr( dc, pdcattr);
247 return TRUE;
248 }
249 // LOL! DCU_ Sync hDc Attr to User,,, need it speeled out for you?
250 BOOL
251 FASTCALL
252 DCU_SynchDcAttrtoUser(HDC hDC)
253 {
254 BOOL Ret;
255 PDC pDC = DC_LockDc ( hDC );
256 if (!pDC) return FALSE;
257 Ret = DCU_SyncDcAttrtoUser(pDC);
258 DC_UnlockDc( pDC );
259 return Ret;
260 }
261