Prevent multiple definitions caused by MSVCRT headers.
[wine.git] / windows / win.c
blob4329e92267e1db5cc7e77d8ee5019dcb2ee3db27
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 "winerror.h"
25 #include "stackframe.h"
26 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(win);
29 DECLARE_DEBUG_CHANNEL(msg);
31 /**********************************************************************/
33 WND_DRIVER *WND_Driver = NULL;
35 /* Desktop window */
36 static WND *pWndDesktop = NULL;
38 static HWND hwndSysModal = 0;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 /* thread safeness */
44 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
46 /***********************************************************************
47 * WIN_LockWnds
49 * Locks access to all WND structures for thread safeness
51 void WIN_LockWnds( void )
53 _EnterSysLevel( &WIN_SysLevel );
56 /***********************************************************************
57 * WIN_UnlockWnds
59 * Unlocks access to all WND structures
61 void WIN_UnlockWnds( void )
63 _LeaveSysLevel( &WIN_SysLevel );
66 /***********************************************************************
67 * WIN_SuspendWndsLock
69 * Suspend the lock on WND structures.
70 * Returns the number of locks suspended
72 int WIN_SuspendWndsLock( void )
74 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
75 int count = isuspendedLocks;
77 while ( count-- > 0 )
78 _LeaveSysLevel( &WIN_SysLevel );
80 return isuspendedLocks;
83 /***********************************************************************
84 * WIN_RestoreWndsLock
86 * Restore the suspended locks on WND structures
88 void WIN_RestoreWndsLock( int ipreviousLocks )
90 while ( ipreviousLocks-- > 0 )
91 _EnterSysLevel( &WIN_SysLevel );
94 /***********************************************************************
95 * WIN_FindWndPtr
97 * Return a pointer to the WND structure corresponding to a HWND.
99 WND * WIN_FindWndPtr( HWND hwnd )
101 WND * ptr;
103 if (!hwnd || HIWORD(hwnd)) goto error2;
104 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
105 /* Lock all WND structures for thread safeness*/
106 WIN_LockWnds();
107 /*and increment destruction monitoring*/
108 ptr->irefCount++;
110 if (ptr->dwMagic != WND_MAGIC) goto error;
111 if (ptr->hwndSelf != hwnd)
113 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
114 goto error;
116 /* returns a locked pointer */
117 return ptr;
118 error:
119 /* Unlock all WND structures for thread safeness*/
120 WIN_UnlockWnds();
121 /* and decrement destruction monitoring value */
122 ptr->irefCount--;
124 error2:
125 if ( hwnd!=0 )
126 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
127 return NULL;
130 /***********************************************************************
131 * WIN_LockWndPtr
133 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
134 * but by initWndPtr;
135 * Returns the locked initialisation pointer
137 WND *WIN_LockWndPtr(WND *initWndPtr)
139 if(!initWndPtr) return 0;
141 /* Lock all WND structures for thread safeness*/
142 WIN_LockWnds();
143 /*and increment destruction monitoring*/
144 initWndPtr->irefCount++;
146 return initWndPtr;
150 /***********************************************************************
151 * WIN_ReleaseWndPtr
153 * Release the pointer to the WND structure.
155 void WIN_ReleaseWndPtr(WND *wndPtr)
157 if(!wndPtr) return;
159 /*Decrement destruction monitoring value*/
160 wndPtr->irefCount--;
161 /* Check if it's time to release the memory*/
162 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
164 /* Release memory */
165 USER_HEAP_FREE( wndPtr->hwndSelf);
166 wndPtr->hwndSelf = 0;
168 else if(wndPtr->irefCount < 0)
170 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
171 ERR("forgot a Lock on %p somewhere\n",wndPtr);
173 /*unlock all WND structures for thread safeness*/
174 WIN_UnlockWnds();
177 /***********************************************************************
178 * WIN_UpdateWndPtr
180 * Updates the value of oldPtr to newPtr.
182 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
184 WND *tmpWnd = NULL;
186 tmpWnd = WIN_LockWndPtr(newPtr);
187 WIN_ReleaseWndPtr(*oldPtr);
188 *oldPtr = tmpWnd;
192 /***********************************************************************
193 * WIN_DumpWindow
195 * Dump the content of a window structure to stderr.
197 void WIN_DumpWindow( HWND hwnd )
199 WND *ptr;
200 char className[80];
201 int i;
203 if (!(ptr = WIN_FindWndPtr( hwnd )))
205 WARN("%04x is not a window handle\n", hwnd );
206 return;
209 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
210 strcpy( className, "#NULL#" );
212 TRACE("Window %04x (%p):\n", hwnd, ptr );
213 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
214 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
215 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
216 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
217 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
218 ptr->next, ptr->child, ptr->parent, ptr->owner,
219 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
220 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
221 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
222 ptr->text ? debugstr_w(ptr->text) : "",
223 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
224 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
225 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
226 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
228 if (ptr->cbWndExtra)
230 DPRINTF( "extra bytes:" );
231 for (i = 0; i < ptr->cbWndExtra; i++)
232 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
233 DPRINTF( "\n" );
235 DPRINTF( "\n" );
236 WIN_ReleaseWndPtr(ptr);
240 /***********************************************************************
241 * WIN_WalkWindows
243 * Walk the windows tree and print each window on stderr.
245 void WIN_WalkWindows( HWND hwnd, int indent )
247 WND *ptr;
248 char className[80];
250 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
252 if (!ptr)
254 WARN("Invalid window handle %04x\n", hwnd );
255 return;
258 if (!indent) /* first time around */
259 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
260 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
261 " Text");
263 while (ptr)
265 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
267 GetClassNameA( ptr->hwndSelf, className, sizeof(className) );
268 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
269 (DWORD)ptr, ptr->hmemTaskQ, className,
270 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
271 ptr->text ? debugstr_w(ptr->text) : "<null>");
273 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
274 WIN_UpdateWndPtr(&ptr,ptr->next);
278 /***********************************************************************
279 * WIN_UnlinkWindow
281 * Remove a window from the siblings linked list.
283 BOOL WIN_UnlinkWindow( HWND hwnd )
285 WND *wndPtr, **ppWnd;
286 BOOL ret = FALSE;
288 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
289 else if(!wndPtr->parent)
291 WIN_ReleaseWndPtr(wndPtr);
292 return FALSE;
295 ppWnd = &wndPtr->parent->child;
296 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
297 if (*ppWnd)
299 *ppWnd = wndPtr->next;
300 ret = TRUE;
302 WIN_ReleaseWndPtr(wndPtr);
303 return ret;
307 /***********************************************************************
308 * WIN_LinkWindow
310 * Insert a window into the siblings linked list.
311 * The window is inserted after the specified window, which can also
312 * be specified as HWND_TOP or HWND_BOTTOM.
314 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
316 WND *wndPtr, **ppWnd;
318 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
319 else if(!wndPtr->parent)
321 WIN_ReleaseWndPtr(wndPtr);
322 return FALSE;
324 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
326 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
327 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
328 while (*ppWnd) ppWnd = &(*ppWnd)->next;
330 else /* Normal case */
332 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
333 if (!afterPtr)
335 WIN_ReleaseWndPtr(wndPtr);
336 return FALSE;
338 ppWnd = &afterPtr->next;
339 WIN_ReleaseWndPtr(afterPtr);
341 wndPtr->next = *ppWnd;
342 *ppWnd = wndPtr;
343 WIN_ReleaseWndPtr(wndPtr);
344 return TRUE;
348 /***********************************************************************
349 * WIN_FindWinToRepaint
351 * Find a window that needs repaint.
353 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
355 HWND hwndRet;
356 WND *pWnd;
358 /* Note: the desktop window never gets WM_PAINT messages
359 * The real reason why is because Windows DesktopWndProc
360 * does ValidateRgn inside WM_ERASEBKGND handler.
363 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
365 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
367 if (!(pWnd->dwStyle & WS_VISIBLE))
369 TRACE("skipping window %04x\n",
370 pWnd->hwndSelf );
372 else if ((pWnd->hmemTaskQ == hQueue) &&
373 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
374 break;
376 else if (pWnd->child )
377 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
379 WIN_ReleaseWndPtr(pWnd);
380 return hwndRet;
385 if(!pWnd)
387 return 0;
390 hwndRet = pWnd->hwndSelf;
392 /* look among siblings if we got a transparent window */
393 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
394 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
396 WIN_UpdateWndPtr(&pWnd,pWnd->next);
398 if (pWnd)
400 hwndRet = pWnd->hwndSelf;
401 WIN_ReleaseWndPtr(pWnd);
403 TRACE("found %04x\n",hwndRet);
404 return hwndRet;
408 /***********************************************************************
409 * WIN_DestroyWindow
411 * Destroy storage associated to a window. "Internals" p.358
412 * returns a locked wndPtr->next
414 static WND* WIN_DestroyWindow( WND* wndPtr )
416 HWND hwnd = wndPtr->hwndSelf;
417 WND *pWnd;
419 TRACE("%04x\n", wndPtr->hwndSelf );
421 /* free child windows */
422 WIN_LockWndPtr(wndPtr->child);
423 while ((pWnd = wndPtr->child))
425 wndPtr->child = WIN_DestroyWindow( pWnd );
426 WIN_ReleaseWndPtr(pWnd);
430 * Clear the update region to make sure no WM_PAINT messages will be
431 * generated for this window while processing the WM_NCDESTROY.
433 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
435 if (wndPtr->hrgnUpdate > 1)
436 DeleteObject( wndPtr->hrgnUpdate );
438 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
440 wndPtr->hrgnUpdate = 0;
444 * Send the WM_NCDESTROY to the window being destroyed.
446 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
448 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
450 WINPOS_CheckInternalPos( wndPtr );
451 if( hwnd == GetCapture()) ReleaseCapture();
453 /* free resources associated with the window */
455 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
456 PROPERTY_RemoveWindowProps( wndPtr );
458 wndPtr->dwMagic = 0; /* Mark it as invalid */
460 /* toss stale messages from the queue */
462 if( wndPtr->hmemTaskQ )
464 BOOL bPostQuit = FALSE;
465 WPARAM wQuitParam = 0;
466 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
467 QMSG *qmsg;
469 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
471 if( qmsg->msg.message == WM_QUIT )
473 bPostQuit = TRUE;
474 wQuitParam = qmsg->msg.wParam;
476 QUEUE_RemoveMsg(msgQ, qmsg);
479 QUEUE_Unlock(msgQ);
481 /* repost WM_QUIT to make sure this app exits its message loop */
482 if( bPostQuit ) PostQuitMessage(wQuitParam);
483 wndPtr->hmemTaskQ = 0;
486 if (!(wndPtr->dwStyle & WS_CHILD))
487 if (wndPtr->wIDmenu)
489 DestroyMenu( wndPtr->wIDmenu );
490 wndPtr->wIDmenu = 0;
492 if (wndPtr->hSysMenu)
494 DestroyMenu( wndPtr->hSysMenu );
495 wndPtr->hSysMenu = 0;
497 wndPtr->pDriver->pDestroyWindow( wndPtr );
498 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
499 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
500 CLASS_RemoveWindow( wndPtr->class );
501 wndPtr->class = NULL;
503 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
505 wndPtr->pDriver->pFinalize(wndPtr);
507 return pWnd;
510 /***********************************************************************
511 * WIN_ResetQueueWindows
513 * Reset the queue of all the children of a given window.
514 * Return TRUE if something was done.
516 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
518 BOOL ret = FALSE;
520 if (hNew) /* Set a new queue */
522 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
524 if (wnd->hmemTaskQ == hQueue)
526 wnd->hmemTaskQ = hNew;
527 ret = TRUE;
529 if (wnd->child)
531 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
535 else /* Queue is being destroyed */
537 while (wnd->child)
539 WND *tmp = WIN_LockWndPtr(wnd->child);
540 WND *tmp2;
541 ret = FALSE;
542 while (tmp)
544 if (tmp->hmemTaskQ == hQueue)
546 DestroyWindow( tmp->hwndSelf );
547 ret = TRUE;
548 break;
550 tmp2 = WIN_LockWndPtr(tmp->child);
551 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
552 ret = TRUE;
553 else
555 WIN_UpdateWndPtr(&tmp,tmp->next);
557 WIN_ReleaseWndPtr(tmp2);
559 WIN_ReleaseWndPtr(tmp);
560 if (!ret) break;
563 return ret;
566 /***********************************************************************
567 * WIN_CreateDesktopWindow
569 * Create the desktop window.
571 BOOL WIN_CreateDesktopWindow(void)
573 struct tagCLASS *class;
574 HWND hwndDesktop;
575 INT wndExtra;
576 DWORD clsStyle;
577 WNDPROC winproc;
578 DCE *dce;
580 TRACE("Creating desktop window\n");
583 if (!WINPOS_CreateInternalPosAtom() ||
584 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
585 &wndExtra, &winproc, &clsStyle, &dce )))
586 return FALSE;
588 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
589 if (!hwndDesktop) return FALSE;
590 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
592 pWndDesktop->pDriver = WND_Driver;
593 pWndDesktop->pDriver->pInitialize(pWndDesktop);
595 pWndDesktop->next = NULL;
596 pWndDesktop->child = NULL;
597 pWndDesktop->parent = NULL;
598 pWndDesktop->owner = NULL;
599 pWndDesktop->class = class;
600 pWndDesktop->dwMagic = WND_MAGIC;
601 pWndDesktop->hwndSelf = hwndDesktop;
602 pWndDesktop->hInstance = 0;
603 pWndDesktop->rectWindow.left = 0;
604 pWndDesktop->rectWindow.top = 0;
605 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
606 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
607 pWndDesktop->rectClient = pWndDesktop->rectWindow;
608 pWndDesktop->text = NULL;
609 pWndDesktop->hmemTaskQ = GetFastQueue16();
610 pWndDesktop->hrgnUpdate = 0;
611 pWndDesktop->hwndLastActive = hwndDesktop;
612 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
613 WS_CLIPSIBLINGS;
614 pWndDesktop->dwExStyle = 0;
615 pWndDesktop->clsStyle = clsStyle;
616 pWndDesktop->dce = NULL;
617 pWndDesktop->pVScroll = NULL;
618 pWndDesktop->pHScroll = NULL;
619 pWndDesktop->pProp = NULL;
620 pWndDesktop->wIDmenu = 0;
621 pWndDesktop->helpContext = 0;
622 pWndDesktop->flags = 0;
623 pWndDesktop->hSysMenu = 0;
624 pWndDesktop->userdata = 0;
625 pWndDesktop->winproc = winproc;
626 pWndDesktop->cbWndExtra = wndExtra;
627 pWndDesktop->irefCount = 0;
629 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop)) return FALSE;
631 SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
632 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
633 return TRUE;
637 /***********************************************************************
638 * WIN_FixCoordinates
640 * Fix the coordinates - Helper for WIN_CreateWindowEx.
641 * returns default show mode in sw.
642 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
644 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
646 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
647 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
649 if (cs->style & (WS_CHILD | WS_POPUP))
651 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
652 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
654 else /* overlapped window */
656 STARTUPINFOA info;
658 GetStartupInfoA( &info );
660 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
662 /* Never believe Microsoft's documentation... CreateWindowEx doc says
663 * that if an overlapped window is created with WS_VISIBLE style bit
664 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
665 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
666 * reveals that
668 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
669 * 2) it does not ignore the y parameter as the docs claim; instead, it
670 * uses it as second parameter to ShowWindow() unless y is either
671 * CW_USEDEFAULT or CW_USEDEFAULT16.
673 * The fact that we didn't do 2) caused bogus windows pop up when wine
674 * was running apps that were using this obscure feature. Example -
675 * calc.exe that comes with Win98 (only Win98, it's different from
676 * the one that comes with Win95 and NT)
678 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
679 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
680 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
683 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
685 if (info.dwFlags & STARTF_USESIZE)
687 cs->cx = info.dwXSize;
688 cs->cy = info.dwYSize;
690 else /* if no other hint from the app, pick 3/4 of the screen real estate */
692 RECT r;
693 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
694 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
695 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
702 /***********************************************************************
703 * WIN_CreateWindowEx
705 * Implementation of CreateWindowEx().
707 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
708 WINDOWPROCTYPE type )
710 INT sw = SW_SHOW;
711 struct tagCLASS *classPtr;
712 WND *wndPtr;
713 HWND retvalue;
714 HWND16 hwnd, hwndLinkAfter;
715 POINT maxSize, maxPos, minTrack, maxTrack;
716 INT wndExtra;
717 DWORD clsStyle;
718 WNDPROC winproc;
719 DCE *dce;
720 LRESULT CALLBACK (*localSend32)(HWND, UINT, WPARAM, LPARAM);
722 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
723 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
724 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
725 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
726 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
728 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
729 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
731 /* Find the parent window */
733 if (cs->hwndParent)
735 /* Make sure parent is valid */
736 if (!IsWindow( cs->hwndParent ))
738 WARN("Bad parent %04x\n", cs->hwndParent );
739 return 0;
741 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
742 WARN("No parent for child window\n" );
743 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
746 /* Find the window class */
747 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
748 &wndExtra, &winproc, &clsStyle, &dce )))
750 WARN("Bad class '%s'\n", cs->lpszClass );
751 return 0;
754 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
756 /* Create the window structure */
758 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
760 TRACE("out of memory\n" );
761 return 0;
764 /* Fill the window structure */
766 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
767 wndPtr->next = NULL;
768 wndPtr->child = NULL;
770 if ((cs->style & WS_CHILD) && cs->hwndParent)
772 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
773 wndPtr->owner = NULL;
774 WIN_ReleaseWndPtr(wndPtr->parent);
776 else
778 wndPtr->parent = pWndDesktop;
779 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
780 wndPtr->owner = NULL;
781 else
783 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
784 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
785 WIN_ReleaseWndPtr(wndPtr->owner);
786 WIN_ReleaseWndPtr(tmpWnd);
791 wndPtr->pDriver = wndPtr->parent->pDriver;
792 wndPtr->pDriver->pInitialize(wndPtr);
794 wndPtr->class = classPtr;
795 wndPtr->winproc = winproc;
796 wndPtr->dwMagic = WND_MAGIC;
797 wndPtr->hwndSelf = hwnd;
798 wndPtr->hInstance = cs->hInstance;
799 wndPtr->text = NULL;
800 wndPtr->hmemTaskQ = GetFastQueue16();
801 wndPtr->hrgnUpdate = 0;
802 wndPtr->hrgnWnd = 0;
803 wndPtr->hwndLastActive = hwnd;
804 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
805 wndPtr->dwExStyle = cs->dwExStyle;
806 wndPtr->clsStyle = clsStyle;
807 wndPtr->wIDmenu = 0;
808 wndPtr->helpContext = 0;
809 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
810 wndPtr->pVScroll = NULL;
811 wndPtr->pHScroll = NULL;
812 wndPtr->pProp = NULL;
813 wndPtr->userdata = 0;
814 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
815 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
816 wndPtr->cbWndExtra = wndExtra;
817 wndPtr->irefCount = 1;
819 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
821 /* Call the WH_CBT hook */
823 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
824 ? HWND_BOTTOM : HWND_TOP;
826 if (HOOK_IsHooked( WH_CBT ))
828 CBT_CREATEWNDA cbtc;
829 LRESULT ret;
831 cbtc.lpcs = cs;
832 cbtc.hwndInsertAfter = hwndLinkAfter;
833 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
834 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
835 if (ret)
837 TRACE("CBT-hook returned 0\n");
838 wndPtr->pDriver->pFinalize(wndPtr);
839 USER_HEAP_FREE( hwnd );
840 CLASS_RemoveWindow( classPtr );
841 retvalue = 0;
842 goto end;
846 /* Correct the window style */
848 if (!(cs->style & WS_CHILD))
850 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
851 if (!(cs->style & WS_POPUP))
853 wndPtr->dwStyle |= WS_CAPTION;
854 wndPtr->flags |= WIN_NEED_SIZE;
858 /* Get class or window DC if needed */
860 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
861 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
862 else wndPtr->dce = NULL;
864 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
866 wndPtr->rectWindow.left = cs->x;
867 wndPtr->rectWindow.top = cs->y;
868 wndPtr->rectWindow.right = cs->x + cs->cx;
869 wndPtr->rectWindow.bottom = cs->y + cs->cy;
870 wndPtr->rectClient = wndPtr->rectWindow;
872 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
874 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
876 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
877 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
878 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
879 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
880 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
883 if (cs->cx < 0) cs->cx = 0;
884 if (cs->cy < 0) cs->cy = 0;
886 wndPtr->rectWindow.left = cs->x;
887 wndPtr->rectWindow.top = cs->y;
888 wndPtr->rectWindow.right = cs->x + cs->cx;
889 wndPtr->rectWindow.bottom = cs->y + cs->cy;
890 wndPtr->rectClient = wndPtr->rectWindow;
892 if(!wndPtr->pDriver->pCreateWindow(wndPtr, cs, type == WIN_PROC_32W))
894 retvalue = FALSE;
895 goto end;
898 /* Set the window menu */
900 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
902 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
903 else
905 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
906 if (menuName)
908 if (HIWORD(cs->hInstance))
909 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
910 else
911 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
913 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
917 else wndPtr->wIDmenu = (UINT)cs->hMenu;
919 /* Send the WM_CREATE message
920 * Perhaps we shouldn't allow width/height changes as well.
921 * See p327 in "Internals".
924 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
926 localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
927 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
929 /* Insert the window in the linked list */
931 WIN_LinkWindow( hwnd, hwndLinkAfter );
933 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
934 NULL, NULL, 0, &wndPtr->rectClient );
935 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
936 maxPos.y - wndPtr->rectWindow.top);
937 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
939 /* Send the size messages */
941 if (!(wndPtr->flags & WIN_NEED_SIZE))
943 /* send it anyway */
944 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
945 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
946 WARN("sending bogus WM_SIZE message 0x%08lx\n",
947 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
948 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
949 (*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
950 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
951 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
952 (*localSend32)( hwnd, WM_MOVE, 0,
953 MAKELONG( wndPtr->rectClient.left,
954 wndPtr->rectClient.top ) );
957 /* Show the window, maximizing or minimizing if needed */
959 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
961 RECT16 newPos;
962 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
963 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
964 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
965 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
966 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
967 : SWP_NOZORDER | SWP_FRAMECHANGED;
968 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
969 newPos.right, newPos.bottom, swFlag );
972 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
974 /* Notify the parent window only */
976 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
977 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
978 if( !IsWindow(hwnd) )
980 retvalue = 0;
981 goto end;
985 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
987 /* Call WH_SHELL hook */
989 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
990 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
992 TRACE("created window %04x\n", hwnd);
993 retvalue = hwnd;
994 goto end;
996 WIN_UnlinkWindow( hwnd );
999 /* Abort window creation */
1001 WARN("aborted by WM_xxCREATE!\n");
1002 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1003 CLASS_RemoveWindow( classPtr );
1004 retvalue = 0;
1005 end:
1006 WIN_ReleaseWndPtr(wndPtr);
1008 return retvalue;
1012 /***********************************************************************
1013 * CreateWindow (USER.41)
1015 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1016 DWORD style, INT16 x, INT16 y, INT16 width,
1017 INT16 height, HWND16 parent, HMENU16 menu,
1018 HINSTANCE16 instance, LPVOID data )
1020 return CreateWindowEx16( 0, className, windowName, style,
1021 x, y, width, height, parent, menu, instance, data );
1025 /***********************************************************************
1026 * CreateWindowEx (USER.452)
1028 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1029 LPCSTR windowName, DWORD style, INT16 x,
1030 INT16 y, INT16 width, INT16 height,
1031 HWND16 parent, HMENU16 menu,
1032 HINSTANCE16 instance, LPVOID data )
1034 ATOM classAtom;
1035 CREATESTRUCTA cs;
1036 char buffer[256];
1038 /* Find the class atom */
1040 if (HIWORD(className))
1042 if (!(classAtom = GlobalFindAtomA( className )))
1044 ERR( "bad class name %s\n", debugres_a(className) );
1045 return 0;
1048 else
1050 classAtom = LOWORD(className);
1051 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1053 ERR( "bad atom %x\n", classAtom);
1054 return 0;
1056 className = buffer;
1059 /* Fix the coordinates */
1061 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1062 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1063 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1064 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1066 /* Create the window */
1068 cs.lpCreateParams = data;
1069 cs.hInstance = (HINSTANCE)instance;
1070 cs.hMenu = (HMENU)menu;
1071 cs.hwndParent = (HWND)parent;
1072 cs.style = style;
1073 cs.lpszName = windowName;
1074 cs.lpszClass = className;
1075 cs.dwExStyle = exStyle;
1077 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1081 /***********************************************************************
1082 * CreateWindowExA (USER32.@)
1084 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1085 LPCSTR windowName, DWORD style, INT x,
1086 INT y, INT width, INT height,
1087 HWND parent, HMENU menu,
1088 HINSTANCE instance, LPVOID data )
1090 ATOM classAtom;
1091 CREATESTRUCTA cs;
1092 char buffer[256];
1094 if(!instance)
1095 instance=GetModuleHandleA(NULL);
1097 if(exStyle & WS_EX_MDICHILD)
1098 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1100 /* Find the class atom */
1102 if (HIWORD(className))
1104 if (!(classAtom = GlobalFindAtomA( className )))
1106 ERR( "bad class name %s\n", debugres_a(className) );
1107 return 0;
1110 else
1112 classAtom = LOWORD(className);
1113 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1115 ERR( "bad atom %x\n", classAtom);
1116 return 0;
1118 className = buffer;
1121 /* Create the window */
1123 cs.lpCreateParams = data;
1124 cs.hInstance = instance;
1125 cs.hMenu = menu;
1126 cs.hwndParent = parent;
1127 cs.x = x;
1128 cs.y = y;
1129 cs.cx = width;
1130 cs.cy = height;
1131 cs.style = style;
1132 cs.lpszName = windowName;
1133 cs.lpszClass = className;
1134 cs.dwExStyle = exStyle;
1136 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1140 /***********************************************************************
1141 * CreateWindowExW (USER32.@)
1143 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1144 LPCWSTR windowName, DWORD style, INT x,
1145 INT y, INT width, INT height,
1146 HWND parent, HMENU menu,
1147 HINSTANCE instance, LPVOID data )
1149 ATOM classAtom;
1150 CREATESTRUCTW cs;
1151 WCHAR buffer[256];
1153 if(!instance)
1154 instance=GetModuleHandleA(NULL);
1156 if(exStyle & WS_EX_MDICHILD)
1157 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1159 /* Find the class atom */
1161 if (HIWORD(className))
1163 if (!(classAtom = GlobalFindAtomW( className )))
1165 ERR( "bad class name %s\n", debugres_w(className) );
1166 return 0;
1169 else
1171 classAtom = LOWORD(className);
1172 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1174 ERR( "bad atom %x\n", classAtom);
1175 return 0;
1177 className = buffer;
1180 /* Create the window */
1182 cs.lpCreateParams = data;
1183 cs.hInstance = instance;
1184 cs.hMenu = menu;
1185 cs.hwndParent = parent;
1186 cs.x = x;
1187 cs.y = y;
1188 cs.cx = width;
1189 cs.cy = height;
1190 cs.style = style;
1191 cs.lpszName = windowName;
1192 cs.lpszClass = className;
1193 cs.dwExStyle = exStyle;
1195 /* Note: we rely on the fact that CREATESTRUCTA and */
1196 /* CREATESTRUCTW have the same layout. */
1197 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1200 /***********************************************************************
1201 * WIN_SendDestroyMsg
1203 static void WIN_SendDestroyMsg( WND* pWnd )
1205 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1206 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1209 * Send the WM_DESTROY to the window.
1211 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1214 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1215 * make sure that the window still exists when we come back.
1217 if (IsWindow(pWnd->hwndSelf))
1219 HWND* pWndArray = NULL;
1220 WND* pChild = NULL;
1221 int nKidCount = 0;
1224 * Now, if the window has kids, we have to send WM_DESTROY messages
1225 * recursively to it's kids. It seems that those calls can also
1226 * trigger re-entrant calls to DestroyWindow for the kids so we must
1227 * protect against corruption of the list of siblings. We first build
1228 * a list of HWNDs representing all the kids.
1230 pChild = WIN_LockWndPtr(pWnd->child);
1231 while( pChild )
1233 nKidCount++;
1234 WIN_UpdateWndPtr(&pChild,pChild->next);
1238 * If there are no kids, we're done.
1240 if (nKidCount==0)
1241 return;
1243 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1246 * Sanity check
1248 if (pWndArray==NULL)
1249 return;
1252 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1253 * call, our linked list of siblings should be safe.
1255 nKidCount = 0;
1256 pChild = WIN_LockWndPtr(pWnd->child);
1257 while( pChild )
1259 pWndArray[nKidCount] = pChild->hwndSelf;
1260 nKidCount++;
1261 WIN_UpdateWndPtr(&pChild,pChild->next);
1265 * Now that we have a list, go through that list again and send the destroy
1266 * message to those windows. We are using the HWND to retrieve the
1267 * WND pointer so we are effectively checking that all the kid windows are
1268 * still valid before sending the message.
1270 while (nKidCount>0)
1272 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1274 if (pChild!=NULL)
1276 WIN_SendDestroyMsg( pChild );
1277 WIN_ReleaseWndPtr(pChild);
1282 * Cleanup
1284 HeapFree(GetProcessHeap(), 0, pWndArray);
1286 else
1287 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1291 /***********************************************************************
1292 * DestroyWindow (USER.53)
1294 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1296 return DestroyWindow(hwnd);
1300 /***********************************************************************
1301 * DestroyWindow (USER32.@)
1303 BOOL WINAPI DestroyWindow( HWND hwnd )
1305 WND * wndPtr;
1306 BOOL retvalue;
1307 HWND h;
1308 BOOL bFocusSet = FALSE;
1310 TRACE("(%04x)\n", hwnd);
1312 /* Initialization */
1314 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1315 if (wndPtr == pWndDesktop)
1317 retvalue = FALSE; /* Can't destroy desktop */
1318 goto end;
1321 /* Look whether the focus is within the tree of windows we will
1322 * be destroying.
1324 h = GetFocus16();
1325 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1327 if (h == hwnd)
1329 SetFocus(GetParent(h));
1330 bFocusSet = TRUE;
1331 break;
1333 h = GetParent(h);
1335 /* If the focus is on the window we will destroy and it has no parent,
1336 * set the focus to 0.
1338 if (! bFocusSet && (h == hwnd))
1340 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1341 SetFocus(0);
1344 /* Call hooks */
1346 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1348 retvalue = FALSE;
1349 goto end;
1352 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1354 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1355 /* FIXME: clean up palette - see "Internals" p.352 */
1358 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1359 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1361 /* Notify the parent window only */
1362 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1363 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1364 if( !IsWindow(hwnd) )
1366 retvalue = TRUE;
1367 goto end;
1371 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1373 /* Hide the window */
1375 if (wndPtr->dwStyle & WS_VISIBLE)
1377 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1378 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1379 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1380 if (!IsWindow(hwnd))
1382 retvalue = TRUE;
1383 goto end;
1387 /* Recursively destroy owned windows */
1389 if( !(wndPtr->dwStyle & WS_CHILD) )
1391 /* make sure top menu popup doesn't get destroyed */
1392 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1394 for (;;)
1396 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1397 while (siblingPtr)
1399 if (siblingPtr->owner == wndPtr)
1401 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1402 break;
1403 else
1404 siblingPtr->owner = NULL;
1406 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1408 if (siblingPtr)
1410 DestroyWindow( siblingPtr->hwndSelf );
1411 WIN_ReleaseWndPtr(siblingPtr);
1413 else break;
1416 if( !Options.managed || EVENT_CheckFocus() )
1417 WINPOS_ActivateOtherWindow(wndPtr);
1419 if( wndPtr->owner &&
1420 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1421 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1424 /* Send destroy messages */
1426 WIN_SendDestroyMsg( wndPtr );
1427 if (!IsWindow(hwnd))
1429 retvalue = TRUE;
1430 goto end;
1433 /* Unlink now so we won't bother with the children later on */
1435 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1437 /* Destroy the window storage */
1439 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1440 retvalue = TRUE;
1441 end:
1442 WIN_ReleaseWndPtr(wndPtr);
1443 return retvalue;
1447 /***********************************************************************
1448 * CloseWindow (USER.43)
1450 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1452 return CloseWindow( hwnd );
1456 /***********************************************************************
1457 * CloseWindow (USER32.@)
1459 BOOL WINAPI CloseWindow( HWND hwnd )
1461 WND * wndPtr = WIN_FindWndPtr( hwnd );
1462 BOOL retvalue;
1464 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1466 retvalue = FALSE;
1467 goto end;
1469 ShowWindow( hwnd, SW_MINIMIZE );
1470 retvalue = TRUE;
1471 end:
1472 WIN_ReleaseWndPtr(wndPtr);
1473 return retvalue;
1478 /***********************************************************************
1479 * OpenIcon (USER.44)
1481 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1483 return OpenIcon( hwnd );
1487 /***********************************************************************
1488 * OpenIcon (USER32.@)
1490 BOOL WINAPI OpenIcon( HWND hwnd )
1492 if (!IsIconic( hwnd )) return FALSE;
1493 ShowWindow( hwnd, SW_SHOWNORMAL );
1494 return TRUE;
1498 /***********************************************************************
1499 * WIN_FindWindow
1501 * Implementation of FindWindow() and FindWindowEx().
1503 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1504 LPCWSTR title )
1506 WND *pWnd;
1507 HWND retvalue;
1509 if (child)
1511 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1512 if (parent)
1514 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1516 retvalue = 0;
1517 goto end;
1520 else if (pWnd->parent != pWndDesktop)
1522 retvalue = 0;
1523 goto end;
1525 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1527 else
1529 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1531 retvalue = 0;
1532 goto end;
1534 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1536 if (!pWnd)
1538 retvalue = 0;
1539 goto end;
1542 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1544 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1545 continue; /* Not the right class */
1547 /* Now check the title */
1549 if (!title)
1551 retvalue = pWnd->hwndSelf;
1552 goto end;
1554 if (pWnd->text && !strcmpW( pWnd->text, title ))
1556 retvalue = pWnd->hwndSelf;
1557 goto end;
1560 retvalue = 0;
1561 /* In this case we need to check whether other processes
1562 own a window with the given paramters on the Desktop,
1563 but we don't, so let's at least warn about it */
1564 FIXME("Returning 0 without checking other processes\n");
1565 end:
1566 WIN_ReleaseWndPtr(pWnd);
1567 return retvalue;
1572 /***********************************************************************
1573 * FindWindow (USER.50)
1575 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1577 return FindWindowA( className, title );
1581 /***********************************************************************
1582 * FindWindowEx (USER.427)
1584 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1586 return FindWindowExA( parent, child, className, title );
1590 /***********************************************************************
1591 * FindWindowA (USER32.@)
1593 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1595 HWND ret = FindWindowExA( 0, 0, className, title );
1596 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1597 return ret;
1601 /***********************************************************************
1602 * FindWindowExA (USER32.@)
1604 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1605 LPCSTR className, LPCSTR title )
1607 ATOM atom = 0;
1608 LPWSTR buffer;
1609 HWND hwnd;
1611 if (className)
1613 /* If the atom doesn't exist, then no class */
1614 /* with this name exists either. */
1615 if (!(atom = GlobalFindAtomA( className )))
1617 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1618 return 0;
1622 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1623 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1624 HeapFree( GetProcessHeap(), 0, buffer );
1625 return hwnd;
1629 /***********************************************************************
1630 * FindWindowExW (USER32.@)
1632 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1633 LPCWSTR className, LPCWSTR title )
1635 ATOM atom = 0;
1637 if (className)
1639 /* If the atom doesn't exist, then no class */
1640 /* with this name exists either. */
1641 if (!(atom = GlobalFindAtomW( className )))
1643 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1644 return 0;
1647 return WIN_FindWindow( parent, child, atom, title );
1651 /***********************************************************************
1652 * FindWindowW (USER32.@)
1654 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1656 return FindWindowExW( 0, 0, className, title );
1660 /**********************************************************************
1661 * WIN_GetDesktop
1662 * returns a locked pointer
1664 WND *WIN_GetDesktop(void)
1666 return WIN_LockWndPtr(pWndDesktop);
1668 /**********************************************************************
1669 * WIN_ReleaseDesktop
1670 * unlock the desktop pointer
1672 void WIN_ReleaseDesktop(void)
1674 WIN_ReleaseWndPtr(pWndDesktop);
1678 /**********************************************************************
1679 * GetDesktopWindow (USER.286)
1681 HWND16 WINAPI GetDesktopWindow16(void)
1683 return (HWND16)pWndDesktop->hwndSelf;
1687 /**********************************************************************
1688 * GetDesktopWindow (USER32.@)
1690 HWND WINAPI GetDesktopWindow(void)
1692 if (pWndDesktop) return pWndDesktop->hwndSelf;
1693 ERR( "You need the -desktop option when running with native USER\n" );
1694 ExitProcess(1);
1695 return 0;
1699 /**********************************************************************
1700 * GetDesktopHwnd (USER.278)
1702 * Exactly the same thing as GetDesktopWindow(), but not documented.
1703 * Don't ask me why...
1705 HWND16 WINAPI GetDesktopHwnd16(void)
1707 return (HWND16)pWndDesktop->hwndSelf;
1711 /*******************************************************************
1712 * EnableWindow (USER.34)
1714 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1716 return EnableWindow( hwnd, enable );
1720 /*******************************************************************
1721 * EnableWindow (USER32.@)
1723 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1725 WND *wndPtr;
1726 BOOL retvalue;
1728 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1730 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1731 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1733 /* Enable window */
1734 wndPtr->dwStyle &= ~WS_DISABLED;
1736 if( wndPtr->flags & WIN_NATIVE )
1737 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1739 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1740 retvalue = TRUE;
1741 goto end;
1743 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1745 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1747 /* Disable window */
1748 wndPtr->dwStyle |= WS_DISABLED;
1750 if( wndPtr->flags & WIN_NATIVE )
1751 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1753 if (hwnd == GetFocus())
1755 SetFocus( 0 ); /* A disabled window can't have the focus */
1757 if (hwnd == GetCapture())
1759 ReleaseCapture(); /* A disabled window can't capture the mouse */
1761 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1762 retvalue = FALSE;
1763 goto end;
1765 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1766 end:
1767 WIN_ReleaseWndPtr(wndPtr);
1768 return retvalue;
1772 /***********************************************************************
1773 * IsWindowEnabled (USER.35)
1775 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1777 return IsWindowEnabled(hWnd);
1781 /***********************************************************************
1782 * IsWindowEnabled (USER32.@)
1784 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1786 WND * wndPtr;
1787 BOOL retvalue;
1789 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1790 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1791 WIN_ReleaseWndPtr(wndPtr);
1792 return retvalue;
1797 /***********************************************************************
1798 * IsWindowUnicode (USER32.@)
1800 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1802 WND * wndPtr;
1803 BOOL retvalue;
1805 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1806 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1807 WIN_ReleaseWndPtr(wndPtr);
1808 return retvalue;
1812 /**********************************************************************
1813 * GetWindowWord (USER.133)
1815 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1817 return GetWindowWord( hwnd, offset );
1821 /**********************************************************************
1822 * GetWindowWord (USER32.@)
1824 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1826 WORD retvalue;
1827 WND * wndPtr = WIN_FindWndPtr( hwnd );
1828 if (!wndPtr) return 0;
1829 if (offset >= 0)
1831 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1833 WARN("Invalid offset %d\n", offset );
1834 retvalue = 0;
1835 goto end;
1837 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1838 goto end;
1840 switch(offset)
1842 case GWW_ID:
1843 if (HIWORD(wndPtr->wIDmenu))
1844 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1845 wndPtr->wIDmenu);
1846 retvalue = (WORD)wndPtr->wIDmenu;
1847 goto end;
1848 case GWW_HWNDPARENT:
1849 retvalue = GetParent(hwnd);
1850 goto end;
1851 case GWW_HINSTANCE:
1852 if (HIWORD(wndPtr->hInstance))
1853 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1854 wndPtr->hInstance);
1855 retvalue = (WORD)wndPtr->hInstance;
1856 goto end;
1857 default:
1858 WARN("Invalid offset %d\n", offset );
1859 retvalue = 0;
1860 goto end;
1862 end:
1863 WIN_ReleaseWndPtr(wndPtr);
1864 return retvalue;
1867 /**********************************************************************
1868 * SetWindowWord (USER.134)
1870 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1872 return SetWindowWord( hwnd, offset, newval );
1876 /**********************************************************************
1877 * SetWindowWord (USER32.@)
1879 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1881 WORD *ptr, retval;
1882 WND * wndPtr = WIN_FindWndPtr( hwnd );
1883 if (!wndPtr) return 0;
1884 if (offset >= 0)
1886 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1888 WARN("Invalid offset %d\n", offset );
1889 retval = 0;
1890 goto end;
1892 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1894 else switch(offset)
1896 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1897 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1898 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1899 goto end;
1900 default:
1901 WARN("Invalid offset %d\n", offset );
1902 retval = 0;
1903 goto end;
1905 retval = *ptr;
1906 *ptr = newval;
1907 end:
1908 WIN_ReleaseWndPtr(wndPtr);
1909 return retval;
1913 /**********************************************************************
1914 * WIN_GetWindowLong
1916 * Helper function for GetWindowLong().
1918 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1920 LONG retvalue;
1921 WND * wndPtr = WIN_FindWndPtr( hwnd );
1922 if (!wndPtr) return 0;
1923 if (offset >= 0)
1925 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1927 WARN("Invalid offset %d\n", offset );
1928 retvalue = 0;
1929 goto end;
1931 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1932 /* Special case for dialog window procedure */
1933 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1935 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1936 goto end;
1938 goto end;
1940 switch(offset)
1942 case GWL_USERDATA: retvalue = wndPtr->userdata;
1943 goto end;
1944 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1945 goto end;
1946 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1947 goto end;
1948 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1949 goto end;
1950 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1951 type );
1952 goto end;
1953 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1954 goto end;
1955 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1956 goto end;
1957 default:
1958 WARN("Unknown offset %d\n", offset );
1960 retvalue = 0;
1961 end:
1962 WIN_ReleaseWndPtr(wndPtr);
1963 return retvalue;
1967 /**********************************************************************
1968 * WIN_SetWindowLong
1970 * Helper function for SetWindowLong().
1972 * 0 is the failure code. However, in the case of failure SetLastError
1973 * must be set to distinguish between a 0 return value and a failure.
1975 * FIXME: The error values for SetLastError may not be right. Can
1976 * someone check with the real thing?
1978 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1979 WINDOWPROCTYPE type )
1981 LONG *ptr, retval;
1982 WND * wndPtr = WIN_FindWndPtr( hwnd );
1983 STYLESTRUCT style;
1985 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1987 if (!wndPtr)
1989 /* Is this the right error? */
1990 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1991 return 0;
1994 if (offset >= 0)
1996 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1998 WARN("Invalid offset %d\n", offset );
2000 /* Is this the right error? */
2001 SetLastError( ERROR_OUTOFMEMORY );
2003 retval = 0;
2004 goto end;
2006 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2007 /* Special case for dialog window procedure */
2008 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2010 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2011 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2012 type, WIN_PROC_WINDOW );
2013 goto end;
2016 else switch(offset)
2018 case GWL_ID:
2019 ptr = (DWORD*)&wndPtr->wIDmenu;
2020 break;
2021 case GWL_HINSTANCE:
2022 retval = SetWindowWord( hwnd, offset, newval );
2023 goto end;
2024 case GWL_WNDPROC:
2025 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2026 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2027 type, WIN_PROC_WINDOW );
2028 goto end;
2029 case GWL_STYLE:
2030 style.styleOld = wndPtr->dwStyle;
2031 style.styleNew = newval;
2032 if (wndPtr->flags & WIN_ISWIN32)
2033 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2034 wndPtr->dwStyle = style.styleNew;
2035 if (wndPtr->flags & WIN_ISWIN32)
2036 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2037 retval = style.styleOld;
2038 goto end;
2040 case GWL_USERDATA:
2041 ptr = &wndPtr->userdata;
2042 break;
2043 case GWL_EXSTYLE:
2044 style.styleOld = wndPtr->dwExStyle;
2045 style.styleNew = newval;
2046 if (wndPtr->flags & WIN_ISWIN32)
2047 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2048 wndPtr->dwExStyle = newval;
2049 if (wndPtr->flags & WIN_ISWIN32)
2050 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2051 retval = style.styleOld;
2052 goto end;
2054 default:
2055 WARN("Invalid offset %d\n", offset );
2057 /* Don't think this is right error but it should do */
2058 SetLastError( ERROR_OUTOFMEMORY );
2060 retval = 0;
2061 goto end;
2063 retval = *ptr;
2064 *ptr = newval;
2065 end:
2066 WIN_ReleaseWndPtr(wndPtr);
2067 return retval;
2071 /**********************************************************************
2072 * GetWindowLong (USER.135)
2074 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2076 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2080 /**********************************************************************
2081 * GetWindowLongA (USER32.@)
2083 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2085 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2089 /**********************************************************************
2090 * GetWindowLongW (USER32.@)
2092 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2094 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2098 /**********************************************************************
2099 * SetWindowLong (USER.136)
2101 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2103 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2107 /**********************************************************************
2108 * SetWindowLongA (USER32.@)
2110 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2112 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2116 /**********************************************************************
2117 * SetWindowLongW (USER32.@) Set window attribute
2119 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2120 * value in a window's extra memory.
2122 * The _hwnd_ parameter specifies the window. is the handle to a
2123 * window that has extra memory. The _newval_ parameter contains the
2124 * new attribute or extra memory value. If positive, the _offset_
2125 * parameter is the byte-addressed location in the window's extra
2126 * memory to set. If negative, _offset_ specifies the window
2127 * attribute to set, and should be one of the following values:
2129 * GWL_EXSTYLE The window's extended window style
2131 * GWL_STYLE The window's window style.
2133 * GWL_WNDPROC Pointer to the window's window procedure.
2135 * GWL_HINSTANCE The window's pplication instance handle.
2137 * GWL_ID The window's identifier.
2139 * GWL_USERDATA The window's user-specified data.
2141 * If the window is a dialog box, the _offset_ parameter can be one of
2142 * the following values:
2144 * DWL_DLGPROC The address of the window's dialog box procedure.
2146 * DWL_MSGRESULT The return value of a message
2147 * that the dialog box procedure processed.
2149 * DWL_USER Application specific information.
2151 * RETURNS
2153 * If successful, returns the previous value located at _offset_. Otherwise,
2154 * returns 0.
2156 * NOTES
2158 * Extra memory for a window class is specified by a nonzero cbWndExtra
2159 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2160 * time of class creation.
2162 * Using GWL_WNDPROC to set a new window procedure effectively creates
2163 * a window subclass. Use CallWindowProc() in the new windows procedure
2164 * to pass messages to the superclass's window procedure.
2166 * The user data is reserved for use by the application which created
2167 * the window.
2169 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2170 * instead, call the EnableWindow() function to change the window's
2171 * disabled state.
2173 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2174 * SetParent() instead.
2176 * Win95:
2177 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2178 * it sends WM_STYLECHANGING before changing the settings
2179 * and WM_STYLECHANGED afterwards.
2180 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2182 * BUGS
2184 * GWL_STYLE does not dispatch WM_STYLE... messages.
2186 * CONFORMANCE
2188 * ECMA-234, Win32
2191 LONG WINAPI SetWindowLongW(
2192 HWND hwnd, /* [in] window to alter */
2193 INT offset, /* [in] offset, in bytes, of location to alter */
2194 LONG newval /* [in] new value of location */
2196 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2200 /*******************************************************************
2201 * GetWindowText (USER.36)
2203 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2205 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2209 /*******************************************************************
2210 * GetWindowTextA (USER32.@)
2212 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2214 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2215 (LPARAM)lpString );
2218 /*******************************************************************
2219 * InternalGetWindowText (USER32.@)
2221 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2223 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2224 return GetWindowTextW(hwnd,lpString,nMaxCount);
2228 /*******************************************************************
2229 * GetWindowTextW (USER32.@)
2231 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2233 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2234 (LPARAM)lpString );
2238 /*******************************************************************
2239 * SetWindowText (USER.37)
2241 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2243 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2247 /*******************************************************************
2248 * SetWindowText (USER32.@)
2250 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2252 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2256 /*******************************************************************
2257 * SetWindowTextW (USER32.@)
2259 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2261 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2265 /*******************************************************************
2266 * GetWindowTextLength (USER.38)
2268 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2270 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2274 /*******************************************************************
2275 * GetWindowTextLengthA (USER32.@)
2277 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2279 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2282 /*******************************************************************
2283 * GetWindowTextLengthW (USER32.@)
2285 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2287 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2291 /*******************************************************************
2292 * IsWindow (USER.47)
2294 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2296 CURRENT_STACK16->es = USER_HeapSel;
2297 return IsWindow( hwnd );
2301 /*******************************************************************
2302 * IsWindow (USER32.@)
2304 BOOL WINAPI IsWindow( HWND hwnd )
2306 WND * wndPtr;
2307 BOOL retvalue;
2309 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2310 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2311 WIN_ReleaseWndPtr(wndPtr);
2312 return retvalue;
2317 /*****************************************************************
2318 * GetParent (USER.46)
2320 HWND16 WINAPI GetParent16( HWND16 hwnd )
2322 return (HWND16)GetParent( hwnd );
2326 /*****************************************************************
2327 * GetParent (USER32.@)
2329 HWND WINAPI GetParent( HWND hwnd )
2331 WND *wndPtr;
2332 HWND retvalue = 0;
2334 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2335 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2336 goto end;
2338 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2339 if (wndPtr)
2340 retvalue = wndPtr->hwndSelf;
2342 end:
2343 WIN_ReleaseWndPtr(wndPtr);
2344 return retvalue;
2348 /*****************************************************************
2349 * WIN_GetTopParent
2351 * Get the top-level parent for a child window.
2352 * returns a locked pointer
2354 WND* WIN_GetTopParentPtr( WND* pWnd )
2356 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2358 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2360 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2362 return tmpWnd;
2365 /*****************************************************************
2366 * WIN_GetTopParent
2368 * Get the top-level parent for a child window.
2370 HWND WIN_GetTopParent( HWND hwnd )
2372 HWND retvalue;
2373 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2374 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2376 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2377 WIN_ReleaseWndPtr(tmpPtr);
2378 WIN_ReleaseWndPtr(wndPtr);
2379 return retvalue;
2383 /*****************************************************************
2384 * SetParent (USER.233)
2386 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2388 return SetParent( hwndChild, hwndNewParent );
2392 /*****************************************************************
2393 * SetParent (USER32.@)
2395 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2397 WND *wndPtr;
2398 DWORD dwStyle;
2399 WND *pWndNewParent;
2400 WND *pWndOldParent;
2401 HWND retvalue;
2404 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2406 dwStyle = wndPtr->dwStyle;
2408 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2409 : WIN_LockWndPtr(pWndDesktop);
2411 /* Windows hides the window first, then shows it again
2412 * including the WM_SHOWWINDOW messages and all */
2413 if (dwStyle & WS_VISIBLE)
2414 ShowWindow( hwndChild, SW_HIDE );
2416 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2418 /* SetParent additionally needs to make hwndChild the topmost window
2419 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2420 WM_WINDOWPOSCHANGED notification messages.
2422 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2423 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2424 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2425 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2427 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2429 WIN_ReleaseWndPtr(pWndOldParent);
2430 WIN_ReleaseWndPtr(pWndNewParent);
2431 WIN_ReleaseWndPtr(wndPtr);
2433 return retvalue;
2437 /*******************************************************************
2438 * IsChild (USER.48)
2440 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2442 return IsChild(parent,child);
2446 /*******************************************************************
2447 * IsChild (USER32.@)
2449 BOOL WINAPI IsChild( HWND parent, HWND child )
2451 WND * wndPtr = WIN_FindWndPtr( child );
2452 while (wndPtr && wndPtr->parent)
2454 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2455 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2456 if (wndPtr->hwndSelf == parent)
2458 WIN_ReleaseWndPtr(wndPtr);
2459 return TRUE;
2462 WIN_ReleaseWndPtr(wndPtr);
2463 return FALSE;
2467 /***********************************************************************
2468 * IsWindowVisible (USER.49)
2470 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2472 return IsWindowVisible(hwnd);
2476 /***********************************************************************
2477 * IsWindowVisible (USER32.@)
2479 BOOL WINAPI IsWindowVisible( HWND hwnd )
2481 BOOL retval;
2482 WND *wndPtr = WIN_FindWndPtr( hwnd );
2483 while (wndPtr && wndPtr->parent)
2485 if (!(wndPtr->dwStyle & WS_VISIBLE))
2487 WIN_ReleaseWndPtr(wndPtr);
2488 return FALSE;
2490 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2492 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2493 WIN_ReleaseWndPtr(wndPtr);
2494 return retval;
2498 /***********************************************************************
2499 * WIN_IsWindowDrawable
2501 * hwnd is drawable when it is visible, all parents are not
2502 * minimized, and it is itself not minimized unless we are
2503 * trying to draw its default class icon.
2505 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2507 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2508 if ((wnd->dwStyle & WS_MINIMIZE) &&
2509 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2510 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2511 if( wnd->dwStyle & WS_MINIMIZE ||
2512 !(wnd->dwStyle & WS_VISIBLE) ) break;
2513 return (wnd == NULL);
2517 /*******************************************************************
2518 * GetTopWindow (USER.229)
2520 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2522 return GetTopWindow(hwnd);
2526 /*******************************************************************
2527 * GetTopWindow (USER32.@)
2529 HWND WINAPI GetTopWindow( HWND hwnd )
2531 HWND retval = 0;
2532 WND * wndPtr = (hwnd) ?
2533 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2535 if (wndPtr && wndPtr->child)
2536 retval = wndPtr->child->hwndSelf;
2538 WIN_ReleaseWndPtr(wndPtr);
2539 return retval;
2543 /*******************************************************************
2544 * GetWindow (USER.262)
2546 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2548 return GetWindow( hwnd,rel );
2552 /*******************************************************************
2553 * GetWindow (USER32.@)
2555 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2557 HWND retval;
2559 WND * wndPtr = WIN_FindWndPtr( hwnd );
2560 if (!wndPtr) return 0;
2561 switch(rel)
2563 case GW_HWNDFIRST:
2564 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2565 goto end;
2567 case GW_HWNDLAST:
2568 if (!wndPtr->parent)
2570 retval = 0; /* Desktop window */
2571 goto end;
2573 while (wndPtr->next)
2575 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2577 retval = wndPtr->hwndSelf;
2578 goto end;
2580 case GW_HWNDNEXT:
2581 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2582 goto end;
2584 case GW_HWNDPREV:
2585 if (!wndPtr->parent)
2587 retval = 0; /* Desktop window */
2588 goto end;
2590 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2591 if (wndPtr->hwndSelf == hwnd)
2593 retval = 0; /* First in list */
2594 goto end;
2596 while (wndPtr->next)
2598 if (wndPtr->next->hwndSelf == hwnd)
2600 retval = wndPtr->hwndSelf;
2601 goto end;
2603 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2605 retval = 0;
2606 goto end;
2608 case GW_OWNER:
2609 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2610 goto end;
2612 case GW_CHILD:
2613 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2614 goto end;
2616 retval = 0;
2617 end:
2618 WIN_ReleaseWndPtr(wndPtr);
2619 return retval;
2623 /*******************************************************************
2624 * GetNextWindow (USER.230)
2626 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2628 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2629 return GetWindow16( hwnd, flag );
2632 /***********************************************************************
2633 * WIN_InternalShowOwnedPopups
2635 * Internal version of ShowOwnedPopups; Wine functions should use this
2636 * to avoid interfering with application calls to ShowOwnedPopups
2637 * and to make sure the application can't prevent showing/hiding.
2639 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2643 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2645 INT totalChild=0, count=0;
2647 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2649 if (!pWnd) return TRUE;
2652 * Show windows Lowest first, Highest last to preserve Z-Order
2654 for (count = totalChild-1 ; count >=0; count--)
2656 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2658 if (fShow)
2660 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2661 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2664 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2666 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2667 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2670 else
2672 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2673 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2674 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2677 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2679 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2680 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2681 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2686 WIN_ReleaseDesktop();
2687 WIN_ReleaseWinArray(pWnd);
2689 return TRUE;
2692 /*******************************************************************
2693 * ShowOwnedPopups (USER.265)
2695 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2697 ShowOwnedPopups( owner, fShow );
2701 /*******************************************************************
2702 * ShowOwnedPopups (USER32.@)
2704 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2706 UINT totalChild=0, count=0;
2708 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2710 if (!pWnd) return TRUE;
2712 for (; count < totalChild; count++)
2714 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2716 if (fShow)
2718 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2721 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2722 * regardless of the state of the owner
2724 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2725 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2728 else
2730 if (IsWindowVisible(pWnd[count]->hwndSelf))
2733 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2734 * regardless of the state of the owner
2736 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2737 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2743 WIN_ReleaseDesktop();
2744 WIN_ReleaseWinArray(pWnd);
2745 return TRUE;
2749 /*******************************************************************
2750 * GetLastActivePopup (USER.287)
2752 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2754 return GetLastActivePopup( hwnd );
2757 /*******************************************************************
2758 * GetLastActivePopup (USER32.@)
2760 HWND WINAPI GetLastActivePopup( HWND hwnd )
2762 HWND retval;
2763 WND *wndPtr =WIN_FindWndPtr(hwnd);
2764 if (!wndPtr) return hwnd;
2765 retval = wndPtr->hwndLastActive;
2766 WIN_ReleaseWndPtr(wndPtr);
2767 if ((retval != hwnd) && (!IsWindow(retval)))
2768 retval = hwnd;
2769 return retval;
2773 /*******************************************************************
2774 * WIN_BuildWinArray
2776 * Build an array of pointers to the children of a given window.
2777 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2778 * when no windows are found.
2780 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2782 /* Future: this function will lock all windows associated with this array */
2784 WND **list, **ppWnd;
2785 WND *pWnd;
2786 UINT count = 0, skipOwned, skipHidden;
2787 DWORD skipFlags;
2789 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2790 skipOwned = bwaFlags & BWA_SKIPOWNED;
2791 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2792 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2794 /* First count the windows */
2796 if (!wndPtr)
2797 wndPtr = WIN_GetDesktop();
2799 pWnd = WIN_LockWndPtr(wndPtr->child);
2800 while (pWnd)
2802 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2803 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2804 count++;
2805 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2808 if( count )
2810 /* Now build the list of all windows */
2812 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2814 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2816 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2817 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2819 *ppWnd++ = pWnd;
2820 count++;
2823 WIN_ReleaseWndPtr(pWnd);
2824 *ppWnd = NULL;
2826 else count = 0;
2827 } else list = NULL;
2829 if( pTotal ) *pTotal = count;
2830 return list;
2832 /*******************************************************************
2833 * WIN_ReleaseWinArray
2835 void WIN_ReleaseWinArray(WND **wndArray)
2837 /* Future: this function will also unlock all windows associated with wndArray */
2838 HeapFree( GetProcessHeap(), 0, wndArray );
2842 /*******************************************************************
2843 * EnumWindows (USER32.@)
2845 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2847 WND **list, **ppWnd;
2849 /* We have to build a list of all windows first, to avoid */
2850 /* unpleasant side-effects, for instance if the callback */
2851 /* function changes the Z-order of the windows. */
2853 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2855 WIN_ReleaseDesktop();
2856 return FALSE;
2859 /* Now call the callback function for every window */
2861 for (ppWnd = list; *ppWnd; ppWnd++)
2863 LRESULT lpEnumFuncRetval;
2864 int iWndsLocks = 0;
2865 /* Make sure that the window still exists */
2866 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2868 /* To avoid any deadlocks, all the locks on the windows
2869 structures must be suspended before the control
2870 is passed to the application */
2871 iWndsLocks = WIN_SuspendWndsLock();
2872 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2873 WIN_RestoreWndsLock(iWndsLocks);
2875 if (!lpEnumFuncRetval) break;
2877 WIN_ReleaseWinArray(list);
2878 WIN_ReleaseDesktop();
2879 return TRUE;
2883 /**********************************************************************
2884 * WIN_EnumQueueWindows
2886 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2888 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2890 WND **list, **ppWnd;
2892 /* This function is the same as EnumWindows(), */
2893 /* except for an added check on the window's task. */
2895 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2897 WIN_ReleaseDesktop();
2898 return FALSE;
2901 /* Now call the callback function for every window */
2903 for (ppWnd = list; *ppWnd; ppWnd++)
2905 LRESULT funcRetval;
2906 int iWndsLocks = 0;
2907 /* Make sure that the window still exists */
2908 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2909 if ((*ppWnd)->hmemTaskQ != queue) continue;
2911 /* To avoid any deadlocks, all the locks on the windows
2912 structures must be suspended before the control
2913 is passed to the application */
2914 iWndsLocks = WIN_SuspendWndsLock();
2915 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2916 WIN_RestoreWndsLock(iWndsLocks);
2918 if (!funcRetval) break;
2920 WIN_ReleaseWinArray(list);
2921 WIN_ReleaseDesktop();
2922 return TRUE;
2926 /**********************************************************************
2927 * EnumTaskWindows16 (USER.225)
2929 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2930 LPARAM lParam )
2932 HQUEUE16 queue = GetTaskQueue16( hTask );
2933 if (!queue) return FALSE;
2934 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2938 /**********************************************************************
2939 * EnumThreadWindows (USER32.@)
2941 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2943 HQUEUE16 queue = GetThreadQueue16( id );
2944 if (!queue) return FALSE;
2945 return WIN_EnumQueueWindows( queue, func, lParam );
2949 /**********************************************************************
2950 * WIN_EnumChildWindows
2952 * Helper function for EnumChildWindows().
2954 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2956 WND **childList;
2957 BOOL16 ret = FALSE;
2959 for ( ; *ppWnd; ppWnd++)
2961 int iWndsLocks = 0;
2963 /* Make sure that the window still exists */
2964 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2965 /* Build children list first */
2966 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2968 /* To avoid any deadlocks, all the locks on the windows
2969 structures must be suspended before the control
2970 is passed to the application */
2971 iWndsLocks = WIN_SuspendWndsLock();
2972 ret = func( (*ppWnd)->hwndSelf, lParam );
2973 WIN_RestoreWndsLock(iWndsLocks);
2975 if (childList)
2977 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2978 WIN_ReleaseWinArray(childList);
2980 if (!ret) return FALSE;
2982 return TRUE;
2986 /**********************************************************************
2987 * EnumChildWindows (USER32.@)
2989 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2990 LPARAM lParam )
2992 WND **list, *pParent;
2994 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2995 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2997 WIN_ReleaseWndPtr(pParent);
2998 return FALSE;
3000 WIN_EnumChildWindows( list, func, lParam );
3001 WIN_ReleaseWinArray(list);
3002 WIN_ReleaseWndPtr(pParent);
3003 return TRUE;
3007 /*******************************************************************
3008 * AnyPopup (USER.52)
3010 BOOL16 WINAPI AnyPopup16(void)
3012 return AnyPopup();
3016 /*******************************************************************
3017 * AnyPopup (USER32.@)
3019 BOOL WINAPI AnyPopup(void)
3021 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3022 BOOL retvalue;
3024 while (wndPtr)
3026 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3028 retvalue = TRUE;
3029 goto end;
3031 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3033 retvalue = FALSE;
3034 end:
3035 WIN_ReleaseWndPtr(wndPtr);
3036 return retvalue;
3040 /*******************************************************************
3041 * FlashWindow (USER.105)
3043 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3045 return FlashWindow( hWnd, bInvert );
3049 /*******************************************************************
3050 * FlashWindow (USER32.@)
3052 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3054 WND *wndPtr = WIN_FindWndPtr(hWnd);
3056 TRACE("%04x\n", hWnd);
3058 if (!wndPtr) return FALSE;
3060 if (wndPtr->dwStyle & WS_MINIMIZE)
3062 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3064 HDC hDC = GetDC(hWnd);
3066 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3067 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3069 ReleaseDC( hWnd, hDC );
3070 wndPtr->flags |= WIN_NCACTIVATED;
3072 else
3074 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3075 RDW_UPDATENOW | RDW_FRAME, 0 );
3076 wndPtr->flags &= ~WIN_NCACTIVATED;
3078 WIN_ReleaseWndPtr(wndPtr);
3079 return TRUE;
3081 else
3083 WPARAM16 wparam;
3084 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3085 else wparam = (hWnd == GetActiveWindow());
3087 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3088 WIN_ReleaseWndPtr(wndPtr);
3089 return wparam;
3094 /*******************************************************************
3095 * SetSysModalWindow (USER.188)
3097 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3099 HWND hWndOldModal = hwndSysModal;
3100 hwndSysModal = hWnd;
3101 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3102 return hWndOldModal;
3106 /*******************************************************************
3107 * GetSysModalWindow (USER.189)
3109 HWND16 WINAPI GetSysModalWindow16(void)
3111 return hwndSysModal;
3115 /*******************************************************************
3116 * GetWindowContextHelpId (USER32.@)
3118 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3120 DWORD retval;
3121 WND *wnd = WIN_FindWndPtr( hwnd );
3122 if (!wnd) return 0;
3123 retval = wnd->helpContext;
3124 WIN_ReleaseWndPtr(wnd);
3125 return retval;
3129 /*******************************************************************
3130 * SetWindowContextHelpId (USER32.@)
3132 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3134 WND *wnd = WIN_FindWndPtr( hwnd );
3135 if (!wnd) return FALSE;
3136 wnd->helpContext = id;
3137 WIN_ReleaseWndPtr(wnd);
3138 return TRUE;
3142 /*******************************************************************
3143 * DRAG_QueryUpdate
3145 * recursively find a child that contains spDragInfo->pt point
3146 * and send WM_QUERYDROPOBJECT
3148 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3150 BOOL16 wParam, bResult = 0;
3151 POINT pt;
3152 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3153 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3154 RECT tempRect;
3156 if( !ptrQueryWnd || !ptrDragInfo )
3157 goto end;
3159 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3161 GetWindowRect(hQueryWnd,&tempRect);
3163 if( !PtInRect(&tempRect,pt) ||
3164 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3165 goto end;
3167 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3169 tempRect = ptrQueryWnd->rectClient;
3170 if(ptrQueryWnd->parent)
3171 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3172 (LPPOINT)&tempRect, 2 );
3174 if (PtInRect( &tempRect, pt))
3176 wParam = 0;
3178 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3180 if( ptrWnd->dwStyle & WS_VISIBLE )
3182 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3183 if (PtInRect( &tempRect, pt )) break;
3187 if(ptrWnd)
3189 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3190 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3191 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3192 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3193 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3195 WIN_ReleaseWndPtr(ptrWnd);
3198 if(bResult)
3199 goto end;
3201 else wParam = 1;
3203 else wParam = 1;
3205 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3207 ptrDragInfo->hScope = hQueryWnd;
3209 bResult = ( bNoSend )
3210 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3211 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3212 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3213 if( !bResult )
3214 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3216 end:
3217 WIN_ReleaseWndPtr(ptrQueryWnd);
3218 return bResult;
3222 /*******************************************************************
3223 * DragDetect (USER.465)
3225 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3227 POINT pt32;
3228 CONV_POINT16TO32( &pt, &pt32 );
3229 return DragDetect( hWnd, pt32 );
3232 /*******************************************************************
3233 * DragDetect (USER32.@)
3235 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3237 MSG msg;
3238 RECT rect;
3240 rect.left = pt.x - wDragWidth;
3241 rect.right = pt.x + wDragWidth;
3243 rect.top = pt.y - wDragHeight;
3244 rect.bottom = pt.y + wDragHeight;
3246 SetCapture(hWnd);
3248 while(1)
3250 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3252 if( msg.message == WM_LBUTTONUP )
3254 ReleaseCapture();
3255 return 0;
3257 if( msg.message == WM_MOUSEMOVE )
3259 POINT tmp;
3260 tmp.x = LOWORD(msg.lParam);
3261 tmp.y = HIWORD(msg.lParam);
3262 if( !PtInRect( &rect, tmp ))
3264 ReleaseCapture();
3265 return 1;
3269 WaitMessage();
3271 return 0;
3274 /******************************************************************************
3275 * DragObject (USER.464)
3277 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3278 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3280 MSG msg;
3281 LPDRAGINFO16 lpDragInfo;
3282 SEGPTR spDragInfo;
3283 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3284 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3285 WND *wndPtr = WIN_FindWndPtr(hWnd);
3286 HCURSOR16 hCurrentCursor = 0;
3287 HWND16 hCurrentWnd = 0;
3289 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3290 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3292 if( !lpDragInfo || !spDragInfo )
3294 WIN_ReleaseWndPtr(wndPtr);
3295 return 0L;
3298 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3300 if( !hBummer || !wndPtr )
3302 GlobalFree16(hDragInfo);
3303 WIN_ReleaseWndPtr(wndPtr);
3304 return 0L;
3307 if(hCursor)
3309 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3311 GlobalFree16(hDragInfo);
3312 WIN_ReleaseWndPtr(wndPtr);
3313 return 0L;
3316 if( hDragCursor == hCursor ) hDragCursor = 0;
3317 else hCursor = hDragCursor;
3319 hOldCursor = SetCursor(hDragCursor);
3322 lpDragInfo->hWnd = hWnd;
3323 lpDragInfo->hScope = 0;
3324 lpDragInfo->wFlags = wObj;
3325 lpDragInfo->hList = szList; /* near pointer! */
3326 lpDragInfo->hOfStruct = hOfStruct;
3327 lpDragInfo->l = 0L;
3329 SetCapture(hWnd);
3330 ShowCursor( TRUE );
3334 do{ WaitMessage(); }
3335 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3337 *(lpDragInfo+1) = *lpDragInfo;
3339 lpDragInfo->pt.x = msg.pt.x;
3340 lpDragInfo->pt.y = msg.pt.y;
3342 /* update DRAGINFO struct */
3343 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3345 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3346 hCurrentCursor = hCursor;
3347 else
3349 hCurrentCursor = hBummer;
3350 lpDragInfo->hScope = 0;
3352 if( hCurrentCursor )
3353 SetCursor(hCurrentCursor);
3355 /* send WM_DRAGLOOP */
3356 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3357 (LPARAM) spDragInfo );
3358 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3359 if( hCurrentWnd != lpDragInfo->hScope )
3361 if( hCurrentWnd )
3362 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3363 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3364 HIWORD(spDragInfo)) );
3365 hCurrentWnd = lpDragInfo->hScope;
3366 if( hCurrentWnd )
3367 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3369 else
3370 if( hCurrentWnd )
3371 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3373 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3375 ReleaseCapture();
3376 ShowCursor( FALSE );
3378 if( hCursor )
3380 SetCursor( hOldCursor );
3381 if (hDragCursor) DestroyCursor( hDragCursor );
3384 if( hCurrentCursor != hBummer )
3385 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3386 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3387 else
3388 msg.lParam = 0;
3389 GlobalFree16(hDragInfo);
3390 WIN_ReleaseWndPtr(wndPtr);
3392 return (DWORD)(msg.lParam);
3396 /******************************************************************************
3397 * GetWindowModuleFileNameA (USER32.@)
3399 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3401 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3402 hwnd, lpszFileName, cchFileNameMax);
3403 return 0;
3406 /******************************************************************************
3407 * GetWindowModuleFileNameW (USER32.@)
3409 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3411 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3412 hwnd, lpszFileName, cchFileNameMax);
3413 return 0;