ws2_32: Return a valid value for WSAIoctl SIO_IDEAL_SEND_BACKLOG_QUERY.
[wine.git] / dlls / win32u / driver.c
blobb4ed3f8cb4e01b67b778a24c2dc77d91ef7b025b
1 /*
2 * Graphics driver management functions
4 * Copyright 1994 Bob Amstadt
5 * Copyright 1996, 2001 Alexandre Julliard
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
22 #if 0
23 #pragma makedep unix
24 #endif
26 #include <assert.h>
27 #include <pthread.h>
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "ntgdi_private.h"
32 #include "ntuser_private.h"
33 #include "wine/winbase16.h"
34 #include "wine/list.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(driver);
38 WINE_DECLARE_DEBUG_CHANNEL(winediag);
40 struct d3dkmt_adapter
42 D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */
43 struct list entry; /* List entry */
46 struct d3dkmt_device
48 D3DKMT_HANDLE handle; /* Kernel mode graphics device handle*/
49 struct list entry; /* List entry */
52 static const struct user_driver_funcs lazy_load_driver;
53 static struct user_driver_funcs null_user_driver;
55 static struct list d3dkmt_adapters = LIST_INIT( d3dkmt_adapters );
56 static struct list d3dkmt_devices = LIST_INIT( d3dkmt_devices );
58 static pthread_mutex_t driver_lock = PTHREAD_MUTEX_INITIALIZER;
59 static WCHAR driver_load_error[80];
61 static INT CDECL nulldrv_AbortDoc( PHYSDEV dev )
63 return 0;
66 static BOOL CDECL nulldrv_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
67 INT xstart, INT ystart, INT xend, INT yend )
69 return TRUE;
72 static BOOL CDECL nulldrv_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
73 INT xstart, INT ystart, INT xend, INT yend )
75 return TRUE;
78 static BOOL CDECL nulldrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
80 if (!user_driver->dc_funcs.pCreateCompatibleDC) return TRUE;
81 return user_driver->dc_funcs.pCreateCompatibleDC( NULL, pdev );
84 static BOOL CDECL nulldrv_CreateDC( PHYSDEV *dev, LPCWSTR device, LPCWSTR output,
85 const DEVMODEW *devmode )
87 assert(0); /* should never be called */
88 return FALSE;
91 static BOOL CDECL nulldrv_DeleteDC( PHYSDEV dev )
93 assert(0); /* should never be called */
94 return TRUE;
97 static BOOL CDECL nulldrv_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
99 return TRUE;
102 static BOOL CDECL nulldrv_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
104 return TRUE;
107 static INT CDECL nulldrv_EndDoc( PHYSDEV dev )
109 return 0;
112 static INT CDECL nulldrv_EndPage( PHYSDEV dev )
114 return 0;
117 static BOOL CDECL nulldrv_EnumFonts( PHYSDEV dev, LOGFONTW *logfont, FONTENUMPROCW proc, LPARAM lParam )
119 return TRUE;
122 static INT CDECL nulldrv_ExtEscape( PHYSDEV dev, INT escape, INT in_size, const void *in_data,
123 INT out_size, void *out_data )
125 return 0;
128 static BOOL CDECL nulldrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type )
130 return TRUE;
133 static BOOL CDECL nulldrv_FontIsLinked( PHYSDEV dev )
135 return FALSE;
138 static UINT CDECL nulldrv_GetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags )
140 return DCB_RESET;
143 static BOOL CDECL nulldrv_GetCharABCWidths( PHYSDEV dev, UINT first, UINT count,
144 WCHAR *chars, ABC *abc )
146 return FALSE;
149 static BOOL CDECL nulldrv_GetCharABCWidthsI( PHYSDEV dev, UINT first, UINT count, WORD *indices, LPABC abc )
151 return FALSE;
154 static BOOL CDECL nulldrv_GetCharWidth( PHYSDEV dev, UINT first, UINT count,
155 const WCHAR *chars, INT *buffer )
157 return FALSE;
160 static BOOL CDECL nulldrv_GetCharWidthInfo( PHYSDEV dev, void *info )
162 return FALSE;
165 static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap )
167 int bpp;
169 switch (cap)
171 case DRIVERVERSION: return 0x4000;
172 case TECHNOLOGY: return DT_RASDISPLAY;
173 case HORZSIZE: return muldiv( NtGdiGetDeviceCaps( dev->hdc, HORZRES ), 254,
174 NtGdiGetDeviceCaps( dev->hdc, LOGPIXELSX ) * 10 );
175 case VERTSIZE: return muldiv( NtGdiGetDeviceCaps( dev->hdc, VERTRES ), 254,
176 NtGdiGetDeviceCaps( dev->hdc, LOGPIXELSY ) * 10 );
177 case HORZRES:
179 DC *dc = get_nulldrv_dc( dev );
180 RECT rect;
181 int ret;
183 if (dc->display[0])
185 rect = get_display_rect( dc->display );
186 if (!IsRectEmpty( &rect )) return rect.right - rect.left;
189 ret = get_system_metrics( SM_CXSCREEN );
190 return ret ? ret : 640;
192 case VERTRES:
194 DC *dc = get_nulldrv_dc( dev );
195 RECT rect;
196 int ret;
198 if (dc->display[0])
200 rect = get_display_rect( dc->display );
201 if (!IsRectEmpty( &rect )) return rect.bottom - rect.top;
204 ret = get_system_metrics( SM_CYSCREEN );
205 return ret ? ret : 480;
207 case BITSPIXEL:
209 UNICODE_STRING display;
210 DEVMODEW devmode;
211 DC *dc;
213 if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY)
215 dc = get_nulldrv_dc( dev );
216 memset( &devmode, 0, sizeof(devmode) );
217 devmode.dmSize = sizeof(devmode);
218 RtlInitUnicodeString( &display, dc->display );
219 if (NtUserEnumDisplaySettings( &display, ENUM_CURRENT_SETTINGS, &devmode, 0 ) &&
220 (devmode.dmFields & DM_BITSPERPEL) && devmode.dmBitsPerPel)
221 return devmode.dmBitsPerPel;
223 return 32;
225 case PLANES: return 1;
226 case NUMBRUSHES: return -1;
227 case NUMPENS: return -1;
228 case NUMMARKERS: return 0;
229 case NUMFONTS: return 0;
230 case PDEVICESIZE: return 0;
231 case CURVECAPS: return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
232 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
233 case LINECAPS: return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
234 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
235 case POLYGONALCAPS: return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
236 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
237 case TEXTCAPS: return (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
238 TC_CR_ANY | TC_SF_X_YINDEP | TC_SA_DOUBLE | TC_SA_INTEGER |
239 TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE | TC_VA_ABLE);
240 case CLIPCAPS: return CP_RECTANGLE;
241 case RASTERCAPS: return (RC_BITBLT | RC_BITMAP64 | RC_GDI20_OUTPUT | RC_DI_BITMAP | RC_DIBTODEV |
242 RC_BIGFONT | RC_STRETCHBLT | RC_FLOODFILL | RC_STRETCHDIB | RC_DEVBITS |
243 (NtGdiGetDeviceCaps( dev->hdc, SIZEPALETTE ) ? RC_PALETTE : 0));
244 case ASPECTX: return 36;
245 case ASPECTY: return 36;
246 case ASPECTXY: return (int)(hypot( NtGdiGetDeviceCaps( dev->hdc, ASPECTX ),
247 NtGdiGetDeviceCaps( dev->hdc, ASPECTY )) + 0.5);
248 case CAPS1: return 0;
249 case SIZEPALETTE: return 0;
250 case NUMRESERVED: return 20;
251 case PHYSICALWIDTH: return 0;
252 case PHYSICALHEIGHT: return 0;
253 case PHYSICALOFFSETX: return 0;
254 case PHYSICALOFFSETY: return 0;
255 case SCALINGFACTORX: return 0;
256 case SCALINGFACTORY: return 0;
257 case VREFRESH:
259 UNICODE_STRING display;
260 DEVMODEW devmode;
261 DC *dc;
263 if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) != DT_RASDISPLAY)
264 return 0;
266 dc = get_nulldrv_dc( dev );
268 memset( &devmode, 0, sizeof(devmode) );
269 devmode.dmSize = sizeof(devmode);
270 RtlInitUnicodeString( &display, dc->display );
271 if (NtUserEnumDisplaySettings( &display, ENUM_CURRENT_SETTINGS, &devmode, 0 ) &&
272 devmode.dmDisplayFrequency)
273 return devmode.dmDisplayFrequency;
274 return 1;
276 case DESKTOPHORZRES:
277 if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY)
279 RECT rect = get_virtual_screen_rect( 0 );
280 return rect.right - rect.left;
282 return NtGdiGetDeviceCaps( dev->hdc, HORZRES );
283 case DESKTOPVERTRES:
284 if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY)
286 RECT rect = get_virtual_screen_rect( 0 );
287 return rect.bottom - rect.top;
289 return NtGdiGetDeviceCaps( dev->hdc, VERTRES );
290 case BLTALIGNMENT: return 0;
291 case SHADEBLENDCAPS: return 0;
292 case COLORMGMTCAPS: return 0;
293 case LOGPIXELSX:
294 case LOGPIXELSY: return get_system_dpi();
295 case NUMCOLORS:
296 bpp = NtGdiGetDeviceCaps( dev->hdc, BITSPIXEL );
297 /* Newer versions of Windows return -1 for 8-bit and higher */
298 return (bpp > 4) ? -1 : (1 << bpp);
299 case COLORRES:
300 /* The observed correspondence between BITSPIXEL and COLORRES is:
301 * BITSPIXEL: 8 -> COLORRES: 18
302 * BITSPIXEL: 16 -> COLORRES: 16
303 * BITSPIXEL: 24 -> COLORRES: 24
304 * BITSPIXEL: 32 -> COLORRES: 24 */
305 bpp = NtGdiGetDeviceCaps( dev->hdc, BITSPIXEL );
306 return (bpp <= 8) ? 18 : min( 24, bpp );
307 default:
308 FIXME("(%p): unsupported capability %d, will return 0\n", dev->hdc, cap );
309 return 0;
313 static BOOL CDECL nulldrv_GetDeviceGammaRamp( PHYSDEV dev, void *ramp )
315 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER );
316 return FALSE;
319 static DWORD CDECL nulldrv_GetFontData( PHYSDEV dev, DWORD table, DWORD offset, LPVOID buffer, DWORD length )
321 return FALSE;
324 static BOOL CDECL nulldrv_GetFontRealizationInfo( PHYSDEV dev, void *info )
326 return FALSE;
329 static DWORD CDECL nulldrv_GetFontUnicodeRanges( PHYSDEV dev, LPGLYPHSET glyphs )
331 return 0;
334 static DWORD CDECL nulldrv_GetGlyphIndices( PHYSDEV dev, LPCWSTR str, INT count, LPWORD indices, DWORD flags )
336 return GDI_ERROR;
339 static DWORD CDECL nulldrv_GetGlyphOutline( PHYSDEV dev, UINT ch, UINT format, LPGLYPHMETRICS metrics,
340 DWORD size, LPVOID buffer, const MAT2 *mat )
342 return GDI_ERROR;
345 static BOOL CDECL nulldrv_GetICMProfile( PHYSDEV dev, BOOL allow_default, LPDWORD size, LPWSTR filename )
347 return FALSE;
350 static DWORD CDECL nulldrv_GetImage( PHYSDEV dev, BITMAPINFO *info, struct gdi_image_bits *bits,
351 struct bitblt_coords *src )
353 return ERROR_NOT_SUPPORTED;
356 static DWORD CDECL nulldrv_GetKerningPairs( PHYSDEV dev, DWORD count, LPKERNINGPAIR pairs )
358 return 0;
361 static UINT CDECL nulldrv_GetOutlineTextMetrics( PHYSDEV dev, UINT size, LPOUTLINETEXTMETRICW otm )
363 return 0;
366 static UINT CDECL nulldrv_GetTextCharsetInfo( PHYSDEV dev, LPFONTSIGNATURE fs, DWORD flags )
368 return DEFAULT_CHARSET;
371 static BOOL CDECL nulldrv_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR str, INT count, INT *dx )
373 return FALSE;
376 static BOOL CDECL nulldrv_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, INT count, INT *dx )
378 return FALSE;
381 static INT CDECL nulldrv_GetTextFace( PHYSDEV dev, INT size, LPWSTR name )
383 INT ret = 0;
384 LOGFONTW font;
385 DC *dc = get_nulldrv_dc( dev );
387 if (NtGdiExtGetObjectW( dc->hFont, sizeof(font), &font ))
389 ret = lstrlenW( font.lfFaceName ) + 1;
390 if (name)
392 lstrcpynW( name, font.lfFaceName, size );
393 ret = min( size, ret );
396 return ret;
399 static BOOL CDECL nulldrv_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
401 return FALSE;
404 static BOOL CDECL nulldrv_LineTo( PHYSDEV dev, INT x, INT y )
406 return TRUE;
409 static BOOL CDECL nulldrv_MoveTo( PHYSDEV dev, INT x, INT y )
411 return TRUE;
414 static BOOL CDECL nulldrv_PaintRgn( PHYSDEV dev, HRGN rgn )
416 return TRUE;
419 static BOOL CDECL nulldrv_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
421 return TRUE;
424 static BOOL CDECL nulldrv_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
425 INT xstart, INT ystart, INT xend, INT yend )
427 return TRUE;
430 static BOOL CDECL nulldrv_PolyPolygon( PHYSDEV dev, const POINT *points, const INT *counts, UINT polygons )
432 return TRUE;
435 static BOOL CDECL nulldrv_PolyPolyline( PHYSDEV dev, const POINT *points, const DWORD *counts, DWORD lines )
437 return TRUE;
440 static DWORD CDECL nulldrv_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
441 const struct gdi_image_bits *bits, struct bitblt_coords *src,
442 struct bitblt_coords *dst, DWORD rop )
444 return ERROR_SUCCESS;
447 static UINT CDECL nulldrv_RealizeDefaultPalette( PHYSDEV dev )
449 return 0;
452 static UINT CDECL nulldrv_RealizePalette( PHYSDEV dev, HPALETTE palette, BOOL primary )
454 return 0;
457 static BOOL CDECL nulldrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
459 return TRUE;
462 static BOOL CDECL nulldrv_ResetDC( PHYSDEV dev, const DEVMODEW *devmode )
464 return FALSE;
467 static BOOL CDECL nulldrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
468 INT ell_width, INT ell_height )
470 return TRUE;
473 static HBITMAP CDECL nulldrv_SelectBitmap( PHYSDEV dev, HBITMAP bitmap )
475 return bitmap;
478 static HBRUSH CDECL nulldrv_SelectBrush( PHYSDEV dev, HBRUSH brush, const struct brush_pattern *pattern )
480 return brush;
483 static HFONT CDECL nulldrv_SelectFont( PHYSDEV dev, HFONT font, UINT *aa_flags )
485 return font;
488 static HPEN CDECL nulldrv_SelectPen( PHYSDEV dev, HPEN pen, const struct brush_pattern *pattern )
490 return pen;
493 static COLORREF CDECL nulldrv_SetBkColor( PHYSDEV dev, COLORREF color )
495 return color;
498 static UINT CDECL nulldrv_SetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags )
500 return DCB_RESET;
503 static COLORREF CDECL nulldrv_SetDCBrushColor( PHYSDEV dev, COLORREF color )
505 return color;
508 static COLORREF CDECL nulldrv_SetDCPenColor( PHYSDEV dev, COLORREF color )
510 return color;
513 static void CDECL nulldrv_SetDeviceClipping( PHYSDEV dev, HRGN rgn )
517 static BOOL CDECL nulldrv_SetDeviceGammaRamp( PHYSDEV dev, void *ramp )
519 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER );
520 return FALSE;
523 static COLORREF CDECL nulldrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
525 return color;
528 static COLORREF CDECL nulldrv_SetTextColor( PHYSDEV dev, COLORREF color )
530 return color;
533 static INT CDECL nulldrv_StartDoc( PHYSDEV dev, const DOCINFOW *info )
535 return 0;
538 static INT CDECL nulldrv_StartPage( PHYSDEV dev )
540 return 1;
543 static BOOL CDECL nulldrv_UnrealizePalette( HPALETTE palette )
545 return FALSE;
548 static NTSTATUS CDECL nulldrv_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
550 return STATUS_PROCEDURE_NOT_FOUND;
553 static NTSTATUS CDECL nulldrv_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
555 return STATUS_PROCEDURE_NOT_FOUND;
558 static NTSTATUS CDECL nulldrv_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
560 return STATUS_PROCEDURE_NOT_FOUND;
563 static NTSTATUS CDECL nulldrv_D3DKMTQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc )
565 return STATUS_PROCEDURE_NOT_FOUND;
568 static NTSTATUS CDECL nulldrv_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
570 return STATUS_PROCEDURE_NOT_FOUND;
573 const struct gdi_dc_funcs null_driver =
575 nulldrv_AbortDoc, /* pAbortDoc */
576 nulldrv_AbortPath, /* pAbortPath */
577 nulldrv_AlphaBlend, /* pAlphaBlend */
578 nulldrv_AngleArc, /* pAngleArc */
579 nulldrv_Arc, /* pArc */
580 nulldrv_ArcTo, /* pArcTo */
581 nulldrv_BeginPath, /* pBeginPath */
582 nulldrv_BlendImage, /* pBlendImage */
583 nulldrv_Chord, /* pChord */
584 nulldrv_CloseFigure, /* pCloseFigure */
585 nulldrv_CreateCompatibleDC, /* pCreateCompatibleDC */
586 nulldrv_CreateDC, /* pCreateDC */
587 nulldrv_DeleteDC, /* pDeleteDC */
588 nulldrv_DeleteObject, /* pDeleteObject */
589 nulldrv_Ellipse, /* pEllipse */
590 nulldrv_EndDoc, /* pEndDoc */
591 nulldrv_EndPage, /* pEndPage */
592 nulldrv_EndPath, /* pEndPath */
593 nulldrv_EnumFonts, /* pEnumFonts */
594 nulldrv_ExtEscape, /* pExtEscape */
595 nulldrv_ExtFloodFill, /* pExtFloodFill */
596 nulldrv_ExtTextOut, /* pExtTextOut */
597 nulldrv_FillPath, /* pFillPath */
598 nulldrv_FillRgn, /* pFillRgn */
599 nulldrv_FontIsLinked, /* pFontIsLinked */
600 nulldrv_FrameRgn, /* pFrameRgn */
601 nulldrv_GetBoundsRect, /* pGetBoundsRect */
602 nulldrv_GetCharABCWidths, /* pGetCharABCWidths */
603 nulldrv_GetCharABCWidthsI, /* pGetCharABCWidthsI */
604 nulldrv_GetCharWidth, /* pGetCharWidth */
605 nulldrv_GetCharWidthInfo, /* pGetCharWidthInfo */
606 nulldrv_GetDeviceCaps, /* pGetDeviceCaps */
607 nulldrv_GetDeviceGammaRamp, /* pGetDeviceGammaRamp */
608 nulldrv_GetFontData, /* pGetFontData */
609 nulldrv_GetFontRealizationInfo, /* pGetFontRealizationInfo */
610 nulldrv_GetFontUnicodeRanges, /* pGetFontUnicodeRanges */
611 nulldrv_GetGlyphIndices, /* pGetGlyphIndices */
612 nulldrv_GetGlyphOutline, /* pGetGlyphOutline */
613 nulldrv_GetICMProfile, /* pGetICMProfile */
614 nulldrv_GetImage, /* pGetImage */
615 nulldrv_GetKerningPairs, /* pGetKerningPairs */
616 nulldrv_GetNearestColor, /* pGetNearestColor */
617 nulldrv_GetOutlineTextMetrics, /* pGetOutlineTextMetrics */
618 nulldrv_GetPixel, /* pGetPixel */
619 nulldrv_GetSystemPaletteEntries, /* pGetSystemPaletteEntries */
620 nulldrv_GetTextCharsetInfo, /* pGetTextCharsetInfo */
621 nulldrv_GetTextExtentExPoint, /* pGetTextExtentExPoint */
622 nulldrv_GetTextExtentExPointI, /* pGetTextExtentExPointI */
623 nulldrv_GetTextFace, /* pGetTextFace */
624 nulldrv_GetTextMetrics, /* pGetTextMetrics */
625 nulldrv_GradientFill, /* pGradientFill */
626 nulldrv_InvertRgn, /* pInvertRgn */
627 nulldrv_LineTo, /* pLineTo */
628 nulldrv_MoveTo, /* pMoveTo */
629 nulldrv_PaintRgn, /* pPaintRgn */
630 nulldrv_PatBlt, /* pPatBlt */
631 nulldrv_Pie, /* pPie */
632 nulldrv_PolyBezier, /* pPolyBezier */
633 nulldrv_PolyBezierTo, /* pPolyBezierTo */
634 nulldrv_PolyDraw, /* pPolyDraw */
635 nulldrv_PolyPolygon, /* pPolyPolygon */
636 nulldrv_PolyPolyline, /* pPolyPolyline */
637 nulldrv_PolylineTo, /* pPolylineTo */
638 nulldrv_PutImage, /* pPutImage */
639 nulldrv_RealizeDefaultPalette, /* pRealizeDefaultPalette */
640 nulldrv_RealizePalette, /* pRealizePalette */
641 nulldrv_Rectangle, /* pRectangle */
642 nulldrv_ResetDC, /* pResetDC */
643 nulldrv_RoundRect, /* pRoundRect */
644 nulldrv_SelectBitmap, /* pSelectBitmap */
645 nulldrv_SelectBrush, /* pSelectBrush */
646 nulldrv_SelectFont, /* pSelectFont */
647 nulldrv_SelectPen, /* pSelectPen */
648 nulldrv_SetBkColor, /* pSetBkColor */
649 nulldrv_SetBoundsRect, /* pSetBoundsRect */
650 nulldrv_SetDCBrushColor, /* pSetDCBrushColor */
651 nulldrv_SetDCPenColor, /* pSetDCPenColor */
652 nulldrv_SetDIBitsToDevice, /* pSetDIBitsToDevice */
653 nulldrv_SetDeviceClipping, /* pSetDeviceClipping */
654 nulldrv_SetDeviceGammaRamp, /* pSetDeviceGammaRamp */
655 nulldrv_SetPixel, /* pSetPixel */
656 nulldrv_SetTextColor, /* pSetTextColor */
657 nulldrv_StartDoc, /* pStartDoc */
658 nulldrv_StartPage, /* pStartPage */
659 nulldrv_StretchBlt, /* pStretchBlt */
660 nulldrv_StretchDIBits, /* pStretchDIBits */
661 nulldrv_StrokeAndFillPath, /* pStrokeAndFillPath */
662 nulldrv_StrokePath, /* pStrokePath */
663 nulldrv_UnrealizePalette, /* pUnrealizePalette */
664 nulldrv_D3DKMTCheckVidPnExclusiveOwnership, /* pD3DKMTCheckVidPnExclusiveOwnership */
665 nulldrv_D3DKMTCloseAdapter, /* pD3DKMTCloseAdapter */
666 nulldrv_D3DKMTOpenAdapterFromLuid, /* pD3DKMTOpenAdapterFromLuid */
667 nulldrv_D3DKMTQueryVideoMemoryInfo, /* pD3DKMTQueryVideoMemoryInfo */
668 nulldrv_D3DKMTSetVidPnSourceOwner, /* pD3DKMTSetVidPnSourceOwner */
670 GDI_PRIORITY_NULL_DRV /* priority */
674 /**********************************************************************
675 * Null user driver
677 * These are fallbacks for entry points that are not implemented in the real driver.
680 static BOOL nulldrv_ActivateKeyboardLayout( HKL layout, UINT flags )
682 return TRUE;
685 static void nulldrv_Beep(void)
689 static UINT nulldrv_GetKeyboardLayoutList( INT size, HKL *layouts )
691 return ~0; /* use default implementation */
694 static INT nulldrv_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size )
696 return -1; /* use default implementation */
699 static UINT nulldrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout )
701 return -1; /* use default implementation */
704 static BOOL nulldrv_RegisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
706 return TRUE;
709 static INT nulldrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str,
710 int size, UINT flags, HKL layout )
712 return -2; /* use default implementation */
715 static void nulldrv_UnregisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
719 static SHORT nulldrv_VkKeyScanEx( WCHAR ch, HKL layout )
721 return -256; /* use default implementation */
724 static LRESULT nulldrv_DesktopWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
726 return default_window_proc( hwnd, msg, wparam, lparam, FALSE );
729 static void nulldrv_DestroyCursorIcon( HCURSOR cursor )
733 static void nulldrv_SetCursor( HCURSOR cursor )
737 static BOOL nulldrv_GetCursorPos( LPPOINT pt )
739 return TRUE;
742 static BOOL nulldrv_SetCursorPos( INT x, INT y )
744 return TRUE;
747 static BOOL nulldrv_ClipCursor( LPCRECT clip )
749 return TRUE;
752 static void nulldrv_UpdateClipboard(void)
756 static LONG nulldrv_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd,
757 DWORD flags, LPVOID lparam )
759 return DISP_CHANGE_FAILED;
762 static BOOL nulldrv_EnumDisplaySettingsEx( LPCWSTR name, DWORD num, LPDEVMODEW mode, DWORD flags )
764 return FALSE;
767 static BOOL nulldrv_GetCurrentDisplaySettings( LPCWSTR name, LPDEVMODEW mode )
769 return FALSE;
772 static BOOL nulldrv_UpdateDisplayDevices( const struct gdi_device_manager *manager, BOOL force, void *param )
774 return FALSE;
777 static BOOL nulldrv_CreateDesktopWindow( HWND hwnd )
779 return TRUE;
782 static BOOL nodrv_CreateWindow( HWND hwnd )
784 static int warned;
785 HWND parent = NtUserGetAncestor( hwnd, GA_PARENT );
787 /* HWND_MESSAGE windows don't need a graphics driver */
788 if (!parent || parent == UlongToHandle( NtUserGetThreadInfo()->msg_window )) return TRUE;
789 if (warned++) return FALSE;
791 ERR_(winediag)( "Application tried to create a window, but no driver could be loaded.\n" );
792 if (driver_load_error[0]) ERR_(winediag)( "%s\n", debugstr_w(driver_load_error) );
793 return FALSE;
796 static BOOL nulldrv_CreateWindow( HWND hwnd )
798 return TRUE;
801 static void nulldrv_DestroyWindow( HWND hwnd )
805 static void nulldrv_FlashWindowEx( FLASHWINFO *info )
809 static void nulldrv_GetDC( HDC hdc, HWND hwnd, HWND top_win, const RECT *win_rect,
810 const RECT *top_rect, DWORD flags )
814 static NTSTATUS nulldrv_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
815 const LARGE_INTEGER *timeout,
816 DWORD mask, DWORD flags )
818 if (!count && timeout && !timeout->QuadPart) return WAIT_TIMEOUT;
819 return NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL),
820 !!(flags & MWMO_ALERTABLE), timeout );
823 static void nulldrv_ReleaseDC( HWND hwnd, HDC hdc )
827 static BOOL nulldrv_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update )
829 RECT rect;
831 NtGdiGetAppClipBox( hdc, &rect );
832 return NtGdiBitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
833 hdc, rect.left - dx, rect.top - dy, SRCCOPY, 0, 0 );
836 static void nulldrv_SetCapture( HWND hwnd, UINT flags )
840 static void nulldrv_SetFocus( HWND hwnd )
844 static void nulldrv_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
848 static void nulldrv_SetParent( HWND hwnd, HWND parent, HWND old_parent )
852 static void nulldrv_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
856 static void nulldrv_SetWindowIcon( HWND hwnd, UINT type, HICON icon )
860 static void nulldrv_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style )
864 static void nulldrv_SetWindowText( HWND hwnd, LPCWSTR text )
868 static UINT nulldrv_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp )
870 return ~0; /* use default implementation */
873 static LRESULT nulldrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam )
875 return -1;
878 static BOOL nulldrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
879 const RECT *window_rect )
881 return TRUE;
884 static LRESULT nulldrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
886 return 0;
889 static BOOL nulldrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
890 const RECT *window_rect, const RECT *client_rect,
891 RECT *visible_rect, struct window_surface **surface )
893 return FALSE;
896 static void nulldrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
897 const RECT *window_rect, const RECT *client_rect,
898 const RECT *visible_rect, const RECT *valid_rects,
899 struct window_surface *surface )
903 static BOOL nulldrv_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
905 return FALSE;
908 static const struct vulkan_funcs *nulldrv_wine_get_vulkan_driver( UINT version )
910 return NULL;
913 static struct opengl_funcs *nulldrv_wine_get_wgl_driver( UINT version )
915 return (void *)-1;
918 static void nulldrv_ThreadDetach( void )
922 static const WCHAR guid_key_prefixW[] =
924 '\\','R','e','g','i','s','t','r','y',
925 '\\','M','a','c','h','i','n','e',
926 '\\','S','y','s','t','e','m',
927 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
928 '\\','C','o','n','t','r','o','l',
929 '\\','V','i','d','e','o','\\','{'
931 static const WCHAR guid_key_suffixW[] = {'}','\\','0','0','0','0'};
933 static BOOL load_desktop_driver( HWND hwnd )
935 WCHAR key[ARRAYSIZE(guid_key_prefixW) + 40 + ARRAYSIZE(guid_key_suffixW)], *ptr;
936 char buf[4096];
937 KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
938 ATOM_BASIC_INFORMATION *abi = (ATOM_BASIC_INFORMATION *)buf;
939 BOOL ret = FALSE;
940 HKEY hkey;
941 DWORD size;
942 UINT guid_atom;
944 static const WCHAR prop_nameW[] =
945 {'_','_','w','i','n','e','_','d','i','s','p','l','a','y','_','d','e','v','i','c','e',
946 '_','g','u','i','d',0};
948 user_check_not_lock();
950 asciiz_to_unicode( driver_load_error, "The explorer process failed to start." ); /* default error */
951 /* wait for graphics driver to be ready */
952 send_message( hwnd, WM_NULL, 0, 0 );
954 guid_atom = HandleToULong( NtUserGetProp( hwnd, prop_nameW ));
955 memcpy( key, guid_key_prefixW, sizeof(guid_key_prefixW) );
956 ptr = key + ARRAYSIZE(guid_key_prefixW);
957 if (NtQueryInformationAtom( guid_atom, AtomBasicInformation, buf, sizeof(buf), NULL ))
958 return FALSE;
959 memcpy( ptr, abi->Name, abi->NameLength );
960 ptr += abi->NameLength / sizeof(WCHAR);
961 memcpy( ptr, guid_key_suffixW, sizeof(guid_key_suffixW) );
962 ptr += ARRAY_SIZE(guid_key_suffixW);
964 if (!(hkey = reg_open_key( NULL, key, (ptr - key) * sizeof(WCHAR) ))) return FALSE;
966 if ((size = query_reg_ascii_value( hkey, "GraphicsDriver", info, sizeof(buf) )))
968 static const WCHAR nullW[] = {'n','u','l','l',0};
969 TRACE( "trying driver %s\n", debugstr_wn( (const WCHAR *)info->Data,
970 info->DataLength / sizeof(WCHAR) ));
971 if (info->DataLength != sizeof(nullW) || memcmp( info->Data, nullW, sizeof(nullW) ))
973 void *ret_ptr;
974 ULONG ret_len;
975 ret = KeUserModeCallback( NtUserLoadDriver, info->Data, info->DataLength,
976 &ret_ptr, &ret_len );
978 else
980 __wine_set_user_driver( &null_user_driver, WINE_GDI_DRIVER_VERSION );
981 ret = TRUE;
984 else if ((size = query_reg_ascii_value( hkey, "DriverError", info, sizeof(buf) )))
986 memcpy( driver_load_error, info->Data, min( info->DataLength, sizeof(driver_load_error) ));
987 driver_load_error[ARRAYSIZE(driver_load_error) - 1] = 0;
990 NtClose( hkey );
991 return ret;
994 /**********************************************************************
995 * Lazy loading user driver
997 * Initial driver used before another driver is loaded.
998 * Each entry point simply loads the real driver and chains to it.
1001 static const struct user_driver_funcs *load_driver(void)
1003 USEROBJECTFLAGS flags;
1004 HWINSTA winstation;
1006 if (!load_desktop_driver( get_desktop_window() ) || user_driver == &lazy_load_driver)
1008 winstation = NtUserGetProcessWindowStation();
1009 if (!NtUserGetObjectInformation( winstation, UOI_FLAGS, &flags, sizeof(flags), NULL )
1010 || (flags.dwFlags & WSF_VISIBLE))
1011 null_user_driver.pCreateWindow = nodrv_CreateWindow;
1013 __wine_set_user_driver( &null_user_driver, WINE_GDI_DRIVER_VERSION );
1016 return user_driver;
1019 /**********************************************************************
1020 * get_display_driver
1022 const struct gdi_dc_funcs *get_display_driver(void)
1024 if (user_driver == &lazy_load_driver) load_driver();
1025 return &user_driver->dc_funcs;
1028 static BOOL loaderdrv_ActivateKeyboardLayout( HKL layout, UINT flags )
1030 return load_driver()->pActivateKeyboardLayout( layout, flags );
1033 static void loaderdrv_Beep(void)
1035 load_driver()->pBeep();
1038 static INT loaderdrv_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size )
1040 return load_driver()->pGetKeyNameText( lparam, buffer, size );
1043 static UINT loaderdrv_GetKeyboardLayoutList( INT size, HKL *layouts )
1045 return load_driver()->pGetKeyboardLayoutList( size, layouts );
1048 static UINT loaderdrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout )
1050 return load_driver()->pMapVirtualKeyEx( code, type, layout );
1053 static INT loaderdrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str,
1054 int size, UINT flags, HKL layout )
1056 return load_driver()->pToUnicodeEx( virt, scan, state, str, size, flags, layout );
1059 static BOOL loaderdrv_RegisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
1061 return load_driver()->pRegisterHotKey( hwnd, modifiers, vk );
1064 static void loaderdrv_UnregisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
1066 load_driver()->pUnregisterHotKey( hwnd, modifiers, vk );
1069 static SHORT loaderdrv_VkKeyScanEx( WCHAR ch, HKL layout )
1071 return load_driver()->pVkKeyScanEx( ch, layout );
1074 static LONG loaderdrv_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd,
1075 DWORD flags, LPVOID lparam )
1077 return load_driver()->pChangeDisplaySettings( displays, hwnd, flags, lparam );
1080 static BOOL loaderdrv_EnumDisplaySettingsEx( LPCWSTR name, DWORD num, LPDEVMODEW mode, DWORD flags )
1082 return load_driver()->pEnumDisplaySettingsEx( name, num, mode, flags );
1085 static BOOL loaderdrv_GetCurrentDisplaySettings( LPCWSTR name, LPDEVMODEW mode )
1087 return load_driver()->pGetCurrentDisplaySettings( name, mode );
1090 static void loaderdrv_SetCursor( HCURSOR cursor )
1092 load_driver()->pSetCursor( cursor );
1095 static BOOL loaderdrv_GetCursorPos( POINT *pt )
1097 return load_driver()->pGetCursorPos( pt );
1100 static BOOL loaderdrv_SetCursorPos( INT x, INT y )
1102 return load_driver()->pSetCursorPos( x, y );
1105 static BOOL loaderdrv_ClipCursor( const RECT *clip )
1107 return load_driver()->pClipCursor( clip );
1110 static LRESULT nulldrv_ClipboardWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
1112 return 0;
1115 static void loaderdrv_UpdateClipboard(void)
1117 load_driver()->pUpdateClipboard();
1120 static BOOL loaderdrv_UpdateDisplayDevices( const struct gdi_device_manager *manager, BOOL force, void *param )
1122 return load_driver()->pUpdateDisplayDevices( manager, force, param );
1125 static BOOL loaderdrv_CreateDesktopWindow( HWND hwnd )
1127 return load_driver()->pCreateDesktopWindow( hwnd );
1130 static BOOL loaderdrv_CreateWindow( HWND hwnd )
1132 return load_driver()->pCreateWindow( hwnd );
1135 static void loaderdrv_GetDC( HDC hdc, HWND hwnd, HWND top_win, const RECT *win_rect,
1136 const RECT *top_rect, DWORD flags )
1138 load_driver()->pGetDC( hdc, hwnd, top_win, win_rect, top_rect, flags );
1141 static void loaderdrv_FlashWindowEx( FLASHWINFO *info )
1143 load_driver()->pFlashWindowEx( info );
1146 static void loaderdrv_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
1148 load_driver()->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
1151 static void loaderdrv_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
1153 load_driver()->pSetWindowRgn( hwnd, hrgn, redraw );
1156 static BOOL loaderdrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
1157 const RECT *window_rect )
1159 return load_driver()->pUpdateLayeredWindow( hwnd, info, window_rect );
1162 static const struct vulkan_funcs * loaderdrv_wine_get_vulkan_driver( UINT version )
1164 return load_driver()->pwine_get_vulkan_driver( version );
1167 static const struct user_driver_funcs lazy_load_driver =
1169 { NULL },
1170 /* keyboard functions */
1171 loaderdrv_ActivateKeyboardLayout,
1172 loaderdrv_Beep,
1173 loaderdrv_GetKeyNameText,
1174 loaderdrv_GetKeyboardLayoutList,
1175 loaderdrv_MapVirtualKeyEx,
1176 loaderdrv_RegisterHotKey,
1177 loaderdrv_ToUnicodeEx,
1178 loaderdrv_UnregisterHotKey,
1179 loaderdrv_VkKeyScanEx,
1180 /* cursor/icon functions */
1181 nulldrv_DestroyCursorIcon,
1182 loaderdrv_SetCursor,
1183 loaderdrv_GetCursorPos,
1184 loaderdrv_SetCursorPos,
1185 loaderdrv_ClipCursor,
1186 /* clipboard functions */
1187 nulldrv_ClipboardWindowProc,
1188 loaderdrv_UpdateClipboard,
1189 /* display modes */
1190 loaderdrv_ChangeDisplaySettings,
1191 loaderdrv_EnumDisplaySettingsEx,
1192 loaderdrv_GetCurrentDisplaySettings,
1193 loaderdrv_UpdateDisplayDevices,
1194 /* windowing functions */
1195 loaderdrv_CreateDesktopWindow,
1196 loaderdrv_CreateWindow,
1197 nulldrv_DesktopWindowProc,
1198 nulldrv_DestroyWindow,
1199 loaderdrv_FlashWindowEx,
1200 loaderdrv_GetDC,
1201 nulldrv_MsgWaitForMultipleObjectsEx,
1202 nulldrv_ReleaseDC,
1203 nulldrv_ScrollDC,
1204 nulldrv_SetCapture,
1205 nulldrv_SetFocus,
1206 loaderdrv_SetLayeredWindowAttributes,
1207 nulldrv_SetParent,
1208 loaderdrv_SetWindowRgn,
1209 nulldrv_SetWindowIcon,
1210 nulldrv_SetWindowStyle,
1211 nulldrv_SetWindowText,
1212 nulldrv_ShowWindow,
1213 nulldrv_SysCommand,
1214 loaderdrv_UpdateLayeredWindow,
1215 nulldrv_WindowMessage,
1216 nulldrv_WindowPosChanging,
1217 nulldrv_WindowPosChanged,
1218 /* system parameters */
1219 nulldrv_SystemParametersInfo,
1220 /* vulkan support */
1221 loaderdrv_wine_get_vulkan_driver,
1222 /* opengl support */
1223 nulldrv_wine_get_wgl_driver,
1224 /* thread management */
1225 nulldrv_ThreadDetach,
1228 const struct user_driver_funcs *user_driver = &lazy_load_driver;
1230 /******************************************************************************
1231 * __wine_set_user_driver (win32u.so)
1233 void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version )
1235 struct user_driver_funcs *driver, *prev;
1237 if (version != WINE_GDI_DRIVER_VERSION)
1239 ERR( "version mismatch, driver wants %u but win32u has %u\n",
1240 version, WINE_GDI_DRIVER_VERSION );
1241 return;
1244 driver = malloc( sizeof(*driver) );
1245 *driver = *funcs;
1247 #define SET_USER_FUNC(name) \
1248 do { if (!driver->p##name) driver->p##name = nulldrv_##name; } while(0)
1250 SET_USER_FUNC(ActivateKeyboardLayout);
1251 SET_USER_FUNC(Beep);
1252 SET_USER_FUNC(GetKeyNameText);
1253 SET_USER_FUNC(GetKeyboardLayoutList);
1254 SET_USER_FUNC(MapVirtualKeyEx);
1255 SET_USER_FUNC(RegisterHotKey);
1256 SET_USER_FUNC(ToUnicodeEx);
1257 SET_USER_FUNC(UnregisterHotKey);
1258 SET_USER_FUNC(VkKeyScanEx);
1259 SET_USER_FUNC(DestroyCursorIcon);
1260 SET_USER_FUNC(SetCursor);
1261 SET_USER_FUNC(GetCursorPos);
1262 SET_USER_FUNC(SetCursorPos);
1263 SET_USER_FUNC(ClipCursor);
1264 SET_USER_FUNC(ClipboardWindowProc);
1265 SET_USER_FUNC(UpdateClipboard);
1266 SET_USER_FUNC(ChangeDisplaySettings);
1267 SET_USER_FUNC(EnumDisplaySettingsEx);
1268 SET_USER_FUNC(GetCurrentDisplaySettings);
1269 SET_USER_FUNC(UpdateDisplayDevices);
1270 SET_USER_FUNC(CreateDesktopWindow);
1271 SET_USER_FUNC(CreateWindow);
1272 SET_USER_FUNC(DesktopWindowProc);
1273 SET_USER_FUNC(DestroyWindow);
1274 SET_USER_FUNC(FlashWindowEx);
1275 SET_USER_FUNC(GetDC);
1276 SET_USER_FUNC(MsgWaitForMultipleObjectsEx);
1277 SET_USER_FUNC(ReleaseDC);
1278 SET_USER_FUNC(ScrollDC);
1279 SET_USER_FUNC(SetCapture);
1280 SET_USER_FUNC(SetFocus);
1281 SET_USER_FUNC(SetLayeredWindowAttributes);
1282 SET_USER_FUNC(SetParent);
1283 SET_USER_FUNC(SetWindowRgn);
1284 SET_USER_FUNC(SetWindowIcon);
1285 SET_USER_FUNC(SetWindowStyle);
1286 SET_USER_FUNC(SetWindowText);
1287 SET_USER_FUNC(ShowWindow);
1288 SET_USER_FUNC(SysCommand);
1289 SET_USER_FUNC(UpdateLayeredWindow);
1290 SET_USER_FUNC(WindowMessage);
1291 SET_USER_FUNC(WindowPosChanging);
1292 SET_USER_FUNC(WindowPosChanged);
1293 SET_USER_FUNC(SystemParametersInfo);
1294 SET_USER_FUNC(wine_get_vulkan_driver);
1295 SET_USER_FUNC(wine_get_wgl_driver);
1296 SET_USER_FUNC(ThreadDetach);
1297 #undef SET_USER_FUNC
1299 prev = InterlockedCompareExchangePointer( (void **)&user_driver, driver, (void *)&lazy_load_driver );
1300 if (prev != &lazy_load_driver)
1302 /* another thread beat us to it */
1303 free( driver );
1304 driver = prev;
1308 /******************************************************************************
1309 * NtGdiExtEscape (win32u.@)
1311 * Access capabilities of a particular device that are not available through GDI.
1313 INT WINAPI NtGdiExtEscape( HDC hdc, WCHAR *driver, int driver_id, INT escape, INT input_size,
1314 const char *input, INT output_size, char *output )
1316 PHYSDEV physdev;
1317 INT ret;
1318 DC * dc = get_dc_ptr( hdc );
1320 if (!dc) return 0;
1321 update_dc( dc );
1322 physdev = GET_DC_PHYSDEV( dc, pExtEscape );
1323 ret = physdev->funcs->pExtEscape( physdev, escape, input_size, input, output_size, output );
1324 release_dc_ptr( dc );
1325 return ret;
1329 /******************************************************************************
1330 * NtGdiDdDDIOpenAdapterFromHdc (win32u.@)
1332 NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromHdc( D3DKMT_OPENADAPTERFROMHDC *desc )
1334 FIXME( "(%p): stub\n", desc );
1335 return STATUS_NO_MEMORY;
1338 /******************************************************************************
1339 * NtGdiDdDDIEscape (win32u.@)
1341 NTSTATUS WINAPI NtGdiDdDDIEscape( const D3DKMT_ESCAPE *desc )
1343 FIXME( "(%p): stub\n", desc );
1344 return STATUS_NO_MEMORY;
1347 /******************************************************************************
1348 * NtGdiDdDDICloseAdapter (win32u.@)
1350 NTSTATUS WINAPI NtGdiDdDDICloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
1352 NTSTATUS status = STATUS_INVALID_PARAMETER;
1353 struct d3dkmt_adapter *adapter;
1355 TRACE("(%p)\n", desc);
1357 if (!desc || !desc->hAdapter)
1358 return STATUS_INVALID_PARAMETER;
1360 if (get_display_driver()->pD3DKMTCloseAdapter)
1361 get_display_driver()->pD3DKMTCloseAdapter( desc );
1363 pthread_mutex_lock( &driver_lock );
1364 LIST_FOR_EACH_ENTRY( adapter, &d3dkmt_adapters, struct d3dkmt_adapter, entry )
1366 if (adapter->handle == desc->hAdapter)
1368 list_remove( &adapter->entry );
1369 free( adapter );
1370 status = STATUS_SUCCESS;
1371 break;
1374 pthread_mutex_unlock( &driver_lock );
1376 return status;
1379 /******************************************************************************
1380 * NtGdiDdDDIOpenAdapterFromDeviceName (win32u.@)
1382 NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromDeviceName( D3DKMT_OPENADAPTERFROMDEVICENAME *desc )
1384 D3DKMT_OPENADAPTERFROMLUID desc_luid;
1385 NTSTATUS status;
1387 FIXME( "desc %p stub.\n", desc );
1389 if (!desc || !desc->pDeviceName) return STATUS_INVALID_PARAMETER;
1391 memset( &desc_luid, 0, sizeof( desc_luid ));
1392 if ((status = NtGdiDdDDIOpenAdapterFromLuid( &desc_luid ))) return status;
1394 desc->AdapterLuid = desc_luid.AdapterLuid;
1395 desc->hAdapter = desc_luid.hAdapter;
1396 return STATUS_SUCCESS;
1399 /******************************************************************************
1400 * NtGdiDdDDIOpenAdapterFromLuid (win32u.@)
1402 NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
1404 static D3DKMT_HANDLE handle_start = 0;
1405 struct d3dkmt_adapter *adapter;
1407 if (!(adapter = malloc( sizeof( *adapter ) ))) return STATUS_NO_MEMORY;
1409 pthread_mutex_lock( &driver_lock );
1410 desc->hAdapter = adapter->handle = ++handle_start;
1411 list_add_tail( &d3dkmt_adapters, &adapter->entry );
1412 pthread_mutex_unlock( &driver_lock );
1414 if (get_display_driver()->pD3DKMTOpenAdapterFromLuid)
1415 get_display_driver()->pD3DKMTOpenAdapterFromLuid( desc );
1417 return STATUS_SUCCESS;
1420 /******************************************************************************
1421 * NtGdiDdDDICreateDevice (win32u.@)
1423 NTSTATUS WINAPI NtGdiDdDDICreateDevice( D3DKMT_CREATEDEVICE *desc )
1425 static D3DKMT_HANDLE handle_start = 0;
1426 struct d3dkmt_adapter *adapter;
1427 struct d3dkmt_device *device;
1428 BOOL found = FALSE;
1430 TRACE("(%p)\n", desc);
1432 if (!desc)
1433 return STATUS_INVALID_PARAMETER;
1435 pthread_mutex_lock( &driver_lock );
1436 LIST_FOR_EACH_ENTRY( adapter, &d3dkmt_adapters, struct d3dkmt_adapter, entry )
1438 if (adapter->handle == desc->hAdapter)
1440 found = TRUE;
1441 break;
1444 pthread_mutex_unlock( &driver_lock );
1446 if (!found)
1447 return STATUS_INVALID_PARAMETER;
1449 if (desc->Flags.LegacyMode || desc->Flags.RequestVSync || desc->Flags.DisableGpuTimeout)
1450 FIXME("Flags unsupported.\n");
1452 device = calloc( 1, sizeof( *device ) );
1453 if (!device)
1454 return STATUS_NO_MEMORY;
1456 pthread_mutex_lock( &driver_lock );
1457 device->handle = ++handle_start;
1458 list_add_tail( &d3dkmt_devices, &device->entry );
1459 pthread_mutex_unlock( &driver_lock );
1461 desc->hDevice = device->handle;
1462 return STATUS_SUCCESS;
1465 /******************************************************************************
1466 * NtGdiDdDDIDestroyDevice (win32u.@)
1468 NTSTATUS WINAPI NtGdiDdDDIDestroyDevice( const D3DKMT_DESTROYDEVICE *desc )
1470 NTSTATUS status = STATUS_INVALID_PARAMETER;
1471 D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc;
1472 struct d3dkmt_device *device;
1474 TRACE("(%p)\n", desc);
1476 if (!desc || !desc->hDevice)
1477 return STATUS_INVALID_PARAMETER;
1479 pthread_mutex_lock( &driver_lock );
1480 LIST_FOR_EACH_ENTRY( device, &d3dkmt_devices, struct d3dkmt_device, entry )
1482 if (device->handle == desc->hDevice)
1484 memset( &set_owner_desc, 0, sizeof(set_owner_desc) );
1485 set_owner_desc.hDevice = desc->hDevice;
1486 NtGdiDdDDISetVidPnSourceOwner( &set_owner_desc );
1487 list_remove( &device->entry );
1488 free( device );
1489 status = STATUS_SUCCESS;
1490 break;
1493 pthread_mutex_unlock( &driver_lock );
1495 return status;
1498 /******************************************************************************
1499 * NtGdiDdDDIQueryStatistics (win32u.@)
1501 NTSTATUS WINAPI NtGdiDdDDIQueryStatistics( D3DKMT_QUERYSTATISTICS *stats )
1503 FIXME("(%p): stub\n", stats);
1504 return STATUS_SUCCESS;
1507 /******************************************************************************
1508 * NtGdiDdDDIQueryVideoMemoryInfo (win32u.@)
1510 NTSTATUS WINAPI NtGdiDdDDIQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc )
1512 OBJECT_BASIC_INFORMATION info;
1513 NTSTATUS status;
1515 TRACE("(%p)\n", desc);
1517 if (!desc || !desc->hAdapter ||
1518 (desc->MemorySegmentGroup != D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL &&
1519 desc->MemorySegmentGroup != D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL))
1520 return STATUS_INVALID_PARAMETER;
1522 /* FIXME: Wine currently doesn't support linked adapters */
1523 if (desc->PhysicalAdapterIndex > 0)
1524 return STATUS_INVALID_PARAMETER;
1526 status = NtQueryObject(desc->hProcess ? desc->hProcess : GetCurrentProcess(),
1527 ObjectBasicInformation, &info, sizeof(info), NULL);
1528 if (status != STATUS_SUCCESS)
1529 return status;
1530 if (!(info.GrantedAccess & PROCESS_QUERY_INFORMATION))
1531 return STATUS_ACCESS_DENIED;
1533 if (!get_display_driver()->pD3DKMTQueryVideoMemoryInfo)
1534 return STATUS_PROCEDURE_NOT_FOUND;
1535 return get_display_driver()->pD3DKMTQueryVideoMemoryInfo(desc);
1538 /******************************************************************************
1539 * NtGdiDdDDISetQueuedLimit (win32u.@)
1541 NTSTATUS WINAPI NtGdiDdDDISetQueuedLimit( D3DKMT_SETQUEUEDLIMIT *desc )
1543 FIXME( "(%p): stub\n", desc );
1544 return STATUS_NOT_IMPLEMENTED;
1547 /******************************************************************************
1548 * NtGdiDdDDISetVidPnSourceOwner (win32u.@)
1550 NTSTATUS WINAPI NtGdiDdDDISetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
1552 TRACE("(%p)\n", desc);
1554 if (!get_display_driver()->pD3DKMTSetVidPnSourceOwner)
1555 return STATUS_PROCEDURE_NOT_FOUND;
1557 if (!desc || !desc->hDevice || (desc->VidPnSourceCount && (!desc->pType || !desc->pVidPnSourceId)))
1558 return STATUS_INVALID_PARAMETER;
1560 /* Store the VidPN source ownership info in the graphics driver because
1561 * the graphics driver needs to change ownership sometimes. For example,
1562 * when a new window is moved to a VidPN source with an exclusive owner,
1563 * such an exclusive owner will be released before showing the new window */
1564 return get_display_driver()->pD3DKMTSetVidPnSourceOwner( desc );
1567 /******************************************************************************
1568 * NtGdiDdDDICheckVidPnExclusiveOwnership (win32u.@)
1570 NTSTATUS WINAPI NtGdiDdDDICheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
1572 TRACE("(%p)\n", desc);
1574 if (!get_display_driver()->pD3DKMTCheckVidPnExclusiveOwnership)
1575 return STATUS_PROCEDURE_NOT_FOUND;
1577 if (!desc || !desc->hAdapter)
1578 return STATUS_INVALID_PARAMETER;
1580 return get_display_driver()->pD3DKMTCheckVidPnExclusiveOwnership( desc );