4 * Copyright 2000, 2005 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "user_private.h"
27 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(user
);
31 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
33 static struct user_driver_funcs null_driver
, lazy_load_driver
;
35 const struct user_driver_funcs
*USER_Driver
= &lazy_load_driver
;
36 static char driver_load_error
[80];
38 static BOOL CDECL
nodrv_CreateWindow( HWND hwnd
);
40 static BOOL
load_desktop_driver( HWND hwnd
)
46 WCHAR key
[ARRAY_SIZE(L
"System\\CurrentControlSet\\Control\\Video\\{}\\0000") + 40];
51 strcpy( driver_load_error
, "The explorer process failed to start." ); /* default error */
52 wait_graphics_driver_ready();
54 guid_atom
= HandleToULong( GetPropW( hwnd
, L
"__wine_display_device_guid" ));
55 lstrcpyW( key
, L
"System\\CurrentControlSet\\Control\\Video\\{" );
56 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
57 lstrcatW( key
, L
"}\\0000" );
58 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
60 if (!RegQueryValueExW( hkey
, L
"GraphicsDriver", NULL
, NULL
, (BYTE
*)path
, &size
))
62 if (wcscmp( path
, L
"null" ))
64 ret
= LoadLibraryW( path
) != NULL
;
65 if (!ret
) ERR( "failed to load %s\n", debugstr_w(path
) );
69 __wine_set_user_driver( &null_driver
, WINE_GDI_DRIVER_VERSION
);
72 TRACE( "%s\n", debugstr_w(path
) );
76 size
= sizeof(driver_load_error
);
77 RegQueryValueExA( hkey
, "DriverError", NULL
, NULL
, (BYTE
*)driver_load_error
, &size
);
83 /* load the graphics driver */
84 static const struct user_driver_funcs
*load_driver(void)
86 struct user_driver_funcs driver
;
87 USEROBJECTFLAGS flags
;
90 if (!load_desktop_driver( GetDesktopWindow() ) || USER_Driver
== &lazy_load_driver
)
92 memset( &driver
, 0, sizeof(driver
) );
93 winstation
= NtUserGetProcessWindowStation();
94 if (!NtUserGetObjectInformation( winstation
, UOI_FLAGS
, &flags
, sizeof(flags
), NULL
)
95 || (flags
.dwFlags
& WSF_VISIBLE
))
96 driver
.pCreateWindow
= nodrv_CreateWindow
;
98 __wine_set_user_driver( &driver
, WINE_GDI_DRIVER_VERSION
);
104 /* unload the graphics driver on process exit */
105 void USER_unload_driver(void)
107 struct user_driver_funcs
*prev
;
108 __wine_set_display_driver( &null_driver
, WINE_GDI_DRIVER_VERSION
);
109 /* make sure we don't try to call the driver after it has been detached */
110 prev
= InterlockedExchangePointer( (void **)&USER_Driver
, &null_driver
);
111 if (prev
!= &lazy_load_driver
&& prev
!= &null_driver
)
112 HeapFree( GetProcessHeap(), 0, prev
);
116 /**********************************************************************
119 * These are fallbacks for entry points that are not implemented in the real driver.
122 static void CDECL
nulldrv_Beep(void)
126 static BOOL CDECL
nulldrv_RegisterHotKey( HWND hwnd
, UINT modifiers
, UINT vk
)
131 static void CDECL
nulldrv_UnregisterHotKey( HWND hwnd
, UINT modifiers
, UINT vk
)
135 static void CDECL
nulldrv_DestroyCursorIcon( HCURSOR cursor
)
139 static void CDECL
nulldrv_SetCursor( HCURSOR cursor
)
143 static BOOL CDECL
nulldrv_GetCursorPos( LPPOINT pt
)
148 static BOOL CDECL
nulldrv_SetCursorPos( INT x
, INT y
)
153 static BOOL CDECL
nulldrv_ClipCursor( LPCRECT clip
)
158 static void CDECL
nulldrv_UpdateClipboard(void)
162 static BOOL CDECL
nodrv_CreateWindow( HWND hwnd
)
165 HWND parent
= GetAncestor( hwnd
, GA_PARENT
);
167 /* HWND_MESSAGE windows don't need a graphics driver */
168 if (!parent
|| parent
== get_user_thread_info()->msg_window
) return TRUE
;
169 if (warned
++) return FALSE
;
171 ERR_(winediag
)( "Application tried to create a window, but no driver could be loaded.\n" );
172 if (driver_load_error
[0]) ERR_(winediag
)( "%s\n", driver_load_error
);
176 static BOOL CDECL
nulldrv_CreateDesktopWindow( HWND hwnd
)
181 static BOOL CDECL
nulldrv_CreateWindow( HWND hwnd
)
186 static void CDECL
nulldrv_DestroyWindow( HWND hwnd
)
190 static void CDECL
nulldrv_FlashWindowEx( FLASHWINFO
*info
)
194 static void CDECL
nulldrv_GetDC( HDC hdc
, HWND hwnd
, HWND top_win
, const RECT
*win_rect
,
195 const RECT
*top_rect
, DWORD flags
)
199 static DWORD CDECL
nulldrv_MsgWaitForMultipleObjectsEx( DWORD count
, const HANDLE
*handles
, DWORD timeout
,
200 DWORD mask
, DWORD flags
)
202 if (!count
&& !timeout
) return WAIT_TIMEOUT
;
203 return WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
204 timeout
, flags
& MWMO_ALERTABLE
);
207 static void CDECL
nulldrv_ReleaseDC( HWND hwnd
, HDC hdc
)
211 static void CDECL
nulldrv_SetCapture( HWND hwnd
, UINT flags
)
215 static void CDECL
nulldrv_SetFocus( HWND hwnd
)
219 static void CDECL
nulldrv_SetLayeredWindowAttributes( HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
223 static void CDECL
nulldrv_SetParent( HWND hwnd
, HWND parent
, HWND old_parent
)
227 static void CDECL
nulldrv_SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL redraw
)
231 static void CDECL
nulldrv_SetWindowIcon( HWND hwnd
, UINT type
, HICON icon
)
235 static void CDECL
nulldrv_SetWindowStyle( HWND hwnd
, INT offset
, STYLESTRUCT
*style
)
239 static void CDECL
nulldrv_SetWindowText( HWND hwnd
, LPCWSTR text
)
243 static UINT CDECL
nulldrv_ShowWindow( HWND hwnd
, INT cmd
, RECT
*rect
, UINT swp
)
245 return ~0; /* use default implementation */
248 static LRESULT CDECL
nulldrv_SysCommand( HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
253 static BOOL CDECL
nulldrv_UpdateLayeredWindow( HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
,
254 const RECT
*window_rect
)
259 static LRESULT CDECL
nulldrv_WindowMessage( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
264 static BOOL CDECL
nulldrv_WindowPosChanging( HWND hwnd
, HWND insert_after
, UINT swp_flags
,
265 const RECT
*window_rect
, const RECT
*client_rect
,
266 RECT
*visible_rect
, struct window_surface
**surface
)
271 static void CDECL
nulldrv_WindowPosChanged( HWND hwnd
, HWND insert_after
, UINT swp_flags
,
272 const RECT
*window_rect
, const RECT
*client_rect
,
273 const RECT
*visible_rect
, const RECT
*valid_rects
,
274 struct window_surface
*surface
)
278 static void CDECL
nulldrv_ThreadDetach( void )
283 /**********************************************************************
284 * Lazy loading user driver
286 * Initial driver used before another driver is loaded.
287 * Each entry point simply loads the real driver and chains to it.
290 static void CDECL
loaderdrv_Beep(void)
292 load_driver()->pBeep();
295 static BOOL CDECL
loaderdrv_RegisterHotKey( HWND hwnd
, UINT modifiers
, UINT vk
)
297 return load_driver()->pRegisterHotKey( hwnd
, modifiers
, vk
);
300 static void CDECL
loaderdrv_UnregisterHotKey( HWND hwnd
, UINT modifiers
, UINT vk
)
302 load_driver()->pUnregisterHotKey( hwnd
, modifiers
, vk
);
305 static void CDECL
loaderdrv_SetCursor( HCURSOR cursor
)
307 load_driver()->pSetCursor( cursor
);
310 static BOOL CDECL
loaderdrv_GetCursorPos( LPPOINT pt
)
312 return load_driver()->pGetCursorPos( pt
);
315 static BOOL CDECL
loaderdrv_SetCursorPos( INT x
, INT y
)
317 return load_driver()->pSetCursorPos( x
, y
);
320 static BOOL CDECL
loaderdrv_ClipCursor( LPCRECT clip
)
322 return load_driver()->pClipCursor( clip
);
325 static void CDECL
loaderdrv_UpdateClipboard(void)
327 load_driver()->pUpdateClipboard();
330 static BOOL CDECL
loaderdrv_CreateDesktopWindow( HWND hwnd
)
332 return load_driver()->pCreateDesktopWindow( hwnd
);
335 static BOOL CDECL
loaderdrv_CreateWindow( HWND hwnd
)
337 return load_driver()->pCreateWindow( hwnd
);
340 static void CDECL
loaderdrv_FlashWindowEx( FLASHWINFO
*info
)
342 load_driver()->pFlashWindowEx( info
);
345 static void CDECL
loaderdrv_GetDC( HDC hdc
, HWND hwnd
, HWND top_win
, const RECT
*win_rect
,
346 const RECT
*top_rect
, DWORD flags
)
348 load_driver()->pGetDC( hdc
, hwnd
, top_win
, win_rect
, top_rect
, flags
);
351 static void CDECL
loaderdrv_SetLayeredWindowAttributes( HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
353 load_driver()->pSetLayeredWindowAttributes( hwnd
, key
, alpha
, flags
);
356 static void CDECL
loaderdrv_SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL redraw
)
358 load_driver()->pSetWindowRgn( hwnd
, hrgn
, redraw
);
361 static BOOL CDECL
loaderdrv_UpdateLayeredWindow( HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
,
362 const RECT
*window_rect
)
364 return load_driver()->pUpdateLayeredWindow( hwnd
, info
, window_rect
);
367 static struct user_driver_funcs lazy_load_driver
=
370 /* keyboard functions */
376 loaderdrv_RegisterHotKey
,
378 loaderdrv_UnregisterHotKey
,
380 /* cursor/icon functions */
381 nulldrv_DestroyCursorIcon
,
383 loaderdrv_GetCursorPos
,
384 loaderdrv_SetCursorPos
,
385 loaderdrv_ClipCursor
,
386 /* clipboard functions */
387 loaderdrv_UpdateClipboard
,
392 /* windowing functions */
393 loaderdrv_CreateDesktopWindow
,
394 loaderdrv_CreateWindow
,
395 nulldrv_DestroyWindow
,
396 loaderdrv_FlashWindowEx
,
398 nulldrv_MsgWaitForMultipleObjectsEx
,
403 loaderdrv_SetLayeredWindowAttributes
,
405 loaderdrv_SetWindowRgn
,
406 nulldrv_SetWindowIcon
,
407 nulldrv_SetWindowStyle
,
408 nulldrv_SetWindowText
,
411 loaderdrv_UpdateLayeredWindow
,
412 nulldrv_WindowMessage
,
413 nulldrv_WindowPosChanging
,
414 nulldrv_WindowPosChanged
,
415 /* system parameters */
419 /* thread management */
423 void CDECL
__wine_set_user_driver( const struct user_driver_funcs
*funcs
, UINT version
)
425 struct user_driver_funcs
*driver
, *prev
;
427 if (version
!= WINE_GDI_DRIVER_VERSION
)
429 ERR( "version mismatch, driver wants %u but user32 has %u\n", version
, WINE_GDI_DRIVER_VERSION
);
433 driver
= HeapAlloc( GetProcessHeap(), 0, sizeof(*driver
) );
436 #define SET_USER_FUNC(name) \
437 do { if (!driver->p##name) driver->p##name = nulldrv_##name; } while(0)
440 SET_USER_FUNC(RegisterHotKey
);
441 SET_USER_FUNC(UnregisterHotKey
);
442 SET_USER_FUNC(DestroyCursorIcon
);
443 SET_USER_FUNC(SetCursor
);
444 SET_USER_FUNC(GetCursorPos
);
445 SET_USER_FUNC(SetCursorPos
);
446 SET_USER_FUNC(ClipCursor
);
447 SET_USER_FUNC(UpdateClipboard
);
448 SET_USER_FUNC(CreateDesktopWindow
);
449 SET_USER_FUNC(CreateWindow
);
450 SET_USER_FUNC(DestroyWindow
);
451 SET_USER_FUNC(FlashWindowEx
);
452 SET_USER_FUNC(GetDC
);
453 SET_USER_FUNC(MsgWaitForMultipleObjectsEx
);
454 SET_USER_FUNC(ReleaseDC
);
455 SET_USER_FUNC(SetCapture
);
456 SET_USER_FUNC(SetFocus
);
457 SET_USER_FUNC(SetLayeredWindowAttributes
);
458 SET_USER_FUNC(SetParent
);
459 SET_USER_FUNC(SetWindowRgn
);
460 SET_USER_FUNC(SetWindowIcon
);
461 SET_USER_FUNC(SetWindowStyle
);
462 SET_USER_FUNC(SetWindowText
);
463 SET_USER_FUNC(ShowWindow
);
464 SET_USER_FUNC(SysCommand
);
465 SET_USER_FUNC(UpdateLayeredWindow
);
466 SET_USER_FUNC(WindowMessage
);
467 SET_USER_FUNC(WindowPosChanging
);
468 SET_USER_FUNC(WindowPosChanged
);
469 SET_USER_FUNC(ThreadDetach
);
472 prev
= InterlockedCompareExchangePointer( (void **)&USER_Driver
, driver
, &lazy_load_driver
);
473 if (prev
!= &lazy_load_driver
)
475 /* another thread beat us to it */
476 HeapFree( GetProcessHeap(), 0, driver
);
480 __wine_set_display_driver( driver
, version
);