Removed SUBDIRS in winmm Makefile.
[wine/multimedia.git] / windows / win.c
blobb35f52ff73252fa17f12cf85b750eace88c012a4
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 "wingdi.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/unicode.h"
14 #include "options.h"
15 #include "class.h"
16 #include "win.h"
17 #include "heap.h"
18 #include "user.h"
19 #include "dce.h"
20 #include "cursoricon.h"
21 #include "hook.h"
22 #include "menu.h"
23 #include "message.h"
24 #include "nonclient.h"
25 #include "queue.h"
26 #include "winpos.h"
27 #include "clipboard.h"
28 #include "winproc.h"
29 #include "task.h"
30 #include "thread.h"
31 #include "winerror.h"
32 #include "mdi.h"
33 #include "local.h"
34 #include "syslevel.h"
35 #include "stackframe.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(win);
39 DECLARE_DEBUG_CHANNEL(msg);
41 /**********************************************************************/
43 WND_DRIVER *WND_Driver = NULL;
45 /* Desktop window */
46 static WND *pWndDesktop = NULL;
48 static HWND hwndSysModal = 0;
50 static WORD wDragWidth = 4;
51 static WORD wDragHeight= 3;
53 /* thread safeness */
54 static SYSLEVEL WIN_SysLevel;
56 /***********************************************************************
57 * WIN_Init
58 */
59 void WIN_Init( void )
61 /* Initialisation of the critical section for thread safeness */
62 _CreateSysLevel( &WIN_SysLevel, 2 );
65 /***********************************************************************
66 * WIN_LockWnds
68 * Locks access to all WND structures for thread safeness
70 void WIN_LockWnds( void )
72 _EnterSysLevel( &WIN_SysLevel );
75 /***********************************************************************
76 * WIN_UnlockWnds
78 * Unlocks access to all WND structures
80 void WIN_UnlockWnds( void )
82 _LeaveSysLevel( &WIN_SysLevel );
85 /***********************************************************************
86 * WIN_SuspendWndsLock
88 * Suspend the lock on WND structures.
89 * Returns the number of locks suspended
91 int WIN_SuspendWndsLock( void )
93 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
94 int count = isuspendedLocks;
96 while ( count-- > 0 )
97 _LeaveSysLevel( &WIN_SysLevel );
99 return isuspendedLocks;
102 /***********************************************************************
103 * WIN_RestoreWndsLock
105 * Restore the suspended locks on WND structures
107 void WIN_RestoreWndsLock( int ipreviousLocks )
109 while ( ipreviousLocks-- > 0 )
110 _EnterSysLevel( &WIN_SysLevel );
113 /***********************************************************************
114 * WIN_FindWndPtr
116 * Return a pointer to the WND structure corresponding to a HWND.
118 WND * WIN_FindWndPtr( HWND hwnd )
120 WND * ptr;
122 if (!hwnd || HIWORD(hwnd)) goto error2;
123 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
124 /* Lock all WND structures for thread safeness*/
125 WIN_LockWnds();
126 /*and increment destruction monitoring*/
127 ptr->irefCount++;
129 if (ptr->dwMagic != WND_MAGIC) goto error;
130 if (ptr->hwndSelf != hwnd)
132 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
133 goto error;
135 /* returns a locked pointer */
136 return ptr;
137 error:
138 /* Unlock all WND structures for thread safeness*/
139 WIN_UnlockWnds();
140 /* and decrement destruction monitoring value */
141 ptr->irefCount--;
143 error2:
144 if ( hwnd!=0 )
145 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
146 return NULL;
149 /***********************************************************************
150 * WIN_LockWndPtr
152 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
153 * but by initWndPtr;
154 * Returns the locked initialisation pointer
156 WND *WIN_LockWndPtr(WND *initWndPtr)
158 if(!initWndPtr) return 0;
160 /* Lock all WND structures for thread safeness*/
161 WIN_LockWnds();
162 /*and increment destruction monitoring*/
163 initWndPtr->irefCount++;
165 return initWndPtr;
169 /***********************************************************************
170 * WIN_ReleaseWndPtr
172 * Release the pointer to the WND structure.
174 void WIN_ReleaseWndPtr(WND *wndPtr)
176 if(!wndPtr) return;
178 /*Decrement destruction monitoring value*/
179 wndPtr->irefCount--;
180 /* Check if it's time to release the memory*/
181 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
183 /* Release memory */
184 USER_HEAP_FREE( wndPtr->hwndSelf);
185 wndPtr->hwndSelf = 0;
187 else if(wndPtr->irefCount < 0)
189 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
190 ERR("forgot a Lock on %p somewhere\n",wndPtr);
192 /*unlock all WND structures for thread safeness*/
193 WIN_UnlockWnds();
196 /***********************************************************************
197 * WIN_UpdateWndPtr
199 * Updates the value of oldPtr to newPtr.
201 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
203 WND *tmpWnd = NULL;
205 tmpWnd = WIN_LockWndPtr(newPtr);
206 WIN_ReleaseWndPtr(*oldPtr);
207 *oldPtr = tmpWnd;
211 /***********************************************************************
212 * WIN_DumpWindow
214 * Dump the content of a window structure to stderr.
216 void WIN_DumpWindow( HWND hwnd )
218 WND *ptr;
219 char className[80];
220 int i;
222 if (!(ptr = WIN_FindWndPtr( hwnd )))
224 WARN("%04x is not a window handle\n", hwnd );
225 return;
228 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
229 strcpy( className, "#NULL#" );
231 TRACE("Window %04x (%p):\n", hwnd, ptr );
232 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
233 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
234 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
235 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
236 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
237 ptr->next, ptr->child, ptr->parent, ptr->owner,
238 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
239 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
240 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
241 ptr->text ? debugstr_w(ptr->text) : "",
242 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
243 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
244 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
245 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
247 if (ptr->class->cbWndExtra)
249 DPRINTF( "extra bytes:" );
250 for (i = 0; i < ptr->class->cbWndExtra; i++)
251 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
252 DPRINTF( "\n" );
254 DPRINTF( "\n" );
255 WIN_ReleaseWndPtr(ptr);
259 /***********************************************************************
260 * WIN_WalkWindows
262 * Walk the windows tree and print each window on stderr.
264 void WIN_WalkWindows( HWND hwnd, int indent )
266 WND *ptr;
267 char className[80];
269 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
271 if (!ptr)
273 WARN("Invalid window handle %04x\n", hwnd );
274 return;
277 if (!indent) /* first time around */
278 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
279 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
280 " Text");
282 while (ptr)
284 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
286 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
288 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
289 (DWORD)ptr, ptr->hmemTaskQ, className,
290 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
291 ptr->text ? debugstr_w(ptr->text) : "<null>");
293 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
294 WIN_UpdateWndPtr(&ptr,ptr->next);
300 /***********************************************************************
301 * WIN_UnlinkWindow
303 * Remove a window from the siblings linked list.
305 BOOL WIN_UnlinkWindow( HWND hwnd )
307 WND *wndPtr, **ppWnd;
308 BOOL ret = FALSE;
310 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
311 else if(!wndPtr->parent)
313 WIN_ReleaseWndPtr(wndPtr);
314 return FALSE;
317 ppWnd = &wndPtr->parent->child;
318 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
319 if (*ppWnd)
321 *ppWnd = wndPtr->next;
322 ret = TRUE;
324 WIN_ReleaseWndPtr(wndPtr);
325 return ret;
329 /***********************************************************************
330 * WIN_LinkWindow
332 * Insert a window into the siblings linked list.
333 * The window is inserted after the specified window, which can also
334 * be specified as HWND_TOP or HWND_BOTTOM.
336 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
338 WND *wndPtr, **ppWnd;
340 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
341 else if(!wndPtr->parent)
343 WIN_ReleaseWndPtr(wndPtr);
344 return FALSE;
346 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
348 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
349 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
350 while (*ppWnd) ppWnd = &(*ppWnd)->next;
352 else /* Normal case */
354 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
355 if (!afterPtr)
357 WIN_ReleaseWndPtr(wndPtr);
358 return FALSE;
360 ppWnd = &afterPtr->next;
361 WIN_ReleaseWndPtr(afterPtr);
363 wndPtr->next = *ppWnd;
364 *ppWnd = wndPtr;
365 WIN_ReleaseWndPtr(wndPtr);
366 return TRUE;
370 /***********************************************************************
371 * WIN_FindWinToRepaint
373 * Find a window that needs repaint.
375 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
377 HWND hwndRet;
378 WND *pWnd;
380 /* Note: the desktop window never gets WM_PAINT messages
381 * The real reason why is because Windows DesktopWndProc
382 * does ValidateRgn inside WM_ERASEBKGND handler.
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE))
391 TRACE("skipping window %04x\n",
392 pWnd->hwndSelf );
394 else if ((pWnd->hmemTaskQ == hQueue) &&
395 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
396 break;
398 else if (pWnd->child )
399 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
401 WIN_ReleaseWndPtr(pWnd);
402 return hwndRet;
407 if(!pWnd)
409 return 0;
412 hwndRet = pWnd->hwndSelf;
414 /* look among siblings if we got a transparent window */
415 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
416 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
418 WIN_UpdateWndPtr(&pWnd,pWnd->next);
420 if (pWnd)
422 hwndRet = pWnd->hwndSelf;
423 WIN_ReleaseWndPtr(pWnd);
425 TRACE("found %04x\n",hwndRet);
426 return hwndRet;
430 /***********************************************************************
431 * WIN_DestroyWindow
433 * Destroy storage associated to a window. "Internals" p.358
434 * returns a locked wndPtr->next
436 static WND* WIN_DestroyWindow( WND* wndPtr )
438 HWND hwnd = wndPtr->hwndSelf;
439 WND *pWnd;
441 TRACE("%04x\n", wndPtr->hwndSelf );
443 /* free child windows */
444 WIN_LockWndPtr(wndPtr->child);
445 while ((pWnd = wndPtr->child))
447 wndPtr->child = WIN_DestroyWindow( pWnd );
448 WIN_ReleaseWndPtr(pWnd);
452 * Clear the update region to make sure no WM_PAINT messages will be
453 * generated for this window while processing the WM_NCDESTROY.
455 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
457 if (wndPtr->hrgnUpdate > 1)
458 DeleteObject( wndPtr->hrgnUpdate );
460 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
462 wndPtr->hrgnUpdate = 0;
466 * Send the WM_NCDESTROY to the window being destroyed.
468 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
470 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
472 WINPOS_CheckInternalPos( wndPtr );
473 if( hwnd == GetCapture()) ReleaseCapture();
475 /* free resources associated with the window */
477 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
478 PROPERTY_RemoveWindowProps( wndPtr );
480 wndPtr->dwMagic = 0; /* Mark it as invalid */
482 /* toss stale messages from the queue */
484 if( wndPtr->hmemTaskQ )
486 BOOL bPostQuit = FALSE;
487 WPARAM wQuitParam = 0;
488 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
489 QMSG *qmsg;
491 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
493 if( qmsg->msg.message == WM_QUIT )
495 bPostQuit = TRUE;
496 wQuitParam = qmsg->msg.wParam;
498 QUEUE_RemoveMsg(msgQ, qmsg);
501 QUEUE_Unlock(msgQ);
503 /* repost WM_QUIT to make sure this app exits its message loop */
504 if( bPostQuit ) PostQuitMessage(wQuitParam);
505 wndPtr->hmemTaskQ = 0;
508 if (!(wndPtr->dwStyle & WS_CHILD))
509 if (wndPtr->wIDmenu)
511 DestroyMenu( wndPtr->wIDmenu );
512 wndPtr->wIDmenu = 0;
514 if (wndPtr->hSysMenu)
516 DestroyMenu( wndPtr->hSysMenu );
517 wndPtr->hSysMenu = 0;
519 wndPtr->pDriver->pDestroyWindow( wndPtr );
520 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
521 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
522 wndPtr->class->cWindows--;
523 wndPtr->class = NULL;
525 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
527 wndPtr->pDriver->pFinalize(wndPtr);
529 return pWnd;
532 /***********************************************************************
533 * WIN_ResetQueueWindows
535 * Reset the queue of all the children of a given window.
536 * Return TRUE if something was done.
538 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
540 BOOL ret = FALSE;
542 if (hNew) /* Set a new queue */
544 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
546 if (wnd->hmemTaskQ == hQueue)
548 wnd->hmemTaskQ = hNew;
549 ret = TRUE;
551 if (wnd->child)
553 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
557 else /* Queue is being destroyed */
559 while (wnd->child)
561 WND *tmp = WIN_LockWndPtr(wnd->child);
562 WND *tmp2;
563 ret = FALSE;
564 while (tmp)
566 if (tmp->hmemTaskQ == hQueue)
568 DestroyWindow( tmp->hwndSelf );
569 ret = TRUE;
570 break;
572 tmp2 = WIN_LockWndPtr(tmp->child);
573 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
574 ret = TRUE;
575 else
577 WIN_UpdateWndPtr(&tmp,tmp->next);
579 WIN_ReleaseWndPtr(tmp2);
581 WIN_ReleaseWndPtr(tmp);
582 if (!ret) break;
585 return ret;
588 /***********************************************************************
589 * WIN_CreateDesktopWindow
591 * Create the desktop window.
593 BOOL WIN_CreateDesktopWindow(void)
595 CLASS *class;
596 HWND hwndDesktop;
598 TRACE("Creating desktop window\n");
601 if (!ICONTITLE_Init() ||
602 !WINPOS_CreateInternalPosAtom() ||
603 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
604 return FALSE;
606 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
607 if (!hwndDesktop) return FALSE;
608 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
610 pWndDesktop->pDriver = WND_Driver;
611 pWndDesktop->pDriver->pInitialize(pWndDesktop);
613 pWndDesktop->next = NULL;
614 pWndDesktop->child = NULL;
615 pWndDesktop->parent = NULL;
616 pWndDesktop->owner = NULL;
617 pWndDesktop->class = class;
618 pWndDesktop->dwMagic = WND_MAGIC;
619 pWndDesktop->hwndSelf = hwndDesktop;
620 pWndDesktop->hInstance = 0;
621 pWndDesktop->rectWindow.left = 0;
622 pWndDesktop->rectWindow.top = 0;
623 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
624 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
625 pWndDesktop->rectClient = pWndDesktop->rectWindow;
626 pWndDesktop->text = NULL;
627 pWndDesktop->hmemTaskQ = GetFastQueue16();
628 pWndDesktop->hrgnUpdate = 0;
629 pWndDesktop->hwndLastActive = hwndDesktop;
630 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
631 WS_CLIPSIBLINGS;
632 pWndDesktop->dwExStyle = 0;
633 pWndDesktop->dce = NULL;
634 pWndDesktop->pVScroll = NULL;
635 pWndDesktop->pHScroll = NULL;
636 pWndDesktop->pProp = NULL;
637 pWndDesktop->wIDmenu = 0;
638 pWndDesktop->helpContext = 0;
639 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
640 pWndDesktop->hSysMenu = 0;
641 pWndDesktop->userdata = 0;
642 pWndDesktop->winproc = (WNDPROC16)class->winproc;
643 pWndDesktop->irefCount = 0;
645 /* FIXME: How do we know if it should be Unicode or not */
646 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
647 return FALSE;
649 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
650 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
651 return TRUE;
655 /***********************************************************************
656 * WIN_CreateWindowEx
658 * Fix the coordinates - Helper for WIN_CreateWindowEx.
659 * returns default show mode in sw.
660 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
662 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
664 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
665 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
667 if (cs->style & (WS_CHILD | WS_POPUP))
669 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
670 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
672 else /* overlapped window */
674 STARTUPINFOA info;
676 GetStartupInfoA( &info );
678 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
680 /* Never believe Microsoft's documentation... CreateWindowEx doc says
681 * that if an overlapped window is created with WS_VISIBLE style bit
682 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
683 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
684 * reveals that
686 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
687 * 2) it does not ignore the y parameter as the docs claim; instead, it
688 * uses it as second parameter to ShowWindow() unless y is either
689 * CW_USEDEFAULT or CW_USEDEFAULT16.
691 * The fact that we didn't do 2) caused bogus windows pop up when wine
692 * was running apps that were using this obscure feature. Example -
693 * calc.exe that comes with Win98 (only Win98, it's different from
694 * the one that comes with Win95 and NT)
696 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
697 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
698 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
701 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
703 if (info.dwFlags & STARTF_USESIZE)
705 cs->cx = info.dwXSize;
706 cs->cy = info.dwYSize;
708 else /* if no other hint from the app, pick 3/4 of the screen real estate */
710 RECT r;
711 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
712 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
713 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
720 /***********************************************************************
721 * WIN_CreateWindowEx
723 * Implementation of CreateWindowEx().
725 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
726 BOOL win32, BOOL unicode )
728 INT sw = SW_SHOW;
729 CLASS *classPtr;
730 WND *wndPtr;
731 HWND retvalue;
732 HWND16 hwnd, hwndLinkAfter;
733 POINT maxSize, maxPos, minTrack, maxTrack;
734 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
736 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
737 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
738 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
739 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
740 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
742 /* Find the parent window */
744 if (cs->hwndParent)
746 /* Make sure parent is valid */
747 if (!IsWindow( cs->hwndParent ))
749 WARN("Bad parent %04x\n", cs->hwndParent );
750 return 0;
752 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
753 WARN("No parent for child window\n" );
754 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
757 /* Find the window class */
758 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
760 WARN("Bad class '%s'\n", cs->lpszClass );
761 return 0;
764 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
766 /* Create the window structure */
768 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
769 - sizeof(wndPtr->wExtra) )))
771 TRACE("out of memory\n" );
772 return 0;
775 /* Fill the window structure */
777 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
778 wndPtr->next = NULL;
779 wndPtr->child = NULL;
781 if ((cs->style & WS_CHILD) && cs->hwndParent)
783 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
784 wndPtr->owner = NULL;
785 WIN_ReleaseWndPtr(wndPtr->parent);
787 else
789 wndPtr->parent = pWndDesktop;
790 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
791 wndPtr->owner = NULL;
792 else
794 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
795 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
796 WIN_ReleaseWndPtr(wndPtr->owner);
797 WIN_ReleaseWndPtr(tmpWnd);
802 wndPtr->pDriver = wndPtr->parent->pDriver;
803 wndPtr->pDriver->pInitialize(wndPtr);
805 wndPtr->class = classPtr;
806 wndPtr->winproc = classPtr->winproc;
807 wndPtr->dwMagic = WND_MAGIC;
808 wndPtr->hwndSelf = hwnd;
809 wndPtr->hInstance = cs->hInstance;
810 wndPtr->text = NULL;
811 wndPtr->hmemTaskQ = GetFastQueue16();
812 wndPtr->hrgnUpdate = 0;
813 wndPtr->hrgnWnd = 0;
814 wndPtr->hwndLastActive = hwnd;
815 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
816 wndPtr->dwExStyle = cs->dwExStyle;
817 wndPtr->wIDmenu = 0;
818 wndPtr->helpContext = 0;
819 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
820 wndPtr->pVScroll = NULL;
821 wndPtr->pHScroll = NULL;
822 wndPtr->pProp = NULL;
823 wndPtr->userdata = 0;
824 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
825 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
826 wndPtr->irefCount = 1;
828 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
830 /* Call the WH_CBT hook */
832 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
833 ? HWND_BOTTOM : HWND_TOP;
835 if (HOOK_IsHooked( WH_CBT ))
837 CBT_CREATEWNDA cbtc;
838 LRESULT ret;
840 cbtc.lpcs = cs;
841 cbtc.hwndInsertAfter = hwndLinkAfter;
842 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
843 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
844 if (ret)
846 TRACE("CBT-hook returned 0\n");
847 wndPtr->pDriver->pFinalize(wndPtr);
848 USER_HEAP_FREE( hwnd );
849 retvalue = 0;
850 goto end;
854 /* Increment class window counter */
856 classPtr->cWindows++;
858 /* Correct the window style */
860 if (!(cs->style & WS_CHILD))
862 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
863 if (!(cs->style & WS_POPUP))
865 wndPtr->dwStyle |= WS_CAPTION;
866 wndPtr->flags |= WIN_NEED_SIZE;
870 /* Get class or window DC if needed */
872 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
873 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
874 else wndPtr->dce = NULL;
876 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
878 wndPtr->rectWindow.left = cs->x;
879 wndPtr->rectWindow.top = cs->y;
880 wndPtr->rectWindow.right = cs->x + cs->cx;
881 wndPtr->rectWindow.bottom = cs->y + cs->cy;
882 wndPtr->rectClient = wndPtr->rectWindow;
884 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
886 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
888 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
889 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
890 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
891 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
892 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
895 if (cs->cx < 0) cs->cx = 0;
896 if (cs->cy < 0) cs->cy = 0;
898 wndPtr->rectWindow.left = cs->x;
899 wndPtr->rectWindow.top = cs->y;
900 wndPtr->rectWindow.right = cs->x + cs->cx;
901 wndPtr->rectWindow.bottom = cs->y + cs->cy;
902 wndPtr->rectClient = wndPtr->rectWindow;
904 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
906 retvalue = FALSE;
907 goto end;
910 /* Set the window menu */
912 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
914 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
915 else
917 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
918 if (classPtr->menuNameA)
919 cs->hMenu = HIWORD(classPtr->menuNameA) ?
920 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
921 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
922 #else
923 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
924 if (menuName)
926 if (HIWORD(cs->hInstance))
927 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
928 else
929 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
931 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
933 #endif
936 else wndPtr->wIDmenu = (UINT)cs->hMenu;
938 /* Send the WM_CREATE message
939 * Perhaps we shouldn't allow width/height changes as well.
940 * See p327 in "Internals".
943 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
945 localSend32 = unicode ? SendMessageW : SendMessageA;
946 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
948 /* Insert the window in the linked list */
950 WIN_LinkWindow( hwnd, hwndLinkAfter );
952 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
953 NULL, NULL, 0, &wndPtr->rectClient );
954 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
955 maxPos.y - wndPtr->rectWindow.top);
956 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
958 /* Send the size messages */
960 if (!(wndPtr->flags & WIN_NEED_SIZE))
962 /* send it anyway */
963 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
964 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
965 WARN("sending bogus WM_SIZE message 0x%08lx\n",
966 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
967 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
968 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
969 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
970 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
971 SendMessageA( hwnd, WM_MOVE, 0,
972 MAKELONG( wndPtr->rectClient.left,
973 wndPtr->rectClient.top ) );
976 /* Show the window, maximizing or minimizing if needed */
978 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
980 RECT16 newPos;
981 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
982 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
983 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
984 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
985 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
986 : SWP_NOZORDER | SWP_FRAMECHANGED;
987 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
988 newPos.right, newPos.bottom, swFlag );
991 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
993 /* Notify the parent window only */
995 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
996 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
997 if( !IsWindow(hwnd) )
999 retvalue = 0;
1000 goto end;
1004 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1006 /* Call WH_SHELL hook */
1008 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1009 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1011 TRACE("created window %04x\n", hwnd);
1012 retvalue = hwnd;
1013 goto end;
1015 WIN_UnlinkWindow( hwnd );
1018 /* Abort window creation */
1020 WARN("aborted by WM_xxCREATE!\n");
1021 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1022 retvalue = 0;
1023 end:
1024 WIN_ReleaseWndPtr(wndPtr);
1026 return retvalue;
1030 /***********************************************************************
1031 * CreateWindow16 (USER.41)
1033 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1034 DWORD style, INT16 x, INT16 y, INT16 width,
1035 INT16 height, HWND16 parent, HMENU16 menu,
1036 HINSTANCE16 instance, LPVOID data )
1038 return CreateWindowEx16( 0, className, windowName, style,
1039 x, y, width, height, parent, menu, instance, data );
1043 /***********************************************************************
1044 * CreateWindowEx16 (USER.452)
1046 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1047 LPCSTR windowName, DWORD style, INT16 x,
1048 INT16 y, INT16 width, INT16 height,
1049 HWND16 parent, HMENU16 menu,
1050 HINSTANCE16 instance, LPVOID data )
1052 ATOM classAtom;
1053 CREATESTRUCTA cs;
1054 char buffer[256];
1056 /* Find the class atom */
1058 if (HIWORD(className))
1060 if (!(classAtom = GlobalFindAtomA( className )))
1062 ERR( "bad class name %s\n", debugres_a(className) );
1063 return 0;
1066 else
1068 classAtom = LOWORD(className);
1069 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1071 ERR( "bad atom %x\n", classAtom);
1072 return 0;
1074 className = buffer;
1077 /* Fix the coordinates */
1079 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1080 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1081 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1082 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1084 /* Create the window */
1086 cs.lpCreateParams = data;
1087 cs.hInstance = (HINSTANCE)instance;
1088 cs.hMenu = (HMENU)menu;
1089 cs.hwndParent = (HWND)parent;
1090 cs.style = style;
1091 cs.lpszName = windowName;
1092 cs.lpszClass = className;
1093 cs.dwExStyle = exStyle;
1095 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1099 /***********************************************************************
1100 * CreateWindowExA (USER32.83)
1102 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1103 LPCSTR windowName, DWORD style, INT x,
1104 INT y, INT width, INT height,
1105 HWND parent, HMENU menu,
1106 HINSTANCE instance, LPVOID data )
1108 ATOM classAtom;
1109 CREATESTRUCTA cs;
1110 char buffer[256];
1112 if(!instance)
1113 instance=GetModuleHandleA(NULL);
1115 if(exStyle & WS_EX_MDICHILD)
1116 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1118 /* Find the class atom */
1120 if (HIWORD(className))
1122 if (!(classAtom = GlobalFindAtomA( className )))
1124 ERR( "bad class name %s\n", debugres_a(className) );
1125 return 0;
1128 else
1130 classAtom = LOWORD(className);
1131 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1133 ERR( "bad atom %x\n", classAtom);
1134 return 0;
1136 className = buffer;
1139 /* Create the window */
1141 cs.lpCreateParams = data;
1142 cs.hInstance = instance;
1143 cs.hMenu = menu;
1144 cs.hwndParent = parent;
1145 cs.x = x;
1146 cs.y = y;
1147 cs.cx = width;
1148 cs.cy = height;
1149 cs.style = style;
1150 cs.lpszName = windowName;
1151 cs.lpszClass = className;
1152 cs.dwExStyle = exStyle;
1154 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1158 /***********************************************************************
1159 * CreateWindowExW (USER32.84)
1161 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1162 LPCWSTR windowName, DWORD style, INT x,
1163 INT y, INT width, INT height,
1164 HWND parent, HMENU menu,
1165 HINSTANCE instance, LPVOID data )
1167 ATOM classAtom;
1168 CREATESTRUCTW cs;
1169 WCHAR buffer[256];
1171 if(!instance)
1172 instance=GetModuleHandleA(NULL);
1174 if(exStyle & WS_EX_MDICHILD)
1175 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1177 /* Find the class atom */
1179 if (HIWORD(className))
1181 if (!(classAtom = GlobalFindAtomW( className )))
1183 ERR( "bad class name %s\n", debugres_w(className) );
1184 return 0;
1187 else
1189 classAtom = LOWORD(className);
1190 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1192 ERR( "bad atom %x\n", classAtom);
1193 return 0;
1195 className = buffer;
1198 /* Create the window */
1200 cs.lpCreateParams = data;
1201 cs.hInstance = instance;
1202 cs.hMenu = menu;
1203 cs.hwndParent = parent;
1204 cs.x = x;
1205 cs.y = y;
1206 cs.cx = width;
1207 cs.cy = height;
1208 cs.style = style;
1209 cs.lpszName = windowName;
1210 cs.lpszClass = className;
1211 cs.dwExStyle = exStyle;
1213 /* Note: we rely on the fact that CREATESTRUCTA and */
1214 /* CREATESTRUCTW have the same layout. */
1215 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1218 /***********************************************************************
1219 * WIN_SendDestroyMsg
1221 static void WIN_SendDestroyMsg( WND* pWnd )
1223 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1224 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1227 * Send the WM_DESTROY to the window.
1229 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1232 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1233 * make sure that the window still exists when we come back.
1235 if (IsWindow(pWnd->hwndSelf))
1237 HWND* pWndArray = NULL;
1238 WND* pChild = NULL;
1239 int nKidCount = 0;
1242 * Now, if the window has kids, we have to send WM_DESTROY messages
1243 * recursively to it's kids. It seems that those calls can also
1244 * trigger re-entrant calls to DestroyWindow for the kids so we must
1245 * protect against corruption of the list of siblings. We first build
1246 * a list of HWNDs representing all the kids.
1248 pChild = WIN_LockWndPtr(pWnd->child);
1249 while( pChild )
1251 nKidCount++;
1252 WIN_UpdateWndPtr(&pChild,pChild->next);
1256 * If there are no kids, we're done.
1258 if (nKidCount==0)
1259 return;
1261 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1264 * Sanity check
1266 if (pWndArray==NULL)
1267 return;
1270 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1271 * call, our linked list of siblings should be safe.
1273 nKidCount = 0;
1274 pChild = WIN_LockWndPtr(pWnd->child);
1275 while( pChild )
1277 pWndArray[nKidCount] = pChild->hwndSelf;
1278 nKidCount++;
1279 WIN_UpdateWndPtr(&pChild,pChild->next);
1283 * Now that we have a list, go through that list again and send the destroy
1284 * message to those windows. We are using the HWND to retrieve the
1285 * WND pointer so we are effectively checking that all the kid windows are
1286 * still valid before sending the message.
1288 while (nKidCount>0)
1290 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1292 if (pChild!=NULL)
1294 WIN_SendDestroyMsg( pChild );
1295 WIN_ReleaseWndPtr(pChild);
1300 * Cleanup
1302 HeapFree(GetProcessHeap(), 0, pWndArray);
1304 else
1305 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1309 /***********************************************************************
1310 * DestroyWindow16 (USER.53)
1312 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1314 return DestroyWindow(hwnd);
1318 /***********************************************************************
1319 * DestroyWindow (USER32.135)
1321 BOOL WINAPI DestroyWindow( HWND hwnd )
1323 WND * wndPtr;
1324 BOOL retvalue;
1325 HWND h;
1326 BOOL bFocusSet = FALSE;
1328 TRACE("(%04x)\n", hwnd);
1330 /* Initialization */
1332 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1333 if (wndPtr == pWndDesktop)
1335 retvalue = FALSE; /* Can't destroy desktop */
1336 goto end;
1339 /* Look whether the focus is within the tree of windows we will
1340 * be destroying.
1342 h = GetFocus16();
1343 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1345 if (h == hwnd)
1347 SetFocus(GetWindowLongA(hwnd,GWL_HWNDPARENT));
1348 bFocusSet = TRUE;
1349 break;
1351 h = GetWindowLongA(h,GWL_HWNDPARENT);
1353 /* If the focus is on the window we will destroy and it has no parent,
1354 * set the focus to 0.
1356 if (! bFocusSet && (h == hwnd))
1358 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1359 SetFocus(0);
1362 /* Call hooks */
1364 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1366 retvalue = FALSE;
1367 goto end;
1370 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1372 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1373 /* FIXME: clean up palette - see "Internals" p.352 */
1376 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1377 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1379 /* Notify the parent window only */
1380 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1381 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1382 if( !IsWindow(hwnd) )
1384 retvalue = TRUE;
1385 goto end;
1389 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1391 /* Hide the window */
1393 if (wndPtr->dwStyle & WS_VISIBLE)
1395 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1396 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1397 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1398 if (!IsWindow(hwnd))
1400 retvalue = TRUE;
1401 goto end;
1405 /* Recursively destroy owned windows */
1407 if( !(wndPtr->dwStyle & WS_CHILD) )
1409 /* make sure top menu popup doesn't get destroyed */
1410 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1412 for (;;)
1414 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1415 while (siblingPtr)
1417 if (siblingPtr->owner == wndPtr)
1419 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1420 break;
1421 else
1422 siblingPtr->owner = NULL;
1424 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1426 if (siblingPtr)
1428 DestroyWindow( siblingPtr->hwndSelf );
1429 WIN_ReleaseWndPtr(siblingPtr);
1431 else break;
1434 if( !Options.managed || EVENT_CheckFocus() )
1435 WINPOS_ActivateOtherWindow(wndPtr);
1437 if( wndPtr->owner &&
1438 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1439 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1442 /* Send destroy messages */
1444 WIN_SendDestroyMsg( wndPtr );
1445 if (!IsWindow(hwnd))
1447 retvalue = TRUE;
1448 goto end;
1451 /* Unlink now so we won't bother with the children later on */
1453 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1455 /* Destroy the window storage */
1457 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1458 retvalue = TRUE;
1459 end:
1460 WIN_ReleaseWndPtr(wndPtr);
1461 return retvalue;
1465 /***********************************************************************
1466 * CloseWindow16 (USER.43)
1468 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1470 return CloseWindow( hwnd );
1474 /***********************************************************************
1475 * CloseWindow (USER32.56)
1477 BOOL WINAPI CloseWindow( HWND hwnd )
1479 WND * wndPtr = WIN_FindWndPtr( hwnd );
1480 BOOL retvalue;
1482 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1484 retvalue = FALSE;
1485 goto end;
1487 ShowWindow( hwnd, SW_MINIMIZE );
1488 retvalue = TRUE;
1489 end:
1490 WIN_ReleaseWndPtr(wndPtr);
1491 return retvalue;
1496 /***********************************************************************
1497 * OpenIcon16 (USER.44)
1499 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1501 return OpenIcon( hwnd );
1505 /***********************************************************************
1506 * OpenIcon (USER32.410)
1508 BOOL WINAPI OpenIcon( HWND hwnd )
1510 if (!IsIconic( hwnd )) return FALSE;
1511 ShowWindow( hwnd, SW_SHOWNORMAL );
1512 return TRUE;
1516 /***********************************************************************
1517 * WIN_FindWindow
1519 * Implementation of FindWindow() and FindWindowEx().
1521 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1522 LPCWSTR title )
1524 WND *pWnd;
1525 HWND retvalue;
1527 if (child)
1529 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1530 if (parent)
1532 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1534 retvalue = 0;
1535 goto end;
1538 else if (pWnd->parent != pWndDesktop)
1540 retvalue = 0;
1541 goto end;
1543 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1545 else
1547 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1549 retvalue = 0;
1550 goto end;
1552 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1554 if (!pWnd)
1556 retvalue = 0;
1557 goto end;
1560 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1562 if (className && (pWnd->class->atomName != className))
1563 continue; /* Not the right class */
1565 /* Now check the title */
1567 if (!title)
1569 retvalue = pWnd->hwndSelf;
1570 goto end;
1572 if (pWnd->text && !strcmpW( pWnd->text, title ))
1574 retvalue = pWnd->hwndSelf;
1575 goto end;
1578 retvalue = 0;
1579 end:
1580 WIN_ReleaseWndPtr(pWnd);
1581 return retvalue;
1586 /***********************************************************************
1587 * FindWindow16 (USER.50)
1589 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1591 return FindWindowA( className, title );
1595 /***********************************************************************
1596 * FindWindowEx16 (USER.427)
1598 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1600 return FindWindowExA( parent, child, className, title );
1604 /***********************************************************************
1605 * FindWindowA (USER32.198)
1607 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1609 HWND ret = FindWindowExA( 0, 0, className, title );
1610 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1611 return ret;
1615 /***********************************************************************
1616 * FindWindowExA (USER32.199)
1618 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1619 LPCSTR className, LPCSTR title )
1621 ATOM atom = 0;
1622 LPWSTR buffer;
1623 HWND hwnd;
1625 if (className)
1627 /* If the atom doesn't exist, then no class */
1628 /* with this name exists either. */
1629 if (!(atom = GlobalFindAtomA( className )))
1631 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1632 return 0;
1636 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1637 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1638 HeapFree( GetProcessHeap(), 0, buffer );
1639 return hwnd;
1643 /***********************************************************************
1644 * FindWindowExW (USER32.200)
1646 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1647 LPCWSTR className, LPCWSTR title )
1649 ATOM atom = 0;
1651 if (className)
1653 /* If the atom doesn't exist, then no class */
1654 /* with this name exists either. */
1655 if (!(atom = GlobalFindAtomW( className )))
1657 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1658 return 0;
1661 return WIN_FindWindow( parent, child, atom, title );
1665 /***********************************************************************
1666 * FindWindowW (USER32.201)
1668 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1670 return FindWindowExW( 0, 0, className, title );
1674 /**********************************************************************
1675 * WIN_GetDesktop
1676 * returns a locked pointer
1678 WND *WIN_GetDesktop(void)
1680 return WIN_LockWndPtr(pWndDesktop);
1682 /**********************************************************************
1683 * WIN_ReleaseDesktop
1684 * unlock the desktop pointer
1686 void WIN_ReleaseDesktop(void)
1688 WIN_ReleaseWndPtr(pWndDesktop);
1692 /**********************************************************************
1693 * GetDesktopWindow16 (USER.286)
1695 HWND16 WINAPI GetDesktopWindow16(void)
1697 return (HWND16)pWndDesktop->hwndSelf;
1701 /**********************************************************************
1702 * GetDesktopWindow (USER32.232)
1704 HWND WINAPI GetDesktopWindow(void)
1706 if (pWndDesktop) return pWndDesktop->hwndSelf;
1707 ERR( "You need the -desktop option when running with native USER\n" );
1708 ExitProcess(1);
1709 return 0;
1713 /**********************************************************************
1714 * GetDesktopHwnd (USER.278)
1716 * Exactly the same thing as GetDesktopWindow(), but not documented.
1717 * Don't ask me why...
1719 HWND16 WINAPI GetDesktopHwnd16(void)
1721 return (HWND16)pWndDesktop->hwndSelf;
1725 /*******************************************************************
1726 * EnableWindow16 (USER.34)
1728 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1730 return EnableWindow( hwnd, enable );
1734 /*******************************************************************
1735 * EnableWindow (USER32.172)
1737 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1739 WND *wndPtr;
1740 BOOL retvalue;
1742 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1744 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1745 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1747 /* Enable window */
1748 wndPtr->dwStyle &= ~WS_DISABLED;
1750 if( wndPtr->flags & WIN_NATIVE )
1751 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1753 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1754 retvalue = TRUE;
1755 goto end;
1757 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1759 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1761 /* Disable window */
1762 wndPtr->dwStyle |= WS_DISABLED;
1764 if( wndPtr->flags & WIN_NATIVE )
1765 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1767 if (hwnd == GetFocus())
1769 SetFocus( 0 ); /* A disabled window can't have the focus */
1771 if (hwnd == GetCapture())
1773 ReleaseCapture(); /* A disabled window can't capture the mouse */
1775 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1776 retvalue = FALSE;
1777 goto end;
1779 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1780 end:
1781 WIN_ReleaseWndPtr(wndPtr);
1782 return retvalue;
1786 /***********************************************************************
1787 * IsWindowEnabled16 (USER.35)
1789 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1791 return IsWindowEnabled(hWnd);
1795 /***********************************************************************
1796 * IsWindowEnabled (USER32.349)
1798 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1800 WND * wndPtr;
1801 BOOL retvalue;
1803 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1804 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1805 WIN_ReleaseWndPtr(wndPtr);
1806 return retvalue;
1811 /***********************************************************************
1812 * IsWindowUnicode (USER32.350)
1814 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1816 WND * wndPtr;
1817 BOOL retvalue;
1819 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1820 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1821 WIN_ReleaseWndPtr(wndPtr);
1822 return retvalue;
1826 /**********************************************************************
1827 * GetWindowWord16 (USER.133)
1829 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1831 return GetWindowWord( hwnd, offset );
1835 /**********************************************************************
1836 * GetWindowWord (USER32.314)
1838 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1840 WORD retvalue;
1841 WND * wndPtr = WIN_FindWndPtr( hwnd );
1842 if (!wndPtr) return 0;
1843 if (offset >= 0)
1845 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1847 WARN("Invalid offset %d\n", offset );
1848 retvalue = 0;
1849 goto end;
1851 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1852 goto end;
1854 switch(offset)
1856 case GWW_ID:
1857 if (HIWORD(wndPtr->wIDmenu))
1858 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1859 wndPtr->wIDmenu);
1860 retvalue = (WORD)wndPtr->wIDmenu;
1861 goto end;
1862 case GWW_HWNDPARENT:
1863 retvalue = GetParent(hwnd);
1864 goto end;
1865 case GWW_HINSTANCE:
1866 if (HIWORD(wndPtr->hInstance))
1867 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1868 wndPtr->hInstance);
1869 retvalue = (WORD)wndPtr->hInstance;
1870 goto end;
1871 default:
1872 WARN("Invalid offset %d\n", offset );
1873 retvalue = 0;
1874 goto end;
1876 end:
1877 WIN_ReleaseWndPtr(wndPtr);
1878 return retvalue;
1881 /**********************************************************************
1882 * SetWindowWord16 (USER.134)
1884 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1886 return SetWindowWord( hwnd, offset, newval );
1890 /**********************************************************************
1891 * SetWindowWord (USER32.524)
1893 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1895 WORD *ptr, retval;
1896 WND * wndPtr = WIN_FindWndPtr( hwnd );
1897 if (!wndPtr) return 0;
1898 if (offset >= 0)
1900 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1902 WARN("Invalid offset %d\n", offset );
1903 retval = 0;
1904 goto end;
1906 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1908 else switch(offset)
1910 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1911 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1912 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1913 goto end;
1914 default:
1915 WARN("Invalid offset %d\n", offset );
1916 retval = 0;
1917 goto end;
1919 retval = *ptr;
1920 *ptr = newval;
1921 end:
1922 WIN_ReleaseWndPtr(wndPtr);
1923 return retval;
1927 /**********************************************************************
1928 * WIN_GetWindowLong
1930 * Helper function for GetWindowLong().
1932 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1934 LONG retvalue;
1935 WND * wndPtr = WIN_FindWndPtr( hwnd );
1936 if (!wndPtr) return 0;
1937 if (offset >= 0)
1939 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1941 WARN("Invalid offset %d\n", offset );
1942 retvalue = 0;
1943 goto end;
1945 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1946 /* Special case for dialog window procedure */
1947 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1949 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1950 goto end;
1952 goto end;
1954 switch(offset)
1956 case GWL_USERDATA: retvalue = wndPtr->userdata;
1957 goto end;
1958 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1959 goto end;
1960 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1961 goto end;
1962 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1963 goto end;
1964 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1965 type );
1966 goto end;
1967 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1968 goto end;
1969 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1970 goto end;
1971 default:
1972 WARN("Unknown offset %d\n", offset );
1974 retvalue = 0;
1975 end:
1976 WIN_ReleaseWndPtr(wndPtr);
1977 return retvalue;
1981 /**********************************************************************
1982 * WIN_SetWindowLong
1984 * Helper function for SetWindowLong().
1986 * 0 is the failure code. However, in the case of failure SetLastError
1987 * must be set to distinguish between a 0 return value and a failure.
1989 * FIXME: The error values for SetLastError may not be right. Can
1990 * someone check with the real thing?
1992 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1993 WINDOWPROCTYPE type )
1995 LONG *ptr, retval;
1996 WND * wndPtr = WIN_FindWndPtr( hwnd );
1997 STYLESTRUCT style;
1999 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
2001 if (!wndPtr)
2003 /* Is this the right error? */
2004 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2005 return 0;
2008 if (offset >= 0)
2010 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
2012 WARN("Invalid offset %d\n", offset );
2014 /* Is this the right error? */
2015 SetLastError( ERROR_OUTOFMEMORY );
2017 retval = 0;
2018 goto end;
2020 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2021 /* Special case for dialog window procedure */
2022 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2024 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2025 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2026 type, WIN_PROC_WINDOW );
2027 goto end;
2030 else switch(offset)
2032 case GWL_ID:
2033 ptr = (DWORD*)&wndPtr->wIDmenu;
2034 break;
2035 case GWL_HINSTANCE:
2036 retval = SetWindowWord( hwnd, offset, newval );
2037 goto end;
2038 case GWL_WNDPROC:
2039 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2040 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2041 type, WIN_PROC_WINDOW );
2042 goto end;
2043 case GWL_STYLE:
2044 style.styleOld = wndPtr->dwStyle;
2045 newval &= ~(WS_CHILD); /* this bit can't be changed this way */
2046 style.styleNew = newval | (style.styleOld & (WS_CHILD));
2048 if (wndPtr->flags & WIN_ISWIN32)
2049 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2050 wndPtr->dwStyle = style.styleNew;
2051 if (wndPtr->flags & WIN_ISWIN32)
2052 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2053 retval = style.styleOld;
2054 goto end;
2056 case GWL_USERDATA:
2057 ptr = &wndPtr->userdata;
2058 break;
2059 case GWL_EXSTYLE:
2060 style.styleOld = wndPtr->dwExStyle;
2061 style.styleNew = newval;
2062 if (wndPtr->flags & WIN_ISWIN32)
2063 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2064 wndPtr->dwExStyle = newval;
2065 if (wndPtr->flags & WIN_ISWIN32)
2066 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2067 retval = style.styleOld;
2068 goto end;
2070 default:
2071 WARN("Invalid offset %d\n", offset );
2073 /* Don't think this is right error but it should do */
2074 SetLastError( ERROR_OUTOFMEMORY );
2076 retval = 0;
2077 goto end;
2079 retval = *ptr;
2080 *ptr = newval;
2081 end:
2082 WIN_ReleaseWndPtr(wndPtr);
2083 return retval;
2087 /**********************************************************************
2088 * GetWindowLong16 (USER.135)
2090 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2092 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2096 /**********************************************************************
2097 * GetWindowLongA (USER32.305)
2099 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2101 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2105 /**********************************************************************
2106 * GetWindowLongW (USER32.306)
2108 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2110 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2114 /**********************************************************************
2115 * SetWindowLong16 (USER.136)
2117 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2119 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2123 /**********************************************************************
2124 * SetWindowLongA (USER32.517)
2126 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2128 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2132 /**********************************************************************
2133 * SetWindowLongW (USER32.518) Set window attribute
2135 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2136 * value in a window's extra memory.
2138 * The _hwnd_ parameter specifies the window. is the handle to a
2139 * window that has extra memory. The _newval_ parameter contains the
2140 * new attribute or extra memory value. If positive, the _offset_
2141 * parameter is the byte-addressed location in the window's extra
2142 * memory to set. If negative, _offset_ specifies the window
2143 * attribute to set, and should be one of the following values:
2145 * GWL_EXSTYLE The window's extended window style
2147 * GWL_STYLE The window's window style.
2149 * GWL_WNDPROC Pointer to the window's window procedure.
2151 * GWL_HINSTANCE The window's pplication instance handle.
2153 * GWL_ID The window's identifier.
2155 * GWL_USERDATA The window's user-specified data.
2157 * If the window is a dialog box, the _offset_ parameter can be one of
2158 * the following values:
2160 * DWL_DLGPROC The address of the window's dialog box procedure.
2162 * DWL_MSGRESULT The return value of a message
2163 * that the dialog box procedure processed.
2165 * DWL_USER Application specific information.
2167 * RETURNS
2169 * If successful, returns the previous value located at _offset_. Otherwise,
2170 * returns 0.
2172 * NOTES
2174 * Extra memory for a window class is specified by a nonzero cbWndExtra
2175 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2176 * time of class creation.
2178 * Using GWL_WNDPROC to set a new window procedure effectively creates
2179 * a window subclass. Use CallWindowProc() in the new windows procedure
2180 * to pass messages to the superclass's window procedure.
2182 * The user data is reserved for use by the application which created
2183 * the window.
2185 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2186 * instead, call the EnableWindow() function to change the window's
2187 * disabled state.
2189 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2190 * SetParent() instead.
2192 * Win95:
2193 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2194 * it sends WM_STYLECHANGING before changing the settings
2195 * and WM_STYLECHANGED afterwards.
2196 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2198 * BUGS
2200 * GWL_STYLE does not dispatch WM_STYLE... messages.
2202 * CONFORMANCE
2204 * ECMA-234, Win32
2207 LONG WINAPI SetWindowLongW(
2208 HWND hwnd, /* window to alter */
2209 INT offset, /* offset, in bytes, of location to alter */
2210 LONG newval /* new value of location */
2212 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2216 /*******************************************************************
2217 * GetWindowText16 (USER.36)
2219 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2221 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2225 /*******************************************************************
2226 * GetWindowTextA (USER32.309)
2228 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2230 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2231 (LPARAM)lpString );
2234 /*******************************************************************
2235 * InternalGetWindowText (USER32.326)
2237 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2239 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2240 return GetWindowTextW(hwnd,lpString,nMaxCount);
2244 /*******************************************************************
2245 * GetWindowTextW (USER32.312)
2247 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2249 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2250 (LPARAM)lpString );
2254 /*******************************************************************
2255 * SetWindowText16 (USER.37)
2257 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2259 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2263 /*******************************************************************
2264 * SetWindowTextA (USER32.521)
2266 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2268 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2272 /*******************************************************************
2273 * SetWindowTextW (USER32.523)
2275 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2277 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2281 /*******************************************************************
2282 * GetWindowTextLength16 (USER.38)
2284 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2286 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2290 /*******************************************************************
2291 * GetWindowTextLengthA (USER32.310)
2293 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2295 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2298 /*******************************************************************
2299 * GetWindowTextLengthW (USER32.311)
2301 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2303 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2307 /*******************************************************************
2308 * IsWindow16 (USER.47)
2310 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2312 CURRENT_STACK16->es = USER_HeapSel;
2313 return IsWindow( hwnd );
2317 /*******************************************************************
2318 * IsWindow (USER32.348)
2320 BOOL WINAPI IsWindow( HWND hwnd )
2322 WND * wndPtr;
2323 BOOL retvalue;
2325 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2326 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2327 WIN_ReleaseWndPtr(wndPtr);
2328 return retvalue;
2333 /*****************************************************************
2334 * GetParent16 (USER.46)
2336 HWND16 WINAPI GetParent16( HWND16 hwnd )
2338 return (HWND16)GetParent( hwnd );
2342 /*****************************************************************
2343 * GetParent (USER32.278)
2345 HWND WINAPI GetParent( HWND hwnd )
2347 WND *wndPtr;
2348 HWND retvalue = 0;
2350 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2351 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2352 goto end;
2354 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2355 if (wndPtr)
2356 retvalue = wndPtr->hwndSelf;
2358 end:
2359 WIN_ReleaseWndPtr(wndPtr);
2360 return retvalue;
2364 /*****************************************************************
2365 * WIN_GetTopParent
2367 * Get the top-level parent for a child window.
2368 * returns a locked pointer
2370 WND* WIN_GetTopParentPtr( WND* pWnd )
2372 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2374 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2376 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2378 return tmpWnd;
2381 /*****************************************************************
2382 * WIN_GetTopParent
2384 * Get the top-level parent for a child window.
2386 HWND WIN_GetTopParent( HWND hwnd )
2388 HWND retvalue;
2389 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2390 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2392 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2393 WIN_ReleaseWndPtr(tmpPtr);
2394 WIN_ReleaseWndPtr(wndPtr);
2395 return retvalue;
2399 /*****************************************************************
2400 * SetParent16 (USER.233)
2402 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2404 return SetParent( hwndChild, hwndNewParent );
2408 /*****************************************************************
2409 * SetParent (USER32.495)
2411 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2413 WND *wndPtr;
2414 DWORD dwStyle;
2415 WND *pWndNewParent;
2416 WND *pWndOldParent;
2417 HWND retvalue;
2420 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2422 dwStyle = wndPtr->dwStyle;
2424 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2425 : WIN_LockWndPtr(pWndDesktop);
2427 /* Windows hides the window first, then shows it again
2428 * including the WM_SHOWWINDOW messages and all */
2429 if (dwStyle & WS_VISIBLE)
2430 ShowWindow( hwndChild, SW_HIDE );
2432 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2434 /* SetParent additionally needs to make hwndChild the topmost window
2435 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2436 WM_WINDOWPOSCHANGED notification messages.
2438 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2439 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2440 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2441 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2443 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2445 WIN_ReleaseWndPtr(pWndOldParent);
2446 WIN_ReleaseWndPtr(pWndNewParent);
2447 WIN_ReleaseWndPtr(wndPtr);
2449 return retvalue;
2453 /*******************************************************************
2454 * IsChild16 (USER.48)
2456 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2458 return IsChild(parent,child);
2462 /*******************************************************************
2463 * IsChild (USER32.339)
2465 BOOL WINAPI IsChild( HWND parent, HWND child )
2467 WND * wndPtr = WIN_FindWndPtr( child );
2468 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2470 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2471 if (wndPtr->hwndSelf == parent)
2473 WIN_ReleaseWndPtr(wndPtr);
2474 return TRUE;
2477 WIN_ReleaseWndPtr(wndPtr);
2478 return FALSE;
2482 /***********************************************************************
2483 * IsWindowVisible16 (USER.49)
2485 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2487 return IsWindowVisible(hwnd);
2491 /***********************************************************************
2492 * IsWindowVisible (USER32.351)
2494 BOOL WINAPI IsWindowVisible( HWND hwnd )
2496 BOOL retval;
2497 WND *wndPtr = WIN_FindWndPtr( hwnd );
2498 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2500 if (!(wndPtr->dwStyle & WS_VISIBLE))
2502 WIN_ReleaseWndPtr(wndPtr);
2503 return FALSE;
2505 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2507 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2508 WIN_ReleaseWndPtr(wndPtr);
2509 return retval;
2514 /***********************************************************************
2515 * WIN_IsWindowDrawable
2517 * hwnd is drawable when it is visible, all parents are not
2518 * minimized, and it is itself not minimized unless we are
2519 * trying to draw its default class icon.
2521 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2523 if( (wnd->dwStyle & WS_MINIMIZE &&
2524 icon && wnd->class->hIcon) ||
2525 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2526 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2527 if( wnd->dwStyle & WS_MINIMIZE ||
2528 !(wnd->dwStyle & WS_VISIBLE) ) break;
2529 return (wnd == NULL);
2533 /*******************************************************************
2534 * GetTopWindow16 (USER.229)
2536 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2538 return GetTopWindow(hwnd);
2542 /*******************************************************************
2543 * GetTopWindow (USER.229)
2545 HWND WINAPI GetTopWindow( HWND hwnd )
2547 HWND retval = 0;
2548 WND * wndPtr = (hwnd) ?
2549 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2551 if (wndPtr && wndPtr->child)
2552 retval = wndPtr->child->hwndSelf;
2554 WIN_ReleaseWndPtr(wndPtr);
2555 return retval;
2559 /*******************************************************************
2560 * GetWindow16 (USER.262)
2562 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2564 return GetWindow( hwnd,rel );
2568 /*******************************************************************
2569 * GetWindow (USER32.302)
2571 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2573 HWND retval;
2575 WND * wndPtr = WIN_FindWndPtr( hwnd );
2576 if (!wndPtr) return 0;
2577 switch(rel)
2579 case GW_HWNDFIRST:
2580 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2581 goto end;
2583 case GW_HWNDLAST:
2584 if (!wndPtr->parent)
2586 retval = 0; /* Desktop window */
2587 goto end;
2589 while (wndPtr->next)
2591 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2593 retval = wndPtr->hwndSelf;
2594 goto end;
2596 case GW_HWNDNEXT:
2597 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2598 goto end;
2600 case GW_HWNDPREV:
2601 if (!wndPtr->parent)
2603 retval = 0; /* Desktop window */
2604 goto end;
2606 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2607 if (wndPtr->hwndSelf == hwnd)
2609 retval = 0; /* First in list */
2610 goto end;
2612 while (wndPtr->next)
2614 if (wndPtr->next->hwndSelf == hwnd)
2616 retval = wndPtr->hwndSelf;
2617 goto end;
2619 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2621 retval = 0;
2622 goto end;
2624 case GW_OWNER:
2625 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2626 goto end;
2628 case GW_CHILD:
2629 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2630 goto end;
2632 retval = 0;
2633 end:
2634 WIN_ReleaseWndPtr(wndPtr);
2635 return retval;
2639 /*******************************************************************
2640 * GetNextWindow16 (USER.230)
2642 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2644 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2645 return GetWindow16( hwnd, flag );
2648 /***********************************************************************
2649 * WIN_InternalShowOwnedPopups
2651 * Internal version of ShowOwnedPopups; Wine functions should use this
2652 * to avoid interfering with application calls to ShowOwnedPopups
2653 * and to make sure the application can't prevent showing/hiding.
2655 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2659 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2661 INT totalChild=0, count=0;
2663 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2665 if (!pWnd) return TRUE;
2668 * Show windows Lowest first, Highest last to preserve Z-Order
2670 for (count = totalChild-1 ; count >=0; count--)
2672 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2674 if (fShow)
2676 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2677 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2680 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2682 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2683 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2686 else
2688 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2689 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2690 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2693 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2695 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2696 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2697 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2702 WIN_ReleaseDesktop();
2703 WIN_ReleaseWinArray(pWnd);
2705 return TRUE;
2708 /*******************************************************************
2709 * ShowOwnedPopups16 (USER.265)
2711 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2713 ShowOwnedPopups( owner, fShow );
2717 /*******************************************************************
2718 * ShowOwnedPopups (USER32.531)
2720 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2722 UINT totalChild=0, count=0;
2724 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2726 if (!pWnd) return TRUE;
2728 for (; count < totalChild; count++)
2730 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2732 if (fShow)
2734 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2737 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2738 * regardless of the state of the owner
2740 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2741 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2744 else
2746 if (IsWindowVisible(pWnd[count]->hwndSelf))
2749 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2750 * regardless of the state of the owner
2752 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2753 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2759 WIN_ReleaseDesktop();
2760 WIN_ReleaseWinArray(pWnd);
2761 return TRUE;
2765 /*******************************************************************
2766 * GetLastActivePopup16 (USER.287)
2768 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2770 return GetLastActivePopup( hwnd );
2773 /*******************************************************************
2774 * GetLastActivePopup (USER32.256)
2776 HWND WINAPI GetLastActivePopup( HWND hwnd )
2778 HWND retval;
2779 WND *wndPtr =WIN_FindWndPtr(hwnd);
2780 if (!wndPtr) return hwnd;
2781 retval = wndPtr->hwndLastActive;
2782 WIN_ReleaseWndPtr(wndPtr);
2783 return retval;
2787 /*******************************************************************
2788 * WIN_BuildWinArray
2790 * Build an array of pointers to the children of a given window.
2791 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2792 * when no windows are found.
2794 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2796 /* Future: this function will lock all windows associated with this array */
2798 WND **list, **ppWnd;
2799 WND *pWnd;
2800 UINT count = 0, skipOwned, skipHidden;
2801 DWORD skipFlags;
2803 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2804 skipOwned = bwaFlags & BWA_SKIPOWNED;
2805 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2806 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2808 /* First count the windows */
2810 if (!wndPtr)
2811 wndPtr = WIN_GetDesktop();
2813 pWnd = WIN_LockWndPtr(wndPtr->child);
2814 while (pWnd)
2816 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2817 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2818 count++;
2819 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2822 if( count )
2824 /* Now build the list of all windows */
2826 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2828 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2830 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2831 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2833 *ppWnd++ = pWnd;
2834 count++;
2837 WIN_ReleaseWndPtr(pWnd);
2838 *ppWnd = NULL;
2840 else count = 0;
2841 } else list = NULL;
2843 if( pTotal ) *pTotal = count;
2844 return list;
2846 /*******************************************************************
2847 * WIN_ReleaseWinArray
2849 void WIN_ReleaseWinArray(WND **wndArray)
2851 /* Future: this function will also unlock all windows associated with wndArray */
2852 HeapFree( GetProcessHeap(), 0, wndArray );
2856 /*******************************************************************
2857 * EnumWindows (USER32.193)
2859 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2861 WND **list, **ppWnd;
2863 /* We have to build a list of all windows first, to avoid */
2864 /* unpleasant side-effects, for instance if the callback */
2865 /* function changes the Z-order of the windows. */
2867 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2869 WIN_ReleaseDesktop();
2870 return FALSE;
2873 /* Now call the callback function for every window */
2875 for (ppWnd = list; *ppWnd; ppWnd++)
2877 LRESULT lpEnumFuncRetval;
2878 int iWndsLocks = 0;
2879 /* Make sure that the window still exists */
2880 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2882 /* To avoid any deadlocks, all the locks on the windows
2883 structures must be suspended before the control
2884 is passed to the application */
2885 iWndsLocks = WIN_SuspendWndsLock();
2886 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2887 WIN_RestoreWndsLock(iWndsLocks);
2889 if (!lpEnumFuncRetval) break;
2891 WIN_ReleaseWinArray(list);
2892 WIN_ReleaseDesktop();
2893 return TRUE;
2897 /**********************************************************************
2898 * EnumTaskWindows16 (USER.225)
2900 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2901 LPARAM lParam )
2903 WND **list, **ppWnd;
2905 /* This function is the same as EnumWindows(), */
2906 /* except for an added check on the window's task. */
2908 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2910 WIN_ReleaseDesktop();
2911 return FALSE;
2914 /* Now call the callback function for every window */
2916 for (ppWnd = list; *ppWnd; ppWnd++)
2918 LRESULT funcRetval;
2919 int iWndsLocks = 0;
2920 /* Make sure that the window still exists */
2921 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2922 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2924 /* To avoid any deadlocks, all the locks on the windows
2925 structures must be suspended before the control
2926 is passed to the application */
2927 iWndsLocks = WIN_SuspendWndsLock();
2928 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2929 WIN_RestoreWndsLock(iWndsLocks);
2931 if (!funcRetval) break;
2933 WIN_ReleaseWinArray(list);
2934 WIN_ReleaseDesktop();
2935 return TRUE;
2939 /**********************************************************************
2940 * EnumThreadWindows (USER32.190)
2942 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2944 TEB *teb = THREAD_IdToTEB(id);
2946 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2950 /**********************************************************************
2951 * WIN_EnumChildWindows
2953 * Helper function for EnumChildWindows().
2955 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2957 WND **childList;
2958 BOOL16 ret = FALSE;
2960 for ( ; *ppWnd; ppWnd++)
2962 int iWndsLocks = 0;
2964 /* Make sure that the window still exists */
2965 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2966 /* Build children list first */
2967 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2969 /* To avoid any deadlocks, all the locks on the windows
2970 structures must be suspended before the control
2971 is passed to the application */
2972 iWndsLocks = WIN_SuspendWndsLock();
2973 ret = func( (*ppWnd)->hwndSelf, lParam );
2974 WIN_RestoreWndsLock(iWndsLocks);
2976 if (childList)
2978 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2979 WIN_ReleaseWinArray(childList);
2981 if (!ret) return FALSE;
2983 return TRUE;
2987 /**********************************************************************
2988 * EnumChildWindows (USER32.178)
2990 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2991 LPARAM lParam )
2993 WND **list, *pParent;
2995 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2996 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2998 WIN_ReleaseWndPtr(pParent);
2999 return FALSE;
3001 WIN_EnumChildWindows( list, func, lParam );
3002 WIN_ReleaseWinArray(list);
3003 WIN_ReleaseWndPtr(pParent);
3004 return TRUE;
3008 /*******************************************************************
3009 * AnyPopup16 (USER.52)
3011 BOOL16 WINAPI AnyPopup16(void)
3013 return AnyPopup();
3017 /*******************************************************************
3018 * AnyPopup (USER32.4)
3020 BOOL WINAPI AnyPopup(void)
3022 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3023 BOOL retvalue;
3025 while (wndPtr)
3027 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3029 retvalue = TRUE;
3030 goto end;
3032 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3034 retvalue = FALSE;
3035 end:
3036 WIN_ReleaseWndPtr(wndPtr);
3037 return retvalue;
3041 /*******************************************************************
3042 * FlashWindow16 (USER.105)
3044 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3046 return FlashWindow( hWnd, bInvert );
3050 /*******************************************************************
3051 * FlashWindow (USER32.202)
3053 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3055 WND *wndPtr = WIN_FindWndPtr(hWnd);
3057 TRACE("%04x\n", hWnd);
3059 if (!wndPtr) return FALSE;
3061 if (wndPtr->dwStyle & WS_MINIMIZE)
3063 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3065 HDC hDC = GetDC(hWnd);
3067 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3068 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3070 ReleaseDC( hWnd, hDC );
3071 wndPtr->flags |= WIN_NCACTIVATED;
3073 else
3075 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3076 RDW_UPDATENOW | RDW_FRAME, 0 );
3077 wndPtr->flags &= ~WIN_NCACTIVATED;
3079 WIN_ReleaseWndPtr(wndPtr);
3080 return TRUE;
3082 else
3084 WPARAM16 wparam;
3085 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3086 else wparam = (hWnd == GetActiveWindow());
3088 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3089 WIN_ReleaseWndPtr(wndPtr);
3090 return wparam;
3095 /*******************************************************************
3096 * SetSysModalWindow16 (USER.188)
3098 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3100 HWND hWndOldModal = hwndSysModal;
3101 hwndSysModal = hWnd;
3102 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3103 return hWndOldModal;
3107 /*******************************************************************
3108 * GetSysModalWindow16 (USER.52)
3110 HWND16 WINAPI GetSysModalWindow16(void)
3112 return hwndSysModal;
3116 /*******************************************************************
3117 * GetWindowContextHelpId (USER32.303)
3119 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3121 DWORD retval;
3122 WND *wnd = WIN_FindWndPtr( hwnd );
3123 if (!wnd) return 0;
3124 retval = wnd->helpContext;
3125 WIN_ReleaseWndPtr(wnd);
3126 return retval;
3130 /*******************************************************************
3131 * SetWindowContextHelpId (USER32.515)
3133 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3135 WND *wnd = WIN_FindWndPtr( hwnd );
3136 if (!wnd) return FALSE;
3137 wnd->helpContext = id;
3138 WIN_ReleaseWndPtr(wnd);
3139 return TRUE;
3143 /*******************************************************************
3144 * DRAG_QueryUpdate
3146 * recursively find a child that contains spDragInfo->pt point
3147 * and send WM_QUERYDROPOBJECT
3149 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3151 BOOL16 wParam, bResult = 0;
3152 POINT pt;
3153 LPDRAGINFO16 ptrDragInfo = (LPDRAGINFO16) PTR_SEG_TO_LIN(spDragInfo);
3154 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3155 RECT tempRect;
3157 if( !ptrQueryWnd || !ptrDragInfo )
3158 goto end;
3160 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3162 GetWindowRect(hQueryWnd,&tempRect);
3164 if( !PtInRect(&tempRect,pt) ||
3165 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3166 goto end;
3168 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3170 tempRect = ptrQueryWnd->rectClient;
3171 if(ptrQueryWnd->dwStyle & WS_CHILD)
3172 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3173 (LPPOINT)&tempRect, 2 );
3175 if (PtInRect( &tempRect, pt))
3177 wParam = 0;
3179 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3181 if( ptrWnd->dwStyle & WS_VISIBLE )
3183 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3184 if (PtInRect( &tempRect, pt )) break;
3188 if(ptrWnd)
3190 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3191 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3192 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3193 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3194 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3196 WIN_ReleaseWndPtr(ptrWnd);
3199 if(bResult)
3200 goto end;
3202 else wParam = 1;
3204 else wParam = 1;
3206 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3208 ptrDragInfo->hScope = hQueryWnd;
3210 bResult = ( bNoSend )
3211 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3212 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3213 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3214 if( !bResult )
3215 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3217 end:
3218 WIN_ReleaseWndPtr(ptrQueryWnd);
3219 return bResult;
3223 /*******************************************************************
3224 * DragDetect (USER.465)
3226 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3228 POINT pt32;
3229 CONV_POINT16TO32( &pt, &pt32 );
3230 return DragDetect( hWnd, pt32 );
3233 /*******************************************************************
3234 * DragDetect (USER32.151)
3236 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3238 MSG msg;
3239 RECT rect;
3241 rect.left = pt.x - wDragWidth;
3242 rect.right = pt.x + wDragWidth;
3244 rect.top = pt.y - wDragHeight;
3245 rect.bottom = pt.y + wDragHeight;
3247 SetCapture(hWnd);
3249 while(1)
3251 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3253 if( msg.message == WM_LBUTTONUP )
3255 ReleaseCapture();
3256 return 0;
3258 if( msg.message == WM_MOUSEMOVE )
3260 POINT tmp;
3261 tmp.x = LOWORD(msg.lParam);
3262 tmp.y = HIWORD(msg.lParam);
3263 if( !PtInRect( &rect, tmp ))
3265 ReleaseCapture();
3266 return 1;
3270 WaitMessage();
3272 return 0;
3275 /******************************************************************************
3276 * DragObject16 (USER.464)
3278 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3279 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3281 MSG msg;
3282 LPDRAGINFO16 lpDragInfo;
3283 SEGPTR spDragInfo;
3284 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3285 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3286 WND *wndPtr = WIN_FindWndPtr(hWnd);
3287 HCURSOR16 hCurrentCursor = 0;
3288 HWND16 hCurrentWnd = 0;
3290 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3291 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3293 if( !lpDragInfo || !spDragInfo )
3295 WIN_ReleaseWndPtr(wndPtr);
3296 return 0L;
3299 hBummer = LoadCursor16(0, IDC_BUMMER16);
3301 if( !hBummer || !wndPtr )
3303 GlobalFree16(hDragInfo);
3304 WIN_ReleaseWndPtr(wndPtr);
3305 return 0L;
3308 if(hCursor)
3310 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3312 GlobalFree16(hDragInfo);
3313 WIN_ReleaseWndPtr(wndPtr);
3314 return 0L;
3317 if( hDragCursor == hCursor ) hDragCursor = 0;
3318 else hCursor = hDragCursor;
3320 hOldCursor = SetCursor(hDragCursor);
3323 lpDragInfo->hWnd = hWnd;
3324 lpDragInfo->hScope = 0;
3325 lpDragInfo->wFlags = wObj;
3326 lpDragInfo->hList = szList; /* near pointer! */
3327 lpDragInfo->hOfStruct = hOfStruct;
3328 lpDragInfo->l = 0L;
3330 SetCapture(hWnd);
3331 ShowCursor( TRUE );
3335 do{ WaitMessage(); }
3336 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3338 *(lpDragInfo+1) = *lpDragInfo;
3340 lpDragInfo->pt.x = msg.pt.x;
3341 lpDragInfo->pt.y = msg.pt.y;
3343 /* update DRAGINFO struct */
3344 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3346 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3347 hCurrentCursor = hCursor;
3348 else
3350 hCurrentCursor = hBummer;
3351 lpDragInfo->hScope = 0;
3353 if( hCurrentCursor )
3354 SetCursor(hCurrentCursor);
3356 /* send WM_DRAGLOOP */
3357 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3358 (LPARAM) spDragInfo );
3359 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3360 if( hCurrentWnd != lpDragInfo->hScope )
3362 if( hCurrentWnd )
3363 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3364 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3365 HIWORD(spDragInfo)) );
3366 hCurrentWnd = lpDragInfo->hScope;
3367 if( hCurrentWnd )
3368 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3370 else
3371 if( hCurrentWnd )
3372 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3374 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3376 ReleaseCapture();
3377 ShowCursor( FALSE );
3379 if( hCursor )
3381 SetCursor( hOldCursor );
3382 if (hDragCursor) DestroyCursor( hDragCursor );
3385 if( hCurrentCursor != hBummer )
3386 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3387 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3388 else
3389 msg.lParam = 0;
3390 GlobalFree16(hDragInfo);
3391 WIN_ReleaseWndPtr(wndPtr);
3393 return (DWORD)(msg.lParam);