8fedb8fb820a1c93be78cc29da3042f7ba4f71bb
[reactos.git] / reactos / dll / win32 / 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 SetLastError(ERROR_INVALID_PARAMETER);
134 return FALSE;
135 }
136
137 /* Check if we are the owner */
138 if ((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) != CurrentProcessId)
139 {
140 return FALSE;
141 }
142
143 *UserData = Entry->UserData;
144 return TRUE;
145 }
146
147 PLDC
148 FASTCALL
149 GdiGetLDC(HDC hDC)
150 {
151 PDC_ATTR Dc_Attr;
152 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX((HGDIOBJ) hDC);
153 HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
154 // Don't check the mask, just the object type.
155 if ( Entry->ObjectType == GDIObjType_DC_TYPE &&
156 (pid == NULL || pid == CurrentProcessId) )
157 {
158 BOOL Result = TRUE;
159 if (Entry->UserData)
160 {
161 volatile CHAR *Current = (volatile CHAR*)Entry->UserData;
162 _SEH2_TRY
163 {
164 *Current = *Current;
165 }
166 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
167 {
168 Result = FALSE;
169 }
170 _SEH2_END
171 }
172 else
173 Result = FALSE;
174
175 if (Result)
176 {
177 Dc_Attr = (PDC_ATTR)Entry->UserData;
178 return Dc_Attr->pvLDC;
179 }
180 }
181 return NULL;
182 }
183
184 VOID GdiSAPCallback(PLDC pldc)
185 {
186 DWORD Time, NewTime = GetTickCount();
187
188 Time = NewTime - pldc->CallBackTick;
189
190 if ( Time < SAPCALLBACKDELAY) return;
191
192 pldc->CallBackTick = NewTime;
193
194 if ( !pldc->pAbortProc(pldc->hDC, 0) )
195 {
196 CancelDC(pldc->hDC);
197 AbortDoc(pldc->hDC);
198 }
199 }
200
201 /*
202 * @implemented
203 */
204 DWORD
205 WINAPI
206 GdiSetBatchLimit(DWORD Limit)
207 {
208 DWORD OldLimit = GDI_BatchLimit;
209
210 if ( (!Limit) ||
211 (Limit >= GDI_BATCH_LIMIT))
212 {
213 return Limit;
214 }
215
216 GdiFlush();
217 GDI_BatchLimit = Limit;
218 return OldLimit;
219 }
220
221
222 /*
223 * @implemented
224 */
225 DWORD
226 WINAPI
227 GdiGetBatchLimit()
228 {
229 return GDI_BatchLimit;
230 }
231
232 /*
233 * @unimplemented
234 */
235 BOOL
236 WINAPI
237 GdiReleaseDC(HDC hdc)
238 {
239 return 0;
240 }
241
242 INT
243 WINAPI
244 ExtEscape(HDC hDC,
245 int nEscape,
246 int cbInput,
247 LPCSTR lpszInData,
248 int cbOutput,
249 LPSTR lpszOutData)
250 {
251 return NtGdiExtEscape(hDC, NULL, 0, nEscape, cbInput, (LPSTR)lpszInData, cbOutput, lpszOutData);
252 }
253
254 /*
255 * @implemented
256 */
257 VOID
258 WINAPI
259 GdiSetLastError(DWORD dwErrCode)
260 {
261 NtCurrentTeb()->LastErrorValue = (ULONG) dwErrCode;
262 }
263
264 BOOL
265 WINAPI
266 GdiAddGlsBounds(HDC hdc,LPRECT prc)
267 {
268 //FIXME: Lookup what 0x8000 means
269 return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE;
270 }
271
272 extern PGDIHANDLECACHE GdiHandleCache;
273
274 HGDIOBJ
275 FASTCALL
276 hGetPEBHandle(HANDLECACHETYPE Type, COLORREF cr)
277 {
278 int Number;
279 HANDLE Lock;
280 HGDIOBJ Handle = NULL;
281
282 Lock = InterlockedCompareExchangePointer( (PVOID*)&GdiHandleCache->ulLock,
283 NtCurrentTeb(),
284 NULL );
285
286 if (Lock) return Handle;
287
288 Number = GdiHandleCache->ulNumHandles[Type];
289
290 if ( Number && Number <= CACHE_REGION_ENTRIES )
291 {
292 if ( Type == hctRegionHandle)
293 {
294 PRGN_ATTR pRgn_Attr;
295 HGDIOBJ *hPtr;
296 hPtr = GdiHandleCache->Handle + CACHE_BRUSH_ENTRIES+CACHE_PEN_ENTRIES;
297 Handle = hPtr[Number - 1];
298
299 if (GdiGetHandleUserData( Handle, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
300 {
301 if (pRgn_Attr->AttrFlags & ATTR_CACHED)
302 {
303 DPRINT("Get Handle! Count %d PEB 0x%x\n", GdiHandleCache->ulNumHandles[Type], NtCurrentTeb()->ProcessEnvironmentBlock);
304 pRgn_Attr->AttrFlags &= ~ATTR_CACHED;
305 hPtr[Number - 1] = NULL;
306 GdiHandleCache->ulNumHandles[Type]--;
307 }
308 }
309 }
310 }
311 (void)InterlockedExchangePointer((PVOID*)&GdiHandleCache->ulLock, Lock);
312 return Handle;
313 }
314