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