diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 5cc3c7e557b..dbdc561c273 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -35,6 +35,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(dc); +static inline const char *debugstr_us( const UNICODE_STRING *us ) +{ + if (!us) return ""; + return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) ); +} + static BOOL DC_DeleteObject( HGDIOBJ handle ); static const struct gdi_obj_funcs dc_funcs = @@ -628,45 +634,43 @@ BOOL WINAPI NtGdiRestoreDC( HDC hdc, INT level ) /*********************************************************************** - * CreateDCW (GDI32.@) + * NtGdiOpenDCW (win32u.@) */ -HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, - const DEVMODEW *initData ) +HDC WINAPI NtGdiOpenDCW( UNICODE_STRING *device, const DEVMODEW *devmode, UNICODE_STRING *output, + ULONG type, BOOL is_display, HANDLE hspool, DRIVER_INFO_2W *driver_info, + void *pdev ) { - const WCHAR *display, *p; + const struct gdi_dc_funcs *funcs = NULL; HDC hdc; DC * dc; - const struct gdi_dc_funcs *funcs; - WCHAR buf[300]; GDI_CheckNotLock(); - if (!device || !DRIVER_GetDriverName( device, buf, 300 )) + if (is_display) + funcs = get_display_driver(); + else if (hspool) { - if (!driver) - { - ERR( "no device found for %s\n", debugstr_w(device) ); - return 0; - } - lstrcpyW(buf, driver); + const struct gdi_dc_funcs * (CDECL *wine_get_gdi_driver)( unsigned int ) = hspool; + funcs = wine_get_gdi_driver( WINE_GDI_DRIVER_VERSION ); } - - if (!(funcs = DRIVER_load_driver( buf ))) + if (!funcs) { - ERR( "no driver found for %s\n", debugstr_w(buf) ); + ERR( "no driver found\n" ); return 0; } + if (!(dc = alloc_dc_ptr( NTGDI_OBJ_DC ))) return 0; hdc = dc->hSelf; dc->hBitmap = GDI_inc_ref_count( get_stock_object( DEFAULT_BITMAP )); - TRACE("(driver=%s, device=%s, output=%s): returning %p\n", - debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf ); + TRACE("(device=%s, output=%s): returning %p\n", + debugstr_us(device), debugstr_us(output), dc->hSelf ); if (funcs->pCreateDC) { - if (!funcs->pCreateDC( &dc->physDev, device, output, initData )) + if (!funcs->pCreateDC( &dc->physDev, device ? device->Buffer : NULL, + output ? output->Buffer : NULL, devmode )) { WARN("creation aborted by device\n" ); free_dc_ptr( dc ); @@ -674,21 +678,11 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, } } - if (is_display_device( driver )) - display = driver; - else if (is_display_device( device )) - display = device; - else - display = NULL; - - if (display) + if (is_display && device) { - /* Copy only the display name. For example, \\.\DISPLAY1 in \\.\DISPLAY1\Monitor0 */ - p = display + 12; - while (iswdigit( *p )) - ++p; - lstrcpynW( dc->display, display, p - display + 1 ); - dc->display[p - display] = '\0'; + memcpy( dc->display, device->Buffer, device->Length ); + dc->display[device->Length / sizeof(WCHAR)] = 0; + } dc->attr->vis_rect.left = 0; @@ -721,7 +715,7 @@ HDC WINAPI NtGdiCreateCompatibleDC( HDC hdc ) funcs = physDev->funcs; release_dc_ptr( origDC ); } - else funcs = DRIVER_load_driver( L"display" ); + else funcs = get_display_driver(); if (!(dc = alloc_dc_ptr( NTGDI_OBJ_MEMDC ))) return 0; diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index e1032dc3412..b277dc17452 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -39,13 +39,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(driver); -struct graphics_driver -{ - struct list entry; - HMODULE module; /* module handle */ - const struct gdi_dc_funcs *funcs; -}; - struct d3dkmt_adapter { D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */ @@ -58,8 +51,7 @@ struct d3dkmt_device struct list entry; /* List entry */ }; -static struct list drivers = LIST_INIT( drivers ); -static struct graphics_driver *display_driver; +const struct gdi_dc_funcs *driver_funcs; static struct list d3dkmt_adapters = LIST_INIT( d3dkmt_adapters ); static struct list d3dkmt_devices = LIST_INIT( d3dkmt_devices ); @@ -80,147 +72,27 @@ static BOOL (WINAPI *pGetMonitorInfoW)(HMONITOR, LPMONITORINFO); static INT (WINAPI *pGetSystemMetrics)(INT); static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); -/********************************************************************** - * create_driver - * - * Allocate and fill the driver structure for a given module. - */ -static struct graphics_driver *create_driver( HMODULE module ) -{ - static const struct gdi_dc_funcs empty_funcs; - const struct gdi_dc_funcs *funcs = NULL; - struct graphics_driver *driver; - - if (!(driver = HeapAlloc( GetProcessHeap(), 0, sizeof(*driver)))) return NULL; - driver->module = module; - - if (module) - { - const struct gdi_dc_funcs * (CDECL *wine_get_gdi_driver)( unsigned int version ); - - if ((wine_get_gdi_driver = (void *)GetProcAddress( module, "wine_get_gdi_driver" ))) - funcs = wine_get_gdi_driver( WINE_GDI_DRIVER_VERSION ); - } - if (!funcs) funcs = &empty_funcs; - driver->funcs = funcs; - return driver; -} - /********************************************************************** * get_display_driver * * Special case for loading the display driver: get the name from the config file */ -static const struct gdi_dc_funcs *get_display_driver(void) +const struct gdi_dc_funcs *get_display_driver(void) { - if (!display_driver) + if (!driver_funcs) { HMODULE user32 = LoadLibraryA( "user32.dll" ); pGetDesktopWindow = (void *)GetProcAddress( user32, "GetDesktopWindow" ); - if (!pGetDesktopWindow() || !display_driver) + if (!pGetDesktopWindow() || !driver_funcs) { + static struct gdi_dc_funcs empty_funcs; WARN( "failed to load the display driver, falling back to null driver\n" ); - __wine_set_display_driver( 0 ); + driver_funcs = &empty_funcs; } } - return display_driver->funcs; -} - - -/********************************************************************** - * is_display_device - */ -BOOL is_display_device( LPCWSTR name ) -{ - const WCHAR *p = name; - - if (!name) - return FALSE; - - if (wcsnicmp( name, L"\\\\.\\DISPLAY", lstrlenW(L"\\\\.\\DISPLAY") )) return FALSE; - - p += lstrlenW(L"\\\\.\\DISPLAY"); - - if (!iswdigit( *p++ )) - return FALSE; - - for (; *p; p++) - { - if (!iswdigit( *p )) - return FALSE; - } - - return TRUE; -} - -#ifdef __i386__ -static const WCHAR printer_env[] = L"w32x86"; -#elif defined __x86_64__ -static const WCHAR printer_env[] = L"x64"; -#elif defined __arm__ -static const WCHAR printer_env[] = L"arm"; -#elif defined __aarch64__ -static const WCHAR printer_env[] = L"arm64"; -#else -#error not defined for this cpu -#endif - -/********************************************************************** - * DRIVER_load_driver - */ -const struct gdi_dc_funcs *DRIVER_load_driver( LPCWSTR name ) -{ - HMODULE module; - struct graphics_driver *driver, *new_driver; - - /* display driver is a special case */ - if (!wcsicmp( name, L"display" ) || is_display_device( name )) return get_display_driver(); - - if ((module = GetModuleHandleW( name ))) - { - if (display_driver && display_driver->module == module) return display_driver->funcs; - - EnterCriticalSection( &driver_section ); - LIST_FOR_EACH_ENTRY( driver, &drivers, struct graphics_driver, entry ) - { - if (driver->module == module) goto done; - } - LeaveCriticalSection( &driver_section ); - } - - if (!(module = LoadLibraryW( name ))) - { - WCHAR path[MAX_PATH]; - - GetSystemDirectoryW( path, MAX_PATH ); - swprintf( path + wcslen(path), MAX_PATH - wcslen(path), L"\\spool\\drivers\\%s\\3\\%s", - printer_env, name ); - if (!(module = LoadLibraryW( path ))) return NULL; - } - - if (!(new_driver = create_driver( module ))) - { - FreeLibrary( module ); - return NULL; - } - - /* check if someone else added it in the meantime */ - EnterCriticalSection( &driver_section ); - LIST_FOR_EACH_ENTRY( driver, &drivers, struct graphics_driver, entry ) - { - if (driver->module != module) continue; - FreeLibrary( module ); - HeapFree( GetProcessHeap(), 0, new_driver ); - goto done; - } - driver = new_driver; - list_add_head( &drivers, &driver->entry ); - TRACE( "loaded driver %p for %s\n", driver, debugstr_w(name) ); -done: - LeaveCriticalSection( &driver_section ); - return driver->funcs; + return driver_funcs; } @@ -229,16 +101,18 @@ done: */ void CDECL __wine_set_display_driver( HMODULE module ) { - struct graphics_driver *driver; + const struct gdi_dc_funcs * (CDECL *wine_get_gdi_driver)( unsigned int ); + const struct gdi_dc_funcs *funcs = NULL; HMODULE user32; - if (!(driver = create_driver( module ))) + wine_get_gdi_driver = (void *)GetProcAddress( module, "wine_get_gdi_driver" ); + if (wine_get_gdi_driver) funcs = wine_get_gdi_driver( WINE_GDI_DRIVER_VERSION ); + if (!funcs) { ERR( "Could not create graphics driver\n" ); NtTerminateProcess( GetCurrentThread(), 1 ); } - if (InterlockedCompareExchangePointer( (void **)&display_driver, driver, NULL )) - HeapFree( GetProcessHeap(), 0, driver ); + InterlockedExchangePointer( (void **)&driver_funcs, (void *)funcs ); user32 = LoadLibraryA( "user32.dll" ); pGetMonitorInfoW = (void *)GetProcAddress( user32, "GetMonitorInfoW" ); @@ -289,8 +163,8 @@ static BOOL CDECL nulldrv_Chord( PHYSDEV dev, INT left, INT top, INT right, INT static BOOL CDECL nulldrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev ) { - if (!display_driver || !display_driver->funcs->pCreateCompatibleDC) return TRUE; - return display_driver->funcs->pCreateCompatibleDC( NULL, pdev ); + if (!driver_funcs || !driver_funcs->pCreateCompatibleDC) return TRUE; + return driver_funcs->pCreateCompatibleDC( NULL, pdev ); } static BOOL CDECL nulldrv_CreateDC( PHYSDEV *dev, LPCWSTR device, LPCWSTR output, @@ -889,38 +763,6 @@ const struct gdi_dc_funcs null_driver = }; -/***************************************************************************** - * DRIVER_GetDriverName - * - */ -BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) -{ - WCHAR *p; - - /* display is a special case */ - if (!wcsicmp( device, L"display" ) || is_display_device( device )) - { - lstrcpynW( driver, L"display", size ); - return TRUE; - } - - size = GetProfileStringW(L"devices", device, L"", driver, size); - if(!size) { - WARN("Unable to find %s in [devices] section of win.ini\n", debugstr_w(device)); - return FALSE; - } - p = wcschr(driver, ','); - if(!p) - { - WARN("%s entry in [devices] section of win.ini is malformed.\n", debugstr_w(device)); - return FALSE; - } - *p = 0; - TRACE("Found %s for %s\n", debugstr_w(driver), debugstr_w(device)); - return TRUE; -} - - /****************************************************************************** * NtGdiExtEscape (win32u.@) * diff --git a/dlls/gdi32/emfdrv.c b/dlls/gdi32/emfdrv.c index 8569f5dd8c7..ebf93f91f40 100644 --- a/dlls/gdi32/emfdrv.c +++ b/dlls/gdi32/emfdrv.c @@ -585,7 +585,7 @@ HDC WINAPI NtGdiCreateMetafileDC( HDC hdc ) if (hdc) /* if no ref, use current display */ ref_dc = hdc; else - ref_dc = CreateDCW( L"DISPLAY", NULL, NULL, NULL ); + ref_dc = NtGdiOpenDCW( NULL, NULL, NULL, 0, TRUE, NULL, NULL, NULL ); memset( physDev->dev_caps, 0, sizeof(physDev->dev_caps) ); for (cap = 0; cap < ARRAY_SIZE( physDev->dev_caps ); cap++) diff --git a/dlls/gdi32/gdidc.c b/dlls/gdi32/gdidc.c index b2e673fe581..5ea18e58b18 100644 --- a/dlls/gdi32/gdidc.c +++ b/dlls/gdi32/gdidc.c @@ -25,10 +25,32 @@ #include "ddrawgdi.h" #include "winnls.h" +#include "wine/list.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(gdi); +static struct list drivers = LIST_INIT( drivers ); + +static CRITICAL_SECTION driver_section; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &driver_section, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": driver_section") } +}; +static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 }; + +typedef const void * (CDECL *driver_entry_point)( unsigned int version ); + +struct graphics_driver +{ + struct list entry; + HMODULE module; /* module handle */ + driver_entry_point entry_point; +}; + + DC_ATTR *get_dc_attr( HDC hdc ) { DWORD type = gdi_handle_type( hdc ); @@ -41,6 +63,199 @@ DC_ATTR *get_dc_attr( HDC hdc ) return dc_attr->disabled ? NULL : dc_attr; } +static BOOL is_display_device( const WCHAR *name ) +{ + const WCHAR *p = name; + + if (!name) + return FALSE; + + if (wcsnicmp( name, L"\\\\.\\DISPLAY", lstrlenW(L"\\\\.\\DISPLAY") )) return FALSE; + + p += lstrlenW(L"\\\\.\\DISPLAY"); + + if (!iswdigit( *p++ )) + return FALSE; + + for (; *p; p++) + { + if (!iswdigit( *p )) + return FALSE; + } + + return TRUE; +} + +static BOOL get_driver_name( const WCHAR *device, WCHAR *driver, DWORD size ) +{ + WCHAR *p; + + /* display is a special case */ + if (!wcsicmp( device, L"display" ) || is_display_device( device )) + { + lstrcpynW( driver, L"display", size ); + return TRUE; + } + + size = GetProfileStringW(L"devices", device, L"", driver, size); + if (!size) + { + WARN("Unable to find %s in [devices] section of win.ini\n", debugstr_w(device)); + return FALSE; + } + p = wcschr(driver, ','); + if (!p) + { + WARN("%s entry in [devices] section of win.ini is malformed.\n", debugstr_w(device)); + return FALSE; + } + *p = 0; + TRACE("Found %s for %s\n", debugstr_w(driver), debugstr_w(device)); + return TRUE; +} + +static struct graphics_driver *create_driver( HMODULE module ) +{ + struct graphics_driver *driver; + + if (!(driver = HeapAlloc( GetProcessHeap(), 0, sizeof(*driver)))) return NULL; + driver->module = module; + + if (module) + driver->entry_point = (void *)GetProcAddress( module, "wine_get_gdi_driver" ); + else + driver->entry_point = NULL; + + return driver; +} + +#ifdef __i386__ +static const WCHAR printer_env[] = L"w32x86"; +#elif defined __x86_64__ +static const WCHAR printer_env[] = L"x64"; +#elif defined __arm__ +static const WCHAR printer_env[] = L"arm"; +#elif defined __aarch64__ +static const WCHAR printer_env[] = L"arm64"; +#else +#error not defined for this cpu +#endif + +static driver_entry_point load_driver( LPCWSTR name ) +{ + HMODULE module; + struct graphics_driver *driver, *new_driver; + + if ((module = GetModuleHandleW( name ))) + { + EnterCriticalSection( &driver_section ); + LIST_FOR_EACH_ENTRY( driver, &drivers, struct graphics_driver, entry ) + { + if (driver->module == module) goto done; + } + LeaveCriticalSection( &driver_section ); + } + + if (!(module = LoadLibraryW( name ))) + { + WCHAR path[MAX_PATH]; + + GetSystemDirectoryW( path, MAX_PATH ); + swprintf( path + wcslen(path), MAX_PATH - wcslen(path), L"\\spool\\drivers\\%s\\3\\%s", + printer_env, name ); + if (!(module = LoadLibraryW( path ))) return NULL; + } + + if (!(new_driver = create_driver( module ))) + { + FreeLibrary( module ); + return NULL; + } + + /* check if someone else added it in the meantime */ + EnterCriticalSection( &driver_section ); + LIST_FOR_EACH_ENTRY( driver, &drivers, struct graphics_driver, entry ) + { + if (driver->module != module) continue; + FreeLibrary( module ); + HeapFree( GetProcessHeap(), 0, new_driver ); + goto done; + } + driver = new_driver; + list_add_head( &drivers, &driver->entry ); + TRACE( "loaded driver %p for %s\n", driver, debugstr_w(name) ); +done: + LeaveCriticalSection( &driver_section ); + return driver->entry_point; +} + +/*********************************************************************** + * CreateDCW (GDI32.@) + */ +HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, + const DEVMODEW *devmode ) +{ + UNICODE_STRING device_str, output_str; + driver_entry_point entry_point = NULL; + const WCHAR *display = NULL, *p; + BOOL is_display = FALSE; + WCHAR buf[300]; + + if (!device || !get_driver_name( device, buf, 300 )) + { + if (!driver) + { + ERR( "no device found for %s\n", debugstr_w(device) ); + return 0; + } + lstrcpyW(buf, driver); + } + + if (is_display_device( driver )) + { + display = driver; + is_display = TRUE; + } + else if (is_display_device( device )) + { + display = device; + is_display = TRUE; + } + else if (!wcsicmp( buf, L"display" ) || is_display_device( buf )) + { + is_display = TRUE; + } + else if (!(entry_point = load_driver( buf ))) + { + ERR( "no driver found for %s\n", debugstr_w(buf) ); + return 0; + } + + if (display) + { + /* Use only the display name. For example, \\.\DISPLAY1 in \\.\DISPLAY1\Monitor0 */ + p = display + 12; + while (iswdigit( *p )) p++; + + device_str.Length = device_str.MaximumLength = (p - display) * sizeof(WCHAR); + device_str.Buffer = (WCHAR *)display; + } + else if (device) + { + device_str.Length = device_str.MaximumLength = lstrlenW( device ) * sizeof(WCHAR); + device_str.Buffer = (WCHAR *)device; + } + + if (output) + { + output_str.Length = output_str.MaximumLength = lstrlenW(output) * sizeof(WCHAR); + output_str.Buffer = (WCHAR *)output; + } + + return NtGdiOpenDCW( device || display ? &device_str : NULL, devmode, output ? &output_str : NULL, + 0, is_display, entry_point, NULL, NULL ); +} + /*********************************************************************** * CreateDCA (GDI32.@) */ diff --git a/dlls/gdi32/ntgdi_private.h b/dlls/gdi32/ntgdi_private.h index c342bcf3a7c..a39fe05bc01 100644 --- a/dlls/gdi32/ntgdi_private.h +++ b/dlls/gdi32/ntgdi_private.h @@ -218,8 +218,7 @@ extern const struct gdi_dc_funcs null_driver DECLSPEC_HIDDEN; extern const struct gdi_dc_funcs dib_driver DECLSPEC_HIDDEN; extern const struct gdi_dc_funcs path_driver DECLSPEC_HIDDEN; extern const struct gdi_dc_funcs font_driver DECLSPEC_HIDDEN; -extern const struct gdi_dc_funcs *DRIVER_load_driver( LPCWSTR name ) DECLSPEC_HIDDEN; -extern BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) DECLSPEC_HIDDEN; +extern const struct gdi_dc_funcs *get_display_driver(void) DECLSPEC_HIDDEN; /* font.c */