Misc fixes for QueryPathOfRegTypeLib, TLB_ReadTypeLib,
[wine.git] / windows / win.c
blob99489b16e17bd24d08eede55c49ec9e859974cf0
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/unicode.h"
13 #include "options.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "controls.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "message.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "task.h"
25 #include "thread.h"
26 #include "winerror.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
31 DECLARE_DEBUG_CHANNEL(msg);
33 /**********************************************************************/
35 WND_DRIVER *WND_Driver = NULL;
37 /* Desktop window */
38 static WND *pWndDesktop = NULL;
40 static HWND hwndSysModal = 0;
42 static WORD wDragWidth = 4;
43 static WORD wDragHeight= 3;
45 /* thread safeness */
46 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
48 /***********************************************************************
49 * WIN_LockWnds
51 * Locks access to all WND structures for thread safeness
53 void WIN_LockWnds( void )
55 _EnterSysLevel( &WIN_SysLevel );
58 /***********************************************************************
59 * WIN_UnlockWnds
61 * Unlocks access to all WND structures
63 void WIN_UnlockWnds( void )
65 _LeaveSysLevel( &WIN_SysLevel );
68 /***********************************************************************
69 * WIN_SuspendWndsLock
71 * Suspend the lock on WND structures.
72 * Returns the number of locks suspended
74 int WIN_SuspendWndsLock( void )
76 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
77 int count = isuspendedLocks;
79 while ( count-- > 0 )
80 _LeaveSysLevel( &WIN_SysLevel );
82 return isuspendedLocks;
85 /***********************************************************************
86 * WIN_RestoreWndsLock
88 * Restore the suspended locks on WND structures
90 void WIN_RestoreWndsLock( int ipreviousLocks )
92 while ( ipreviousLocks-- > 0 )
93 _EnterSysLevel( &WIN_SysLevel );
96 /***********************************************************************
97 * WIN_FindWndPtr
99 * Return a pointer to the WND structure corresponding to a HWND.
101 WND * WIN_FindWndPtr( HWND hwnd )
103 WND * ptr;
105 if (!hwnd || HIWORD(hwnd)) goto error2;
106 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
107 /* Lock all WND structures for thread safeness*/
108 WIN_LockWnds();
109 /*and increment destruction monitoring*/
110 ptr->irefCount++;
112 if (ptr->dwMagic != WND_MAGIC) goto error;
113 if (ptr->hwndSelf != hwnd)
115 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
116 goto error;
118 /* returns a locked pointer */
119 return ptr;
120 error:
121 /* Unlock all WND structures for thread safeness*/
122 WIN_UnlockWnds();
123 /* and decrement destruction monitoring value */
124 ptr->irefCount--;
126 error2:
127 if ( hwnd!=0 )
128 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
129 return NULL;
132 /***********************************************************************
133 * WIN_LockWndPtr
135 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
136 * but by initWndPtr;
137 * Returns the locked initialisation pointer
139 WND *WIN_LockWndPtr(WND *initWndPtr)
141 if(!initWndPtr) return 0;
143 /* Lock all WND structures for thread safeness*/
144 WIN_LockWnds();
145 /*and increment destruction monitoring*/
146 initWndPtr->irefCount++;
148 return initWndPtr;
152 /***********************************************************************
153 * WIN_ReleaseWndPtr
155 * Release the pointer to the WND structure.
157 void WIN_ReleaseWndPtr(WND *wndPtr)
159 if(!wndPtr) return;
161 /*Decrement destruction monitoring value*/
162 wndPtr->irefCount--;
163 /* Check if it's time to release the memory*/
164 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
166 /* Release memory */
167 USER_HEAP_FREE( wndPtr->hwndSelf);
168 wndPtr->hwndSelf = 0;
170 else if(wndPtr->irefCount < 0)
172 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
173 ERR("forgot a Lock on %p somewhere\n",wndPtr);
175 /*unlock all WND structures for thread safeness*/
176 WIN_UnlockWnds();
179 /***********************************************************************
180 * WIN_UpdateWndPtr
182 * Updates the value of oldPtr to newPtr.
184 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
186 WND *tmpWnd = NULL;
188 tmpWnd = WIN_LockWndPtr(newPtr);
189 WIN_ReleaseWndPtr(*oldPtr);
190 *oldPtr = tmpWnd;
194 /***********************************************************************
195 * WIN_DumpWindow
197 * Dump the content of a window structure to stderr.
199 void WIN_DumpWindow( HWND hwnd )
201 WND *ptr;
202 char className[80];
203 int i;
205 if (!(ptr = WIN_FindWndPtr( hwnd )))
207 WARN("%04x is not a window handle\n", hwnd );
208 return;
211 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
212 strcpy( className, "#NULL#" );
214 TRACE("Window %04x (%p):\n", hwnd, ptr );
215 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
216 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
217 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
218 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
219 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
220 ptr->next, ptr->child, ptr->parent, ptr->owner,
221 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
222 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
223 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
224 ptr->text ? debugstr_w(ptr->text) : "",
225 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
226 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
227 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
228 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
230 if (ptr->cbWndExtra)
232 DPRINTF( "extra bytes:" );
233 for (i = 0; i < ptr->cbWndExtra; i++)
234 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
235 DPRINTF( "\n" );
237 DPRINTF( "\n" );
238 WIN_ReleaseWndPtr(ptr);
242 /***********************************************************************
243 * WIN_WalkWindows
245 * Walk the windows tree and print each window on stderr.
247 void WIN_WalkWindows( HWND hwnd, int indent )
249 WND *ptr;
250 char className[80];
252 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
254 if (!ptr)
256 WARN("Invalid window handle %04x\n", hwnd );
257 return;
260 if (!indent) /* first time around */
261 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
262 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
263 " Text");
265 while (ptr)
267 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
269 GetClassNameA( hwnd, className, sizeof(className) );
270 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
271 (DWORD)ptr, ptr->hmemTaskQ, className,
272 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
273 ptr->text ? debugstr_w(ptr->text) : "<null>");
275 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
276 WIN_UpdateWndPtr(&ptr,ptr->next);
282 /***********************************************************************
283 * WIN_UnlinkWindow
285 * Remove a window from the siblings linked list.
287 BOOL WIN_UnlinkWindow( HWND hwnd )
289 WND *wndPtr, **ppWnd;
290 BOOL ret = FALSE;
292 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
293 else if(!wndPtr->parent)
295 WIN_ReleaseWndPtr(wndPtr);
296 return FALSE;
299 ppWnd = &wndPtr->parent->child;
300 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
301 if (*ppWnd)
303 *ppWnd = wndPtr->next;
304 ret = TRUE;
306 WIN_ReleaseWndPtr(wndPtr);
307 return ret;
311 /***********************************************************************
312 * WIN_LinkWindow
314 * Insert a window into the siblings linked list.
315 * The window is inserted after the specified window, which can also
316 * be specified as HWND_TOP or HWND_BOTTOM.
318 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
320 WND *wndPtr, **ppWnd;
322 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
323 else if(!wndPtr->parent)
325 WIN_ReleaseWndPtr(wndPtr);
326 return FALSE;
328 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
330 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
331 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
332 while (*ppWnd) ppWnd = &(*ppWnd)->next;
334 else /* Normal case */
336 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
337 if (!afterPtr)
339 WIN_ReleaseWndPtr(wndPtr);
340 return FALSE;
342 ppWnd = &afterPtr->next;
343 WIN_ReleaseWndPtr(afterPtr);
345 wndPtr->next = *ppWnd;
346 *ppWnd = wndPtr;
347 WIN_ReleaseWndPtr(wndPtr);
348 return TRUE;
352 /***********************************************************************
353 * WIN_FindWinToRepaint
355 * Find a window that needs repaint.
357 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
359 HWND hwndRet;
360 WND *pWnd;
362 /* Note: the desktop window never gets WM_PAINT messages
363 * The real reason why is because Windows DesktopWndProc
364 * does ValidateRgn inside WM_ERASEBKGND handler.
367 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
369 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
371 if (!(pWnd->dwStyle & WS_VISIBLE))
373 TRACE("skipping window %04x\n",
374 pWnd->hwndSelf );
376 else if ((pWnd->hmemTaskQ == hQueue) &&
377 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
378 break;
380 else if (pWnd->child )
381 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
383 WIN_ReleaseWndPtr(pWnd);
384 return hwndRet;
389 if(!pWnd)
391 return 0;
394 hwndRet = pWnd->hwndSelf;
396 /* look among siblings if we got a transparent window */
397 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
398 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
400 WIN_UpdateWndPtr(&pWnd,pWnd->next);
402 if (pWnd)
404 hwndRet = pWnd->hwndSelf;
405 WIN_ReleaseWndPtr(pWnd);
407 TRACE("found %04x\n",hwndRet);
408 return hwndRet;
412 /***********************************************************************
413 * WIN_DestroyWindow
415 * Destroy storage associated to a window. "Internals" p.358
416 * returns a locked wndPtr->next
418 static WND* WIN_DestroyWindow( WND* wndPtr )
420 HWND hwnd = wndPtr->hwndSelf;
421 WND *pWnd;
423 TRACE("%04x\n", wndPtr->hwndSelf );
425 /* free child windows */
426 WIN_LockWndPtr(wndPtr->child);
427 while ((pWnd = wndPtr->child))
429 wndPtr->child = WIN_DestroyWindow( pWnd );
430 WIN_ReleaseWndPtr(pWnd);
434 * Clear the update region to make sure no WM_PAINT messages will be
435 * generated for this window while processing the WM_NCDESTROY.
437 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
439 if (wndPtr->hrgnUpdate > 1)
440 DeleteObject( wndPtr->hrgnUpdate );
442 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
444 wndPtr->hrgnUpdate = 0;
448 * Send the WM_NCDESTROY to the window being destroyed.
450 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
452 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
454 WINPOS_CheckInternalPos( wndPtr );
455 if( hwnd == GetCapture()) ReleaseCapture();
457 /* free resources associated with the window */
459 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
460 PROPERTY_RemoveWindowProps( wndPtr );
462 wndPtr->dwMagic = 0; /* Mark it as invalid */
464 /* toss stale messages from the queue */
466 if( wndPtr->hmemTaskQ )
468 BOOL bPostQuit = FALSE;
469 WPARAM wQuitParam = 0;
470 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
471 QMSG *qmsg;
473 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
475 if( qmsg->msg.message == WM_QUIT )
477 bPostQuit = TRUE;
478 wQuitParam = qmsg->msg.wParam;
480 QUEUE_RemoveMsg(msgQ, qmsg);
483 QUEUE_Unlock(msgQ);
485 /* repost WM_QUIT to make sure this app exits its message loop */
486 if( bPostQuit ) PostQuitMessage(wQuitParam);
487 wndPtr->hmemTaskQ = 0;
490 if (!(wndPtr->dwStyle & WS_CHILD))
491 if (wndPtr->wIDmenu)
493 DestroyMenu( wndPtr->wIDmenu );
494 wndPtr->wIDmenu = 0;
496 if (wndPtr->hSysMenu)
498 DestroyMenu( wndPtr->hSysMenu );
499 wndPtr->hSysMenu = 0;
501 wndPtr->pDriver->pDestroyWindow( wndPtr );
502 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
503 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
504 CLASS_RemoveWindow( wndPtr->class );
505 wndPtr->class = NULL;
507 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
509 wndPtr->pDriver->pFinalize(wndPtr);
511 return pWnd;
514 /***********************************************************************
515 * WIN_ResetQueueWindows
517 * Reset the queue of all the children of a given window.
518 * Return TRUE if something was done.
520 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
522 BOOL ret = FALSE;
524 if (hNew) /* Set a new queue */
526 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
528 if (wnd->hmemTaskQ == hQueue)
530 wnd->hmemTaskQ = hNew;
531 ret = TRUE;
533 if (wnd->child)
535 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
539 else /* Queue is being destroyed */
541 while (wnd->child)
543 WND *tmp = WIN_LockWndPtr(wnd->child);
544 WND *tmp2;
545 ret = FALSE;
546 while (tmp)
548 if (tmp->hmemTaskQ == hQueue)
550 DestroyWindow( tmp->hwndSelf );
551 ret = TRUE;
552 break;
554 tmp2 = WIN_LockWndPtr(tmp->child);
555 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
556 ret = TRUE;
557 else
559 WIN_UpdateWndPtr(&tmp,tmp->next);
561 WIN_ReleaseWndPtr(tmp2);
563 WIN_ReleaseWndPtr(tmp);
564 if (!ret) break;
567 return ret;
570 /***********************************************************************
571 * WIN_CreateDesktopWindow
573 * Create the desktop window.
575 BOOL WIN_CreateDesktopWindow(void)
577 struct tagCLASS *class;
578 HWND hwndDesktop;
579 INT wndExtra;
580 DWORD clsStyle;
581 WNDPROC winproc;
582 DCE *dce;
584 TRACE("Creating desktop window\n");
587 if (!WINPOS_CreateInternalPosAtom() ||
588 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
589 &wndExtra, &winproc, &clsStyle, &dce )))
590 return FALSE;
592 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
593 if (!hwndDesktop) return FALSE;
594 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
596 pWndDesktop->pDriver = WND_Driver;
597 pWndDesktop->pDriver->pInitialize(pWndDesktop);
599 pWndDesktop->next = NULL;
600 pWndDesktop->child = NULL;
601 pWndDesktop->parent = NULL;
602 pWndDesktop->owner = NULL;
603 pWndDesktop->class = class;
604 pWndDesktop->dwMagic = WND_MAGIC;
605 pWndDesktop->hwndSelf = hwndDesktop;
606 pWndDesktop->hInstance = 0;
607 pWndDesktop->rectWindow.left = 0;
608 pWndDesktop->rectWindow.top = 0;
609 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
610 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
611 pWndDesktop->rectClient = pWndDesktop->rectWindow;
612 pWndDesktop->text = NULL;
613 pWndDesktop->hmemTaskQ = GetFastQueue16();
614 pWndDesktop->hrgnUpdate = 0;
615 pWndDesktop->hwndLastActive = hwndDesktop;
616 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
617 WS_CLIPSIBLINGS;
618 pWndDesktop->dwExStyle = 0;
619 pWndDesktop->clsStyle = clsStyle;
620 pWndDesktop->dce = NULL;
621 pWndDesktop->pVScroll = NULL;
622 pWndDesktop->pHScroll = NULL;
623 pWndDesktop->pProp = NULL;
624 pWndDesktop->wIDmenu = 0;
625 pWndDesktop->helpContext = 0;
626 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
627 pWndDesktop->hSysMenu = 0;
628 pWndDesktop->userdata = 0;
629 pWndDesktop->winproc = winproc;
630 pWndDesktop->cbWndExtra = wndExtra;
631 pWndDesktop->irefCount = 0;
633 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop)) return FALSE;
635 SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
636 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
637 return TRUE;
641 /***********************************************************************
642 * WIN_FixCoordinates
644 * Fix the coordinates - Helper for WIN_CreateWindowEx.
645 * returns default show mode in sw.
646 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
648 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
650 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
651 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
653 if (cs->style & (WS_CHILD | WS_POPUP))
655 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
656 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
658 else /* overlapped window */
660 STARTUPINFOA info;
662 GetStartupInfoA( &info );
664 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
666 /* Never believe Microsoft's documentation... CreateWindowEx doc says
667 * that if an overlapped window is created with WS_VISIBLE style bit
668 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
669 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
670 * reveals that
672 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
673 * 2) it does not ignore the y parameter as the docs claim; instead, it
674 * uses it as second parameter to ShowWindow() unless y is either
675 * CW_USEDEFAULT or CW_USEDEFAULT16.
677 * The fact that we didn't do 2) caused bogus windows pop up when wine
678 * was running apps that were using this obscure feature. Example -
679 * calc.exe that comes with Win98 (only Win98, it's different from
680 * the one that comes with Win95 and NT)
682 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
683 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
684 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
687 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
689 if (info.dwFlags & STARTF_USESIZE)
691 cs->cx = info.dwXSize;
692 cs->cy = info.dwYSize;
694 else /* if no other hint from the app, pick 3/4 of the screen real estate */
696 RECT r;
697 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
698 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
699 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
706 /***********************************************************************
707 * WIN_CreateWindowEx
709 * Implementation of CreateWindowEx().
711 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
712 WINDOWPROCTYPE type )
714 INT sw = SW_SHOW;
715 struct tagCLASS *classPtr;
716 WND *wndPtr;
717 HWND retvalue;
718 HWND16 hwnd, hwndLinkAfter;
719 POINT maxSize, maxPos, minTrack, maxTrack;
720 INT wndExtra;
721 DWORD clsStyle;
722 WNDPROC winproc;
723 DCE *dce;
724 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
726 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
727 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
728 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
729 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
730 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
732 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
733 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
735 /* Find the parent window */
737 if (cs->hwndParent)
739 /* Make sure parent is valid */
740 if (!IsWindow( cs->hwndParent ))
742 WARN("Bad parent %04x\n", cs->hwndParent );
743 return 0;
745 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
746 WARN("No parent for child window\n" );
747 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
750 /* Find the window class */
751 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
752 &wndExtra, &winproc, &clsStyle, &dce )))
754 WARN("Bad class '%s'\n", cs->lpszClass );
755 return 0;
758 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
760 /* Create the window structure */
762 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
764 TRACE("out of memory\n" );
765 return 0;
768 /* Fill the window structure */
770 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
771 wndPtr->next = NULL;
772 wndPtr->child = NULL;
774 if ((cs->style & WS_CHILD) && cs->hwndParent)
776 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
777 wndPtr->owner = NULL;
778 WIN_ReleaseWndPtr(wndPtr->parent);
780 else
782 wndPtr->parent = pWndDesktop;
783 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
784 wndPtr->owner = NULL;
785 else
787 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
788 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
789 WIN_ReleaseWndPtr(wndPtr->owner);
790 WIN_ReleaseWndPtr(tmpWnd);
795 wndPtr->pDriver = wndPtr->parent->pDriver;
796 wndPtr->pDriver->pInitialize(wndPtr);
798 wndPtr->class = classPtr;
799 wndPtr->winproc = winproc;
800 wndPtr->dwMagic = WND_MAGIC;
801 wndPtr->hwndSelf = hwnd;
802 wndPtr->hInstance = cs->hInstance;
803 wndPtr->text = NULL;
804 wndPtr->hmemTaskQ = GetFastQueue16();
805 wndPtr->hrgnUpdate = 0;
806 wndPtr->hrgnWnd = 0;
807 wndPtr->hwndLastActive = hwnd;
808 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
809 wndPtr->dwExStyle = cs->dwExStyle;
810 wndPtr->clsStyle = clsStyle;
811 wndPtr->wIDmenu = 0;
812 wndPtr->helpContext = 0;
813 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
814 wndPtr->pVScroll = NULL;
815 wndPtr->pHScroll = NULL;
816 wndPtr->pProp = NULL;
817 wndPtr->userdata = 0;
818 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
819 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
820 wndPtr->cbWndExtra = wndExtra;
821 wndPtr->irefCount = 1;
823 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
825 /* Call the WH_CBT hook */
827 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
828 ? HWND_BOTTOM : HWND_TOP;
830 if (HOOK_IsHooked( WH_CBT ))
832 CBT_CREATEWNDA cbtc;
833 LRESULT ret;
835 cbtc.lpcs = cs;
836 cbtc.hwndInsertAfter = hwndLinkAfter;
837 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
838 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
839 if (ret)
841 TRACE("CBT-hook returned 0\n");
842 wndPtr->pDriver->pFinalize(wndPtr);
843 USER_HEAP_FREE( hwnd );
844 CLASS_RemoveWindow( classPtr );
845 retvalue = 0;
846 goto end;
850 /* Correct the window style */
852 if (!(cs->style & WS_CHILD))
854 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
855 if (!(cs->style & WS_POPUP))
857 wndPtr->dwStyle |= WS_CAPTION;
858 wndPtr->flags |= WIN_NEED_SIZE;
862 /* Get class or window DC if needed */
864 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
865 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
866 else wndPtr->dce = NULL;
868 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
870 wndPtr->rectWindow.left = cs->x;
871 wndPtr->rectWindow.top = cs->y;
872 wndPtr->rectWindow.right = cs->x + cs->cx;
873 wndPtr->rectWindow.bottom = cs->y + cs->cy;
874 wndPtr->rectClient = wndPtr->rectWindow;
876 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
878 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
880 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
881 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
882 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
883 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
884 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
887 if (cs->cx < 0) cs->cx = 0;
888 if (cs->cy < 0) cs->cy = 0;
890 wndPtr->rectWindow.left = cs->x;
891 wndPtr->rectWindow.top = cs->y;
892 wndPtr->rectWindow.right = cs->x + cs->cx;
893 wndPtr->rectWindow.bottom = cs->y + cs->cy;
894 wndPtr->rectClient = wndPtr->rectWindow;
896 if(!wndPtr->pDriver->pCreateWindow(wndPtr, cs, type == WIN_PROC_32W))
898 retvalue = FALSE;
899 goto end;
902 /* Set the window menu */
904 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
906 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
907 else
909 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
910 if (menuName)
912 if (HIWORD(cs->hInstance))
913 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
914 else
915 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
917 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
921 else wndPtr->wIDmenu = (UINT)cs->hMenu;
923 /* Send the WM_CREATE message
924 * Perhaps we shouldn't allow width/height changes as well.
925 * See p327 in "Internals".
928 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
930 localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
931 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
933 /* Insert the window in the linked list */
935 WIN_LinkWindow( hwnd, hwndLinkAfter );
937 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
938 NULL, NULL, 0, &wndPtr->rectClient );
939 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
940 maxPos.y - wndPtr->rectWindow.top);
941 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
943 /* Send the size messages */
945 if (!(wndPtr->flags & WIN_NEED_SIZE))
947 /* send it anyway */
948 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
949 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
950 WARN("sending bogus WM_SIZE message 0x%08lx\n",
951 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
952 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
953 (*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
954 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
955 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
956 (*localSend32)( hwnd, WM_MOVE, 0,
957 MAKELONG( wndPtr->rectClient.left,
958 wndPtr->rectClient.top ) );
961 /* Show the window, maximizing or minimizing if needed */
963 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
965 RECT16 newPos;
966 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
967 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
968 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
969 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
970 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
971 : SWP_NOZORDER | SWP_FRAMECHANGED;
972 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
973 newPos.right, newPos.bottom, swFlag );
976 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
978 /* Notify the parent window only */
980 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
981 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
982 if( !IsWindow(hwnd) )
984 retvalue = 0;
985 goto end;
989 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
991 /* Call WH_SHELL hook */
993 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
994 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
996 TRACE("created window %04x\n", hwnd);
997 retvalue = hwnd;
998 goto end;
1000 WIN_UnlinkWindow( hwnd );
1003 /* Abort window creation */
1005 WARN("aborted by WM_xxCREATE!\n");
1006 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1007 CLASS_RemoveWindow( classPtr );
1008 retvalue = 0;
1009 end:
1010 WIN_ReleaseWndPtr(wndPtr);
1012 return retvalue;
1016 /***********************************************************************
1017 * CreateWindow16 (USER.41)
1019 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1020 DWORD style, INT16 x, INT16 y, INT16 width,
1021 INT16 height, HWND16 parent, HMENU16 menu,
1022 HINSTANCE16 instance, LPVOID data )
1024 return CreateWindowEx16( 0, className, windowName, style,
1025 x, y, width, height, parent, menu, instance, data );
1029 /***********************************************************************
1030 * CreateWindowEx16 (USER.452)
1032 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1033 LPCSTR windowName, DWORD style, INT16 x,
1034 INT16 y, INT16 width, INT16 height,
1035 HWND16 parent, HMENU16 menu,
1036 HINSTANCE16 instance, LPVOID data )
1038 ATOM classAtom;
1039 CREATESTRUCTA cs;
1040 char buffer[256];
1042 /* Find the class atom */
1044 if (HIWORD(className))
1046 if (!(classAtom = GlobalFindAtomA( className )))
1048 ERR( "bad class name %s\n", debugres_a(className) );
1049 return 0;
1052 else
1054 classAtom = LOWORD(className);
1055 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1057 ERR( "bad atom %x\n", classAtom);
1058 return 0;
1060 className = buffer;
1063 /* Fix the coordinates */
1065 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1066 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1067 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1068 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1070 /* Create the window */
1072 cs.lpCreateParams = data;
1073 cs.hInstance = (HINSTANCE)instance;
1074 cs.hMenu = (HMENU)menu;
1075 cs.hwndParent = (HWND)parent;
1076 cs.style = style;
1077 cs.lpszName = windowName;
1078 cs.lpszClass = className;
1079 cs.dwExStyle = exStyle;
1081 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1085 /***********************************************************************
1086 * CreateWindowExA (USER32.83)
1088 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1089 LPCSTR windowName, DWORD style, INT x,
1090 INT y, INT width, INT height,
1091 HWND parent, HMENU menu,
1092 HINSTANCE instance, LPVOID data )
1094 ATOM classAtom;
1095 CREATESTRUCTA cs;
1096 char buffer[256];
1098 if(!instance)
1099 instance=GetModuleHandleA(NULL);
1101 if(exStyle & WS_EX_MDICHILD)
1102 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1104 /* Find the class atom */
1106 if (HIWORD(className))
1108 if (!(classAtom = GlobalFindAtomA( className )))
1110 ERR( "bad class name %s\n", debugres_a(className) );
1111 return 0;
1114 else
1116 classAtom = LOWORD(className);
1117 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1119 ERR( "bad atom %x\n", classAtom);
1120 return 0;
1122 className = buffer;
1125 /* Create the window */
1127 cs.lpCreateParams = data;
1128 cs.hInstance = instance;
1129 cs.hMenu = menu;
1130 cs.hwndParent = parent;
1131 cs.x = x;
1132 cs.y = y;
1133 cs.cx = width;
1134 cs.cy = height;
1135 cs.style = style;
1136 cs.lpszName = windowName;
1137 cs.lpszClass = className;
1138 cs.dwExStyle = exStyle;
1140 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1144 /***********************************************************************
1145 * CreateWindowExW (USER32.84)
1147 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1148 LPCWSTR windowName, DWORD style, INT x,
1149 INT y, INT width, INT height,
1150 HWND parent, HMENU menu,
1151 HINSTANCE instance, LPVOID data )
1153 ATOM classAtom;
1154 CREATESTRUCTW cs;
1155 WCHAR buffer[256];
1157 if(!instance)
1158 instance=GetModuleHandleA(NULL);
1160 if(exStyle & WS_EX_MDICHILD)
1161 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1163 /* Find the class atom */
1165 if (HIWORD(className))
1167 if (!(classAtom = GlobalFindAtomW( className )))
1169 ERR( "bad class name %s\n", debugres_w(className) );
1170 return 0;
1173 else
1175 classAtom = LOWORD(className);
1176 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1178 ERR( "bad atom %x\n", classAtom);
1179 return 0;
1181 className = buffer;
1184 /* Create the window */
1186 cs.lpCreateParams = data;
1187 cs.hInstance = instance;
1188 cs.hMenu = menu;
1189 cs.hwndParent = parent;
1190 cs.x = x;
1191 cs.y = y;
1192 cs.cx = width;
1193 cs.cy = height;
1194 cs.style = style;
1195 cs.lpszName = windowName;
1196 cs.lpszClass = className;
1197 cs.dwExStyle = exStyle;
1199 /* Note: we rely on the fact that CREATESTRUCTA and */
1200 /* CREATESTRUCTW have the same layout. */
1201 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1204 /***********************************************************************
1205 * WIN_SendDestroyMsg
1207 static void WIN_SendDestroyMsg( WND* pWnd )
1209 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1210 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1213 * Send the WM_DESTROY to the window.
1215 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1218 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1219 * make sure that the window still exists when we come back.
1221 if (IsWindow(pWnd->hwndSelf))
1223 HWND* pWndArray = NULL;
1224 WND* pChild = NULL;
1225 int nKidCount = 0;
1228 * Now, if the window has kids, we have to send WM_DESTROY messages
1229 * recursively to it's kids. It seems that those calls can also
1230 * trigger re-entrant calls to DestroyWindow for the kids so we must
1231 * protect against corruption of the list of siblings. We first build
1232 * a list of HWNDs representing all the kids.
1234 pChild = WIN_LockWndPtr(pWnd->child);
1235 while( pChild )
1237 nKidCount++;
1238 WIN_UpdateWndPtr(&pChild,pChild->next);
1242 * If there are no kids, we're done.
1244 if (nKidCount==0)
1245 return;
1247 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1250 * Sanity check
1252 if (pWndArray==NULL)
1253 return;
1256 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1257 * call, our linked list of siblings should be safe.
1259 nKidCount = 0;
1260 pChild = WIN_LockWndPtr(pWnd->child);
1261 while( pChild )
1263 pWndArray[nKidCount] = pChild->hwndSelf;
1264 nKidCount++;
1265 WIN_UpdateWndPtr(&pChild,pChild->next);
1269 * Now that we have a list, go through that list again and send the destroy
1270 * message to those windows. We are using the HWND to retrieve the
1271 * WND pointer so we are effectively checking that all the kid windows are
1272 * still valid before sending the message.
1274 while (nKidCount>0)
1276 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1278 if (pChild!=NULL)
1280 WIN_SendDestroyMsg( pChild );
1281 WIN_ReleaseWndPtr(pChild);
1286 * Cleanup
1288 HeapFree(GetProcessHeap(), 0, pWndArray);
1290 else
1291 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1295 /***********************************************************************
1296 * DestroyWindow16 (USER.53)
1298 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1300 return DestroyWindow(hwnd);
1304 /***********************************************************************
1305 * DestroyWindow (USER32.135)
1307 BOOL WINAPI DestroyWindow( HWND hwnd )
1309 WND * wndPtr;
1310 BOOL retvalue;
1311 HWND h;
1312 BOOL bFocusSet = FALSE;
1314 TRACE("(%04x)\n", hwnd);
1316 /* Initialization */
1318 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1319 if (wndPtr == pWndDesktop)
1321 retvalue = FALSE; /* Can't destroy desktop */
1322 goto end;
1325 /* Look whether the focus is within the tree of windows we will
1326 * be destroying.
1328 h = GetFocus16();
1329 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1331 if (h == hwnd)
1333 SetFocus(GetWindowLongA(hwnd,GWL_HWNDPARENT));
1334 bFocusSet = TRUE;
1335 break;
1337 h = GetWindowLongA(h,GWL_HWNDPARENT);
1339 /* If the focus is on the window we will destroy and it has no parent,
1340 * set the focus to 0.
1342 if (! bFocusSet && (h == hwnd))
1344 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1345 SetFocus(0);
1348 /* Call hooks */
1350 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1352 retvalue = FALSE;
1353 goto end;
1356 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1358 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1359 /* FIXME: clean up palette - see "Internals" p.352 */
1362 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1363 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1365 /* Notify the parent window only */
1366 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1367 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1368 if( !IsWindow(hwnd) )
1370 retvalue = TRUE;
1371 goto end;
1375 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1377 /* Hide the window */
1379 if (wndPtr->dwStyle & WS_VISIBLE)
1381 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1382 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1383 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1384 if (!IsWindow(hwnd))
1386 retvalue = TRUE;
1387 goto end;
1391 /* Recursively destroy owned windows */
1393 if( !(wndPtr->dwStyle & WS_CHILD) )
1395 /* make sure top menu popup doesn't get destroyed */
1396 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1398 for (;;)
1400 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1401 while (siblingPtr)
1403 if (siblingPtr->owner == wndPtr)
1405 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1406 break;
1407 else
1408 siblingPtr->owner = NULL;
1410 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1412 if (siblingPtr)
1414 DestroyWindow( siblingPtr->hwndSelf );
1415 WIN_ReleaseWndPtr(siblingPtr);
1417 else break;
1420 if( !Options.managed || EVENT_CheckFocus() )
1421 WINPOS_ActivateOtherWindow(wndPtr);
1423 if( wndPtr->owner &&
1424 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1425 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1428 /* Send destroy messages */
1430 WIN_SendDestroyMsg( wndPtr );
1431 if (!IsWindow(hwnd))
1433 retvalue = TRUE;
1434 goto end;
1437 /* Unlink now so we won't bother with the children later on */
1439 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1441 /* Destroy the window storage */
1443 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1444 retvalue = TRUE;
1445 end:
1446 WIN_ReleaseWndPtr(wndPtr);
1447 return retvalue;
1451 /***********************************************************************
1452 * CloseWindow16 (USER.43)
1454 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1456 return CloseWindow( hwnd );
1460 /***********************************************************************
1461 * CloseWindow (USER32.56)
1463 BOOL WINAPI CloseWindow( HWND hwnd )
1465 WND * wndPtr = WIN_FindWndPtr( hwnd );
1466 BOOL retvalue;
1468 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1470 retvalue = FALSE;
1471 goto end;
1473 ShowWindow( hwnd, SW_MINIMIZE );
1474 retvalue = TRUE;
1475 end:
1476 WIN_ReleaseWndPtr(wndPtr);
1477 return retvalue;
1482 /***********************************************************************
1483 * OpenIcon16 (USER.44)
1485 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1487 return OpenIcon( hwnd );
1491 /***********************************************************************
1492 * OpenIcon (USER32.410)
1494 BOOL WINAPI OpenIcon( HWND hwnd )
1496 if (!IsIconic( hwnd )) return FALSE;
1497 ShowWindow( hwnd, SW_SHOWNORMAL );
1498 return TRUE;
1502 /***********************************************************************
1503 * WIN_FindWindow
1505 * Implementation of FindWindow() and FindWindowEx().
1507 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1508 LPCWSTR title )
1510 WND *pWnd;
1511 HWND retvalue;
1513 if (child)
1515 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1516 if (parent)
1518 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1520 retvalue = 0;
1521 goto end;
1524 else if (pWnd->parent != pWndDesktop)
1526 retvalue = 0;
1527 goto end;
1529 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1531 else
1533 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1535 retvalue = 0;
1536 goto end;
1538 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1540 if (!pWnd)
1542 retvalue = 0;
1543 goto end;
1546 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1548 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1549 continue; /* Not the right class */
1551 /* Now check the title */
1553 if (!title)
1555 retvalue = pWnd->hwndSelf;
1556 goto end;
1558 if (pWnd->text && !strcmpW( pWnd->text, title ))
1560 retvalue = pWnd->hwndSelf;
1561 goto end;
1564 retvalue = 0;
1565 end:
1566 WIN_ReleaseWndPtr(pWnd);
1567 return retvalue;
1572 /***********************************************************************
1573 * FindWindow16 (USER.50)
1575 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1577 return FindWindowA( className, title );
1581 /***********************************************************************
1582 * FindWindowEx16 (USER.427)
1584 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1586 return FindWindowExA( parent, child, className, title );
1590 /***********************************************************************
1591 * FindWindowA (USER32.198)
1593 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1595 HWND ret = FindWindowExA( 0, 0, className, title );
1596 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1597 return ret;
1601 /***********************************************************************
1602 * FindWindowExA (USER32.199)
1604 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1605 LPCSTR className, LPCSTR title )
1607 ATOM atom = 0;
1608 LPWSTR buffer;
1609 HWND hwnd;
1611 if (className)
1613 /* If the atom doesn't exist, then no class */
1614 /* with this name exists either. */
1615 if (!(atom = GlobalFindAtomA( className )))
1617 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1618 return 0;
1622 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1623 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1624 HeapFree( GetProcessHeap(), 0, buffer );
1625 return hwnd;
1629 /***********************************************************************
1630 * FindWindowExW (USER32.200)
1632 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1633 LPCWSTR className, LPCWSTR title )
1635 ATOM atom = 0;
1637 if (className)
1639 /* If the atom doesn't exist, then no class */
1640 /* with this name exists either. */
1641 if (!(atom = GlobalFindAtomW( className )))
1643 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1644 return 0;
1647 return WIN_FindWindow( parent, child, atom, title );
1651 /***********************************************************************
1652 * FindWindowW (USER32.201)
1654 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1656 return FindWindowExW( 0, 0, className, title );
1660 /**********************************************************************
1661 * WIN_GetDesktop
1662 * returns a locked pointer
1664 WND *WIN_GetDesktop(void)
1666 return WIN_LockWndPtr(pWndDesktop);
1668 /**********************************************************************
1669 * WIN_ReleaseDesktop
1670 * unlock the desktop pointer
1672 void WIN_ReleaseDesktop(void)
1674 WIN_ReleaseWndPtr(pWndDesktop);
1678 /**********************************************************************
1679 * GetDesktopWindow16 (USER.286)
1681 HWND16 WINAPI GetDesktopWindow16(void)
1683 return (HWND16)pWndDesktop->hwndSelf;
1687 /**********************************************************************
1688 * GetDesktopWindow (USER32.232)
1690 HWND WINAPI GetDesktopWindow(void)
1692 if (pWndDesktop) return pWndDesktop->hwndSelf;
1693 ERR( "You need the -desktop option when running with native USER\n" );
1694 ExitProcess(1);
1695 return 0;
1699 /**********************************************************************
1700 * GetDesktopHwnd (USER.278)
1702 * Exactly the same thing as GetDesktopWindow(), but not documented.
1703 * Don't ask me why...
1705 HWND16 WINAPI GetDesktopHwnd16(void)
1707 return (HWND16)pWndDesktop->hwndSelf;
1711 /*******************************************************************
1712 * EnableWindow16 (USER.34)
1714 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1716 return EnableWindow( hwnd, enable );
1720 /*******************************************************************
1721 * EnableWindow (USER32.172)
1723 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1725 WND *wndPtr;
1726 BOOL retvalue;
1728 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1730 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1731 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1733 /* Enable window */
1734 wndPtr->dwStyle &= ~WS_DISABLED;
1736 if( wndPtr->flags & WIN_NATIVE )
1737 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1739 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1740 retvalue = TRUE;
1741 goto end;
1743 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1745 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1747 /* Disable window */
1748 wndPtr->dwStyle |= WS_DISABLED;
1750 if( wndPtr->flags & WIN_NATIVE )
1751 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1753 if (hwnd == GetFocus())
1755 SetFocus( 0 ); /* A disabled window can't have the focus */
1757 if (hwnd == GetCapture())
1759 ReleaseCapture(); /* A disabled window can't capture the mouse */
1761 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1762 retvalue = FALSE;
1763 goto end;
1765 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1766 end:
1767 WIN_ReleaseWndPtr(wndPtr);
1768 return retvalue;
1772 /***********************************************************************
1773 * IsWindowEnabled16 (USER.35)
1775 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1777 return IsWindowEnabled(hWnd);
1781 /***********************************************************************
1782 * IsWindowEnabled (USER32.349)
1784 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1786 WND * wndPtr;
1787 BOOL retvalue;
1789 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1790 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1791 WIN_ReleaseWndPtr(wndPtr);
1792 return retvalue;
1797 /***********************************************************************
1798 * IsWindowUnicode (USER32.350)
1800 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1802 WND * wndPtr;
1803 BOOL retvalue;
1805 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1806 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1807 WIN_ReleaseWndPtr(wndPtr);
1808 return retvalue;
1812 /**********************************************************************
1813 * GetWindowWord16 (USER.133)
1815 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1817 return GetWindowWord( hwnd, offset );
1821 /**********************************************************************
1822 * GetWindowWord (USER32.314)
1824 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1826 WORD retvalue;
1827 WND * wndPtr = WIN_FindWndPtr( hwnd );
1828 if (!wndPtr) return 0;
1829 if (offset >= 0)
1831 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1833 WARN("Invalid offset %d\n", offset );
1834 retvalue = 0;
1835 goto end;
1837 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1838 goto end;
1840 switch(offset)
1842 case GWW_ID:
1843 if (HIWORD(wndPtr->wIDmenu))
1844 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1845 wndPtr->wIDmenu);
1846 retvalue = (WORD)wndPtr->wIDmenu;
1847 goto end;
1848 case GWW_HWNDPARENT:
1849 retvalue = GetParent(hwnd);
1850 goto end;
1851 case GWW_HINSTANCE:
1852 if (HIWORD(wndPtr->hInstance))
1853 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1854 wndPtr->hInstance);
1855 retvalue = (WORD)wndPtr->hInstance;
1856 goto end;
1857 default:
1858 WARN("Invalid offset %d\n", offset );
1859 retvalue = 0;
1860 goto end;
1862 end:
1863 WIN_ReleaseWndPtr(wndPtr);
1864 return retvalue;
1867 /**********************************************************************
1868 * SetWindowWord16 (USER.134)
1870 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1872 return SetWindowWord( hwnd, offset, newval );
1876 /**********************************************************************
1877 * SetWindowWord (USER32.524)
1879 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1881 WORD *ptr, retval;
1882 WND * wndPtr = WIN_FindWndPtr( hwnd );
1883 if (!wndPtr) return 0;
1884 if (offset >= 0)
1886 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1888 WARN("Invalid offset %d\n", offset );
1889 retval = 0;
1890 goto end;
1892 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1894 else switch(offset)
1896 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1897 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1898 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1899 goto end;
1900 default:
1901 WARN("Invalid offset %d\n", offset );
1902 retval = 0;
1903 goto end;
1905 retval = *ptr;
1906 *ptr = newval;
1907 end:
1908 WIN_ReleaseWndPtr(wndPtr);
1909 return retval;
1913 /**********************************************************************
1914 * WIN_GetWindowLong
1916 * Helper function for GetWindowLong().
1918 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1920 LONG retvalue;
1921 WND * wndPtr = WIN_FindWndPtr( hwnd );
1922 if (!wndPtr) return 0;
1923 if (offset >= 0)
1925 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1927 WARN("Invalid offset %d\n", offset );
1928 retvalue = 0;
1929 goto end;
1931 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1932 /* Special case for dialog window procedure */
1933 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1935 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1936 goto end;
1938 goto end;
1940 switch(offset)
1942 case GWL_USERDATA: retvalue = wndPtr->userdata;
1943 goto end;
1944 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1945 goto end;
1946 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1947 goto end;
1948 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1949 goto end;
1950 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1951 type );
1952 goto end;
1953 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1954 goto end;
1955 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1956 goto end;
1957 default:
1958 WARN("Unknown offset %d\n", offset );
1960 retvalue = 0;
1961 end:
1962 WIN_ReleaseWndPtr(wndPtr);
1963 return retvalue;
1967 /**********************************************************************
1968 * WIN_SetWindowLong
1970 * Helper function for SetWindowLong().
1972 * 0 is the failure code. However, in the case of failure SetLastError
1973 * must be set to distinguish between a 0 return value and a failure.
1975 * FIXME: The error values for SetLastError may not be right. Can
1976 * someone check with the real thing?
1978 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1979 WINDOWPROCTYPE type )
1981 LONG *ptr, retval;
1982 WND * wndPtr = WIN_FindWndPtr( hwnd );
1983 STYLESTRUCT style;
1985 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1987 if (!wndPtr)
1989 /* Is this the right error? */
1990 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1991 return 0;
1994 if (offset >= 0)
1996 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1998 WARN("Invalid offset %d\n", offset );
2000 /* Is this the right error? */
2001 SetLastError( ERROR_OUTOFMEMORY );
2003 retval = 0;
2004 goto end;
2006 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2007 /* Special case for dialog window procedure */
2008 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2010 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2011 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2012 type, WIN_PROC_WINDOW );
2013 goto end;
2016 else switch(offset)
2018 case GWL_ID:
2019 ptr = (DWORD*)&wndPtr->wIDmenu;
2020 break;
2021 case GWL_HINSTANCE:
2022 retval = SetWindowWord( hwnd, offset, newval );
2023 goto end;
2024 case GWL_WNDPROC:
2025 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2026 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2027 type, WIN_PROC_WINDOW );
2028 goto end;
2029 case GWL_STYLE:
2030 style.styleOld = wndPtr->dwStyle;
2031 newval &= ~(WS_CHILD); /* this bit can't be changed this way */
2032 style.styleNew = newval | (style.styleOld & (WS_CHILD));
2034 if (wndPtr->flags & WIN_ISWIN32)
2035 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2036 wndPtr->dwStyle = style.styleNew;
2037 if (wndPtr->flags & WIN_ISWIN32)
2038 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2039 retval = style.styleOld;
2040 goto end;
2042 case GWL_USERDATA:
2043 ptr = &wndPtr->userdata;
2044 break;
2045 case GWL_EXSTYLE:
2046 style.styleOld = wndPtr->dwExStyle;
2047 style.styleNew = newval;
2048 if (wndPtr->flags & WIN_ISWIN32)
2049 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2050 wndPtr->dwExStyle = newval;
2051 if (wndPtr->flags & WIN_ISWIN32)
2052 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2053 retval = style.styleOld;
2054 goto end;
2056 default:
2057 WARN("Invalid offset %d\n", offset );
2059 /* Don't think this is right error but it should do */
2060 SetLastError( ERROR_OUTOFMEMORY );
2062 retval = 0;
2063 goto end;
2065 retval = *ptr;
2066 *ptr = newval;
2067 end:
2068 WIN_ReleaseWndPtr(wndPtr);
2069 return retval;
2073 /**********************************************************************
2074 * GetWindowLong16 (USER.135)
2076 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2078 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2082 /**********************************************************************
2083 * GetWindowLongA (USER32.305)
2085 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2087 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2091 /**********************************************************************
2092 * GetWindowLongW (USER32.306)
2094 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2096 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2100 /**********************************************************************
2101 * SetWindowLong16 (USER.136)
2103 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2105 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2109 /**********************************************************************
2110 * SetWindowLongA (USER32.517)
2112 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2114 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2118 /**********************************************************************
2119 * SetWindowLongW (USER32.518) Set window attribute
2121 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2122 * value in a window's extra memory.
2124 * The _hwnd_ parameter specifies the window. is the handle to a
2125 * window that has extra memory. The _newval_ parameter contains the
2126 * new attribute or extra memory value. If positive, the _offset_
2127 * parameter is the byte-addressed location in the window's extra
2128 * memory to set. If negative, _offset_ specifies the window
2129 * attribute to set, and should be one of the following values:
2131 * GWL_EXSTYLE The window's extended window style
2133 * GWL_STYLE The window's window style.
2135 * GWL_WNDPROC Pointer to the window's window procedure.
2137 * GWL_HINSTANCE The window's pplication instance handle.
2139 * GWL_ID The window's identifier.
2141 * GWL_USERDATA The window's user-specified data.
2143 * If the window is a dialog box, the _offset_ parameter can be one of
2144 * the following values:
2146 * DWL_DLGPROC The address of the window's dialog box procedure.
2148 * DWL_MSGRESULT The return value of a message
2149 * that the dialog box procedure processed.
2151 * DWL_USER Application specific information.
2153 * RETURNS
2155 * If successful, returns the previous value located at _offset_. Otherwise,
2156 * returns 0.
2158 * NOTES
2160 * Extra memory for a window class is specified by a nonzero cbWndExtra
2161 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2162 * time of class creation.
2164 * Using GWL_WNDPROC to set a new window procedure effectively creates
2165 * a window subclass. Use CallWindowProc() in the new windows procedure
2166 * to pass messages to the superclass's window procedure.
2168 * The user data is reserved for use by the application which created
2169 * the window.
2171 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2172 * instead, call the EnableWindow() function to change the window's
2173 * disabled state.
2175 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2176 * SetParent() instead.
2178 * Win95:
2179 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2180 * it sends WM_STYLECHANGING before changing the settings
2181 * and WM_STYLECHANGED afterwards.
2182 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2184 * BUGS
2186 * GWL_STYLE does not dispatch WM_STYLE... messages.
2188 * CONFORMANCE
2190 * ECMA-234, Win32
2193 LONG WINAPI SetWindowLongW(
2194 HWND hwnd, /* [in] window to alter */
2195 INT offset, /* [in] offset, in bytes, of location to alter */
2196 LONG newval /* [in] new value of location */
2198 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2202 /*******************************************************************
2203 * GetWindowText16 (USER.36)
2205 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2207 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2211 /*******************************************************************
2212 * GetWindowTextA (USER32.309)
2214 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2216 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2217 (LPARAM)lpString );
2220 /*******************************************************************
2221 * InternalGetWindowText (USER32.326)
2223 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2225 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2226 return GetWindowTextW(hwnd,lpString,nMaxCount);
2230 /*******************************************************************
2231 * GetWindowTextW (USER32.312)
2233 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2235 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2236 (LPARAM)lpString );
2240 /*******************************************************************
2241 * SetWindowText16 (USER.37)
2243 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2245 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2249 /*******************************************************************
2250 * SetWindowTextA (USER32.521)
2252 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2254 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2258 /*******************************************************************
2259 * SetWindowTextW (USER32.523)
2261 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2263 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2267 /*******************************************************************
2268 * GetWindowTextLength16 (USER.38)
2270 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2272 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2276 /*******************************************************************
2277 * GetWindowTextLengthA (USER32.310)
2279 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2281 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2284 /*******************************************************************
2285 * GetWindowTextLengthW (USER32.311)
2287 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2289 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2293 /*******************************************************************
2294 * IsWindow16 (USER.47)
2296 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2298 CURRENT_STACK16->es = USER_HeapSel;
2299 return IsWindow( hwnd );
2303 /*******************************************************************
2304 * IsWindow (USER32.348)
2306 BOOL WINAPI IsWindow( HWND hwnd )
2308 WND * wndPtr;
2309 BOOL retvalue;
2311 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2312 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2313 WIN_ReleaseWndPtr(wndPtr);
2314 return retvalue;
2319 /*****************************************************************
2320 * GetParent16 (USER.46)
2322 HWND16 WINAPI GetParent16( HWND16 hwnd )
2324 return (HWND16)GetParent( hwnd );
2328 /*****************************************************************
2329 * GetParent (USER32.278)
2331 HWND WINAPI GetParent( HWND hwnd )
2333 WND *wndPtr;
2334 HWND retvalue = 0;
2336 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2337 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2338 goto end;
2340 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2341 if (wndPtr)
2342 retvalue = wndPtr->hwndSelf;
2344 end:
2345 WIN_ReleaseWndPtr(wndPtr);
2346 return retvalue;
2350 /*****************************************************************
2351 * WIN_GetTopParent
2353 * Get the top-level parent for a child window.
2354 * returns a locked pointer
2356 WND* WIN_GetTopParentPtr( WND* pWnd )
2358 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2360 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2362 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2364 return tmpWnd;
2367 /*****************************************************************
2368 * WIN_GetTopParent
2370 * Get the top-level parent for a child window.
2372 HWND WIN_GetTopParent( HWND hwnd )
2374 HWND retvalue;
2375 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2376 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2378 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2379 WIN_ReleaseWndPtr(tmpPtr);
2380 WIN_ReleaseWndPtr(wndPtr);
2381 return retvalue;
2385 /*****************************************************************
2386 * SetParent16 (USER.233)
2388 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2390 return SetParent( hwndChild, hwndNewParent );
2394 /*****************************************************************
2395 * SetParent (USER32.495)
2397 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2399 WND *wndPtr;
2400 DWORD dwStyle;
2401 WND *pWndNewParent;
2402 WND *pWndOldParent;
2403 HWND retvalue;
2406 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2408 dwStyle = wndPtr->dwStyle;
2410 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2411 : WIN_LockWndPtr(pWndDesktop);
2413 /* Windows hides the window first, then shows it again
2414 * including the WM_SHOWWINDOW messages and all */
2415 if (dwStyle & WS_VISIBLE)
2416 ShowWindow( hwndChild, SW_HIDE );
2418 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2420 /* SetParent additionally needs to make hwndChild the topmost window
2421 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2422 WM_WINDOWPOSCHANGED notification messages.
2424 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2425 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2426 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2427 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2429 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2431 WIN_ReleaseWndPtr(pWndOldParent);
2432 WIN_ReleaseWndPtr(pWndNewParent);
2433 WIN_ReleaseWndPtr(wndPtr);
2435 return retvalue;
2439 /*******************************************************************
2440 * IsChild16 (USER.48)
2442 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2444 return IsChild(parent,child);
2448 /*******************************************************************
2449 * IsChild (USER32.339)
2451 BOOL WINAPI IsChild( HWND parent, HWND child )
2453 WND * wndPtr = WIN_FindWndPtr( child );
2454 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2456 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2457 if (wndPtr->hwndSelf == parent)
2459 WIN_ReleaseWndPtr(wndPtr);
2460 return TRUE;
2463 WIN_ReleaseWndPtr(wndPtr);
2464 return FALSE;
2468 /***********************************************************************
2469 * IsWindowVisible16 (USER.49)
2471 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2473 return IsWindowVisible(hwnd);
2477 /***********************************************************************
2478 * IsWindowVisible (USER32.351)
2480 BOOL WINAPI IsWindowVisible( HWND hwnd )
2482 BOOL retval;
2483 WND *wndPtr = WIN_FindWndPtr( hwnd );
2484 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2486 if (!(wndPtr->dwStyle & WS_VISIBLE))
2488 WIN_ReleaseWndPtr(wndPtr);
2489 return FALSE;
2491 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2493 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2494 WIN_ReleaseWndPtr(wndPtr);
2495 return retval;
2500 /***********************************************************************
2501 * WIN_IsWindowDrawable
2503 * hwnd is drawable when it is visible, all parents are not
2504 * minimized, and it is itself not minimized unless we are
2505 * trying to draw its default class icon.
2507 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2509 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2510 if ((wnd->dwStyle & WS_MINIMIZE) &&
2511 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2512 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2513 if( wnd->dwStyle & WS_MINIMIZE ||
2514 !(wnd->dwStyle & WS_VISIBLE) ) break;
2515 return (wnd == NULL);
2519 /*******************************************************************
2520 * GetTopWindow16 (USER.229)
2522 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2524 return GetTopWindow(hwnd);
2528 /*******************************************************************
2529 * GetTopWindow (USER.229)
2531 HWND WINAPI GetTopWindow( HWND hwnd )
2533 HWND retval = 0;
2534 WND * wndPtr = (hwnd) ?
2535 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2537 if (wndPtr && wndPtr->child)
2538 retval = wndPtr->child->hwndSelf;
2540 WIN_ReleaseWndPtr(wndPtr);
2541 return retval;
2545 /*******************************************************************
2546 * GetWindow16 (USER.262)
2548 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2550 return GetWindow( hwnd,rel );
2554 /*******************************************************************
2555 * GetWindow (USER32.302)
2557 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2559 HWND retval;
2561 WND * wndPtr = WIN_FindWndPtr( hwnd );
2562 if (!wndPtr) return 0;
2563 switch(rel)
2565 case GW_HWNDFIRST:
2566 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2567 goto end;
2569 case GW_HWNDLAST:
2570 if (!wndPtr->parent)
2572 retval = 0; /* Desktop window */
2573 goto end;
2575 while (wndPtr->next)
2577 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2579 retval = wndPtr->hwndSelf;
2580 goto end;
2582 case GW_HWNDNEXT:
2583 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2584 goto end;
2586 case GW_HWNDPREV:
2587 if (!wndPtr->parent)
2589 retval = 0; /* Desktop window */
2590 goto end;
2592 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2593 if (wndPtr->hwndSelf == hwnd)
2595 retval = 0; /* First in list */
2596 goto end;
2598 while (wndPtr->next)
2600 if (wndPtr->next->hwndSelf == hwnd)
2602 retval = wndPtr->hwndSelf;
2603 goto end;
2605 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2607 retval = 0;
2608 goto end;
2610 case GW_OWNER:
2611 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2612 goto end;
2614 case GW_CHILD:
2615 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2616 goto end;
2618 retval = 0;
2619 end:
2620 WIN_ReleaseWndPtr(wndPtr);
2621 return retval;
2625 /*******************************************************************
2626 * GetNextWindow16 (USER.230)
2628 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2630 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2631 return GetWindow16( hwnd, flag );
2634 /***********************************************************************
2635 * WIN_InternalShowOwnedPopups
2637 * Internal version of ShowOwnedPopups; Wine functions should use this
2638 * to avoid interfering with application calls to ShowOwnedPopups
2639 * and to make sure the application can't prevent showing/hiding.
2641 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2645 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2647 INT totalChild=0, count=0;
2649 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2651 if (!pWnd) return TRUE;
2654 * Show windows Lowest first, Highest last to preserve Z-Order
2656 for (count = totalChild-1 ; count >=0; count--)
2658 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2660 if (fShow)
2662 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2663 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2666 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2668 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2669 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2672 else
2674 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2675 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2676 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2679 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2681 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2682 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2683 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2688 WIN_ReleaseDesktop();
2689 WIN_ReleaseWinArray(pWnd);
2691 return TRUE;
2694 /*******************************************************************
2695 * ShowOwnedPopups16 (USER.265)
2697 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2699 ShowOwnedPopups( owner, fShow );
2703 /*******************************************************************
2704 * ShowOwnedPopups (USER32.531)
2706 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2708 UINT totalChild=0, count=0;
2710 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2712 if (!pWnd) return TRUE;
2714 for (; count < totalChild; count++)
2716 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2718 if (fShow)
2720 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2723 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2724 * regardless of the state of the owner
2726 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2727 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2730 else
2732 if (IsWindowVisible(pWnd[count]->hwndSelf))
2735 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2736 * regardless of the state of the owner
2738 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2739 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2745 WIN_ReleaseDesktop();
2746 WIN_ReleaseWinArray(pWnd);
2747 return TRUE;
2751 /*******************************************************************
2752 * GetLastActivePopup16 (USER.287)
2754 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2756 return GetLastActivePopup( hwnd );
2759 /*******************************************************************
2760 * GetLastActivePopup (USER32.256)
2762 HWND WINAPI GetLastActivePopup( HWND hwnd )
2764 HWND retval;
2765 WND *wndPtr =WIN_FindWndPtr(hwnd);
2766 if (!wndPtr) return hwnd;
2767 retval = wndPtr->hwndLastActive;
2768 WIN_ReleaseWndPtr(wndPtr);
2769 if ((retval != hwnd) && (!IsWindow(retval)))
2770 retval = hwnd;
2771 return retval;
2775 /*******************************************************************
2776 * WIN_BuildWinArray
2778 * Build an array of pointers to the children of a given window.
2779 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2780 * when no windows are found.
2782 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2784 /* Future: this function will lock all windows associated with this array */
2786 WND **list, **ppWnd;
2787 WND *pWnd;
2788 UINT count = 0, skipOwned, skipHidden;
2789 DWORD skipFlags;
2791 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2792 skipOwned = bwaFlags & BWA_SKIPOWNED;
2793 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2794 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2796 /* First count the windows */
2798 if (!wndPtr)
2799 wndPtr = WIN_GetDesktop();
2801 pWnd = WIN_LockWndPtr(wndPtr->child);
2802 while (pWnd)
2804 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2805 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2806 count++;
2807 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2810 if( count )
2812 /* Now build the list of all windows */
2814 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2816 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2818 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2819 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2821 *ppWnd++ = pWnd;
2822 count++;
2825 WIN_ReleaseWndPtr(pWnd);
2826 *ppWnd = NULL;
2828 else count = 0;
2829 } else list = NULL;
2831 if( pTotal ) *pTotal = count;
2832 return list;
2834 /*******************************************************************
2835 * WIN_ReleaseWinArray
2837 void WIN_ReleaseWinArray(WND **wndArray)
2839 /* Future: this function will also unlock all windows associated with wndArray */
2840 HeapFree( GetProcessHeap(), 0, wndArray );
2844 /*******************************************************************
2845 * EnumWindows (USER32.193)
2847 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2849 WND **list, **ppWnd;
2851 /* We have to build a list of all windows first, to avoid */
2852 /* unpleasant side-effects, for instance if the callback */
2853 /* function changes the Z-order of the windows. */
2855 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2857 WIN_ReleaseDesktop();
2858 return FALSE;
2861 /* Now call the callback function for every window */
2863 for (ppWnd = list; *ppWnd; ppWnd++)
2865 LRESULT lpEnumFuncRetval;
2866 int iWndsLocks = 0;
2867 /* Make sure that the window still exists */
2868 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2870 /* To avoid any deadlocks, all the locks on the windows
2871 structures must be suspended before the control
2872 is passed to the application */
2873 iWndsLocks = WIN_SuspendWndsLock();
2874 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2875 WIN_RestoreWndsLock(iWndsLocks);
2877 if (!lpEnumFuncRetval) break;
2879 WIN_ReleaseWinArray(list);
2880 WIN_ReleaseDesktop();
2881 return TRUE;
2885 /**********************************************************************
2886 * EnumTaskWindows16 (USER.225)
2888 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2889 LPARAM lParam )
2891 WND **list, **ppWnd;
2893 /* This function is the same as EnumWindows(), */
2894 /* except for an added check on the window's task. */
2896 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2898 WIN_ReleaseDesktop();
2899 return FALSE;
2902 /* Now call the callback function for every window */
2904 for (ppWnd = list; *ppWnd; ppWnd++)
2906 LRESULT funcRetval;
2907 int iWndsLocks = 0;
2908 /* Make sure that the window still exists */
2909 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2910 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2912 /* To avoid any deadlocks, all the locks on the windows
2913 structures must be suspended before the control
2914 is passed to the application */
2915 iWndsLocks = WIN_SuspendWndsLock();
2916 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2917 WIN_RestoreWndsLock(iWndsLocks);
2919 if (!funcRetval) break;
2921 WIN_ReleaseWinArray(list);
2922 WIN_ReleaseDesktop();
2923 return TRUE;
2927 /**********************************************************************
2928 * EnumThreadWindows (USER32.190)
2930 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2932 TEB *teb = THREAD_IdToTEB(id);
2934 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2938 /**********************************************************************
2939 * WIN_EnumChildWindows
2941 * Helper function for EnumChildWindows().
2943 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2945 WND **childList;
2946 BOOL16 ret = FALSE;
2948 for ( ; *ppWnd; ppWnd++)
2950 int iWndsLocks = 0;
2952 /* Make sure that the window still exists */
2953 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2954 /* Build children list first */
2955 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2957 /* To avoid any deadlocks, all the locks on the windows
2958 structures must be suspended before the control
2959 is passed to the application */
2960 iWndsLocks = WIN_SuspendWndsLock();
2961 ret = func( (*ppWnd)->hwndSelf, lParam );
2962 WIN_RestoreWndsLock(iWndsLocks);
2964 if (childList)
2966 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2967 WIN_ReleaseWinArray(childList);
2969 if (!ret) return FALSE;
2971 return TRUE;
2975 /**********************************************************************
2976 * EnumChildWindows (USER32.178)
2978 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2979 LPARAM lParam )
2981 WND **list, *pParent;
2983 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2984 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2986 WIN_ReleaseWndPtr(pParent);
2987 return FALSE;
2989 WIN_EnumChildWindows( list, func, lParam );
2990 WIN_ReleaseWinArray(list);
2991 WIN_ReleaseWndPtr(pParent);
2992 return TRUE;
2996 /*******************************************************************
2997 * AnyPopup16 (USER.52)
2999 BOOL16 WINAPI AnyPopup16(void)
3001 return AnyPopup();
3005 /*******************************************************************
3006 * AnyPopup (USER32.4)
3008 BOOL WINAPI AnyPopup(void)
3010 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3011 BOOL retvalue;
3013 while (wndPtr)
3015 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3017 retvalue = TRUE;
3018 goto end;
3020 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3022 retvalue = FALSE;
3023 end:
3024 WIN_ReleaseWndPtr(wndPtr);
3025 return retvalue;
3029 /*******************************************************************
3030 * FlashWindow16 (USER.105)
3032 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3034 return FlashWindow( hWnd, bInvert );
3038 /*******************************************************************
3039 * FlashWindow (USER32.202)
3041 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3043 WND *wndPtr = WIN_FindWndPtr(hWnd);
3045 TRACE("%04x\n", hWnd);
3047 if (!wndPtr) return FALSE;
3049 if (wndPtr->dwStyle & WS_MINIMIZE)
3051 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3053 HDC hDC = GetDC(hWnd);
3055 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3056 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3058 ReleaseDC( hWnd, hDC );
3059 wndPtr->flags |= WIN_NCACTIVATED;
3061 else
3063 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3064 RDW_UPDATENOW | RDW_FRAME, 0 );
3065 wndPtr->flags &= ~WIN_NCACTIVATED;
3067 WIN_ReleaseWndPtr(wndPtr);
3068 return TRUE;
3070 else
3072 WPARAM16 wparam;
3073 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3074 else wparam = (hWnd == GetActiveWindow());
3076 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3077 WIN_ReleaseWndPtr(wndPtr);
3078 return wparam;
3083 /*******************************************************************
3084 * SetSysModalWindow16 (USER.188)
3086 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3088 HWND hWndOldModal = hwndSysModal;
3089 hwndSysModal = hWnd;
3090 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3091 return hWndOldModal;
3095 /*******************************************************************
3096 * GetSysModalWindow16 (USER.52)
3098 HWND16 WINAPI GetSysModalWindow16(void)
3100 return hwndSysModal;
3104 /*******************************************************************
3105 * GetWindowContextHelpId (USER32.303)
3107 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3109 DWORD retval;
3110 WND *wnd = WIN_FindWndPtr( hwnd );
3111 if (!wnd) return 0;
3112 retval = wnd->helpContext;
3113 WIN_ReleaseWndPtr(wnd);
3114 return retval;
3118 /*******************************************************************
3119 * SetWindowContextHelpId (USER32.515)
3121 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3123 WND *wnd = WIN_FindWndPtr( hwnd );
3124 if (!wnd) return FALSE;
3125 wnd->helpContext = id;
3126 WIN_ReleaseWndPtr(wnd);
3127 return TRUE;
3131 /*******************************************************************
3132 * DRAG_QueryUpdate
3134 * recursively find a child that contains spDragInfo->pt point
3135 * and send WM_QUERYDROPOBJECT
3137 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3139 BOOL16 wParam, bResult = 0;
3140 POINT pt;
3141 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3142 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3143 RECT tempRect;
3145 if( !ptrQueryWnd || !ptrDragInfo )
3146 goto end;
3148 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3150 GetWindowRect(hQueryWnd,&tempRect);
3152 if( !PtInRect(&tempRect,pt) ||
3153 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3154 goto end;
3156 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3158 tempRect = ptrQueryWnd->rectClient;
3159 if(ptrQueryWnd->dwStyle & WS_CHILD)
3160 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3161 (LPPOINT)&tempRect, 2 );
3163 if (PtInRect( &tempRect, pt))
3165 wParam = 0;
3167 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3169 if( ptrWnd->dwStyle & WS_VISIBLE )
3171 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3172 if (PtInRect( &tempRect, pt )) break;
3176 if(ptrWnd)
3178 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3179 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3180 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3181 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3182 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3184 WIN_ReleaseWndPtr(ptrWnd);
3187 if(bResult)
3188 goto end;
3190 else wParam = 1;
3192 else wParam = 1;
3194 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3196 ptrDragInfo->hScope = hQueryWnd;
3198 bResult = ( bNoSend )
3199 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3200 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3201 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3202 if( !bResult )
3203 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3205 end:
3206 WIN_ReleaseWndPtr(ptrQueryWnd);
3207 return bResult;
3211 /*******************************************************************
3212 * DragDetect (USER.465)
3214 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3216 POINT pt32;
3217 CONV_POINT16TO32( &pt, &pt32 );
3218 return DragDetect( hWnd, pt32 );
3221 /*******************************************************************
3222 * DragDetect (USER32.151)
3224 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3226 MSG msg;
3227 RECT rect;
3229 rect.left = pt.x - wDragWidth;
3230 rect.right = pt.x + wDragWidth;
3232 rect.top = pt.y - wDragHeight;
3233 rect.bottom = pt.y + wDragHeight;
3235 SetCapture(hWnd);
3237 while(1)
3239 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3241 if( msg.message == WM_LBUTTONUP )
3243 ReleaseCapture();
3244 return 0;
3246 if( msg.message == WM_MOUSEMOVE )
3248 POINT tmp;
3249 tmp.x = LOWORD(msg.lParam);
3250 tmp.y = HIWORD(msg.lParam);
3251 if( !PtInRect( &rect, tmp ))
3253 ReleaseCapture();
3254 return 1;
3258 WaitMessage();
3260 return 0;
3263 /******************************************************************************
3264 * DragObject16 (USER.464)
3266 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3267 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3269 MSG msg;
3270 LPDRAGINFO16 lpDragInfo;
3271 SEGPTR spDragInfo;
3272 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3273 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3274 WND *wndPtr = WIN_FindWndPtr(hWnd);
3275 HCURSOR16 hCurrentCursor = 0;
3276 HWND16 hCurrentWnd = 0;
3278 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3279 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3281 if( !lpDragInfo || !spDragInfo )
3283 WIN_ReleaseWndPtr(wndPtr);
3284 return 0L;
3287 hBummer = LoadCursorA(0, IDC_BUMMERA);
3289 if( !hBummer || !wndPtr )
3291 GlobalFree16(hDragInfo);
3292 WIN_ReleaseWndPtr(wndPtr);
3293 return 0L;
3296 if(hCursor)
3298 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3300 GlobalFree16(hDragInfo);
3301 WIN_ReleaseWndPtr(wndPtr);
3302 return 0L;
3305 if( hDragCursor == hCursor ) hDragCursor = 0;
3306 else hCursor = hDragCursor;
3308 hOldCursor = SetCursor(hDragCursor);
3311 lpDragInfo->hWnd = hWnd;
3312 lpDragInfo->hScope = 0;
3313 lpDragInfo->wFlags = wObj;
3314 lpDragInfo->hList = szList; /* near pointer! */
3315 lpDragInfo->hOfStruct = hOfStruct;
3316 lpDragInfo->l = 0L;
3318 SetCapture(hWnd);
3319 ShowCursor( TRUE );
3323 do{ WaitMessage(); }
3324 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3326 *(lpDragInfo+1) = *lpDragInfo;
3328 lpDragInfo->pt.x = msg.pt.x;
3329 lpDragInfo->pt.y = msg.pt.y;
3331 /* update DRAGINFO struct */
3332 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3334 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3335 hCurrentCursor = hCursor;
3336 else
3338 hCurrentCursor = hBummer;
3339 lpDragInfo->hScope = 0;
3341 if( hCurrentCursor )
3342 SetCursor(hCurrentCursor);
3344 /* send WM_DRAGLOOP */
3345 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3346 (LPARAM) spDragInfo );
3347 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3348 if( hCurrentWnd != lpDragInfo->hScope )
3350 if( hCurrentWnd )
3351 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3352 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3353 HIWORD(spDragInfo)) );
3354 hCurrentWnd = lpDragInfo->hScope;
3355 if( hCurrentWnd )
3356 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3358 else
3359 if( hCurrentWnd )
3360 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3362 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3364 ReleaseCapture();
3365 ShowCursor( FALSE );
3367 if( hCursor )
3369 SetCursor( hOldCursor );
3370 if (hDragCursor) DestroyCursor( hDragCursor );
3373 if( hCurrentCursor != hBummer )
3374 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3375 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3376 else
3377 msg.lParam = 0;
3378 GlobalFree16(hDragInfo);
3379 WIN_ReleaseWndPtr(wndPtr);
3381 return (DWORD)(msg.lParam);