[BRANCHES]
[reactos.git] / reactos / win32ss / gdi / gdi32 / misc / misc.c
1 /*
2 * ReactOS GDI lib
3 * Copyright (C) 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * PROJECT: ReactOS gdi32.dll
21 * FILE: dll/win32/gdi32/misc/misc.c
22 * PURPOSE: Miscellaneous functions
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
24 * UPDATE HISTORY:
25 * 2004/09/04 Created
26 */
27
28 #include <precomp.h>
29
30 #define NDEBUG
31 #include <debug.h>
32
33 PGDI_TABLE_ENTRY GdiHandleTable = NULL;
34 PGDI_SHARED_HANDLE_TABLE GdiSharedHandleTable = NULL;
35 HANDLE CurrentProcessId = NULL;
36 DWORD GDI_BatchLimit = 1;
37
38
39 BOOL
40 WINAPI
41 GdiAlphaBlend(
42 HDC hDCDst,
43 int DstX,
44 int DstY,
45 int DstCx,
46 int DstCy,
47 HDC hDCSrc,
48 int SrcX,
49 int SrcY,
50 int SrcCx,
51 int SrcCy,
52 BLENDFUNCTION BlendFunction
53 )
54 {
55 if ( hDCSrc == NULL ) return FALSE;
56
57 if (GDI_HANDLE_GET_TYPE(hDCSrc) == GDI_OBJECT_TYPE_METADC) return FALSE;
58
59 return NtGdiAlphaBlend(
60 hDCDst,
61 DstX,
62 DstY,
63 DstCx,
64 DstCy,
65 hDCSrc,
66 SrcX,
67 SrcY,
68 SrcCx,
69 SrcCy,
70 BlendFunction,
71 0 );
72 }
73
74 /*
75 * @implemented
76 */
77 HGDIOBJ
78 WINAPI
79 GdiFixUpHandle(HGDIOBJ hGdiObj)
80 {
81 PGDI_TABLE_ENTRY Entry;
82
83 if (((ULONG_PTR)(hGdiObj)) & GDI_HANDLE_UPPER_MASK )
84 {
85 return hGdiObj;
86 }
87
88 /* FIXME is this right ?? */
89
90 Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
91
92 /* Rebuild handle for Object */
93 return hGdiObj = (HGDIOBJ)(((LONG_PTR)(hGdiObj)) | (Entry->Type << GDI_ENTRY_UPPER_SHIFT));
94 }
95
96 /*
97 * @implemented
98 */
99 PVOID
100 WINAPI
101 GdiQueryTable(VOID)
102 {
103 return (PVOID)GdiHandleTable;
104 }
105
106 BOOL GdiIsHandleValid(HGDIOBJ hGdiObj)
107 {
108 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
109 // We are only looking for TYPE not the rest here, and why is FullUnique filled up with CRAP!?
110 // DPRINT1("FullUnique -> %x\n", Entry->FullUnique);
111 if((Entry->Type & GDI_ENTRY_BASETYPE_MASK) != 0 &&
112 ( (Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK ) ==
113 GDI_HANDLE_GET_TYPE(hGdiObj))
114 {
115 HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
116 if(pid == NULL || pid == CurrentProcessId)
117 {
118 return TRUE;
119 }
120 }
121 return FALSE;
122 }
123
124 BOOL GdiGetHandleUserData(HGDIOBJ hGdiObj, DWORD ObjectType, PVOID *UserData)
125 {
126 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
127
128 /* Check if twe have the correct type */
129 if (GDI_HANDLE_GET_TYPE(hGdiObj) != ObjectType ||
130 ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK) != ObjectType ||
131 (Entry->Type & GDI_ENTRY_BASETYPE_MASK) != (ObjectType & GDI_ENTRY_BASETYPE_MASK))
132 {
133 return FALSE;
134 }
135
136 /* Check if we are the owner */
137 if ((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) != CurrentProcessId)
138 {
139 return FALSE;
140 }
141
142 *UserData = Entry->UserData;
143 return TRUE;
144 }
145
146 PLDC
147 FASTCALL
148 GdiGetLDC(HDC hDC)
149 {
150 PDC_ATTR Dc_Attr;
151 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX((HGDIOBJ) hDC);
152 HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
153 // Don't check the mask, just the object type.
154 if ( Entry->ObjectType == GDIObjType_DC_TYPE &&
155 (pid == NULL || pid == CurrentProcessId) )
156 {
157 BOOL Result = TRUE;
158 if (Entry->UserData)
159 {
160 volatile CHAR *Current = (volatile CHAR*)Entry->UserData;
161 _SEH2_TRY
162 {
163 *Current = *Current;
164 }
165 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
166 {
167 Result = FALSE;
168 }
169 _SEH2_END
170 }
171 else
172 Result = FALSE;
173
174 if (Result)
175 {
176 Dc_Attr = (PDC_ATTR)Entry->UserData;
177 return Dc_Attr->pvLDC;
178 }
179 }
180 return NULL;
181 }
182
183 VOID GdiSAPCallback(PLDC pldc)
184 {
185 DWORD Time, NewTime = GetTickCount();
186
187 Time = NewTime - pldc->CallBackTick;
188
189 if ( Time < SAPCALLBACKDELAY) return;
190
191 pldc->CallBackTick = NewTime;
192
193 if ( !pldc->pAbortProc(pldc->hDC, 0) )
194 {
195 CancelDC(pldc->hDC);
196 AbortDoc(pldc->hDC);
197 }
198 }
199
200 /*
201 * @implemented
202 */
203 DWORD
204 WINAPI
205 GdiSetBatchLimit(DWORD Limit)
206 {
207 DWORD OldLimit = GDI_BatchLimit;
208
209 if ( (!Limit) ||
210 (Limit >= GDI_BATCH_LIMIT))
211 {
212 return Limit;
213 }
214
215 GdiFlush();
216 GDI_BatchLimit = Limit;
217 return OldLimit;
218 }
219
220
221 /*
222 * @implemented
223 */
224 DWORD
225 WINAPI
226 GdiGetBatchLimit()
227 {
228 return GDI_BatchLimit;
229 }
230
231 /*
232 * @unimplemented
233 */
234 BOOL
235 WINAPI
236 GdiReleaseDC(HDC hdc)
237 {
238 return 0;
239 }
240
241 INT
242 WINAPI
243 ExtEscape(HDC hDC,
244 int nEscape,
245 int cbInput,
246 LPCSTR lpszInData,
247 int cbOutput,
248 LPSTR lpszOutData)
249 {
250 return NtGdiExtEscape(hDC, NULL, 0, nEscape, cbInput, (LPSTR)lpszInData, cbOutput, lpszOutData);
251 }
252
253 /*
254 * @implemented
255 */
256 VOID
257 WINAPI
258 GdiSetLastError(DWORD dwErrCode)
259 {
260 NtCurrentTeb()->LastErrorValue = (ULONG) dwErrCode;
261 }
262
263 BOOL
264 WINAPI
265 GdiAddGlsBounds(HDC hdc,LPRECT prc)
266 {
267 //FIXME: Lookup what 0x8000 means
268 return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE;
269 }
270
271 extern PGDIHANDLECACHE GdiHandleCache;
272
273 HGDIOBJ
274 FASTCALL
275 hGetPEBHandle(HANDLECACHETYPE Type, COLORREF cr)
276 {
277 int Number, Offset, MaxNum, GdiType;
278 HANDLE Lock;
279 HGDIOBJ Handle = NULL;
280
281 Lock = InterlockedCompareExchangePointer( (PVOID*)&GdiHandleCache->ulLock,
282 NtCurrentTeb(),
283 NULL );
284
285 if (Lock) return Handle;
286
287 Number = GdiHandleCache->ulNumHandles[Type];
288
289 if (Type == hctBrushHandle)
290 {
291 Offset = 0;
292 MaxNum = CACHE_BRUSH_ENTRIES;
293 GdiType = GDILoObjType_LO_BRUSH_TYPE;
294 }
295 else if (Type == hctPenHandle)
296 {
297 Offset = CACHE_BRUSH_ENTRIES;
298 MaxNum = CACHE_PEN_ENTRIES;
299 GdiType = GDILoObjType_LO_PEN_TYPE;
300 }
301 else if (Type == hctRegionHandle)
302 {
303 Offset = CACHE_BRUSH_ENTRIES+CACHE_PEN_ENTRIES;
304 MaxNum = CACHE_REGION_ENTRIES;
305 GdiType = GDILoObjType_LO_REGION_TYPE;
306 }
307 else // Font is not supported here.
308 {
309 return Handle;
310 }
311
312 if ( Number && Number <= MaxNum )
313 {
314 PBRUSH_ATTR pBrush_Attr;
315 HGDIOBJ *hPtr;
316 hPtr = GdiHandleCache->Handle + Offset;
317 Handle = hPtr[Number - 1];
318
319 if (GdiGetHandleUserData( Handle, GdiType, (PVOID) &pBrush_Attr))
320 {
321 if (pBrush_Attr->AttrFlags & ATTR_CACHED)
322 {
323 DPRINT("Get Handle! Type %d Count %lu PEB 0x%p\n", Type, GdiHandleCache->ulNumHandles[Type], NtCurrentTeb()->ProcessEnvironmentBlock);
324 pBrush_Attr->AttrFlags &= ~ATTR_CACHED;
325 hPtr[Number - 1] = NULL;
326 GdiHandleCache->ulNumHandles[Type]--;
327 if ( Type == hctBrushHandle ) // Handle only brush.
328 {
329 if ( pBrush_Attr->lbColor != cr )
330 {
331 pBrush_Attr->lbColor = cr ;
332 pBrush_Attr->AttrFlags |= ATTR_NEW_COLOR;
333 }
334 }
335 }
336 }
337 else
338 {
339 Handle = NULL;
340 }
341 }
342 (void)InterlockedExchangePointer((PVOID*)&GdiHandleCache->ulLock, Lock);
343 return Handle;
344 }
345