4 * Copyright 1993 Alexandre Julliard
5 * Copyright 2021 Jacek Caban for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WIN32_NO_STATUS
26 #include "gdi_private.h"
34 #include "wine/rbtree.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(gdi
);
40 DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID
, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
42 #define FIRST_GDI_HANDLE 32
49 void (*delete)( HDC hdc
, HGDIOBJ handle
);
50 struct hdc_list
*next
;
55 struct wine_rb_entry entry
;
56 struct hdc_list
*list
;
60 static CRITICAL_SECTION obj_map_cs
;
61 static CRITICAL_SECTION_DEBUG obj_map_debug
=
64 { &obj_map_debug
.ProcessLocksList
, &obj_map_debug
.ProcessLocksList
},
65 0, 0, { (DWORD_PTR
)(__FILE__
": obj_map_cs") }
67 static CRITICAL_SECTION obj_map_cs
= { &obj_map_debug
, -1, 0, 0, 0, 0 };
69 static GDI_SHARED_MEMORY
*get_gdi_shared(void)
72 if (NtCurrentTeb()->GdiBatchCount
)
74 TEB64
*teb64
= (TEB64
*)(UINT_PTR
)NtCurrentTeb()->GdiBatchCount
;
75 PEB64
*peb64
= (PEB64
*)(UINT_PTR
)teb64
->Peb
;
76 return (GDI_SHARED_MEMORY
*)(UINT_PTR
)peb64
->GdiSharedHandleTable
;
79 return (GDI_SHARED_MEMORY
*)NtCurrentTeb()->Peb
->GdiSharedHandleTable
;
82 static BOOL
is_stock_object( HGDIOBJ obj
)
84 unsigned int handle
= HandleToULong( obj
);
85 return !!(handle
& NTGDI_HANDLE_STOCK_OBJECT
);
88 static inline GDI_HANDLE_ENTRY
*handle_entry( HGDIOBJ handle
)
90 GDI_SHARED_MEMORY
*gdi_shared
= get_gdi_shared();
91 unsigned int idx
= LOWORD(handle
);
93 if (idx
< GDI_MAX_HANDLE_COUNT
&& gdi_shared
->Handles
[idx
].Type
)
95 if (!HIWORD( handle
) || HIWORD( handle
) == gdi_shared
->Handles
[idx
].Unique
)
96 return &gdi_shared
->Handles
[idx
];
98 if (handle
) WARN( "invalid handle %p\n", handle
);
102 static HGDIOBJ
entry_to_handle( GDI_HANDLE_ENTRY
*entry
)
104 unsigned int idx
= entry
- get_gdi_shared()->Handles
;
105 return ULongToHandle( idx
| (entry
->Unique
<< NTGDI_HANDLE_TYPE_SHIFT
) );
108 static DWORD
get_object_type( HGDIOBJ obj
)
110 GDI_HANDLE_ENTRY
*entry
= handle_entry( obj
);
111 return entry
? entry
->ExtType
<< NTGDI_HANDLE_TYPE_SHIFT
: 0;
114 void set_gdi_client_ptr( HGDIOBJ obj
, void *ptr
)
116 GDI_HANDLE_ENTRY
*entry
= handle_entry( obj
);
117 if (entry
) entry
->UserPointer
= (UINT_PTR
)ptr
;
120 void *get_gdi_client_ptr( HGDIOBJ obj
, DWORD type
)
122 GDI_HANDLE_ENTRY
*entry
= handle_entry( obj
);
123 if (!entry
|| (type
&& entry
->ExtType
<< NTGDI_HANDLE_TYPE_SHIFT
!= type
))
125 return (void *)(UINT_PTR
)entry
->UserPointer
;
128 HGDIOBJ
get_full_gdi_handle( HGDIOBJ obj
)
130 GDI_HANDLE_ENTRY
*entry
= handle_entry( obj
);
131 return entry
? entry_to_handle( entry
) : 0;
134 /***********************************************************************
137 * GDI initialization.
139 BOOL WINAPI
DllMain( HINSTANCE inst
, DWORD reason
, LPVOID reserved
)
141 if (reason
!= DLL_PROCESS_ATTACH
) return TRUE
;
143 DisableThreadLibraryCalls( inst
);
148 /***********************************************************************
149 * GetObjectType (GDI32.@)
151 DWORD WINAPI
GetObjectType( HGDIOBJ handle
)
153 DWORD type
= get_object_type( handle
);
155 TRACE( "%p -> %lu\n", handle
, type
);
159 case NTGDI_OBJ_PEN
: return OBJ_PEN
;
160 case NTGDI_OBJ_BRUSH
: return OBJ_BRUSH
;
161 case NTGDI_OBJ_DC
: return OBJ_DC
;
162 case NTGDI_OBJ_METADC
: return OBJ_METADC
;
163 case NTGDI_OBJ_PAL
: return OBJ_PAL
;
164 case NTGDI_OBJ_FONT
: return OBJ_FONT
;
165 case NTGDI_OBJ_BITMAP
: return OBJ_BITMAP
;
166 case NTGDI_OBJ_REGION
: return OBJ_REGION
;
167 case NTGDI_OBJ_METAFILE
: return OBJ_METAFILE
;
168 case NTGDI_OBJ_MEMDC
: return OBJ_MEMDC
;
169 case NTGDI_OBJ_EXTPEN
: return OBJ_EXTPEN
;
170 case NTGDI_OBJ_ENHMETADC
: return OBJ_ENHMETADC
;
171 case NTGDI_OBJ_ENHMETAFILE
: return OBJ_ENHMETAFILE
;
173 SetLastError( ERROR_INVALID_HANDLE
);
178 static int obj_map_cmp( const void *key
, const struct wine_rb_entry
*entry
)
180 struct obj_map_entry
*obj_entry
= WINE_RB_ENTRY_VALUE( entry
, struct obj_map_entry
, entry
);
181 UINT_PTR a
= (UINT_PTR
)key
;
182 UINT_PTR b
= (UINT_PTR
)obj_entry
->obj
;
184 if (a
< b
) return -1;
188 struct wine_rb_tree obj_map
= { obj_map_cmp
};
190 /***********************************************************************
191 * DeleteObject (GDI32.@)
193 * Delete a Gdi object.
195 BOOL WINAPI
DeleteObject( HGDIOBJ obj
)
197 struct hdc_list
*hdc_list
= NULL
;
198 struct wine_rb_entry
*entry
;
200 obj
= get_full_gdi_handle( obj
);
201 switch (gdi_handle_type( obj
))
204 case NTGDI_OBJ_MEMDC
:
205 case NTGDI_OBJ_ENHMETADC
:
206 case NTGDI_OBJ_METADC
:
207 return DeleteDC( obj
);
210 EnterCriticalSection( &obj_map_cs
);
212 if ((entry
= wine_rb_get( &obj_map
, obj
)))
214 struct obj_map_entry
*obj_entry
= WINE_RB_ENTRY_VALUE( entry
, struct obj_map_entry
, entry
);
215 wine_rb_remove( &obj_map
, entry
);
216 hdc_list
= obj_entry
->list
;
217 HeapFree( GetProcessHeap(), 0, obj_entry
);
220 LeaveCriticalSection( &obj_map_cs
);
224 struct hdc_list
*next
= hdc_list
->next
;
226 TRACE( "hdc %p has interest in %p\n", hdc_list
->hdc
, obj
);
228 hdc_list
->delete( hdc_list
->hdc
, obj
);
229 HeapFree( GetProcessHeap(), 0, hdc_list
);
233 return NtGdiDeleteObjectApp( obj
);
236 /***********************************************************************
237 * GDI_hdc_using_object
239 * Call this if the dc requires DeleteObject notification
241 void GDI_hdc_using_object( HGDIOBJ obj
, HDC hdc
, void (*delete)( HDC hdc
, HGDIOBJ handle
))
243 struct hdc_list
*hdc_list
;
244 GDI_HANDLE_ENTRY
*entry
;
246 TRACE( "obj %p hdc %p\n", obj
, hdc
);
248 EnterCriticalSection( &obj_map_cs
);
249 if (!is_stock_object( obj
) && (entry
= handle_entry( obj
)))
251 struct obj_map_entry
*map_entry
;
252 struct wine_rb_entry
*entry
;
254 if (!(entry
= wine_rb_get( &obj_map
, obj
)))
256 if (!(map_entry
= HeapAlloc( GetProcessHeap(), 0, sizeof(*map_entry
) )))
258 LeaveCriticalSection( &obj_map_cs
);
261 map_entry
->obj
= obj
;
262 map_entry
->list
= NULL
;
263 wine_rb_put( &obj_map
, obj
, &map_entry
->entry
);
265 else map_entry
= WINE_RB_ENTRY_VALUE( entry
, struct obj_map_entry
, entry
);
267 for (hdc_list
= map_entry
->list
; hdc_list
; hdc_list
= hdc_list
->next
)
268 if (hdc_list
->hdc
== hdc
) break;
272 if (!(hdc_list
= HeapAlloc( GetProcessHeap(), 0, sizeof(*hdc_list
) )))
274 LeaveCriticalSection( &obj_map_cs
);
278 hdc_list
->delete = delete;
279 hdc_list
->next
= map_entry
->list
;
280 map_entry
->list
= hdc_list
;
283 LeaveCriticalSection( &obj_map_cs
);
286 /***********************************************************************
287 * GDI_hdc_not_using_object
290 void GDI_hdc_not_using_object( HGDIOBJ obj
, HDC hdc
)
292 struct wine_rb_entry
*entry
;
294 TRACE( "obj %p hdc %p\n", obj
, hdc
);
296 EnterCriticalSection( &obj_map_cs
);
297 if ((entry
= wine_rb_get( &obj_map
, obj
)))
299 struct obj_map_entry
*map_entry
= WINE_RB_ENTRY_VALUE( entry
, struct obj_map_entry
, entry
);
300 struct hdc_list
**list_ptr
, *hdc_list
;
302 for (list_ptr
= &map_entry
->list
; *list_ptr
; list_ptr
= &(*list_ptr
)->next
)
304 if ((*list_ptr
)->hdc
!= hdc
) continue;
306 hdc_list
= *list_ptr
;
307 *list_ptr
= hdc_list
->next
;
308 HeapFree( GetProcessHeap(), 0, hdc_list
);
309 if (list_ptr
== &map_entry
->list
&& !*list_ptr
)
311 wine_rb_remove( &obj_map
, &map_entry
->entry
);
312 HeapFree( GetProcessHeap(), 0, map_entry
);
317 LeaveCriticalSection( &obj_map_cs
);
320 /***********************************************************************
321 * SelectObject (GDI32.@)
323 * Select a Gdi object into a device context.
325 HGDIOBJ WINAPI
SelectObject( HDC hdc
, HGDIOBJ obj
)
330 TRACE( "(%p,%p)\n", hdc
, obj
);
332 obj
= get_full_gdi_handle( obj
);
333 if (is_meta_dc( hdc
)) return METADC_SelectObject( hdc
, obj
);
334 if (!(dc_attr
= get_dc_attr( hdc
))) return 0;
335 if (dc_attr
->emf
&& !EMFDC_SelectObject( dc_attr
, obj
)) return 0;
337 switch (get_object_type( obj
))
340 case NTGDI_OBJ_EXTPEN
:
341 ret
= NtGdiSelectPen( hdc
, obj
);
343 case NTGDI_OBJ_BRUSH
:
344 ret
= NtGdiSelectBrush( hdc
, obj
);
347 ret
= NtGdiSelectFont( hdc
, obj
);
349 case NTGDI_OBJ_BITMAP
:
350 ret
= NtGdiSelectBitmap( hdc
, obj
);
352 case NTGDI_OBJ_REGION
:
353 ret
= ULongToHandle(SelectClipRgn( hdc
, obj
));
359 if (!ret
) SetLastError( ERROR_INVALID_HANDLE
);
363 /***********************************************************************
364 * GetObjectW (GDI32.@)
366 INT WINAPI
GetObjectW( HGDIOBJ handle
, INT count
, void *buffer
)
370 TRACE( "%p %d %p\n", handle
, count
, buffer
);
372 result
= NtGdiExtGetObjectW( handle
, count
, buffer
);
373 if (!result
&& count
)
375 switch(get_object_type( handle
))
378 case NTGDI_OBJ_BITMAP
:
379 case NTGDI_OBJ_BRUSH
:
383 case NTGDI_OBJ_EXTPEN
:
386 SetLastError( ERROR_INVALID_HANDLE
);
392 /***********************************************************************
393 * GetCurrentObject (GDI32.@)
395 HGDIOBJ WINAPI
GetCurrentObject( HDC hdc
, UINT type
)
397 unsigned int obj_type
;
401 case OBJ_EXTPEN
: obj_type
= NTGDI_OBJ_EXTPEN
; break;
402 case OBJ_PEN
: obj_type
= NTGDI_OBJ_PEN
; break;
403 case OBJ_BRUSH
: obj_type
= NTGDI_OBJ_BRUSH
; break;
404 case OBJ_PAL
: obj_type
= NTGDI_OBJ_PAL
; break;
405 case OBJ_FONT
: obj_type
= NTGDI_OBJ_FONT
; break;
406 case OBJ_BITMAP
: obj_type
= NTGDI_OBJ_SURF
; break;
408 /* tests show that OBJ_REGION is explicitly ignored */
411 FIXME( "(%p,%d): unknown type.\n", hdc
, type
);
415 return NtGdiGetDCObject( hdc
, obj_type
);
418 /***********************************************************************
419 * GetStockObject (GDI32.@)
421 HGDIOBJ WINAPI
GetStockObject( INT obj
)
423 if (obj
< 0 || obj
> STOCK_LAST
+ 1 || obj
== 9) return 0;
425 /* Wine stores stock objects in predictable order, see init_stock_objects */
429 if (GetDpiForSystem() != 96) obj
= 9;
432 if (GetDpiForSystem() != 96) obj
= STOCK_LAST
+ 2;
434 case SYSTEM_FIXED_FONT
:
435 if (GetDpiForSystem() != 96) obj
= STOCK_LAST
+ 3;
437 case DEFAULT_GUI_FONT
:
438 if (GetDpiForSystem() != 96) obj
= STOCK_LAST
+ 4;
442 return entry_to_handle( handle_entry( ULongToHandle( obj
+ FIRST_GDI_HANDLE
)));
445 /***********************************************************************
446 * GetObjectA (GDI32.@)
448 INT WINAPI
GetObjectA( HGDIOBJ handle
, INT count
, void *buffer
)
450 TRACE("%p %d %p\n", handle
, count
, buffer
);
452 if (get_object_type( handle
) == NTGDI_OBJ_FONT
)
454 LOGFONTA
*lfA
= buffer
;
457 if (!buffer
) return sizeof(*lfA
);
458 if (!GetObjectW( handle
, sizeof(lf
), &lf
)) return 0;
459 if (count
> sizeof(*lfA
)) count
= sizeof(*lfA
);
460 memcpy( lfA
, &lf
, min( count
, FIELD_OFFSET(LOGFONTA
, lfFaceName
) ));
461 if (count
> FIELD_OFFSET(LOGFONTA
, lfFaceName
))
463 WideCharToMultiByte( CP_ACP
, 0, lf
.lfFaceName
, -1, lfA
->lfFaceName
,
464 count
- FIELD_OFFSET(LOGFONTA
, lfFaceName
), NULL
, NULL
);
465 if (count
== sizeof(*lfA
)) lfA
->lfFaceName
[LF_FACESIZE
- 1] = 0;
470 return GetObjectW( handle
, count
, buffer
);
473 /***********************************************************************
474 * CreatePenIndirect (GDI32.@)
476 HPEN WINAPI
CreatePenIndirect( const LOGPEN
*pen
)
478 return CreatePen( pen
->lopnStyle
, pen
->lopnWidth
.x
, pen
->lopnColor
);
481 /***********************************************************************
482 * CreatePen (GDI32.@)
484 HPEN WINAPI
CreatePen( INT style
, INT width
, COLORREF color
)
486 if (style
< 0 || style
> PS_INSIDEFRAME
) style
= PS_SOLID
;
487 return NtGdiCreatePen( style
, width
, color
, NULL
);
490 /***********************************************************************
491 * ExtCreatePen (GDI32.@)
493 HPEN WINAPI
ExtCreatePen( DWORD style
, DWORD width
, const LOGBRUSH
*brush
, DWORD style_count
,
494 const DWORD
*style_bits
)
496 ULONG brush_style
= brush
->lbStyle
;
497 ULONG_PTR hatch
= brush
->lbHatch
;
500 if (brush_style
== BS_DIBPATTERN
)
502 if (!(hatch
= (ULONG_PTR
)GlobalLock( (HGLOBAL
)hatch
))) return 0;
503 brush_style
= BS_DIBPATTERNPT
;
506 pen
= NtGdiExtCreatePen( style
, width
, brush_style
, brush
->lbColor
, brush
->lbHatch
, hatch
,
507 style_count
, style_bits
, /* FIXME */ 0, FALSE
, NULL
);
509 if (brush
->lbStyle
== BS_DIBPATTERN
) GlobalUnlock( (HGLOBAL
)brush
->lbHatch
);
513 /***********************************************************************
514 * CreateBrushIndirect (GDI32.@)
516 HBRUSH WINAPI
CreateBrushIndirect( const LOGBRUSH
*brush
)
518 switch (brush
->lbStyle
)
521 return GetStockObject( NULL_BRUSH
);
523 return CreateSolidBrush( brush
->lbColor
);
525 return CreateHatchBrush( brush
->lbHatch
, brush
->lbColor
);
528 return CreatePatternBrush( (HBITMAP
)brush
->lbHatch
);
530 return CreateDIBPatternBrush( (HGLOBAL
)brush
->lbHatch
, brush
->lbColor
);
531 case BS_DIBPATTERNPT
:
532 return CreateDIBPatternBrushPt( (void *)brush
->lbHatch
, brush
->lbColor
);
534 WARN( "invalid brush style %u\n", brush
->lbStyle
);
539 /***********************************************************************
540 * CreateSolidBrush (GDI32.@)
542 HBRUSH WINAPI
CreateSolidBrush( COLORREF color
)
544 return NtGdiCreateSolidBrush( color
, NULL
);
547 /***********************************************************************
548 * CreateHatchBrush (GDI32.@)
550 HBRUSH WINAPI
CreateHatchBrush( INT style
, COLORREF color
)
552 return NtGdiCreateHatchBrushInternal( style
, color
, FALSE
);
555 /***********************************************************************
556 * CreatePatternBrush (GDI32.@)
558 HBRUSH WINAPI
CreatePatternBrush( HBITMAP bitmap
)
560 return NtGdiCreatePatternBrushInternal( bitmap
, FALSE
, FALSE
);
563 /***********************************************************************
564 * CreateDIBPatternBrush (GDI32.@)
566 HBRUSH WINAPI
CreateDIBPatternBrush( HGLOBAL hbitmap
, UINT coloruse
)
571 TRACE( "%p\n", hbitmap
);
573 if (!(mem
= GlobalLock( hbitmap
))) return 0;
574 brush
= NtGdiCreateDIBBrush( mem
, coloruse
, /* FIXME */ 0, FALSE
, FALSE
, hbitmap
);
575 GlobalUnlock( hbitmap
);
579 /***********************************************************************
580 * CreateDIBPatternBrushPt (GDI32.@)
582 HBRUSH WINAPI
CreateDIBPatternBrushPt( const void *data
, UINT coloruse
)
584 return NtGdiCreateDIBBrush( data
, coloruse
, /* FIXME */ 0, FALSE
, FALSE
, data
);
587 /***********************************************************************
588 * CreateBitmapIndirect (GDI32.@)
590 HBITMAP WINAPI
CreateBitmapIndirect( const BITMAP
*bmp
)
592 if (!bmp
|| bmp
->bmType
)
594 SetLastError( ERROR_INVALID_PARAMETER
);
598 return CreateBitmap( bmp
->bmWidth
, bmp
->bmHeight
, bmp
->bmPlanes
,
599 bmp
->bmBitsPixel
, bmp
->bmBits
);
602 /******************************************************************************
603 * CreateBitmap (GDI32.@)
605 * Creates a bitmap with the specified info.
607 HBITMAP WINAPI
CreateBitmap( INT width
, INT height
, UINT planes
,
608 UINT bpp
, const void *bits
)
610 if (!width
|| !height
)
611 return GetStockObject( STOCK_LAST
+ 1 ); /* default 1x1 bitmap */
613 return NtGdiCreateBitmap( width
, height
, planes
, bpp
, bits
);
616 /******************************************************************************
617 * CreateCompatibleBitmap (GDI32.@)
619 * Creates a bitmap compatible with the DC.
621 HBITMAP WINAPI
CreateCompatibleBitmap( HDC hdc
, INT width
, INT height
)
623 if (!width
|| !height
)
624 return GetStockObject( STOCK_LAST
+ 1 ); /* default 1x1 bitmap */
626 return NtGdiCreateCompatibleBitmap( hdc
, width
, height
);
629 /******************************************************************************
630 * CreateDiscardableBitmap (GDI32.@)
632 * Creates a discardable bitmap.
634 HBITMAP WINAPI
CreateDiscardableBitmap( HDC hdc
, INT width
, INT height
)
636 return CreateCompatibleBitmap( hdc
, width
, height
);
639 /***********************************************************************
640 * ExtCreateRegion (GDI32.@)
642 * Creates a region as specified by the transformation data and region data.
644 HRGN WINAPI
ExtCreateRegion( const XFORM
*xform
, DWORD count
, const RGNDATA
*data
)
648 SetLastError( ERROR_INVALID_PARAMETER
);
652 return NtGdiExtCreateRegion( xform
, count
, data
);
655 /***********************************************************************
656 * CreatePolyPolygonRgn (GDI32.@)
658 HRGN WINAPI
CreatePolyPolygonRgn( const POINT
*points
, const INT
*counts
, INT count
, INT mode
)
660 ULONG ret
= NtGdiPolyPolyDraw( ULongToHandle(mode
), points
, (const ULONG
*)counts
,
661 count
, NtGdiPolyPolygonRgn
);
662 return ULongToHandle( ret
);
665 /***********************************************************************
666 * CreateRectRgnIndirect (GDI32.@)
668 * Creates a simple rectangular region.
670 HRGN WINAPI
CreateRectRgnIndirect( const RECT
* rect
)
672 return NtGdiCreateRectRgn( rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
675 /***********************************************************************
676 * CreateEllipticRgnIndirect (GDI32.@)
678 * Creates an elliptical region.
680 HRGN WINAPI
CreateEllipticRgnIndirect( const RECT
*rect
)
682 return NtGdiCreateEllipticRgn( rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
685 /***********************************************************************
686 * CreatePolygonRgn (GDI32.@)
688 HRGN WINAPI
CreatePolygonRgn( const POINT
*points
, INT count
, INT mode
)
690 return CreatePolyPolygonRgn( points
, &count
, 1, mode
);
693 /***********************************************************************
694 * MirrorRgn (GDI32.@)
696 BOOL WINAPI
MirrorRgn( HWND hwnd
, HRGN hrgn
)
698 return NtUserMirrorRgn( hwnd
, hrgn
);
701 /***********************************************************************
702 * CreateColorSpaceA (GDI32.@)
704 HCOLORSPACE WINAPI
CreateColorSpaceA( LOGCOLORSPACEA
*cs
)
710 /***********************************************************************
711 * CreateColorSpaceW (GDI32.@)
713 HCOLORSPACE WINAPI
CreateColorSpaceW( LOGCOLORSPACEW
*cs
)
719 /***********************************************************************
720 * DeleteColorSpace (GDI32.@)
722 BOOL WINAPI
DeleteColorSpace( HCOLORSPACE cs
)
728 /***********************************************************************
729 * GetColorSpace (GDI32.@)
731 HCOLORSPACE WINAPI
GetColorSpace( HDC hdc
)
737 /***********************************************************************
738 * SetColorSpace (GDI32.@)
740 HCOLORSPACE WINAPI
SetColorSpace( HDC hdc
, HCOLORSPACE cs
)
746 /***********************************************************************
747 * CreatePalette (GDI32.@)
749 HPALETTE WINAPI
CreatePalette( const LOGPALETTE
*palette
)
751 if (!palette
) return 0;
752 return NtGdiCreatePaletteInternal( palette
, palette
->palNumEntries
);
755 /***********************************************************************
756 * GetPaletteEntries (GDI32.@)
758 UINT WINAPI
GetPaletteEntries( HPALETTE palette
, UINT start
, UINT count
, PALETTEENTRY
*entries
)
760 return NtGdiDoPalette( palette
, start
, count
, entries
, NtGdiGetPaletteEntries
, TRUE
);
763 /***********************************************************************
764 * SetPaletteEntries (GDI32.@)
766 UINT WINAPI
SetPaletteEntries( HPALETTE palette
, UINT start
, UINT count
,
767 const PALETTEENTRY
*entries
)
769 palette
= get_full_gdi_handle( palette
);
770 return NtGdiDoPalette( palette
, start
, count
, (void *)entries
, NtGdiSetPaletteEntries
, FALSE
);
773 /***********************************************************************
774 * AnimatePalette (GDI32.@)
776 BOOL WINAPI
AnimatePalette( HPALETTE palette
, UINT start
, UINT count
, const PALETTEENTRY
*entries
)
778 palette
= get_full_gdi_handle( palette
);
779 return NtGdiDoPalette( palette
, start
, count
, (void *)entries
, NtGdiAnimatePalette
, FALSE
);
782 /* first and last 10 entries are the default system palette entries */
783 static const PALETTEENTRY default_system_palette_low
[] =
785 { 0x00, 0x00, 0x00 }, { 0x80, 0x00, 0x00 }, { 0x00, 0x80, 0x00 }, { 0x80, 0x80, 0x00 },
786 { 0x00, 0x00, 0x80 }, { 0x80, 0x00, 0x80 }, { 0x00, 0x80, 0x80 }, { 0xc0, 0xc0, 0xc0 },
787 { 0xc0, 0xdc, 0xc0 }, { 0xa6, 0xca, 0xf0 }
789 static const PALETTEENTRY default_system_palette_high
[] =
791 { 0xff, 0xfb, 0xf0 }, { 0xa0, 0xa0, 0xa4 }, { 0x80, 0x80, 0x80 }, { 0xff, 0x00, 0x00 },
792 { 0x00, 0xff, 0x00 }, { 0xff, 0xff, 0x00 }, { 0x00, 0x00, 0xff }, { 0xff, 0x00, 0xff },
793 { 0x00, 0xff, 0xff }, { 0xff, 0xff, 0xff }
796 /***********************************************************************
797 * GetSystemPaletteEntries (GDI32.@)
799 * Gets range of palette entries.
801 UINT WINAPI
GetSystemPaletteEntries( HDC hdc
, UINT start
, UINT count
, PALETTEENTRY
*entries
)
805 ret
= NtGdiDoPalette( hdc
, start
, count
, (void *)entries
,
806 NtGdiGetSystemPaletteEntries
, FALSE
);
809 /* always fill output, even if hdc is an invalid handle */
810 if (!entries
|| start
>= 256) return 0;
811 if (start
+ count
> 256) count
= 256 - start
;
813 for (i
= 0; i
< count
; i
++)
816 entries
[i
] = default_system_palette_low
[start
+ i
];
817 else if (start
+ i
>= 246)
818 entries
[i
] = default_system_palette_high
[start
+ i
- 246];
820 memset( &entries
[i
], 0, sizeof(entries
[i
]) );
826 /***********************************************************************
827 * CreateDIBitmap (GDI32.@)
829 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
, DWORD init
,
830 const void *bits
, const BITMAPINFO
*data
, UINT coloruse
)
834 if (!header
) return 0;
836 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
838 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)header
;
839 width
= core
->bcWidth
;
840 height
= core
->bcHeight
;
842 else if (header
->biSize
>= sizeof(BITMAPINFOHEADER
))
844 if (header
->biCompression
== BI_JPEG
|| header
->biCompression
== BI_PNG
) return 0;
845 width
= header
->biWidth
;
846 height
= header
->biHeight
;
850 if (!width
|| !height
) return GetStockObject( STOCK_LAST
+ 1 ); /* default 1x1 bitmap */
851 return NtGdiCreateDIBitmapInternal( hdc
, width
, height
, init
, bits
, data
, coloruse
,
855 /***********************************************************************
856 * CreateDIBSection (GDI32.@)
858 HBITMAP WINAPI DECLSPEC_HOTPATCH
CreateDIBSection( HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
859 void **bits
, HANDLE section
, DWORD offset
)
861 return NtGdiCreateDIBSection( hdc
, section
, offset
, bmi
, usage
, 0, 0, 0, bits
);
864 /***********************************************************************
865 * GetDIBits (win32u.@)
867 INT WINAPI DECLSPEC_HOTPATCH
GetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
, UINT lines
,
868 void *bits
, BITMAPINFO
*info
, UINT coloruse
)
870 return NtGdiGetDIBitsInternal( hdc
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
, 0, 0 );
873 /***********************************************************************
874 * GetDIBColorTable (GDI32.@)
876 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT start
, UINT count
, RGBQUAD
*colors
)
878 return NtGdiDoPalette( hdc
, start
, count
, colors
, NtGdiGetDIBColorTable
, TRUE
);
881 /***********************************************************************
882 * SetDIBColorTable (GDI32.@)
884 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT start
, UINT count
, const RGBQUAD
*colors
)
886 return NtGdiDoPalette( hdc
, start
, count
, (void *)colors
, NtGdiSetDIBColorTable
, FALSE
);
889 static HANDLE
get_display_device_init_mutex( void )
891 HANDLE mutex
= CreateMutexW( NULL
, FALSE
, L
"display_device_init" );
893 WaitForSingleObject( mutex
, INFINITE
);
897 static void release_display_device_init_mutex( HANDLE mutex
)
899 ReleaseMutex( mutex
);
900 CloseHandle( mutex
);
903 /***********************************************************************
904 * D3DKMTOpenAdapterFromGdiDisplayName (GDI32.@)
906 NTSTATUS WINAPI
D3DKMTOpenAdapterFromGdiDisplayName( D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME
*desc
)
908 WCHAR
*end
, key_nameW
[MAX_PATH
], bufferW
[MAX_PATH
];
909 HDEVINFO devinfo
= INVALID_HANDLE_VALUE
;
910 NTSTATUS status
= STATUS_UNSUCCESSFUL
;
911 D3DKMT_OPENADAPTERFROMLUID luid_desc
;
912 SP_DEVINFO_DATA device_data
;
913 DWORD size
, state_flags
;
918 TRACE("(%p)\n", desc
);
921 return STATUS_UNSUCCESSFUL
;
923 TRACE("DeviceName: %s\n", wine_dbgstr_w( desc
->DeviceName
));
924 if (wcsnicmp( desc
->DeviceName
, L
"\\\\.\\DISPLAY", lstrlenW(L
"\\\\.\\DISPLAY") ))
925 return STATUS_UNSUCCESSFUL
;
927 index
= wcstol( desc
->DeviceName
+ lstrlenW(L
"\\\\.\\DISPLAY"), &end
, 10 ) - 1;
929 return STATUS_UNSUCCESSFUL
;
931 /* Get adapter LUID from SetupAPI */
932 mutex
= get_display_device_init_mutex();
934 size
= sizeof( bufferW
);
935 swprintf( key_nameW
, MAX_PATH
, L
"\\Device\\Video%d", index
);
936 if (RegGetValueW( HKEY_LOCAL_MACHINE
, L
"HARDWARE\\DEVICEMAP\\VIDEO", key_nameW
,
937 RRF_RT_REG_SZ
, NULL
, bufferW
, &size
))
940 /* Strip \Registry\Machine\ prefix and retrieve Wine specific data set by the display driver */
941 lstrcpyW( key_nameW
, bufferW
+ 18 );
942 size
= sizeof( state_flags
);
943 if (RegGetValueW( HKEY_CURRENT_CONFIG
, key_nameW
, L
"StateFlags", RRF_RT_REG_DWORD
, NULL
,
944 &state_flags
, &size
))
947 if (!(state_flags
& DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
))
950 size
= sizeof( bufferW
);
951 if (RegGetValueW( HKEY_CURRENT_CONFIG
, key_nameW
, L
"GPUID", RRF_RT_REG_SZ
, NULL
, bufferW
, &size
))
954 devinfo
= SetupDiCreateDeviceInfoList( &GUID_DEVCLASS_DISPLAY
, NULL
);
955 device_data
.cbSize
= sizeof( device_data
);
956 SetupDiOpenDeviceInfoW( devinfo
, bufferW
, NULL
, 0, &device_data
);
957 if (!SetupDiGetDevicePropertyW( devinfo
, &device_data
, &DEVPROPKEY_GPU_LUID
, &type
,
958 (BYTE
*)&luid_desc
.AdapterLuid
, sizeof( luid_desc
.AdapterLuid
),
962 if ((status
= NtGdiDdDDIOpenAdapterFromLuid( &luid_desc
))) goto done
;
964 desc
->hAdapter
= luid_desc
.hAdapter
;
965 desc
->AdapterLuid
= luid_desc
.AdapterLuid
;
966 desc
->VidPnSourceId
= index
;
969 SetupDiDestroyDeviceInfoList( devinfo
);
970 release_display_device_init_mutex( mutex
);
974 /***********************************************************************
975 * SetObjectOwner (GDI32.@)
977 void WINAPI
SetObjectOwner( HGDIOBJ handle
, HANDLE owner
)
982 /***********************************************************************
983 * GdiInitializeLanguagePack (GDI32.@)
985 DWORD WINAPI
GdiInitializeLanguagePack( DWORD arg
)
991 /***********************************************************************
992 * GdiGetBatchLimit (GDI32.@)
994 DWORD WINAPI
GdiGetBatchLimit(void)
996 return 1; /* FIXME */
999 /***********************************************************************
1000 * GdiSetBatchLimit (GDI32.@)
1002 DWORD WINAPI
GdiSetBatchLimit( DWORD limit
)
1004 return 1; /* FIXME */
1007 /* Solid colors to enumerate */
1008 static const COLORREF solid_colors
[] =
1010 RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1011 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1012 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1013 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1014 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1015 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1016 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1017 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1020 /***********************************************************************
1021 * EnumObjects (GDI32.@)
1023 INT WINAPI
EnumObjects( HDC hdc
, INT type
, GOBJENUMPROC enum_func
, LPARAM param
)
1030 TRACE( "%p %d %p %08Ix\n", hdc
, type
, enum_func
, param
);
1035 /* Enumerate solid pens */
1036 for (i
= 0; i
< ARRAY_SIZE(solid_colors
); i
++)
1038 pen
.lopnStyle
= PS_SOLID
;
1039 pen
.lopnWidth
.x
= 1;
1040 pen
.lopnWidth
.y
= 0;
1041 pen
.lopnColor
= solid_colors
[i
];
1042 retval
= enum_func( &pen
, param
);
1043 TRACE( "solid pen %08lx, ret=%d\n", solid_colors
[i
], retval
);
1049 /* Enumerate solid brushes */
1050 for (i
= 0; i
< ARRAY_SIZE(solid_colors
); i
++)
1052 brush
.lbStyle
= BS_SOLID
;
1053 brush
.lbColor
= solid_colors
[i
];
1055 retval
= enum_func( &brush
, param
);
1056 TRACE( "solid brush %08lx, ret=%d\n", solid_colors
[i
], retval
);
1060 /* Now enumerate hatched brushes */
1061 for (i
= HS_HORIZONTAL
; retval
&& i
<= HS_DIAGCROSS
; i
++)
1063 brush
.lbStyle
= BS_HATCHED
;
1064 brush
.lbColor
= RGB(0,0,0);
1066 retval
= enum_func( &brush
, param
);
1067 TRACE( "hatched brush %d, ret=%d\n", i
, retval
);
1072 /* FIXME: implement Win32 types */
1073 WARN( "(%d): Invalid type\n", type
);
1080 /***********************************************************************
1081 * CombineTransform (GDI32.@)
1083 * Combines two transformation matrices.
1085 BOOL WINAPI
CombineTransform( XFORM
*result
, const XFORM
*xform1
, const XFORM
*xform2
)
1089 if (!result
|| !xform1
|| !xform2
) return FALSE
;
1091 /* Create the result in a temporary XFORM, since result may be
1092 * equal to xform1 or xform2 */
1093 r
.eM11
= xform1
->eM11
* xform2
->eM11
+ xform1
->eM12
* xform2
->eM21
;
1094 r
.eM12
= xform1
->eM11
* xform2
->eM12
+ xform1
->eM12
* xform2
->eM22
;
1095 r
.eM21
= xform1
->eM21
* xform2
->eM11
+ xform1
->eM22
* xform2
->eM21
;
1096 r
.eM22
= xform1
->eM21
* xform2
->eM12
+ xform1
->eM22
* xform2
->eM22
;
1097 r
.eDx
= xform1
->eDx
* xform2
->eM11
+ xform1
->eDy
* xform2
->eM21
+ xform2
->eDx
;
1098 r
.eDy
= xform1
->eDx
* xform2
->eM12
+ xform1
->eDy
* xform2
->eM22
+ xform2
->eDy
;
1104 /***********************************************************************
1107 BOOL WINAPI
LineDDA( INT x_start
, INT y_start
, INT x_end
, INT y_end
,
1108 LINEDDAPROC callback
, LPARAM lparam
)
1110 INT xadd
= 1, yadd
= 1;
1113 INT dx
= x_end
- x_start
;
1114 INT dy
= y_end
- y_start
;
1116 TRACE( "(%d, %d), (%d, %d), %p, %Ix\n", x_start
, y_start
,
1117 x_end
, y_end
, callback
, lparam
);
1129 if (dx
> dy
) /* line is "more horizontal" */
1131 err
= 2*dy
- dx
; erradd
= 2*dy
- 2*dx
;
1132 for(cnt
= 0;cnt
< dx
; cnt
++)
1134 callback( x_start
, y_start
, lparam
);
1144 else /* line is "more vertical" */
1146 err
= 2*dx
- dy
; erradd
= 2*dx
- 2*dy
;
1147 for(cnt
= 0; cnt
< dy
; cnt
++)
1149 callback( x_start
, y_start
, lparam
);
1162 /***********************************************************************
1163 * GdiDllInitialize (GDI32.@)
1165 * Stub entry point, some games (CoD: Black Ops 3) call it directly.
1167 BOOL WINAPI
GdiDllInitialize( HINSTANCE inst
, DWORD reason
, LPVOID reserved
)