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)
15 #define GDIDCATTRFREE 8
17 typedef struct _GDI_DC_ATTR_FREELIST
21 PVOID AttrList
[GDIDCATTRFREE
];
22 } GDI_DC_ATTR_FREELIST
, *PGDI_DC_ATTR_FREELIST
;
24 typedef struct _GDI_DC_ATTR_ENTRY
26 DC_ATTR Attr
[GDIDCATTRFREE
];
27 } GDI_DC_ATTR_ENTRY
, *PGDI_DC_ATTR_ENTRY
;
37 PGDI_DC_ATTR_FREELIST pGdiDcAttrFreeList
;
38 PGDI_DC_ATTR_ENTRY pGdiDcAttrEntry
;
41 pti
= PsGetCurrentThreadWin32Thread();
44 pDc_Attr
= pti
->pgdiDcattr
; // Get the free one.
45 pti
->pgdiDcattr
= NULL
;
49 ppi
= PsGetCurrentProcessWin32Process();
51 if (!ppi
->pDCAttrList
) // If set point is null, allocate new group.
53 pGdiDcAttrEntry
= EngAllocUserMem(sizeof(GDI_DC_ATTR_ENTRY
), 0);
57 DPRINT1("DcAttr Failed User Allocation!\n");
61 DPRINT("AllocDcAttr User 0x%x\n",pGdiDcAttrEntry
);
63 pGdiDcAttrFreeList
= ExAllocatePoolWithTag( PagedPool
,
64 sizeof(GDI_DC_ATTR_FREELIST
),
66 if ( !pGdiDcAttrFreeList
)
68 EngFreeUserMem(pGdiDcAttrEntry
);
72 RtlZeroMemory(pGdiDcAttrFreeList
, sizeof(GDI_DC_ATTR_FREELIST
));
74 DPRINT("AllocDcAttr Ex 0x%x\n",pGdiDcAttrFreeList
);
76 InsertHeadList( &ppi
->GDIDcAttrFreeList
, &pGdiDcAttrFreeList
->Entry
);
78 pGdiDcAttrFreeList
->nEntries
= GDIDCATTRFREE
;
79 // Start at the bottom up and set end of free list point.
80 ppi
->pDCAttrList
= &pGdiDcAttrEntry
->Attr
[GDIDCATTRFREE
-1];
81 // Build the free attr list.
82 for ( i
= 0; i
< GDIDCATTRFREE
; i
++)
84 pGdiDcAttrFreeList
->AttrList
[i
] = &pGdiDcAttrEntry
->Attr
[i
];
88 pDc_Attr
= ppi
->pDCAttrList
;
89 pGdiDcAttrFreeList
= (PGDI_DC_ATTR_FREELIST
)ppi
->GDIDcAttrFreeList
.Flink
;
91 // Free the list when it is full!
92 if ( pGdiDcAttrFreeList
->nEntries
-- == 1)
93 { // No more free entries, so yank the list.
94 RemoveEntryList( &pGdiDcAttrFreeList
->Entry
);
96 ExFreePoolWithTag( pGdiDcAttrFreeList
, GDITAG_DC_FREELIST
);
98 if ( IsListEmpty( &ppi
->GDIDcAttrFreeList
) )
100 ppi
->pDCAttrList
= NULL
;
104 pGdiDcAttrFreeList
= (PGDI_DC_ATTR_FREELIST
)ppi
->GDIDcAttrFreeList
.Flink
;
107 ppi
->pDCAttrList
= pGdiDcAttrFreeList
->AttrList
[pGdiDcAttrFreeList
->nEntries
-1];
114 FreeDcAttr(PDC_ATTR pDc_Attr
)
118 PGDI_DC_ATTR_FREELIST pGdiDcAttrFreeList
;
120 pti
= PsGetCurrentThreadWin32Thread();
124 if (!pti
->pgdiDcattr
)
125 { // If it is null, just cache it for the next time.
126 pti
->pgdiDcattr
= pDc_Attr
;
130 ppi
= PsGetCurrentProcessWin32Process();
132 pGdiDcAttrFreeList
= (PGDI_DC_ATTR_FREELIST
)ppi
->GDIDcAttrFreeList
.Flink
;
134 // We add to the list of free entries, so this will grows!
135 if ( IsListEmpty(&ppi
->GDIDcAttrFreeList
) ||
136 pGdiDcAttrFreeList
->nEntries
== GDIDCATTRFREE
)
138 pGdiDcAttrFreeList
= ExAllocatePoolWithTag( PagedPool
,
139 sizeof(GDI_DC_ATTR_FREELIST
),
141 if ( !pGdiDcAttrFreeList
)
145 InsertHeadList( &ppi
->GDIDcAttrFreeList
, &pGdiDcAttrFreeList
->Entry
);
146 pGdiDcAttrFreeList
->nEntries
= 0;
148 // Up count, save the entry and set end of free list point.
149 ++pGdiDcAttrFreeList
->nEntries
; // Top Down...
150 pGdiDcAttrFreeList
->AttrList
[pGdiDcAttrFreeList
->nEntries
-1] = pDc_Attr
;
151 ppi
->pDCAttrList
= pDc_Attr
;
158 DC_AllocateDcAttr(HDC hDC
)
162 HANDLE Pid
= NtCurrentProcess();
163 ULONG MemSize
= sizeof(DC_ATTR
); //PAGE_SIZE it will allocate that size
165 NTSTATUS Status
= ZwAllocateVirtualMemory(Pid
,
169 MEM_COMMIT
|MEM_RESERVE
,
171 KeEnterCriticalRegion();
173 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)hDC
);
174 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
175 // FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData
176 if (NT_SUCCESS(Status
))
178 RtlZeroMemory(NewMem
, MemSize
);
179 Entry
->UserData
= NewMem
;
180 DPRINT("DC_ATTR allocated! 0x%x\n",NewMem
);
184 DPRINT("DC_ATTR not allocated!\n");
187 KeLeaveCriticalRegion();
188 pDC
= DC_LockDc(hDC
);
189 ASSERT(pDC
->pdcattr
== &pDC
->dcattr
);
192 pDC
->pdcattr
= NewMem
; // Store pointer
199 DC_FreeDcAttr(HDC DCToFree
)
201 HANDLE Pid
= NtCurrentProcess();
202 PDC pDC
= DC_LockDc(DCToFree
);
203 if (pDC
->pdcattr
== &pDC
->dcattr
) return; // Internal DC object!
204 pDC
->pdcattr
= &pDC
->dcattr
;
207 KeEnterCriticalRegion();
209 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)DCToFree
);
210 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
213 ULONG MemSize
= sizeof(DC_ATTR
); //PAGE_SIZE;
214 NTSTATUS Status
= ZwFreeVirtualMemory(Pid
,
218 if (NT_SUCCESS(Status
))
220 DPRINT("DC_FreeDC DC_ATTR 0x%x\n", Entry
->UserData
);
221 Entry
->UserData
= NULL
;
225 KeLeaveCriticalRegion();
231 CopytoUserDcAttr(PDC dc
, PDC_ATTR pdcattr
)
233 NTSTATUS Status
= STATUS_SUCCESS
;
234 dc
->dcattr
.mxWorldToDevice
= dc
->dclevel
.mxWorldToDevice
;
235 dc
->dcattr
.mxDeviceToWorld
= dc
->dclevel
.mxDeviceToWorld
;
236 dc
->dcattr
.mxWorldToPage
= dc
->dclevel
.mxWorldToPage
;
240 ProbeForWrite( pdcattr
,
243 RtlCopyMemory( pdcattr
,
247 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
249 Status
= _SEH2_GetExceptionCode();
255 // FIXME: wtf? 2 functions, where one has a typo in the name????
258 DCU_SyncDcAttrtoUser(PDC dc
)
260 PDC_ATTR pdcattr
= dc
->pdcattr
;
262 if (pdcattr
== &dc
->dcattr
) return TRUE
; // No need to copy self.
264 CopytoUserDcAttr( dc
, pdcattr
);
270 DCU_SynchDcAttrtoUser(HDC hDC
)
273 PDC pDC
= DC_LockDc ( hDC
);
274 if (!pDC
) return FALSE
;
275 Ret
= DCU_SyncDcAttrtoUser(pDC
);