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