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
);
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
))
131 HANDLE pid
= (HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1);
132 if(pid
== NULL
|| pid
== CurrentProcessId
)
135 // Need to test if we have Read & Write access to the VM address space.
140 volatile CHAR
*Current
= (volatile CHAR
*)Entry
->UserData
;
145 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
152 Result
= FALSE
; // Can not be zero.
153 if (Result
) *UserData
= Entry
->UserData
;
157 SetLastError(ERROR_INVALID_PARAMETER
);
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
) )
175 volatile CHAR
*Current
= (volatile CHAR
*)Entry
->UserData
;
180 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
191 Dc_Attr
= (PDC_ATTR
)Entry
->UserData
;
192 return Dc_Attr
->pvLDC
;
198 VOID
GdiSAPCallback(PLDC pldc
)
200 DWORD Time
, NewTime
= GetTickCount();
202 Time
= NewTime
- pldc
->CallBackTick
;
204 if ( Time
< SAPCALLBACKDELAY
) return;
206 pldc
->CallBackTick
= NewTime
;
208 if ( !pldc
->pAbortProc(pldc
->hDC
, 0) )
220 GdiSetBatchLimit(DWORD Limit
)
222 DWORD OldLimit
= GDI_BatchLimit
;
225 (Limit
>= GDI_BATCH_LIMIT
))
231 GDI_BatchLimit
= Limit
;
243 return GDI_BatchLimit
;
251 GdiReleaseDC(HDC hdc
)
265 return NtGdiExtEscape(hDC
, NULL
, 0, nEscape
, cbInput
, (LPSTR
)lpszInData
, cbOutput
, lpszOutData
);
273 GdiSetLastError(DWORD dwErrCode
)
275 NtCurrentTeb()->LastErrorValue
= (ULONG
) dwErrCode
;
280 GdiAddGlsBounds(HDC hdc
,LPRECT prc
)
282 //FIXME: Lookup what 0x8000 means
283 return NtGdiSetBoundsRect(hdc
, prc
, 0x8000 | DCB_ACCUMULATE
) ? TRUE
: FALSE
;
286 extern PGDIHANDLECACHE GdiHandleCache
;
290 hGetPEBHandle(HANDLECACHETYPE Type
, COLORREF cr
)
294 HGDIOBJ Handle
= NULL
;
296 Lock
= InterlockedCompareExchangePointer( (PVOID
*)&GdiHandleCache
->ulLock
,
300 if (Lock
) return Handle
;
302 Number
= GdiHandleCache
->ulNumHandles
[Type
];
304 if ( Number
&& Number
<= CACHE_REGION_ENTRIES
)
306 if ( Type
== hctRegionHandle
)
310 hPtr
= GdiHandleCache
->Handle
+ CACHE_BRUSH_ENTRIES
+CACHE_PEN_ENTRIES
;
311 Handle
= hPtr
[Number
- 1];
313 if (GdiGetHandleUserData( Handle
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
315 if (pRgn_Attr
->AttrFlags
& ATTR_CACHED
)
317 DPRINT1("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
]--;
325 (void)InterlockedExchangePointer((PVOID
*)&GdiHandleCache
->ulLock
, Lock
);