Workaround for SuSE 7 2.2.16 kernel bug.
[wine.git] / windows / win.c
blobfa086472c1b866cf5e4e64c084347a0012d680aa
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/unicode.h"
13 #include "options.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "controls.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "message.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "task.h"
25 #include "thread.h"
26 #include "winerror.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
31 DECLARE_DEBUG_CHANNEL(msg);
33 /**********************************************************************/
35 WND_DRIVER *WND_Driver = NULL;
37 /* Desktop window */
38 static WND *pWndDesktop = NULL;
40 static HWND hwndSysModal = 0;
42 static WORD wDragWidth = 4;
43 static WORD wDragHeight= 3;
45 /* thread safeness */
46 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
48 /***********************************************************************
49 * WIN_LockWnds
51 * Locks access to all WND structures for thread safeness
53 void WIN_LockWnds( void )
55 _EnterSysLevel( &WIN_SysLevel );
58 /***********************************************************************
59 * WIN_UnlockWnds
61 * Unlocks access to all WND structures
63 void WIN_UnlockWnds( void )
65 _LeaveSysLevel( &WIN_SysLevel );
68 /***********************************************************************
69 * WIN_SuspendWndsLock
71 * Suspend the lock on WND structures.
72 * Returns the number of locks suspended
74 int WIN_SuspendWndsLock( void )
76 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
77 int count = isuspendedLocks;
79 while ( count-- > 0 )
80 _LeaveSysLevel( &WIN_SysLevel );
82 return isuspendedLocks;
85 /***********************************************************************
86 * WIN_RestoreWndsLock
88 * Restore the suspended locks on WND structures
90 void WIN_RestoreWndsLock( int ipreviousLocks )
92 while ( ipreviousLocks-- > 0 )
93 _EnterSysLevel( &WIN_SysLevel );
96 /***********************************************************************
97 * WIN_FindWndPtr
99 * Return a pointer to the WND structure corresponding to a HWND.
101 WND * WIN_FindWndPtr( HWND hwnd )
103 WND * ptr;
105 if (!hwnd || HIWORD(hwnd)) goto error2;
106 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
107 /* Lock all WND structures for thread safeness*/
108 WIN_LockWnds();
109 /*and increment destruction monitoring*/
110 ptr->irefCount++;
112 if (ptr->dwMagic != WND_MAGIC) goto error;
113 if (ptr->hwndSelf != hwnd)
115 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
116 goto error;
118 /* returns a locked pointer */
119 return ptr;
120 error:
121 /* Unlock all WND structures for thread safeness*/
122 WIN_UnlockWnds();
123 /* and decrement destruction monitoring value */
124 ptr->irefCount--;
126 error2:
127 if ( hwnd!=0 )
128 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
129 return NULL;
132 /***********************************************************************
133 * WIN_LockWndPtr
135 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
136 * but by initWndPtr;
137 * Returns the locked initialisation pointer
139 WND *WIN_LockWndPtr(WND *initWndPtr)
141 if(!initWndPtr) return 0;
143 /* Lock all WND structures for thread safeness*/
144 WIN_LockWnds();
145 /*and increment destruction monitoring*/
146 initWndPtr->irefCount++;
148 return initWndPtr;
152 /***********************************************************************
153 * WIN_ReleaseWndPtr
155 * Release the pointer to the WND structure.
157 void WIN_ReleaseWndPtr(WND *wndPtr)
159 if(!wndPtr) return;
161 /*Decrement destruction monitoring value*/
162 wndPtr->irefCount--;
163 /* Check if it's time to release the memory*/
164 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
166 /* Release memory */
167 USER_HEAP_FREE( wndPtr->hwndSelf);
168 wndPtr->hwndSelf = 0;
170 else if(wndPtr->irefCount < 0)
172 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
173 ERR("forgot a Lock on %p somewhere\n",wndPtr);
175 /*unlock all WND structures for thread safeness*/
176 WIN_UnlockWnds();
179 /***********************************************************************
180 * WIN_UpdateWndPtr
182 * Updates the value of oldPtr to newPtr.
184 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
186 WND *tmpWnd = NULL;
188 tmpWnd = WIN_LockWndPtr(newPtr);
189 WIN_ReleaseWndPtr(*oldPtr);
190 *oldPtr = tmpWnd;
194 /***********************************************************************
195 * WIN_DumpWindow
197 * Dump the content of a window structure to stderr.
199 void WIN_DumpWindow( HWND hwnd )
201 WND *ptr;
202 char className[80];
203 int i;
205 if (!(ptr = WIN_FindWndPtr( hwnd )))
207 WARN("%04x is not a window handle\n", hwnd );
208 return;
211 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
212 strcpy( className, "#NULL#" );
214 TRACE("Window %04x (%p):\n", hwnd, ptr );
215 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
216 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
217 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
218 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
219 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
220 ptr->next, ptr->child, ptr->parent, ptr->owner,
221 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
222 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
223 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
224 ptr->text ? debugstr_w(ptr->text) : "",
225 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
226 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
227 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
228 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
230 if (ptr->cbWndExtra)
232 DPRINTF( "extra bytes:" );
233 for (i = 0; i < ptr->cbWndExtra; i++)
234 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
235 DPRINTF( "\n" );
237 DPRINTF( "\n" );
238 WIN_ReleaseWndPtr(ptr);
242 /***********************************************************************
243 * WIN_WalkWindows
245 * Walk the windows tree and print each window on stderr.
247 void WIN_WalkWindows( HWND hwnd, int indent )
249 WND *ptr;
250 char className[80];
252 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
254 if (!ptr)
256 WARN("Invalid window handle %04x\n", hwnd );
257 return;
260 if (!indent) /* first time around */
261 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
262 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
263 " Text");
265 while (ptr)
267 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
269 GetClassNameA( hwnd, className, sizeof(className) );
270 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
271 (DWORD)ptr, ptr->hmemTaskQ, className,
272 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
273 ptr->text ? debugstr_w(ptr->text) : "<null>");
275 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
276 WIN_UpdateWndPtr(&ptr,ptr->next);
282 /***********************************************************************
283 * WIN_UnlinkWindow
285 * Remove a window from the siblings linked list.
287 BOOL WIN_UnlinkWindow( HWND hwnd )
289 WND *wndPtr, **ppWnd;
290 BOOL ret = FALSE;
292 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
293 else if(!wndPtr->parent)
295 WIN_ReleaseWndPtr(wndPtr);
296 return FALSE;
299 ppWnd = &wndPtr->parent->child;
300 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
301 if (*ppWnd)
303 *ppWnd = wndPtr->next;
304 ret = TRUE;
306 WIN_ReleaseWndPtr(wndPtr);
307 return ret;
311 /***********************************************************************
312 * WIN_LinkWindow
314 * Insert a window into the siblings linked list.
315 * The window is inserted after the specified window, which can also
316 * be specified as HWND_TOP or HWND_BOTTOM.
318 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
320 WND *wndPtr, **ppWnd;
322 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
323 else if(!wndPtr->parent)
325 WIN_ReleaseWndPtr(wndPtr);
326 return FALSE;
328 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
330 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
331 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
332 while (*ppWnd) ppWnd = &(*ppWnd)->next;
334 else /* Normal case */
336 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
337 if (!afterPtr)
339 WIN_ReleaseWndPtr(wndPtr);
340 return FALSE;
342 ppWnd = &afterPtr->next;
343 WIN_ReleaseWndPtr(afterPtr);
345 wndPtr->next = *ppWnd;
346 *ppWnd = wndPtr;
347 WIN_ReleaseWndPtr(wndPtr);
348 return TRUE;
352 /***********************************************************************
353 * WIN_FindWinToRepaint
355 * Find a window that needs repaint.
357 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
359 HWND hwndRet;
360 WND *pWnd;
362 /* Note: the desktop window never gets WM_PAINT messages
363 * The real reason why is because Windows DesktopWndProc
364 * does ValidateRgn inside WM_ERASEBKGND handler.
367 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
369 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
371 if (!(pWnd->dwStyle & WS_VISIBLE))
373 TRACE("skipping window %04x\n",
374 pWnd->hwndSelf );
376 else if ((pWnd->hmemTaskQ == hQueue) &&
377 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
378 break;
380 else if (pWnd->child )
381 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
383 WIN_ReleaseWndPtr(pWnd);
384 return hwndRet;
389 if(!pWnd)
391 return 0;
394 hwndRet = pWnd->hwndSelf;
396 /* look among siblings if we got a transparent window */
397 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
398 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
400 WIN_UpdateWndPtr(&pWnd,pWnd->next);
402 if (pWnd)
404 hwndRet = pWnd->hwndSelf;
405 WIN_ReleaseWndPtr(pWnd);
407 TRACE("found %04x\n",hwndRet);
408 return hwndRet;
412 /***********************************************************************
413 * WIN_DestroyWindow
415 * Destroy storage associated to a window. "Internals" p.358
416 * returns a locked wndPtr->next
418 static WND* WIN_DestroyWindow( WND* wndPtr )
420 HWND hwnd = wndPtr->hwndSelf;
421 WND *pWnd;
423 TRACE("%04x\n", wndPtr->hwndSelf );
425 /* free child windows */
426 WIN_LockWndPtr(wndPtr->child);
427 while ((pWnd = wndPtr->child))
429 wndPtr->child = WIN_DestroyWindow( pWnd );
430 WIN_ReleaseWndPtr(pWnd);
434 * Clear the update region to make sure no WM_PAINT messages will be
435 * generated for this window while processing the WM_NCDESTROY.
437 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
439 if (wndPtr->hrgnUpdate > 1)
440 DeleteObject( wndPtr->hrgnUpdate );
442 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
444 wndPtr->hrgnUpdate = 0;
448 * Send the WM_NCDESTROY to the window being destroyed.
450 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
452 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
454 WINPOS_CheckInternalPos( wndPtr );
455 if( hwnd == GetCapture()) ReleaseCapture();
457 /* free resources associated with the window */
459 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
460 PROPERTY_RemoveWindowProps( wndPtr );
462 wndPtr->dwMagic = 0; /* Mark it as invalid */
464 /* toss stale messages from the queue */
466 if( wndPtr->hmemTaskQ )
468 BOOL bPostQuit = FALSE;
469 WPARAM wQuitParam = 0;
470 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
471 QMSG *qmsg;
473 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
475 if( qmsg->msg.message == WM_QUIT )
477 bPostQuit = TRUE;
478 wQuitParam = qmsg->msg.wParam;
480 QUEUE_RemoveMsg(msgQ, qmsg);
483 QUEUE_Unlock(msgQ);
485 /* repost WM_QUIT to make sure this app exits its message loop */
486 if( bPostQuit ) PostQuitMessage(wQuitParam);
487 wndPtr->hmemTaskQ = 0;
490 if (!(wndPtr->dwStyle & WS_CHILD))
491 if (wndPtr->wIDmenu)
493 DestroyMenu( wndPtr->wIDmenu );
494 wndPtr->wIDmenu = 0;
496 if (wndPtr->hSysMenu)
498 DestroyMenu( wndPtr->hSysMenu );
499 wndPtr->hSysMenu = 0;
501 wndPtr->pDriver->pDestroyWindow( wndPtr );
502 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
503 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
504 CLASS_RemoveWindow( wndPtr->class );
505 wndPtr->class = NULL;
507 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
509 wndPtr->pDriver->pFinalize(wndPtr);
511 return pWnd;
514 /***********************************************************************
515 * WIN_ResetQueueWindows
517 * Reset the queue of all the children of a given window.
518 * Return TRUE if something was done.
520 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
522 BOOL ret = FALSE;
524 if (hNew) /* Set a new queue */
526 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
528 if (wnd->hmemTaskQ == hQueue)
530 wnd->hmemTaskQ = hNew;
531 ret = TRUE;
533 if (wnd->child)
535 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
539 else /* Queue is being destroyed */
541 while (wnd->child)
543 WND *tmp = WIN_LockWndPtr(wnd->child);
544 WND *tmp2;
545 ret = FALSE;
546 while (tmp)
548 if (tmp->hmemTaskQ == hQueue)
550 DestroyWindow( tmp->hwndSelf );
551 ret = TRUE;
552 break;
554 tmp2 = WIN_LockWndPtr(tmp->child);
555 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
556 ret = TRUE;
557 else
559 WIN_UpdateWndPtr(&tmp,tmp->next);
561 WIN_ReleaseWndPtr(tmp2);
563 WIN_ReleaseWndPtr(tmp);
564 if (!ret) break;
567 return ret;
570 /***********************************************************************
571 * WIN_CreateDesktopWindow
573 * Create the desktop window.
575 BOOL WIN_CreateDesktopWindow(void)
577 struct tagCLASS *class;
578 HWND hwndDesktop;
579 INT wndExtra;
580 DWORD clsStyle;
581 WNDPROC winproc;
582 DCE *dce;
584 TRACE("Creating desktop window\n");
587 if (!WINPOS_CreateInternalPosAtom() ||
588 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
589 &wndExtra, &winproc, &clsStyle, &dce )))
590 return FALSE;
592 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
593 if (!hwndDesktop) return FALSE;
594 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
596 pWndDesktop->pDriver = WND_Driver;
597 pWndDesktop->pDriver->pInitialize(pWndDesktop);
599 pWndDesktop->next = NULL;
600 pWndDesktop->child = NULL;
601 pWndDesktop->parent = NULL;
602 pWndDesktop->owner = NULL;
603 pWndDesktop->class = class;
604 pWndDesktop->dwMagic = WND_MAGIC;
605 pWndDesktop->hwndSelf = hwndDesktop;
606 pWndDesktop->hInstance = 0;
607 pWndDesktop->rectWindow.left = 0;
608 pWndDesktop->rectWindow.top = 0;
609 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
610 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
611 pWndDesktop->rectClient = pWndDesktop->rectWindow;
612 pWndDesktop->text = NULL;
613 pWndDesktop->hmemTaskQ = GetFastQueue16();
614 pWndDesktop->hrgnUpdate = 0;
615 pWndDesktop->hwndLastActive = hwndDesktop;
616 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
617 WS_CLIPSIBLINGS;
618 pWndDesktop->dwExStyle = 0;
619 pWndDesktop->clsStyle = clsStyle;
620 pWndDesktop->dce = NULL;
621 pWndDesktop->pVScroll = NULL;
622 pWndDesktop->pHScroll = NULL;
623 pWndDesktop->pProp = NULL;
624 pWndDesktop->wIDmenu = 0;
625 pWndDesktop->helpContext = 0;
626 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
627 pWndDesktop->hSysMenu = 0;
628 pWndDesktop->userdata = 0;
629 pWndDesktop->winproc = winproc;
630 pWndDesktop->cbWndExtra = wndExtra;
631 pWndDesktop->irefCount = 0;
633 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop)) return FALSE;
635 SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
636 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
637 return TRUE;
641 /***********************************************************************
642 * WIN_FixCoordinates
644 * Fix the coordinates - Helper for WIN_CreateWindowEx.
645 * returns default show mode in sw.
646 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
648 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
650 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
651 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
653 if (cs->style & (WS_CHILD | WS_POPUP))
655 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
656 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
658 else /* overlapped window */
660 STARTUPINFOA info;
662 GetStartupInfoA( &info );
664 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
666 /* Never believe Microsoft's documentation... CreateWindowEx doc says
667 * that if an overlapped window is created with WS_VISIBLE style bit
668 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
669 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
670 * reveals that
672 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
673 * 2) it does not ignore the y parameter as the docs claim; instead, it
674 * uses it as second parameter to ShowWindow() unless y is either
675 * CW_USEDEFAULT or CW_USEDEFAULT16.
677 * The fact that we didn't do 2) caused bogus windows pop up when wine
678 * was running apps that were using this obscure feature. Example -
679 * calc.exe that comes with Win98 (only Win98, it's different from
680 * the one that comes with Win95 and NT)
682 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
683 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
684 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
687 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
689 if (info.dwFlags & STARTF_USESIZE)
691 cs->cx = info.dwXSize;
692 cs->cy = info.dwYSize;
694 else /* if no other hint from the app, pick 3/4 of the screen real estate */
696 RECT r;
697 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
698 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
699 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
706 /***********************************************************************
707 * WIN_CreateWindowEx
709 * Implementation of CreateWindowEx().
711 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
712 WINDOWPROCTYPE type )
714 INT sw = SW_SHOW;
715 struct tagCLASS *classPtr;
716 WND *wndPtr;
717 HWND retvalue;
718 HWND16 hwnd, hwndLinkAfter;
719 POINT maxSize, maxPos, minTrack, maxTrack;
720 INT wndExtra;
721 DWORD clsStyle;
722 WNDPROC winproc;
723 DCE *dce;
724 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
726 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
727 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
728 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
729 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
730 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
732 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
733 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
735 /* Find the parent window */
737 if (cs->hwndParent)
739 /* Make sure parent is valid */
740 if (!IsWindow( cs->hwndParent ))
742 WARN("Bad parent %04x\n", cs->hwndParent );
743 return 0;
745 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
746 WARN("No parent for child window\n" );
747 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
750 /* Find the window class */
751 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
752 &wndExtra, &winproc, &clsStyle, &dce )))
754 WARN("Bad class '%s'\n", cs->lpszClass );
755 return 0;
758 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
760 /* Create the window structure */
762 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
764 TRACE("out of memory\n" );
765 return 0;
768 /* Fill the window structure */
770 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
771 wndPtr->next = NULL;
772 wndPtr->child = NULL;
774 if ((cs->style & WS_CHILD) && cs->hwndParent)
776 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
777 wndPtr->owner = NULL;
778 WIN_ReleaseWndPtr(wndPtr->parent);
780 else
782 wndPtr->parent = pWndDesktop;
783 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
784 wndPtr->owner = NULL;
785 else
787 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
788 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
789 WIN_ReleaseWndPtr(wndPtr->owner);
790 WIN_ReleaseWndPtr(tmpWnd);
795 wndPtr->pDriver = wndPtr->parent->pDriver;
796 wndPtr->pDriver->pInitialize(wndPtr);
798 wndPtr->class = classPtr;
799 wndPtr->winproc = winproc;
800 wndPtr->dwMagic = WND_MAGIC;
801 wndPtr->hwndSelf = hwnd;
802 wndPtr->hInstance = cs->hInstance;
803 wndPtr->text = NULL;
804 wndPtr->hmemTaskQ = GetFastQueue16();
805 wndPtr->hrgnUpdate = 0;
806 wndPtr->hrgnWnd = 0;
807 wndPtr->hwndLastActive = hwnd;
808 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
809 wndPtr->dwExStyle = cs->dwExStyle;
810 wndPtr->clsStyle = clsStyle;
811 wndPtr->wIDmenu = 0;
812 wndPtr->helpContext = 0;
813 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
814 wndPtr->pVScroll = NULL;
815 wndPtr->pHScroll = NULL;
816 wndPtr->pProp = NULL;
817 wndPtr->userdata = 0;
818 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
819 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
820 wndPtr->cbWndExtra = wndExtra;
821 wndPtr->irefCount = 1;
823 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
825 /* Call the WH_CBT hook */
827 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
828 ? HWND_BOTTOM : HWND_TOP;
830 if (HOOK_IsHooked( WH_CBT ))
832 CBT_CREATEWNDA cbtc;
833 LRESULT ret;
835 cbtc.lpcs = cs;
836 cbtc.hwndInsertAfter = hwndLinkAfter;
837 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
838 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
839 if (ret)
841 TRACE("CBT-hook returned 0\n");
842 wndPtr->pDriver->pFinalize(wndPtr);
843 USER_HEAP_FREE( hwnd );
844 CLASS_RemoveWindow( classPtr );
845 retvalue = 0;
846 goto end;
850 /* Correct the window style */
852 if (!(cs->style & WS_CHILD))
854 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
855 if (!(cs->style & WS_POPUP))
857 wndPtr->dwStyle |= WS_CAPTION;
858 wndPtr->flags |= WIN_NEED_SIZE;
862 /* Get class or window DC if needed */
864 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
865 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
866 else wndPtr->dce = NULL;
868 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
870 wndPtr->rectWindow.left = cs->x;
871 wndPtr->rectWindow.top = cs->y;
872 wndPtr->rectWindow.right = cs->x + cs->cx;
873 wndPtr->rectWindow.bottom = cs->y + cs->cy;
874 wndPtr->rectClient = wndPtr->rectWindow;
876 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
878 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
880 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
881 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
882 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
883 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
884 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
887 if (cs->cx < 0) cs->cx = 0;
888 if (cs->cy < 0) cs->cy = 0;
890 wndPtr->rectWindow.left = cs->x;
891 wndPtr->rectWindow.top = cs->y;
892 wndPtr->rectWindow.right = cs->x + cs->cx;
893 wndPtr->rectWindow.bottom = cs->y + cs->cy;
894 wndPtr->rectClient = wndPtr->rectWindow;
896 if(!wndPtr->pDriver->pCreateWindow(wndPtr, cs, type == WIN_PROC_32W))
898 retvalue = FALSE;
899 goto end;
902 /* Set the window menu */
904 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
906 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
907 else
909 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
910 if (menuName)
912 if (HIWORD(cs->hInstance))
913 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
914 else
915 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
917 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
921 else wndPtr->wIDmenu = (UINT)cs->hMenu;
923 /* Send the WM_CREATE message
924 * Perhaps we shouldn't allow width/height changes as well.
925 * See p327 in "Internals".
928 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
930 localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
931 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
933 /* Insert the window in the linked list */
935 WIN_LinkWindow( hwnd, hwndLinkAfter );
937 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
938 NULL, NULL, 0, &wndPtr->rectClient );
939 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
940 maxPos.y - wndPtr->rectWindow.top);
941 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
943 /* Send the size messages */
945 if (!(wndPtr->flags & WIN_NEED_SIZE))
947 /* send it anyway */
948 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
949 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
950 WARN("sending bogus WM_SIZE message 0x%08lx\n",
951 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
952 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
953 (*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
954 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
955 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
956 (*localSend32)( hwnd, WM_MOVE, 0,
957 MAKELONG( wndPtr->rectClient.left,
958 wndPtr->rectClient.top ) );
961 /* Show the window, maximizing or minimizing if needed */
963 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
965 RECT16 newPos;
966 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
967 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
968 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
969 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
970 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
971 : SWP_NOZORDER | SWP_FRAMECHANGED;
972 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
973 newPos.right, newPos.bottom, swFlag );
976 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
978 /* Notify the parent window only */
980 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
981 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
982 if( !IsWindow(hwnd) )
984 retvalue = 0;
985 goto end;
989 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
991 /* Call WH_SHELL hook */
993 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
994 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
996 TRACE("created window %04x\n", hwnd);
997 retvalue = hwnd;
998 goto end;
1000 WIN_UnlinkWindow( hwnd );
1003 /* Abort window creation */
1005 WARN("aborted by WM_xxCREATE!\n");
1006 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1007 CLASS_RemoveWindow( classPtr );
1008 retvalue = 0;
1009 end:
1010 WIN_ReleaseWndPtr(wndPtr);
1012 return retvalue;
1016 /***********************************************************************
1017 * CreateWindow (USER.41)
1019 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1020 DWORD style, INT16 x, INT16 y, INT16 width,
1021 INT16 height, HWND16 parent, HMENU16 menu,
1022 HINSTANCE16 instance, LPVOID data )
1024 return CreateWindowEx16( 0, className, windowName, style,
1025 x, y, width, height, parent, menu, instance, data );
1029 /***********************************************************************
1030 * CreateWindowEx (USER.452)
1032 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1033 LPCSTR windowName, DWORD style, INT16 x,
1034 INT16 y, INT16 width, INT16 height,
1035 HWND16 parent, HMENU16 menu,
1036 HINSTANCE16 instance, LPVOID data )
1038 ATOM classAtom;
1039 CREATESTRUCTA cs;
1040 char buffer[256];
1042 /* Find the class atom */
1044 if (HIWORD(className))
1046 if (!(classAtom = GlobalFindAtomA( className )))
1048 ERR( "bad class name %s\n", debugres_a(className) );
1049 return 0;
1052 else
1054 classAtom = LOWORD(className);
1055 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1057 ERR( "bad atom %x\n", classAtom);
1058 return 0;
1060 className = buffer;
1063 /* Fix the coordinates */
1065 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1066 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1067 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1068 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1070 /* Create the window */
1072 cs.lpCreateParams = data;
1073 cs.hInstance = (HINSTANCE)instance;
1074 cs.hMenu = (HMENU)menu;
1075 cs.hwndParent = (HWND)parent;
1076 cs.style = style;
1077 cs.lpszName = windowName;
1078 cs.lpszClass = className;
1079 cs.dwExStyle = exStyle;
1081 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1085 /***********************************************************************
1086 * CreateWindowExA (USER32.@)
1088 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1089 LPCSTR windowName, DWORD style, INT x,
1090 INT y, INT width, INT height,
1091 HWND parent, HMENU menu,
1092 HINSTANCE instance, LPVOID data )
1094 ATOM classAtom;
1095 CREATESTRUCTA cs;
1096 char buffer[256];
1098 if(!instance)
1099 instance=GetModuleHandleA(NULL);
1101 if(exStyle & WS_EX_MDICHILD)
1102 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1104 /* Find the class atom */
1106 if (HIWORD(className))
1108 if (!(classAtom = GlobalFindAtomA( className )))
1110 ERR( "bad class name %s\n", debugres_a(className) );
1111 return 0;
1114 else
1116 classAtom = LOWORD(className);
1117 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1119 ERR( "bad atom %x\n", classAtom);
1120 return 0;
1122 className = buffer;
1125 /* Create the window */
1127 cs.lpCreateParams = data;
1128 cs.hInstance = instance;
1129 cs.hMenu = menu;
1130 cs.hwndParent = parent;
1131 cs.x = x;
1132 cs.y = y;
1133 cs.cx = width;
1134 cs.cy = height;
1135 cs.style = style;
1136 cs.lpszName = windowName;
1137 cs.lpszClass = className;
1138 cs.dwExStyle = exStyle;
1140 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1144 /***********************************************************************
1145 * CreateWindowExW (USER32.@)
1147 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1148 LPCWSTR windowName, DWORD style, INT x,
1149 INT y, INT width, INT height,
1150 HWND parent, HMENU menu,
1151 HINSTANCE instance, LPVOID data )
1153 ATOM classAtom;
1154 CREATESTRUCTW cs;
1155 WCHAR buffer[256];
1157 if(!instance)
1158 instance=GetModuleHandleA(NULL);
1160 if(exStyle & WS_EX_MDICHILD)
1161 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1163 /* Find the class atom */
1165 if (HIWORD(className))
1167 if (!(classAtom = GlobalFindAtomW( className )))
1169 ERR( "bad class name %s\n", debugres_w(className) );
1170 return 0;
1173 else
1175 classAtom = LOWORD(className);
1176 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1178 ERR( "bad atom %x\n", classAtom);
1179 return 0;
1181 className = buffer;
1184 /* Create the window */
1186 cs.lpCreateParams = data;
1187 cs.hInstance = instance;
1188 cs.hMenu = menu;
1189 cs.hwndParent = parent;
1190 cs.x = x;
1191 cs.y = y;
1192 cs.cx = width;
1193 cs.cy = height;
1194 cs.style = style;
1195 cs.lpszName = windowName;
1196 cs.lpszClass = className;
1197 cs.dwExStyle = exStyle;
1199 /* Note: we rely on the fact that CREATESTRUCTA and */
1200 /* CREATESTRUCTW have the same layout. */
1201 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1204 /***********************************************************************
1205 * WIN_SendDestroyMsg
1207 static void WIN_SendDestroyMsg( WND* pWnd )
1209 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1210 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1213 * Send the WM_DESTROY to the window.
1215 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1218 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1219 * make sure that the window still exists when we come back.
1221 if (IsWindow(pWnd->hwndSelf))
1223 HWND* pWndArray = NULL;
1224 WND* pChild = NULL;
1225 int nKidCount = 0;
1228 * Now, if the window has kids, we have to send WM_DESTROY messages
1229 * recursively to it's kids. It seems that those calls can also
1230 * trigger re-entrant calls to DestroyWindow for the kids so we must
1231 * protect against corruption of the list of siblings. We first build
1232 * a list of HWNDs representing all the kids.
1234 pChild = WIN_LockWndPtr(pWnd->child);
1235 while( pChild )
1237 nKidCount++;
1238 WIN_UpdateWndPtr(&pChild,pChild->next);
1242 * If there are no kids, we're done.
1244 if (nKidCount==0)
1245 return;
1247 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1250 * Sanity check
1252 if (pWndArray==NULL)
1253 return;
1256 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1257 * call, our linked list of siblings should be safe.
1259 nKidCount = 0;
1260 pChild = WIN_LockWndPtr(pWnd->child);
1261 while( pChild )
1263 pWndArray[nKidCount] = pChild->hwndSelf;
1264 nKidCount++;
1265 WIN_UpdateWndPtr(&pChild,pChild->next);
1269 * Now that we have a list, go through that list again and send the destroy
1270 * message to those windows. We are using the HWND to retrieve the
1271 * WND pointer so we are effectively checking that all the kid windows are
1272 * still valid before sending the message.
1274 while (nKidCount>0)
1276 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1278 if (pChild!=NULL)
1280 WIN_SendDestroyMsg( pChild );
1281 WIN_ReleaseWndPtr(pChild);
1286 * Cleanup
1288 HeapFree(GetProcessHeap(), 0, pWndArray);
1290 else
1291 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1295 /***********************************************************************
1296 * DestroyWindow (USER.53)
1298 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1300 return DestroyWindow(hwnd);
1304 /***********************************************************************
1305 * DestroyWindow (USER32.@)
1307 BOOL WINAPI DestroyWindow( HWND hwnd )
1309 WND * wndPtr;
1310 BOOL retvalue;
1311 HWND h;
1312 BOOL bFocusSet = FALSE;
1314 TRACE("(%04x)\n", hwnd);
1316 /* Initialization */
1318 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1319 if (wndPtr == pWndDesktop)
1321 retvalue = FALSE; /* Can't destroy desktop */
1322 goto end;
1325 /* Look whether the focus is within the tree of windows we will
1326 * be destroying.
1328 h = GetFocus16();
1329 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1331 if (h == hwnd)
1333 SetFocus(GetWindowLongA(hwnd,GWL_HWNDPARENT));
1334 bFocusSet = TRUE;
1335 break;
1337 h = GetWindowLongA(h,GWL_HWNDPARENT);
1339 /* If the focus is on the window we will destroy and it has no parent,
1340 * set the focus to 0.
1342 if (! bFocusSet && (h == hwnd))
1344 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1345 SetFocus(0);
1348 /* Call hooks */
1350 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1352 retvalue = FALSE;
1353 goto end;
1356 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1358 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1359 /* FIXME: clean up palette - see "Internals" p.352 */
1362 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1363 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1365 /* Notify the parent window only */
1366 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1367 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1368 if( !IsWindow(hwnd) )
1370 retvalue = TRUE;
1371 goto end;
1375 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1377 /* Hide the window */
1379 if (wndPtr->dwStyle & WS_VISIBLE)
1381 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1382 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1383 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1384 if (!IsWindow(hwnd))
1386 retvalue = TRUE;
1387 goto end;
1391 /* Recursively destroy owned windows */
1393 if( !(wndPtr->dwStyle & WS_CHILD) )
1395 /* make sure top menu popup doesn't get destroyed */
1396 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1398 for (;;)
1400 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1401 while (siblingPtr)
1403 if (siblingPtr->owner == wndPtr)
1405 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1406 break;
1407 else
1408 siblingPtr->owner = NULL;
1410 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1412 if (siblingPtr)
1414 DestroyWindow( siblingPtr->hwndSelf );
1415 WIN_ReleaseWndPtr(siblingPtr);
1417 else break;
1420 if( !Options.managed || EVENT_CheckFocus() )
1421 WINPOS_ActivateOtherWindow(wndPtr);
1423 if( wndPtr->owner &&
1424 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1425 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1428 /* Send destroy messages */
1430 WIN_SendDestroyMsg( wndPtr );
1431 if (!IsWindow(hwnd))
1433 retvalue = TRUE;
1434 goto end;
1437 /* Unlink now so we won't bother with the children later on */
1439 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1441 /* Destroy the window storage */
1443 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1444 retvalue = TRUE;
1445 end:
1446 WIN_ReleaseWndPtr(wndPtr);
1447 return retvalue;
1451 /***********************************************************************
1452 * CloseWindow (USER.43)
1454 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1456 return CloseWindow( hwnd );
1460 /***********************************************************************
1461 * CloseWindow (USER32.@)
1463 BOOL WINAPI CloseWindow( HWND hwnd )
1465 WND * wndPtr = WIN_FindWndPtr( hwnd );
1466 BOOL retvalue;
1468 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1470 retvalue = FALSE;
1471 goto end;
1473 ShowWindow( hwnd, SW_MINIMIZE );
1474 retvalue = TRUE;
1475 end:
1476 WIN_ReleaseWndPtr(wndPtr);
1477 return retvalue;
1482 /***********************************************************************
1483 * OpenIcon (USER.44)
1485 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1487 return OpenIcon( hwnd );
1491 /***********************************************************************
1492 * OpenIcon (USER32.@)
1494 BOOL WINAPI OpenIcon( HWND hwnd )
1496 if (!IsIconic( hwnd )) return FALSE;
1497 ShowWindow( hwnd, SW_SHOWNORMAL );
1498 return TRUE;
1502 /***********************************************************************
1503 * WIN_FindWindow
1505 * Implementation of FindWindow() and FindWindowEx().
1507 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1508 LPCWSTR title )
1510 WND *pWnd;
1511 HWND retvalue;
1513 if (child)
1515 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1516 if (parent)
1518 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1520 retvalue = 0;
1521 goto end;
1524 else if (pWnd->parent != pWndDesktop)
1526 retvalue = 0;
1527 goto end;
1529 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1531 else
1533 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1535 retvalue = 0;
1536 goto end;
1538 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1540 if (!pWnd)
1542 retvalue = 0;
1543 goto end;
1546 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1548 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1549 continue; /* Not the right class */
1551 /* Now check the title */
1553 if (!title)
1555 retvalue = pWnd->hwndSelf;
1556 goto end;
1558 if (pWnd->text && !strcmpW( pWnd->text, title ))
1560 retvalue = pWnd->hwndSelf;
1561 goto end;
1564 retvalue = 0;
1565 /* In this case we need to check whether other processes
1566 own a window with the given paramters on the Desktop,
1567 but we don't, so let's at least warn about it */
1568 FIXME("Returning 0 without checking other processes\n");
1569 end:
1570 WIN_ReleaseWndPtr(pWnd);
1571 return retvalue;
1576 /***********************************************************************
1577 * FindWindow (USER.50)
1579 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1581 return FindWindowA( className, title );
1585 /***********************************************************************
1586 * FindWindowEx (USER.427)
1588 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1590 return FindWindowExA( parent, child, className, title );
1594 /***********************************************************************
1595 * FindWindowA (USER32.@)
1597 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1599 HWND ret = FindWindowExA( 0, 0, className, title );
1600 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1601 return ret;
1605 /***********************************************************************
1606 * FindWindowExA (USER32.@)
1608 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1609 LPCSTR className, LPCSTR title )
1611 ATOM atom = 0;
1612 LPWSTR buffer;
1613 HWND hwnd;
1615 if (className)
1617 /* If the atom doesn't exist, then no class */
1618 /* with this name exists either. */
1619 if (!(atom = GlobalFindAtomA( className )))
1621 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1622 return 0;
1626 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1627 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1628 HeapFree( GetProcessHeap(), 0, buffer );
1629 return hwnd;
1633 /***********************************************************************
1634 * FindWindowExW (USER32.@)
1636 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1637 LPCWSTR className, LPCWSTR title )
1639 ATOM atom = 0;
1641 if (className)
1643 /* If the atom doesn't exist, then no class */
1644 /* with this name exists either. */
1645 if (!(atom = GlobalFindAtomW( className )))
1647 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1648 return 0;
1651 return WIN_FindWindow( parent, child, atom, title );
1655 /***********************************************************************
1656 * FindWindowW (USER32.@)
1658 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1660 return FindWindowExW( 0, 0, className, title );
1664 /**********************************************************************
1665 * WIN_GetDesktop
1666 * returns a locked pointer
1668 WND *WIN_GetDesktop(void)
1670 return WIN_LockWndPtr(pWndDesktop);
1672 /**********************************************************************
1673 * WIN_ReleaseDesktop
1674 * unlock the desktop pointer
1676 void WIN_ReleaseDesktop(void)
1678 WIN_ReleaseWndPtr(pWndDesktop);
1682 /**********************************************************************
1683 * GetDesktopWindow (USER.286)
1685 HWND16 WINAPI GetDesktopWindow16(void)
1687 return (HWND16)pWndDesktop->hwndSelf;
1691 /**********************************************************************
1692 * GetDesktopWindow (USER32.@)
1694 HWND WINAPI GetDesktopWindow(void)
1696 if (pWndDesktop) return pWndDesktop->hwndSelf;
1697 ERR( "You need the -desktop option when running with native USER\n" );
1698 ExitProcess(1);
1699 return 0;
1703 /**********************************************************************
1704 * GetDesktopHwnd (USER.278)
1706 * Exactly the same thing as GetDesktopWindow(), but not documented.
1707 * Don't ask me why...
1709 HWND16 WINAPI GetDesktopHwnd16(void)
1711 return (HWND16)pWndDesktop->hwndSelf;
1715 /*******************************************************************
1716 * EnableWindow (USER.34)
1718 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1720 return EnableWindow( hwnd, enable );
1724 /*******************************************************************
1725 * EnableWindow (USER32.@)
1727 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1729 WND *wndPtr;
1730 BOOL retvalue;
1732 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1734 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1735 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1737 /* Enable window */
1738 wndPtr->dwStyle &= ~WS_DISABLED;
1740 if( wndPtr->flags & WIN_NATIVE )
1741 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1743 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1744 retvalue = TRUE;
1745 goto end;
1747 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1749 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1751 /* Disable window */
1752 wndPtr->dwStyle |= WS_DISABLED;
1754 if( wndPtr->flags & WIN_NATIVE )
1755 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1757 if (hwnd == GetFocus())
1759 SetFocus( 0 ); /* A disabled window can't have the focus */
1761 if (hwnd == GetCapture())
1763 ReleaseCapture(); /* A disabled window can't capture the mouse */
1765 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1766 retvalue = FALSE;
1767 goto end;
1769 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1770 end:
1771 WIN_ReleaseWndPtr(wndPtr);
1772 return retvalue;
1776 /***********************************************************************
1777 * IsWindowEnabled (USER.35)
1779 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1781 return IsWindowEnabled(hWnd);
1785 /***********************************************************************
1786 * IsWindowEnabled (USER32.@)
1788 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1790 WND * wndPtr;
1791 BOOL retvalue;
1793 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1794 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1795 WIN_ReleaseWndPtr(wndPtr);
1796 return retvalue;
1801 /***********************************************************************
1802 * IsWindowUnicode (USER32.@)
1804 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1806 WND * wndPtr;
1807 BOOL retvalue;
1809 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1810 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1811 WIN_ReleaseWndPtr(wndPtr);
1812 return retvalue;
1816 /**********************************************************************
1817 * GetWindowWord (USER.133)
1819 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1821 return GetWindowWord( hwnd, offset );
1825 /**********************************************************************
1826 * GetWindowWord (USER32.@)
1828 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1830 WORD retvalue;
1831 WND * wndPtr = WIN_FindWndPtr( hwnd );
1832 if (!wndPtr) return 0;
1833 if (offset >= 0)
1835 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1837 WARN("Invalid offset %d\n", offset );
1838 retvalue = 0;
1839 goto end;
1841 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1842 goto end;
1844 switch(offset)
1846 case GWW_ID:
1847 if (HIWORD(wndPtr->wIDmenu))
1848 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1849 wndPtr->wIDmenu);
1850 retvalue = (WORD)wndPtr->wIDmenu;
1851 goto end;
1852 case GWW_HWNDPARENT:
1853 retvalue = GetParent(hwnd);
1854 goto end;
1855 case GWW_HINSTANCE:
1856 if (HIWORD(wndPtr->hInstance))
1857 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1858 wndPtr->hInstance);
1859 retvalue = (WORD)wndPtr->hInstance;
1860 goto end;
1861 default:
1862 WARN("Invalid offset %d\n", offset );
1863 retvalue = 0;
1864 goto end;
1866 end:
1867 WIN_ReleaseWndPtr(wndPtr);
1868 return retvalue;
1871 /**********************************************************************
1872 * SetWindowWord (USER.134)
1874 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1876 return SetWindowWord( hwnd, offset, newval );
1880 /**********************************************************************
1881 * SetWindowWord (USER32.@)
1883 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1885 WORD *ptr, retval;
1886 WND * wndPtr = WIN_FindWndPtr( hwnd );
1887 if (!wndPtr) return 0;
1888 if (offset >= 0)
1890 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1892 WARN("Invalid offset %d\n", offset );
1893 retval = 0;
1894 goto end;
1896 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1898 else switch(offset)
1900 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1901 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1902 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1903 goto end;
1904 default:
1905 WARN("Invalid offset %d\n", offset );
1906 retval = 0;
1907 goto end;
1909 retval = *ptr;
1910 *ptr = newval;
1911 end:
1912 WIN_ReleaseWndPtr(wndPtr);
1913 return retval;
1917 /**********************************************************************
1918 * WIN_GetWindowLong
1920 * Helper function for GetWindowLong().
1922 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1924 LONG retvalue;
1925 WND * wndPtr = WIN_FindWndPtr( hwnd );
1926 if (!wndPtr) return 0;
1927 if (offset >= 0)
1929 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1931 WARN("Invalid offset %d\n", offset );
1932 retvalue = 0;
1933 goto end;
1935 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1936 /* Special case for dialog window procedure */
1937 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1939 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1940 goto end;
1942 goto end;
1944 switch(offset)
1946 case GWL_USERDATA: retvalue = wndPtr->userdata;
1947 goto end;
1948 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1949 goto end;
1950 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1951 goto end;
1952 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1953 goto end;
1954 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1955 type );
1956 goto end;
1957 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1958 goto end;
1959 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1960 goto end;
1961 default:
1962 WARN("Unknown offset %d\n", offset );
1964 retvalue = 0;
1965 end:
1966 WIN_ReleaseWndPtr(wndPtr);
1967 return retvalue;
1971 /**********************************************************************
1972 * WIN_SetWindowLong
1974 * Helper function for SetWindowLong().
1976 * 0 is the failure code. However, in the case of failure SetLastError
1977 * must be set to distinguish between a 0 return value and a failure.
1979 * FIXME: The error values for SetLastError may not be right. Can
1980 * someone check with the real thing?
1982 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1983 WINDOWPROCTYPE type )
1985 LONG *ptr, retval;
1986 WND * wndPtr = WIN_FindWndPtr( hwnd );
1987 STYLESTRUCT style;
1989 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1991 if (!wndPtr)
1993 /* Is this the right error? */
1994 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1995 return 0;
1998 if (offset >= 0)
2000 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
2002 WARN("Invalid offset %d\n", offset );
2004 /* Is this the right error? */
2005 SetLastError( ERROR_OUTOFMEMORY );
2007 retval = 0;
2008 goto end;
2010 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2011 /* Special case for dialog window procedure */
2012 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2014 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2015 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2016 type, WIN_PROC_WINDOW );
2017 goto end;
2020 else switch(offset)
2022 case GWL_ID:
2023 ptr = (DWORD*)&wndPtr->wIDmenu;
2024 break;
2025 case GWL_HINSTANCE:
2026 retval = SetWindowWord( hwnd, offset, newval );
2027 goto end;
2028 case GWL_WNDPROC:
2029 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2030 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2031 type, WIN_PROC_WINDOW );
2032 goto end;
2033 case GWL_STYLE:
2034 style.styleOld = wndPtr->dwStyle;
2035 newval &= ~(WS_CHILD); /* this bit can't be changed this way */
2036 style.styleNew = newval | (style.styleOld & (WS_CHILD));
2038 if (wndPtr->flags & WIN_ISWIN32)
2039 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2040 wndPtr->dwStyle = style.styleNew;
2041 if (wndPtr->flags & WIN_ISWIN32)
2042 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2043 retval = style.styleOld;
2044 goto end;
2046 case GWL_USERDATA:
2047 ptr = &wndPtr->userdata;
2048 break;
2049 case GWL_EXSTYLE:
2050 style.styleOld = wndPtr->dwExStyle;
2051 style.styleNew = newval;
2052 if (wndPtr->flags & WIN_ISWIN32)
2053 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2054 wndPtr->dwExStyle = newval;
2055 if (wndPtr->flags & WIN_ISWIN32)
2056 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2057 retval = style.styleOld;
2058 goto end;
2060 default:
2061 WARN("Invalid offset %d\n", offset );
2063 /* Don't think this is right error but it should do */
2064 SetLastError( ERROR_OUTOFMEMORY );
2066 retval = 0;
2067 goto end;
2069 retval = *ptr;
2070 *ptr = newval;
2071 end:
2072 WIN_ReleaseWndPtr(wndPtr);
2073 return retval;
2077 /**********************************************************************
2078 * GetWindowLong (USER.135)
2080 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2082 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2086 /**********************************************************************
2087 * GetWindowLongA (USER32.@)
2089 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2091 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2095 /**********************************************************************
2096 * GetWindowLongW (USER32.@)
2098 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2100 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2104 /**********************************************************************
2105 * SetWindowLong (USER.136)
2107 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2109 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2113 /**********************************************************************
2114 * SetWindowLongA (USER32.@)
2116 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2118 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2122 /**********************************************************************
2123 * SetWindowLongW (USER32.@) Set window attribute
2125 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2126 * value in a window's extra memory.
2128 * The _hwnd_ parameter specifies the window. is the handle to a
2129 * window that has extra memory. The _newval_ parameter contains the
2130 * new attribute or extra memory value. If positive, the _offset_
2131 * parameter is the byte-addressed location in the window's extra
2132 * memory to set. If negative, _offset_ specifies the window
2133 * attribute to set, and should be one of the following values:
2135 * GWL_EXSTYLE The window's extended window style
2137 * GWL_STYLE The window's window style.
2139 * GWL_WNDPROC Pointer to the window's window procedure.
2141 * GWL_HINSTANCE The window's pplication instance handle.
2143 * GWL_ID The window's identifier.
2145 * GWL_USERDATA The window's user-specified data.
2147 * If the window is a dialog box, the _offset_ parameter can be one of
2148 * the following values:
2150 * DWL_DLGPROC The address of the window's dialog box procedure.
2152 * DWL_MSGRESULT The return value of a message
2153 * that the dialog box procedure processed.
2155 * DWL_USER Application specific information.
2157 * RETURNS
2159 * If successful, returns the previous value located at _offset_. Otherwise,
2160 * returns 0.
2162 * NOTES
2164 * Extra memory for a window class is specified by a nonzero cbWndExtra
2165 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2166 * time of class creation.
2168 * Using GWL_WNDPROC to set a new window procedure effectively creates
2169 * a window subclass. Use CallWindowProc() in the new windows procedure
2170 * to pass messages to the superclass's window procedure.
2172 * The user data is reserved for use by the application which created
2173 * the window.
2175 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2176 * instead, call the EnableWindow() function to change the window's
2177 * disabled state.
2179 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2180 * SetParent() instead.
2182 * Win95:
2183 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2184 * it sends WM_STYLECHANGING before changing the settings
2185 * and WM_STYLECHANGED afterwards.
2186 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2188 * BUGS
2190 * GWL_STYLE does not dispatch WM_STYLE... messages.
2192 * CONFORMANCE
2194 * ECMA-234, Win32
2197 LONG WINAPI SetWindowLongW(
2198 HWND hwnd, /* [in] window to alter */
2199 INT offset, /* [in] offset, in bytes, of location to alter */
2200 LONG newval /* [in] new value of location */
2202 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2206 /*******************************************************************
2207 * GetWindowText (USER.36)
2209 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2211 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2215 /*******************************************************************
2216 * GetWindowTextA (USER32.@)
2218 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2220 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2221 (LPARAM)lpString );
2224 /*******************************************************************
2225 * InternalGetWindowText (USER32.@)
2227 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2229 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2230 return GetWindowTextW(hwnd,lpString,nMaxCount);
2234 /*******************************************************************
2235 * GetWindowTextW (USER32.@)
2237 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2239 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2240 (LPARAM)lpString );
2244 /*******************************************************************
2245 * SetWindowText (USER.37)
2247 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2249 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2253 /*******************************************************************
2254 * SetWindowTextA (USER32.@)
2256 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2258 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2262 /*******************************************************************
2263 * SetWindowTextW (USER32.@)
2265 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2267 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2271 /*******************************************************************
2272 * GetWindowTextLength (USER.38)
2274 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2276 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2280 /*******************************************************************
2281 * GetWindowTextLengthA (USER32.@)
2283 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2285 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2288 /*******************************************************************
2289 * GetWindowTextLengthW (USER32.@)
2291 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2293 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2297 /*******************************************************************
2298 * IsWindow (USER.47)
2300 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2302 CURRENT_STACK16->es = USER_HeapSel;
2303 return IsWindow( hwnd );
2307 /*******************************************************************
2308 * IsWindow (USER32.@)
2310 BOOL WINAPI IsWindow( HWND hwnd )
2312 WND * wndPtr;
2313 BOOL retvalue;
2315 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2316 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2317 WIN_ReleaseWndPtr(wndPtr);
2318 return retvalue;
2323 /*****************************************************************
2324 * GetParent (USER.46)
2326 HWND16 WINAPI GetParent16( HWND16 hwnd )
2328 return (HWND16)GetParent( hwnd );
2332 /*****************************************************************
2333 * GetParent (USER32.@)
2335 HWND WINAPI GetParent( HWND hwnd )
2337 WND *wndPtr;
2338 HWND retvalue = 0;
2340 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2341 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2342 goto end;
2344 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2345 if (wndPtr)
2346 retvalue = wndPtr->hwndSelf;
2348 end:
2349 WIN_ReleaseWndPtr(wndPtr);
2350 return retvalue;
2354 /*****************************************************************
2355 * WIN_GetTopParent
2357 * Get the top-level parent for a child window.
2358 * returns a locked pointer
2360 WND* WIN_GetTopParentPtr( WND* pWnd )
2362 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2364 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2366 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2368 return tmpWnd;
2371 /*****************************************************************
2372 * WIN_GetTopParent
2374 * Get the top-level parent for a child window.
2376 HWND WIN_GetTopParent( HWND hwnd )
2378 HWND retvalue;
2379 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2380 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2382 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2383 WIN_ReleaseWndPtr(tmpPtr);
2384 WIN_ReleaseWndPtr(wndPtr);
2385 return retvalue;
2389 /*****************************************************************
2390 * SetParent (USER.233)
2392 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2394 return SetParent( hwndChild, hwndNewParent );
2398 /*****************************************************************
2399 * SetParent (USER32.@)
2401 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2403 WND *wndPtr;
2404 DWORD dwStyle;
2405 WND *pWndNewParent;
2406 WND *pWndOldParent;
2407 HWND retvalue;
2410 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2412 dwStyle = wndPtr->dwStyle;
2414 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2415 : WIN_LockWndPtr(pWndDesktop);
2417 /* Windows hides the window first, then shows it again
2418 * including the WM_SHOWWINDOW messages and all */
2419 if (dwStyle & WS_VISIBLE)
2420 ShowWindow( hwndChild, SW_HIDE );
2422 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2424 /* SetParent additionally needs to make hwndChild the topmost window
2425 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2426 WM_WINDOWPOSCHANGED notification messages.
2428 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2429 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2430 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2431 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2433 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2435 WIN_ReleaseWndPtr(pWndOldParent);
2436 WIN_ReleaseWndPtr(pWndNewParent);
2437 WIN_ReleaseWndPtr(wndPtr);
2439 return retvalue;
2443 /*******************************************************************
2444 * IsChild (USER.48)
2446 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2448 return IsChild(parent,child);
2452 /*******************************************************************
2453 * IsChild (USER32.@)
2455 BOOL WINAPI IsChild( HWND parent, HWND child )
2457 WND * wndPtr = WIN_FindWndPtr( child );
2458 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2460 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2461 if (wndPtr->hwndSelf == parent)
2463 WIN_ReleaseWndPtr(wndPtr);
2464 return TRUE;
2467 WIN_ReleaseWndPtr(wndPtr);
2468 return FALSE;
2472 /***********************************************************************
2473 * IsWindowVisible (USER.49)
2475 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2477 return IsWindowVisible(hwnd);
2481 /***********************************************************************
2482 * IsWindowVisible (USER32.@)
2484 BOOL WINAPI IsWindowVisible( HWND hwnd )
2486 BOOL retval;
2487 WND *wndPtr = WIN_FindWndPtr( hwnd );
2488 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2490 if (!(wndPtr->dwStyle & WS_VISIBLE))
2492 WIN_ReleaseWndPtr(wndPtr);
2493 return FALSE;
2495 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2497 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2498 WIN_ReleaseWndPtr(wndPtr);
2499 return retval;
2504 /***********************************************************************
2505 * WIN_IsWindowDrawable
2507 * hwnd is drawable when it is visible, all parents are not
2508 * minimized, and it is itself not minimized unless we are
2509 * trying to draw its default class icon.
2511 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2513 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2514 if ((wnd->dwStyle & WS_MINIMIZE) &&
2515 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2516 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2517 if( wnd->dwStyle & WS_MINIMIZE ||
2518 !(wnd->dwStyle & WS_VISIBLE) ) break;
2519 return (wnd == NULL);
2523 /*******************************************************************
2524 * GetTopWindow (USER.229)
2526 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2528 return GetTopWindow(hwnd);
2532 /*******************************************************************
2533 * GetTopWindow (USER32.@)
2535 HWND WINAPI GetTopWindow( HWND hwnd )
2537 HWND retval = 0;
2538 WND * wndPtr = (hwnd) ?
2539 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2541 if (wndPtr && wndPtr->child)
2542 retval = wndPtr->child->hwndSelf;
2544 WIN_ReleaseWndPtr(wndPtr);
2545 return retval;
2549 /*******************************************************************
2550 * GetWindow (USER.262)
2552 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2554 return GetWindow( hwnd,rel );
2558 /*******************************************************************
2559 * GetWindow (USER32.@)
2561 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2563 HWND retval;
2565 WND * wndPtr = WIN_FindWndPtr( hwnd );
2566 if (!wndPtr) return 0;
2567 switch(rel)
2569 case GW_HWNDFIRST:
2570 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2571 goto end;
2573 case GW_HWNDLAST:
2574 if (!wndPtr->parent)
2576 retval = 0; /* Desktop window */
2577 goto end;
2579 while (wndPtr->next)
2581 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2583 retval = wndPtr->hwndSelf;
2584 goto end;
2586 case GW_HWNDNEXT:
2587 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2588 goto end;
2590 case GW_HWNDPREV:
2591 if (!wndPtr->parent)
2593 retval = 0; /* Desktop window */
2594 goto end;
2596 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2597 if (wndPtr->hwndSelf == hwnd)
2599 retval = 0; /* First in list */
2600 goto end;
2602 while (wndPtr->next)
2604 if (wndPtr->next->hwndSelf == hwnd)
2606 retval = wndPtr->hwndSelf;
2607 goto end;
2609 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2611 retval = 0;
2612 goto end;
2614 case GW_OWNER:
2615 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2616 goto end;
2618 case GW_CHILD:
2619 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2620 goto end;
2622 retval = 0;
2623 end:
2624 WIN_ReleaseWndPtr(wndPtr);
2625 return retval;
2629 /*******************************************************************
2630 * GetNextWindow (USER.230)
2632 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2634 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2635 return GetWindow16( hwnd, flag );
2638 /***********************************************************************
2639 * WIN_InternalShowOwnedPopups
2641 * Internal version of ShowOwnedPopups; Wine functions should use this
2642 * to avoid interfering with application calls to ShowOwnedPopups
2643 * and to make sure the application can't prevent showing/hiding.
2645 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2649 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2651 INT totalChild=0, count=0;
2653 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2655 if (!pWnd) return TRUE;
2658 * Show windows Lowest first, Highest last to preserve Z-Order
2660 for (count = totalChild-1 ; count >=0; count--)
2662 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2664 if (fShow)
2666 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2667 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2670 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2672 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2673 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2676 else
2678 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2679 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2680 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2683 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2685 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2686 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2687 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2692 WIN_ReleaseDesktop();
2693 WIN_ReleaseWinArray(pWnd);
2695 return TRUE;
2698 /*******************************************************************
2699 * ShowOwnedPopups (USER.265)
2701 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2703 ShowOwnedPopups( owner, fShow );
2707 /*******************************************************************
2708 * ShowOwnedPopups (USER32.@)
2710 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2712 UINT totalChild=0, count=0;
2714 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2716 if (!pWnd) return TRUE;
2718 for (; count < totalChild; count++)
2720 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2722 if (fShow)
2724 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2727 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2728 * regardless of the state of the owner
2730 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2731 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2734 else
2736 if (IsWindowVisible(pWnd[count]->hwndSelf))
2739 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2740 * regardless of the state of the owner
2742 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2743 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2749 WIN_ReleaseDesktop();
2750 WIN_ReleaseWinArray(pWnd);
2751 return TRUE;
2755 /*******************************************************************
2756 * GetLastActivePopup (USER.287)
2758 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2760 return GetLastActivePopup( hwnd );
2763 /*******************************************************************
2764 * GetLastActivePopup (USER32.@)
2766 HWND WINAPI GetLastActivePopup( HWND hwnd )
2768 HWND retval;
2769 WND *wndPtr =WIN_FindWndPtr(hwnd);
2770 if (!wndPtr) return hwnd;
2771 retval = wndPtr->hwndLastActive;
2772 WIN_ReleaseWndPtr(wndPtr);
2773 if ((retval != hwnd) && (!IsWindow(retval)))
2774 retval = hwnd;
2775 return retval;
2779 /*******************************************************************
2780 * WIN_BuildWinArray
2782 * Build an array of pointers to the children of a given window.
2783 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2784 * when no windows are found.
2786 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2788 /* Future: this function will lock all windows associated with this array */
2790 WND **list, **ppWnd;
2791 WND *pWnd;
2792 UINT count = 0, skipOwned, skipHidden;
2793 DWORD skipFlags;
2795 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2796 skipOwned = bwaFlags & BWA_SKIPOWNED;
2797 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2798 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2800 /* First count the windows */
2802 if (!wndPtr)
2803 wndPtr = WIN_GetDesktop();
2805 pWnd = WIN_LockWndPtr(wndPtr->child);
2806 while (pWnd)
2808 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2809 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2810 count++;
2811 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2814 if( count )
2816 /* Now build the list of all windows */
2818 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2820 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2822 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2823 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2825 *ppWnd++ = pWnd;
2826 count++;
2829 WIN_ReleaseWndPtr(pWnd);
2830 *ppWnd = NULL;
2832 else count = 0;
2833 } else list = NULL;
2835 if( pTotal ) *pTotal = count;
2836 return list;
2838 /*******************************************************************
2839 * WIN_ReleaseWinArray
2841 void WIN_ReleaseWinArray(WND **wndArray)
2843 /* Future: this function will also unlock all windows associated with wndArray */
2844 HeapFree( GetProcessHeap(), 0, wndArray );
2848 /*******************************************************************
2849 * EnumWindows (USER32.@)
2851 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2853 WND **list, **ppWnd;
2855 /* We have to build a list of all windows first, to avoid */
2856 /* unpleasant side-effects, for instance if the callback */
2857 /* function changes the Z-order of the windows. */
2859 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2861 WIN_ReleaseDesktop();
2862 return FALSE;
2865 /* Now call the callback function for every window */
2867 for (ppWnd = list; *ppWnd; ppWnd++)
2869 LRESULT lpEnumFuncRetval;
2870 int iWndsLocks = 0;
2871 /* Make sure that the window still exists */
2872 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2874 /* To avoid any deadlocks, all the locks on the windows
2875 structures must be suspended before the control
2876 is passed to the application */
2877 iWndsLocks = WIN_SuspendWndsLock();
2878 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2879 WIN_RestoreWndsLock(iWndsLocks);
2881 if (!lpEnumFuncRetval) break;
2883 WIN_ReleaseWinArray(list);
2884 WIN_ReleaseDesktop();
2885 return TRUE;
2889 /**********************************************************************
2890 * EnumTaskWindows (USER.225)
2892 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2893 LPARAM lParam )
2895 WND **list, **ppWnd;
2897 /* This function is the same as EnumWindows(), */
2898 /* except for an added check on the window's task. */
2900 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2902 WIN_ReleaseDesktop();
2903 return FALSE;
2906 /* Now call the callback function for every window */
2908 for (ppWnd = list; *ppWnd; ppWnd++)
2910 LRESULT funcRetval;
2911 int iWndsLocks = 0;
2912 /* Make sure that the window still exists */
2913 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2914 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2916 /* To avoid any deadlocks, all the locks on the windows
2917 structures must be suspended before the control
2918 is passed to the application */
2919 iWndsLocks = WIN_SuspendWndsLock();
2920 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2921 WIN_RestoreWndsLock(iWndsLocks);
2923 if (!funcRetval) break;
2925 WIN_ReleaseWinArray(list);
2926 WIN_ReleaseDesktop();
2927 return TRUE;
2931 /**********************************************************************
2932 * EnumThreadWindows (USER32.@)
2934 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2936 TEB *teb = THREAD_IdToTEB(id);
2938 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2942 /**********************************************************************
2943 * WIN_EnumChildWindows
2945 * Helper function for EnumChildWindows().
2947 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2949 WND **childList;
2950 BOOL16 ret = FALSE;
2952 for ( ; *ppWnd; ppWnd++)
2954 int iWndsLocks = 0;
2956 /* Make sure that the window still exists */
2957 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2958 /* Build children list first */
2959 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2961 /* To avoid any deadlocks, all the locks on the windows
2962 structures must be suspended before the control
2963 is passed to the application */
2964 iWndsLocks = WIN_SuspendWndsLock();
2965 ret = func( (*ppWnd)->hwndSelf, lParam );
2966 WIN_RestoreWndsLock(iWndsLocks);
2968 if (childList)
2970 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2971 WIN_ReleaseWinArray(childList);
2973 if (!ret) return FALSE;
2975 return TRUE;
2979 /**********************************************************************
2980 * EnumChildWindows (USER32.@)
2982 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2983 LPARAM lParam )
2985 WND **list, *pParent;
2987 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2988 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2990 WIN_ReleaseWndPtr(pParent);
2991 return FALSE;
2993 WIN_EnumChildWindows( list, func, lParam );
2994 WIN_ReleaseWinArray(list);
2995 WIN_ReleaseWndPtr(pParent);
2996 return TRUE;
3000 /*******************************************************************
3001 * AnyPopup (USER.52)
3003 BOOL16 WINAPI AnyPopup16(void)
3005 return AnyPopup();
3009 /*******************************************************************
3010 * AnyPopup (USER32.@)
3012 BOOL WINAPI AnyPopup(void)
3014 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3015 BOOL retvalue;
3017 while (wndPtr)
3019 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3021 retvalue = TRUE;
3022 goto end;
3024 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3026 retvalue = FALSE;
3027 end:
3028 WIN_ReleaseWndPtr(wndPtr);
3029 return retvalue;
3033 /*******************************************************************
3034 * FlashWindow (USER.105)
3036 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3038 return FlashWindow( hWnd, bInvert );
3042 /*******************************************************************
3043 * FlashWindow (USER32.@)
3045 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3047 WND *wndPtr = WIN_FindWndPtr(hWnd);
3049 TRACE("%04x\n", hWnd);
3051 if (!wndPtr) return FALSE;
3053 if (wndPtr->dwStyle & WS_MINIMIZE)
3055 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3057 HDC hDC = GetDC(hWnd);
3059 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3060 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3062 ReleaseDC( hWnd, hDC );
3063 wndPtr->flags |= WIN_NCACTIVATED;
3065 else
3067 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3068 RDW_UPDATENOW | RDW_FRAME, 0 );
3069 wndPtr->flags &= ~WIN_NCACTIVATED;
3071 WIN_ReleaseWndPtr(wndPtr);
3072 return TRUE;
3074 else
3076 WPARAM16 wparam;
3077 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3078 else wparam = (hWnd == GetActiveWindow());
3080 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3081 WIN_ReleaseWndPtr(wndPtr);
3082 return wparam;
3087 /*******************************************************************
3088 * SetSysModalWindow (USER.188)
3090 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3092 HWND hWndOldModal = hwndSysModal;
3093 hwndSysModal = hWnd;
3094 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3095 return hWndOldModal;
3099 /*******************************************************************
3100 * GetSysModalWindow (USER.189)
3102 HWND16 WINAPI GetSysModalWindow16(void)
3104 return hwndSysModal;
3108 /*******************************************************************
3109 * GetWindowContextHelpId (USER32.@)
3111 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3113 DWORD retval;
3114 WND *wnd = WIN_FindWndPtr( hwnd );
3115 if (!wnd) return 0;
3116 retval = wnd->helpContext;
3117 WIN_ReleaseWndPtr(wnd);
3118 return retval;
3122 /*******************************************************************
3123 * SetWindowContextHelpId (USER32.@)
3125 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3127 WND *wnd = WIN_FindWndPtr( hwnd );
3128 if (!wnd) return FALSE;
3129 wnd->helpContext = id;
3130 WIN_ReleaseWndPtr(wnd);
3131 return TRUE;
3135 /*******************************************************************
3136 * DRAG_QueryUpdate
3138 * recursively find a child that contains spDragInfo->pt point
3139 * and send WM_QUERYDROPOBJECT
3141 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3143 BOOL16 wParam, bResult = 0;
3144 POINT pt;
3145 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3146 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3147 RECT tempRect;
3149 if( !ptrQueryWnd || !ptrDragInfo )
3150 goto end;
3152 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3154 GetWindowRect(hQueryWnd,&tempRect);
3156 if( !PtInRect(&tempRect,pt) ||
3157 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3158 goto end;
3160 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3162 tempRect = ptrQueryWnd->rectClient;
3163 if(ptrQueryWnd->dwStyle & WS_CHILD)
3164 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3165 (LPPOINT)&tempRect, 2 );
3167 if (PtInRect( &tempRect, pt))
3169 wParam = 0;
3171 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3173 if( ptrWnd->dwStyle & WS_VISIBLE )
3175 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3176 if (PtInRect( &tempRect, pt )) break;
3180 if(ptrWnd)
3182 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3183 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3184 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3185 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3186 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3188 WIN_ReleaseWndPtr(ptrWnd);
3191 if(bResult)
3192 goto end;
3194 else wParam = 1;
3196 else wParam = 1;
3198 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3200 ptrDragInfo->hScope = hQueryWnd;
3202 bResult = ( bNoSend )
3203 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3204 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3205 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3206 if( !bResult )
3207 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3209 end:
3210 WIN_ReleaseWndPtr(ptrQueryWnd);
3211 return bResult;
3215 /*******************************************************************
3216 * DragDetect (USER.465)
3218 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3220 POINT pt32;
3221 CONV_POINT16TO32( &pt, &pt32 );
3222 return DragDetect( hWnd, pt32 );
3225 /*******************************************************************
3226 * DragDetect (USER32.@)
3228 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3230 MSG msg;
3231 RECT rect;
3233 rect.left = pt.x - wDragWidth;
3234 rect.right = pt.x + wDragWidth;
3236 rect.top = pt.y - wDragHeight;
3237 rect.bottom = pt.y + wDragHeight;
3239 SetCapture(hWnd);
3241 while(1)
3243 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3245 if( msg.message == WM_LBUTTONUP )
3247 ReleaseCapture();
3248 return 0;
3250 if( msg.message == WM_MOUSEMOVE )
3252 POINT tmp;
3253 tmp.x = LOWORD(msg.lParam);
3254 tmp.y = HIWORD(msg.lParam);
3255 if( !PtInRect( &rect, tmp ))
3257 ReleaseCapture();
3258 return 1;
3262 WaitMessage();
3264 return 0;
3267 /******************************************************************************
3268 * DragObject (USER.464)
3270 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3271 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3273 MSG msg;
3274 LPDRAGINFO16 lpDragInfo;
3275 SEGPTR spDragInfo;
3276 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3277 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3278 WND *wndPtr = WIN_FindWndPtr(hWnd);
3279 HCURSOR16 hCurrentCursor = 0;
3280 HWND16 hCurrentWnd = 0;
3282 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3283 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3285 if( !lpDragInfo || !spDragInfo )
3287 WIN_ReleaseWndPtr(wndPtr);
3288 return 0L;
3291 hBummer = LoadCursorA(0, IDC_BUMMERA);
3293 if( !hBummer || !wndPtr )
3295 GlobalFree16(hDragInfo);
3296 WIN_ReleaseWndPtr(wndPtr);
3297 return 0L;
3300 if(hCursor)
3302 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3304 GlobalFree16(hDragInfo);
3305 WIN_ReleaseWndPtr(wndPtr);
3306 return 0L;
3309 if( hDragCursor == hCursor ) hDragCursor = 0;
3310 else hCursor = hDragCursor;
3312 hOldCursor = SetCursor(hDragCursor);
3315 lpDragInfo->hWnd = hWnd;
3316 lpDragInfo->hScope = 0;
3317 lpDragInfo->wFlags = wObj;
3318 lpDragInfo->hList = szList; /* near pointer! */
3319 lpDragInfo->hOfStruct = hOfStruct;
3320 lpDragInfo->l = 0L;
3322 SetCapture(hWnd);
3323 ShowCursor( TRUE );
3327 do{ WaitMessage(); }
3328 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3330 *(lpDragInfo+1) = *lpDragInfo;
3332 lpDragInfo->pt.x = msg.pt.x;
3333 lpDragInfo->pt.y = msg.pt.y;
3335 /* update DRAGINFO struct */
3336 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3338 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3339 hCurrentCursor = hCursor;
3340 else
3342 hCurrentCursor = hBummer;
3343 lpDragInfo->hScope = 0;
3345 if( hCurrentCursor )
3346 SetCursor(hCurrentCursor);
3348 /* send WM_DRAGLOOP */
3349 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3350 (LPARAM) spDragInfo );
3351 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3352 if( hCurrentWnd != lpDragInfo->hScope )
3354 if( hCurrentWnd )
3355 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3356 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3357 HIWORD(spDragInfo)) );
3358 hCurrentWnd = lpDragInfo->hScope;
3359 if( hCurrentWnd )
3360 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3362 else
3363 if( hCurrentWnd )
3364 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3366 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3368 ReleaseCapture();
3369 ShowCursor( FALSE );
3371 if( hCursor )
3373 SetCursor( hOldCursor );
3374 if (hDragCursor) DestroyCursor( hDragCursor );
3377 if( hCurrentCursor != hBummer )
3378 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3379 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3380 else
3381 msg.lParam = 0;
3382 GlobalFree16(hDragInfo);
3383 WIN_ReleaseWndPtr(wndPtr);
3385 return (DWORD)(msg.lParam);