Cosmetic fixes.
[wine/multimedia.git] / windows / win.c
blob79bc061fd18f558d2d901da5e35eaa4024a6c4b4
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "windef.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/server.h"
14 #include "wine/unicode.h"
15 #include "win.h"
16 #include "heap.h"
17 #include "user.h"
18 #include "dce.h"
19 #include "controls.h"
20 #include "cursoricon.h"
21 #include "hook.h"
22 #include "message.h"
23 #include "queue.h"
24 #include "task.h"
25 #include "winpos.h"
26 #include "winerror.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
31 DECLARE_DEBUG_CHANNEL(msg);
33 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
35 /**********************************************************************/
37 /* Desktop window */
38 static WND *pWndDesktop = NULL;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 static void *user_handles[NB_USER_HANDLES];
45 /* thread safeness */
46 extern SYSLEVEL USER_SysLevel; /* FIXME */
48 /***********************************************************************
49 * WIN_SuspendWndsLock
51 * Suspend the lock on WND structures.
52 * Returns the number of locks suspended
54 int WIN_SuspendWndsLock( void )
56 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
57 int count = isuspendedLocks;
59 while ( count-- > 0 )
60 _LeaveSysLevel( &USER_SysLevel );
62 return isuspendedLocks;
65 /***********************************************************************
66 * WIN_RestoreWndsLock
68 * Restore the suspended locks on WND structures
70 void WIN_RestoreWndsLock( int ipreviousLocks )
72 while ( ipreviousLocks-- > 0 )
73 _EnterSysLevel( &USER_SysLevel );
76 /***********************************************************************
77 * create_window_handle
79 * Create a window handle with the server.
81 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
83 BOOL res;
84 user_handle_t handle = 0;
85 WORD index;
86 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
88 if (!win) return NULL;
90 USER_Lock();
92 SERVER_START_REQ( create_window )
94 req->parent = parent;
95 req->owner = owner;
96 req->atom = atom;
97 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
99 SERVER_END_REQ;
101 if (!res)
103 USER_Unlock();
104 HeapFree( GetProcessHeap(), 0, win );
105 return NULL;
107 index = LOWORD(handle) - FIRST_USER_HANDLE;
108 assert( index < NB_USER_HANDLES );
109 user_handles[index] = win;
110 win->hwndSelf = handle;
111 win->dwMagic = WND_MAGIC;
112 win->irefCount = 1;
113 return win;
117 /***********************************************************************
118 * free_window_handle
120 * Free a window handle.
122 static WND *free_window_handle( HWND hwnd )
124 WND *ptr;
125 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
127 if (index >= NB_USER_HANDLES) return NULL;
128 USER_Lock();
129 if ((ptr = user_handles[index]))
131 SERVER_START_REQ( destroy_window )
133 req->handle = hwnd;
134 if (!SERVER_CALL_ERR())
135 user_handles[index] = NULL;
136 else
137 ptr = NULL;
139 SERVER_END_REQ;
141 USER_Unlock();
142 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
143 return ptr;
147 /*******************************************************************
148 * list_window_children
150 * Build an array of the children of a given window. The array must be
151 * freed with HeapFree. Returns NULL when no windows are found.
153 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
155 HWND *list = NULL;
157 SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
159 req->parent = hwnd;
160 req->atom = atom;
161 req->tid = (void *)tid;
162 if (!SERVER_CALL())
164 user_handle_t *data = server_data_ptr(req);
165 int i, count = server_data_size(req) / sizeof(*data);
166 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
168 for (i = 0; i < count; i++) list[i] = data[i];
169 list[i] = 0;
173 SERVER_END_VAR_REQ;
174 return list;
178 /*******************************************************************
179 * send_parent_notify
181 static void send_parent_notify( HWND hwnd, UINT msg )
183 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
184 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
185 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
186 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
190 /***********************************************************************
191 * WIN_GetPtr
193 * Return a pointer to the WND structure if local to the process,
194 * or WND_OTHER_PROCESS is handle may be valid in other process.
195 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
197 WND *WIN_GetPtr( HWND hwnd )
199 WND * ptr;
200 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
202 if (index >= NB_USER_HANDLES) return NULL;
204 USER_Lock();
205 if ((ptr = user_handles[index]))
207 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
208 return ptr;
209 ptr = NULL;
211 else ptr = WND_OTHER_PROCESS;
212 USER_Unlock();
213 return ptr;
217 /***********************************************************************
218 * WIN_IsCurrentProcess
220 * Check whether a given window belongs to the current process (and return the full handle).
222 HWND WIN_IsCurrentProcess( HWND hwnd )
224 WND *ptr;
225 HWND ret;
227 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
228 ret = ptr->hwndSelf;
229 WIN_ReleasePtr( ptr );
230 return ret;
234 /***********************************************************************
235 * WIN_IsCurrentThread
237 * Check whether a given window belongs to the current thread (and return the full handle).
239 HWND WIN_IsCurrentThread( HWND hwnd )
241 WND *ptr;
242 HWND ret = 0;
244 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
246 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
247 WIN_ReleasePtr( ptr );
249 return ret;
253 /***********************************************************************
254 * WIN_Handle32
256 * Convert a 16-bit window handle to a full 32-bit handle.
258 HWND WIN_Handle32( HWND16 hwnd16 )
260 WND *ptr;
261 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
263 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
264 /* do sign extension for -2 and -3 */
265 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
267 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
269 if (ptr != WND_OTHER_PROCESS)
271 hwnd = ptr->hwndSelf;
272 WIN_ReleasePtr( ptr );
274 else /* may belong to another process */
276 SERVER_START_REQ( get_window_info )
278 req->handle = hwnd;
279 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
281 SERVER_END_REQ;
283 return hwnd;
287 /***********************************************************************
288 * WIN_FindWndPtr
290 * Return a pointer to the WND structure corresponding to a HWND.
292 WND * WIN_FindWndPtr( HWND hwnd )
294 WND * ptr;
296 if (!hwnd) return NULL;
298 if ((ptr = WIN_GetPtr( hwnd )))
300 if (ptr != WND_OTHER_PROCESS)
302 /* increment destruction monitoring */
303 ptr->irefCount++;
304 return ptr;
306 if (IsWindow( hwnd )) /* check other processes */
308 ERR( "window %04x belongs to other process\n", hwnd );
309 /* DbgBreakPoint(); */
312 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
313 return NULL;
317 /***********************************************************************
318 * WIN_ReleaseWndPtr
320 * Release the pointer to the WND structure.
322 void WIN_ReleaseWndPtr(WND *wndPtr)
324 if(!wndPtr) return;
326 /* Decrement destruction monitoring value */
327 wndPtr->irefCount--;
328 /* Check if it's time to release the memory */
329 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
331 /* Release memory */
332 free_window_handle( wndPtr->hwndSelf );
334 else if(wndPtr->irefCount < 0)
336 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
337 ERR("forgot a Lock on %p somewhere\n",wndPtr);
339 /* unlock all WND structures for thread safeness */
340 USER_Unlock();
344 /***********************************************************************
345 * WIN_UnlinkWindow
347 * Remove a window from the siblings linked list.
349 void WIN_UnlinkWindow( HWND hwnd )
351 WIN_LinkWindow( hwnd, 0, 0 );
355 /***********************************************************************
356 * WIN_LinkWindow
358 * Insert a window into the siblings linked list.
359 * The window is inserted after the specified window, which can also
360 * be specified as HWND_TOP or HWND_BOTTOM.
361 * If parent is 0, window is unlinked from the tree.
363 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
365 WND *wndPtr = WIN_GetPtr( hwnd );
367 if (!wndPtr) return;
368 if (wndPtr == WND_OTHER_PROCESS)
370 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
371 return;
374 SERVER_START_REQ( link_window )
376 req->handle = hwnd;
377 req->parent = parent;
378 req->previous = hwndInsertAfter;
379 if (!SERVER_CALL())
381 if (req->full_parent && req->full_parent != wndPtr->parent)
383 wndPtr->owner = 0; /* reset owner when changing parent */
384 wndPtr->parent = req->full_parent;
389 SERVER_END_REQ;
390 WIN_ReleasePtr( wndPtr );
394 /***********************************************************************
395 * WIN_SetOwner
397 * Change the owner of a window.
399 void WIN_SetOwner( HWND hwnd, HWND owner )
401 WND *win = WIN_GetPtr( hwnd );
403 if (!win) return;
404 if (win == WND_OTHER_PROCESS)
406 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
407 return;
409 SERVER_START_REQ( set_window_owner )
411 req->handle = hwnd;
412 req->owner = owner;
413 if (!SERVER_CALL()) win->owner = req->full_owner;
415 SERVER_END_REQ;
416 WIN_ReleasePtr( win );
420 /***********************************************************************
421 * WIN_SetStyle
423 * Change the style of a window.
425 LONG WIN_SetStyle( HWND hwnd, LONG style )
427 BOOL ok;
428 LONG ret = 0;
429 WND *win = WIN_GetPtr( hwnd );
431 if (!win) return 0;
432 if (win == WND_OTHER_PROCESS)
434 if (IsWindow(hwnd))
435 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
436 return 0;
438 if (style == win->dwStyle)
440 WIN_ReleasePtr( win );
441 return style;
443 SERVER_START_REQ( set_window_info )
445 req->handle = hwnd;
446 req->flags = SET_WIN_STYLE;
447 req->style = style;
448 if ((ok = !SERVER_CALL()))
450 ret = req->old_style;
451 win->dwStyle = style;
454 SERVER_END_REQ;
455 WIN_ReleasePtr( win );
456 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
457 return ret;
461 /***********************************************************************
462 * WIN_SetExStyle
464 * Change the extended style of a window.
466 LONG WIN_SetExStyle( HWND hwnd, LONG style )
468 LONG ret = 0;
469 WND *win = WIN_GetPtr( hwnd );
471 if (!win) return 0;
472 if (win == WND_OTHER_PROCESS)
474 if (IsWindow(hwnd))
475 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
476 return 0;
478 if (style == win->dwExStyle)
480 WIN_ReleasePtr( win );
481 return style;
483 SERVER_START_REQ( set_window_info )
485 req->handle = hwnd;
486 req->flags = SET_WIN_EXSTYLE;
487 req->ex_style = style;
488 if (!SERVER_CALL())
490 ret = req->old_ex_style;
491 win->dwExStyle = style;
494 SERVER_END_REQ;
495 WIN_ReleasePtr( win );
496 return ret;
500 /***********************************************************************
501 * WIN_SetRectangles
503 * Set the window and client rectangles.
505 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
507 WND *win = WIN_GetPtr( hwnd );
508 BOOL ret;
510 if (!win) return;
511 if (win == WND_OTHER_PROCESS)
513 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
514 return;
516 SERVER_START_REQ( set_window_rectangles )
518 req->handle = hwnd;
519 req->window.left = rectWindow->left;
520 req->window.top = rectWindow->top;
521 req->window.right = rectWindow->right;
522 req->window.bottom = rectWindow->bottom;
523 req->client.left = rectClient->left;
524 req->client.top = rectClient->top;
525 req->client.right = rectClient->right;
526 req->client.bottom = rectClient->bottom;
527 ret = !SERVER_CALL();
529 SERVER_END_REQ;
530 if (ret)
532 win->rectWindow = *rectWindow;
533 win->rectClient = *rectClient;
535 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
536 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
537 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
539 WIN_ReleasePtr( win );
543 /***********************************************************************
544 * find_child_to_repaint
546 * Find a window that needs repaint among the children of the specified window.
548 static HWND find_child_to_repaint( HWND parent )
550 int i;
551 HWND ret = 0;
552 HWND *list;
554 if (!parent) parent = GetDesktopWindow();
555 if (!(list = list_window_children( parent, 0, 0 ))) return 0;
557 for (i = 0; list[i] && !ret; i++)
559 WND *win = WIN_GetPtr( list[i] );
560 if (!win) continue; /* ignore it */
561 if (win == WND_OTHER_PROCESS)
563 /* doesn't belong to this process, but check children */
564 ret = find_child_to_repaint( list[i] );
565 continue;
567 if (!(win->dwStyle & WS_VISIBLE))
569 WIN_ReleasePtr( win );
570 continue;
572 if ((win->tid != GetCurrentThreadId()) ||
573 (!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
575 /* does not need repaint, check children */
576 WIN_ReleasePtr( win );
577 ret = find_child_to_repaint( list[i] );
578 continue;
581 /* now we have something */
582 ret = list[i];
583 if (!(win->dwExStyle & WS_EX_TRANSPARENT))
585 /* not transparent, we can repaint it */
586 WIN_ReleasePtr( win );
587 break;
589 WIN_ReleasePtr( win );
591 /* transparent window, look for non-transparent sibling to paint first */
592 for (i++; list[i]; i++)
594 if (!(win = WIN_GetPtr( list[i] ))) continue;
595 if (win == WND_OTHER_PROCESS) continue;
596 if (!(win->dwStyle & WS_VISIBLE))
598 WIN_ReleasePtr( win );
599 continue;
601 if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
602 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
604 ret = list[i];
605 WIN_ReleasePtr( win );
606 break;
608 WIN_ReleasePtr( win );
611 HeapFree( GetProcessHeap(), 0, list );
612 return ret;
616 /***********************************************************************
617 * WIN_FindWinToRepaint
619 * Find a window that needs repaint.
621 HWND WIN_FindWinToRepaint( HWND hwnd )
623 /* Note: the desktop window never gets WM_PAINT messages
624 * The real reason why is because Windows DesktopWndProc
625 * does ValidateRgn inside WM_ERASEBKGND handler.
627 if (hwnd == GetDesktopWindow()) hwnd = 0;
629 if (hwnd)
631 /* check the window itself first */
632 WND *win = WIN_FindWndPtr( hwnd );
633 if (!win) return 0;
634 if ((win->dwStyle & WS_VISIBLE) &&
635 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
637 WIN_ReleaseWndPtr( win );
638 return hwnd;
640 WIN_ReleaseWndPtr( win );
642 /* now check its children */
643 return find_child_to_repaint( hwnd );
647 /***********************************************************************
648 * WIN_DestroyWindow
650 * Destroy storage associated to a window. "Internals" p.358
652 LRESULT WIN_DestroyWindow( HWND hwnd )
654 WND *wndPtr;
655 HWND *list;
657 TRACE("%04x\n", hwnd );
659 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
661 ERR( "window doesn't belong to current thread\n" );
662 return 0;
665 /* free child windows */
666 if ((list = WIN_ListChildren( hwnd )))
668 int i;
669 for (i = 0; list[i]; i++)
671 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
672 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
674 HeapFree( GetProcessHeap(), 0, list );
678 * Clear the update region to make sure no WM_PAINT messages will be
679 * generated for this window while processing the WM_NCDESTROY.
681 RedrawWindow( hwnd, NULL, 0,
682 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
685 * Send the WM_NCDESTROY to the window being destroyed.
687 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
689 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
691 WINPOS_CheckInternalPos( hwnd );
692 if( hwnd == GetCapture()) ReleaseCapture();
694 /* free resources associated with the window */
696 TIMER_RemoveWindowTimers( hwnd );
698 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
699 wndPtr->hmemTaskQ = 0;
701 if (!(wndPtr->dwStyle & WS_CHILD))
703 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
704 if (menu) DestroyMenu( menu );
706 if (wndPtr->hSysMenu)
708 DestroyMenu( wndPtr->hSysMenu );
709 wndPtr->hSysMenu = 0;
711 USER_Driver.pDestroyWindow( hwnd );
712 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
713 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
714 CLASS_RemoveWindow( wndPtr->class );
715 wndPtr->class = NULL;
716 wndPtr->dwMagic = 0; /* Mark it as invalid */
717 WIN_ReleaseWndPtr( wndPtr );
718 return 0;
721 /***********************************************************************
722 * WIN_DestroyThreadWindows
724 * Destroy all children of 'wnd' owned by the current thread.
725 * Return TRUE if something was done.
727 void WIN_DestroyThreadWindows( HWND hwnd )
729 HWND *list;
730 int i;
732 if (!(list = WIN_ListChildren( hwnd ))) return;
733 for (i = 0; list[i]; i++)
735 if (WIN_IsCurrentThread( list[i] ))
736 DestroyWindow( list[i] );
737 else
738 WIN_DestroyThreadWindows( list[i] );
740 HeapFree( GetProcessHeap(), 0, list );
743 /***********************************************************************
744 * WIN_CreateDesktopWindow
746 * Create the desktop window.
748 BOOL WIN_CreateDesktopWindow(void)
750 struct tagCLASS *class;
751 HWND hwndDesktop;
752 INT wndExtra;
753 DWORD clsStyle;
754 WNDPROC winproc;
755 DCE *dce;
756 CREATESTRUCTA cs;
757 RECT rect;
759 TRACE("Creating desktop window\n");
761 if (!WINPOS_CreateInternalPosAtom() ||
762 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
763 &wndExtra, &winproc, &clsStyle, &dce )))
764 return FALSE;
766 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
767 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
768 if (!pWndDesktop) return FALSE;
769 hwndDesktop = pWndDesktop->hwndSelf;
771 pWndDesktop->tid = 0; /* nobody owns the desktop */
772 pWndDesktop->parent = 0;
773 pWndDesktop->owner = 0;
774 pWndDesktop->class = class;
775 pWndDesktop->hInstance = 0;
776 pWndDesktop->text = NULL;
777 pWndDesktop->hmemTaskQ = 0;
778 pWndDesktop->hrgnUpdate = 0;
779 pWndDesktop->hwndLastActive = hwndDesktop;
780 pWndDesktop->dwStyle = 0;
781 pWndDesktop->dwExStyle = 0;
782 pWndDesktop->clsStyle = clsStyle;
783 pWndDesktop->dce = NULL;
784 pWndDesktop->pVScroll = NULL;
785 pWndDesktop->pHScroll = NULL;
786 pWndDesktop->wIDmenu = 0;
787 pWndDesktop->helpContext = 0;
788 pWndDesktop->flags = 0;
789 pWndDesktop->hSysMenu = 0;
790 pWndDesktop->userdata = 0;
791 pWndDesktop->winproc = winproc;
792 pWndDesktop->cbWndExtra = wndExtra;
794 cs.lpCreateParams = NULL;
795 cs.hInstance = 0;
796 cs.hMenu = 0;
797 cs.hwndParent = 0;
798 cs.x = 0;
799 cs.y = 0;
800 cs.cx = GetSystemMetrics( SM_CXSCREEN );
801 cs.cy = GetSystemMetrics( SM_CYSCREEN );
802 cs.style = pWndDesktop->dwStyle;
803 cs.dwExStyle = pWndDesktop->dwExStyle;
804 cs.lpszName = NULL;
805 cs.lpszClass = DESKTOP_CLASS_ATOM;
807 SetRect( &rect, 0, 0, cs.cx, cs.cy );
808 WIN_SetRectangles( hwndDesktop, &rect, &rect );
809 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
811 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
813 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
814 WIN_ReleaseWndPtr( pWndDesktop );
815 return TRUE;
819 /***********************************************************************
820 * WIN_FixCoordinates
822 * Fix the coordinates - Helper for WIN_CreateWindowEx.
823 * returns default show mode in sw.
824 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
826 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
828 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
829 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
831 if (cs->style & (WS_CHILD | WS_POPUP))
833 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
834 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
836 else /* overlapped window */
838 STARTUPINFOA info;
840 GetStartupInfoA( &info );
842 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
844 /* Never believe Microsoft's documentation... CreateWindowEx doc says
845 * that if an overlapped window is created with WS_VISIBLE style bit
846 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
847 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
848 * reveals that
850 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
851 * 2) it does not ignore the y parameter as the docs claim; instead, it
852 * uses it as second parameter to ShowWindow() unless y is either
853 * CW_USEDEFAULT or CW_USEDEFAULT16.
855 * The fact that we didn't do 2) caused bogus windows pop up when wine
856 * was running apps that were using this obscure feature. Example -
857 * calc.exe that comes with Win98 (only Win98, it's different from
858 * the one that comes with Win95 and NT)
860 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
861 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
862 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
865 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
867 if (info.dwFlags & STARTF_USESIZE)
869 cs->cx = info.dwXSize;
870 cs->cy = info.dwYSize;
872 else /* if no other hint from the app, pick 3/4 of the screen real estate */
874 RECT r;
875 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
876 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
877 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
884 /***********************************************************************
885 * WIN_CreateWindowEx
887 * Implementation of CreateWindowEx().
889 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
890 WINDOWPROCTYPE type )
892 INT sw = SW_SHOW;
893 struct tagCLASS *classPtr;
894 WND *wndPtr;
895 HWND hwnd, hwndLinkAfter, parent, owner;
896 INT wndExtra;
897 DWORD clsStyle;
898 WNDPROC winproc;
899 DCE *dce;
900 BOOL unicode = (type == WIN_PROC_32W);
902 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
903 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
904 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
905 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
906 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
908 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
909 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
911 /* Find the parent window */
913 parent = GetDesktopWindow();
914 owner = 0;
915 if (cs->hwndParent)
917 /* Make sure parent is valid */
918 if (!IsWindow( cs->hwndParent ))
920 WARN("Bad parent %04x\n", cs->hwndParent );
921 return 0;
923 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
924 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
926 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
928 WARN("No parent for child window\n" );
929 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
932 /* Find the window class */
933 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
934 &wndExtra, &winproc, &clsStyle, &dce )))
936 WARN("Bad class '%s'\n", cs->lpszClass );
937 return 0;
940 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
942 /* Correct the window style - stage 1
944 * These are patches that appear to affect both the style loaded into the
945 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
947 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
948 * why does the user get to set it?
951 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
952 * tested for WS_POPUP
954 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
955 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
956 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
957 cs->dwExStyle |= WS_EX_WINDOWEDGE;
958 else
959 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
961 /* Create the window structure */
963 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
964 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
966 TRACE("out of memory\n" );
967 return 0;
969 hwnd = wndPtr->hwndSelf;
971 /* Fill the window structure */
973 wndPtr->tid = GetCurrentThreadId();
974 wndPtr->owner = owner;
975 wndPtr->parent = parent;
976 wndPtr->class = classPtr;
977 wndPtr->winproc = winproc;
978 wndPtr->hInstance = cs->hInstance;
979 wndPtr->text = NULL;
980 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
981 wndPtr->hrgnUpdate = 0;
982 wndPtr->hrgnWnd = 0;
983 wndPtr->hwndLastActive = hwnd;
984 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
985 wndPtr->dwExStyle = cs->dwExStyle;
986 wndPtr->clsStyle = clsStyle;
987 wndPtr->wIDmenu = 0;
988 wndPtr->helpContext = 0;
989 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
990 wndPtr->pVScroll = NULL;
991 wndPtr->pHScroll = NULL;
992 wndPtr->userdata = 0;
993 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
994 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
995 wndPtr->cbWndExtra = wndExtra;
997 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
999 /* Call the WH_CBT hook */
1001 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1002 ? HWND_BOTTOM : HWND_TOP;
1004 if (HOOK_IsHooked( WH_CBT ))
1006 CBT_CREATEWNDA cbtc;
1007 LRESULT ret;
1009 cbtc.lpcs = cs;
1010 cbtc.hwndInsertAfter = hwndLinkAfter;
1011 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
1012 (WPARAM)hwnd, (LPARAM)&cbtc)
1013 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
1014 (WPARAM)hwnd, (LPARAM)&cbtc);
1015 if (ret)
1017 TRACE("CBT-hook returned 0\n");
1018 free_window_handle( hwnd );
1019 CLASS_RemoveWindow( classPtr );
1020 WIN_ReleaseWndPtr(wndPtr);
1021 return 0;
1025 /* Correct the window style - stage 2 */
1027 if (!(cs->style & WS_CHILD))
1029 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1030 if (!(cs->style & WS_POPUP))
1032 wndPtr->dwStyle |= WS_CAPTION;
1033 wndPtr->flags |= WIN_NEED_SIZE;
1036 SERVER_START_REQ( set_window_info )
1038 req->handle = hwnd;
1039 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1040 req->style = wndPtr->dwStyle;
1041 req->ex_style = wndPtr->dwExStyle;
1042 req->instance = (void *)wndPtr->hInstance;
1043 SERVER_CALL();
1045 SERVER_END_REQ;
1047 /* Get class or window DC if needed */
1049 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1050 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1051 else wndPtr->dce = NULL;
1053 /* Set the window menu */
1055 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1057 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1058 else
1060 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1061 if (menuName)
1063 if (HIWORD(cs->hInstance))
1064 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1065 else
1066 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1068 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1072 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1073 WIN_ReleaseWndPtr( wndPtr );
1075 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1077 WIN_DestroyWindow( hwnd );
1078 return 0;
1081 /* Notify the parent window only */
1083 send_parent_notify( hwnd, WM_CREATE );
1084 if (!IsWindow( hwnd )) return 0;
1086 if (cs->style & WS_VISIBLE)
1088 /* in case WS_VISIBLE got set in the meantime */
1089 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1090 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1091 WIN_ReleasePtr( wndPtr );
1092 ShowWindow( hwnd, sw );
1095 /* Call WH_SHELL hook */
1097 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1098 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1100 TRACE("created window %04x\n", hwnd);
1101 return hwnd;
1105 /***********************************************************************
1106 * CreateWindow (USER.41)
1108 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1109 DWORD style, INT16 x, INT16 y, INT16 width,
1110 INT16 height, HWND16 parent, HMENU16 menu,
1111 HINSTANCE16 instance, LPVOID data )
1113 return CreateWindowEx16( 0, className, windowName, style,
1114 x, y, width, height, parent, menu, instance, data );
1118 /***********************************************************************
1119 * CreateWindowEx (USER.452)
1121 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1122 LPCSTR windowName, DWORD style, INT16 x,
1123 INT16 y, INT16 width, INT16 height,
1124 HWND16 parent, HMENU16 menu,
1125 HINSTANCE16 instance, LPVOID data )
1127 ATOM classAtom;
1128 CREATESTRUCTA cs;
1129 char buffer[256];
1131 /* Find the class atom */
1133 if (HIWORD(className))
1135 if (!(classAtom = GlobalFindAtomA( className )))
1137 ERR( "bad class name %s\n", debugres_a(className) );
1138 return 0;
1141 else
1143 classAtom = LOWORD(className);
1144 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1146 ERR( "bad atom %x\n", classAtom);
1147 return 0;
1149 className = buffer;
1152 /* Fix the coordinates */
1154 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1155 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1156 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1157 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1159 /* Create the window */
1161 cs.lpCreateParams = data;
1162 cs.hInstance = (HINSTANCE)instance;
1163 cs.hMenu = (HMENU)menu;
1164 cs.hwndParent = WIN_Handle32( parent );
1165 cs.style = style;
1166 cs.lpszName = windowName;
1167 cs.lpszClass = className;
1168 cs.dwExStyle = exStyle;
1170 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1174 /***********************************************************************
1175 * CreateWindowExA (USER32.@)
1177 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1178 LPCSTR windowName, DWORD style, INT x,
1179 INT y, INT width, INT height,
1180 HWND parent, HMENU menu,
1181 HINSTANCE instance, LPVOID data )
1183 ATOM classAtom;
1184 CREATESTRUCTA cs;
1185 char buffer[256];
1187 if(!instance)
1188 instance=GetModuleHandleA(NULL);
1190 if(exStyle & WS_EX_MDICHILD)
1191 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1193 /* Find the class atom */
1195 if (HIWORD(className))
1197 if (!(classAtom = GlobalFindAtomA( className )))
1199 ERR( "bad class name %s\n", debugres_a(className) );
1200 return 0;
1203 else
1205 classAtom = LOWORD(className);
1206 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1208 ERR( "bad atom %x\n", classAtom);
1209 return 0;
1211 className = buffer;
1214 /* Create the window */
1216 cs.lpCreateParams = data;
1217 cs.hInstance = instance;
1218 cs.hMenu = menu;
1219 cs.hwndParent = parent;
1220 cs.x = x;
1221 cs.y = y;
1222 cs.cx = width;
1223 cs.cy = height;
1224 cs.style = style;
1225 cs.lpszName = windowName;
1226 cs.lpszClass = className;
1227 cs.dwExStyle = exStyle;
1229 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1233 /***********************************************************************
1234 * CreateWindowExW (USER32.@)
1236 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1237 LPCWSTR windowName, DWORD style, INT x,
1238 INT y, INT width, INT height,
1239 HWND parent, HMENU menu,
1240 HINSTANCE instance, LPVOID data )
1242 ATOM classAtom;
1243 CREATESTRUCTW cs;
1244 WCHAR buffer[256];
1246 if(!instance)
1247 instance=GetModuleHandleA(NULL);
1249 if(exStyle & WS_EX_MDICHILD)
1250 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1252 /* Find the class atom */
1254 if (HIWORD(className))
1256 if (!(classAtom = GlobalFindAtomW( className )))
1258 ERR( "bad class name %s\n", debugres_w(className) );
1259 return 0;
1262 else
1264 classAtom = LOWORD(className);
1265 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1267 ERR( "bad atom %x\n", classAtom);
1268 return 0;
1270 className = buffer;
1273 /* Create the window */
1275 cs.lpCreateParams = data;
1276 cs.hInstance = instance;
1277 cs.hMenu = menu;
1278 cs.hwndParent = parent;
1279 cs.x = x;
1280 cs.y = y;
1281 cs.cx = width;
1282 cs.cy = height;
1283 cs.style = style;
1284 cs.lpszName = windowName;
1285 cs.lpszClass = className;
1286 cs.dwExStyle = exStyle;
1288 /* Note: we rely on the fact that CREATESTRUCTA and */
1289 /* CREATESTRUCTW have the same layout. */
1290 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1294 /***********************************************************************
1295 * WIN_SendDestroyMsg
1297 static void WIN_SendDestroyMsg( HWND hwnd )
1299 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1300 if (USER_Driver.pResetSelectionOwner)
1301 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1304 * Send the WM_DESTROY to the window.
1306 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1309 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1310 * make sure that the window still exists when we come back.
1312 if (IsWindow(hwnd))
1314 HWND* pWndArray;
1315 int i;
1317 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1319 /* start from the end (FIXME: is this needed?) */
1320 for (i = 0; pWndArray[i]; i++) ;
1322 while (--i >= 0)
1324 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1326 HeapFree( GetProcessHeap(), 0, pWndArray );
1328 else
1329 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1333 /***********************************************************************
1334 * DestroyWindow (USER32.@)
1336 BOOL WINAPI DestroyWindow( HWND hwnd )
1338 BOOL is_child;
1339 HWND h;
1341 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1343 SetLastError( ERROR_ACCESS_DENIED );
1344 return FALSE;
1347 TRACE("(%04x)\n", hwnd);
1349 /* Look whether the focus is within the tree of windows we will
1350 * be destroying.
1352 h = GetFocus();
1353 if (h == hwnd || IsChild( hwnd, h ))
1355 HWND parent = GetAncestor( hwnd, GA_PARENT );
1356 if (parent == GetDesktopWindow()) parent = 0;
1357 SetFocus( parent );
1360 /* Call hooks */
1362 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1364 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1366 if (is_child)
1368 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1369 send_parent_notify( hwnd, WM_DESTROY );
1371 else if (!GetWindow( hwnd, GW_OWNER ))
1373 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1374 /* FIXME: clean up palette - see "Internals" p.352 */
1377 if (!IsWindow(hwnd)) return TRUE;
1379 if (USER_Driver.pResetSelectionOwner)
1380 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1382 /* Hide the window */
1384 ShowWindow( hwnd, SW_HIDE );
1385 if (!IsWindow(hwnd)) return TRUE;
1387 /* Recursively destroy owned windows */
1389 if (!is_child)
1391 HWND owner;
1393 for (;;)
1395 int i, got_one = 0;
1396 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1397 if (list)
1399 for (i = 0; list[i]; i++)
1401 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1402 if (WIN_IsCurrentThread( list[i] ))
1404 DestroyWindow( list[i] );
1405 got_one = 1;
1406 continue;
1408 WIN_SetOwner( list[i], 0 );
1410 HeapFree( GetProcessHeap(), 0, list );
1412 if (!got_one) break;
1415 WINPOS_ActivateOtherWindow( hwnd );
1417 if ((owner = GetWindow( hwnd, GW_OWNER )))
1419 WND *ptr = WIN_FindWndPtr( owner );
1420 if (ptr)
1422 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1423 WIN_ReleaseWndPtr( ptr );
1428 /* Send destroy messages */
1430 WIN_SendDestroyMsg( hwnd );
1431 if (!IsWindow( hwnd )) return TRUE;
1433 /* Unlink now so we won't bother with the children later on */
1435 WIN_UnlinkWindow( hwnd );
1437 /* Destroy the window storage */
1439 WIN_DestroyWindow( hwnd );
1440 return TRUE;
1444 /***********************************************************************
1445 * CloseWindow (USER32.@)
1447 BOOL WINAPI CloseWindow( HWND hwnd )
1449 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1450 ShowWindow( hwnd, SW_MINIMIZE );
1451 return TRUE;
1455 /***********************************************************************
1456 * OpenIcon (USER32.@)
1458 BOOL WINAPI OpenIcon( HWND hwnd )
1460 if (!IsIconic( hwnd )) return FALSE;
1461 ShowWindow( hwnd, SW_SHOWNORMAL );
1462 return TRUE;
1466 /***********************************************************************
1467 * WIN_FindWindow
1469 * Implementation of FindWindow() and FindWindowEx().
1471 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1473 HWND *list = NULL;
1474 HWND retvalue = 0;
1475 int i = 0, len = 0;
1476 WCHAR *buffer = NULL;
1478 if (!parent) parent = GetDesktopWindow();
1479 if (title)
1481 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1482 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1485 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1487 if (child)
1489 child = WIN_GetFullHandle( child );
1490 while (list[i] && list[i] != child) i++;
1491 if (!list[i]) goto done;
1492 i++; /* start from next window */
1495 if (title)
1497 while (list[i])
1499 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1500 i++;
1503 retvalue = list[i];
1505 done:
1506 if (list) HeapFree( GetProcessHeap(), 0, list );
1507 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1508 return retvalue;
1513 /***********************************************************************
1514 * FindWindowA (USER32.@)
1516 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1518 HWND ret = FindWindowExA( 0, 0, className, title );
1519 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1520 return ret;
1524 /***********************************************************************
1525 * FindWindowExA (USER32.@)
1527 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1528 LPCSTR className, LPCSTR title )
1530 ATOM atom = 0;
1531 LPWSTR buffer;
1532 HWND hwnd;
1534 if (className)
1536 /* If the atom doesn't exist, then no class */
1537 /* with this name exists either. */
1538 if (!(atom = GlobalFindAtomA( className )))
1540 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1541 return 0;
1545 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1546 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1547 HeapFree( GetProcessHeap(), 0, buffer );
1548 return hwnd;
1552 /***********************************************************************
1553 * FindWindowExW (USER32.@)
1555 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1556 LPCWSTR className, LPCWSTR title )
1558 ATOM atom = 0;
1560 if (className)
1562 /* If the atom doesn't exist, then no class */
1563 /* with this name exists either. */
1564 if (!(atom = GlobalFindAtomW( className )))
1566 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1567 return 0;
1570 return WIN_FindWindow( parent, child, atom, title );
1574 /***********************************************************************
1575 * FindWindowW (USER32.@)
1577 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1579 return FindWindowExW( 0, 0, className, title );
1583 /**********************************************************************
1584 * GetDesktopWindow (USER32.@)
1586 HWND WINAPI GetDesktopWindow(void)
1588 if (pWndDesktop) return pWndDesktop->hwndSelf;
1589 ERR( "You need the -desktop option when running with native USER\n" );
1590 ExitProcess(1);
1591 return 0;
1595 /*******************************************************************
1596 * EnableWindow (USER32.@)
1598 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1600 WND *wndPtr;
1601 BOOL retvalue;
1602 LONG style;
1603 HWND full_handle;
1605 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1606 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1608 hwnd = full_handle;
1610 TRACE("( %x, %d )\n", hwnd, enable);
1612 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1613 style = wndPtr->dwStyle;
1614 retvalue = ((style & WS_DISABLED) != 0);
1615 WIN_ReleasePtr( wndPtr );
1617 if (enable && retvalue)
1619 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1620 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1622 else if (!enable && !retvalue)
1624 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1626 WIN_SetStyle( hwnd, style | WS_DISABLED );
1628 if (hwnd == GetFocus())
1629 SetFocus( 0 ); /* A disabled window can't have the focus */
1631 if (hwnd == GetCapture())
1632 ReleaseCapture(); /* A disabled window can't capture the mouse */
1634 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1636 return retvalue;
1640 /***********************************************************************
1641 * IsWindowEnabled (USER32.@)
1643 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1645 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1649 /***********************************************************************
1650 * IsWindowUnicode (USER32.@)
1652 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1654 WND * wndPtr;
1655 BOOL retvalue;
1657 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1658 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1659 WIN_ReleaseWndPtr(wndPtr);
1660 return retvalue;
1664 /**********************************************************************
1665 * GetWindowWord (USER32.@)
1667 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1669 if (offset >= 0)
1671 WORD retvalue = 0;
1672 WND *wndPtr = WIN_GetPtr( hwnd );
1673 if (!wndPtr)
1675 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1676 return 0;
1678 if (wndPtr == WND_OTHER_PROCESS)
1680 if (IsWindow( hwnd ))
1681 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1682 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1683 return 0;
1685 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1687 WARN("Invalid offset %d\n", offset );
1688 SetLastError( ERROR_INVALID_INDEX );
1690 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1691 WIN_ReleasePtr( wndPtr );
1692 return retvalue;
1695 switch(offset)
1697 case GWL_HWNDPARENT:
1698 return GetWindowLongW( hwnd, offset );
1699 case GWL_ID:
1700 case GWL_HINSTANCE:
1702 LONG ret = GetWindowLongW( hwnd, offset );
1703 if (HIWORD(ret))
1704 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1705 return LOWORD(ret);
1707 default:
1708 WARN("Invalid offset %d\n", offset );
1709 return 0;
1714 /**********************************************************************
1715 * SetWindowWord (USER32.@)
1717 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1719 WORD *ptr, retval;
1720 WND * wndPtr;
1722 switch(offset)
1724 case GWL_ID:
1725 case GWL_HINSTANCE:
1726 case GWL_HWNDPARENT:
1727 return SetWindowLongW( hwnd, offset, (UINT)newval );
1728 default:
1729 if (offset < 0)
1731 WARN("Invalid offset %d\n", offset );
1732 SetLastError( ERROR_INVALID_INDEX );
1733 return 0;
1737 wndPtr = WIN_GetPtr( hwnd );
1738 if (wndPtr == WND_OTHER_PROCESS)
1740 if (IsWindow(hwnd))
1741 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1742 offset, newval, hwnd );
1743 wndPtr = NULL;
1745 if (!wndPtr)
1747 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1748 return 0;
1751 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1753 WARN("Invalid offset %d\n", offset );
1754 WIN_ReleasePtr(wndPtr);
1755 SetLastError( ERROR_INVALID_INDEX );
1756 return 0;
1758 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1759 retval = *ptr;
1760 *ptr = newval;
1761 WIN_ReleasePtr(wndPtr);
1762 return retval;
1766 /**********************************************************************
1767 * WIN_GetWindowLong
1769 * Helper function for GetWindowLong().
1771 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1773 LONG retvalue = 0;
1774 WND *wndPtr;
1776 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1778 if (!(wndPtr = WIN_GetPtr( hwnd )))
1780 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1781 return 0;
1784 if (wndPtr == WND_OTHER_PROCESS)
1786 if (offset >= 0)
1788 if (IsWindow(hwnd))
1789 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1790 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1791 return 0;
1793 if (offset == GWL_WNDPROC)
1795 SetLastError( ERROR_ACCESS_DENIED );
1796 return 0;
1798 SERVER_START_REQ( set_window_info )
1800 req->handle = hwnd;
1801 req->flags = 0; /* don't set anything, just retrieve */
1802 if (!SERVER_CALL_ERR())
1804 switch(offset)
1806 case GWL_STYLE: retvalue = req->style; break;
1807 case GWL_EXSTYLE: retvalue = req->ex_style; break;
1808 case GWL_ID: retvalue = req->id; break;
1809 case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break;
1810 case GWL_USERDATA: retvalue = (ULONG_PTR)req->user_data; break;
1811 default:
1812 SetLastError( ERROR_INVALID_INDEX );
1813 break;
1817 SERVER_END_REQ;
1818 return retvalue;
1821 /* now we have a valid wndPtr */
1823 if (offset >= 0)
1825 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1827 WARN("Invalid offset %d\n", offset );
1828 WIN_ReleasePtr( wndPtr );
1829 SetLastError( ERROR_INVALID_INDEX );
1830 return 0;
1832 /* Special case for dialog window procedure */
1833 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1834 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1835 else
1836 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1837 WIN_ReleasePtr( wndPtr );
1838 return retvalue;
1841 switch(offset)
1843 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1844 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1845 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1846 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1847 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1848 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1849 default:
1850 WARN("Unknown offset %d\n", offset );
1851 SetLastError( ERROR_INVALID_INDEX );
1852 break;
1854 WIN_ReleasePtr(wndPtr);
1855 return retvalue;
1859 /**********************************************************************
1860 * WIN_SetWindowLong
1862 * Helper function for SetWindowLong().
1864 * 0 is the failure code. However, in the case of failure SetLastError
1865 * must be set to distinguish between a 0 return value and a failure.
1867 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1868 WINDOWPROCTYPE type )
1870 LONG retval = 0;
1871 WND *wndPtr;
1873 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1875 if (!WIN_IsCurrentProcess( hwnd ))
1877 if (offset == GWL_WNDPROC)
1879 SetLastError( ERROR_ACCESS_DENIED );
1880 return 0;
1882 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1885 wndPtr = WIN_GetPtr( hwnd );
1887 if (offset >= 0)
1889 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1890 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1892 WARN("Invalid offset %d\n", offset );
1893 WIN_ReleasePtr( wndPtr );
1894 SetLastError( ERROR_INVALID_INDEX );
1895 return 0;
1897 /* Special case for dialog window procedure */
1898 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1900 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1901 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1902 type, WIN_PROC_WINDOW );
1903 WIN_ReleasePtr( wndPtr );
1904 return retval;
1906 retval = *ptr;
1907 *ptr = newval;
1908 WIN_ReleasePtr( wndPtr );
1910 else
1912 STYLESTRUCT style;
1913 BOOL ok;
1915 /* first some special cases */
1916 switch( offset )
1918 case GWL_STYLE:
1919 case GWL_EXSTYLE:
1920 style.styleOld = wndPtr->dwStyle;
1921 style.styleNew = newval;
1922 WIN_ReleasePtr( wndPtr );
1923 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1924 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1925 newval = style.styleNew;
1926 break;
1927 case GWL_HWNDPARENT:
1928 WIN_ReleasePtr( wndPtr );
1929 return (LONG)SetParent( hwnd, (HWND)newval );
1930 case GWL_WNDPROC:
1931 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1932 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1933 type, WIN_PROC_WINDOW );
1934 WIN_ReleasePtr( wndPtr );
1935 return retval;
1936 case GWL_ID:
1937 case GWL_HINSTANCE:
1938 case GWL_USERDATA:
1939 break;
1940 default:
1941 WIN_ReleasePtr( wndPtr );
1942 WARN("Invalid offset %d\n", offset );
1943 SetLastError( ERROR_INVALID_INDEX );
1944 return 0;
1947 SERVER_START_REQ( set_window_info )
1949 req->handle = hwnd;
1950 switch(offset)
1952 case GWL_STYLE:
1953 req->flags = SET_WIN_STYLE;
1954 req->style = newval;
1955 break;
1956 case GWL_EXSTYLE:
1957 req->flags = SET_WIN_EXSTYLE;
1958 req->ex_style = newval;
1959 break;
1960 case GWL_ID:
1961 req->flags = SET_WIN_ID;
1962 req->id = newval;
1963 break;
1964 case GWL_HINSTANCE:
1965 req->flags = SET_WIN_INSTANCE;
1966 req->instance = (void *)newval;
1967 break;
1968 case GWL_USERDATA:
1969 req->flags = SET_WIN_USERDATA;
1970 req->user_data = (void *)newval;
1971 break;
1973 if ((ok = !SERVER_CALL_ERR()))
1975 switch(offset)
1977 case GWL_STYLE:
1978 wndPtr->dwStyle = newval;
1979 retval = req->old_style;
1980 break;
1981 case GWL_EXSTYLE:
1982 wndPtr->dwExStyle = newval;
1983 retval = req->old_ex_style;
1984 break;
1985 case GWL_ID:
1986 wndPtr->wIDmenu = newval;
1987 retval = req->old_id;
1988 break;
1989 case GWL_HINSTANCE:
1990 wndPtr->hInstance = newval;
1991 retval = (HINSTANCE)req->old_instance;
1992 break;
1993 case GWL_USERDATA:
1994 wndPtr->userdata = newval;
1995 retval = (ULONG_PTR)req->old_user_data;
1996 break;
2000 SERVER_END_REQ;
2001 WIN_ReleasePtr( wndPtr );
2003 if (!ok) return 0;
2005 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2006 USER_Driver.pSetWindowStyle( hwnd, retval );
2008 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2009 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2012 return retval;
2016 /**********************************************************************
2017 * GetWindowLong (USER.135)
2019 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2021 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2025 /**********************************************************************
2026 * GetWindowLongA (USER32.@)
2028 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2030 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2034 /**********************************************************************
2035 * GetWindowLongW (USER32.@)
2037 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2039 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2043 /**********************************************************************
2044 * SetWindowLong (USER.136)
2046 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2048 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2052 /**********************************************************************
2053 * SetWindowLongA (USER32.@)
2055 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2057 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2061 /**********************************************************************
2062 * SetWindowLongW (USER32.@) Set window attribute
2064 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2065 * value in a window's extra memory.
2067 * The _hwnd_ parameter specifies the window. is the handle to a
2068 * window that has extra memory. The _newval_ parameter contains the
2069 * new attribute or extra memory value. If positive, the _offset_
2070 * parameter is the byte-addressed location in the window's extra
2071 * memory to set. If negative, _offset_ specifies the window
2072 * attribute to set, and should be one of the following values:
2074 * GWL_EXSTYLE The window's extended window style
2076 * GWL_STYLE The window's window style.
2078 * GWL_WNDPROC Pointer to the window's window procedure.
2080 * GWL_HINSTANCE The window's pplication instance handle.
2082 * GWL_ID The window's identifier.
2084 * GWL_USERDATA The window's user-specified data.
2086 * If the window is a dialog box, the _offset_ parameter can be one of
2087 * the following values:
2089 * DWL_DLGPROC The address of the window's dialog box procedure.
2091 * DWL_MSGRESULT The return value of a message
2092 * that the dialog box procedure processed.
2094 * DWL_USER Application specific information.
2096 * RETURNS
2098 * If successful, returns the previous value located at _offset_. Otherwise,
2099 * returns 0.
2101 * NOTES
2103 * Extra memory for a window class is specified by a nonzero cbWndExtra
2104 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2105 * time of class creation.
2107 * Using GWL_WNDPROC to set a new window procedure effectively creates
2108 * a window subclass. Use CallWindowProc() in the new windows procedure
2109 * to pass messages to the superclass's window procedure.
2111 * The user data is reserved for use by the application which created
2112 * the window.
2114 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2115 * instead, call the EnableWindow() function to change the window's
2116 * disabled state.
2118 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2119 * SetParent() instead.
2121 * Win95:
2122 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2123 * it sends WM_STYLECHANGING before changing the settings
2124 * and WM_STYLECHANGED afterwards.
2125 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2127 LONG WINAPI SetWindowLongW(
2128 HWND hwnd, /* [in] window to alter */
2129 INT offset, /* [in] offset, in bytes, of location to alter */
2130 LONG newval /* [in] new value of location */
2132 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2136 /*******************************************************************
2137 * GetWindowTextA (USER32.@)
2139 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2141 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2142 (LPARAM)lpString );
2145 /*******************************************************************
2146 * InternalGetWindowText (USER32.@)
2148 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2150 WND *win = WIN_FindWndPtr( hwnd );
2151 if (!win) return 0;
2152 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2153 else lpString[0] = 0;
2154 WIN_ReleaseWndPtr( win );
2155 return strlenW(lpString);
2159 /*******************************************************************
2160 * GetWindowTextW (USER32.@)
2162 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2164 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2165 (LPARAM)lpString );
2169 /*******************************************************************
2170 * SetWindowText (USER32.@)
2171 * SetWindowTextA (USER32.@)
2173 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2175 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2179 /*******************************************************************
2180 * SetWindowTextW (USER32.@)
2182 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2184 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2188 /*******************************************************************
2189 * GetWindowTextLengthA (USER32.@)
2191 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2193 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2196 /*******************************************************************
2197 * GetWindowTextLengthW (USER32.@)
2199 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2201 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2205 /*******************************************************************
2206 * IsWindow (USER32.@)
2208 BOOL WINAPI IsWindow( HWND hwnd )
2210 WND *ptr;
2211 BOOL ret;
2213 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2215 if (ptr != WND_OTHER_PROCESS)
2217 WIN_ReleasePtr( ptr );
2218 return TRUE;
2221 /* check other processes */
2222 SERVER_START_REQ( get_window_info )
2224 req->handle = hwnd;
2225 ret = !SERVER_CALL_ERR();
2227 SERVER_END_REQ;
2228 return ret;
2232 /***********************************************************************
2233 * GetWindowThreadProcessId (USER32.@)
2235 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2237 WND *ptr;
2238 DWORD tid = 0;
2240 if (!(ptr = WIN_GetPtr( hwnd )))
2242 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2243 return 0;
2246 if (ptr != WND_OTHER_PROCESS)
2248 /* got a valid window */
2249 tid = ptr->tid;
2250 if (process) *process = GetCurrentProcessId();
2251 WIN_ReleasePtr( ptr );
2252 return tid;
2255 /* check other processes */
2256 SERVER_START_REQ( get_window_info )
2258 req->handle = hwnd;
2259 if (!SERVER_CALL_ERR())
2261 tid = (DWORD)req->tid;
2262 if (process) *process = (DWORD)req->pid;
2265 SERVER_END_REQ;
2266 return tid;
2270 /*****************************************************************
2271 * GetParent (USER32.@)
2273 HWND WINAPI GetParent( HWND hwnd )
2275 WND *wndPtr;
2276 HWND retvalue = 0;
2278 if (!(wndPtr = WIN_GetPtr( hwnd )))
2280 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2281 return 0;
2283 if (wndPtr == WND_OTHER_PROCESS)
2285 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2286 if (style & (WS_POPUP | WS_CHILD))
2288 SERVER_START_REQ( get_window_tree )
2290 req->handle = hwnd;
2291 if (!SERVER_CALL_ERR())
2293 if (style & WS_CHILD) retvalue = req->parent;
2294 else retvalue = req->owner;
2297 SERVER_END_REQ;
2300 else
2302 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2303 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2304 WIN_ReleasePtr( wndPtr );
2306 return retvalue;
2310 /*****************************************************************
2311 * GetAncestor (USER32.@)
2313 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2315 WND *win;
2316 HWND ret = 0;
2317 size_t size;
2319 for (;;)
2321 if (!(win = WIN_GetPtr( hwnd )))
2323 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2324 return 0;
2326 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2327 ret = win->parent;
2328 WIN_ReleasePtr( win );
2329 if (type == GA_PARENT) return ret;
2330 if (!ret || ret == GetDesktopWindow())
2332 ret = hwnd; /* if ret is the desktop, hwnd is the root ancestor */
2333 goto done;
2335 hwnd = ret; /* restart with parent as hwnd */
2338 size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2340 SERVER_START_VAR_REQ( get_window_parents, size )
2342 req->handle = hwnd;
2343 if (!SERVER_CALL())
2345 user_handle_t *data = server_data_ptr(req);
2346 int count = server_data_size(req) / sizeof(*data);
2347 if (count)
2349 switch(type)
2351 case GA_PARENT:
2352 ret = data[0];
2353 break;
2354 case GA_ROOT:
2355 case GA_ROOTOWNER:
2356 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2357 else ret = WIN_GetFullHandle( hwnd );
2358 break;
2363 SERVER_END_VAR_REQ;
2365 done:
2366 if (ret && type == GA_ROOTOWNER)
2368 for (;;)
2370 HWND owner = GetWindow( ret, GW_OWNER );
2371 if (!owner) break;
2372 ret = owner;
2375 return ret;
2379 /*****************************************************************
2380 * SetParent (USER32.@)
2382 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2384 WND *wndPtr;
2385 HWND retvalue, full_handle;
2386 BOOL was_visible;
2388 if (!parent) parent = GetDesktopWindow();
2389 else parent = WIN_GetFullHandle( parent );
2391 if (!IsWindow( parent ))
2393 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2394 return 0;
2397 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2398 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2400 hwnd = full_handle;
2402 if (USER_Driver.pSetParent)
2403 return USER_Driver.pSetParent( hwnd, parent );
2405 /* Windows hides the window first, then shows it again
2406 * including the WM_SHOWWINDOW messages and all */
2407 was_visible = ShowWindow( hwnd, SW_HIDE );
2409 if (!IsWindow( parent )) return 0;
2410 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2412 retvalue = wndPtr->parent; /* old parent */
2413 if (parent != retvalue)
2415 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2417 if (parent != GetDesktopWindow()) /* a child window */
2419 if (!(wndPtr->dwStyle & WS_CHILD))
2421 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2422 if (menu) DestroyMenu( menu );
2426 WIN_ReleasePtr( wndPtr );
2428 /* SetParent additionally needs to make hwnd the topmost window
2429 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2430 WM_WINDOWPOSCHANGED notification messages.
2432 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2433 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2434 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2435 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2436 return retvalue;
2440 /*******************************************************************
2441 * IsChild (USER32.@)
2443 BOOL WINAPI IsChild( HWND parent, HWND child )
2445 HWND *list = WIN_ListParents( child );
2446 int i;
2447 BOOL ret;
2449 if (!list) return FALSE;
2450 parent = WIN_GetFullHandle( parent );
2451 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2452 ret = (list[i] != 0);
2453 HeapFree( GetProcessHeap(), 0, list );
2454 return ret;
2458 /***********************************************************************
2459 * IsWindowVisible (USER32.@)
2461 BOOL WINAPI IsWindowVisible( HWND hwnd )
2463 HWND *list;
2464 BOOL retval;
2465 int i;
2467 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2468 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2469 for (i = 0; list[i]; i++)
2470 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2471 retval = !list[i];
2472 HeapFree( GetProcessHeap(), 0, list );
2473 return retval;
2477 /***********************************************************************
2478 * WIN_IsWindowDrawable
2480 * hwnd is drawable when it is visible, all parents are not
2481 * minimized, and it is itself not minimized unless we are
2482 * trying to draw its default class icon.
2484 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2486 HWND *list;
2487 BOOL retval;
2488 int i;
2489 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2491 if (!(style & WS_VISIBLE)) return FALSE;
2492 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2494 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2495 for (i = 0; list[i]; i++)
2496 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2497 break;
2498 retval = !list[i];
2499 HeapFree( GetProcessHeap(), 0, list );
2500 return retval;
2504 /*******************************************************************
2505 * GetTopWindow (USER32.@)
2507 HWND WINAPI GetTopWindow( HWND hwnd )
2509 if (!hwnd) hwnd = GetDesktopWindow();
2510 return GetWindow( hwnd, GW_CHILD );
2514 /*******************************************************************
2515 * GetWindow (USER32.@)
2517 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2519 HWND retval = 0;
2521 if (rel == GW_OWNER) /* this one may be available locally */
2523 WND *wndPtr = WIN_GetPtr( hwnd );
2524 if (!wndPtr)
2526 SetLastError( ERROR_INVALID_HANDLE );
2527 return 0;
2529 if (wndPtr != WND_OTHER_PROCESS)
2531 retval = wndPtr->owner;
2532 WIN_ReleasePtr( wndPtr );
2533 return retval;
2535 /* else fall through to server call */
2538 SERVER_START_REQ( get_window_tree )
2540 req->handle = hwnd;
2541 if (!SERVER_CALL_ERR())
2543 switch(rel)
2545 case GW_HWNDFIRST:
2546 retval = req->first_sibling;
2547 break;
2548 case GW_HWNDLAST:
2549 retval = req->last_sibling;
2550 break;
2551 case GW_HWNDNEXT:
2552 retval = req->next_sibling;
2553 break;
2554 case GW_HWNDPREV:
2555 retval = req->prev_sibling;
2556 break;
2557 case GW_OWNER:
2558 retval = req->owner;
2559 break;
2560 case GW_CHILD:
2561 retval = req->first_child;
2562 break;
2566 SERVER_END_REQ;
2567 return retval;
2571 /***********************************************************************
2572 * WIN_InternalShowOwnedPopups
2574 * Internal version of ShowOwnedPopups; Wine functions should use this
2575 * to avoid interfering with application calls to ShowOwnedPopups
2576 * and to make sure the application can't prevent showing/hiding.
2578 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2582 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2584 int count = 0;
2585 WND *pWnd;
2586 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2588 if (!win_array) return TRUE;
2591 * Show windows Lowest first, Highest last to preserve Z-Order
2593 while (win_array[count]) count++;
2594 while (--count >= 0)
2596 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2597 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2599 if (pWnd->dwStyle & WS_POPUP)
2601 if (fShow)
2603 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2604 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2607 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2609 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2610 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2613 else
2615 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2616 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2617 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2620 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2622 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2623 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2624 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2628 WIN_ReleaseWndPtr( pWnd );
2630 HeapFree( GetProcessHeap(), 0, win_array );
2632 return TRUE;
2635 /*******************************************************************
2636 * ShowOwnedPopups (USER32.@)
2638 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2640 int count = 0;
2641 WND *pWnd;
2642 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2644 if (!win_array) return TRUE;
2646 while (win_array[count]) count++;
2647 while (--count >= 0)
2649 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2650 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2652 if (pWnd->dwStyle & WS_POPUP)
2654 if (fShow)
2656 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2658 /* In Windows, ShowOwnedPopups(TRUE) generates
2659 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2660 * regardless of the state of the owner
2662 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2663 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2666 else
2668 if (IsWindowVisible(pWnd->hwndSelf))
2670 /* In Windows, ShowOwnedPopups(FALSE) generates
2671 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2672 * regardless of the state of the owner
2674 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2675 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2679 WIN_ReleaseWndPtr( pWnd );
2681 HeapFree( GetProcessHeap(), 0, win_array );
2682 return TRUE;
2686 /*******************************************************************
2687 * GetLastActivePopup (USER32.@)
2689 HWND WINAPI GetLastActivePopup( HWND hwnd )
2691 HWND retval;
2692 WND *wndPtr =WIN_FindWndPtr(hwnd);
2693 if (!wndPtr) return hwnd;
2694 retval = wndPtr->hwndLastActive;
2695 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2696 WIN_ReleaseWndPtr(wndPtr);
2697 return retval;
2701 /*******************************************************************
2702 * WIN_ListParents
2704 * Build an array of all parents of a given window, starting with
2705 * the immediate parent. The array must be freed with HeapFree.
2706 * Returns NULL if window is a top-level window.
2708 HWND *WIN_ListParents( HWND hwnd )
2710 WND *win;
2711 HWND current, *list;
2712 int pos = 0, size = 16, count = 0;
2714 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2716 current = hwnd;
2717 for (;;)
2719 if (!(win = WIN_GetPtr( current ))) goto empty;
2720 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2721 list[pos] = win->parent;
2722 WIN_ReleasePtr( win );
2723 if (!(current = list[pos]))
2725 if (!pos) goto empty;
2726 return list;
2728 if (++pos == size - 1)
2730 /* need to grow the list */
2731 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2732 if (!new_list) goto empty;
2733 list = new_list;
2734 size += 16;
2738 /* at least one parent belongs to another process, have to query the server */
2739 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2741 req->handle = hwnd;
2742 if (!SERVER_CALL())
2744 user_handle_t *data = server_data_ptr(req);
2745 count = server_data_size(req) / sizeof(*data);
2746 if (count)
2748 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0,
2749 list, (count + 1) * sizeof(HWND) );
2750 if (new_list)
2752 list = new_list;
2753 for (pos = 0; pos < count; pos++) list[pos] = data[pos];
2754 list[pos] = 0;
2756 else count = 0;
2760 SERVER_END_VAR_REQ;
2761 if (count) return list;
2763 empty:
2764 HeapFree( GetProcessHeap(), 0, list );
2765 return NULL;
2769 /*******************************************************************
2770 * WIN_ListChildren
2772 * Build an array of the children of a given window. The array must be
2773 * freed with HeapFree. Returns NULL when no windows are found.
2775 HWND *WIN_ListChildren( HWND hwnd )
2777 return list_window_children( hwnd, 0, 0 );
2781 /*******************************************************************
2782 * EnumWindows (USER32.@)
2784 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2786 HWND *list;
2787 BOOL ret = TRUE;
2788 int i, iWndsLocks;
2790 /* We have to build a list of all windows first, to avoid */
2791 /* unpleasant side-effects, for instance if the callback */
2792 /* function changes the Z-order of the windows. */
2794 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2796 /* Now call the callback function for every window */
2798 iWndsLocks = WIN_SuspendWndsLock();
2799 for (i = 0; list[i]; i++)
2801 /* Make sure that the window still exists */
2802 if (!IsWindow( list[i] )) continue;
2803 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2805 WIN_RestoreWndsLock(iWndsLocks);
2806 HeapFree( GetProcessHeap(), 0, list );
2807 return ret;
2811 /**********************************************************************
2812 * EnumTaskWindows16 (USER.225)
2814 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2815 LPARAM lParam )
2817 TDB *tdb = TASK_GetPtr( hTask );
2818 if (!tdb) return FALSE;
2819 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2823 /**********************************************************************
2824 * EnumThreadWindows (USER32.@)
2826 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2828 HWND *list;
2829 int i, iWndsLocks;
2831 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2832 return FALSE;
2834 /* Now call the callback function for every window */
2836 iWndsLocks = WIN_SuspendWndsLock();
2837 for (i = 0; list[i]; i++)
2838 if (!func( list[i], lParam )) break;
2839 WIN_RestoreWndsLock(iWndsLocks);
2840 HeapFree( GetProcessHeap(), 0, list );
2841 return TRUE;
2845 /**********************************************************************
2846 * WIN_EnumChildWindows
2848 * Helper function for EnumChildWindows().
2850 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2852 HWND *childList;
2853 BOOL ret = FALSE;
2855 for ( ; *list; list++)
2857 /* Make sure that the window still exists */
2858 if (!IsWindow( *list )) continue;
2859 /* skip owned windows */
2860 if (GetWindow( *list, GW_OWNER )) continue;
2861 /* Build children list first */
2862 childList = WIN_ListChildren( *list );
2864 ret = func( *list, lParam );
2866 if (childList)
2868 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2869 HeapFree( GetProcessHeap(), 0, childList );
2871 if (!ret) return FALSE;
2873 return TRUE;
2877 /**********************************************************************
2878 * EnumChildWindows (USER32.@)
2880 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2882 HWND *list;
2883 int iWndsLocks;
2885 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2886 iWndsLocks = WIN_SuspendWndsLock();
2887 WIN_EnumChildWindows( list, func, lParam );
2888 WIN_RestoreWndsLock(iWndsLocks);
2889 HeapFree( GetProcessHeap(), 0, list );
2890 return TRUE;
2894 /*******************************************************************
2895 * AnyPopup (USER.52)
2897 BOOL16 WINAPI AnyPopup16(void)
2899 return AnyPopup();
2903 /*******************************************************************
2904 * AnyPopup (USER32.@)
2906 BOOL WINAPI AnyPopup(void)
2908 int i;
2909 BOOL retvalue;
2910 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2912 if (!list) return FALSE;
2913 for (i = 0; list[i]; i++)
2915 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2917 retvalue = (list[i] != 0);
2918 HeapFree( GetProcessHeap(), 0, list );
2919 return retvalue;
2923 /*******************************************************************
2924 * FlashWindow (USER32.@)
2926 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2928 WND *wndPtr = WIN_FindWndPtr(hWnd);
2930 TRACE("%04x\n", hWnd);
2932 if (!wndPtr) return FALSE;
2933 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2935 if (wndPtr->dwStyle & WS_MINIMIZE)
2937 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2939 HDC hDC = GetDC(hWnd);
2941 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2942 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2944 ReleaseDC( hWnd, hDC );
2945 wndPtr->flags |= WIN_NCACTIVATED;
2947 else
2949 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2950 wndPtr->flags &= ~WIN_NCACTIVATED;
2952 WIN_ReleaseWndPtr(wndPtr);
2953 return TRUE;
2955 else
2957 WPARAM16 wparam;
2958 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2959 else wparam = (hWnd == GetActiveWindow());
2961 WIN_ReleaseWndPtr(wndPtr);
2962 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2963 return wparam;
2968 /*******************************************************************
2969 * GetWindowContextHelpId (USER32.@)
2971 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2973 DWORD retval;
2974 WND *wnd = WIN_FindWndPtr( hwnd );
2975 if (!wnd) return 0;
2976 retval = wnd->helpContext;
2977 WIN_ReleaseWndPtr(wnd);
2978 return retval;
2982 /*******************************************************************
2983 * SetWindowContextHelpId (USER32.@)
2985 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2987 WND *wnd = WIN_FindWndPtr( hwnd );
2988 if (!wnd) return FALSE;
2989 wnd->helpContext = id;
2990 WIN_ReleaseWndPtr(wnd);
2991 return TRUE;
2995 /*******************************************************************
2996 * DRAG_QueryUpdate
2998 * recursively find a child that contains spDragInfo->pt point
2999 * and send WM_QUERYDROPOBJECT
3001 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3003 BOOL16 wParam, bResult = 0;
3004 POINT pt;
3005 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3006 RECT tempRect;
3008 if (!ptrDragInfo) return FALSE;
3010 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3012 GetWindowRect(hQueryWnd,&tempRect);
3014 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3016 if (!IsIconic( hQueryWnd ))
3018 GetClientRect( hQueryWnd, &tempRect );
3019 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3021 if (PtInRect( &tempRect, pt))
3023 int i;
3024 HWND *list = WIN_ListChildren( hQueryWnd );
3026 wParam = 0;
3028 if (list)
3030 for (i = 0; list[i]; i++)
3032 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3034 GetWindowRect( list[i], &tempRect );
3035 if (PtInRect( &tempRect, pt )) break;
3038 if (list[i])
3040 if (IsWindowEnabled( list[i] ))
3041 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3043 HeapFree( GetProcessHeap(), 0, list );
3045 if(bResult) return bResult;
3047 else wParam = 1;
3049 else wParam = 1;
3051 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3053 ptrDragInfo->hScope = hQueryWnd;
3055 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3056 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3058 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3060 return bResult;
3064 /*******************************************************************
3065 * DragDetect (USER32.@)
3067 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3069 MSG msg;
3070 RECT rect;
3072 rect.left = pt.x - wDragWidth;
3073 rect.right = pt.x + wDragWidth;
3075 rect.top = pt.y - wDragHeight;
3076 rect.bottom = pt.y + wDragHeight;
3078 SetCapture(hWnd);
3080 while(1)
3082 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3084 if( msg.message == WM_LBUTTONUP )
3086 ReleaseCapture();
3087 return 0;
3089 if( msg.message == WM_MOUSEMOVE )
3091 POINT tmp;
3092 tmp.x = LOWORD(msg.lParam);
3093 tmp.y = HIWORD(msg.lParam);
3094 if( !PtInRect( &rect, tmp ))
3096 ReleaseCapture();
3097 return 1;
3101 WaitMessage();
3103 return 0;
3106 /******************************************************************************
3107 * DragObject (USER.464)
3109 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3110 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3112 MSG msg;
3113 LPDRAGINFO16 lpDragInfo;
3114 SEGPTR spDragInfo;
3115 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3116 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3117 HCURSOR16 hCurrentCursor = 0;
3118 HWND16 hCurrentWnd = 0;
3120 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3121 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3123 if( !lpDragInfo || !spDragInfo ) return 0L;
3125 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3127 GlobalFree16(hDragInfo);
3128 return 0L;
3131 if(hCursor)
3133 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3135 GlobalFree16(hDragInfo);
3136 return 0L;
3139 if( hDragCursor == hCursor ) hDragCursor = 0;
3140 else hCursor = hDragCursor;
3142 hOldCursor = SetCursor(hDragCursor);
3145 lpDragInfo->hWnd = hWnd;
3146 lpDragInfo->hScope = 0;
3147 lpDragInfo->wFlags = wObj;
3148 lpDragInfo->hList = szList; /* near pointer! */
3149 lpDragInfo->hOfStruct = hOfStruct;
3150 lpDragInfo->l = 0L;
3152 SetCapture(hWnd);
3153 ShowCursor( TRUE );
3157 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3159 *(lpDragInfo+1) = *lpDragInfo;
3161 lpDragInfo->pt.x = msg.pt.x;
3162 lpDragInfo->pt.y = msg.pt.y;
3164 /* update DRAGINFO struct */
3165 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3167 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3168 hCurrentCursor = hCursor;
3169 else
3171 hCurrentCursor = hBummer;
3172 lpDragInfo->hScope = 0;
3174 if( hCurrentCursor )
3175 SetCursor(hCurrentCursor);
3177 /* send WM_DRAGLOOP */
3178 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3179 (LPARAM) spDragInfo );
3180 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3181 if( hCurrentWnd != lpDragInfo->hScope )
3183 if( hCurrentWnd )
3184 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3185 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3186 HIWORD(spDragInfo)) );
3187 hCurrentWnd = lpDragInfo->hScope;
3188 if( hCurrentWnd )
3189 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3191 else
3192 if( hCurrentWnd )
3193 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3195 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3197 ReleaseCapture();
3198 ShowCursor( FALSE );
3200 if( hCursor )
3202 SetCursor( hOldCursor );
3203 if (hDragCursor) DestroyCursor( hDragCursor );
3206 if( hCurrentCursor != hBummer )
3207 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3208 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3209 else
3210 msg.lParam = 0;
3211 GlobalFree16(hDragInfo);
3213 return (DWORD)(msg.lParam);
3217 /******************************************************************************
3218 * GetWindowModuleFileNameA (USER32.@)
3220 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3222 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3223 hwnd, lpszFileName, cchFileNameMax);
3224 return 0;
3227 /******************************************************************************
3228 * GetWindowModuleFileNameW (USER32.@)
3230 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3232 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3233 hwnd, lpszFileName, cchFileNameMax);
3234 return 0;