kernelbase/tests: Fix the Sleep() test for non-default timer resolutions.
[wine.git] / dlls / user32 / driver.c
blob59a163c700dd16d024dbfb30332dd6dd43221290
1 /*
2 * USER driver support
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
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <wchar.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnls.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "wine/debug.h"
31 #include "wine/gdi_driver.h"
33 #include "user_private.h"
34 #include "controls.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 )
48 BOOL ret = FALSE;
49 HKEY hkey;
50 DWORD size;
51 WCHAR path[MAX_PATH];
52 WCHAR key[ARRAY_SIZE(L"System\\CurrentControlSet\\Control\\Video\\{}\\0000") + 40];
53 UINT guid_atom;
55 USER_CheckNotLock();
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;
65 size = sizeof(path);
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 );
73 else
75 size = sizeof(driver_load_error);
76 *module = NULL;
77 RegQueryValueExA( hkey, "DriverError", NULL, NULL, (BYTE *)driver_load_error, &size );
79 RegCloseKey( hkey );
80 return ret;
83 /* load the graphics driver */
84 static const USER_DRIVER *load_driver(void)
86 void *ptr;
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;
96 HWINSTA winstation;
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);
109 GET_USER_FUNC(Beep);
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);
151 #undef GET_USER_FUNC
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 );
159 driver = prev;
161 else LdrAddRefDll( 0, graphics_driver );
163 __wine_set_display_driver( graphics_driver );
164 register_builtin_classes();
166 return driver;
169 /* unload the graphics driver on process exit */
170 void USER_unload_driver(void)
172 USER_DRIVER *prev;
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 /**********************************************************************
181 * Null user driver
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 )
188 return TRUE;
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 )
212 return TRUE;
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 )
240 return TRUE;
243 static BOOL CDECL nulldrv_SetCursorPos( INT x, INT y )
245 return TRUE;
248 static BOOL CDECL nulldrv_ClipCursor( LPCRECT clip )
250 return TRUE;
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 )
265 return FALSE;
268 static BOOL CDECL nulldrv_CreateDesktopWindow( HWND hwnd )
270 return TRUE;
273 static BOOL CDECL nodrv_CreateWindow( HWND hwnd )
275 static int warned;
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 );
284 return FALSE;
287 static BOOL CDECL nulldrv_CreateWindow( HWND hwnd )
289 return TRUE;
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 )
319 RECT rect;
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 )
365 return -1;
368 static BOOL CDECL nulldrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
369 const RECT *window_rect )
371 return TRUE;
374 static LRESULT CDECL nulldrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
376 return 0;
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 )
383 return FALSE;
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 )
395 return FALSE;
398 static void CDECL nulldrv_ThreadDetach( void )
402 static USER_DRIVER null_driver =
404 /* keyboard functions */
405 nulldrv_ActivateKeyboardLayout,
406 nulldrv_Beep,
407 nulldrv_GetKeyNameText,
408 nulldrv_GetKeyboardLayoutList,
409 nulldrv_MapVirtualKeyEx,
410 nulldrv_RegisterHotKey,
411 nulldrv_ToUnicodeEx,
412 nulldrv_UnregisterHotKey,
413 nulldrv_VkKeyScanEx,
414 /* cursor/icon functions */
415 nulldrv_DestroyCursorIcon,
416 nulldrv_SetCursor,
417 nulldrv_GetCursorPos,
418 nulldrv_SetCursorPos,
419 nulldrv_ClipCursor,
420 /* clipboard functions */
421 nulldrv_UpdateClipboard,
422 /* display modes */
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,
432 nulldrv_GetDC,
433 nulldrv_MsgWaitForMultipleObjectsEx,
434 nulldrv_ReleaseDC,
435 nulldrv_ScrollDC,
436 nulldrv_SetCapture,
437 nulldrv_SetFocus,
438 nulldrv_SetLayeredWindowAttributes,
439 nulldrv_SetParent,
440 nulldrv_SetWindowRgn,
441 nulldrv_SetWindowIcon,
442 nulldrv_SetWindowStyle,
443 nulldrv_SetWindowText,
444 nulldrv_ShowWindow,
445 nulldrv_SysCommand,
446 nulldrv_UpdateLayeredWindow,
447 nulldrv_WindowMessage,
448 nulldrv_WindowPosChanging,
449 nulldrv_WindowPosChanged,
450 /* system parameters */
451 nulldrv_SystemParametersInfo,
452 /* thread management */
453 nulldrv_ThreadDetach
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,
597 loaderdrv_Beep,
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,
607 loaderdrv_SetCursor,
608 loaderdrv_GetCursorPos,
609 loaderdrv_SetCursorPos,
610 loaderdrv_ClipCursor,
611 /* clipboard functions */
612 loaderdrv_UpdateClipboard,
613 /* display modes */
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,
623 loaderdrv_GetDC,
624 nulldrv_MsgWaitForMultipleObjectsEx,
625 nulldrv_ReleaseDC,
626 nulldrv_ScrollDC,
627 nulldrv_SetCapture,
628 nulldrv_SetFocus,
629 loaderdrv_SetLayeredWindowAttributes,
630 nulldrv_SetParent,
631 loaderdrv_SetWindowRgn,
632 nulldrv_SetWindowIcon,
633 nulldrv_SetWindowStyle,
634 nulldrv_SetWindowText,
635 nulldrv_ShowWindow,
636 nulldrv_SysCommand,
637 loaderdrv_UpdateLayeredWindow,
638 nulldrv_WindowMessage,
639 nulldrv_WindowPosChanging,
640 nulldrv_WindowPosChanged,
641 /* system parameters */
642 nulldrv_SystemParametersInfo,
643 /* thread management */
644 nulldrv_ThreadDetach