gdi32: Use NtGdiOpenDCW for CreateDCW.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-09-29 14:07:36 +02:00 committed by Alexandre Julliard
parent 6342e9217d
commit 09362dbf75
5 changed files with 260 additions and 210 deletions

View File

@ -35,6 +35,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(dc);
static inline const char *debugstr_us( const UNICODE_STRING *us )
{
if (!us) return "<null>";
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;
const struct gdi_dc_funcs * (CDECL *wine_get_gdi_driver)( unsigned int ) = hspool;
funcs = wine_get_gdi_driver( WINE_GDI_DRIVER_VERSION );
}
lstrcpyW(buf, driver);
if (!funcs)
{
ERR( "no driver found\n" );
return 0;
}
if (!(funcs = DRIVER_load_driver( buf )))
{
ERR( "no driver found for %s\n", debugstr_w(buf) );
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;

View File

@ -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.@)
*

View File

@ -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++)

View File

@ -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.@)
*/

View File

@ -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 */