Use libwine and libwine_unicode directly from their build directory
[wine/multimedia.git] / windows / win.c
blobbfe006f274d4dede5f0f179bf208c494be6bcb84
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 "class.h"
15 #include "win.h"
16 #include "heap.h"
17 #include "user.h"
18 #include "dce.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "queue.h"
24 #include "winpos.h"
25 #include "task.h"
26 #include "thread.h"
27 #include "winerror.h"
28 #include "mdi.h"
29 #include "stackframe.h"
30 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(win);
33 DECLARE_DEBUG_CHANNEL(msg);
35 /**********************************************************************/
37 WND_DRIVER *WND_Driver = NULL;
39 /* Desktop window */
40 static WND *pWndDesktop = NULL;
42 static HWND hwndSysModal = 0;
44 static WORD wDragWidth = 4;
45 static WORD wDragHeight= 3;
47 /* thread safeness */
48 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
50 /***********************************************************************
51 * WIN_LockWnds
53 * Locks access to all WND structures for thread safeness
55 void WIN_LockWnds( void )
57 _EnterSysLevel( &WIN_SysLevel );
60 /***********************************************************************
61 * WIN_UnlockWnds
63 * Unlocks access to all WND structures
65 void WIN_UnlockWnds( void )
67 _LeaveSysLevel( &WIN_SysLevel );
70 /***********************************************************************
71 * WIN_SuspendWndsLock
73 * Suspend the lock on WND structures.
74 * Returns the number of locks suspended
76 int WIN_SuspendWndsLock( void )
78 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
79 int count = isuspendedLocks;
81 while ( count-- > 0 )
82 _LeaveSysLevel( &WIN_SysLevel );
84 return isuspendedLocks;
87 /***********************************************************************
88 * WIN_RestoreWndsLock
90 * Restore the suspended locks on WND structures
92 void WIN_RestoreWndsLock( int ipreviousLocks )
94 while ( ipreviousLocks-- > 0 )
95 _EnterSysLevel( &WIN_SysLevel );
98 /***********************************************************************
99 * WIN_FindWndPtr
101 * Return a pointer to the WND structure corresponding to a HWND.
103 WND * WIN_FindWndPtr( HWND hwnd )
105 WND * ptr;
107 if (!hwnd || HIWORD(hwnd)) goto error2;
108 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
109 /* Lock all WND structures for thread safeness*/
110 WIN_LockWnds();
111 /*and increment destruction monitoring*/
112 ptr->irefCount++;
114 if (ptr->dwMagic != WND_MAGIC) goto error;
115 if (ptr->hwndSelf != hwnd)
117 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
118 goto error;
120 /* returns a locked pointer */
121 return ptr;
122 error:
123 /* Unlock all WND structures for thread safeness*/
124 WIN_UnlockWnds();
125 /* and decrement destruction monitoring value */
126 ptr->irefCount--;
128 error2:
129 if ( hwnd!=0 )
130 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
131 return NULL;
134 /***********************************************************************
135 * WIN_LockWndPtr
137 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
138 * but by initWndPtr;
139 * Returns the locked initialisation pointer
141 WND *WIN_LockWndPtr(WND *initWndPtr)
143 if(!initWndPtr) return 0;
145 /* Lock all WND structures for thread safeness*/
146 WIN_LockWnds();
147 /*and increment destruction monitoring*/
148 initWndPtr->irefCount++;
150 return initWndPtr;
154 /***********************************************************************
155 * WIN_ReleaseWndPtr
157 * Release the pointer to the WND structure.
159 void WIN_ReleaseWndPtr(WND *wndPtr)
161 if(!wndPtr) return;
163 /*Decrement destruction monitoring value*/
164 wndPtr->irefCount--;
165 /* Check if it's time to release the memory*/
166 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
168 /* Release memory */
169 USER_HEAP_FREE( wndPtr->hwndSelf);
170 wndPtr->hwndSelf = 0;
172 else if(wndPtr->irefCount < 0)
174 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
175 ERR("forgot a Lock on %p somewhere\n",wndPtr);
177 /*unlock all WND structures for thread safeness*/
178 WIN_UnlockWnds();
181 /***********************************************************************
182 * WIN_UpdateWndPtr
184 * Updates the value of oldPtr to newPtr.
186 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
188 WND *tmpWnd = NULL;
190 tmpWnd = WIN_LockWndPtr(newPtr);
191 WIN_ReleaseWndPtr(*oldPtr);
192 *oldPtr = tmpWnd;
196 /***********************************************************************
197 * WIN_DumpWindow
199 * Dump the content of a window structure to stderr.
201 void WIN_DumpWindow( HWND hwnd )
203 WND *ptr;
204 char className[80];
205 int i;
207 if (!(ptr = WIN_FindWndPtr( hwnd )))
209 WARN("%04x is not a window handle\n", hwnd );
210 return;
213 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
214 strcpy( className, "#NULL#" );
216 TRACE("Window %04x (%p):\n", hwnd, ptr );
217 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
218 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
219 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
220 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
221 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
222 ptr->next, ptr->child, ptr->parent, ptr->owner,
223 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
224 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
225 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
226 ptr->text ? debugstr_w(ptr->text) : "",
227 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
228 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
229 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
230 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
232 if (ptr->class->cbWndExtra)
234 DPRINTF( "extra bytes:" );
235 for (i = 0; i < ptr->class->cbWndExtra; i++)
236 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
237 DPRINTF( "\n" );
239 DPRINTF( "\n" );
240 WIN_ReleaseWndPtr(ptr);
244 /***********************************************************************
245 * WIN_WalkWindows
247 * Walk the windows tree and print each window on stderr.
249 void WIN_WalkWindows( HWND hwnd, int indent )
251 WND *ptr;
252 char className[80];
254 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
256 if (!ptr)
258 WARN("Invalid window handle %04x\n", hwnd );
259 return;
262 if (!indent) /* first time around */
263 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
264 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
265 " Text");
267 while (ptr)
269 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
271 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
273 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
274 (DWORD)ptr, ptr->hmemTaskQ, className,
275 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
276 ptr->text ? debugstr_w(ptr->text) : "<null>");
278 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
279 WIN_UpdateWndPtr(&ptr,ptr->next);
285 /***********************************************************************
286 * WIN_UnlinkWindow
288 * Remove a window from the siblings linked list.
290 BOOL WIN_UnlinkWindow( HWND hwnd )
292 WND *wndPtr, **ppWnd;
293 BOOL ret = FALSE;
295 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
296 else if(!wndPtr->parent)
298 WIN_ReleaseWndPtr(wndPtr);
299 return FALSE;
302 ppWnd = &wndPtr->parent->child;
303 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
304 if (*ppWnd)
306 *ppWnd = wndPtr->next;
307 ret = TRUE;
309 WIN_ReleaseWndPtr(wndPtr);
310 return ret;
314 /***********************************************************************
315 * WIN_LinkWindow
317 * Insert a window into the siblings linked list.
318 * The window is inserted after the specified window, which can also
319 * be specified as HWND_TOP or HWND_BOTTOM.
321 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
323 WND *wndPtr, **ppWnd;
325 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
326 else if(!wndPtr->parent)
328 WIN_ReleaseWndPtr(wndPtr);
329 return FALSE;
331 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
333 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
334 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
335 while (*ppWnd) ppWnd = &(*ppWnd)->next;
337 else /* Normal case */
339 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
340 if (!afterPtr)
342 WIN_ReleaseWndPtr(wndPtr);
343 return FALSE;
345 ppWnd = &afterPtr->next;
346 WIN_ReleaseWndPtr(afterPtr);
348 wndPtr->next = *ppWnd;
349 *ppWnd = wndPtr;
350 WIN_ReleaseWndPtr(wndPtr);
351 return TRUE;
355 /***********************************************************************
356 * WIN_FindWinToRepaint
358 * Find a window that needs repaint.
360 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
362 HWND hwndRet;
363 WND *pWnd;
365 /* Note: the desktop window never gets WM_PAINT messages
366 * The real reason why is because Windows DesktopWndProc
367 * does ValidateRgn inside WM_ERASEBKGND handler.
370 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
372 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
374 if (!(pWnd->dwStyle & WS_VISIBLE))
376 TRACE("skipping window %04x\n",
377 pWnd->hwndSelf );
379 else if ((pWnd->hmemTaskQ == hQueue) &&
380 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
381 break;
383 else if (pWnd->child )
384 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
386 WIN_ReleaseWndPtr(pWnd);
387 return hwndRet;
392 if(!pWnd)
394 return 0;
397 hwndRet = pWnd->hwndSelf;
399 /* look among siblings if we got a transparent window */
400 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
401 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
403 WIN_UpdateWndPtr(&pWnd,pWnd->next);
405 if (pWnd)
407 hwndRet = pWnd->hwndSelf;
408 WIN_ReleaseWndPtr(pWnd);
410 TRACE("found %04x\n",hwndRet);
411 return hwndRet;
415 /***********************************************************************
416 * WIN_DestroyWindow
418 * Destroy storage associated to a window. "Internals" p.358
419 * returns a locked wndPtr->next
421 static WND* WIN_DestroyWindow( WND* wndPtr )
423 HWND hwnd = wndPtr->hwndSelf;
424 WND *pWnd;
426 TRACE("%04x\n", wndPtr->hwndSelf );
428 /* free child windows */
429 WIN_LockWndPtr(wndPtr->child);
430 while ((pWnd = wndPtr->child))
432 wndPtr->child = WIN_DestroyWindow( pWnd );
433 WIN_ReleaseWndPtr(pWnd);
437 * Clear the update region to make sure no WM_PAINT messages will be
438 * generated for this window while processing the WM_NCDESTROY.
440 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
442 if (wndPtr->hrgnUpdate > 1)
443 DeleteObject( wndPtr->hrgnUpdate );
445 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
447 wndPtr->hrgnUpdate = 0;
451 * Send the WM_NCDESTROY to the window being destroyed.
453 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
455 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
457 WINPOS_CheckInternalPos( wndPtr );
458 if( hwnd == GetCapture()) ReleaseCapture();
460 /* free resources associated with the window */
462 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
463 PROPERTY_RemoveWindowProps( wndPtr );
465 wndPtr->dwMagic = 0; /* Mark it as invalid */
467 /* toss stale messages from the queue */
469 if( wndPtr->hmemTaskQ )
471 BOOL bPostQuit = FALSE;
472 WPARAM wQuitParam = 0;
473 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
474 QMSG *qmsg;
476 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
478 if( qmsg->msg.message == WM_QUIT )
480 bPostQuit = TRUE;
481 wQuitParam = qmsg->msg.wParam;
483 QUEUE_RemoveMsg(msgQ, qmsg);
486 QUEUE_Unlock(msgQ);
488 /* repost WM_QUIT to make sure this app exits its message loop */
489 if( bPostQuit ) PostQuitMessage(wQuitParam);
490 wndPtr->hmemTaskQ = 0;
493 if (!(wndPtr->dwStyle & WS_CHILD))
494 if (wndPtr->wIDmenu)
496 DestroyMenu( wndPtr->wIDmenu );
497 wndPtr->wIDmenu = 0;
499 if (wndPtr->hSysMenu)
501 DestroyMenu( wndPtr->hSysMenu );
502 wndPtr->hSysMenu = 0;
504 wndPtr->pDriver->pDestroyWindow( wndPtr );
505 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
506 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
507 wndPtr->class->cWindows--;
508 wndPtr->class = NULL;
510 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
512 wndPtr->pDriver->pFinalize(wndPtr);
514 return pWnd;
517 /***********************************************************************
518 * WIN_ResetQueueWindows
520 * Reset the queue of all the children of a given window.
521 * Return TRUE if something was done.
523 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
525 BOOL ret = FALSE;
527 if (hNew) /* Set a new queue */
529 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
531 if (wnd->hmemTaskQ == hQueue)
533 wnd->hmemTaskQ = hNew;
534 ret = TRUE;
536 if (wnd->child)
538 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
542 else /* Queue is being destroyed */
544 while (wnd->child)
546 WND *tmp = WIN_LockWndPtr(wnd->child);
547 WND *tmp2;
548 ret = FALSE;
549 while (tmp)
551 if (tmp->hmemTaskQ == hQueue)
553 DestroyWindow( tmp->hwndSelf );
554 ret = TRUE;
555 break;
557 tmp2 = WIN_LockWndPtr(tmp->child);
558 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
559 ret = TRUE;
560 else
562 WIN_UpdateWndPtr(&tmp,tmp->next);
564 WIN_ReleaseWndPtr(tmp2);
566 WIN_ReleaseWndPtr(tmp);
567 if (!ret) break;
570 return ret;
573 /***********************************************************************
574 * WIN_CreateDesktopWindow
576 * Create the desktop window.
578 BOOL WIN_CreateDesktopWindow(void)
580 CLASS *class;
581 HWND hwndDesktop;
583 TRACE("Creating desktop window\n");
586 if (!ICONTITLE_Init() ||
587 !WINPOS_CreateInternalPosAtom() ||
588 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
589 return FALSE;
591 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
592 if (!hwndDesktop) return FALSE;
593 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
595 pWndDesktop->pDriver = WND_Driver;
596 pWndDesktop->pDriver->pInitialize(pWndDesktop);
598 pWndDesktop->next = NULL;
599 pWndDesktop->child = NULL;
600 pWndDesktop->parent = NULL;
601 pWndDesktop->owner = NULL;
602 pWndDesktop->class = class;
603 pWndDesktop->dwMagic = WND_MAGIC;
604 pWndDesktop->hwndSelf = hwndDesktop;
605 pWndDesktop->hInstance = 0;
606 pWndDesktop->rectWindow.left = 0;
607 pWndDesktop->rectWindow.top = 0;
608 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
609 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
610 pWndDesktop->rectClient = pWndDesktop->rectWindow;
611 pWndDesktop->text = NULL;
612 pWndDesktop->hmemTaskQ = GetFastQueue16();
613 pWndDesktop->hrgnUpdate = 0;
614 pWndDesktop->hwndLastActive = hwndDesktop;
615 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
616 WS_CLIPSIBLINGS;
617 pWndDesktop->dwExStyle = 0;
618 pWndDesktop->dce = NULL;
619 pWndDesktop->pVScroll = NULL;
620 pWndDesktop->pHScroll = NULL;
621 pWndDesktop->pProp = NULL;
622 pWndDesktop->wIDmenu = 0;
623 pWndDesktop->helpContext = 0;
624 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
625 pWndDesktop->hSysMenu = 0;
626 pWndDesktop->userdata = 0;
627 pWndDesktop->winproc = (WNDPROC16)class->winproc;
628 pWndDesktop->irefCount = 0;
630 /* FIXME: How do we know if it should be Unicode or not */
631 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
632 return FALSE;
634 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
635 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
636 return TRUE;
640 /***********************************************************************
641 * WIN_FixCoordinates
643 * Fix the coordinates - Helper for WIN_CreateWindowEx.
644 * returns default show mode in sw.
645 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
647 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
649 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
650 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
652 if (cs->style & (WS_CHILD | WS_POPUP))
654 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
655 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
657 else /* overlapped window */
659 STARTUPINFOA info;
661 GetStartupInfoA( &info );
663 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
665 /* Never believe Microsoft's documentation... CreateWindowEx doc says
666 * that if an overlapped window is created with WS_VISIBLE style bit
667 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
668 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
669 * reveals that
671 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
672 * 2) it does not ignore the y parameter as the docs claim; instead, it
673 * uses it as second parameter to ShowWindow() unless y is either
674 * CW_USEDEFAULT or CW_USEDEFAULT16.
676 * The fact that we didn't do 2) caused bogus windows pop up when wine
677 * was running apps that were using this obscure feature. Example -
678 * calc.exe that comes with Win98 (only Win98, it's different from
679 * the one that comes with Win95 and NT)
681 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
682 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
683 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
686 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
688 if (info.dwFlags & STARTF_USESIZE)
690 cs->cx = info.dwXSize;
691 cs->cy = info.dwYSize;
693 else /* if no other hint from the app, pick 3/4 of the screen real estate */
695 RECT r;
696 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
697 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
698 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
705 /***********************************************************************
706 * WIN_CreateWindowEx
708 * Implementation of CreateWindowEx().
710 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
711 WINDOWPROCTYPE type )
713 INT sw = SW_SHOW;
714 CLASS *classPtr;
715 WND *wndPtr;
716 HWND retvalue;
717 HWND16 hwnd, hwndLinkAfter;
718 POINT maxSize, maxPos, minTrack, maxTrack;
719 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
721 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
722 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
723 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
724 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
725 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
727 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
728 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
730 /* Find the parent window */
732 if (cs->hwndParent)
734 /* Make sure parent is valid */
735 if (!IsWindow( cs->hwndParent ))
737 WARN("Bad parent %04x\n", cs->hwndParent );
738 return 0;
740 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
741 WARN("No parent for child window\n" );
742 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
745 /* Find the window class */
746 if (!(classPtr = CLASS_FindClassByAtom( classAtom, (type == WIN_PROC_16) ? GetExePtr(cs->hInstance) : cs->hInstance )))
748 WARN("Bad class '%s'\n", cs->lpszClass );
749 return 0;
752 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
754 /* Create the window structure */
756 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
757 - sizeof(wndPtr->wExtra) )))
759 TRACE("out of memory\n" );
760 return 0;
763 /* Fill the window structure */
765 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
766 wndPtr->next = NULL;
767 wndPtr->child = NULL;
769 if ((cs->style & WS_CHILD) && cs->hwndParent)
771 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
772 wndPtr->owner = NULL;
773 WIN_ReleaseWndPtr(wndPtr->parent);
775 else
777 wndPtr->parent = pWndDesktop;
778 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
779 wndPtr->owner = NULL;
780 else
782 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
783 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
784 WIN_ReleaseWndPtr(wndPtr->owner);
785 WIN_ReleaseWndPtr(tmpWnd);
790 wndPtr->pDriver = wndPtr->parent->pDriver;
791 wndPtr->pDriver->pInitialize(wndPtr);
793 wndPtr->class = classPtr;
794 wndPtr->winproc = classPtr->winproc;
795 wndPtr->dwMagic = WND_MAGIC;
796 wndPtr->hwndSelf = hwnd;
797 wndPtr->hInstance = cs->hInstance;
798 wndPtr->text = NULL;
799 wndPtr->hmemTaskQ = GetFastQueue16();
800 wndPtr->hrgnUpdate = 0;
801 wndPtr->hrgnWnd = 0;
802 wndPtr->hwndLastActive = hwnd;
803 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
804 wndPtr->dwExStyle = cs->dwExStyle;
805 wndPtr->wIDmenu = 0;
806 wndPtr->helpContext = 0;
807 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
808 wndPtr->pVScroll = NULL;
809 wndPtr->pHScroll = NULL;
810 wndPtr->pProp = NULL;
811 wndPtr->userdata = 0;
812 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
813 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
814 wndPtr->irefCount = 1;
816 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
818 /* Call the WH_CBT hook */
820 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
821 ? HWND_BOTTOM : HWND_TOP;
823 if (HOOK_IsHooked( WH_CBT ))
825 CBT_CREATEWNDA cbtc;
826 LRESULT ret;
828 cbtc.lpcs = cs;
829 cbtc.hwndInsertAfter = hwndLinkAfter;
830 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
831 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
832 if (ret)
834 TRACE("CBT-hook returned 0\n");
835 wndPtr->pDriver->pFinalize(wndPtr);
836 USER_HEAP_FREE( hwnd );
837 retvalue = 0;
838 goto end;
842 /* Increment class window counter */
844 classPtr->cWindows++;
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 (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
861 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->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, classPtr, 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 /* FIXME: should check if classPtr->menuNameW can be used as is */
906 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
907 if (menuName)
909 if (HIWORD(cs->hInstance))
910 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
911 else
912 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
914 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
918 else wndPtr->wIDmenu = (UINT)cs->hMenu;
920 /* Send the WM_CREATE message
921 * Perhaps we shouldn't allow width/height changes as well.
922 * See p327 in "Internals".
925 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
927 localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
928 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
930 /* Insert the window in the linked list */
932 WIN_LinkWindow( hwnd, hwndLinkAfter );
934 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
935 NULL, NULL, 0, &wndPtr->rectClient );
936 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
937 maxPos.y - wndPtr->rectWindow.top);
938 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
940 /* Send the size messages */
942 if (!(wndPtr->flags & WIN_NEED_SIZE))
944 /* send it anyway */
945 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
946 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
947 WARN("sending bogus WM_SIZE message 0x%08lx\n",
948 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
949 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
950 (*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
951 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
952 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
953 (*localSend32)( hwnd, WM_MOVE, 0,
954 MAKELONG( wndPtr->rectClient.left,
955 wndPtr->rectClient.top ) );
958 /* Show the window, maximizing or minimizing if needed */
960 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
962 RECT16 newPos;
963 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
964 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
965 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
966 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
967 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
968 : SWP_NOZORDER | SWP_FRAMECHANGED;
969 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
970 newPos.right, newPos.bottom, swFlag );
973 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
975 /* Notify the parent window only */
977 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
978 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
979 if( !IsWindow(hwnd) )
981 retvalue = 0;
982 goto end;
986 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
988 /* Call WH_SHELL hook */
990 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
991 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
993 TRACE("created window %04x\n", hwnd);
994 retvalue = hwnd;
995 goto end;
997 WIN_UnlinkWindow( hwnd );
1000 /* Abort window creation */
1002 WARN("aborted by WM_xxCREATE!\n");
1003 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1004 retvalue = 0;
1005 end:
1006 WIN_ReleaseWndPtr(wndPtr);
1008 return retvalue;
1012 /***********************************************************************
1013 * CreateWindow16 (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 * CreateWindowEx16 (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.83)
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 MDI_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.84)
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 MDI_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 * DestroyWindow16 (USER.53)
1294 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1296 return DestroyWindow(hwnd);
1300 /***********************************************************************
1301 * DestroyWindow (USER32.135)
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(GetWindowLongA(hwnd,GWL_HWNDPARENT));
1330 bFocusSet = TRUE;
1331 break;
1333 h = GetWindowLongA(h,GWL_HWNDPARENT);
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 * CloseWindow16 (USER.43)
1450 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1452 return CloseWindow( hwnd );
1456 /***********************************************************************
1457 * CloseWindow (USER32.56)
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 * OpenIcon16 (USER.44)
1481 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1483 return OpenIcon( hwnd );
1487 /***********************************************************************
1488 * OpenIcon (USER32.410)
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 && (pWnd->class->atomName != 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 end:
1562 WIN_ReleaseWndPtr(pWnd);
1563 return retvalue;
1568 /***********************************************************************
1569 * FindWindow16 (USER.50)
1571 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1573 return FindWindowA( className, title );
1577 /***********************************************************************
1578 * FindWindowEx16 (USER.427)
1580 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1582 return FindWindowExA( parent, child, className, title );
1586 /***********************************************************************
1587 * FindWindowA (USER32.198)
1589 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1591 HWND ret = FindWindowExA( 0, 0, className, title );
1592 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1593 return ret;
1597 /***********************************************************************
1598 * FindWindowExA (USER32.199)
1600 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1601 LPCSTR className, LPCSTR title )
1603 ATOM atom = 0;
1604 LPWSTR buffer;
1605 HWND hwnd;
1607 if (className)
1609 /* If the atom doesn't exist, then no class */
1610 /* with this name exists either. */
1611 if (!(atom = GlobalFindAtomA( className )))
1613 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1614 return 0;
1618 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1619 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1620 HeapFree( GetProcessHeap(), 0, buffer );
1621 return hwnd;
1625 /***********************************************************************
1626 * FindWindowExW (USER32.200)
1628 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1629 LPCWSTR className, LPCWSTR title )
1631 ATOM atom = 0;
1633 if (className)
1635 /* If the atom doesn't exist, then no class */
1636 /* with this name exists either. */
1637 if (!(atom = GlobalFindAtomW( className )))
1639 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1640 return 0;
1643 return WIN_FindWindow( parent, child, atom, title );
1647 /***********************************************************************
1648 * FindWindowW (USER32.201)
1650 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1652 return FindWindowExW( 0, 0, className, title );
1656 /**********************************************************************
1657 * WIN_GetDesktop
1658 * returns a locked pointer
1660 WND *WIN_GetDesktop(void)
1662 return WIN_LockWndPtr(pWndDesktop);
1664 /**********************************************************************
1665 * WIN_ReleaseDesktop
1666 * unlock the desktop pointer
1668 void WIN_ReleaseDesktop(void)
1670 WIN_ReleaseWndPtr(pWndDesktop);
1674 /**********************************************************************
1675 * GetDesktopWindow16 (USER.286)
1677 HWND16 WINAPI GetDesktopWindow16(void)
1679 return (HWND16)pWndDesktop->hwndSelf;
1683 /**********************************************************************
1684 * GetDesktopWindow (USER32.232)
1686 HWND WINAPI GetDesktopWindow(void)
1688 if (pWndDesktop) return pWndDesktop->hwndSelf;
1689 ERR( "You need the -desktop option when running with native USER\n" );
1690 ExitProcess(1);
1691 return 0;
1695 /**********************************************************************
1696 * GetDesktopHwnd (USER.278)
1698 * Exactly the same thing as GetDesktopWindow(), but not documented.
1699 * Don't ask me why...
1701 HWND16 WINAPI GetDesktopHwnd16(void)
1703 return (HWND16)pWndDesktop->hwndSelf;
1707 /*******************************************************************
1708 * EnableWindow16 (USER.34)
1710 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1712 return EnableWindow( hwnd, enable );
1716 /*******************************************************************
1717 * EnableWindow (USER32.172)
1719 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1721 WND *wndPtr;
1722 BOOL retvalue;
1724 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1726 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1727 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1729 /* Enable window */
1730 wndPtr->dwStyle &= ~WS_DISABLED;
1732 if( wndPtr->flags & WIN_NATIVE )
1733 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1735 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1736 retvalue = TRUE;
1737 goto end;
1739 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1741 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1743 /* Disable window */
1744 wndPtr->dwStyle |= WS_DISABLED;
1746 if( wndPtr->flags & WIN_NATIVE )
1747 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1749 if (hwnd == GetFocus())
1751 SetFocus( 0 ); /* A disabled window can't have the focus */
1753 if (hwnd == GetCapture())
1755 ReleaseCapture(); /* A disabled window can't capture the mouse */
1757 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1758 retvalue = FALSE;
1759 goto end;
1761 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1762 end:
1763 WIN_ReleaseWndPtr(wndPtr);
1764 return retvalue;
1768 /***********************************************************************
1769 * IsWindowEnabled16 (USER.35)
1771 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1773 return IsWindowEnabled(hWnd);
1777 /***********************************************************************
1778 * IsWindowEnabled (USER32.349)
1780 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1782 WND * wndPtr;
1783 BOOL retvalue;
1785 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1786 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1787 WIN_ReleaseWndPtr(wndPtr);
1788 return retvalue;
1793 /***********************************************************************
1794 * IsWindowUnicode (USER32.350)
1796 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1798 WND * wndPtr;
1799 BOOL retvalue;
1801 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1802 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1803 WIN_ReleaseWndPtr(wndPtr);
1804 return retvalue;
1808 /**********************************************************************
1809 * GetWindowWord16 (USER.133)
1811 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1813 return GetWindowWord( hwnd, offset );
1817 /**********************************************************************
1818 * GetWindowWord (USER32.314)
1820 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1822 WORD retvalue;
1823 WND * wndPtr = WIN_FindWndPtr( hwnd );
1824 if (!wndPtr) return 0;
1825 if (offset >= 0)
1827 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1829 WARN("Invalid offset %d\n", offset );
1830 retvalue = 0;
1831 goto end;
1833 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1834 goto end;
1836 switch(offset)
1838 case GWW_ID:
1839 if (HIWORD(wndPtr->wIDmenu))
1840 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1841 wndPtr->wIDmenu);
1842 retvalue = (WORD)wndPtr->wIDmenu;
1843 goto end;
1844 case GWW_HWNDPARENT:
1845 retvalue = GetParent(hwnd);
1846 goto end;
1847 case GWW_HINSTANCE:
1848 if (HIWORD(wndPtr->hInstance))
1849 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1850 wndPtr->hInstance);
1851 retvalue = (WORD)wndPtr->hInstance;
1852 goto end;
1853 default:
1854 WARN("Invalid offset %d\n", offset );
1855 retvalue = 0;
1856 goto end;
1858 end:
1859 WIN_ReleaseWndPtr(wndPtr);
1860 return retvalue;
1863 /**********************************************************************
1864 * SetWindowWord16 (USER.134)
1866 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1868 return SetWindowWord( hwnd, offset, newval );
1872 /**********************************************************************
1873 * SetWindowWord (USER32.524)
1875 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1877 WORD *ptr, retval;
1878 WND * wndPtr = WIN_FindWndPtr( hwnd );
1879 if (!wndPtr) return 0;
1880 if (offset >= 0)
1882 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1884 WARN("Invalid offset %d\n", offset );
1885 retval = 0;
1886 goto end;
1888 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1890 else switch(offset)
1892 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1893 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1894 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1895 goto end;
1896 default:
1897 WARN("Invalid offset %d\n", offset );
1898 retval = 0;
1899 goto end;
1901 retval = *ptr;
1902 *ptr = newval;
1903 end:
1904 WIN_ReleaseWndPtr(wndPtr);
1905 return retval;
1909 /**********************************************************************
1910 * WIN_GetWindowLong
1912 * Helper function for GetWindowLong().
1914 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1916 LONG retvalue;
1917 WND * wndPtr = WIN_FindWndPtr( hwnd );
1918 if (!wndPtr) return 0;
1919 if (offset >= 0)
1921 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1923 WARN("Invalid offset %d\n", offset );
1924 retvalue = 0;
1925 goto end;
1927 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1928 /* Special case for dialog window procedure */
1929 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1931 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1932 goto end;
1934 goto end;
1936 switch(offset)
1938 case GWL_USERDATA: retvalue = wndPtr->userdata;
1939 goto end;
1940 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1941 goto end;
1942 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1943 goto end;
1944 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1945 goto end;
1946 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1947 type );
1948 goto end;
1949 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1950 goto end;
1951 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1952 goto end;
1953 default:
1954 WARN("Unknown offset %d\n", offset );
1956 retvalue = 0;
1957 end:
1958 WIN_ReleaseWndPtr(wndPtr);
1959 return retvalue;
1963 /**********************************************************************
1964 * WIN_SetWindowLong
1966 * Helper function for SetWindowLong().
1968 * 0 is the failure code. However, in the case of failure SetLastError
1969 * must be set to distinguish between a 0 return value and a failure.
1971 * FIXME: The error values for SetLastError may not be right. Can
1972 * someone check with the real thing?
1974 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1975 WINDOWPROCTYPE type )
1977 LONG *ptr, retval;
1978 WND * wndPtr = WIN_FindWndPtr( hwnd );
1979 STYLESTRUCT style;
1981 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1983 if (!wndPtr)
1985 /* Is this the right error? */
1986 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1987 return 0;
1990 if (offset >= 0)
1992 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1994 WARN("Invalid offset %d\n", offset );
1996 /* Is this the right error? */
1997 SetLastError( ERROR_OUTOFMEMORY );
1999 retval = 0;
2000 goto end;
2002 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2003 /* Special case for dialog window procedure */
2004 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2006 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2007 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2008 type, WIN_PROC_WINDOW );
2009 goto end;
2012 else switch(offset)
2014 case GWL_ID:
2015 ptr = (DWORD*)&wndPtr->wIDmenu;
2016 break;
2017 case GWL_HINSTANCE:
2018 retval = SetWindowWord( hwnd, offset, newval );
2019 goto end;
2020 case GWL_WNDPROC:
2021 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2022 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2023 type, WIN_PROC_WINDOW );
2024 goto end;
2025 case GWL_STYLE:
2026 style.styleOld = wndPtr->dwStyle;
2027 newval &= ~(WS_CHILD); /* this bit can't be changed this way */
2028 style.styleNew = newval | (style.styleOld & (WS_CHILD));
2030 if (wndPtr->flags & WIN_ISWIN32)
2031 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2032 wndPtr->dwStyle = style.styleNew;
2033 if (wndPtr->flags & WIN_ISWIN32)
2034 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2035 retval = style.styleOld;
2036 goto end;
2038 case GWL_USERDATA:
2039 ptr = &wndPtr->userdata;
2040 break;
2041 case GWL_EXSTYLE:
2042 style.styleOld = wndPtr->dwExStyle;
2043 style.styleNew = newval;
2044 if (wndPtr->flags & WIN_ISWIN32)
2045 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2046 wndPtr->dwExStyle = newval;
2047 if (wndPtr->flags & WIN_ISWIN32)
2048 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2049 retval = style.styleOld;
2050 goto end;
2052 default:
2053 WARN("Invalid offset %d\n", offset );
2055 /* Don't think this is right error but it should do */
2056 SetLastError( ERROR_OUTOFMEMORY );
2058 retval = 0;
2059 goto end;
2061 retval = *ptr;
2062 *ptr = newval;
2063 end:
2064 WIN_ReleaseWndPtr(wndPtr);
2065 return retval;
2069 /**********************************************************************
2070 * GetWindowLong16 (USER.135)
2072 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2074 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2078 /**********************************************************************
2079 * GetWindowLongA (USER32.305)
2081 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2083 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2087 /**********************************************************************
2088 * GetWindowLongW (USER32.306)
2090 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2092 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2096 /**********************************************************************
2097 * SetWindowLong16 (USER.136)
2099 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2101 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2105 /**********************************************************************
2106 * SetWindowLongA (USER32.517)
2108 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2110 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2114 /**********************************************************************
2115 * SetWindowLongW (USER32.518) Set window attribute
2117 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2118 * value in a window's extra memory.
2120 * The _hwnd_ parameter specifies the window. is the handle to a
2121 * window that has extra memory. The _newval_ parameter contains the
2122 * new attribute or extra memory value. If positive, the _offset_
2123 * parameter is the byte-addressed location in the window's extra
2124 * memory to set. If negative, _offset_ specifies the window
2125 * attribute to set, and should be one of the following values:
2127 * GWL_EXSTYLE The window's extended window style
2129 * GWL_STYLE The window's window style.
2131 * GWL_WNDPROC Pointer to the window's window procedure.
2133 * GWL_HINSTANCE The window's pplication instance handle.
2135 * GWL_ID The window's identifier.
2137 * GWL_USERDATA The window's user-specified data.
2139 * If the window is a dialog box, the _offset_ parameter can be one of
2140 * the following values:
2142 * DWL_DLGPROC The address of the window's dialog box procedure.
2144 * DWL_MSGRESULT The return value of a message
2145 * that the dialog box procedure processed.
2147 * DWL_USER Application specific information.
2149 * RETURNS
2151 * If successful, returns the previous value located at _offset_. Otherwise,
2152 * returns 0.
2154 * NOTES
2156 * Extra memory for a window class is specified by a nonzero cbWndExtra
2157 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2158 * time of class creation.
2160 * Using GWL_WNDPROC to set a new window procedure effectively creates
2161 * a window subclass. Use CallWindowProc() in the new windows procedure
2162 * to pass messages to the superclass's window procedure.
2164 * The user data is reserved for use by the application which created
2165 * the window.
2167 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2168 * instead, call the EnableWindow() function to change the window's
2169 * disabled state.
2171 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2172 * SetParent() instead.
2174 * Win95:
2175 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2176 * it sends WM_STYLECHANGING before changing the settings
2177 * and WM_STYLECHANGED afterwards.
2178 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2180 * BUGS
2182 * GWL_STYLE does not dispatch WM_STYLE... messages.
2184 * CONFORMANCE
2186 * ECMA-234, Win32
2189 LONG WINAPI SetWindowLongW(
2190 HWND hwnd, /* [in] window to alter */
2191 INT offset, /* [in] offset, in bytes, of location to alter */
2192 LONG newval /* [in] new value of location */
2194 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2198 /*******************************************************************
2199 * GetWindowText16 (USER.36)
2201 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2203 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2207 /*******************************************************************
2208 * GetWindowTextA (USER32.309)
2210 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2212 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2213 (LPARAM)lpString );
2216 /*******************************************************************
2217 * InternalGetWindowText (USER32.326)
2219 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2221 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2222 return GetWindowTextW(hwnd,lpString,nMaxCount);
2226 /*******************************************************************
2227 * GetWindowTextW (USER32.312)
2229 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2231 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2232 (LPARAM)lpString );
2236 /*******************************************************************
2237 * SetWindowText16 (USER.37)
2239 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2241 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2245 /*******************************************************************
2246 * SetWindowTextA (USER32.521)
2248 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2250 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2254 /*******************************************************************
2255 * SetWindowTextW (USER32.523)
2257 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2259 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2263 /*******************************************************************
2264 * GetWindowTextLength16 (USER.38)
2266 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2268 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2272 /*******************************************************************
2273 * GetWindowTextLengthA (USER32.310)
2275 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2277 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2280 /*******************************************************************
2281 * GetWindowTextLengthW (USER32.311)
2283 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2285 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2289 /*******************************************************************
2290 * IsWindow16 (USER.47)
2292 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2294 CURRENT_STACK16->es = USER_HeapSel;
2295 return IsWindow( hwnd );
2299 /*******************************************************************
2300 * IsWindow (USER32.348)
2302 BOOL WINAPI IsWindow( HWND hwnd )
2304 WND * wndPtr;
2305 BOOL retvalue;
2307 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2308 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2309 WIN_ReleaseWndPtr(wndPtr);
2310 return retvalue;
2315 /*****************************************************************
2316 * GetParent16 (USER.46)
2318 HWND16 WINAPI GetParent16( HWND16 hwnd )
2320 return (HWND16)GetParent( hwnd );
2324 /*****************************************************************
2325 * GetParent (USER32.278)
2327 HWND WINAPI GetParent( HWND hwnd )
2329 WND *wndPtr;
2330 HWND retvalue = 0;
2332 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2333 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2334 goto end;
2336 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2337 if (wndPtr)
2338 retvalue = wndPtr->hwndSelf;
2340 end:
2341 WIN_ReleaseWndPtr(wndPtr);
2342 return retvalue;
2346 /*****************************************************************
2347 * WIN_GetTopParent
2349 * Get the top-level parent for a child window.
2350 * returns a locked pointer
2352 WND* WIN_GetTopParentPtr( WND* pWnd )
2354 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2356 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2358 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2360 return tmpWnd;
2363 /*****************************************************************
2364 * WIN_GetTopParent
2366 * Get the top-level parent for a child window.
2368 HWND WIN_GetTopParent( HWND hwnd )
2370 HWND retvalue;
2371 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2372 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2374 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2375 WIN_ReleaseWndPtr(tmpPtr);
2376 WIN_ReleaseWndPtr(wndPtr);
2377 return retvalue;
2381 /*****************************************************************
2382 * SetParent16 (USER.233)
2384 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2386 return SetParent( hwndChild, hwndNewParent );
2390 /*****************************************************************
2391 * SetParent (USER32.495)
2393 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2395 WND *wndPtr;
2396 DWORD dwStyle;
2397 WND *pWndNewParent;
2398 WND *pWndOldParent;
2399 HWND retvalue;
2402 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2404 dwStyle = wndPtr->dwStyle;
2406 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2407 : WIN_LockWndPtr(pWndDesktop);
2409 /* Windows hides the window first, then shows it again
2410 * including the WM_SHOWWINDOW messages and all */
2411 if (dwStyle & WS_VISIBLE)
2412 ShowWindow( hwndChild, SW_HIDE );
2414 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2416 /* SetParent additionally needs to make hwndChild the topmost window
2417 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2418 WM_WINDOWPOSCHANGED notification messages.
2420 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2421 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2422 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2423 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2425 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2427 WIN_ReleaseWndPtr(pWndOldParent);
2428 WIN_ReleaseWndPtr(pWndNewParent);
2429 WIN_ReleaseWndPtr(wndPtr);
2431 return retvalue;
2435 /*******************************************************************
2436 * IsChild16 (USER.48)
2438 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2440 return IsChild(parent,child);
2444 /*******************************************************************
2445 * IsChild (USER32.339)
2447 BOOL WINAPI IsChild( HWND parent, HWND child )
2449 WND * wndPtr = WIN_FindWndPtr( child );
2450 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2452 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2453 if (wndPtr->hwndSelf == parent)
2455 WIN_ReleaseWndPtr(wndPtr);
2456 return TRUE;
2459 WIN_ReleaseWndPtr(wndPtr);
2460 return FALSE;
2464 /***********************************************************************
2465 * IsWindowVisible16 (USER.49)
2467 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2469 return IsWindowVisible(hwnd);
2473 /***********************************************************************
2474 * IsWindowVisible (USER32.351)
2476 BOOL WINAPI IsWindowVisible( HWND hwnd )
2478 BOOL retval;
2479 WND *wndPtr = WIN_FindWndPtr( hwnd );
2480 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2482 if (!(wndPtr->dwStyle & WS_VISIBLE))
2484 WIN_ReleaseWndPtr(wndPtr);
2485 return FALSE;
2487 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2489 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2490 WIN_ReleaseWndPtr(wndPtr);
2491 return retval;
2496 /***********************************************************************
2497 * WIN_IsWindowDrawable
2499 * hwnd is drawable when it is visible, all parents are not
2500 * minimized, and it is itself not minimized unless we are
2501 * trying to draw its default class icon.
2503 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2505 if( (wnd->dwStyle & WS_MINIMIZE &&
2506 icon && wnd->class->hIcon) ||
2507 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2508 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2509 if( wnd->dwStyle & WS_MINIMIZE ||
2510 !(wnd->dwStyle & WS_VISIBLE) ) break;
2511 return (wnd == NULL);
2515 /*******************************************************************
2516 * GetTopWindow16 (USER.229)
2518 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2520 return GetTopWindow(hwnd);
2524 /*******************************************************************
2525 * GetTopWindow (USER.229)
2527 HWND WINAPI GetTopWindow( HWND hwnd )
2529 HWND retval = 0;
2530 WND * wndPtr = (hwnd) ?
2531 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2533 if (wndPtr && wndPtr->child)
2534 retval = wndPtr->child->hwndSelf;
2536 WIN_ReleaseWndPtr(wndPtr);
2537 return retval;
2541 /*******************************************************************
2542 * GetWindow16 (USER.262)
2544 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2546 return GetWindow( hwnd,rel );
2550 /*******************************************************************
2551 * GetWindow (USER32.302)
2553 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2555 HWND retval;
2557 WND * wndPtr = WIN_FindWndPtr( hwnd );
2558 if (!wndPtr) return 0;
2559 switch(rel)
2561 case GW_HWNDFIRST:
2562 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2563 goto end;
2565 case GW_HWNDLAST:
2566 if (!wndPtr->parent)
2568 retval = 0; /* Desktop window */
2569 goto end;
2571 while (wndPtr->next)
2573 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2575 retval = wndPtr->hwndSelf;
2576 goto end;
2578 case GW_HWNDNEXT:
2579 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2580 goto end;
2582 case GW_HWNDPREV:
2583 if (!wndPtr->parent)
2585 retval = 0; /* Desktop window */
2586 goto end;
2588 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2589 if (wndPtr->hwndSelf == hwnd)
2591 retval = 0; /* First in list */
2592 goto end;
2594 while (wndPtr->next)
2596 if (wndPtr->next->hwndSelf == hwnd)
2598 retval = wndPtr->hwndSelf;
2599 goto end;
2601 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2603 retval = 0;
2604 goto end;
2606 case GW_OWNER:
2607 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2608 goto end;
2610 case GW_CHILD:
2611 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2612 goto end;
2614 retval = 0;
2615 end:
2616 WIN_ReleaseWndPtr(wndPtr);
2617 return retval;
2621 /*******************************************************************
2622 * GetNextWindow16 (USER.230)
2624 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2626 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2627 return GetWindow16( hwnd, flag );
2630 /***********************************************************************
2631 * WIN_InternalShowOwnedPopups
2633 * Internal version of ShowOwnedPopups; Wine functions should use this
2634 * to avoid interfering with application calls to ShowOwnedPopups
2635 * and to make sure the application can't prevent showing/hiding.
2637 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2641 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2643 INT totalChild=0, count=0;
2645 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2647 if (!pWnd) return TRUE;
2650 * Show windows Lowest first, Highest last to preserve Z-Order
2652 for (count = totalChild-1 ; count >=0; count--)
2654 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2656 if (fShow)
2658 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2659 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2662 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2664 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2665 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2668 else
2670 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2671 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2672 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2675 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2677 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2678 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2679 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2684 WIN_ReleaseDesktop();
2685 WIN_ReleaseWinArray(pWnd);
2687 return TRUE;
2690 /*******************************************************************
2691 * ShowOwnedPopups16 (USER.265)
2693 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2695 ShowOwnedPopups( owner, fShow );
2699 /*******************************************************************
2700 * ShowOwnedPopups (USER32.531)
2702 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2704 UINT totalChild=0, count=0;
2706 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2708 if (!pWnd) return TRUE;
2710 for (; count < totalChild; count++)
2712 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2714 if (fShow)
2716 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2719 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2720 * regardless of the state of the owner
2722 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2723 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2726 else
2728 if (IsWindowVisible(pWnd[count]->hwndSelf))
2731 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2732 * regardless of the state of the owner
2734 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2735 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2741 WIN_ReleaseDesktop();
2742 WIN_ReleaseWinArray(pWnd);
2743 return TRUE;
2747 /*******************************************************************
2748 * GetLastActivePopup16 (USER.287)
2750 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2752 return GetLastActivePopup( hwnd );
2755 /*******************************************************************
2756 * GetLastActivePopup (USER32.256)
2758 HWND WINAPI GetLastActivePopup( HWND hwnd )
2760 HWND retval;
2761 WND *wndPtr =WIN_FindWndPtr(hwnd);
2762 if (!wndPtr) return hwnd;
2763 retval = wndPtr->hwndLastActive;
2764 WIN_ReleaseWndPtr(wndPtr);
2765 return retval;
2769 /*******************************************************************
2770 * WIN_BuildWinArray
2772 * Build an array of pointers to the children of a given window.
2773 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2774 * when no windows are found.
2776 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2778 /* Future: this function will lock all windows associated with this array */
2780 WND **list, **ppWnd;
2781 WND *pWnd;
2782 UINT count = 0, skipOwned, skipHidden;
2783 DWORD skipFlags;
2785 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2786 skipOwned = bwaFlags & BWA_SKIPOWNED;
2787 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2788 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2790 /* First count the windows */
2792 if (!wndPtr)
2793 wndPtr = WIN_GetDesktop();
2795 pWnd = WIN_LockWndPtr(wndPtr->child);
2796 while (pWnd)
2798 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2799 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2800 count++;
2801 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2804 if( count )
2806 /* Now build the list of all windows */
2808 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2810 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2812 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2813 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2815 *ppWnd++ = pWnd;
2816 count++;
2819 WIN_ReleaseWndPtr(pWnd);
2820 *ppWnd = NULL;
2822 else count = 0;
2823 } else list = NULL;
2825 if( pTotal ) *pTotal = count;
2826 return list;
2828 /*******************************************************************
2829 * WIN_ReleaseWinArray
2831 void WIN_ReleaseWinArray(WND **wndArray)
2833 /* Future: this function will also unlock all windows associated with wndArray */
2834 HeapFree( GetProcessHeap(), 0, wndArray );
2838 /*******************************************************************
2839 * EnumWindows (USER32.193)
2841 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2843 WND **list, **ppWnd;
2845 /* We have to build a list of all windows first, to avoid */
2846 /* unpleasant side-effects, for instance if the callback */
2847 /* function changes the Z-order of the windows. */
2849 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2851 WIN_ReleaseDesktop();
2852 return FALSE;
2855 /* Now call the callback function for every window */
2857 for (ppWnd = list; *ppWnd; ppWnd++)
2859 LRESULT lpEnumFuncRetval;
2860 int iWndsLocks = 0;
2861 /* Make sure that the window still exists */
2862 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2864 /* To avoid any deadlocks, all the locks on the windows
2865 structures must be suspended before the control
2866 is passed to the application */
2867 iWndsLocks = WIN_SuspendWndsLock();
2868 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2869 WIN_RestoreWndsLock(iWndsLocks);
2871 if (!lpEnumFuncRetval) break;
2873 WIN_ReleaseWinArray(list);
2874 WIN_ReleaseDesktop();
2875 return TRUE;
2879 /**********************************************************************
2880 * EnumTaskWindows16 (USER.225)
2882 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2883 LPARAM lParam )
2885 WND **list, **ppWnd;
2887 /* This function is the same as EnumWindows(), */
2888 /* except for an added check on the window's task. */
2890 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2892 WIN_ReleaseDesktop();
2893 return FALSE;
2896 /* Now call the callback function for every window */
2898 for (ppWnd = list; *ppWnd; ppWnd++)
2900 LRESULT funcRetval;
2901 int iWndsLocks = 0;
2902 /* Make sure that the window still exists */
2903 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2904 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2906 /* To avoid any deadlocks, all the locks on the windows
2907 structures must be suspended before the control
2908 is passed to the application */
2909 iWndsLocks = WIN_SuspendWndsLock();
2910 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2911 WIN_RestoreWndsLock(iWndsLocks);
2913 if (!funcRetval) break;
2915 WIN_ReleaseWinArray(list);
2916 WIN_ReleaseDesktop();
2917 return TRUE;
2921 /**********************************************************************
2922 * EnumThreadWindows (USER32.190)
2924 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2926 TEB *teb = THREAD_IdToTEB(id);
2928 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2932 /**********************************************************************
2933 * WIN_EnumChildWindows
2935 * Helper function for EnumChildWindows().
2937 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2939 WND **childList;
2940 BOOL16 ret = FALSE;
2942 for ( ; *ppWnd; ppWnd++)
2944 int iWndsLocks = 0;
2946 /* Make sure that the window still exists */
2947 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2948 /* Build children list first */
2949 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2951 /* To avoid any deadlocks, all the locks on the windows
2952 structures must be suspended before the control
2953 is passed to the application */
2954 iWndsLocks = WIN_SuspendWndsLock();
2955 ret = func( (*ppWnd)->hwndSelf, lParam );
2956 WIN_RestoreWndsLock(iWndsLocks);
2958 if (childList)
2960 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2961 WIN_ReleaseWinArray(childList);
2963 if (!ret) return FALSE;
2965 return TRUE;
2969 /**********************************************************************
2970 * EnumChildWindows (USER32.178)
2972 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2973 LPARAM lParam )
2975 WND **list, *pParent;
2977 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2978 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2980 WIN_ReleaseWndPtr(pParent);
2981 return FALSE;
2983 WIN_EnumChildWindows( list, func, lParam );
2984 WIN_ReleaseWinArray(list);
2985 WIN_ReleaseWndPtr(pParent);
2986 return TRUE;
2990 /*******************************************************************
2991 * AnyPopup16 (USER.52)
2993 BOOL16 WINAPI AnyPopup16(void)
2995 return AnyPopup();
2999 /*******************************************************************
3000 * AnyPopup (USER32.4)
3002 BOOL WINAPI AnyPopup(void)
3004 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3005 BOOL retvalue;
3007 while (wndPtr)
3009 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3011 retvalue = TRUE;
3012 goto end;
3014 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3016 retvalue = FALSE;
3017 end:
3018 WIN_ReleaseWndPtr(wndPtr);
3019 return retvalue;
3023 /*******************************************************************
3024 * FlashWindow16 (USER.105)
3026 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3028 return FlashWindow( hWnd, bInvert );
3032 /*******************************************************************
3033 * FlashWindow (USER32.202)
3035 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3037 WND *wndPtr = WIN_FindWndPtr(hWnd);
3039 TRACE("%04x\n", hWnd);
3041 if (!wndPtr) return FALSE;
3043 if (wndPtr->dwStyle & WS_MINIMIZE)
3045 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3047 HDC hDC = GetDC(hWnd);
3049 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3050 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3052 ReleaseDC( hWnd, hDC );
3053 wndPtr->flags |= WIN_NCACTIVATED;
3055 else
3057 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3058 RDW_UPDATENOW | RDW_FRAME, 0 );
3059 wndPtr->flags &= ~WIN_NCACTIVATED;
3061 WIN_ReleaseWndPtr(wndPtr);
3062 return TRUE;
3064 else
3066 WPARAM16 wparam;
3067 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3068 else wparam = (hWnd == GetActiveWindow());
3070 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3071 WIN_ReleaseWndPtr(wndPtr);
3072 return wparam;
3077 /*******************************************************************
3078 * SetSysModalWindow16 (USER.188)
3080 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3082 HWND hWndOldModal = hwndSysModal;
3083 hwndSysModal = hWnd;
3084 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3085 return hWndOldModal;
3089 /*******************************************************************
3090 * GetSysModalWindow16 (USER.52)
3092 HWND16 WINAPI GetSysModalWindow16(void)
3094 return hwndSysModal;
3098 /*******************************************************************
3099 * GetWindowContextHelpId (USER32.303)
3101 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3103 DWORD retval;
3104 WND *wnd = WIN_FindWndPtr( hwnd );
3105 if (!wnd) return 0;
3106 retval = wnd->helpContext;
3107 WIN_ReleaseWndPtr(wnd);
3108 return retval;
3112 /*******************************************************************
3113 * SetWindowContextHelpId (USER32.515)
3115 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3117 WND *wnd = WIN_FindWndPtr( hwnd );
3118 if (!wnd) return FALSE;
3119 wnd->helpContext = id;
3120 WIN_ReleaseWndPtr(wnd);
3121 return TRUE;
3125 /*******************************************************************
3126 * DRAG_QueryUpdate
3128 * recursively find a child that contains spDragInfo->pt point
3129 * and send WM_QUERYDROPOBJECT
3131 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3133 BOOL16 wParam, bResult = 0;
3134 POINT pt;
3135 LPDRAGINFO16 ptrDragInfo = (LPDRAGINFO16) PTR_SEG_TO_LIN(spDragInfo);
3136 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3137 RECT tempRect;
3139 if( !ptrQueryWnd || !ptrDragInfo )
3140 goto end;
3142 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3144 GetWindowRect(hQueryWnd,&tempRect);
3146 if( !PtInRect(&tempRect,pt) ||
3147 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3148 goto end;
3150 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3152 tempRect = ptrQueryWnd->rectClient;
3153 if(ptrQueryWnd->dwStyle & WS_CHILD)
3154 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3155 (LPPOINT)&tempRect, 2 );
3157 if (PtInRect( &tempRect, pt))
3159 wParam = 0;
3161 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3163 if( ptrWnd->dwStyle & WS_VISIBLE )
3165 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3166 if (PtInRect( &tempRect, pt )) break;
3170 if(ptrWnd)
3172 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3173 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3174 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3175 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3176 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3178 WIN_ReleaseWndPtr(ptrWnd);
3181 if(bResult)
3182 goto end;
3184 else wParam = 1;
3186 else wParam = 1;
3188 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3190 ptrDragInfo->hScope = hQueryWnd;
3192 bResult = ( bNoSend )
3193 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3194 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3195 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3196 if( !bResult )
3197 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3199 end:
3200 WIN_ReleaseWndPtr(ptrQueryWnd);
3201 return bResult;
3205 /*******************************************************************
3206 * DragDetect (USER.465)
3208 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3210 POINT pt32;
3211 CONV_POINT16TO32( &pt, &pt32 );
3212 return DragDetect( hWnd, pt32 );
3215 /*******************************************************************
3216 * DragDetect (USER32.151)
3218 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3220 MSG msg;
3221 RECT rect;
3223 rect.left = pt.x - wDragWidth;
3224 rect.right = pt.x + wDragWidth;
3226 rect.top = pt.y - wDragHeight;
3227 rect.bottom = pt.y + wDragHeight;
3229 SetCapture(hWnd);
3231 while(1)
3233 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3235 if( msg.message == WM_LBUTTONUP )
3237 ReleaseCapture();
3238 return 0;
3240 if( msg.message == WM_MOUSEMOVE )
3242 POINT tmp;
3243 tmp.x = LOWORD(msg.lParam);
3244 tmp.y = HIWORD(msg.lParam);
3245 if( !PtInRect( &rect, tmp ))
3247 ReleaseCapture();
3248 return 1;
3252 WaitMessage();
3254 return 0;
3257 /******************************************************************************
3258 * DragObject16 (USER.464)
3260 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3261 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3263 MSG msg;
3264 LPDRAGINFO16 lpDragInfo;
3265 SEGPTR spDragInfo;
3266 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3267 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3268 WND *wndPtr = WIN_FindWndPtr(hWnd);
3269 HCURSOR16 hCurrentCursor = 0;
3270 HWND16 hCurrentWnd = 0;
3272 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3273 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3275 if( !lpDragInfo || !spDragInfo )
3277 WIN_ReleaseWndPtr(wndPtr);
3278 return 0L;
3281 hBummer = LoadCursorA(0, IDC_BUMMERA);
3283 if( !hBummer || !wndPtr )
3285 GlobalFree16(hDragInfo);
3286 WIN_ReleaseWndPtr(wndPtr);
3287 return 0L;
3290 if(hCursor)
3292 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3294 GlobalFree16(hDragInfo);
3295 WIN_ReleaseWndPtr(wndPtr);
3296 return 0L;
3299 if( hDragCursor == hCursor ) hDragCursor = 0;
3300 else hCursor = hDragCursor;
3302 hOldCursor = SetCursor(hDragCursor);
3305 lpDragInfo->hWnd = hWnd;
3306 lpDragInfo->hScope = 0;
3307 lpDragInfo->wFlags = wObj;
3308 lpDragInfo->hList = szList; /* near pointer! */
3309 lpDragInfo->hOfStruct = hOfStruct;
3310 lpDragInfo->l = 0L;
3312 SetCapture(hWnd);
3313 ShowCursor( TRUE );
3317 do{ WaitMessage(); }
3318 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3320 *(lpDragInfo+1) = *lpDragInfo;
3322 lpDragInfo->pt.x = msg.pt.x;
3323 lpDragInfo->pt.y = msg.pt.y;
3325 /* update DRAGINFO struct */
3326 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3328 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3329 hCurrentCursor = hCursor;
3330 else
3332 hCurrentCursor = hBummer;
3333 lpDragInfo->hScope = 0;
3335 if( hCurrentCursor )
3336 SetCursor(hCurrentCursor);
3338 /* send WM_DRAGLOOP */
3339 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3340 (LPARAM) spDragInfo );
3341 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3342 if( hCurrentWnd != lpDragInfo->hScope )
3344 if( hCurrentWnd )
3345 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3346 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3347 HIWORD(spDragInfo)) );
3348 hCurrentWnd = lpDragInfo->hScope;
3349 if( hCurrentWnd )
3350 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3352 else
3353 if( hCurrentWnd )
3354 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3356 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3358 ReleaseCapture();
3359 ShowCursor( FALSE );
3361 if( hCursor )
3363 SetCursor( hOldCursor );
3364 if (hDragCursor) DestroyCursor( hDragCursor );
3367 if( hCurrentCursor != hBummer )
3368 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3369 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3370 else
3371 msg.lParam = 0;
3372 GlobalFree16(hDragInfo);
3373 WIN_ReleaseWndPtr(wndPtr);
3375 return (DWORD)(msg.lParam);