win32u: Move menu tracking implementation from user32.
[wine.git] / dlls / win32u / gdiobj.c
blobda2e78be2dd5eff65083782dc5985f6e905d340c
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(void)
469 unsigned int n;
470 CHARSETINFO csi;
472 if (ansi_cp.CodePage == CP_UTF8) return &default_fonts[0];
474 csi.ciCharset = ANSI_CHARSET;
475 translate_charset_info( ULongToPtr(ansi_cp.CodePage), &csi, TCI_SRCCODEPAGE );
477 for(n = 0; n < ARRAY_SIZE( default_fonts ); n++)
478 if ( default_fonts[n].charset == csi.ciCharset )
479 return &default_fonts[n];
481 FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", csi.ciCharset );
482 return &default_fonts[0];
486 /***********************************************************************
487 * GDI_get_ref_count
489 * Retrieve the reference count of a GDI object.
490 * Note: the object must be locked otherwise the count is meaningless.
492 UINT GDI_get_ref_count( HGDIOBJ handle )
494 GDI_HANDLE_ENTRY *entry;
495 UINT ret = 0;
497 pthread_mutex_lock( &gdi_lock );
498 if ((entry = handle_entry( handle ))) ret = entry_obj( entry )->selcount;
499 pthread_mutex_unlock( &gdi_lock );
500 return ret;
504 /***********************************************************************
505 * GDI_inc_ref_count
507 * Increment the reference count of a GDI object.
509 HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle )
511 GDI_HANDLE_ENTRY *entry;
513 pthread_mutex_lock( &gdi_lock );
514 if ((entry = handle_entry( handle ))) entry_obj( entry )->selcount++;
515 else handle = 0;
516 pthread_mutex_unlock( &gdi_lock );
517 return handle;
521 /***********************************************************************
522 * GDI_dec_ref_count
524 * Decrement the reference count of a GDI object.
526 BOOL GDI_dec_ref_count( HGDIOBJ handle )
528 GDI_HANDLE_ENTRY *entry;
530 pthread_mutex_lock( &gdi_lock );
531 if ((entry = handle_entry( handle )))
533 assert( entry_obj( entry )->selcount );
534 if (!--entry_obj( entry )->selcount && entry_obj( entry )->deleted)
536 /* handle delayed DeleteObject*/
537 entry_obj( entry )->deleted = 0;
538 pthread_mutex_unlock( &gdi_lock );
539 TRACE( "executing delayed DeleteObject for %p\n", handle );
540 NtGdiDeleteObjectApp( handle );
541 return TRUE;
544 pthread_mutex_unlock( &gdi_lock );
545 return entry != NULL;
549 static HFONT create_font( const LOGFONTW *deffont )
551 ENUMLOGFONTEXDVW lf;
553 memset( &lf, 0, sizeof(lf) );
554 lf.elfEnumLogfontEx.elfLogFont = *deffont;
555 return NtGdiHfontCreate( &lf, sizeof(lf), 0, 0, NULL );
558 static HFONT create_scaled_font( const LOGFONTW *deffont, unsigned int dpi )
560 LOGFONTW lf;
562 lf = *deffont;
563 lf.lfHeight = muldiv( lf.lfHeight, dpi, 96 );
564 return create_font( &lf );
567 static void init_gdi_shared(void)
569 SIZE_T size = sizeof(*gdi_shared);
571 if (NtAllocateVirtualMemory( GetCurrentProcess(), (void **)&gdi_shared, 0, &size,
572 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ))
573 return;
574 next_unused = gdi_shared->Handles + FIRST_GDI_HANDLE;
576 #ifndef _WIN64
577 if (NtCurrentTeb()->GdiBatchCount)
579 TEB64 *teb64 = (TEB64 *)(UINT_PTR)NtCurrentTeb()->GdiBatchCount;
580 PEB64 *peb64 = (PEB64 *)(UINT_PTR)teb64->Peb;
581 peb64->GdiSharedHandleTable = (UINT_PTR)gdi_shared;
582 return;
584 #endif
585 /* NOTE: Windows uses 32-bit for 32-bit kernel */
586 NtCurrentTeb()->Peb->GdiSharedHandleTable = gdi_shared;
589 /***********************************************************************
590 * GetStockObject (win32u.so)
592 HGDIOBJ WINAPI GetStockObject( INT obj )
594 assert( obj >= 0 && obj <= STOCK_LAST + 1 && obj != 9 );
596 switch (obj)
598 case OEM_FIXED_FONT:
599 if (get_system_dpi() != 96) obj = 9;
600 break;
601 case SYSTEM_FONT:
602 if (get_system_dpi() != 96) obj = STOCK_LAST + 2;
603 break;
604 case SYSTEM_FIXED_FONT:
605 if (get_system_dpi() != 96) obj = STOCK_LAST + 3;
606 break;
607 case DEFAULT_GUI_FONT:
608 if (get_system_dpi() != 96) obj = STOCK_LAST + 4;
609 break;
612 return entry_to_handle( handle_entry( ULongToHandle( obj + FIRST_GDI_HANDLE )));
615 static void init_stock_objects( unsigned int dpi )
617 const struct DefaultFontInfo *deffonts;
618 unsigned int i;
619 HGDIOBJ obj;
621 /* Create stock objects in order matching stock object macros,
622 * so that they use predictable handle slots. Our GetStockObject
623 * depends on it. */
624 create_brush( &WhiteBrush );
625 create_brush( &LtGrayBrush );
626 create_brush( &GrayBrush );
627 create_brush( &DkGrayBrush );
628 create_brush( &BlackBrush );
629 create_brush( &NullBrush );
631 create_pen( PS_SOLID, 0, RGB(255,255,255) );
632 create_pen( PS_SOLID, 0, RGB(0,0,0) );
633 create_pen( PS_NULL, 0, RGB(0,0,0) );
635 /* slot 9 is not used for non-scaled stock objects */
636 create_scaled_font( &OEMFixedFont, dpi );
638 /* language-independent stock fonts */
639 create_font( &OEMFixedFont );
640 create_font( &AnsiFixedFont );
641 create_font( &AnsiVarFont );
643 /* language-dependent stock fonts */
644 deffonts = get_default_fonts();
645 create_font( &deffonts->SystemFont );
646 create_font( &deffonts->DeviceDefaultFont );
648 PALETTE_Init();
650 create_font( &deffonts->SystemFixedFont );
651 create_font( &deffonts->DefaultGuiFont );
653 create_brush( &DCBrush );
654 NtGdiCreatePen( PS_SOLID, 0, RGB(0,0,0), NULL );
656 obj = NtGdiCreateBitmap( 1, 1, 1, 1, NULL );
658 assert( (HandleToULong( obj ) & 0xffff) == FIRST_GDI_HANDLE + DEFAULT_BITMAP );
660 create_scaled_font( &deffonts->SystemFont, dpi );
661 create_scaled_font( &deffonts->SystemFixedFont, dpi );
662 create_scaled_font( &deffonts->DefaultGuiFont, dpi );
664 /* clear the NOSYSTEM bit on all stock objects*/
665 for (i = 0; i < STOCK_LAST + 5; i++)
667 GDI_HANDLE_ENTRY *entry = &gdi_shared->Handles[FIRST_GDI_HANDLE + i];
668 entry_obj( entry )->system = TRUE;
669 entry->StockFlag = 1;
674 static const char *gdi_obj_type( unsigned type )
676 switch ( type )
678 case NTGDI_OBJ_PEN: return "NTGDI_OBJ_PEN";
679 case NTGDI_OBJ_BRUSH: return "NTGDI_OBJ_BRUSH";
680 case NTGDI_OBJ_DC: return "NTGDI_OBJ_DC";
681 case NTGDI_OBJ_METADC: return "NTGDI_OBJ_METADC";
682 case NTGDI_OBJ_PAL: return "NTGDI_OBJ_PAL";
683 case NTGDI_OBJ_FONT: return "NTGDI_OBJ_FONT";
684 case NTGDI_OBJ_BITMAP: return "NTGDI_OBJ_BITMAP";
685 case NTGDI_OBJ_REGION: return "NTGDI_OBJ_REGION";
686 case NTGDI_OBJ_METAFILE: return "NTGDI_OBJ_METAFILE";
687 case NTGDI_OBJ_MEMDC: return "NTGDI_OBJ_MEMDC";
688 case NTGDI_OBJ_EXTPEN: return "NTGDI_OBJ_EXTPEN";
689 case NTGDI_OBJ_ENHMETADC: return "NTGDI_OBJ_ENHMETADC";
690 case NTGDI_OBJ_ENHMETAFILE: return "NTGDI_OBJ_ENHMETAFILE";
691 default: return "UNKNOWN";
695 static void dump_gdi_objects( void )
697 GDI_HANDLE_ENTRY *entry;
699 TRACE( "%u objects:\n", GDI_MAX_HANDLE_COUNT );
701 pthread_mutex_lock( &gdi_lock );
702 for (entry = gdi_shared->Handles; entry < next_unused; entry++)
704 if (!entry->Type)
705 TRACE( "handle %p FREE\n", entry_to_handle( entry ));
706 else
707 TRACE( "handle %p obj %s type %s selcount %u deleted %u\n",
708 entry_to_handle( entry ), wine_dbgstr_longlong( entry->Object ),
709 gdi_obj_type( entry->ExtType << NTGDI_HANDLE_TYPE_SHIFT ),
710 entry_obj( entry )->selcount, entry_obj( entry )->deleted );
712 pthread_mutex_unlock( &gdi_lock );
715 /***********************************************************************
716 * alloc_gdi_handle
718 * Allocate a GDI handle for an object, which must have been allocated on the process heap.
720 HGDIOBJ alloc_gdi_handle( struct gdi_obj_header *obj, DWORD type, const struct gdi_obj_funcs *funcs )
722 GDI_HANDLE_ENTRY *entry;
723 HGDIOBJ ret;
725 assert( type ); /* type 0 is reserved to mark free entries */
727 pthread_mutex_lock( &gdi_lock );
729 entry = next_free;
730 if (entry)
731 next_free = (GDI_HANDLE_ENTRY *)(UINT_PTR)entry->Object;
732 else if (next_unused < gdi_shared->Handles + GDI_MAX_HANDLE_COUNT)
733 entry = next_unused++;
734 else
736 pthread_mutex_unlock( &gdi_lock );
737 ERR( "out of GDI object handles, expect a crash\n" );
738 if (TRACE_ON(gdi)) dump_gdi_objects();
739 return 0;
741 obj->funcs = funcs;
742 obj->selcount = 0;
743 obj->system = 0;
744 obj->deleted = 0;
745 entry->Object = (UINT_PTR)obj;
746 entry->ExtType = type >> NTGDI_HANDLE_TYPE_SHIFT;
747 entry->Type = entry->ExtType & 0x1f;
748 if (++entry->Generation == 0xff) entry->Generation = 1;
749 ret = entry_to_handle( entry );
750 pthread_mutex_unlock( &gdi_lock );
751 TRACE( "allocated %s %p %u/%u\n", gdi_obj_type(type), ret,
752 InterlockedIncrement( &debug_count ), GDI_MAX_HANDLE_COUNT );
753 return ret;
757 /***********************************************************************
758 * free_gdi_handle
760 * Free a GDI handle and return a pointer to the object.
762 void *free_gdi_handle( HGDIOBJ handle )
764 void *object = NULL;
765 GDI_HANDLE_ENTRY *entry;
767 pthread_mutex_lock( &gdi_lock );
768 if ((entry = handle_entry( handle )))
770 TRACE( "freed %s %p %u/%u\n", gdi_obj_type( entry->ExtType << NTGDI_HANDLE_TYPE_SHIFT ),
771 handle, InterlockedDecrement( &debug_count ) + 1, GDI_MAX_HANDLE_COUNT );
772 object = entry_obj( entry );
773 entry->Type = 0;
774 entry->Object = (UINT_PTR)next_free;
775 next_free = entry;
777 pthread_mutex_unlock( &gdi_lock );
778 return object;
781 DWORD get_gdi_object_type( HGDIOBJ obj )
783 GDI_HANDLE_ENTRY *entry = handle_entry( obj );
784 return entry ? entry->ExtType << NTGDI_HANDLE_TYPE_SHIFT : 0;
787 void set_gdi_client_ptr( HGDIOBJ obj, void *ptr )
789 GDI_HANDLE_ENTRY *entry = handle_entry( obj );
790 if (entry) entry->UserPointer = (UINT_PTR)ptr;
793 /***********************************************************************
794 * get_any_obj_ptr
796 * Return a pointer to, and the type of, the GDI object
797 * associated with the handle.
798 * The object must be released with GDI_ReleaseObj.
800 void *get_any_obj_ptr( HGDIOBJ handle, DWORD *type )
802 void *ptr = NULL;
803 GDI_HANDLE_ENTRY *entry;
805 pthread_mutex_lock( &gdi_lock );
807 if ((entry = handle_entry( handle )))
809 ptr = entry_obj( entry );
810 *type = entry->ExtType << NTGDI_HANDLE_TYPE_SHIFT;
813 if (!ptr) pthread_mutex_unlock( &gdi_lock );
814 return ptr;
817 /***********************************************************************
818 * GDI_GetObjPtr
820 * Return a pointer to the GDI object associated with the handle.
821 * Return NULL if the object has the wrong type.
822 * The object must be released with GDI_ReleaseObj.
824 void *GDI_GetObjPtr( HGDIOBJ handle, DWORD type )
826 DWORD ret_type;
827 void *ptr = get_any_obj_ptr( handle, &ret_type );
828 if (ptr && ret_type != type)
830 GDI_ReleaseObj( handle );
831 ptr = NULL;
833 return ptr;
836 /***********************************************************************
837 * GDI_ReleaseObj
840 void GDI_ReleaseObj( HGDIOBJ handle )
842 pthread_mutex_unlock( &gdi_lock );
846 /***********************************************************************
847 * NtGdiDeleteObjectApp (win32u.@)
849 * Delete a Gdi object.
851 * PARAMS
852 * obj [I] Gdi object to delete
854 * RETURNS
855 * Success: TRUE. If obj was not returned from GetStockObject(), any resources
856 * it consumed are released.
857 * Failure: FALSE, if obj is not a valid Gdi object, or is currently selected
858 * into a DC.
860 BOOL WINAPI NtGdiDeleteObjectApp( HGDIOBJ obj )
862 GDI_HANDLE_ENTRY *entry;
863 const struct gdi_obj_funcs *funcs = NULL;
864 struct gdi_obj_header *header;
866 pthread_mutex_lock( &gdi_lock );
867 if (!(entry = handle_entry( obj )))
869 pthread_mutex_unlock( &gdi_lock );
870 return FALSE;
873 header = entry_obj( entry );
874 if (header->system)
876 TRACE("Preserving system object %p\n", obj);
877 pthread_mutex_unlock( &gdi_lock );
878 return TRUE;
881 obj = entry_to_handle( entry ); /* make it a full handle */
883 if (header->selcount)
885 TRACE("delayed for %p because object in use, count %u\n", obj, header->selcount );
886 header->deleted = 1; /* mark for delete */
888 else funcs = header->funcs;
890 pthread_mutex_unlock( &gdi_lock );
892 TRACE("%p\n", obj );
894 if (funcs && funcs->pDeleteObject) return funcs->pDeleteObject( obj );
895 return TRUE;
898 /***********************************************************************
899 * NtGdiCreateClientObj (win32u.@)
901 HANDLE WINAPI NtGdiCreateClientObj( ULONG type )
903 struct gdi_obj_header *obj;
904 HGDIOBJ handle;
906 if (!(obj = malloc( sizeof(*obj) )))
907 return 0;
909 handle = alloc_gdi_handle( obj, type, NULL );
910 if (!handle) free( obj );
911 return handle;
914 /***********************************************************************
915 * NtGdiDeleteClientObj (win32u.@)
917 BOOL WINAPI NtGdiDeleteClientObj( HGDIOBJ handle )
919 void *obj;
920 if (!(obj = free_gdi_handle( handle ))) return FALSE;
921 free( obj );
922 return TRUE;
926 /***********************************************************************
927 * NtGdiExtGetObjectW (win32u.@)
929 INT WINAPI NtGdiExtGetObjectW( HGDIOBJ handle, INT count, void *buffer )
931 GDI_HANDLE_ENTRY *entry;
932 const struct gdi_obj_funcs *funcs = NULL;
933 INT result = 0;
935 TRACE("%p %d %p\n", handle, count, buffer );
937 pthread_mutex_lock( &gdi_lock );
938 if ((entry = handle_entry( handle )))
940 funcs = entry_obj( entry )->funcs;
941 handle = entry_to_handle( entry ); /* make it a full handle */
943 pthread_mutex_unlock( &gdi_lock );
945 if (funcs && funcs->pGetObjectW)
947 if (buffer && ((ULONG_PTR)buffer >> 16) == 0) /* catch apps getting argument order wrong */
948 SetLastError( ERROR_NOACCESS );
949 else
950 result = funcs->pGetObjectW( handle, count, buffer );
952 return result;
955 /***********************************************************************
956 * NtGdiGetDCObject (win32u.@)
958 * Get the currently selected object of a given type in a device context.
960 HANDLE WINAPI NtGdiGetDCObject( HDC hdc, UINT type )
962 HGDIOBJ ret = 0;
963 DC *dc;
965 if (!(dc = get_dc_ptr( hdc ))) return 0;
967 switch (type)
969 case NTGDI_OBJ_EXTPEN: /* fall through */
970 case NTGDI_OBJ_PEN: ret = dc->hPen; break;
971 case NTGDI_OBJ_BRUSH: ret = dc->hBrush; break;
972 case NTGDI_OBJ_PAL: ret = dc->hPalette; break;
973 case NTGDI_OBJ_FONT: ret = dc->hFont; break;
974 case NTGDI_OBJ_SURF: ret = dc->hBitmap; break;
975 default:
976 FIXME( "(%p, %d): unknown type.\n", hdc, type );
977 break;
979 release_dc_ptr( dc );
980 return ret;
984 /***********************************************************************
985 * NtGdiUnrealizeObject (win32u.@)
987 BOOL WINAPI NtGdiUnrealizeObject( HGDIOBJ obj )
989 const struct gdi_obj_funcs *funcs = NULL;
990 GDI_HANDLE_ENTRY *entry;
992 pthread_mutex_lock( &gdi_lock );
993 if ((entry = handle_entry( obj )))
995 funcs = entry_obj( entry )->funcs;
996 obj = entry_to_handle( entry ); /* make it a full handle */
998 pthread_mutex_unlock( &gdi_lock );
1000 if (funcs && funcs->pUnrealizeObject) return funcs->pUnrealizeObject( obj );
1001 return funcs != NULL;
1005 /***********************************************************************
1006 * NtGdiFlush (win32u.@)
1008 BOOL WINAPI NtGdiFlush(void)
1010 return TRUE; /* FIXME */
1014 /*******************************************************************
1015 * NtGdiGetColorAdjustment (win32u.@)
1017 BOOL WINAPI NtGdiGetColorAdjustment( HDC hdc, COLORADJUSTMENT *ca )
1019 FIXME( "stub\n" );
1020 return FALSE;
1023 /*******************************************************************
1024 * NtGdiSetColorAdjustment (win32u.@)
1026 BOOL WINAPI NtGdiSetColorAdjustment( HDC hdc, const COLORADJUSTMENT *ca )
1028 FIXME( "stub\n" );
1029 return FALSE;
1033 static struct unix_funcs unix_funcs =
1035 NtGdiAbortDoc,
1036 NtGdiAbortPath,
1037 NtGdiAlphaBlend,
1038 NtGdiAngleArc,
1039 NtGdiArcInternal,
1040 NtGdiBeginPath,
1041 NtGdiBitBlt,
1042 NtGdiCloseFigure,
1043 NtGdiComputeXformCoefficients,
1044 NtGdiCreateCompatibleBitmap,
1045 NtGdiCreateCompatibleDC,
1046 NtGdiCreateDIBitmapInternal,
1047 NtGdiCreateMetafileDC,
1048 NtGdiDdDDICheckVidPnExclusiveOwnership,
1049 NtGdiDdDDICloseAdapter,
1050 NtGdiDdDDICreateDCFromMemory,
1051 NtGdiDdDDIDestroyDCFromMemory,
1052 NtGdiDdDDIDestroyDevice,
1053 NtGdiDdDDIEscape,
1054 NtGdiDdDDIOpenAdapterFromDeviceName,
1055 NtGdiDdDDIOpenAdapterFromLuid,
1056 NtGdiDdDDIQueryVideoMemoryInfo,
1057 NtGdiDdDDISetVidPnSourceOwner,
1058 NtGdiDeleteObjectApp,
1059 NtGdiDoPalette,
1060 NtGdiEllipse,
1061 NtGdiEndDoc,
1062 NtGdiEndPath,
1063 NtGdiEndPage,
1064 NtGdiEnumFonts,
1065 NtGdiExcludeClipRect,
1066 NtGdiExtEscape,
1067 NtGdiExtFloodFill,
1068 NtGdiExtTextOutW,
1069 NtGdiExtSelectClipRgn,
1070 NtGdiFillPath,
1071 NtGdiFillRgn,
1072 NtGdiFontIsLinked,
1073 NtGdiFrameRgn,
1074 NtGdiGetAndSetDCDword,
1075 NtGdiGetAppClipBox,
1076 NtGdiGetBoundsRect,
1077 NtGdiGetCharABCWidthsW,
1078 NtGdiGetCharWidthW,
1079 NtGdiGetCharWidthInfo,
1080 NtGdiGetDIBitsInternal,
1081 NtGdiGetDeviceCaps,
1082 NtGdiGetDeviceGammaRamp,
1083 NtGdiGetFontData,
1084 NtGdiGetFontUnicodeRanges,
1085 NtGdiGetGlyphIndicesW,
1086 NtGdiGetGlyphOutline,
1087 NtGdiGetKerningPairs,
1088 NtGdiGetNearestColor,
1089 NtGdiGetOutlineTextMetricsInternalW,
1090 NtGdiGetPixel,
1091 NtGdiGetRandomRgn,
1092 NtGdiGetRasterizerCaps,
1093 NtGdiGetRealizationInfo,
1094 NtGdiGetTextCharsetInfo,
1095 NtGdiGetTextExtentExW,
1096 NtGdiGetTextFaceW,
1097 NtGdiGetTextMetricsW,
1098 NtGdiGradientFill,
1099 NtGdiIntersectClipRect,
1100 NtGdiInvertRgn,
1101 NtGdiLineTo,
1102 NtGdiMaskBlt,
1103 NtGdiModifyWorldTransform,
1104 NtGdiMoveTo,
1105 NtGdiOffsetClipRgn,
1106 NtGdiOpenDCW,
1107 NtGdiPatBlt,
1108 NtGdiPlgBlt,
1109 NtGdiPolyDraw,
1110 NtGdiPolyPolyDraw,
1111 NtGdiPtVisible,
1112 NtGdiRectVisible,
1113 NtGdiRectangle,
1114 NtGdiResetDC,
1115 NtGdiResizePalette,
1116 NtGdiRestoreDC,
1117 NtGdiRoundRect,
1118 NtGdiScaleViewportExtEx,
1119 NtGdiScaleWindowExtEx,
1120 NtGdiSelectBitmap,
1121 NtGdiSelectBrush,
1122 NtGdiSelectClipPath,
1123 NtGdiSelectFont,
1124 NtGdiSelectPen,
1125 NtGdiSetBoundsRect,
1126 NtGdiSetDIBitsToDeviceInternal,
1127 NtGdiSetDeviceGammaRamp,
1128 NtGdiSetLayout,
1129 NtGdiSetPixel,
1130 NtGdiSetSystemPaletteUse,
1131 NtGdiStartDoc,
1132 NtGdiStartPage,
1133 NtGdiStretchBlt,
1134 NtGdiStretchDIBitsInternal,
1135 NtGdiStrokeAndFillPath,
1136 NtGdiStrokePath,
1137 NtGdiTransparentBlt,
1138 NtGdiUnrealizeObject,
1139 NtGdiUpdateColors,
1140 NtGdiWidenPath,
1141 NtUserActivateKeyboardLayout,
1142 NtUserBeginPaint,
1143 NtUserCallHwnd,
1144 NtUserCallHwndParam,
1145 NtUserCallNextHookEx,
1146 NtUserCallNoParam,
1147 NtUserCallOneParam,
1148 NtUserCallTwoParam,
1149 NtUserChangeClipboardChain,
1150 NtUserChangeDisplaySettings,
1151 NtUserClipCursor,
1152 NtUserCloseClipboard,
1153 NtUserCountClipboardFormats,
1154 NtUserCreateCaret,
1155 NtUserCreateWindowEx,
1156 NtUserDeferWindowPosAndBand,
1157 NtUserDestroyCursor,
1158 NtUserDestroyMenu,
1159 NtUserDestroyWindow,
1160 NtUserDispatchMessage,
1161 NtUserDragDetect,
1162 NtUserDrawIconEx,
1163 NtUserDrawMenuBarTemp,
1164 NtUserEmptyClipboard,
1165 NtUserEnableMenuItem,
1166 NtUserEndDeferWindowPosEx,
1167 NtUserEndPaint,
1168 NtUserEnumDisplayDevices,
1169 NtUserEnumDisplayMonitors,
1170 NtUserEnumDisplaySettings,
1171 NtUserExcludeUpdateRgn,
1172 NtUserFlashWindowEx,
1173 NtUserGetAsyncKeyState,
1174 NtUserGetClassInfoEx,
1175 NtUserGetClipboardData,
1176 NtUserGetCursorInfo,
1177 NtUserGetDCEx,
1178 NtUserGetDisplayConfigBufferSizes,
1179 NtUserGetIconInfo,
1180 NtUserGetKeyNameText,
1181 NtUserGetKeyboardLayoutList,
1182 NtUserGetMenuBarInfo,
1183 NtUserGetMessage,
1184 NtUserGetPriorityClipboardFormat,
1185 NtUserGetQueueStatus,
1186 NtUserGetSystemMenu,
1187 NtUserGetUpdateRect,
1188 NtUserGetUpdateRgn,
1189 NtUserGetUpdatedClipboardFormats,
1190 NtUserGetWindowPlacement,
1191 NtUserHideCaret,
1192 NtUserHiliteMenuItem,
1193 NtUserInternalGetWindowIcon,
1194 NtUserInvalidateRect,
1195 NtUserInvalidateRgn,
1196 NtUserIsClipboardFormatAvailable,
1197 NtUserMapVirtualKeyEx,
1198 NtUserMessageCall,
1199 NtUserMoveWindow,
1200 NtUserMsgWaitForMultipleObjectsEx,
1201 NtUserOpenClipboard,
1202 NtUserPeekMessage,
1203 NtUserPostMessage,
1204 NtUserPostThreadMessage,
1205 NtUserRedrawWindow,
1206 NtUserRegisterClassExWOW,
1207 NtUserRegisterHotKey,
1208 NtUserReleaseDC,
1209 NtUserScrollDC,
1210 NtUserScrollWindowEx,
1211 NtUserSelectPalette,
1212 NtUserSendInput,
1213 NtUserSetActiveWindow,
1214 NtUserSetCapture,
1215 NtUserSetClipboardData,
1216 NtUserSetClassLong,
1217 NtUserSetClassLongPtr,
1218 NtUserSetClassWord,
1219 NtUserSetClipboardViewer,
1220 NtUserSetCursor,
1221 NtUserSetCursorIconData,
1222 NtUserSetCursorPos,
1223 NtUserSetFocus,
1224 NtUserSetInternalWindowPos,
1225 NtUserSetLayeredWindowAttributes,
1226 NtUserSetMenu,
1227 NtUserSetParent,
1228 NtUserSetSysColors,
1229 NtUserSetSystemMenu,
1230 NtUserSetWindowLong,
1231 NtUserSetWindowLongPtr,
1232 NtUserSetWindowPlacement,
1233 NtUserSetWindowPos,
1234 NtUserSetWindowRgn,
1235 NtUserSetWindowWord,
1236 NtUserShowCaret,
1237 NtUserShowCursor,
1238 NtUserShowWindow,
1239 NtUserShowWindowAsync,
1240 NtUserSystemParametersInfo,
1241 NtUserSystemParametersInfoForDpi,
1242 NtUserToUnicodeEx,
1243 NtUserTrackMouseEvent,
1244 NtUserTrackPopupMenuEx,
1245 NtUserTranslateAccelerator,
1246 NtUserTranslateMessage,
1247 NtUserUnregisterClass,
1248 NtUserUnregisterHotKey,
1249 NtUserUpdateLayeredWindow,
1250 NtUserVkKeyScanEx,
1251 NtUserWaitForInputIdle,
1252 NtUserWindowFromPoint,
1254 SetDIBits,
1255 __wine_get_brush_bitmap_info,
1256 __wine_get_file_outline_text_metric,
1257 __wine_get_icm_profile,
1258 __wine_get_vulkan_driver,
1259 __wine_get_wgl_driver,
1260 __wine_send_input,
1263 NTSTATUS gdi_init(void)
1265 pthread_mutexattr_t attr;
1266 unsigned int dpi;
1268 pthread_mutexattr_init( &attr );
1269 pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
1270 pthread_mutex_init( &gdi_lock, &attr );
1271 pthread_mutexattr_destroy( &attr );
1273 NtQuerySystemInformation( SystemBasicInformation, &system_info, sizeof(system_info), NULL );
1274 init_gdi_shared();
1275 if (!gdi_shared) return STATUS_NO_MEMORY;
1277 dpi = font_init();
1278 init_stock_objects( dpi );
1279 return 0;
1282 NTSTATUS callbacks_init( void *args )
1284 user_callbacks = *(const struct user_callbacks **)args;
1285 *(const struct unix_funcs **)args = &unix_funcs;
1286 return 0;