user32/tests: Test what happens to a WM_QUIT posted to a window that gets destroyed.
[wine] / dlls / user32 / misc.c
1 /*
2  * Misc USER functions
3  *
4  * Copyright 1995 Thomas Sandford
5  * Copyright 1997 Marcus Meissner
6  * Copyright 1998 Turchanov Sergey
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "wine/windef16.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "winternl.h"
32 #include "user_private.h"
33
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(win);
38
39 /* USER signal proc flags and codes */
40 /* See UserSignalProc for comments */
41 #define USIG_FLAGS_WIN32          0x0001
42 #define USIG_FLAGS_GUI            0x0002
43 #define USIG_FLAGS_FEEDBACK       0x0004
44 #define USIG_FLAGS_FAULT          0x0008
45
46 #define USIG_DLL_UNLOAD_WIN16     0x0001
47 #define USIG_DLL_UNLOAD_WIN32     0x0002
48 #define USIG_FAULT_DIALOG_PUSH    0x0003
49 #define USIG_FAULT_DIALOG_POP     0x0004
50 #define USIG_DLL_UNLOAD_ORPHANS   0x0005
51 #define USIG_THREAD_INIT          0x0010
52 #define USIG_THREAD_EXIT          0x0020
53 #define USIG_PROCESS_CREATE       0x0100
54 #define USIG_PROCESS_INIT         0x0200
55 #define USIG_PROCESS_EXIT         0x0300
56 #define USIG_PROCESS_DESTROY      0x0400
57 #define USIG_PROCESS_RUNNING      0x0500
58 #define USIG_PROCESS_LOADED       0x0600
59
60 /***********************************************************************
61  *              SignalProc32 (USER.391)
62  *              UserSignalProc (USER32.@)
63  *
64  * The exact meaning of the USER signals is undocumented, but this
65  * should cover the basic idea:
66  *
67  * USIG_DLL_UNLOAD_WIN16
68  *     This is sent when a 16-bit module is unloaded.
69  *
70  * USIG_DLL_UNLOAD_WIN32
71  *     This is sent when a 32-bit module is unloaded.
72  *
73  * USIG_DLL_UNLOAD_ORPHANS
74  *     This is sent after the last Win3.1 module is unloaded,
75  *     to allow removal of orphaned menus.
76  *
77  * USIG_FAULT_DIALOG_PUSH
78  * USIG_FAULT_DIALOG_POP
79  *     These are called to allow USER to prepare for displaying a
80  *     fault dialog, even though the fault might have happened while
81  *     inside a USER critical section.
82  *
83  * USIG_THREAD_INIT
84  *     This is called from the context of a new thread, as soon as it
85  *     has started to run.
86  *
87  * USIG_THREAD_EXIT
88  *     This is called, still in its context, just before a thread is
89  *     about to terminate.
90  *
91  * USIG_PROCESS_CREATE
92  *     This is called, in the parent process context, after a new process
93  *     has been created.
94  *
95  * USIG_PROCESS_INIT
96  *     This is called in the new process context, just after the main thread
97  *     has started execution (after the main thread's USIG_THREAD_INIT has
98  *     been sent).
99  *
100  * USIG_PROCESS_LOADED
101  *     This is called after the executable file has been loaded into the
102  *     new process context.
103  *
104  * USIG_PROCESS_RUNNING
105  *     This is called immediately before the main entry point is called.
106  *
107  * USIG_PROCESS_EXIT
108  *     This is called in the context of a process that is about to
109  *     terminate (but before the last thread's USIG_THREAD_EXIT has
110  *     been sent).
111  *
112  * USIG_PROCESS_DESTROY
113  *     This is called after a process has terminated.
114  *
115  *
116  * The meaning of the dwFlags bits is as follows:
117  *
118  * USIG_FLAGS_WIN32
119  *     Current process is 32-bit.
120  *
121  * USIG_FLAGS_GUI
122  *     Current process is a (Win32) GUI process.
123  *
124  * USIG_FLAGS_FEEDBACK
125  *     Current process needs 'feedback' (determined from the STARTUPINFO
126  *     flags STARTF_FORCEONFEEDBACK / STARTF_FORCEOFFFEEDBACK).
127  *
128  * USIG_FLAGS_FAULT
129  *     The signal is being sent due to a fault.
130  */
131 WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
132                             DWORD dwFlags, HMODULE16 hModule )
133 {
134     FIXME("(%04x, %08x, %04x, %04x)\n",
135           uCode, dwThreadOrProcessID, dwFlags, hModule );
136     /* FIXME: Should chain to GdiSignalProc now. */
137     return 0;
138 }
139
140
141 /**********************************************************************
142  * SetLastErrorEx [USER32.@]
143  *
144  * Sets the last-error code.
145  *
146  * RETURNS
147  *    None.
148  */
149 void WINAPI SetLastErrorEx(
150     DWORD error, /* [in] Per-thread error code */
151     DWORD type)  /* [in] Error type */
152 {
153     TRACE("(0x%08x, 0x%08x)\n", error,type);
154     switch(type) {
155         case 0:
156             break;
157         case SLE_ERROR:
158         case SLE_MINORERROR:
159         case SLE_WARNING:
160             /* Fall through for now */
161         default:
162             FIXME("(error=%08x, type=%08x): Unhandled type\n", error,type);
163             break;
164     }
165     SetLastError( error );
166 }
167
168 /******************************************************************************
169  * GetAltTabInfoA [USER32.@]
170  */
171 BOOL WINAPI GetAltTabInfoA(HWND hwnd, int iItem, PALTTABINFO pati, LPSTR pszItemText, UINT cchItemText)
172 {
173     FIXME("(%p, 0x%08x, %p, %p, 0x%08x)\n", hwnd, iItem, pati, pszItemText, cchItemText);
174     return FALSE;
175 }
176
177 /******************************************************************************
178  * GetAltTabInfoW [USER32.@]
179  */
180 BOOL WINAPI GetAltTabInfoW(HWND hwnd, int iItem, PALTTABINFO pati, LPWSTR pszItemText, UINT cchItemText)
181 {
182     FIXME("(%p, 0x%08x, %p, %p, 0x%08x)\n", hwnd, iItem, pati, pszItemText, cchItemText);
183     return FALSE;
184 }
185
186 /******************************************************************************
187  * SetDebugErrorLevel [USER32.@]
188  * Sets the minimum error level for generating debugging events
189  *
190  * PARAMS
191  *    dwLevel [I] Debugging error level
192  *
193  * RETURNS
194  *    Nothing.
195  */
196 VOID WINAPI SetDebugErrorLevel( DWORD dwLevel )
197 {
198     FIXME("(%d): stub\n", dwLevel);
199 }
200
201
202 /***********************************************************************
203  *              SetWindowStationUser (USER32.@)
204  */
205 DWORD WINAPI SetWindowStationUser(DWORD x1,DWORD x2)
206 {
207     FIXME("(0x%08x,0x%08x),stub!\n",x1,x2);
208     return 1;
209 }
210
211 /***********************************************************************
212  *              RegisterLogonProcess (USER32.@)
213  */
214 DWORD WINAPI RegisterLogonProcess(HANDLE hprocess,BOOL x)
215 {
216     FIXME("(%p,%d),stub!\n",hprocess,x);
217     return 1;
218 }
219
220 /***********************************************************************
221  *              SetLogonNotifyWindow (USER32.@)
222  */
223 DWORD WINAPI SetLogonNotifyWindow(HWINSTA hwinsta,HWND hwnd)
224 {
225     FIXME("(%p,%p),stub!\n",hwinsta,hwnd);
226     return 1;
227 }
228
229 static const WCHAR primary_device_name[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','1',0};
230 static const WCHAR primary_device_string[] = {'X','1','1',' ','W','i','n','d','o','w','i','n','g',' ',
231                                               'S','y','s','t','e','m',0};
232 static const WCHAR primary_device_deviceid[] = {'P','C','I','\\','V','E','N','_','0','0','0','0','&',
233                                                 'D','E','V','_','0','0','0','0',0};
234
235 /***********************************************************************
236  *              EnumDisplayDevicesA (USER32.@)
237  */
238 BOOL WINAPI EnumDisplayDevicesA( LPCSTR lpDevice, DWORD i, LPDISPLAY_DEVICEA lpDispDev,
239                                  DWORD dwFlags )
240 {
241     UNICODE_STRING deviceW;
242     DISPLAY_DEVICEW ddW;
243     BOOL ret;
244
245     if(lpDevice)
246         RtlCreateUnicodeStringFromAsciiz(&deviceW, lpDevice); 
247     else
248         deviceW.Buffer = NULL;
249
250     ddW.cb = sizeof(ddW);
251     ret = EnumDisplayDevicesW(deviceW.Buffer, i, &ddW, dwFlags);
252     RtlFreeUnicodeString(&deviceW);
253
254     if(!ret) return ret;
255
256     WideCharToMultiByte(CP_ACP, 0, ddW.DeviceName, -1, lpDispDev->DeviceName, sizeof(lpDispDev->DeviceName), NULL, NULL);
257     WideCharToMultiByte(CP_ACP, 0, ddW.DeviceString, -1, lpDispDev->DeviceString, sizeof(lpDispDev->DeviceString), NULL, NULL);
258     lpDispDev->StateFlags = ddW.StateFlags;
259
260     if(lpDispDev->cb >= offsetof(DISPLAY_DEVICEA, DeviceID) + sizeof(lpDispDev->DeviceID))
261         WideCharToMultiByte(CP_ACP, 0, ddW.DeviceID, -1, lpDispDev->DeviceID, sizeof(lpDispDev->DeviceID), NULL, NULL);
262     if(lpDispDev->cb >= offsetof(DISPLAY_DEVICEA, DeviceKey) + sizeof(lpDispDev->DeviceKey))
263         WideCharToMultiByte(CP_ACP, 0, ddW.DeviceKey, -1, lpDispDev->DeviceKey, sizeof(lpDispDev->DeviceKey), NULL, NULL);
264
265     return TRUE;
266 }
267
268 /***********************************************************************
269  *              EnumDisplayDevicesW (USER32.@)
270  */
271 BOOL WINAPI EnumDisplayDevicesW( LPCWSTR lpDevice, DWORD i, LPDISPLAY_DEVICEW lpDisplayDevice,
272                                  DWORD dwFlags )
273 {
274     FIXME("(%s,%d,%p,0x%08x), stub!\n",debugstr_w(lpDevice),i,lpDisplayDevice,dwFlags);
275
276     if (i)
277         return FALSE;
278
279     memcpy(lpDisplayDevice->DeviceName, primary_device_name, sizeof(primary_device_name));
280     memcpy(lpDisplayDevice->DeviceString, primary_device_string, sizeof(primary_device_string));
281   
282     lpDisplayDevice->StateFlags =
283         DISPLAY_DEVICE_ATTACHED_TO_DESKTOP |
284         DISPLAY_DEVICE_PRIMARY_DEVICE |
285         DISPLAY_DEVICE_VGA_COMPATIBLE;
286
287     if(lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceID) + sizeof(lpDisplayDevice->DeviceID))
288         memcpy(lpDisplayDevice->DeviceID, primary_device_deviceid, sizeof(primary_device_deviceid));
289     if(lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceKey) + sizeof(lpDisplayDevice->DeviceKey))
290         lpDisplayDevice->DeviceKey[0] = 0;
291
292     return TRUE;
293 }
294
295 struct monitor_enum_info
296 {
297     RECT     rect;
298     UINT     max_area;
299     UINT     min_distance;
300     HMONITOR primary;
301     HMONITOR nearest;
302     HMONITOR ret;
303 };
304
305 /* helper callback for MonitorFromRect */
306 static BOOL CALLBACK monitor_enum( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp )
307 {
308     struct monitor_enum_info *info = (struct monitor_enum_info *)lp;
309     RECT intersect;
310
311     if (IntersectRect( &intersect, rect, &info->rect ))
312     {
313         /* check for larger intersecting area */
314         UINT area = (intersect.right - intersect.left) * (intersect.bottom - intersect.top);
315         if (area > info->max_area)
316         {
317             info->max_area = area;
318             info->ret = monitor;
319         }
320     }
321     else if (!info->max_area)  /* if not intersecting, check for min distance */
322     {
323         UINT distance;
324         INT x, y;
325
326         if (rect->left >= info->rect.right) x = info->rect.right - rect->left;
327         else x = rect->right - info->rect.left;
328         if (rect->top >= info->rect.bottom) y = info->rect.bottom - rect->top;
329         else y = rect->bottom - info->rect.top;
330         distance = x * x + y * y;
331         if (distance < info->min_distance)
332         {
333             info->min_distance = distance;
334             info->nearest = monitor;
335         }
336     }
337     if (!info->primary)
338     {
339         MONITORINFO mon_info;
340         mon_info.cbSize = sizeof(mon_info);
341         GetMonitorInfoW( monitor, &mon_info );
342         if (mon_info.dwFlags & MONITORINFOF_PRIMARY) info->primary = monitor;
343     }
344     return TRUE;
345 }
346
347 /***********************************************************************
348  *              MonitorFromRect (USER32.@)
349  */
350 HMONITOR WINAPI MonitorFromRect( LPRECT rect, DWORD flags )
351 {
352     struct monitor_enum_info info;
353
354     /* make sure the desktop window exists */
355     GetDesktopWindow();
356
357     info.rect         = *rect;
358     info.max_area     = 0;
359     info.min_distance = ~0u;
360     info.primary      = 0;
361     info.nearest      = 0;
362     info.ret          = 0;
363     if (!EnumDisplayMonitors( 0, NULL, monitor_enum, (LPARAM)&info )) return 0;
364     if (!info.ret)
365     {
366         if (flags & MONITOR_DEFAULTTOPRIMARY) info.ret = info.primary;
367         else if (flags & MONITOR_DEFAULTTONEAREST) info.ret = info.nearest;
368     }
369
370     TRACE( "%s flags %x returning %p\n", wine_dbgstr_rect(rect), flags, info.ret );
371     return info.ret;
372 }
373
374 /***********************************************************************
375  *              MonitorFromPoint (USER32.@)
376  */
377 HMONITOR WINAPI MonitorFromPoint( POINT pt, DWORD flags )
378 {
379     RECT rect;
380
381     SetRect( &rect, pt.x, pt.y, pt.x + 1, pt.y + 1 );
382     return MonitorFromRect( &rect, flags );
383 }
384
385 /***********************************************************************
386  *              MonitorFromWindow (USER32.@)
387  */
388 HMONITOR WINAPI MonitorFromWindow(HWND hWnd, DWORD dwFlags)
389 {
390     RECT rect;
391     WINDOWPLACEMENT wp;
392
393     TRACE("(%p, 0x%08x)\n", hWnd, dwFlags);
394
395     if (IsIconic(hWnd) && GetWindowPlacement(hWnd, &wp))
396         return MonitorFromRect( &wp.rcNormalPosition, dwFlags );
397
398     if (GetWindowRect( hWnd, &rect ))
399         return MonitorFromRect( &rect, dwFlags );
400
401     if (!(dwFlags & (MONITOR_DEFAULTTOPRIMARY|MONITOR_DEFAULTTONEAREST))) return 0;
402     /* retrieve the primary */
403     SetRect( &rect, 0, 0, 1, 1 );
404     return MonitorFromRect( &rect, dwFlags );
405 }
406
407 /***********************************************************************
408  *              GetMonitorInfoA (USER32.@)
409  */
410 BOOL WINAPI GetMonitorInfoA(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
411 {
412     MONITORINFOEXW miW;
413     MONITORINFOEXA *miA = (MONITORINFOEXA*)lpMonitorInfo;
414     BOOL ret;
415
416     miW.cbSize = sizeof(miW);
417
418     ret = GetMonitorInfoW(hMonitor, (MONITORINFO*)&miW);
419     if(!ret) return ret;
420
421     miA->rcMonitor = miW.rcMonitor;
422     miA->rcWork = miW.rcWork;
423     miA->dwFlags = miW.dwFlags;
424     if(miA->cbSize >= offsetof(MONITORINFOEXA, szDevice) + sizeof(miA->szDevice))
425         WideCharToMultiByte(CP_ACP, 0, miW.szDevice, -1, miA->szDevice, sizeof(miA->szDevice), NULL, NULL);
426     return ret;
427 }
428
429 /***********************************************************************
430  *              GetMonitorInfoW (USER32.@)
431  */
432 BOOL WINAPI GetMonitorInfoW(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
433 {
434     BOOL ret = USER_Driver->pGetMonitorInfo( hMonitor, lpMonitorInfo );
435     if (ret)
436         TRACE("flags %04x, monitor %s, work %s\n", lpMonitorInfo->dwFlags,
437               wine_dbgstr_rect(&lpMonitorInfo->rcMonitor),
438               wine_dbgstr_rect(&lpMonitorInfo->rcWork));
439     return ret;
440 }
441
442 /***********************************************************************
443  *              EnumDisplayMonitors (USER32.@)
444  */
445 BOOL WINAPI EnumDisplayMonitors( HDC hdc, LPRECT rect, MONITORENUMPROC proc, LPARAM lp )
446 {
447     return USER_Driver->pEnumDisplayMonitors( hdc, rect, proc, lp );
448 }
449
450 /***********************************************************************
451  *              RegisterSystemThread (USER32.@)
452  */
453 void WINAPI RegisterSystemThread(DWORD flags, DWORD reserved)
454 {
455     FIXME("(%08x, %08x)\n", flags, reserved);
456 }
457
458 /***********************************************************************
459  *           RegisterShellHookWindow                    [USER32.@]
460  */
461 BOOL WINAPI RegisterShellHookWindow ( HWND hWnd )
462 {
463     FIXME("(%p): stub\n", hWnd);
464     return 0;
465 }
466
467
468 /***********************************************************************
469  *           DeregisterShellHookWindow                  [USER32.@]
470  */
471 HRESULT WINAPI DeregisterShellHookWindow ( DWORD u )
472 {
473     FIXME("0x%08x stub\n",u);
474     return 0;
475
476 }
477
478
479 /***********************************************************************
480  *           RegisterTasklist                           [USER32.@]
481  */
482 DWORD WINAPI RegisterTasklist (DWORD x)
483 {
484     FIXME("0x%08x\n",x);
485     return TRUE;
486 }
487
488
489 /***********************************************************************
490  *              RegisterDeviceNotificationA (USER32.@)
491  *
492  * See RegisterDeviceNotificationW.
493  */
494 HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hnd, LPVOID notifyfilter, DWORD flags)
495 {
496     FIXME("(hwnd=%p, filter=%p,flags=0x%08x) returns a fake device notification handle!\n",
497           hnd,notifyfilter,flags );
498     return (HDEVNOTIFY) 0xcafecafe;
499 }
500
501 /***********************************************************************
502  *              RegisterDeviceNotificationW (USER32.@)
503  *
504  * Registers a window with the system so that it will receive
505  * notifications about a device.
506  *
507  * PARAMS
508  *     hRecepient           [I] Window or service status handle that
509  *                              will receive notifications.
510  *     pNotificationFilter  [I] DEV_BROADCAST_HDR followed by some
511  *                              type-specific data.
512  *     dwFlags              [I] See notes
513  *
514  * RETURNS
515  *
516  * A handle to the device notification.
517  *
518  * NOTES
519  *
520  * The dwFlags parameter can be one of two values:
521  *| DEVICE_NOTIFY_WINDOW_HANDLE  - hRecepient is a window handle
522  *| DEVICE_NOTIFY_SERVICE_HANDLE - hRecepient is a service status handle
523  */
524 HDEVNOTIFY WINAPI RegisterDeviceNotificationW(HANDLE hRecepient, LPVOID pNotificationFilter, DWORD dwFlags)
525 {
526     FIXME("(hwnd=%p, filter=%p,flags=0x%08x) returns a fake device notification handle!\n",
527           hRecepient,pNotificationFilter,dwFlags );
528     return (HDEVNOTIFY) 0xcafeaffe;
529 }
530
531 /***********************************************************************
532  *              UnregisterDeviceNotification (USER32.@)
533  *
534  */
535 BOOL  WINAPI UnregisterDeviceNotification(HDEVNOTIFY hnd)
536 {
537     FIXME("(handle=%p), STUB!\n", hnd);
538     return TRUE;
539 }
540
541 /***********************************************************************
542  *           GetAppCompatFlags   (USER32.@)
543  */
544 DWORD WINAPI GetAppCompatFlags( HTASK hTask )
545 {
546     FIXME("(%p) stub\n", hTask);
547     return 0;
548 }
549
550 /***********************************************************************
551  *           GetAppCompatFlags2   (USER32.@)
552  */
553 DWORD WINAPI GetAppCompatFlags2( HTASK hTask )
554 {
555     FIXME("(%p) stub\n", hTask);
556     return 0;
557 }
558
559
560 /***********************************************************************
561  *           AlignRects   (USER32.@)
562  */
563 BOOL WINAPI AlignRects(LPRECT rect, DWORD b, DWORD c, DWORD d)
564 {
565     FIXME("(%p, %d, %d, %d): stub\n", rect, b, c, d);
566     if (rect)
567         FIXME("rect: [[%d, %d], [%d, %d]]\n", rect->left, rect->top, rect->right, rect->bottom);
568     /* Calls OffsetRect */
569     return FALSE;
570 }
571
572
573 /***********************************************************************
574  *              LoadLocalFonts (USER32.@)
575  */
576 VOID WINAPI LoadLocalFonts(VOID)
577 {
578     /* are loaded. */
579     return;
580 }
581
582
583 /***********************************************************************
584  *              User32InitializeImmEntryTable
585  */
586 BOOL WINAPI User32InitializeImmEntryTable(LPVOID ptr)
587 {
588   FIXME("(%p): stub\n", ptr);
589   return TRUE;
590 }
591
592 /**********************************************************************
593  * WINNLSGetIMEHotkey [USER32.@]
594  *
595  */
596 UINT WINAPI WINNLSGetIMEHotkey(HWND hwnd)
597 {
598     FIXME("hwnd %p: stub!\n", hwnd);
599     return 0; /* unknown */
600 }
601
602 /**********************************************************************
603  * WINNLSEnableIME [USER32.@]
604  *
605  */
606 BOOL WINAPI WINNLSEnableIME(HWND hwnd, BOOL enable)
607 {
608     FIXME("hwnd %p enable %d: stub!\n", hwnd, enable);
609     return TRUE; /* success (?) */
610 }
611
612 /**********************************************************************
613  * WINNLSGetEnableStatus [USER32.@]
614  *
615  */
616 BOOL WINAPI WINNLSGetEnableStatus(HWND hwnd)
617 {
618     FIXME("hwnd %p: stub!\n", hwnd);
619     return TRUE; /* success (?) */
620 }
621
622 /**********************************************************************
623  * SendIMEMessageExA [USER32.@]
624  *
625  */
626 LRESULT WINAPI SendIMEMessageExA(HWND hwnd, LPARAM lparam)
627 {
628   FIXME("(%p,%lx): stub\n", hwnd, lparam);
629   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
630   return 0;
631 }
632
633 /**********************************************************************
634  * SendIMEMessageExW [USER32.@]
635  *
636  */
637 LRESULT WINAPI SendIMEMessageExW(HWND hwnd, LPARAM lparam)
638 {
639   FIXME("(%p,%lx): stub\n", hwnd, lparam);
640   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
641   return 0;
642 }
643
644 /**********************************************************************
645  * DisableProcessWindowsGhosting [USER32.@]
646  *
647  */
648 VOID WINAPI DisableProcessWindowsGhosting(VOID)
649 {
650   FIXME(": stub\n");
651   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
652   return;
653 }