- Hack around the system start up Dll Initialization Bug for GdiHandleTable.
[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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS gdi32.dll
22 * FILE: lib/gdi32/misc/misc.c
23 * PURPOSE: Miscellaneous functions
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
25 * UPDATE HISTORY:
26 * 2004/09/04 Created
27 */
28
29 #include "precomp.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 PGDI_TABLE_ENTRY GdiHandleTable = NULL;
35 PGDI_SHARED_HANDLE_TABLE GdiSharedHandleTable = NULL;
36 HANDLE CurrentProcessId = NULL;
37 DWORD GDI_BatchLimit = 1;
38
39
40 BOOL
41 WINAPI
42 GdiAlphaBlend(
43 HDC hDCDst,
44 int DstX,
45 int DstY,
46 int DstCx,
47 int DstCy,
48 HDC hDCSrc,
49 int SrcX,
50 int SrcY,
51 int SrcCx,
52 int SrcCy,
53 BLENDFUNCTION BlendFunction
54 )
55 {
56 if ( hDCSrc == NULL ) return FALSE;
57
58 if (GDI_HANDLE_GET_TYPE(hDCSrc) == GDI_OBJECT_TYPE_METADC) return FALSE;
59
60 return NtGdiAlphaBlend(
61 hDCDst,
62 DstX,
63 DstY,
64 DstCx,
65 DstCy,
66 hDCSrc,
67 SrcX,
68 SrcY,
69 SrcCx,
70 SrcCy,
71 BlendFunction,
72 0 );
73 }
74
75 /*
76 * @implemented
77 */
78 HGDIOBJ
79 WINAPI
80 GdiFixUpHandle(HGDIOBJ hGdiObj)
81 {
82 PGDI_TABLE_ENTRY Entry;
83
84 if (((ULONG_PTR)(hGdiObj)) & GDI_HANDLE_UPPER_MASK )
85 {
86 return hGdiObj;
87 }
88
89 /* FIXME is this right ?? */
90
91 Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
92
93 /* Rebuild handle for Object */
94 return hGdiObj = (HGDIOBJ)(((LONG_PTR)(hGdiObj)) | (Entry->Type << GDI_ENTRY_UPPER_SHIFT));
95 }
96
97 /*
98 * @implemented
99 */
100 PVOID
101 WINAPI
102 GdiQueryTable(VOID)
103 {
104 return (PVOID)GdiHandleTable;
105 }
106
107 BOOL GdiIsHandleValid(HGDIOBJ hGdiObj)
108 {
109 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
110 // We are only looking for TYPE not the rest here, and why is FullUnique filled up with CRAP!?
111 // DPRINT1("FullUnique -> %x\n", Entry->FullUnique);
112 if((Entry->Type & GDI_ENTRY_BASETYPE_MASK) != 0 &&
113 ( (Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK ) ==
114 GDI_HANDLE_GET_TYPE(hGdiObj))
115 {
116 HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
117 if(pid == NULL || pid == CurrentProcessId)
118 {
119 return TRUE;
120 }
121 }
122 return FALSE;
123 }
124
125 BOOL GdiGetHandleUserData(HGDIOBJ hGdiObj, DWORD ObjectType, PVOID *UserData)
126 {
127 if ( !GdiHandleTable )
128 {
129 // FIXME HAX!! Due to the "Dll Initialization Bug" set the local handle table pointer.
130 GdiHandleTable = NtCurrentTeb()->ProcessEnvironmentBlock->GdiSharedHandleTable;
131 }
132 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
133 if((Entry->Type & GDI_ENTRY_BASETYPE_MASK) == ObjectType &&
134 ( (Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK ) ==
135 GDI_HANDLE_GET_TYPE(hGdiObj))
136 {
137 HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
138 if(pid == NULL || pid == CurrentProcessId)
139 {
140 //
141 // Need to test if we have Read & Write access to the VM address space.
142 //
143 BOOL Result = TRUE;
144 if(Entry->UserData)
145 {
146 volatile CHAR *Current = (volatile CHAR*)Entry->UserData;
147 _SEH2_TRY
148 {
149 *Current = *Current;
150 }
151 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
152 {
153 Result = FALSE;
154 }
155 _SEH2_END
156 }
157 else
158 Result = FALSE; // Can not be zero.
159 if (Result) *UserData = Entry->UserData;
160 return Result;
161 }
162 }
163 SetLastError(ERROR_INVALID_PARAMETER);
164 return FALSE;
165 }
166
167 PLDC
168 FASTCALL
169 GdiGetLDC(HDC hDC)
170 {
171 if ( !GdiHandleTable )
172 {
173 // FIXME HAX!! Due to the "Dll Initialization Bug" set the local handle table pointer.
174 GdiHandleTable = NtCurrentTeb()->ProcessEnvironmentBlock->GdiSharedHandleTable;
175 }
176 PDC_ATTR Dc_Attr;
177 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX((HGDIOBJ) hDC);
178 HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
179 // Don't check the mask, just the object type.
180 if ( Entry->ObjectType == GDIObjType_DC_TYPE &&
181 (pid == NULL || pid == CurrentProcessId) )
182 {
183 BOOL Result = TRUE;
184 if (Entry->UserData)
185 {
186 volatile CHAR *Current = (volatile CHAR*)Entry->UserData;
187 _SEH2_TRY
188 {
189 *Current = *Current;
190 }
191 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
192 {
193 Result = FALSE;
194 }
195 _SEH2_END
196 }
197 else
198 Result = FALSE;
199
200 if (Result)
201 {
202 Dc_Attr = (PDC_ATTR)Entry->UserData;
203 return Dc_Attr->pvLDC;
204 }
205 }
206 return NULL;
207 }
208
209 VOID GdiSAPCallback(PLDC pldc)
210 {
211 DWORD Time, NewTime = GetTickCount();
212
213 Time = NewTime - pldc->CallBackTick;
214
215 if ( Time < SAPCALLBACKDELAY) return;
216
217 pldc->CallBackTick = NewTime;
218
219 if ( !pldc->pAbortProc(pldc->hDC, 0) )
220 {
221 CancelDC(pldc->hDC);
222 AbortDoc(pldc->hDC);
223 }
224 }
225
226 /*
227 * @implemented
228 */
229 DWORD
230 WINAPI
231 GdiSetBatchLimit(DWORD Limit)
232 {
233 DWORD OldLimit = GDI_BatchLimit;
234
235 if ( (!Limit) ||
236 (Limit >= GDI_BATCH_LIMIT))
237 {
238 return Limit;
239 }
240
241 GdiFlush();
242 GDI_BatchLimit = Limit;
243 return OldLimit;
244 }
245
246
247 /*
248 * @implemented
249 */
250 DWORD
251 WINAPI
252 GdiGetBatchLimit()
253 {
254 return GDI_BatchLimit;
255 }
256
257 /*
258 * @unimplemented
259 */
260 BOOL
261 WINAPI
262 GdiReleaseDC(HDC hdc)
263 {
264 return 0;
265 }
266
267 INT
268 WINAPI
269 ExtEscape(HDC hDC,
270 int nEscape,
271 int cbInput,
272 LPCSTR lpszInData,
273 int cbOutput,
274 LPSTR lpszOutData)
275 {
276 return NtGdiExtEscape(hDC, NULL, 0, nEscape, cbInput, (LPSTR)lpszInData, cbOutput, lpszOutData);
277 }
278
279 /*
280 * @implemented
281 */
282 VOID
283 WINAPI
284 GdiSetLastError(DWORD dwErrCode)
285 {
286 NtCurrentTeb()->LastErrorValue = (ULONG) dwErrCode;
287 }
288
289 BOOL
290 WINAPI
291 GdiAddGlsBounds(HDC hdc,LPRECT prc)
292 {
293 //FIXME: Lookup what 0x8000 means
294 return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE;
295 }
296