Merge aicom-network-branch (without NDIS changes for now)
[reactos.git] / reactos / 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 KeEnterCriticalRegion();
163 {
164 INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hDC);
165 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
166
167 NewMem = AllocateDcAttr();
168
169 // FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData
170
171 if (NewMem)
172 {
173 RtlZeroMemory(NewMem, sizeof(DC_ATTR));
174 Entry->UserData = NewMem;
175 DPRINT("DC_ATTR allocated! 0x%x\n",NewMem);
176 }
177 else
178 {
179 DPRINT1("DC_ATTR not allocated!\n");
180 }
181 }
182 KeLeaveCriticalRegion();
183 pDC = DC_LockDc(hDC);
184 ASSERT(pDC->pdcattr == &pDC->dcattr);
185 if (NewMem)
186 {
187 pDC->pdcattr = NewMem; // Store pointer
188 }
189 DC_UnlockDc(pDC);
190 }
191
192 VOID
193 FASTCALL
194 DC_FreeDcAttr(HDC DCToFree )
195 {
196 PDC pDC = DC_LockDc(DCToFree);
197 if (pDC->pdcattr == &pDC->dcattr) return; // Internal DC object!
198 pDC->pdcattr = &pDC->dcattr;
199 DC_UnlockDc(pDC);
200
201 KeEnterCriticalRegion();
202 {
203 INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)DCToFree);
204 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
205 if (Entry->UserData)
206 {
207 FreeDcAttr(Entry->UserData);
208 Entry->UserData = NULL;
209 }
210 }
211 KeLeaveCriticalRegion();
212 }
213
214
215 static
216 VOID
217 CopytoUserDcAttr(PDC dc, PDC_ATTR pdcattr)
218 {
219 NTSTATUS Status = STATUS_SUCCESS;
220 dc->dcattr.mxWorldToDevice = dc->dclevel.mxWorldToDevice;
221 dc->dcattr.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld;
222 dc->dcattr.mxWorldToPage = dc->dclevel.mxWorldToPage;
223
224 _SEH2_TRY
225 {
226 ProbeForWrite( pdcattr,
227 sizeof(DC_ATTR),
228 1);
229 RtlCopyMemory( pdcattr,
230 &dc->dcattr,
231 sizeof(DC_ATTR));
232 }
233 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
234 {
235 Status = _SEH2_GetExceptionCode();
236 ASSERT(FALSE);
237 }
238 _SEH2_END;
239 }
240
241 // FIXME: wtf? 2 functions, where one has a typo in the name????
242 BOOL
243 FASTCALL
244 DCU_SyncDcAttrtoUser(PDC dc)
245 {
246 PDC_ATTR pdcattr = dc->pdcattr;
247
248 if (pdcattr == &dc->dcattr) return TRUE; // No need to copy self.
249 ASSERT(pdcattr);
250 CopytoUserDcAttr( dc, pdcattr);
251 return TRUE;
252 }
253 // LOL! DCU_ Sync hDc Attr to User,,, need it speeled out for you?
254 BOOL
255 FASTCALL
256 DCU_SynchDcAttrtoUser(HDC hDC)
257 {
258 BOOL Ret;
259 PDC pDC = DC_LockDc ( hDC );
260 if (!pDC) return FALSE;
261 Ret = DCU_SyncDcAttrtoUser(pDC);
262 DC_UnlockDc( pDC );
263 return Ret;
264 }
265