wmiutils: Implement IWbemPath::GetServer.
[wine] / dlls / gdi32 / gdiobj.c
1 /*
2  * GDI functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winreg.h"
32 #include "winnls.h"
33 #include "winerror.h"
34 #include "winternl.h"
35
36 #include "gdi_private.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
40
41 #define FIRST_GDI_HANDLE 16
42 #define MAX_GDI_HANDLES  16384
43
44 struct hdc_list
45 {
46     HDC hdc;
47     struct hdc_list *next;
48 };
49
50 struct gdi_handle_entry
51 {
52     void                       *obj;         /* pointer to the object-specific data */
53     const struct gdi_obj_funcs *funcs;       /* type-specific functions */
54     struct hdc_list            *hdcs;        /* list of HDCs interested in this object */
55     WORD                        generation;  /* generation count for reusing handle values */
56     WORD                        type;        /* object type (one of the OBJ_* constants) */
57     WORD                        selcount;    /* number of times the object is selected in a DC */
58     WORD                        system : 1;  /* system object flag */
59     WORD                        deleted : 1; /* whether DeleteObject has been called on this object */
60 };
61
62 static struct gdi_handle_entry gdi_handles[MAX_GDI_HANDLES];
63 static struct gdi_handle_entry *next_free;
64 static struct gdi_handle_entry *next_unused = gdi_handles;
65 static LONG debug_count;
66 HMODULE gdi32_module = 0;
67
68 static inline HGDIOBJ entry_to_handle( struct gdi_handle_entry *entry )
69 {
70     unsigned int idx = entry - gdi_handles + FIRST_GDI_HANDLE;
71     return LongToHandle( idx | (entry->generation << 16) );
72 }
73
74 static inline struct gdi_handle_entry *handle_entry( HGDIOBJ handle )
75 {
76     unsigned int idx = LOWORD(handle) - FIRST_GDI_HANDLE;
77
78     if (idx < MAX_GDI_HANDLES && gdi_handles[idx].type)
79     {
80         if (!HIWORD( handle ) || HIWORD( handle ) == gdi_handles[idx].generation)
81             return &gdi_handles[idx];
82     }
83     if (handle) WARN( "invalid handle %p\n", handle );
84     return NULL;
85 }
86
87 /***********************************************************************
88  *          GDI stock objects
89  */
90
91 static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
92 static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
93 static const LOGBRUSH NullBrush  = { BS_NULL, 0, 0 };
94
95 static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
96 static const LOGBRUSH GrayBrush   = { BS_SOLID, RGB(128,128,128), 0 };
97 static const LOGBRUSH DkGrayBrush = { BS_SOLID, RGB(64,64,64), 0 };
98
99 static const LOGPEN WhitePen = { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
100 static const LOGPEN BlackPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
101 static const LOGPEN NullPen  = { PS_NULL,  { 0, 0 }, 0 };
102
103 static const LOGBRUSH DCBrush = { BS_SOLID, RGB(255,255,255), 0 };
104 static const LOGPEN DCPen     = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
105
106 /* reserve one extra entry for the stock default bitmap */
107 /* this is what Windows does too */
108 #define NB_STOCK_OBJECTS (STOCK_LAST+2)
109
110 static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
111
112 static CRITICAL_SECTION gdi_section;
113 static CRITICAL_SECTION_DEBUG critsect_debug =
114 {
115     0, 0, &gdi_section,
116     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
117       0, 0, { (DWORD_PTR)(__FILE__ ": gdi_section") }
118 };
119 static CRITICAL_SECTION gdi_section = { &critsect_debug, -1, 0, 0, 0, 0 };
120
121
122 /****************************************************************************
123  *
124  *      language-independent stock fonts
125  *
126  */
127
128 static const LOGFONTW OEMFixedFont =
129 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
130   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
131
132 static const LOGFONTW AnsiFixedFont =
133 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
134   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
135   {'C','o','u','r','i','e','r','\0'} };
136
137 static const LOGFONTW AnsiVarFont =
138 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
139   0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
140   {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'} };
141
142 /******************************************************************************
143  *
144  *      language-dependent stock fonts
145  *
146  *      'ANSI' charset and 'DEFAULT' charset is not same.
147  *      The chars in CP_ACP should be drawn with 'DEFAULT' charset.
148  *      'ANSI' charset seems to be identical with ISO-8859-1.
149  *      'DEFAULT' charset is a language-dependent charset.
150  *
151  *      'System' font seems to be an alias for language-dependent font.
152  */
153
154 /*
155  * language-dependent stock fonts for all known charsets
156  * please see TranslateCharsetInfo (dlls/gdi/font.c) and
157  * CharsetBindingInfo (dlls/x11drv/xfont.c),
158  * and modify entries for your language if needed.
159  */
160 struct DefaultFontInfo
161 {
162         UINT            charset;
163         LOGFONTW        SystemFont;
164         LOGFONTW        DeviceDefaultFont;
165         LOGFONTW        SystemFixedFont;
166         LOGFONTW        DefaultGuiFont;
167 };
168
169 static const struct DefaultFontInfo default_fonts[] =
170 {
171     {   ANSI_CHARSET,
172         { /* System */
173           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
174            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
175            {'S','y','s','t','e','m','\0'}
176         },
177         { /* Device Default */
178           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
179            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
180            {'S','y','s','t','e','m','\0'}
181         },
182         { /* System Fixed */
183           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
184            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
185            {'C','o','u','r','i','e','r','\0'}
186         },
187         { /* DefaultGuiFont */
188           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
189            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
190            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
191         },
192     },
193     {   EASTEUROPE_CHARSET,
194         { /* System */
195           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
196            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
197            {'S','y','s','t','e','m','\0'}
198         },
199         { /* Device Default */
200           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
201            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
202            {'S','y','s','t','e','m','\0'}
203         },
204         { /* System Fixed */
205           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
206            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
207            {'C','o','u','r','i','e','r','\0'}
208         },
209         { /* DefaultGuiFont */
210           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
211            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
212            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
213         },
214     },
215     {   RUSSIAN_CHARSET,
216         { /* System */
217           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
218            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
219            {'S','y','s','t','e','m','\0'}
220         },
221         { /* Device Default */
222           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
223            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
224            {'S','y','s','t','e','m','\0'}
225         },
226         { /* System Fixed */
227           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
228            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
229            {'C','o','u','r','i','e','r','\0'}
230         },
231         { /* DefaultGuiFont */
232           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
233            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
234            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
235         },
236     },
237     {   GREEK_CHARSET,
238         { /* System */
239           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GREEK_CHARSET,
240            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
241            {'S','y','s','t','e','m','\0'}
242         },
243         { /* Device Default */
244           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GREEK_CHARSET,
245            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
246            {'S','y','s','t','e','m','\0'}
247         },
248         { /* System Fixed */
249           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
250            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
251            {'C','o','u','r','i','e','r','\0'}
252         },
253         { /* DefaultGuiFont */
254           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
255            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
256            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
257         },
258     },
259     {   TURKISH_CHARSET,
260         { /* System */
261           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, TURKISH_CHARSET,
262            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
263            {'S','y','s','t','e','m','\0'}
264         },
265         { /* Device Default */
266           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, TURKISH_CHARSET,
267            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
268            {'S','y','s','t','e','m','\0'}
269         },
270         { /* System Fixed */
271           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
272            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
273            {'C','o','u','r','i','e','r','\0'}
274         },
275         { /* DefaultGuiFont */
276           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
277            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
278            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
279         },
280     },
281     {   HEBREW_CHARSET,
282         { /* System */
283           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, HEBREW_CHARSET,
284            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
285            {'S','y','s','t','e','m','\0'}
286         },
287         { /* Device Default */
288           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, HEBREW_CHARSET,
289            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
290            {'S','y','s','t','e','m','\0'}
291         },
292         { /* System Fixed */
293           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
294            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
295            {'C','o','u','r','i','e','r','\0'}
296         },
297         { /* DefaultGuiFont */
298           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
299            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
300            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
301         },
302     },
303     {   ARABIC_CHARSET,
304         { /* System */
305           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ARABIC_CHARSET,
306            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
307            {'S','y','s','t','e','m','\0'}
308         },
309         { /* Device Default */
310           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ARABIC_CHARSET,
311            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
312            {'S','y','s','t','e','m','\0'}
313         },
314         { /* System Fixed */
315           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
316            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
317            {'C','o','u','r','i','e','r','\0'}
318         },
319         { /* DefaultGuiFont */
320           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
321            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
322            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
323         },
324     },
325     {   BALTIC_CHARSET,
326         { /* System */
327           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, BALTIC_CHARSET,
328            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
329            {'S','y','s','t','e','m','\0'}
330         },
331         { /* Device Default */
332           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, BALTIC_CHARSET,
333            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
334            {'S','y','s','t','e','m','\0'}
335         },
336         { /* System Fixed */
337           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
338            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
339            {'C','o','u','r','i','e','r','\0'}
340         },
341         { /* DefaultGuiFont */
342           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
343            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
344            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
345         },
346     },
347     {   THAI_CHARSET,
348         { /* System */
349           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, THAI_CHARSET,
350            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
351            {'S','y','s','t','e','m','\0'}
352         },
353         { /* Device Default */
354           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, THAI_CHARSET,
355            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
356            {'S','y','s','t','e','m','\0'}
357         },
358         { /* System Fixed */
359           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
360            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
361            {'C','o','u','r','i','e','r','\0'}
362         },
363         { /* DefaultGuiFont */
364           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
365            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
366            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
367         },
368     },
369     {   SHIFTJIS_CHARSET,
370         { /* System */
371           18, 8, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
372            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
373            {'S','y','s','t','e','m','\0'}
374         },
375         { /* Device Default */
376           18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
377            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
378            {'S','y','s','t','e','m','\0'}
379         },
380         { /* System Fixed */
381           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
382            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
383            {'C','o','u','r','i','e','r','\0'}
384         },
385         { /* DefaultGuiFont */
386           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
387            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
388            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
389         },
390     },
391     {   GB2312_CHARSET,
392         { /* System */
393           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET,
394            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
395            {'S','y','s','t','e','m','\0'}
396         },
397         { /* Device Default */
398           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET,
399            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
400            {'S','y','s','t','e','m','\0'}
401         },
402         { /* System Fixed */
403           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
404            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
405            {'C','o','u','r','i','e','r','\0'}
406         },
407         { /* DefaultGuiFont */
408           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
409            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
410            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
411         },
412     },
413     {   HANGEUL_CHARSET,
414         { /* System */
415           16, 8, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
416            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
417            {'S','y','s','t','e','m','\0'}
418         },
419         { /* Device Default */
420           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
421            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
422            {'S','y','s','t','e','m','\0'}
423         },
424         { /* System Fixed */
425           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
426            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
427            {'C','o','u','r','i','e','r','\0'}
428         },
429         { /* DefaultGuiFont */
430           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
431            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
432            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
433         },
434     },
435     {   CHINESEBIG5_CHARSET,
436         { /* System */
437           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
438            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
439            {'S','y','s','t','e','m','\0'}
440         },
441         { /* Device Default */
442           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
443            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
444            {'S','y','s','t','e','m','\0'}
445         },
446         { /* System Fixed */
447           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
448            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
449            {'C','o','u','r','i','e','r','\0'}
450         },
451         { /* DefaultGuiFont */
452           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
453            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
454            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
455         },
456     },
457     {   JOHAB_CHARSET,
458         { /* System */
459           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, JOHAB_CHARSET,
460            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
461            {'S','y','s','t','e','m','\0'}
462         },
463         { /* Device Default */
464           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, JOHAB_CHARSET,
465            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
466            {'S','y','s','t','e','m','\0'}
467         },
468         { /* System Fixed */
469           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
470            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
471            {'C','o','u','r','i','e','r','\0'}
472         },
473         { /* DefaultGuiFont */
474           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
475            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
476            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
477         },
478     },
479 };
480
481
482 /*************************************************************************
483  * __wine_make_gdi_object_system    (GDI32.@)
484  *
485  * USER has to tell GDI that its system brushes and pens are non-deletable.
486  * For a description of the GDI object magics and their flags,
487  * see "Undocumented Windows" (wrong about the OBJECT_NOSYSTEM flag, though).
488  */
489 void CDECL __wine_make_gdi_object_system( HGDIOBJ handle, BOOL set)
490 {
491     struct gdi_handle_entry *entry;
492
493     EnterCriticalSection( &gdi_section );
494     if ((entry = handle_entry( handle ))) entry->system = !!set;
495     LeaveCriticalSection( &gdi_section );
496 }
497
498 /******************************************************************************
499  *      get_default_fonts
500  */
501 static const struct DefaultFontInfo* get_default_fonts(UINT charset)
502 {
503         unsigned int n;
504
505         for(n=0;n<(sizeof(default_fonts)/sizeof(default_fonts[0]));n++)
506         {
507                 if ( default_fonts[n].charset == charset )
508                         return &default_fonts[n];
509         }
510
511         FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
512         return &default_fonts[0];
513 }
514
515
516 /******************************************************************************
517  *      get_default_charset    (internal)
518  *
519  * get the language-dependent charset that can handle CP_ACP correctly.
520  */
521 static UINT get_default_charset( void )
522 {
523     CHARSETINFO     csi;
524     UINT    uACP;
525
526     uACP = GetACP();
527     csi.ciCharset = ANSI_CHARSET;
528     if ( !TranslateCharsetInfo( ULongToPtr(uACP), &csi, TCI_SRCCODEPAGE ) )
529     {
530         FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", uACP );
531         return ANSI_CHARSET;
532     }
533
534     return csi.ciCharset;
535 }
536
537
538 /***********************************************************************
539  *           GDI_get_ref_count
540  *
541  * Retrieve the reference count of a GDI object.
542  * Note: the object must be locked otherwise the count is meaningless.
543  */
544 UINT GDI_get_ref_count( HGDIOBJ handle )
545 {
546     struct gdi_handle_entry *entry;
547     UINT ret = 0;
548
549     EnterCriticalSection( &gdi_section );
550     if ((entry = handle_entry( handle ))) ret = entry->selcount;
551     LeaveCriticalSection( &gdi_section );
552     return ret;
553 }
554
555
556 /***********************************************************************
557  *           GDI_inc_ref_count
558  *
559  * Increment the reference count of a GDI object.
560  */
561 HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle )
562 {
563     struct gdi_handle_entry *entry;
564
565     EnterCriticalSection( &gdi_section );
566     if ((entry = handle_entry( handle ))) entry->selcount++;
567     else handle = 0;
568     LeaveCriticalSection( &gdi_section );
569     return handle;
570 }
571
572
573 /***********************************************************************
574  *           GDI_dec_ref_count
575  *
576  * Decrement the reference count of a GDI object.
577  */
578 BOOL GDI_dec_ref_count( HGDIOBJ handle )
579 {
580     struct gdi_handle_entry *entry;
581
582     EnterCriticalSection( &gdi_section );
583     if ((entry = handle_entry( handle )))
584     {
585         assert( entry->selcount );
586         if (!--entry->selcount && entry->deleted)
587         {
588             /* handle delayed DeleteObject*/
589             entry->deleted = 0;
590             LeaveCriticalSection( &gdi_section );
591             TRACE( "executing delayed DeleteObject for %p\n", handle );
592             DeleteObject( handle );
593             return TRUE;
594         }
595     }
596     LeaveCriticalSection( &gdi_section );
597     return entry != NULL;
598 }
599
600
601 /***********************************************************************
602  *           DllMain
603  *
604  * GDI initialization.
605  */
606 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
607 {
608     const struct DefaultFontInfo* deffonts;
609     int i;
610
611     if (reason != DLL_PROCESS_ATTACH) return TRUE;
612
613     gdi32_module = inst;
614     DisableThreadLibraryCalls( inst );
615     WineEngInit();
616
617     /* create stock objects */
618     stock_objects[WHITE_BRUSH]  = CreateBrushIndirect( &WhiteBrush );
619     stock_objects[LTGRAY_BRUSH] = CreateBrushIndirect( &LtGrayBrush );
620     stock_objects[GRAY_BRUSH]   = CreateBrushIndirect( &GrayBrush );
621     stock_objects[DKGRAY_BRUSH] = CreateBrushIndirect( &DkGrayBrush );
622     stock_objects[BLACK_BRUSH]  = CreateBrushIndirect( &BlackBrush );
623     stock_objects[NULL_BRUSH]   = CreateBrushIndirect( &NullBrush );
624
625     stock_objects[WHITE_PEN]    = CreatePenIndirect( &WhitePen );
626     stock_objects[BLACK_PEN]    = CreatePenIndirect( &BlackPen );
627     stock_objects[NULL_PEN]     = CreatePenIndirect( &NullPen );
628
629     stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
630     stock_objects[DEFAULT_BITMAP]  = CreateBitmap( 1, 1, 1, 1, NULL );
631
632     /* language-independent stock fonts */
633     stock_objects[OEM_FIXED_FONT]      = CreateFontIndirectW( &OEMFixedFont );
634     stock_objects[ANSI_FIXED_FONT]     = CreateFontIndirectW( &AnsiFixedFont );
635     stock_objects[ANSI_VAR_FONT]       = CreateFontIndirectW( &AnsiVarFont );
636
637     /* language-dependent stock fonts */
638     deffonts = get_default_fonts(get_default_charset());
639     stock_objects[SYSTEM_FONT]         = CreateFontIndirectW( &deffonts->SystemFont );
640     stock_objects[DEVICE_DEFAULT_FONT] = CreateFontIndirectW( &deffonts->DeviceDefaultFont );
641     stock_objects[SYSTEM_FIXED_FONT]   = CreateFontIndirectW( &deffonts->SystemFixedFont );
642     stock_objects[DEFAULT_GUI_FONT]    = CreateFontIndirectW( &deffonts->DefaultGuiFont );
643
644     stock_objects[DC_BRUSH]     = CreateBrushIndirect( &DCBrush );
645     stock_objects[DC_PEN]       = CreatePenIndirect( &DCPen );
646
647     /* clear the NOSYSTEM bit on all stock objects*/
648     for (i = 0; i < NB_STOCK_OBJECTS; i++)
649     {
650         if (!stock_objects[i])
651         {
652             if (i == 9) continue;  /* there's no stock object 9 */
653             ERR( "could not create stock object %d\n", i );
654             return FALSE;
655         }
656         __wine_make_gdi_object_system( stock_objects[i], TRUE );
657     }
658
659     return TRUE;
660 }
661
662 static const char *gdi_obj_type( unsigned type )
663 {
664     switch ( type )
665     {
666         case OBJ_PEN: return "OBJ_PEN";
667         case OBJ_BRUSH: return "OBJ_BRUSH";
668         case OBJ_DC: return "OBJ_DC";
669         case OBJ_METADC: return "OBJ_METADC";
670         case OBJ_PAL: return "OBJ_PAL";
671         case OBJ_FONT: return "OBJ_FONT";
672         case OBJ_BITMAP: return "OBJ_BITMAP";
673         case OBJ_REGION: return "OBJ_REGION";
674         case OBJ_METAFILE: return "OBJ_METAFILE";
675         case OBJ_MEMDC: return "OBJ_MEMDC";
676         case OBJ_EXTPEN: return "OBJ_EXTPEN";
677         case OBJ_ENHMETADC: return "OBJ_ENHMETADC";
678         case OBJ_ENHMETAFILE: return "OBJ_ENHMETAFILE";
679         case OBJ_COLORSPACE: return "OBJ_COLORSPACE";
680         default: return "UNKNOWN";
681     }
682 }
683
684 static void dump_gdi_objects( void )
685 {
686     struct gdi_handle_entry *entry;
687
688     TRACE( "%u objects:\n", MAX_GDI_HANDLES );
689
690     EnterCriticalSection( &gdi_section );
691     for (entry = gdi_handles; entry < next_unused; entry++)
692     {
693         if (!entry->type)
694             TRACE( "handle %p FREE\n", entry_to_handle( entry ));
695         else
696             TRACE( "handle %p obj %p type %s selcount %u deleted %u\n",
697                    entry_to_handle( entry ), entry->obj, gdi_obj_type( entry->type ),
698                    entry->selcount, entry->deleted );
699     }
700     LeaveCriticalSection( &gdi_section );
701 }
702
703 /***********************************************************************
704  *           alloc_gdi_handle
705  *
706  * Allocate a GDI handle for an object, which must have been allocated on the process heap.
707  */
708 HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *funcs )
709 {
710     struct gdi_handle_entry *entry;
711     HGDIOBJ ret;
712
713     assert( type );  /* type 0 is reserved to mark free entries */
714
715     EnterCriticalSection( &gdi_section );
716
717     entry = next_free;
718     if (entry)
719         next_free = entry->obj;
720     else if (next_unused < gdi_handles + MAX_GDI_HANDLES)
721         entry = next_unused++;
722     else
723     {
724         LeaveCriticalSection( &gdi_section );
725         ERR( "out of GDI object handles, expect a crash\n" );
726         if (TRACE_ON(gdi)) dump_gdi_objects();
727         return 0;
728     }
729     entry->obj      = obj;
730     entry->funcs    = funcs;
731     entry->hdcs     = NULL;
732     entry->type     = type;
733     entry->selcount = 0;
734     entry->system   = 0;
735     entry->deleted  = 0;
736     if (++entry->generation == 0xffff) entry->generation = 1;
737     ret = entry_to_handle( entry );
738     LeaveCriticalSection( &gdi_section );
739     TRACE( "allocated %s %p %u/%u\n", gdi_obj_type(type), ret,
740            InterlockedIncrement( &debug_count ), MAX_GDI_HANDLES );
741     return ret;
742 }
743
744
745 /***********************************************************************
746  *           free_gdi_handle
747  *
748  * Free a GDI handle and return a pointer to the object.
749  */
750 void *free_gdi_handle( HGDIOBJ handle )
751 {
752     void *object = NULL;
753     struct gdi_handle_entry *entry;
754
755     EnterCriticalSection( &gdi_section );
756     if ((entry = handle_entry( handle )))
757     {
758         TRACE( "freed %s %p %u/%u\n", gdi_obj_type( entry->type ), handle,
759                InterlockedDecrement( &debug_count ) + 1, MAX_GDI_HANDLES );
760         object = entry->obj;
761         entry->type = 0;
762         entry->obj = next_free;
763         next_free = entry;
764     }
765     LeaveCriticalSection( &gdi_section );
766     return object;
767 }
768
769
770 /***********************************************************************
771  *           get_full_gdi_handle
772  *
773  * Return the full GDI handle from a possibly truncated value.
774  */
775 HGDIOBJ get_full_gdi_handle( HGDIOBJ handle )
776 {
777     struct gdi_handle_entry *entry;
778
779     if (!HIWORD( handle ))
780     {
781         EnterCriticalSection( &gdi_section );
782         if ((entry = handle_entry( handle ))) handle = entry_to_handle( entry );
783         LeaveCriticalSection( &gdi_section );
784     }
785     return handle;
786 }
787
788 /***********************************************************************
789  *           GDI_GetObjPtr
790  *
791  * Return a pointer to the GDI object associated to the handle.
792  * Return NULL if the object has the wrong magic number.
793  * The object must be released with GDI_ReleaseObj.
794  */
795 void *GDI_GetObjPtr( HGDIOBJ handle, WORD type )
796 {
797     void *ptr = NULL;
798     struct gdi_handle_entry *entry;
799
800     EnterCriticalSection( &gdi_section );
801
802     if ((entry = handle_entry( handle )))
803     {
804         if (!type || entry->type == type) ptr = entry->obj;
805     }
806
807     if (!ptr) LeaveCriticalSection( &gdi_section );
808     return ptr;
809 }
810
811
812 /***********************************************************************
813  *           GDI_ReleaseObj
814  *
815  */
816 void GDI_ReleaseObj( HGDIOBJ handle )
817 {
818     LeaveCriticalSection( &gdi_section );
819 }
820
821
822 /***********************************************************************
823  *           GDI_CheckNotLock
824  */
825 void GDI_CheckNotLock(void)
826 {
827     if (gdi_section.OwningThread == ULongToHandle(GetCurrentThreadId()) && gdi_section.RecursionCount)
828     {
829         ERR( "BUG: holding GDI lock\n" );
830         DebugBreak();
831     }
832 }
833
834
835 /***********************************************************************
836  *           DeleteObject    (GDI32.@)
837  *
838  * Delete a Gdi object.
839  *
840  * PARAMS
841  *  obj [I] Gdi object to delete
842  *
843  * RETURNS
844  *  Success: TRUE. If obj was not returned from GetStockObject(), any resources
845  *           it consumed are released.
846  *  Failure: FALSE, if obj is not a valid Gdi object, or is currently selected
847  *           into a DC.
848  */
849 BOOL WINAPI DeleteObject( HGDIOBJ obj )
850 {
851     struct gdi_handle_entry *entry;
852     struct hdc_list *hdcs_head;
853     const struct gdi_obj_funcs *funcs = NULL;
854
855     EnterCriticalSection( &gdi_section );
856     if (!(entry = handle_entry( obj )))
857     {
858         LeaveCriticalSection( &gdi_section );
859         return FALSE;
860     }
861
862     if (entry->system)
863     {
864         TRACE("Preserving system object %p\n", obj);
865         LeaveCriticalSection( &gdi_section );
866         return TRUE;
867     }
868
869     obj = entry_to_handle( entry );  /* make it a full handle */
870
871     hdcs_head = entry->hdcs;
872     entry->hdcs = NULL;
873
874     if (entry->selcount)
875     {
876         TRACE("delayed for %p because object in use, count %u\n", obj, entry->selcount );
877         entry->deleted = 1;  /* mark for delete */
878     }
879     else funcs = entry->funcs;
880
881     LeaveCriticalSection( &gdi_section );
882
883     while (hdcs_head)
884     {
885         struct hdc_list *next = hdcs_head->next;
886         DC *dc = get_dc_ptr(hdcs_head->hdc);
887
888         TRACE("hdc %p has interest in %p\n", hdcs_head->hdc, obj);
889         if(dc)
890         {
891             PHYSDEV physdev = GET_DC_PHYSDEV( dc, pDeleteObject );
892             physdev->funcs->pDeleteObject( physdev, obj );
893             release_dc_ptr( dc );
894         }
895         HeapFree(GetProcessHeap(), 0, hdcs_head);
896         hdcs_head = next;
897     }
898
899     TRACE("%p\n", obj );
900
901     if (funcs && funcs->pDeleteObject) return funcs->pDeleteObject( obj );
902     return TRUE;
903 }
904
905 /***********************************************************************
906  *           GDI_hdc_using_object
907  *
908  * Call this if the dc requires DeleteObject notification
909  */
910 void GDI_hdc_using_object(HGDIOBJ obj, HDC hdc)
911 {
912     struct gdi_handle_entry *entry;
913     struct hdc_list *phdc;
914
915     TRACE("obj %p hdc %p\n", obj, hdc);
916
917     EnterCriticalSection( &gdi_section );
918     if ((entry = handle_entry( obj )) && !entry->system)
919     {
920         for (phdc = entry->hdcs; phdc; phdc = phdc->next)
921             if (phdc->hdc == hdc) break;
922
923         if (!phdc)
924         {
925             phdc = HeapAlloc(GetProcessHeap(), 0, sizeof(*phdc));
926             phdc->hdc = hdc;
927             phdc->next = entry->hdcs;
928             entry->hdcs = phdc;
929         }
930     }
931     LeaveCriticalSection( &gdi_section );
932 }
933
934 /***********************************************************************
935  *           GDI_hdc_not_using_object
936  *
937  */
938 void GDI_hdc_not_using_object(HGDIOBJ obj, HDC hdc)
939 {
940     struct gdi_handle_entry *entry;
941     struct hdc_list **pphdc;
942
943     TRACE("obj %p hdc %p\n", obj, hdc);
944
945     EnterCriticalSection( &gdi_section );
946     if ((entry = handle_entry( obj )) && !entry->system)
947     {
948         for (pphdc = &entry->hdcs; *pphdc; pphdc = &(*pphdc)->next)
949             if ((*pphdc)->hdc == hdc)
950             {
951                 struct hdc_list *phdc = *pphdc;
952                 *pphdc = phdc->next;
953                 HeapFree(GetProcessHeap(), 0, phdc);
954                 break;
955             }
956     }
957     LeaveCriticalSection( &gdi_section );
958 }
959
960 /***********************************************************************
961  *           GetStockObject    (GDI32.@)
962  */
963 HGDIOBJ WINAPI GetStockObject( INT obj )
964 {
965     HGDIOBJ ret;
966     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
967     ret = stock_objects[obj];
968     TRACE("returning %p\n", ret );
969     return ret;
970 }
971
972
973 /***********************************************************************
974  *           GetObjectA    (GDI32.@)
975  */
976 INT WINAPI GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
977 {
978     struct gdi_handle_entry *entry;
979     const struct gdi_obj_funcs *funcs = NULL;
980     INT result = 0;
981
982     TRACE("%p %d %p\n", handle, count, buffer );
983
984     EnterCriticalSection( &gdi_section );
985     if ((entry = handle_entry( handle )))
986     {
987         funcs = entry->funcs;
988         handle = entry_to_handle( entry );  /* make it a full handle */
989     }
990     LeaveCriticalSection( &gdi_section );
991
992     if (funcs)
993     {
994         if (!funcs->pGetObjectA)
995             SetLastError( ERROR_INVALID_HANDLE );
996         else if (buffer && ((ULONG_PTR)buffer >> 16) == 0) /* catch apps getting argument order wrong */
997             SetLastError( ERROR_NOACCESS );
998         else
999             result = funcs->pGetObjectA( handle, count, buffer );
1000     }
1001     return result;
1002 }
1003
1004 /***********************************************************************
1005  *           GetObjectW    (GDI32.@)
1006  */
1007 INT WINAPI GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
1008 {
1009     struct gdi_handle_entry *entry;
1010     const struct gdi_obj_funcs *funcs = NULL;
1011     INT result = 0;
1012
1013     TRACE("%p %d %p\n", handle, count, buffer );
1014
1015     EnterCriticalSection( &gdi_section );
1016     if ((entry = handle_entry( handle )))
1017     {
1018         funcs = entry->funcs;
1019         handle = entry_to_handle( entry );  /* make it a full handle */
1020     }
1021     LeaveCriticalSection( &gdi_section );
1022
1023     if (funcs)
1024     {
1025         if (!funcs->pGetObjectW)
1026             SetLastError( ERROR_INVALID_HANDLE );
1027         else if (buffer && ((ULONG_PTR)buffer >> 16) == 0) /* catch apps getting argument order wrong */
1028             SetLastError( ERROR_NOACCESS );
1029         else
1030             result = funcs->pGetObjectW( handle, count, buffer );
1031     }
1032     return result;
1033 }
1034
1035 /***********************************************************************
1036  *           GetObjectType    (GDI32.@)
1037  */
1038 DWORD WINAPI GetObjectType( HGDIOBJ handle )
1039 {
1040     struct gdi_handle_entry *entry;
1041     DWORD result = 0;
1042
1043     EnterCriticalSection( &gdi_section );
1044     if ((entry = handle_entry( handle ))) result = entry->type;
1045     LeaveCriticalSection( &gdi_section );
1046
1047     TRACE("%p -> %u\n", handle, result );
1048     if (!result) SetLastError( ERROR_INVALID_HANDLE );
1049     return result;
1050 }
1051
1052 /***********************************************************************
1053  *           GetCurrentObject           (GDI32.@)
1054  *
1055  * Get the currently selected object of a given type in a device context.
1056  *
1057  * PARAMS
1058  *  hdc  [I] Device context to get the current object from
1059  *  type [I] Type of current object to get (OBJ_* defines from "wingdi.h")
1060  *
1061  * RETURNS
1062  *  Success: The current object of the given type selected in hdc.
1063  *  Failure: A NULL handle.
1064  *
1065  * NOTES
1066  * - only the following object types are supported:
1067  *| OBJ_PEN
1068  *| OBJ_BRUSH
1069  *| OBJ_PAL
1070  *| OBJ_FONT
1071  *| OBJ_BITMAP
1072  */
1073 HGDIOBJ WINAPI GetCurrentObject(HDC hdc,UINT type)
1074 {
1075     HGDIOBJ ret = 0;
1076     DC * dc = get_dc_ptr( hdc );
1077
1078     if (!dc) return 0;
1079
1080     switch (type) {
1081         case OBJ_EXTPEN: /* fall through */
1082         case OBJ_PEN:    ret = dc->hPen; break;
1083         case OBJ_BRUSH:  ret = dc->hBrush; break;
1084         case OBJ_PAL:    ret = dc->hPalette; break;
1085         case OBJ_FONT:   ret = dc->hFont; break;
1086         case OBJ_BITMAP: ret = dc->hBitmap; break;
1087
1088         /* tests show that OBJ_REGION is explicitly ignored */
1089         case OBJ_REGION: break;
1090         default:
1091             /* the SDK only mentions those above */
1092             FIXME("(%p,%d): unknown type.\n",hdc,type);
1093             break;
1094     }
1095     release_dc_ptr( dc );
1096     return ret;
1097 }
1098
1099
1100 /***********************************************************************
1101  *           SelectObject    (GDI32.@)
1102  *
1103  * Select a Gdi object into a device context.
1104  *
1105  * PARAMS
1106  *  hdc  [I] Device context to associate the object with
1107  *  hObj [I] Gdi object to associate with hdc
1108  *
1109  * RETURNS
1110  *  Success: A non-NULL handle representing the previously selected object of
1111  *           the same type as hObj.
1112  *  Failure: A NULL object. If hdc is invalid, GetLastError() returns ERROR_INVALID_HANDLE.
1113  *           if hObj is not a valid object handle, no last error is set. In either
1114  *           case, hdc is unaffected by the call.
1115  */
1116 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj )
1117 {
1118     struct gdi_handle_entry *entry;
1119     const struct gdi_obj_funcs *funcs = NULL;
1120
1121     TRACE( "(%p,%p)\n", hdc, hObj );
1122
1123     EnterCriticalSection( &gdi_section );
1124     if ((entry = handle_entry( hObj )))
1125     {
1126         funcs = entry->funcs;
1127         hObj = entry_to_handle( entry );  /* make it a full handle */
1128     }
1129     LeaveCriticalSection( &gdi_section );
1130
1131     if (funcs && funcs->pSelectObject) return funcs->pSelectObject( hObj, hdc );
1132     return 0;
1133 }
1134
1135
1136 /***********************************************************************
1137  *           UnrealizeObject    (GDI32.@)
1138  */
1139 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
1140 {
1141     const struct gdi_obj_funcs *funcs = NULL;
1142     struct gdi_handle_entry *entry;
1143
1144     EnterCriticalSection( &gdi_section );
1145     if ((entry = handle_entry( obj )))
1146     {
1147         funcs = entry->funcs;
1148         obj = entry_to_handle( entry );  /* make it a full handle */
1149     }
1150     LeaveCriticalSection( &gdi_section );
1151
1152     if (funcs && funcs->pUnrealizeObject) return funcs->pUnrealizeObject( obj );
1153     return funcs != NULL;
1154 }
1155
1156
1157 /* Solid colors to enumerate */
1158 static const COLORREF solid_colors[] =
1159 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1160 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1161 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1162 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1163 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1164 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1165 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1166 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1167 };
1168
1169
1170 /***********************************************************************
1171  *           EnumObjects    (GDI32.@)
1172  */
1173 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
1174                             GOBJENUMPROC lpEnumFunc, LPARAM lParam )
1175 {
1176     UINT i;
1177     INT retval = 0;
1178     LOGPEN pen;
1179     LOGBRUSH brush;
1180
1181     TRACE("%p %d %p %08lx\n", hdc, nObjType, lpEnumFunc, lParam );
1182     switch(nObjType)
1183     {
1184     case OBJ_PEN:
1185         /* Enumerate solid pens */
1186         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1187         {
1188             pen.lopnStyle   = PS_SOLID;
1189             pen.lopnWidth.x = 1;
1190             pen.lopnWidth.y = 0;
1191             pen.lopnColor   = solid_colors[i];
1192             retval = lpEnumFunc( &pen, lParam );
1193             TRACE("solid pen %08x, ret=%d\n",
1194                          solid_colors[i], retval);
1195             if (!retval) break;
1196         }
1197         break;
1198
1199     case OBJ_BRUSH:
1200         /* Enumerate solid brushes */
1201         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1202         {
1203             brush.lbStyle = BS_SOLID;
1204             brush.lbColor = solid_colors[i];
1205             brush.lbHatch = 0;
1206             retval = lpEnumFunc( &brush, lParam );
1207             TRACE("solid brush %08x, ret=%d\n",
1208                          solid_colors[i], retval);
1209             if (!retval) break;
1210         }
1211
1212         /* Now enumerate hatched brushes */
1213         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1214         {
1215             brush.lbStyle = BS_HATCHED;
1216             brush.lbColor = RGB(0,0,0);
1217             brush.lbHatch = i;
1218             retval = lpEnumFunc( &brush, lParam );
1219             TRACE("hatched brush %d, ret=%d\n",
1220                          i, retval);
1221             if (!retval) break;
1222         }
1223         break;
1224
1225     default:
1226         /* FIXME: implement Win32 types */
1227         WARN("(%d): Invalid type\n", nObjType );
1228         break;
1229     }
1230     return retval;
1231 }
1232
1233
1234 /***********************************************************************
1235  *           SetObjectOwner    (GDI32.@)
1236  */
1237 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1238 {
1239     /* Nothing to do */
1240 }
1241
1242 /***********************************************************************
1243  *           GdiInitializeLanguagePack    (GDI32.@)
1244  */
1245 DWORD WINAPI GdiInitializeLanguagePack( DWORD arg )
1246 {
1247     FIXME("stub\n");
1248     return 0;
1249 }
1250
1251 /***********************************************************************
1252  *           GdiFlush    (GDI32.@)
1253  */
1254 BOOL WINAPI GdiFlush(void)
1255 {
1256     return TRUE;  /* FIXME */
1257 }
1258
1259
1260 /***********************************************************************
1261  *           GdiGetBatchLimit    (GDI32.@)
1262  */
1263 DWORD WINAPI GdiGetBatchLimit(void)
1264 {
1265     return 1;  /* FIXME */
1266 }
1267
1268
1269 /***********************************************************************
1270  *           GdiSetBatchLimit    (GDI32.@)
1271  */
1272 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1273 {
1274     return 1; /* FIXME */
1275 }
1276
1277
1278 /*******************************************************************
1279  *      GetColorAdjustment [GDI32.@]
1280  *
1281  *
1282  */
1283 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1284 {
1285         FIXME("stub\n");
1286         return 0;
1287 }
1288
1289 /*******************************************************************
1290  *      GdiComment [GDI32.@]
1291  *
1292  *
1293  */
1294 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1295 {
1296     DC *dc = get_dc_ptr(hdc);
1297     BOOL ret = FALSE;
1298
1299     if(dc)
1300     {
1301         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGdiComment );
1302         ret = physdev->funcs->pGdiComment( physdev, cbSize, lpData );
1303         release_dc_ptr( dc );
1304     }
1305     return ret;
1306 }
1307
1308 /*******************************************************************
1309  *      SetColorAdjustment [GDI32.@]
1310  *
1311  *
1312  */
1313 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1314 {
1315         FIXME("stub\n");
1316         return 0;
1317 }