win32u: Use CPTABLEINFO to store the Ansi/OEM codepages.
[wine.git] / dlls / win32u / gdiobj.c
blob78fab0189c9427df0ba7939e35e2552b642eb51c
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
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.
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.
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
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include <assert.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <pthread.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winreg.h"
35 #include "winnls.h"
36 #include "winerror.h"
37 #include "winternl.h"
39 #include "ntgdi_private.h"
40 #include "wine/debug.h"
41 #include "wine/unixlib.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
45 #define FIRST_GDI_HANDLE 32
47 static GDI_SHARED_MEMORY *gdi_shared;
48 static GDI_HANDLE_ENTRY *next_free;
49 static GDI_HANDLE_ENTRY *next_unused;
50 static LONG debug_count;
51 SYSTEM_BASIC_INFORMATION system_info;
53 const struct user_callbacks *user_callbacks = NULL;
55 static inline HGDIOBJ entry_to_handle( GDI_HANDLE_ENTRY *entry )
57 unsigned int idx = entry - gdi_shared->Handles;
58 return ULongToHandle( idx | (entry->Unique << NTGDI_HANDLE_TYPE_SHIFT) );
61 static inline GDI_HANDLE_ENTRY *handle_entry( HGDIOBJ handle )
63 unsigned int idx = LOWORD(handle);
65 if (idx < GDI_MAX_HANDLE_COUNT && gdi_shared->Handles[idx].Type)
67 if (!HIWORD( handle ) || HIWORD( handle ) == gdi_shared->Handles[idx].Unique)
68 return &gdi_shared->Handles[idx];
70 if (handle) WARN( "invalid handle %p\n", handle );
71 return NULL;
74 static inline struct gdi_obj_header *entry_obj( GDI_HANDLE_ENTRY *entry )
76 return (struct gdi_obj_header *)(ULONG_PTR)entry->Object;
79 /***********************************************************************
80 * GDI stock objects
83 static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
84 static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
85 static const LOGBRUSH NullBrush = { BS_NULL, 0, 0 };
87 static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
88 static const LOGBRUSH GrayBrush = { BS_SOLID, RGB(128,128,128), 0 };
89 static const LOGBRUSH DkGrayBrush = { BS_SOLID, RGB(64,64,64), 0 };
91 static const LOGBRUSH DCBrush = { BS_SOLID, RGB(255,255,255), 0 };
93 static pthread_mutex_t gdi_lock;
96 /****************************************************************************
98 * language-independent stock fonts
102 static const LOGFONTW OEMFixedFont =
103 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
104 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN };
106 static const LOGFONTW AnsiFixedFont =
107 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
108 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
109 {'C','o','u','r','i','e','r'} };
111 static const LOGFONTW AnsiVarFont =
112 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
113 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
114 {'M','S',' ','S','a','n','s',' ','S','e','r','i','f'} };
116 /******************************************************************************
118 * language-dependent stock fonts
120 * 'ANSI' charset and 'DEFAULT' charset is not same.
121 * The chars in CP_ACP should be drawn with 'DEFAULT' charset.
122 * 'ANSI' charset seems to be identical with ISO-8859-1.
123 * 'DEFAULT' charset is a language-dependent charset.
125 * 'System' font seems to be an alias for language-dependent font.
129 * language-dependent stock fonts for all known charsets
130 * please see TranslateCharsetInfo (dlls/gdi/font.c) and
131 * CharsetBindingInfo (dlls/x11drv/xfont.c),
132 * and modify entries for your language if needed.
134 struct DefaultFontInfo
136 UINT charset;
137 LOGFONTW SystemFont;
138 LOGFONTW DeviceDefaultFont;
139 LOGFONTW SystemFixedFont;
140 LOGFONTW DefaultGuiFont;
143 static const struct DefaultFontInfo default_fonts[] =
145 { ANSI_CHARSET,
146 { /* System */
147 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
148 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
149 {'S','y','s','t','e','m'}
151 { /* Device Default */
152 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
153 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
154 {'S','y','s','t','e','m'}
156 { /* System Fixed */
157 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
158 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
159 {'C','o','u','r','i','e','r'}
161 { /* DefaultGuiFont */
162 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
163 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
164 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
167 { EASTEUROPE_CHARSET,
168 { /* System */
169 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
170 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
171 {'S','y','s','t','e','m'}
173 { /* Device Default */
174 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
175 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
176 {'S','y','s','t','e','m'}
178 { /* System Fixed */
179 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
180 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
181 {'C','o','u','r','i','e','r'}
183 { /* DefaultGuiFont */
184 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
185 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
186 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
189 { RUSSIAN_CHARSET,
190 { /* System */
191 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
192 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
193 {'S','y','s','t','e','m'}
195 { /* Device Default */
196 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
197 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
198 {'S','y','s','t','e','m'}
200 { /* System Fixed */
201 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
202 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
203 {'C','o','u','r','i','e','r'}
205 { /* DefaultGuiFont */
206 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
207 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
208 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
211 { GREEK_CHARSET,
212 { /* System */
213 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GREEK_CHARSET,
214 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
215 {'S','y','s','t','e','m'}
217 { /* Device Default */
218 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GREEK_CHARSET,
219 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
220 {'S','y','s','t','e','m'}
222 { /* System Fixed */
223 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
224 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
225 {'C','o','u','r','i','e','r'}
227 { /* DefaultGuiFont */
228 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
229 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
230 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
233 { TURKISH_CHARSET,
234 { /* System */
235 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, TURKISH_CHARSET,
236 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
237 {'S','y','s','t','e','m'}
239 { /* Device Default */
240 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, TURKISH_CHARSET,
241 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
242 {'S','y','s','t','e','m'}
244 { /* System Fixed */
245 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
246 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
247 {'C','o','u','r','i','e','r'}
249 { /* DefaultGuiFont */
250 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
251 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
252 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
255 { HEBREW_CHARSET,
256 { /* System */
257 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, HEBREW_CHARSET,
258 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
259 {'S','y','s','t','e','m'}
261 { /* Device Default */
262 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, HEBREW_CHARSET,
263 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
264 {'S','y','s','t','e','m'}
266 { /* System Fixed */
267 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
268 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
269 {'C','o','u','r','i','e','r'}
271 { /* DefaultGuiFont */
272 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
273 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
274 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
277 { ARABIC_CHARSET,
278 { /* System */
279 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ARABIC_CHARSET,
280 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
281 {'S','y','s','t','e','m'}
283 { /* Device Default */
284 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ARABIC_CHARSET,
285 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
286 {'S','y','s','t','e','m'}
288 { /* System Fixed */
289 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
290 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
291 {'C','o','u','r','i','e','r'}
293 { /* DefaultGuiFont */
294 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
295 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
296 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
299 { BALTIC_CHARSET,
300 { /* System */
301 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, BALTIC_CHARSET,
302 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
303 {'S','y','s','t','e','m'}
305 { /* Device Default */
306 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, BALTIC_CHARSET,
307 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
308 {'S','y','s','t','e','m'}
310 { /* System Fixed */
311 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
312 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
313 {'C','o','u','r','i','e','r'}
315 { /* DefaultGuiFont */
316 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
317 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
318 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
321 { THAI_CHARSET,
322 { /* System */
323 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, THAI_CHARSET,
324 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
325 {'S','y','s','t','e','m'}
327 { /* Device Default */
328 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, THAI_CHARSET,
329 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
330 {'S','y','s','t','e','m'}
332 { /* System Fixed */
333 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
334 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
335 {'C','o','u','r','i','e','r'}
337 { /* DefaultGuiFont */
338 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
339 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
340 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
343 { SHIFTJIS_CHARSET,
344 { /* System */
345 18, 8, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
346 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
347 {'S','y','s','t','e','m'}
349 { /* Device Default */
350 18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
351 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
352 {'S','y','s','t','e','m'}
354 { /* System Fixed */
355 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
356 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
357 {'C','o','u','r','i','e','r'}
359 { /* DefaultGuiFont */
360 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
361 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
362 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
365 { GB2312_CHARSET,
366 { /* System */
367 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET,
368 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
369 {'S','y','s','t','e','m'}
371 { /* Device Default */
372 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET,
373 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
374 {'S','y','s','t','e','m'}
376 { /* System Fixed */
377 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
378 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
379 {'C','o','u','r','i','e','r'}
381 { /* DefaultGuiFont */
382 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
383 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
384 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
387 { HANGEUL_CHARSET,
388 { /* System */
389 16, 8, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
390 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
391 {'S','y','s','t','e','m'}
393 { /* Device Default */
394 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
395 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
396 {'S','y','s','t','e','m'}
398 { /* System Fixed */
399 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
400 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
401 {'C','o','u','r','i','e','r'}
403 { /* DefaultGuiFont */
404 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
405 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
406 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
409 { CHINESEBIG5_CHARSET,
410 { /* System */
411 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
412 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
413 {'S','y','s','t','e','m'}
415 { /* Device Default */
416 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
417 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
418 {'S','y','s','t','e','m'}
420 { /* System Fixed */
421 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
422 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
423 {'C','o','u','r','i','e','r'}
425 { /* DefaultGuiFont */
426 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
427 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
428 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
431 { JOHAB_CHARSET,
432 { /* System */
433 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, JOHAB_CHARSET,
434 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
435 {'S','y','s','t','e','m'}
437 { /* Device Default */
438 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, JOHAB_CHARSET,
439 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
440 {'S','y','s','t','e','m'}
442 { /* System Fixed */
443 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
444 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
445 {'C','o','u','r','i','e','r'}
447 { /* DefaultGuiFont */
448 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
449 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
450 {'M','S',' ','S','h','e','l','l',' ','D','l','g'}
455 void make_gdi_object_system( HGDIOBJ handle, BOOL set)
457 GDI_HANDLE_ENTRY *entry;
459 pthread_mutex_lock( &gdi_lock );
460 if ((entry = handle_entry( handle ))) entry_obj( entry )->system = !!set;
461 pthread_mutex_unlock( &gdi_lock );
464 /******************************************************************************
465 * get_default_fonts
467 static const struct DefaultFontInfo* get_default_fonts(UINT charset)
469 unsigned int n;
471 for(n = 0; n < ARRAY_SIZE( default_fonts ); n++)
473 if ( default_fonts[n].charset == charset )
474 return &default_fonts[n];
477 FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
478 return &default_fonts[0];
482 /******************************************************************************
483 * get_default_charset (internal)
485 * get the language-dependent charset that can handle CP_ACP correctly.
487 static UINT get_default_charset( void )
489 CHARSETINFO csi;
491 csi.ciCharset = ANSI_CHARSET;
492 if ( !translate_charset_info( ULongToPtr(ansi_cp.CodePage), &csi, TCI_SRCCODEPAGE ) )
494 FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", ansi_cp.CodePage );
495 return ANSI_CHARSET;
498 return csi.ciCharset;
502 /***********************************************************************
503 * GDI_get_ref_count
505 * Retrieve the reference count of a GDI object.
506 * Note: the object must be locked otherwise the count is meaningless.
508 UINT GDI_get_ref_count( HGDIOBJ handle )
510 GDI_HANDLE_ENTRY *entry;
511 UINT ret = 0;
513 pthread_mutex_lock( &gdi_lock );
514 if ((entry = handle_entry( handle ))) ret = entry_obj( entry )->selcount;
515 pthread_mutex_unlock( &gdi_lock );
516 return ret;
520 /***********************************************************************
521 * GDI_inc_ref_count
523 * Increment the reference count of a GDI object.
525 HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle )
527 GDI_HANDLE_ENTRY *entry;
529 pthread_mutex_lock( &gdi_lock );
530 if ((entry = handle_entry( handle ))) entry_obj( entry )->selcount++;
531 else handle = 0;
532 pthread_mutex_unlock( &gdi_lock );
533 return handle;
537 /***********************************************************************
538 * GDI_dec_ref_count
540 * Decrement the reference count of a GDI object.
542 BOOL GDI_dec_ref_count( HGDIOBJ handle )
544 GDI_HANDLE_ENTRY *entry;
546 pthread_mutex_lock( &gdi_lock );
547 if ((entry = handle_entry( handle )))
549 assert( entry_obj( entry )->selcount );
550 if (!--entry_obj( entry )->selcount && entry_obj( entry )->deleted)
552 /* handle delayed DeleteObject*/
553 entry_obj( entry )->deleted = 0;
554 pthread_mutex_unlock( &gdi_lock );
555 TRACE( "executing delayed DeleteObject for %p\n", handle );
556 NtGdiDeleteObjectApp( handle );
557 return TRUE;
560 pthread_mutex_unlock( &gdi_lock );
561 return entry != NULL;
565 static HFONT create_font( const LOGFONTW *deffont )
567 ENUMLOGFONTEXDVW lf;
569 memset( &lf, 0, sizeof(lf) );
570 lf.elfEnumLogfontEx.elfLogFont = *deffont;
571 return NtGdiHfontCreate( &lf, sizeof(lf), 0, 0, NULL );
574 static HFONT create_scaled_font( const LOGFONTW *deffont, unsigned int dpi )
576 LOGFONTW lf;
578 lf = *deffont;
579 lf.lfHeight = muldiv( lf.lfHeight, dpi, 96 );
580 return create_font( &lf );
583 static void init_gdi_shared(void)
585 SIZE_T size = sizeof(*gdi_shared);
587 if (NtAllocateVirtualMemory( GetCurrentProcess(), (void **)&gdi_shared, 0, &size,
588 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ))
589 return;
590 next_unused = gdi_shared->Handles + FIRST_GDI_HANDLE;
592 #ifndef _WIN64
593 if (NtCurrentTeb()->GdiBatchCount)
595 TEB64 *teb64 = (TEB64 *)(UINT_PTR)NtCurrentTeb()->GdiBatchCount;
596 PEB64 *peb64 = (PEB64 *)(UINT_PTR)teb64->Peb;
597 peb64->GdiSharedHandleTable = (UINT_PTR)gdi_shared;
598 return;
600 #endif
601 /* NOTE: Windows uses 32-bit for 32-bit kernel */
602 NtCurrentTeb()->Peb->GdiSharedHandleTable = gdi_shared;
605 HGDIOBJ get_stock_object( INT obj )
607 assert( obj >= 0 && obj <= STOCK_LAST + 1 && obj != 9 );
609 switch (obj)
611 case OEM_FIXED_FONT:
612 if (get_system_dpi() != 96) obj = 9;
613 break;
614 case SYSTEM_FONT:
615 if (get_system_dpi() != 96) obj = STOCK_LAST + 2;
616 break;
617 case SYSTEM_FIXED_FONT:
618 if (get_system_dpi() != 96) obj = STOCK_LAST + 3;
619 break;
620 case DEFAULT_GUI_FONT:
621 if (get_system_dpi() != 96) obj = STOCK_LAST + 4;
622 break;
625 return entry_to_handle( handle_entry( ULongToHandle( obj + FIRST_GDI_HANDLE )));
628 static void init_stock_objects( unsigned int dpi )
630 const struct DefaultFontInfo *deffonts;
631 unsigned int i;
632 HGDIOBJ obj;
634 /* Create stock objects in order matching stock object macros,
635 * so that they use predictable handle slots. Our GetStockObject
636 * depends on it. */
637 create_brush( &WhiteBrush );
638 create_brush( &LtGrayBrush );
639 create_brush( &GrayBrush );
640 create_brush( &DkGrayBrush );
641 create_brush( &BlackBrush );
642 create_brush( &NullBrush );
644 create_pen( PS_SOLID, 0, RGB(255,255,255) );
645 create_pen( PS_SOLID, 0, RGB(0,0,0) );
646 create_pen( PS_NULL, 0, RGB(0,0,0) );
648 /* slot 9 is not used for non-scaled stock objects */
649 create_scaled_font( &OEMFixedFont, dpi );
651 /* language-independent stock fonts */
652 create_font( &OEMFixedFont );
653 create_font( &AnsiFixedFont );
654 create_font( &AnsiVarFont );
656 /* language-dependent stock fonts */
657 deffonts = get_default_fonts(get_default_charset());
658 create_font( &deffonts->SystemFont );
659 create_font( &deffonts->DeviceDefaultFont );
661 PALETTE_Init();
663 create_font( &deffonts->SystemFixedFont );
664 create_font( &deffonts->DefaultGuiFont );
666 create_brush( &DCBrush );
667 NtGdiCreatePen( PS_SOLID, 0, RGB(0,0,0), NULL );
669 obj = NtGdiCreateBitmap( 1, 1, 1, 1, NULL );
671 assert( (HandleToULong( obj ) & 0xffff) == FIRST_GDI_HANDLE + DEFAULT_BITMAP );
673 create_scaled_font( &deffonts->SystemFont, dpi );
674 create_scaled_font( &deffonts->SystemFixedFont, dpi );
675 create_scaled_font( &deffonts->DefaultGuiFont, dpi );
677 /* clear the NOSYSTEM bit on all stock objects*/
678 for (i = 0; i < STOCK_LAST + 5; i++)
680 GDI_HANDLE_ENTRY *entry = &gdi_shared->Handles[FIRST_GDI_HANDLE + i];
681 entry_obj( entry )->system = TRUE;
682 entry->StockFlag = 1;
687 static const char *gdi_obj_type( unsigned type )
689 switch ( type )
691 case NTGDI_OBJ_PEN: return "NTGDI_OBJ_PEN";
692 case NTGDI_OBJ_BRUSH: return "NTGDI_OBJ_BRUSH";
693 case NTGDI_OBJ_DC: return "NTGDI_OBJ_DC";
694 case NTGDI_OBJ_METADC: return "NTGDI_OBJ_METADC";
695 case NTGDI_OBJ_PAL: return "NTGDI_OBJ_PAL";
696 case NTGDI_OBJ_FONT: return "NTGDI_OBJ_FONT";
697 case NTGDI_OBJ_BITMAP: return "NTGDI_OBJ_BITMAP";
698 case NTGDI_OBJ_REGION: return "NTGDI_OBJ_REGION";
699 case NTGDI_OBJ_METAFILE: return "NTGDI_OBJ_METAFILE";
700 case NTGDI_OBJ_MEMDC: return "NTGDI_OBJ_MEMDC";
701 case NTGDI_OBJ_EXTPEN: return "NTGDI_OBJ_EXTPEN";
702 case NTGDI_OBJ_ENHMETADC: return "NTGDI_OBJ_ENHMETADC";
703 case NTGDI_OBJ_ENHMETAFILE: return "NTGDI_OBJ_ENHMETAFILE";
704 default: return "UNKNOWN";
708 static void dump_gdi_objects( void )
710 GDI_HANDLE_ENTRY *entry;
712 TRACE( "%u objects:\n", GDI_MAX_HANDLE_COUNT );
714 pthread_mutex_lock( &gdi_lock );
715 for (entry = gdi_shared->Handles; entry < next_unused; entry++)
717 if (!entry->Type)
718 TRACE( "handle %p FREE\n", entry_to_handle( entry ));
719 else
720 TRACE( "handle %p obj %s type %s selcount %u deleted %u\n",
721 entry_to_handle( entry ), wine_dbgstr_longlong( entry->Object ),
722 gdi_obj_type( entry->ExtType << NTGDI_HANDLE_TYPE_SHIFT ),
723 entry_obj( entry )->selcount, entry_obj( entry )->deleted );
725 pthread_mutex_unlock( &gdi_lock );
728 /***********************************************************************
729 * alloc_gdi_handle
731 * Allocate a GDI handle for an object, which must have been allocated on the process heap.
733 HGDIOBJ alloc_gdi_handle( struct gdi_obj_header *obj, DWORD type, const struct gdi_obj_funcs *funcs )
735 GDI_HANDLE_ENTRY *entry;
736 HGDIOBJ ret;
738 assert( type ); /* type 0 is reserved to mark free entries */
740 pthread_mutex_lock( &gdi_lock );
742 entry = next_free;
743 if (entry)
744 next_free = (GDI_HANDLE_ENTRY *)(UINT_PTR)entry->Object;
745 else if (next_unused < gdi_shared->Handles + GDI_MAX_HANDLE_COUNT)
746 entry = next_unused++;
747 else
749 pthread_mutex_unlock( &gdi_lock );
750 ERR( "out of GDI object handles, expect a crash\n" );
751 if (TRACE_ON(gdi)) dump_gdi_objects();
752 return 0;
754 obj->funcs = funcs;
755 obj->selcount = 0;
756 obj->system = 0;
757 obj->deleted = 0;
758 entry->Object = (UINT_PTR)obj;
759 entry->ExtType = type >> NTGDI_HANDLE_TYPE_SHIFT;
760 entry->Type = entry->ExtType & 0x1f;
761 if (++entry->Generation == 0xff) entry->Generation = 1;
762 ret = entry_to_handle( entry );
763 pthread_mutex_unlock( &gdi_lock );
764 TRACE( "allocated %s %p %u/%u\n", gdi_obj_type(type), ret,
765 InterlockedIncrement( &debug_count ), GDI_MAX_HANDLE_COUNT );
766 return ret;
770 /***********************************************************************
771 * free_gdi_handle
773 * Free a GDI handle and return a pointer to the object.
775 void *free_gdi_handle( HGDIOBJ handle )
777 void *object = NULL;
778 GDI_HANDLE_ENTRY *entry;
780 pthread_mutex_lock( &gdi_lock );
781 if ((entry = handle_entry( handle )))
783 TRACE( "freed %s %p %u/%u\n", gdi_obj_type( entry->ExtType << NTGDI_HANDLE_TYPE_SHIFT ),
784 handle, InterlockedDecrement( &debug_count ) + 1, GDI_MAX_HANDLE_COUNT );
785 object = entry_obj( entry );
786 entry->Type = 0;
787 entry->Object = (UINT_PTR)next_free;
788 next_free = entry;
790 pthread_mutex_unlock( &gdi_lock );
791 return object;
794 DWORD get_gdi_object_type( HGDIOBJ obj )
796 GDI_HANDLE_ENTRY *entry = handle_entry( obj );
797 return entry ? entry->ExtType << NTGDI_HANDLE_TYPE_SHIFT : 0;
800 void set_gdi_client_ptr( HGDIOBJ obj, void *ptr )
802 GDI_HANDLE_ENTRY *entry = handle_entry( obj );
803 if (entry) entry->UserPointer = (UINT_PTR)ptr;
806 /***********************************************************************
807 * get_any_obj_ptr
809 * Return a pointer to, and the type of, the GDI object
810 * associated with the handle.
811 * The object must be released with GDI_ReleaseObj.
813 void *get_any_obj_ptr( HGDIOBJ handle, DWORD *type )
815 void *ptr = NULL;
816 GDI_HANDLE_ENTRY *entry;
818 pthread_mutex_lock( &gdi_lock );
820 if ((entry = handle_entry( handle )))
822 ptr = entry_obj( entry );
823 *type = entry->ExtType << NTGDI_HANDLE_TYPE_SHIFT;
826 if (!ptr) pthread_mutex_unlock( &gdi_lock );
827 return ptr;
830 /***********************************************************************
831 * GDI_GetObjPtr
833 * Return a pointer to the GDI object associated with the handle.
834 * Return NULL if the object has the wrong type.
835 * The object must be released with GDI_ReleaseObj.
837 void *GDI_GetObjPtr( HGDIOBJ handle, DWORD type )
839 DWORD ret_type;
840 void *ptr = get_any_obj_ptr( handle, &ret_type );
841 if (ptr && ret_type != type)
843 GDI_ReleaseObj( handle );
844 ptr = NULL;
846 return ptr;
849 /***********************************************************************
850 * GDI_ReleaseObj
853 void GDI_ReleaseObj( HGDIOBJ handle )
855 pthread_mutex_unlock( &gdi_lock );
859 /***********************************************************************
860 * NtGdiDeleteObjectApp (win32u.@)
862 * Delete a Gdi object.
864 * PARAMS
865 * obj [I] Gdi object to delete
867 * RETURNS
868 * Success: TRUE. If obj was not returned from GetStockObject(), any resources
869 * it consumed are released.
870 * Failure: FALSE, if obj is not a valid Gdi object, or is currently selected
871 * into a DC.
873 BOOL WINAPI NtGdiDeleteObjectApp( HGDIOBJ obj )
875 GDI_HANDLE_ENTRY *entry;
876 const struct gdi_obj_funcs *funcs = NULL;
877 struct gdi_obj_header *header;
879 pthread_mutex_lock( &gdi_lock );
880 if (!(entry = handle_entry( obj )))
882 pthread_mutex_unlock( &gdi_lock );
883 return FALSE;
886 header = entry_obj( entry );
887 if (header->system)
889 TRACE("Preserving system object %p\n", obj);
890 pthread_mutex_unlock( &gdi_lock );
891 return TRUE;
894 obj = entry_to_handle( entry ); /* make it a full handle */
896 if (header->selcount)
898 TRACE("delayed for %p because object in use, count %u\n", obj, header->selcount );
899 header->deleted = 1; /* mark for delete */
901 else funcs = header->funcs;
903 pthread_mutex_unlock( &gdi_lock );
905 TRACE("%p\n", obj );
907 if (funcs && funcs->pDeleteObject) return funcs->pDeleteObject( obj );
908 return TRUE;
911 /***********************************************************************
912 * NtGdiCreateClientObj (win32u.@)
914 HANDLE WINAPI NtGdiCreateClientObj( ULONG type )
916 struct gdi_obj_header *obj;
917 HGDIOBJ handle;
919 if (!(obj = malloc( sizeof(*obj) )))
920 return 0;
922 handle = alloc_gdi_handle( obj, type, NULL );
923 if (!handle) free( obj );
924 return handle;
927 /***********************************************************************
928 * NtGdiDeleteClientObj (win32u.@)
930 BOOL WINAPI NtGdiDeleteClientObj( HGDIOBJ handle )
932 void *obj;
933 if (!(obj = free_gdi_handle( handle ))) return FALSE;
934 free( obj );
935 return TRUE;
939 /***********************************************************************
940 * NtGdiExtGetObjectW (win32u.@)
942 INT WINAPI NtGdiExtGetObjectW( HGDIOBJ handle, INT count, void *buffer )
944 GDI_HANDLE_ENTRY *entry;
945 const struct gdi_obj_funcs *funcs = NULL;
946 INT result = 0;
948 TRACE("%p %d %p\n", handle, count, buffer );
950 pthread_mutex_lock( &gdi_lock );
951 if ((entry = handle_entry( handle )))
953 funcs = entry_obj( entry )->funcs;
954 handle = entry_to_handle( entry ); /* make it a full handle */
956 pthread_mutex_unlock( &gdi_lock );
958 if (funcs && funcs->pGetObjectW)
960 if (buffer && ((ULONG_PTR)buffer >> 16) == 0) /* catch apps getting argument order wrong */
961 SetLastError( ERROR_NOACCESS );
962 else
963 result = funcs->pGetObjectW( handle, count, buffer );
965 return result;
968 /***********************************************************************
969 * NtGdiGetDCObject (win32u.@)
971 * Get the currently selected object of a given type in a device context.
973 HANDLE WINAPI NtGdiGetDCObject( HDC hdc, UINT type )
975 HGDIOBJ ret = 0;
976 DC *dc;
978 if (!(dc = get_dc_ptr( hdc ))) return 0;
980 switch (type)
982 case NTGDI_OBJ_EXTPEN: /* fall through */
983 case NTGDI_OBJ_PEN: ret = dc->hPen; break;
984 case NTGDI_OBJ_BRUSH: ret = dc->hBrush; break;
985 case NTGDI_OBJ_PAL: ret = dc->hPalette; break;
986 case NTGDI_OBJ_FONT: ret = dc->hFont; break;
987 case NTGDI_OBJ_SURF: ret = dc->hBitmap; break;
988 default:
989 FIXME( "(%p, %d): unknown type.\n", hdc, type );
990 break;
992 release_dc_ptr( dc );
993 return ret;
997 /***********************************************************************
998 * NtGdiUnrealizeObject (win32u.@)
1000 BOOL WINAPI NtGdiUnrealizeObject( HGDIOBJ obj )
1002 const struct gdi_obj_funcs *funcs = NULL;
1003 GDI_HANDLE_ENTRY *entry;
1005 pthread_mutex_lock( &gdi_lock );
1006 if ((entry = handle_entry( obj )))
1008 funcs = entry_obj( entry )->funcs;
1009 obj = entry_to_handle( entry ); /* make it a full handle */
1011 pthread_mutex_unlock( &gdi_lock );
1013 if (funcs && funcs->pUnrealizeObject) return funcs->pUnrealizeObject( obj );
1014 return funcs != NULL;
1018 /***********************************************************************
1019 * NtGdiFlush (win32u.@)
1021 BOOL WINAPI NtGdiFlush(void)
1023 return TRUE; /* FIXME */
1027 /*******************************************************************
1028 * NtGdiGetColorAdjustment (win32u.@)
1030 BOOL WINAPI NtGdiGetColorAdjustment( HDC hdc, COLORADJUSTMENT *ca )
1032 FIXME( "stub\n" );
1033 return FALSE;
1036 /*******************************************************************
1037 * NtGdiSetColorAdjustment (win32u.@)
1039 BOOL WINAPI NtGdiSetColorAdjustment( HDC hdc, const COLORADJUSTMENT *ca )
1041 FIXME( "stub\n" );
1042 return FALSE;
1046 static struct unix_funcs unix_funcs =
1048 NtGdiAbortDoc,
1049 NtGdiAbortPath,
1050 NtGdiAlphaBlend,
1051 NtGdiAngleArc,
1052 NtGdiArcInternal,
1053 NtGdiBeginPath,
1054 NtGdiBitBlt,
1055 NtGdiCloseFigure,
1056 NtGdiComputeXformCoefficients,
1057 NtGdiCreateCompatibleBitmap,
1058 NtGdiCreateCompatibleDC,
1059 NtGdiCreateDIBitmapInternal,
1060 NtGdiCreateMetafileDC,
1061 NtGdiDdDDICheckVidPnExclusiveOwnership,
1062 NtGdiDdDDICreateDCFromMemory,
1063 NtGdiDdDDIDestroyDCFromMemory,
1064 NtGdiDdDDIDestroyDevice,
1065 NtGdiDdDDIEscape,
1066 NtGdiDdDDISetVidPnSourceOwner,
1067 NtGdiDeleteObjectApp,
1068 NtGdiDoPalette,
1069 NtGdiEllipse,
1070 NtGdiEndDoc,
1071 NtGdiEndPath,
1072 NtGdiEndPage,
1073 NtGdiEnumFonts,
1074 NtGdiExcludeClipRect,
1075 NtGdiExtEscape,
1076 NtGdiExtFloodFill,
1077 NtGdiExtTextOutW,
1078 NtGdiExtSelectClipRgn,
1079 NtGdiFillPath,
1080 NtGdiFillRgn,
1081 NtGdiFontIsLinked,
1082 NtGdiFrameRgn,
1083 NtGdiGetAndSetDCDword,
1084 NtGdiGetAppClipBox,
1085 NtGdiGetBoundsRect,
1086 NtGdiGetCharABCWidthsW,
1087 NtGdiGetCharWidthW,
1088 NtGdiGetCharWidthInfo,
1089 NtGdiGetDIBitsInternal,
1090 NtGdiGetDeviceCaps,
1091 NtGdiGetDeviceGammaRamp,
1092 NtGdiGetFontData,
1093 NtGdiGetFontUnicodeRanges,
1094 NtGdiGetGlyphIndicesW,
1095 NtGdiGetGlyphOutline,
1096 NtGdiGetKerningPairs,
1097 NtGdiGetNearestColor,
1098 NtGdiGetOutlineTextMetricsInternalW,
1099 NtGdiGetPixel,
1100 NtGdiGetRandomRgn,
1101 NtGdiGetRasterizerCaps,
1102 NtGdiGetRealizationInfo,
1103 NtGdiGetTextCharsetInfo,
1104 NtGdiGetTextExtentExW,
1105 NtGdiGetTextFaceW,
1106 NtGdiGetTextMetricsW,
1107 NtGdiGradientFill,
1108 NtGdiIntersectClipRect,
1109 NtGdiInvertRgn,
1110 NtGdiLineTo,
1111 NtGdiMaskBlt,
1112 NtGdiModifyWorldTransform,
1113 NtGdiMoveTo,
1114 NtGdiOffsetClipRgn,
1115 NtGdiOpenDCW,
1116 NtGdiPatBlt,
1117 NtGdiPlgBlt,
1118 NtGdiPolyDraw,
1119 NtGdiPolyPolyDraw,
1120 NtGdiPtVisible,
1121 NtGdiRectVisible,
1122 NtGdiRectangle,
1123 NtGdiResetDC,
1124 NtGdiResizePalette,
1125 NtGdiRestoreDC,
1126 NtGdiRoundRect,
1127 NtGdiScaleViewportExtEx,
1128 NtGdiScaleWindowExtEx,
1129 NtGdiSelectBitmap,
1130 NtGdiSelectBrush,
1131 NtGdiSelectClipPath,
1132 NtGdiSelectFont,
1133 NtGdiSelectPen,
1134 NtGdiSetBoundsRect,
1135 NtGdiSetDIBitsToDeviceInternal,
1136 NtGdiSetDeviceGammaRamp,
1137 NtGdiSetLayout,
1138 NtGdiSetPixel,
1139 NtGdiSetSystemPaletteUse,
1140 NtGdiStartDoc,
1141 NtGdiStartPage,
1142 NtGdiStretchBlt,
1143 NtGdiStretchDIBitsInternal,
1144 NtGdiStrokeAndFillPath,
1145 NtGdiStrokePath,
1146 NtGdiTransparentBlt,
1147 NtGdiUnrealizeObject,
1148 NtGdiUpdateColors,
1149 NtGdiWidenPath,
1150 NtUserActivateKeyboardLayout,
1151 NtUserBeginPaint,
1152 NtUserCallHwnd,
1153 NtUserCallHwndParam,
1154 NtUserCallNextHookEx,
1155 NtUserCallNoParam,
1156 NtUserCallOneParam,
1157 NtUserCallTwoParam,
1158 NtUserChangeDisplaySettings,
1159 NtUserClipCursor,
1160 NtUserCloseClipboard,
1161 NtUserCountClipboardFormats,
1162 NtUserCreateWindowEx,
1163 NtUserDeferWindowPosAndBand,
1164 NtUserDestroyCursor,
1165 NtUserDestroyMenu,
1166 NtUserDestroyWindow,
1167 NtUserDispatchMessage,
1168 NtUserDrawIconEx,
1169 NtUserEndDeferWindowPosEx,
1170 NtUserEndPaint,
1171 NtUserEnumDisplayDevices,
1172 NtUserEnumDisplayMonitors,
1173 NtUserEnumDisplaySettings,
1174 NtUserFlashWindowEx,
1175 NtUserGetAsyncKeyState,
1176 NtUserGetClassInfoEx,
1177 NtUserGetCursorInfo,
1178 NtUserGetDCEx,
1179 NtUserGetDisplayConfigBufferSizes,
1180 NtUserGetIconInfo,
1181 NtUserGetKeyNameText,
1182 NtUserGetKeyboardLayoutList,
1183 NtUserGetMessage,
1184 NtUserGetPriorityClipboardFormat,
1185 NtUserGetQueueStatus,
1186 NtUserGetUpdateRect,
1187 NtUserGetUpdateRgn,
1188 NtUserGetUpdatedClipboardFormats,
1189 NtUserIsClipboardFormatAvailable,
1190 NtUserMapVirtualKeyEx,
1191 NtUserMessageCall,
1192 NtUserMoveWindow,
1193 NtUserMsgWaitForMultipleObjectsEx,
1194 NtUserPeekMessage,
1195 NtUserPostMessage,
1196 NtUserPostThreadMessage,
1197 NtUserRedrawWindow,
1198 NtUserRegisterClassExWOW,
1199 NtUserRegisterHotKey,
1200 NtUserReleaseDC,
1201 NtUserScrollDC,
1202 NtUserSelectPalette,
1203 NtUserSendInput,
1204 NtUserSetActiveWindow,
1205 NtUserSetCapture,
1206 NtUserSetClassLong,
1207 NtUserSetClassLongPtr,
1208 NtUserSetClassWord,
1209 NtUserSetCursor,
1210 NtUserSetCursorIconData,
1211 NtUserSetCursorPos,
1212 NtUserSetFocus,
1213 NtUserSetLayeredWindowAttributes,
1214 NtUserSetParent,
1215 NtUserSetSysColors,
1216 NtUserSetWindowLong,
1217 NtUserSetWindowLongPtr,
1218 NtUserSetWindowPos,
1219 NtUserSetWindowRgn,
1220 NtUserSetWindowWord,
1221 NtUserShowCursor,
1222 NtUserShowWindow,
1223 NtUserShowWindowAsync,
1224 NtUserSystemParametersInfo,
1225 NtUserSystemParametersInfoForDpi,
1226 NtUserToUnicodeEx,
1227 NtUserUnregisterClass,
1228 NtUserUnregisterHotKey,
1229 NtUserUpdateLayeredWindow,
1230 NtUserVkKeyScanEx,
1231 NtUserWaitForInputIdle,
1232 NtUserWindowFromPoint,
1234 SetDIBits,
1235 __wine_get_brush_bitmap_info,
1236 __wine_get_file_outline_text_metric,
1237 __wine_get_icm_profile,
1238 __wine_get_vulkan_driver,
1239 __wine_get_wgl_driver,
1240 __wine_send_input,
1241 __wine_set_user_driver,
1244 NTSTATUS gdi_init(void)
1246 pthread_mutexattr_t attr;
1247 unsigned int dpi;
1249 pthread_mutexattr_init( &attr );
1250 pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
1251 pthread_mutex_init( &gdi_lock, &attr );
1252 pthread_mutexattr_destroy( &attr );
1254 NtQuerySystemInformation( SystemBasicInformation, &system_info, sizeof(system_info), NULL );
1255 init_gdi_shared();
1256 if (!gdi_shared) return STATUS_NO_MEMORY;
1258 dpi = font_init();
1259 init_stock_objects( dpi );
1260 return 0;
1263 NTSTATUS callbacks_init( void *args )
1265 user_callbacks = *(const struct user_callbacks **)args;
1266 *(const struct unix_funcs **)args = &unix_funcs;
1267 return 0;