win32u: Move load_driver implementation from user32.
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
5df07a48a6
commit
ca0f64f9ba
|
@ -28,74 +28,20 @@
|
|||
#include "controls.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(user);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
|
||||
static struct user_driver_funcs null_driver, lazy_load_driver;
|
||||
|
||||
const struct user_driver_funcs *USER_Driver = &lazy_load_driver;
|
||||
static char driver_load_error[80];
|
||||
|
||||
static BOOL CDECL nodrv_CreateWindow( HWND hwnd );
|
||||
|
||||
static BOOL load_desktop_driver( HWND hwnd )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
HKEY hkey;
|
||||
DWORD size;
|
||||
WCHAR path[MAX_PATH];
|
||||
WCHAR key[ARRAY_SIZE(L"System\\CurrentControlSet\\Control\\Video\\{}\\0000") + 40];
|
||||
UINT guid_atom;
|
||||
|
||||
USER_CheckNotLock();
|
||||
|
||||
strcpy( driver_load_error, "The explorer process failed to start." ); /* default error */
|
||||
wait_graphics_driver_ready();
|
||||
|
||||
guid_atom = HandleToULong( GetPropW( hwnd, L"__wine_display_device_guid" ));
|
||||
lstrcpyW( key, L"System\\CurrentControlSet\\Control\\Video\\{" );
|
||||
if (!GlobalGetAtomNameW( guid_atom, key + lstrlenW(key), 40 )) return 0;
|
||||
lstrcatW( key, L"}\\0000" );
|
||||
if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
|
||||
size = sizeof(path);
|
||||
if (!RegQueryValueExW( hkey, L"GraphicsDriver", NULL, NULL, (BYTE *)path, &size ))
|
||||
{
|
||||
if (wcscmp( path, L"null" ))
|
||||
{
|
||||
ret = LoadLibraryW( path ) != NULL;
|
||||
if (!ret) ERR( "failed to load %s\n", debugstr_w(path) );
|
||||
}
|
||||
else
|
||||
{
|
||||
__wine_set_user_driver( &null_driver, WINE_GDI_DRIVER_VERSION );
|
||||
ret = TRUE;
|
||||
}
|
||||
TRACE( "%s\n", debugstr_w(path) );
|
||||
}
|
||||
else
|
||||
{
|
||||
size = sizeof(driver_load_error);
|
||||
RegQueryValueExA( hkey, "DriverError", NULL, NULL, (BYTE *)driver_load_error, &size );
|
||||
}
|
||||
RegCloseKey( hkey );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* load the graphics driver */
|
||||
static const struct user_driver_funcs *load_driver(void)
|
||||
{
|
||||
struct user_driver_funcs driver;
|
||||
USEROBJECTFLAGS flags;
|
||||
HWINSTA winstation;
|
||||
|
||||
if (!load_desktop_driver( GetDesktopWindow() ) || USER_Driver == &lazy_load_driver)
|
||||
wait_graphics_driver_ready();
|
||||
if (USER_Driver == &lazy_load_driver)
|
||||
{
|
||||
memset( &driver, 0, sizeof(driver) );
|
||||
winstation = NtUserGetProcessWindowStation();
|
||||
if (!NtUserGetObjectInformation( winstation, UOI_FLAGS, &flags, sizeof(flags), NULL )
|
||||
|| (flags.dwFlags & WSF_VISIBLE))
|
||||
driver.pCreateWindow = nodrv_CreateWindow;
|
||||
|
||||
__wine_set_user_driver( &driver, WINE_GDI_DRIVER_VERSION );
|
||||
static struct user_driver_funcs empty_funcs;
|
||||
WARN( "failed to load the display driver, falling back to null driver\n" );
|
||||
__wine_set_user_driver( &empty_funcs, WINE_GDI_DRIVER_VERSION );
|
||||
}
|
||||
|
||||
return USER_Driver;
|
||||
|
@ -128,25 +74,6 @@ static void CDECL nulldrv_UpdateClipboard(void)
|
|||
{
|
||||
}
|
||||
|
||||
static BOOL CDECL nodrv_CreateWindow( HWND hwnd )
|
||||
{
|
||||
static int warned;
|
||||
HWND parent = NtUserGetAncestor( hwnd, GA_PARENT );
|
||||
|
||||
/* HWND_MESSAGE windows don't need a graphics driver */
|
||||
if (!parent || parent == get_user_thread_info()->msg_window) return TRUE;
|
||||
if (warned++) return FALSE;
|
||||
|
||||
ERR_(winediag)( "Application tried to create a window, but no driver could be loaded.\n" );
|
||||
if (driver_load_error[0]) ERR_(winediag)( "%s\n", driver_load_error );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL CDECL nulldrv_CreateDesktopWindow( HWND hwnd )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CDECL nulldrv_CreateWindow( HWND hwnd )
|
||||
{
|
||||
return TRUE;
|
||||
|
@ -253,11 +180,6 @@ static void CDECL loaderdrv_UpdateClipboard(void)
|
|||
load_driver()->pUpdateClipboard();
|
||||
}
|
||||
|
||||
static BOOL CDECL loaderdrv_CreateDesktopWindow( HWND hwnd )
|
||||
{
|
||||
return load_driver()->pCreateDesktopWindow( hwnd );
|
||||
}
|
||||
|
||||
static BOOL CDECL loaderdrv_CreateWindow( HWND hwnd )
|
||||
{
|
||||
return load_driver()->pCreateWindow( hwnd );
|
||||
|
@ -311,7 +233,7 @@ static struct user_driver_funcs lazy_load_driver =
|
|||
NULL,
|
||||
NULL,
|
||||
/* windowing functions */
|
||||
loaderdrv_CreateDesktopWindow,
|
||||
NULL,
|
||||
loaderdrv_CreateWindow,
|
||||
nulldrv_DestroyWindow,
|
||||
NULL,
|
||||
|
@ -361,7 +283,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v
|
|||
|
||||
SET_USER_FUNC(SetCursorPos);
|
||||
SET_USER_FUNC(UpdateClipboard);
|
||||
SET_USER_FUNC(CreateDesktopWindow);
|
||||
SET_USER_FUNC(CreateWindow);
|
||||
SET_USER_FUNC(DestroyWindow);
|
||||
SET_USER_FUNC(GetDC);
|
||||
|
|
|
@ -144,6 +144,7 @@ static const struct user_callbacks user_funcs =
|
|||
WindowFromDC,
|
||||
free_dce,
|
||||
MSG_SendInternalMessageTimeout,
|
||||
(void *)__wine_set_user_driver,
|
||||
};
|
||||
|
||||
static void WINAPI User32CallFreeIcon( ULONG *param, ULONG size )
|
||||
|
@ -151,11 +152,17 @@ static void WINAPI User32CallFreeIcon( ULONG *param, ULONG size )
|
|||
wow_handlers.free_icon_param( *param );
|
||||
}
|
||||
|
||||
static BOOL WINAPI User32LoadDriver( const WCHAR *path, ULONG size )
|
||||
{
|
||||
return LoadLibraryW( path ) != NULL;
|
||||
}
|
||||
|
||||
static const void *kernel_callback_table[NtUserCallCount] =
|
||||
{
|
||||
User32CallEnumDisplayMonitor,
|
||||
User32CallWinEventHook,
|
||||
User32CallWindowsHook,
|
||||
User32LoadDriver,
|
||||
User32CallFreeIcon,
|
||||
};
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name,
|
|||
{
|
||||
if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
|
||||
else assert( full_parent == thread_info->top_window );
|
||||
if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
|
||||
if (full_parent && !NtUserCallHwnd( thread_info->top_window, NtUserCreateDesktopWindow ))
|
||||
ERR( "failed to create desktop window\n" );
|
||||
register_builtin_classes();
|
||||
}
|
||||
|
@ -2098,7 +2098,7 @@ HWND WINAPI GetDesktopWindow(void)
|
|||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
|
||||
if (!thread_info->top_window || !NtUserCallHwnd( thread_info->top_window, NtUserCreateDesktopWindow ))
|
||||
ERR( "failed to create desktop window\n" );
|
||||
|
||||
register_builtin_classes();
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(driver);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
|
||||
struct d3dkmt_adapter
|
||||
{
|
||||
|
@ -49,30 +50,13 @@ struct d3dkmt_device
|
|||
};
|
||||
|
||||
static const struct user_driver_funcs lazy_load_driver;
|
||||
static struct user_driver_funcs null_user_driver;
|
||||
|
||||
static struct list d3dkmt_adapters = LIST_INIT( d3dkmt_adapters );
|
||||
static struct list d3dkmt_devices = LIST_INIT( d3dkmt_devices );
|
||||
|
||||
static pthread_mutex_t driver_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/**********************************************************************
|
||||
* get_display_driver
|
||||
*
|
||||
* Special case for loading the display driver: get the name from the config file
|
||||
*/
|
||||
const struct gdi_dc_funcs *get_display_driver(void)
|
||||
{
|
||||
if (user_driver == &lazy_load_driver)
|
||||
{
|
||||
if (!get_desktop_window() || user_driver == &lazy_load_driver)
|
||||
{
|
||||
static struct user_driver_funcs empty_funcs;
|
||||
WARN( "failed to load the display driver, falling back to null driver\n" );
|
||||
__wine_set_display_driver( &empty_funcs, WINE_GDI_DRIVER_VERSION );
|
||||
}
|
||||
}
|
||||
return &user_driver->dc_funcs;
|
||||
}
|
||||
static WCHAR driver_load_error[80];
|
||||
|
||||
static INT CDECL nulldrv_AbortDoc( PHYSDEV dev )
|
||||
{
|
||||
|
@ -767,6 +751,20 @@ static BOOL CDECL nulldrv_CreateDesktopWindow( HWND hwnd )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CDECL nodrv_CreateWindow( HWND hwnd )
|
||||
{
|
||||
static int warned;
|
||||
HWND parent = NtUserGetAncestor( hwnd, GA_PARENT );
|
||||
|
||||
/* HWND_MESSAGE windows don't need a graphics driver */
|
||||
if (!parent || parent == get_user_thread_info()->msg_window) return TRUE;
|
||||
if (warned++) return FALSE;
|
||||
|
||||
ERR_(winediag)( "Application tried to create a window, but no driver could be loaded.\n" );
|
||||
if (driver_load_error[0]) ERR_(winediag)( "%s\n", debugstr_w(driver_load_error) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL CDECL nulldrv_CreateWindow( HWND hwnd )
|
||||
{
|
||||
return TRUE;
|
||||
|
@ -930,6 +928,83 @@ static void CDECL nulldrv_ThreadDetach( void )
|
|||
{
|
||||
}
|
||||
|
||||
static BOOL setup_null_driver(void)
|
||||
{
|
||||
if (user_callbacks)
|
||||
user_callbacks->set_user_driver( &null_user_driver, WINE_GDI_DRIVER_VERSION );
|
||||
else
|
||||
__wine_set_display_driver( &null_user_driver, WINE_GDI_DRIVER_VERSION );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const WCHAR guid_key_prefixW[] =
|
||||
{
|
||||
'\\','R','e','g','i','s','t','r','y',
|
||||
'\\','M','a','c','h','i','n','e',
|
||||
'\\','S','y','s','t','e','m',
|
||||
'\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
|
||||
'\\','C','o','n','t','r','o','l',
|
||||
'\\','V','i','d','e','o','\\','{'
|
||||
};
|
||||
static const WCHAR guid_key_suffixW[] = {'}','\\','0','0','0','0'};
|
||||
|
||||
static BOOL load_desktop_driver( HWND hwnd )
|
||||
{
|
||||
WCHAR key[ARRAYSIZE(guid_key_prefixW) + 40 + ARRAYSIZE(guid_key_suffixW)], *ptr;
|
||||
char buf[4096];
|
||||
KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
|
||||
ATOM_BASIC_INFORMATION *abi = (ATOM_BASIC_INFORMATION *)buf;
|
||||
BOOL ret = FALSE;
|
||||
HKEY hkey;
|
||||
DWORD size;
|
||||
UINT guid_atom;
|
||||
|
||||
static const WCHAR prop_nameW[] =
|
||||
{'_','_','w','i','n','e','_','d','i','s','p','l','a','y','_','d','e','v','i','c','e',
|
||||
'_','g','u','i','d',0};
|
||||
|
||||
user_check_not_lock();
|
||||
|
||||
asciiz_to_unicode( driver_load_error, "The explorer process failed to start." ); /* default error */
|
||||
/* wait for graphics driver to be ready */
|
||||
send_message( hwnd, WM_NULL, 0, 0 );
|
||||
|
||||
guid_atom = HandleToULong( NtUserGetProp( hwnd, prop_nameW ));
|
||||
memcpy( key, guid_key_prefixW, sizeof(guid_key_prefixW) );
|
||||
ptr = key + ARRAYSIZE(guid_key_prefixW);
|
||||
if (NtQueryInformationAtom( guid_atom, AtomBasicInformation, buf, sizeof(buf), NULL ))
|
||||
return FALSE;
|
||||
memcpy( ptr, abi->Name, abi->NameLength );
|
||||
ptr += abi->NameLength / sizeof(WCHAR);
|
||||
memcpy( ptr, guid_key_suffixW, sizeof(guid_key_suffixW) );
|
||||
ptr += ARRAY_SIZE(guid_key_suffixW);
|
||||
|
||||
if (!(hkey = reg_open_key( NULL, key, (ptr - key) * sizeof(WCHAR) ))) return FALSE;
|
||||
|
||||
if ((size = query_reg_ascii_value( hkey, "GraphicsDriver", info, sizeof(buf) )))
|
||||
{
|
||||
static const WCHAR nullW[] = {'n','u','l','l',0};
|
||||
TRACE( "trying driver %s\n", debugstr_wn( (const WCHAR *)info->Data,
|
||||
info->DataLength / sizeof(WCHAR) ));
|
||||
if (info->DataLength != sizeof(nullW) || memcmp( info->Data, nullW, sizeof(nullW) ))
|
||||
{
|
||||
void *ret_ptr;
|
||||
ULONG ret_len;
|
||||
ret = KeUserModeCallback( NtUserLoadDriver, info->Data, info->DataLength,
|
||||
&ret_ptr, &ret_len );
|
||||
}
|
||||
else ret = setup_null_driver();
|
||||
}
|
||||
else if ((size = query_reg_ascii_value( hkey, "DriverError", info, sizeof(buf) )))
|
||||
{
|
||||
memcpy( driver_load_error, info->Data, min( info->DataLength, sizeof(driver_load_error) ));
|
||||
driver_load_error[ARRAYSIZE(driver_load_error) - 1] = 0;
|
||||
}
|
||||
|
||||
NtClose( hkey );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Lazy loading user driver
|
||||
*
|
||||
|
@ -939,10 +1014,31 @@ static void CDECL nulldrv_ThreadDetach( void )
|
|||
|
||||
static const struct user_driver_funcs *load_driver(void)
|
||||
{
|
||||
get_display_driver();
|
||||
USEROBJECTFLAGS flags;
|
||||
HWINSTA winstation;
|
||||
|
||||
if (!load_desktop_driver( get_desktop_window() ) || user_driver == &lazy_load_driver)
|
||||
{
|
||||
winstation = NtUserGetProcessWindowStation();
|
||||
if (!NtUserGetObjectInformation( winstation, UOI_FLAGS, &flags, sizeof(flags), NULL )
|
||||
|| (flags.dwFlags & WSF_VISIBLE))
|
||||
null_user_driver.pCreateWindow = nodrv_CreateWindow;
|
||||
|
||||
setup_null_driver();
|
||||
}
|
||||
|
||||
return user_driver;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* get_display_driver
|
||||
*/
|
||||
const struct gdi_dc_funcs *get_display_driver(void)
|
||||
{
|
||||
if (user_driver == &lazy_load_driver) load_driver();
|
||||
return &user_driver->dc_funcs;
|
||||
}
|
||||
|
||||
static BOOL CDECL loaderdrv_ActivateKeyboardLayout( HKL layout, UINT flags )
|
||||
{
|
||||
return load_driver()->pActivateKeyboardLayout( layout, flags );
|
||||
|
@ -1031,6 +1127,11 @@ static void CDECL loaderdrv_UpdateDisplayDevices( const struct gdi_device_manage
|
|||
load_driver()->pUpdateDisplayDevices( manager, force, param );
|
||||
}
|
||||
|
||||
static BOOL CDECL loaderdrv_CreateDesktopWindow( HWND hwnd )
|
||||
{
|
||||
return load_driver()->pCreateDesktopWindow( hwnd );
|
||||
}
|
||||
|
||||
static void CDECL loaderdrv_FlashWindowEx( FLASHWINFO *info )
|
||||
{
|
||||
load_driver()->pFlashWindowEx( info );
|
||||
|
@ -1066,6 +1167,7 @@ static const struct user_driver_funcs lazy_load_driver =
|
|||
.pEnumDisplaySettingsEx = loaderdrv_EnumDisplaySettingsEx,
|
||||
.pUpdateDisplayDevices = loaderdrv_UpdateDisplayDevices,
|
||||
/* windowing functions */
|
||||
.pCreateDesktopWindow = loaderdrv_CreateDesktopWindow,
|
||||
.pFlashWindowEx = loaderdrv_FlashWindowEx,
|
||||
.pMsgWaitForMultipleObjectsEx = nulldrv_MsgWaitForMultipleObjectsEx,
|
||||
.pScrollDC = nulldrv_ScrollDC,
|
||||
|
|
|
@ -38,6 +38,7 @@ struct user_callbacks
|
|||
HWND (WINAPI *pWindowFromDC)( HDC );
|
||||
void (WINAPI *free_dce)( struct dce *dce, HWND hwnd );
|
||||
LRESULT (WINAPI *send_ll_message)( DWORD, DWORD, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
|
||||
void (CDECL *set_user_driver)( void *, UINT );
|
||||
};
|
||||
|
||||
struct user_object
|
||||
|
|
|
@ -4537,6 +4537,8 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code )
|
|||
{
|
||||
switch(code)
|
||||
{
|
||||
case NtUserGetDesktopWindow:
|
||||
return HandleToUlong( get_desktop_window() );
|
||||
case NtUserGetInputState:
|
||||
return get_input_state();
|
||||
/* temporary exports */
|
||||
|
|
|
@ -1067,6 +1067,9 @@ DWORD WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
|
|||
return is_window( hwnd );
|
||||
case NtUserIsWindowVisible:
|
||||
return is_window_visible( hwnd );
|
||||
/* temporary exports */
|
||||
case NtUserCreateDesktopWindow:
|
||||
return user_driver->pCreateDesktopWindow( hwnd );
|
||||
default:
|
||||
FIXME( "invalid code %u\n", code );
|
||||
return 0;
|
||||
|
|
|
@ -30,6 +30,7 @@ enum
|
|||
NtUserCallEnumDisplayMonitor,
|
||||
NtUserCallWinEventHook,
|
||||
NtUserCallWindowsHook,
|
||||
NtUserLoadDriver,
|
||||
/* win16 hooks */
|
||||
NtUserCallFreeIcon,
|
||||
/* Vulkan support */
|
||||
|
@ -86,6 +87,7 @@ struct win_hook_params
|
|||
/* NtUserCallNoParam codes, not compatible with Windows */
|
||||
enum
|
||||
{
|
||||
NtUserGetDesktopWindow,
|
||||
NtUserGetInputState,
|
||||
/* temporary exports */
|
||||
NtUserThreadDetach,
|
||||
|
@ -143,6 +145,8 @@ enum
|
|||
NtUserGetWindowTextLength,
|
||||
NtUserIsWindow,
|
||||
NtUserIsWindowVisible,
|
||||
/* temporary exports */
|
||||
NtUserCreateDesktopWindow,
|
||||
};
|
||||
|
||||
/* NtUserCallHwndParam codes, not compatible with Windows */
|
||||
|
|
Loading…
Reference in New Issue