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:
parent
6342e9217d
commit
09362dbf75
|
@ -35,6 +35,12 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dc);
|
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 BOOL DC_DeleteObject( HGDIOBJ handle );
|
||||||
|
|
||||||
static const struct gdi_obj_funcs dc_funcs =
|
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,
|
HDC WINAPI NtGdiOpenDCW( UNICODE_STRING *device, const DEVMODEW *devmode, UNICODE_STRING *output,
|
||||||
const DEVMODEW *initData )
|
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;
|
HDC hdc;
|
||||||
DC * dc;
|
DC * dc;
|
||||||
const struct gdi_dc_funcs *funcs;
|
|
||||||
WCHAR buf[300];
|
|
||||||
|
|
||||||
GDI_CheckNotLock();
|
GDI_CheckNotLock();
|
||||||
|
|
||||||
if (!device || !DRIVER_GetDriverName( device, buf, 300 ))
|
if (is_display)
|
||||||
|
funcs = get_display_driver();
|
||||||
|
else if (hspool)
|
||||||
{
|
{
|
||||||
if (!driver)
|
const struct gdi_dc_funcs * (CDECL *wine_get_gdi_driver)( unsigned int ) = hspool;
|
||||||
{
|
funcs = wine_get_gdi_driver( WINE_GDI_DRIVER_VERSION );
|
||||||
ERR( "no device found for %s\n", debugstr_w(device) );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
lstrcpyW(buf, driver);
|
|
||||||
}
|
}
|
||||||
|
if (!funcs)
|
||||||
if (!(funcs = DRIVER_load_driver( buf )))
|
|
||||||
{
|
{
|
||||||
ERR( "no driver found for %s\n", debugstr_w(buf) );
|
ERR( "no driver found\n" );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dc = alloc_dc_ptr( NTGDI_OBJ_DC ))) return 0;
|
if (!(dc = alloc_dc_ptr( NTGDI_OBJ_DC ))) return 0;
|
||||||
hdc = dc->hSelf;
|
hdc = dc->hSelf;
|
||||||
|
|
||||||
dc->hBitmap = GDI_inc_ref_count( get_stock_object( DEFAULT_BITMAP ));
|
dc->hBitmap = GDI_inc_ref_count( get_stock_object( DEFAULT_BITMAP ));
|
||||||
|
|
||||||
TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
|
TRACE("(device=%s, output=%s): returning %p\n",
|
||||||
debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
|
debugstr_us(device), debugstr_us(output), dc->hSelf );
|
||||||
|
|
||||||
if (funcs->pCreateDC)
|
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" );
|
WARN("creation aborted by device\n" );
|
||||||
free_dc_ptr( dc );
|
free_dc_ptr( dc );
|
||||||
|
@ -674,21 +678,11 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_display_device( driver ))
|
if (is_display && device)
|
||||||
display = driver;
|
|
||||||
else if (is_display_device( device ))
|
|
||||||
display = device;
|
|
||||||
else
|
|
||||||
display = NULL;
|
|
||||||
|
|
||||||
if (display)
|
|
||||||
{
|
{
|
||||||
/* Copy only the display name. For example, \\.\DISPLAY1 in \\.\DISPLAY1\Monitor0 */
|
memcpy( dc->display, device->Buffer, device->Length );
|
||||||
p = display + 12;
|
dc->display[device->Length / sizeof(WCHAR)] = 0;
|
||||||
while (iswdigit( *p ))
|
|
||||||
++p;
|
|
||||||
lstrcpynW( dc->display, display, p - display + 1 );
|
|
||||||
dc->display[p - display] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dc->attr->vis_rect.left = 0;
|
dc->attr->vis_rect.left = 0;
|
||||||
|
@ -721,7 +715,7 @@ HDC WINAPI NtGdiCreateCompatibleDC( HDC hdc )
|
||||||
funcs = physDev->funcs;
|
funcs = physDev->funcs;
|
||||||
release_dc_ptr( origDC );
|
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;
|
if (!(dc = alloc_dc_ptr( NTGDI_OBJ_MEMDC ))) return 0;
|
||||||
|
|
||||||
|
|
|
@ -39,13 +39,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(driver);
|
WINE_DEFAULT_DEBUG_CHANNEL(driver);
|
||||||
|
|
||||||
struct graphics_driver
|
|
||||||
{
|
|
||||||
struct list entry;
|
|
||||||
HMODULE module; /* module handle */
|
|
||||||
const struct gdi_dc_funcs *funcs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct d3dkmt_adapter
|
struct d3dkmt_adapter
|
||||||
{
|
{
|
||||||
D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */
|
D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */
|
||||||
|
@ -58,8 +51,7 @@ struct d3dkmt_device
|
||||||
struct list entry; /* List entry */
|
struct list entry; /* List entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct list drivers = LIST_INIT( drivers );
|
const struct gdi_dc_funcs *driver_funcs;
|
||||||
static struct graphics_driver *display_driver;
|
|
||||||
|
|
||||||
static struct list d3dkmt_adapters = LIST_INIT( d3dkmt_adapters );
|
static struct list d3dkmt_adapters = LIST_INIT( d3dkmt_adapters );
|
||||||
static struct list d3dkmt_devices = LIST_INIT( d3dkmt_devices );
|
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 INT (WINAPI *pGetSystemMetrics)(INT);
|
||||||
static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
|
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
|
* get_display_driver
|
||||||
*
|
*
|
||||||
* Special case for loading the display driver: get the name from the config file
|
* 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" );
|
HMODULE user32 = LoadLibraryA( "user32.dll" );
|
||||||
pGetDesktopWindow = (void *)GetProcAddress( user32, "GetDesktopWindow" );
|
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" );
|
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;
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,16 +101,18 @@ done:
|
||||||
*/
|
*/
|
||||||
void CDECL __wine_set_display_driver( HMODULE module )
|
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;
|
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" );
|
ERR( "Could not create graphics driver\n" );
|
||||||
NtTerminateProcess( GetCurrentThread(), 1 );
|
NtTerminateProcess( GetCurrentThread(), 1 );
|
||||||
}
|
}
|
||||||
if (InterlockedCompareExchangePointer( (void **)&display_driver, driver, NULL ))
|
InterlockedExchangePointer( (void **)&driver_funcs, (void *)funcs );
|
||||||
HeapFree( GetProcessHeap(), 0, driver );
|
|
||||||
|
|
||||||
user32 = LoadLibraryA( "user32.dll" );
|
user32 = LoadLibraryA( "user32.dll" );
|
||||||
pGetMonitorInfoW = (void *)GetProcAddress( user32, "GetMonitorInfoW" );
|
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 )
|
static BOOL CDECL nulldrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
|
||||||
{
|
{
|
||||||
if (!display_driver || !display_driver->funcs->pCreateCompatibleDC) return TRUE;
|
if (!driver_funcs || !driver_funcs->pCreateCompatibleDC) return TRUE;
|
||||||
return display_driver->funcs->pCreateCompatibleDC( NULL, pdev );
|
return driver_funcs->pCreateCompatibleDC( NULL, pdev );
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL CDECL nulldrv_CreateDC( PHYSDEV *dev, LPCWSTR device, LPCWSTR output,
|
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.@)
|
* NtGdiExtEscape (win32u.@)
|
||||||
*
|
*
|
||||||
|
|
|
@ -585,7 +585,7 @@ HDC WINAPI NtGdiCreateMetafileDC( HDC hdc )
|
||||||
if (hdc) /* if no ref, use current display */
|
if (hdc) /* if no ref, use current display */
|
||||||
ref_dc = hdc;
|
ref_dc = hdc;
|
||||||
else
|
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) );
|
memset( physDev->dev_caps, 0, sizeof(physDev->dev_caps) );
|
||||||
for (cap = 0; cap < ARRAY_SIZE( physDev->dev_caps ); cap++)
|
for (cap = 0; cap < ARRAY_SIZE( physDev->dev_caps ); cap++)
|
||||||
|
|
|
@ -25,10 +25,32 @@
|
||||||
#include "ddrawgdi.h"
|
#include "ddrawgdi.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
|
|
||||||
|
#include "wine/list.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(gdi);
|
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 )
|
DC_ATTR *get_dc_attr( HDC hdc )
|
||||||
{
|
{
|
||||||
DWORD type = gdi_handle_type( 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;
|
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.@)
|
* CreateDCA (GDI32.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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 dib_driver DECLSPEC_HIDDEN;
|
||||||
extern const struct gdi_dc_funcs path_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 font_driver DECLSPEC_HIDDEN;
|
||||||
extern const struct gdi_dc_funcs *DRIVER_load_driver( LPCWSTR name ) DECLSPEC_HIDDEN;
|
extern const struct gdi_dc_funcs *get_display_driver(void) DECLSPEC_HIDDEN;
|
||||||
extern BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) DECLSPEC_HIDDEN;
|
|
||||||
|
|
||||||
/* font.c */
|
/* font.c */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue