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
30 #include "wine/debug.h"
31 #include "wine/gdi_driver.h"
33 #include "user_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(user
);
37 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
39 static USER_DRIVER null_driver
, lazy_load_driver
;
41 const USER_DRIVER
*USER_Driver
= &lazy_load_driver
;
42 static char driver_load_error
[80];
44 static BOOL CDECL
nodrv_CreateWindow( HWND hwnd
);
46 static BOOL
load_desktop_driver( HWND hwnd
, HMODULE
*module
)
52 WCHAR key
[ARRAY_SIZE(L
"System\\CurrentControlSet\\Control\\Video\\{}\\0000") + 40];
57 strcpy( driver_load_error
, "The explorer process failed to start." ); /* default error */
58 wait_graphics_driver_ready();
60 guid_atom
= HandleToULong( GetPropW( hwnd
, L
"__wine_display_device_guid" ));
61 lstrcpyW( key
, L
"System\\CurrentControlSet\\Control\\Video\\{" );
62 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
63 lstrcatW( key
, L
"}\\0000" );
64 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
66 if (!RegQueryValueExW( hkey
, L
"GraphicsDriver", NULL
, NULL
, (BYTE
*)path
, &size
))
68 if ((ret
= !wcscmp( path
, L
"null" ))) *module
= NULL
;
69 else ret
= (*module
= LoadLibraryW( path
)) != NULL
;
70 if (!ret
) ERR( "failed to load %s\n", debugstr_w(path
) );
71 TRACE( "%s %p\n", debugstr_w(path
), *module
);
75 size
= sizeof(driver_load_error
);
77 RegQueryValueExA( hkey
, "DriverError", NULL
, NULL
, (BYTE
*)driver_load_error
, &size
);
83 /* load the graphics driver */
84 static const USER_DRIVER
*load_driver(void)
87 HMODULE graphics_driver
;
88 USER_DRIVER
*driver
, *prev
;
90 driver
= HeapAlloc( GetProcessHeap(), 0, sizeof(*driver
) );
91 *driver
= null_driver
;
93 if (!load_desktop_driver( GetDesktopWindow(), &graphics_driver
))
95 USEROBJECTFLAGS flags
;
98 winstation
= GetProcessWindowStation();
99 if (!GetUserObjectInformationA(winstation
, UOI_FLAGS
, &flags
, sizeof(flags
), NULL
)
100 || (flags
.dwFlags
& WSF_VISIBLE
))
101 driver
->pCreateWindow
= nodrv_CreateWindow
;
103 else if (graphics_driver
)
105 #define GET_USER_FUNC(name) \
106 do { if ((ptr = GetProcAddress( graphics_driver, #name ))) driver->p##name = ptr; } while(0)
108 GET_USER_FUNC(ActivateKeyboardLayout
);
110 GET_USER_FUNC(GetKeyNameText
);
111 GET_USER_FUNC(GetKeyboardLayoutList
);
112 GET_USER_FUNC(MapVirtualKeyEx
);
113 GET_USER_FUNC(RegisterHotKey
);
114 GET_USER_FUNC(ToUnicodeEx
);
115 GET_USER_FUNC(UnregisterHotKey
);
116 GET_USER_FUNC(VkKeyScanEx
);
117 GET_USER_FUNC(DestroyCursorIcon
);
118 GET_USER_FUNC(SetCursor
);
119 GET_USER_FUNC(GetCursorPos
);
120 GET_USER_FUNC(SetCursorPos
);
121 GET_USER_FUNC(ClipCursor
);
122 GET_USER_FUNC(UpdateClipboard
);
123 GET_USER_FUNC(ChangeDisplaySettingsEx
);
124 GET_USER_FUNC(EnumDisplayMonitors
);
125 GET_USER_FUNC(EnumDisplaySettingsEx
);
126 GET_USER_FUNC(GetMonitorInfo
);
127 GET_USER_FUNC(CreateDesktopWindow
);
128 GET_USER_FUNC(CreateWindow
);
129 GET_USER_FUNC(DestroyWindow
);
130 GET_USER_FUNC(FlashWindowEx
);
131 GET_USER_FUNC(GetDC
);
132 GET_USER_FUNC(MsgWaitForMultipleObjectsEx
);
133 GET_USER_FUNC(ReleaseDC
);
134 GET_USER_FUNC(ScrollDC
);
135 GET_USER_FUNC(SetCapture
);
136 GET_USER_FUNC(SetFocus
);
137 GET_USER_FUNC(SetLayeredWindowAttributes
);
138 GET_USER_FUNC(SetParent
);
139 GET_USER_FUNC(SetWindowRgn
);
140 GET_USER_FUNC(SetWindowIcon
);
141 GET_USER_FUNC(SetWindowStyle
);
142 GET_USER_FUNC(SetWindowText
);
143 GET_USER_FUNC(ShowWindow
);
144 GET_USER_FUNC(SysCommand
);
145 GET_USER_FUNC(UpdateLayeredWindow
);
146 GET_USER_FUNC(WindowMessage
);
147 GET_USER_FUNC(WindowPosChanging
);
148 GET_USER_FUNC(WindowPosChanged
);
149 GET_USER_FUNC(SystemParametersInfo
);
150 GET_USER_FUNC(ThreadDetach
);
154 prev
= InterlockedCompareExchangePointer( (void **)&USER_Driver
, driver
, &lazy_load_driver
);
155 if (prev
!= &lazy_load_driver
)
157 /* another thread beat us to it */
158 HeapFree( GetProcessHeap(), 0, driver
);
161 else LdrAddRefDll( 0, graphics_driver
);
163 __wine_set_display_driver( graphics_driver
);
164 register_builtin_classes();
169 /* unload the graphics driver on process exit */
170 void USER_unload_driver(void)
173 /* make sure we don't try to call the driver after it has been detached */
174 prev
= InterlockedExchangePointer( (void **)&USER_Driver
, &null_driver
);
175 if (prev
!= &lazy_load_driver
&& prev
!= &null_driver
)
176 HeapFree( GetProcessHeap(), 0, prev
);
180 /**********************************************************************
183 * These are fallbacks for entry points that are not implemented in the real driver.
186 static BOOL CDECL
nulldrv_ActivateKeyboardLayout( HKL layout
, UINT flags
)
191 static void CDECL
nulldrv_Beep(void)
195 static UINT CDECL
nulldrv_GetKeyboardLayoutList( INT size
, HKL
*layouts
)
197 return ~0; /* use default implementation */
200 static INT CDECL
nulldrv_GetKeyNameText( LONG lparam
, LPWSTR buffer
, INT size
)
202 return -1; /* use default implementation */
205 static UINT CDECL
nulldrv_MapVirtualKeyEx( UINT code
, UINT type
, HKL layout
)
207 return -1; /* use default implementation */
210 static BOOL CDECL
nulldrv_RegisterHotKey( HWND hwnd
, UINT modifiers
, UINT vk
)
215 static INT CDECL
nulldrv_ToUnicodeEx( UINT virt
, UINT scan
, const BYTE
*state
, LPWSTR str
,
216 int size
, UINT flags
, HKL layout
)
218 return -2; /* use default implementation */
221 static void CDECL
nulldrv_UnregisterHotKey( HWND hwnd
, UINT modifiers
, UINT vk
)
225 static SHORT CDECL
nulldrv_VkKeyScanEx( WCHAR ch
, HKL layout
)
227 return -256; /* use default implementation */
230 static void CDECL
nulldrv_DestroyCursorIcon( HCURSOR cursor
)
234 static void CDECL
nulldrv_SetCursor( HCURSOR cursor
)
238 static BOOL CDECL
nulldrv_GetCursorPos( LPPOINT pt
)
243 static BOOL CDECL
nulldrv_SetCursorPos( INT x
, INT y
)
248 static BOOL CDECL
nulldrv_ClipCursor( LPCRECT clip
)
253 static void CDECL
nulldrv_UpdateClipboard(void)
257 static LONG CDECL
nulldrv_ChangeDisplaySettingsEx( LPCWSTR name
, LPDEVMODEW mode
, HWND hwnd
,
258 DWORD flags
, LPVOID lparam
)
260 return DISP_CHANGE_FAILED
;
263 static BOOL CDECL
nulldrv_EnumDisplaySettingsEx( LPCWSTR name
, DWORD num
, LPDEVMODEW mode
, DWORD flags
)
268 static BOOL CDECL
nulldrv_CreateDesktopWindow( HWND hwnd
)
273 static BOOL CDECL
nodrv_CreateWindow( HWND hwnd
)
276 HWND parent
= GetAncestor( hwnd
, GA_PARENT
);
278 /* HWND_MESSAGE windows don't need a graphics driver */
279 if (!parent
|| parent
== get_user_thread_info()->msg_window
) return TRUE
;
280 if (warned
++) return FALSE
;
282 ERR_(winediag
)( "Application tried to create a window, but no driver could be loaded.\n" );
283 if (driver_load_error
[0]) ERR_(winediag
)( "%s\n", driver_load_error
);
287 static BOOL CDECL
nulldrv_CreateWindow( HWND hwnd
)
292 static void CDECL
nulldrv_DestroyWindow( HWND hwnd
)
296 static void CDECL
nulldrv_FlashWindowEx( FLASHWINFO
*info
)
300 static void CDECL
nulldrv_GetDC( HDC hdc
, HWND hwnd
, HWND top_win
, const RECT
*win_rect
,
301 const RECT
*top_rect
, DWORD flags
)
305 static DWORD CDECL
nulldrv_MsgWaitForMultipleObjectsEx( DWORD count
, const HANDLE
*handles
, DWORD timeout
,
306 DWORD mask
, DWORD flags
)
308 if (!count
&& !timeout
) return WAIT_TIMEOUT
;
309 return WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
310 timeout
, flags
& MWMO_ALERTABLE
);
313 static void CDECL
nulldrv_ReleaseDC( HWND hwnd
, HDC hdc
)
317 static BOOL CDECL
nulldrv_ScrollDC( HDC hdc
, INT dx
, INT dy
, HRGN update
)
321 GetClipBox( hdc
, &rect
);
322 return BitBlt( hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
323 hdc
, rect
.left
- dx
, rect
.top
- dy
, SRCCOPY
);
326 static void CDECL
nulldrv_SetCapture( HWND hwnd
, UINT flags
)
330 static void CDECL
nulldrv_SetFocus( HWND hwnd
)
334 static void CDECL
nulldrv_SetLayeredWindowAttributes( HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
338 static void CDECL
nulldrv_SetParent( HWND hwnd
, HWND parent
, HWND old_parent
)
342 static void CDECL
nulldrv_SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL redraw
)
346 static void CDECL
nulldrv_SetWindowIcon( HWND hwnd
, UINT type
, HICON icon
)
350 static void CDECL
nulldrv_SetWindowStyle( HWND hwnd
, INT offset
, STYLESTRUCT
*style
)
354 static void CDECL
nulldrv_SetWindowText( HWND hwnd
, LPCWSTR text
)
358 static UINT CDECL
nulldrv_ShowWindow( HWND hwnd
, INT cmd
, RECT
*rect
, UINT swp
)
360 return ~0; /* use default implementation */
363 static LRESULT CDECL
nulldrv_SysCommand( HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
368 static BOOL CDECL
nulldrv_UpdateLayeredWindow( HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
,
369 const RECT
*window_rect
)
374 static LRESULT CDECL
nulldrv_WindowMessage( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
379 static BOOL CDECL
nulldrv_WindowPosChanging( HWND hwnd
, HWND insert_after
, UINT swp_flags
,
380 const RECT
*window_rect
, const RECT
*client_rect
,
381 RECT
*visible_rect
, struct window_surface
**surface
)
386 static void CDECL
nulldrv_WindowPosChanged( HWND hwnd
, HWND insert_after
, UINT swp_flags
,
387 const RECT
*window_rect
, const RECT
*client_rect
,
388 const RECT
*visible_rect
, const RECT
*valid_rects
,
389 struct window_surface
*surface
)
393 static BOOL CDECL
nulldrv_SystemParametersInfo( UINT action
, UINT int_param
, void *ptr_param
, UINT flags
)
398 static void CDECL
nulldrv_ThreadDetach( void )
402 static USER_DRIVER null_driver
=
404 /* keyboard functions */
405 nulldrv_ActivateKeyboardLayout
,
407 nulldrv_GetKeyNameText
,
408 nulldrv_GetKeyboardLayoutList
,
409 nulldrv_MapVirtualKeyEx
,
410 nulldrv_RegisterHotKey
,
412 nulldrv_UnregisterHotKey
,
414 /* cursor/icon functions */
415 nulldrv_DestroyCursorIcon
,
417 nulldrv_GetCursorPos
,
418 nulldrv_SetCursorPos
,
420 /* clipboard functions */
421 nulldrv_UpdateClipboard
,
423 nulldrv_ChangeDisplaySettingsEx
,
424 nulldrv_EnumDisplayMonitors
,
425 nulldrv_EnumDisplaySettingsEx
,
426 nulldrv_GetMonitorInfo
,
427 /* windowing functions */
428 nulldrv_CreateDesktopWindow
,
429 nulldrv_CreateWindow
,
430 nulldrv_DestroyWindow
,
431 nulldrv_FlashWindowEx
,
433 nulldrv_MsgWaitForMultipleObjectsEx
,
438 nulldrv_SetLayeredWindowAttributes
,
440 nulldrv_SetWindowRgn
,
441 nulldrv_SetWindowIcon
,
442 nulldrv_SetWindowStyle
,
443 nulldrv_SetWindowText
,
446 nulldrv_UpdateLayeredWindow
,
447 nulldrv_WindowMessage
,
448 nulldrv_WindowPosChanging
,
449 nulldrv_WindowPosChanged
,
450 /* system parameters */
451 nulldrv_SystemParametersInfo
,
452 /* thread management */
457 /**********************************************************************
458 * Lazy loading user driver
460 * Initial driver used before another driver is loaded.
461 * Each entry point simply loads the real driver and chains to it.
464 static BOOL CDECL
loaderdrv_ActivateKeyboardLayout( HKL layout
, UINT flags
)
466 return load_driver()->pActivateKeyboardLayout( layout
, flags
);
469 static void CDECL
loaderdrv_Beep(void)
471 load_driver()->pBeep();
474 static INT CDECL
loaderdrv_GetKeyNameText( LONG lparam
, LPWSTR buffer
, INT size
)
476 return load_driver()->pGetKeyNameText( lparam
, buffer
, size
);
479 static UINT CDECL
loaderdrv_GetKeyboardLayoutList( INT size
, HKL
*layouts
)
481 return load_driver()->pGetKeyboardLayoutList( size
, layouts
);
484 static UINT CDECL
loaderdrv_MapVirtualKeyEx( UINT code
, UINT type
, HKL layout
)
486 return load_driver()->pMapVirtualKeyEx( code
, type
, layout
);
489 static BOOL CDECL
loaderdrv_RegisterHotKey( HWND hwnd
, UINT modifiers
, UINT vk
)
491 return load_driver()->pRegisterHotKey( hwnd
, modifiers
, vk
);
494 static INT CDECL
loaderdrv_ToUnicodeEx( UINT virt
, UINT scan
, const BYTE
*state
, LPWSTR str
,
495 int size
, UINT flags
, HKL layout
)
497 return load_driver()->pToUnicodeEx( virt
, scan
, state
, str
, size
, flags
, layout
);
500 static void CDECL
loaderdrv_UnregisterHotKey( HWND hwnd
, UINT modifiers
, UINT vk
)
502 load_driver()->pUnregisterHotKey( hwnd
, modifiers
, vk
);
505 static SHORT CDECL
loaderdrv_VkKeyScanEx( WCHAR ch
, HKL layout
)
507 return load_driver()->pVkKeyScanEx( ch
, layout
);
510 static void CDECL
loaderdrv_SetCursor( HCURSOR cursor
)
512 load_driver()->pSetCursor( cursor
);
515 static BOOL CDECL
loaderdrv_GetCursorPos( LPPOINT pt
)
517 return load_driver()->pGetCursorPos( pt
);
520 static BOOL CDECL
loaderdrv_SetCursorPos( INT x
, INT y
)
522 return load_driver()->pSetCursorPos( x
, y
);
525 static BOOL CDECL
loaderdrv_ClipCursor( LPCRECT clip
)
527 return load_driver()->pClipCursor( clip
);
530 static void CDECL
loaderdrv_UpdateClipboard(void)
532 load_driver()->pUpdateClipboard();
535 static LONG CDECL
loaderdrv_ChangeDisplaySettingsEx( LPCWSTR name
, LPDEVMODEW mode
, HWND hwnd
,
536 DWORD flags
, LPVOID lparam
)
538 return load_driver()->pChangeDisplaySettingsEx( name
, mode
, hwnd
, flags
, lparam
);
541 static BOOL CDECL
loaderdrv_EnumDisplayMonitors( HDC hdc
, LPRECT rect
, MONITORENUMPROC proc
, LPARAM lp
)
543 return load_driver()->pEnumDisplayMonitors( hdc
, rect
, proc
, lp
);
546 static BOOL CDECL
loaderdrv_EnumDisplaySettingsEx( LPCWSTR name
, DWORD num
, LPDEVMODEW mode
, DWORD flags
)
548 return load_driver()->pEnumDisplaySettingsEx( name
, num
, mode
, flags
);
551 static BOOL CDECL
loaderdrv_GetMonitorInfo( HMONITOR handle
, LPMONITORINFO info
)
553 return load_driver()->pGetMonitorInfo( handle
, info
);
556 static BOOL CDECL
loaderdrv_CreateDesktopWindow( HWND hwnd
)
558 return load_driver()->pCreateDesktopWindow( hwnd
);
561 static BOOL CDECL
loaderdrv_CreateWindow( HWND hwnd
)
563 return load_driver()->pCreateWindow( hwnd
);
566 static void CDECL
loaderdrv_FlashWindowEx( FLASHWINFO
*info
)
568 load_driver()->pFlashWindowEx( info
);
571 static void CDECL
loaderdrv_GetDC( HDC hdc
, HWND hwnd
, HWND top_win
, const RECT
*win_rect
,
572 const RECT
*top_rect
, DWORD flags
)
574 load_driver()->pGetDC( hdc
, hwnd
, top_win
, win_rect
, top_rect
, flags
);
577 static void CDECL
loaderdrv_SetLayeredWindowAttributes( HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
579 load_driver()->pSetLayeredWindowAttributes( hwnd
, key
, alpha
, flags
);
582 static void CDECL
loaderdrv_SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL redraw
)
584 load_driver()->pSetWindowRgn( hwnd
, hrgn
, redraw
);
587 static BOOL CDECL
loaderdrv_UpdateLayeredWindow( HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
,
588 const RECT
*window_rect
)
590 return load_driver()->pUpdateLayeredWindow( hwnd
, info
, window_rect
);
593 static USER_DRIVER lazy_load_driver
=
595 /* keyboard functions */
596 loaderdrv_ActivateKeyboardLayout
,
598 loaderdrv_GetKeyNameText
,
599 loaderdrv_GetKeyboardLayoutList
,
600 loaderdrv_MapVirtualKeyEx
,
601 loaderdrv_RegisterHotKey
,
602 loaderdrv_ToUnicodeEx
,
603 loaderdrv_UnregisterHotKey
,
604 loaderdrv_VkKeyScanEx
,
605 /* cursor/icon functions */
606 nulldrv_DestroyCursorIcon
,
608 loaderdrv_GetCursorPos
,
609 loaderdrv_SetCursorPos
,
610 loaderdrv_ClipCursor
,
611 /* clipboard functions */
612 loaderdrv_UpdateClipboard
,
614 loaderdrv_ChangeDisplaySettingsEx
,
615 loaderdrv_EnumDisplayMonitors
,
616 loaderdrv_EnumDisplaySettingsEx
,
617 loaderdrv_GetMonitorInfo
,
618 /* windowing functions */
619 loaderdrv_CreateDesktopWindow
,
620 loaderdrv_CreateWindow
,
621 nulldrv_DestroyWindow
,
622 loaderdrv_FlashWindowEx
,
624 nulldrv_MsgWaitForMultipleObjectsEx
,
629 loaderdrv_SetLayeredWindowAttributes
,
631 loaderdrv_SetWindowRgn
,
632 nulldrv_SetWindowIcon
,
633 nulldrv_SetWindowStyle
,
634 nulldrv_SetWindowText
,
637 loaderdrv_UpdateLayeredWindow
,
638 nulldrv_WindowMessage
,
639 nulldrv_WindowPosChanging
,
640 nulldrv_WindowPosChanged
,
641 /* system parameters */
642 nulldrv_SystemParametersInfo
,
643 /* thread management */