3 * Copyright (C) 2003 ReactOS Team
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.
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.
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.
20 * PROJECT: ReactOS gdi32.dll
21 * FILE: dll/win32/gdi32/misc/misc.c
22 * PURPOSE: Miscellaneous functions
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
33 PGDI_TABLE_ENTRY GdiHandleTable
= NULL
;
34 PGDI_SHARED_HANDLE_TABLE GdiSharedHandleTable
= NULL
;
35 HANDLE CurrentProcessId
= NULL
;
36 DWORD GDI_BatchLimit
= 1;
52 BLENDFUNCTION BlendFunction
55 if ( hDCSrc
== NULL
) return FALSE
;
57 if (GDI_HANDLE_GET_TYPE(hDCSrc
) == GDI_OBJECT_TYPE_METADC
) return FALSE
;
59 return NtGdiAlphaBlend(
79 GdiFixUpHandle(HGDIOBJ hGdiObj
)
81 PGDI_TABLE_ENTRY Entry
;
83 if (((ULONG_PTR
)(hGdiObj
)) & GDI_HANDLE_UPPER_MASK
)
88 /* FIXME is this right ?? */
90 Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hGdiObj
);
92 /* Rebuild handle for Object */
93 return hGdiObj
= (HGDIOBJ
)(((LONG_PTR
)(hGdiObj
)) | (Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
));
103 return (PVOID
)GdiHandleTable
;
106 BOOL
GdiIsHandleValid(HGDIOBJ hGdiObj
)
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
))
115 HANDLE pid
= (HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1);
116 if(pid
== NULL
|| pid
== CurrentProcessId
)
124 BOOL
GdiGetHandleUserData(HGDIOBJ hGdiObj
, DWORD ObjectType
, PVOID
*UserData
)
126 PGDI_TABLE_ENTRY Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hGdiObj
);
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
))
136 /* Check if we are the owner */
137 if ((HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1) != CurrentProcessId
)
142 *UserData
= Entry
->UserData
;
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
) )
160 volatile CHAR
*Current
= (volatile CHAR
*)Entry
->UserData
;
165 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
176 Dc_Attr
= (PDC_ATTR
)Entry
->UserData
;
177 return Dc_Attr
->pvLDC
;
183 VOID
GdiSAPCallback(PLDC pldc
)
185 DWORD Time
, NewTime
= GetTickCount();
187 Time
= NewTime
- pldc
->CallBackTick
;
189 if ( Time
< SAPCALLBACKDELAY
) return;
191 pldc
->CallBackTick
= NewTime
;
193 if ( !pldc
->pAbortProc(pldc
->hDC
, 0) )
205 GdiSetBatchLimit(DWORD Limit
)
207 DWORD OldLimit
= GDI_BatchLimit
;
210 (Limit
>= GDI_BATCH_LIMIT
))
216 GDI_BatchLimit
= Limit
;
228 return GDI_BatchLimit
;
236 GdiReleaseDC(HDC hdc
)
250 return NtGdiExtEscape(hDC
, NULL
, 0, nEscape
, cbInput
, (LPSTR
)lpszInData
, cbOutput
, lpszOutData
);
258 GdiSetLastError(DWORD dwErrCode
)
260 NtCurrentTeb()->LastErrorValue
= (ULONG
) dwErrCode
;
265 GdiAddGlsBounds(HDC hdc
,LPRECT prc
)
267 //FIXME: Lookup what 0x8000 means
268 return NtGdiSetBoundsRect(hdc
, prc
, 0x8000 | DCB_ACCUMULATE
) ? TRUE
: FALSE
;
271 extern PGDIHANDLECACHE GdiHandleCache
;
275 hGetPEBHandle(HANDLECACHETYPE Type
, COLORREF cr
)
277 int Number
, Offset
, MaxNum
, GdiType
;
279 HGDIOBJ Handle
= NULL
;
281 Lock
= InterlockedCompareExchangePointer( (PVOID
*)&GdiHandleCache
->ulLock
,
285 if (Lock
) return Handle
;
287 Number
= GdiHandleCache
->ulNumHandles
[Type
];
289 if (Type
== hctBrushHandle
)
292 MaxNum
= CACHE_BRUSH_ENTRIES
;
293 GdiType
= GDILoObjType_LO_BRUSH_TYPE
;
295 else if (Type
== hctPenHandle
)
297 Offset
= CACHE_BRUSH_ENTRIES
;
298 MaxNum
= CACHE_PEN_ENTRIES
;
299 GdiType
= GDILoObjType_LO_PEN_TYPE
;
301 else if (Type
== hctRegionHandle
)
303 Offset
= CACHE_BRUSH_ENTRIES
+CACHE_PEN_ENTRIES
;
304 MaxNum
= CACHE_REGION_ENTRIES
;
305 GdiType
= GDILoObjType_LO_REGION_TYPE
;
307 else // Font is not supported here.
312 if ( Number
&& Number
<= MaxNum
)
314 PBRUSH_ATTR pBrush_Attr
;
316 hPtr
= GdiHandleCache
->Handle
+ Offset
;
317 Handle
= hPtr
[Number
- 1];
319 if (GdiGetHandleUserData( Handle
, GdiType
, (PVOID
) &pBrush_Attr
))
321 if (pBrush_Attr
->AttrFlags
& ATTR_CACHED
)
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.
329 if ( pBrush_Attr
->lbColor
!= cr
)
331 pBrush_Attr
->lbColor
= cr
;
332 pBrush_Attr
->AttrFlags
|= ATTR_NEW_COLOR
;
342 (void)InterlockedExchangePointer((PVOID
*)&GdiHandleCache
->ulLock
, Lock
);