Fixed OleLoadFromStream: Dereference ppvObj and get IPersistStream
[wine.git] / windows / win.c
blob64cf61e7698ec8f68d004b2297fa00b0f4f1d390
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/unicode.h"
14 #include "options.h"
15 #include "class.h"
16 #include "win.h"
17 #include "heap.h"
18 #include "user.h"
19 #include "dce.h"
20 #include "cursoricon.h"
21 #include "hook.h"
22 #include "menu.h"
23 #include "message.h"
24 #include "nonclient.h"
25 #include "queue.h"
26 #include "winpos.h"
27 #include "clipboard.h"
28 #include "winproc.h"
29 #include "task.h"
30 #include "thread.h"
31 #include "winerror.h"
32 #include "mdi.h"
33 #include "local.h"
34 #include "syslevel.h"
35 #include "stackframe.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(win);
39 DECLARE_DEBUG_CHANNEL(msg);
41 /**********************************************************************/
43 WND_DRIVER *WND_Driver = NULL;
45 /* Desktop window */
46 static WND *pWndDesktop = NULL;
48 static HWND hwndSysModal = 0;
50 static WORD wDragWidth = 4;
51 static WORD wDragHeight= 3;
53 /* thread safeness */
54 static SYSLEVEL WIN_SysLevel;
56 /***********************************************************************
57 * WIN_Init
58 */
59 void WIN_Init( void )
61 /* Initialisation of the critical section for thread safeness */
62 _CreateSysLevel( &WIN_SysLevel, 2 );
65 /***********************************************************************
66 * WIN_LockWnds
68 * Locks access to all WND structures for thread safeness
70 void WIN_LockWnds( void )
72 _EnterSysLevel( &WIN_SysLevel );
75 /***********************************************************************
76 * WIN_UnlockWnds
78 * Unlocks access to all WND structures
80 void WIN_UnlockWnds( void )
82 _LeaveSysLevel( &WIN_SysLevel );
85 /***********************************************************************
86 * WIN_SuspendWndsLock
88 * Suspend the lock on WND structures.
89 * Returns the number of locks suspended
91 int WIN_SuspendWndsLock( void )
93 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
94 int count = isuspendedLocks;
96 while ( count-- > 0 )
97 _LeaveSysLevel( &WIN_SysLevel );
99 return isuspendedLocks;
102 /***********************************************************************
103 * WIN_RestoreWndsLock
105 * Restore the suspended locks on WND structures
107 void WIN_RestoreWndsLock( int ipreviousLocks )
109 while ( ipreviousLocks-- > 0 )
110 _EnterSysLevel( &WIN_SysLevel );
113 /***********************************************************************
114 * WIN_FindWndPtr
116 * Return a pointer to the WND structure corresponding to a HWND.
118 WND * WIN_FindWndPtr( HWND hwnd )
120 WND * ptr;
122 if (!hwnd || HIWORD(hwnd)) goto error2;
123 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
124 /* Lock all WND structures for thread safeness*/
125 WIN_LockWnds();
126 /*and increment destruction monitoring*/
127 ptr->irefCount++;
129 if (ptr->dwMagic != WND_MAGIC) goto error;
130 if (ptr->hwndSelf != hwnd)
132 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
133 goto error;
135 /* returns a locked pointer */
136 return ptr;
137 error:
138 /* Unlock all WND structures for thread safeness*/
139 WIN_UnlockWnds();
140 /* and decrement destruction monitoring value */
141 ptr->irefCount--;
143 error2:
144 if ( hwnd!=0 )
145 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
146 return NULL;
149 /***********************************************************************
150 * WIN_LockWndPtr
152 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
153 * but by initWndPtr;
154 * Returns the locked initialisation pointer
156 WND *WIN_LockWndPtr(WND *initWndPtr)
158 if(!initWndPtr) return 0;
160 /* Lock all WND structures for thread safeness*/
161 WIN_LockWnds();
162 /*and increment destruction monitoring*/
163 initWndPtr->irefCount++;
165 return initWndPtr;
169 /***********************************************************************
170 * WIN_ReleaseWndPtr
172 * Release the pointer to the WND structure.
174 void WIN_ReleaseWndPtr(WND *wndPtr)
176 if(!wndPtr) return;
178 /*Decrement destruction monitoring value*/
179 wndPtr->irefCount--;
180 /* Check if it's time to release the memory*/
181 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
183 /* Release memory */
184 USER_HEAP_FREE( wndPtr->hwndSelf);
185 wndPtr->hwndSelf = 0;
187 else if(wndPtr->irefCount < 0)
189 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
190 ERR("forgot a Lock on %p somewhere\n",wndPtr);
192 /*unlock all WND structures for thread safeness*/
193 WIN_UnlockWnds();
196 /***********************************************************************
197 * WIN_UpdateWndPtr
199 * Updates the value of oldPtr to newPtr.
201 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
203 WND *tmpWnd = NULL;
205 tmpWnd = WIN_LockWndPtr(newPtr);
206 WIN_ReleaseWndPtr(*oldPtr);
207 *oldPtr = tmpWnd;
211 /***********************************************************************
212 * WIN_DumpWindow
214 * Dump the content of a window structure to stderr.
216 void WIN_DumpWindow( HWND hwnd )
218 WND *ptr;
219 char className[80];
220 int i;
222 if (!(ptr = WIN_FindWndPtr( hwnd )))
224 WARN("%04x is not a window handle\n", hwnd );
225 return;
228 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
229 strcpy( className, "#NULL#" );
231 TRACE("Window %04x (%p):\n", hwnd, ptr );
232 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
233 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
234 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
235 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
236 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
237 ptr->next, ptr->child, ptr->parent, ptr->owner,
238 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
239 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
240 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
241 ptr->text ? debugstr_w(ptr->text) : "",
242 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
243 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
244 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
245 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
247 if (ptr->class->cbWndExtra)
249 DPRINTF( "extra bytes:" );
250 for (i = 0; i < ptr->class->cbWndExtra; i++)
251 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
252 DPRINTF( "\n" );
254 DPRINTF( "\n" );
255 WIN_ReleaseWndPtr(ptr);
259 /***********************************************************************
260 * WIN_WalkWindows
262 * Walk the windows tree and print each window on stderr.
264 void WIN_WalkWindows( HWND hwnd, int indent )
266 WND *ptr;
267 char className[80];
269 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
271 if (!ptr)
273 WARN("Invalid window handle %04x\n", hwnd );
274 return;
277 if (!indent) /* first time around */
278 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
279 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
280 " Text");
282 while (ptr)
284 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
286 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
288 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
289 (DWORD)ptr, ptr->hmemTaskQ, className,
290 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
291 ptr->text ? debugstr_w(ptr->text) : "<null>");
293 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
294 WIN_UpdateWndPtr(&ptr,ptr->next);
300 /***********************************************************************
301 * WIN_UnlinkWindow
303 * Remove a window from the siblings linked list.
305 BOOL WIN_UnlinkWindow( HWND hwnd )
307 WND *wndPtr, **ppWnd;
308 BOOL ret = FALSE;
310 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
311 else if(!wndPtr->parent)
313 WIN_ReleaseWndPtr(wndPtr);
314 return FALSE;
317 ppWnd = &wndPtr->parent->child;
318 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
319 if (*ppWnd)
321 *ppWnd = wndPtr->next;
322 ret = TRUE;
324 WIN_ReleaseWndPtr(wndPtr);
325 return ret;
329 /***********************************************************************
330 * WIN_LinkWindow
332 * Insert a window into the siblings linked list.
333 * The window is inserted after the specified window, which can also
334 * be specified as HWND_TOP or HWND_BOTTOM.
336 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
338 WND *wndPtr, **ppWnd;
340 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
341 else if(!wndPtr->parent)
343 WIN_ReleaseWndPtr(wndPtr);
344 return FALSE;
346 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
348 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
349 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
350 while (*ppWnd) ppWnd = &(*ppWnd)->next;
352 else /* Normal case */
354 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
355 if (!afterPtr)
357 WIN_ReleaseWndPtr(wndPtr);
358 return FALSE;
360 ppWnd = &afterPtr->next;
361 WIN_ReleaseWndPtr(afterPtr);
363 wndPtr->next = *ppWnd;
364 *ppWnd = wndPtr;
365 WIN_ReleaseWndPtr(wndPtr);
366 return TRUE;
370 /***********************************************************************
371 * WIN_FindWinToRepaint
373 * Find a window that needs repaint.
375 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
377 HWND hwndRet;
378 WND *pWnd;
380 /* Note: the desktop window never gets WM_PAINT messages
381 * The real reason why is because Windows DesktopWndProc
382 * does ValidateRgn inside WM_ERASEBKGND handler.
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE))
391 TRACE("skipping window %04x\n",
392 pWnd->hwndSelf );
394 else if ((pWnd->hmemTaskQ == hQueue) &&
395 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
396 break;
398 else if (pWnd->child )
399 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
401 WIN_ReleaseWndPtr(pWnd);
402 return hwndRet;
407 if(!pWnd)
409 return 0;
412 hwndRet = pWnd->hwndSelf;
414 /* look among siblings if we got a transparent window */
415 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
416 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
418 WIN_UpdateWndPtr(&pWnd,pWnd->next);
420 if (pWnd)
422 hwndRet = pWnd->hwndSelf;
423 WIN_ReleaseWndPtr(pWnd);
425 TRACE("found %04x\n",hwndRet);
426 return hwndRet;
430 /***********************************************************************
431 * WIN_DestroyWindow
433 * Destroy storage associated to a window. "Internals" p.358
434 * returns a locked wndPtr->next
436 static WND* WIN_DestroyWindow( WND* wndPtr )
438 HWND hwnd = wndPtr->hwndSelf;
439 WND *pWnd;
441 TRACE("%04x\n", wndPtr->hwndSelf );
443 /* free child windows */
444 WIN_LockWndPtr(wndPtr->child);
445 while ((pWnd = wndPtr->child))
447 wndPtr->child = WIN_DestroyWindow( pWnd );
448 WIN_ReleaseWndPtr(pWnd);
452 * Clear the update region to make sure no WM_PAINT messages will be
453 * generated for this window while processing the WM_NCDESTROY.
455 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
457 if (wndPtr->hrgnUpdate > 1)
458 DeleteObject( wndPtr->hrgnUpdate );
460 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
462 wndPtr->hrgnUpdate = 0;
466 * Send the WM_NCDESTROY to the window being destroyed.
468 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
470 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
472 WINPOS_CheckInternalPos( wndPtr );
473 if( hwnd == GetCapture()) ReleaseCapture();
475 /* free resources associated with the window */
477 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
478 PROPERTY_RemoveWindowProps( wndPtr );
480 wndPtr->dwMagic = 0; /* Mark it as invalid */
482 /* toss stale messages from the queue */
484 if( wndPtr->hmemTaskQ )
486 BOOL bPostQuit = FALSE;
487 WPARAM wQuitParam = 0;
488 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
489 QMSG *qmsg;
491 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
493 if( qmsg->msg.message == WM_QUIT )
495 bPostQuit = TRUE;
496 wQuitParam = qmsg->msg.wParam;
498 QUEUE_RemoveMsg(msgQ, qmsg);
501 QUEUE_Unlock(msgQ);
503 /* repost WM_QUIT to make sure this app exits its message loop */
504 if( bPostQuit ) PostQuitMessage(wQuitParam);
505 wndPtr->hmemTaskQ = 0;
508 if (!(wndPtr->dwStyle & WS_CHILD))
509 if (wndPtr->wIDmenu)
511 DestroyMenu( wndPtr->wIDmenu );
512 wndPtr->wIDmenu = 0;
514 if (wndPtr->hSysMenu)
516 DestroyMenu( wndPtr->hSysMenu );
517 wndPtr->hSysMenu = 0;
519 wndPtr->pDriver->pDestroyWindow( wndPtr );
520 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
521 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
522 wndPtr->class->cWindows--;
523 wndPtr->class = NULL;
525 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
527 wndPtr->pDriver->pFinalize(wndPtr);
529 return pWnd;
532 /***********************************************************************
533 * WIN_ResetQueueWindows
535 * Reset the queue of all the children of a given window.
536 * Return TRUE if something was done.
538 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
540 BOOL ret = FALSE;
542 if (hNew) /* Set a new queue */
544 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
546 if (wnd->hmemTaskQ == hQueue)
548 wnd->hmemTaskQ = hNew;
549 ret = TRUE;
551 if (wnd->child)
553 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
557 else /* Queue is being destroyed */
559 while (wnd->child)
561 WND *tmp = WIN_LockWndPtr(wnd->child);
562 WND *tmp2;
563 ret = FALSE;
564 while (tmp)
566 if (tmp->hmemTaskQ == hQueue)
568 DestroyWindow( tmp->hwndSelf );
569 ret = TRUE;
570 break;
572 tmp2 = WIN_LockWndPtr(tmp->child);
573 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
574 ret = TRUE;
575 else
577 WIN_UpdateWndPtr(&tmp,tmp->next);
579 WIN_ReleaseWndPtr(tmp2);
581 WIN_ReleaseWndPtr(tmp);
582 if (!ret) break;
585 return ret;
588 /***********************************************************************
589 * WIN_CreateDesktopWindow
591 * Create the desktop window.
593 BOOL WIN_CreateDesktopWindow(void)
595 CLASS *class;
596 HWND hwndDesktop;
598 TRACE("Creating desktop window\n");
601 if (!ICONTITLE_Init() ||
602 !WINPOS_CreateInternalPosAtom() ||
603 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
604 return FALSE;
606 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
607 if (!hwndDesktop) return FALSE;
608 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
610 pWndDesktop->pDriver = WND_Driver;
611 pWndDesktop->pDriver->pInitialize(pWndDesktop);
613 pWndDesktop->next = NULL;
614 pWndDesktop->child = NULL;
615 pWndDesktop->parent = NULL;
616 pWndDesktop->owner = NULL;
617 pWndDesktop->class = class;
618 pWndDesktop->dwMagic = WND_MAGIC;
619 pWndDesktop->hwndSelf = hwndDesktop;
620 pWndDesktop->hInstance = 0;
621 pWndDesktop->rectWindow.left = 0;
622 pWndDesktop->rectWindow.top = 0;
623 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
624 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
625 pWndDesktop->rectClient = pWndDesktop->rectWindow;
626 pWndDesktop->text = NULL;
627 pWndDesktop->hmemTaskQ = GetFastQueue16();
628 pWndDesktop->hrgnUpdate = 0;
629 pWndDesktop->hwndLastActive = hwndDesktop;
630 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
631 WS_CLIPSIBLINGS;
632 pWndDesktop->dwExStyle = 0;
633 pWndDesktop->dce = NULL;
634 pWndDesktop->pVScroll = NULL;
635 pWndDesktop->pHScroll = NULL;
636 pWndDesktop->pProp = NULL;
637 pWndDesktop->wIDmenu = 0;
638 pWndDesktop->helpContext = 0;
639 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
640 pWndDesktop->hSysMenu = 0;
641 pWndDesktop->userdata = 0;
642 pWndDesktop->winproc = (WNDPROC16)class->winproc;
643 pWndDesktop->irefCount = 0;
645 /* FIXME: How do we know if it should be Unicode or not */
646 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
647 return FALSE;
649 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
650 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
651 return TRUE;
655 /***********************************************************************
656 * WIN_CreateWindowEx
658 * Fix the coordinates - Helper for WIN_CreateWindowEx.
659 * returns default show mode in sw.
660 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
662 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
664 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
665 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
667 if (cs->style & (WS_CHILD | WS_POPUP))
669 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
670 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
672 else /* overlapped window */
674 STARTUPINFOA info;
676 GetStartupInfoA( &info );
678 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
680 /* Never believe Microsoft's documentation... CreateWindowEx doc says
681 * that if an overlapped window is created with WS_VISIBLE style bit
682 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
683 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
684 * reveals that
686 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
687 * 2) it does not ignore the y parameter as the docs claim; instead, it
688 * uses it as second parameter to ShowWindow() unless y is either
689 * CW_USEDEFAULT or CW_USEDEFAULT16.
691 * The fact that we didn't do 2) caused bogus windows pop up when wine
692 * was running apps that were using this obscure feature. Example -
693 * calc.exe that comes with Win98 (only Win98, it's different from
694 * the one that comes with Win95 and NT)
696 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
697 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
698 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
701 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
703 if (info.dwFlags & STARTF_USESIZE)
705 cs->cx = info.dwXSize;
706 cs->cy = info.dwYSize;
708 else /* if no other hint from the app, pick 3/4 of the screen real estate */
710 RECT r;
711 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
712 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
713 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
720 /***********************************************************************
721 * WIN_CreateWindowEx
723 * Implementation of CreateWindowEx().
725 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
726 BOOL win32, BOOL unicode )
728 INT sw = SW_SHOW;
729 CLASS *classPtr;
730 WND *wndPtr;
731 HWND retvalue;
732 HWND16 hwnd, hwndLinkAfter;
733 POINT maxSize, maxPos, minTrack, maxTrack;
734 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
736 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
737 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
738 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
739 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
740 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
742 /* Find the parent window */
744 if (cs->hwndParent)
746 /* Make sure parent is valid */
747 if (!IsWindow( cs->hwndParent ))
749 WARN("Bad parent %04x\n", cs->hwndParent );
750 return 0;
752 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
753 WARN("No parent for child window\n" );
754 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
757 /* Find the window class */
758 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
760 WARN("Bad class '%s'\n", cs->lpszClass );
761 return 0;
764 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
766 /* Create the window structure */
768 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
769 - sizeof(wndPtr->wExtra) )))
771 TRACE("out of memory\n" );
772 return 0;
775 /* Fill the window structure */
777 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
778 wndPtr->next = NULL;
779 wndPtr->child = NULL;
781 if ((cs->style & WS_CHILD) && cs->hwndParent)
783 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
784 wndPtr->owner = NULL;
785 WIN_ReleaseWndPtr(wndPtr->parent);
787 else
789 wndPtr->parent = pWndDesktop;
790 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
791 wndPtr->owner = NULL;
792 else
794 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
795 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
796 WIN_ReleaseWndPtr(wndPtr->owner);
797 WIN_ReleaseWndPtr(tmpWnd);
802 wndPtr->pDriver = wndPtr->parent->pDriver;
803 wndPtr->pDriver->pInitialize(wndPtr);
805 wndPtr->class = classPtr;
806 wndPtr->winproc = classPtr->winproc;
807 wndPtr->dwMagic = WND_MAGIC;
808 wndPtr->hwndSelf = hwnd;
809 wndPtr->hInstance = cs->hInstance;
810 wndPtr->text = NULL;
811 wndPtr->hmemTaskQ = GetFastQueue16();
812 wndPtr->hrgnUpdate = 0;
813 wndPtr->hrgnWnd = 0;
814 wndPtr->hwndLastActive = hwnd;
815 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
816 wndPtr->dwExStyle = cs->dwExStyle;
817 wndPtr->wIDmenu = 0;
818 wndPtr->helpContext = 0;
819 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
820 wndPtr->pVScroll = NULL;
821 wndPtr->pHScroll = NULL;
822 wndPtr->pProp = NULL;
823 wndPtr->userdata = 0;
824 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
825 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
826 wndPtr->irefCount = 1;
828 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
830 /* Call the WH_CBT hook */
832 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
833 ? HWND_BOTTOM : HWND_TOP;
835 if (HOOK_IsHooked( WH_CBT ))
837 CBT_CREATEWNDA cbtc;
838 LRESULT ret;
840 cbtc.lpcs = cs;
841 cbtc.hwndInsertAfter = hwndLinkAfter;
842 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
843 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
844 if (ret)
846 TRACE("CBT-hook returned 0\n");
847 wndPtr->pDriver->pFinalize(wndPtr);
848 USER_HEAP_FREE( hwnd );
849 retvalue = 0;
850 goto end;
854 /* Increment class window counter */
856 classPtr->cWindows++;
858 /* Correct the window style */
860 if (!(cs->style & WS_CHILD))
862 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
863 if (!(cs->style & WS_POPUP))
865 wndPtr->dwStyle |= WS_CAPTION;
866 wndPtr->flags |= WIN_NEED_SIZE;
870 /* Get class or window DC if needed */
872 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
873 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
874 else wndPtr->dce = NULL;
876 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
878 wndPtr->rectWindow.left = cs->x;
879 wndPtr->rectWindow.top = cs->y;
880 wndPtr->rectWindow.right = cs->x + cs->cx;
881 wndPtr->rectWindow.bottom = cs->y + cs->cy;
882 wndPtr->rectClient = wndPtr->rectWindow;
884 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
886 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
888 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
889 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
890 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
891 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
892 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
895 if (cs->cx < 0) cs->cx = 0;
896 if (cs->cy < 0) cs->cy = 0;
898 wndPtr->rectWindow.left = cs->x;
899 wndPtr->rectWindow.top = cs->y;
900 wndPtr->rectWindow.right = cs->x + cs->cx;
901 wndPtr->rectWindow.bottom = cs->y + cs->cy;
902 wndPtr->rectClient = wndPtr->rectWindow;
904 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
906 retvalue = FALSE;
907 goto end;
910 /* Set the window menu */
912 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
914 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
915 else
917 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
918 if (classPtr->menuNameA)
919 cs->hMenu = HIWORD(classPtr->menuNameA) ?
920 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
921 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
922 #else
923 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
924 if (menuName)
926 if (HIWORD(cs->hInstance))
927 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
928 else
929 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
931 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
933 #endif
936 else wndPtr->wIDmenu = (UINT)cs->hMenu;
938 /* Send the WM_CREATE message
939 * Perhaps we shouldn't allow width/height changes as well.
940 * See p327 in "Internals".
943 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
945 localSend32 = unicode ? SendMessageW : SendMessageA;
946 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
948 /* Insert the window in the linked list */
950 WIN_LinkWindow( hwnd, hwndLinkAfter );
952 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
953 NULL, NULL, 0, &wndPtr->rectClient );
954 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
955 maxPos.y - wndPtr->rectWindow.top);
956 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
958 /* Send the size messages */
960 if (!(wndPtr->flags & WIN_NEED_SIZE))
962 /* send it anyway */
963 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
964 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
965 WARN("sending bogus WM_SIZE message 0x%08lx\n",
966 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
967 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
968 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
969 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
970 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
971 SendMessageA( hwnd, WM_MOVE, 0,
972 MAKELONG( wndPtr->rectClient.left,
973 wndPtr->rectClient.top ) );
976 /* Show the window, maximizing or minimizing if needed */
978 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
980 RECT16 newPos;
981 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
982 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
983 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
984 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
985 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
986 : SWP_NOZORDER | SWP_FRAMECHANGED;
987 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
988 newPos.right, newPos.bottom, swFlag );
991 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
993 /* Notify the parent window only */
995 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
996 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
997 if( !IsWindow(hwnd) )
999 retvalue = 0;
1000 goto end;
1004 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1006 /* Call WH_SHELL hook */
1008 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1009 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1011 TRACE("created window %04x\n", hwnd);
1012 retvalue = hwnd;
1013 goto end;
1015 WIN_UnlinkWindow( hwnd );
1018 /* Abort window creation */
1020 WARN("aborted by WM_xxCREATE!\n");
1021 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1022 retvalue = 0;
1023 end:
1024 WIN_ReleaseWndPtr(wndPtr);
1026 return retvalue;
1030 /***********************************************************************
1031 * CreateWindow16 (USER.41)
1033 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1034 DWORD style, INT16 x, INT16 y, INT16 width,
1035 INT16 height, HWND16 parent, HMENU16 menu,
1036 HINSTANCE16 instance, LPVOID data )
1038 return CreateWindowEx16( 0, className, windowName, style,
1039 x, y, width, height, parent, menu, instance, data );
1043 /***********************************************************************
1044 * CreateWindowEx16 (USER.452)
1046 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1047 LPCSTR windowName, DWORD style, INT16 x,
1048 INT16 y, INT16 width, INT16 height,
1049 HWND16 parent, HMENU16 menu,
1050 HINSTANCE16 instance, LPVOID data )
1052 ATOM classAtom;
1053 CREATESTRUCTA cs;
1054 char buffer[256];
1056 /* Find the class atom */
1058 if (HIWORD(className))
1060 if (!(classAtom = GlobalFindAtomA( className )))
1062 ERR( "bad class name %s\n", debugres_a(className) );
1063 return 0;
1066 else
1068 classAtom = LOWORD(className);
1069 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1071 ERR( "bad atom %x\n", classAtom);
1072 return 0;
1074 className = buffer;
1077 /* Fix the coordinates */
1079 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1080 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1081 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1082 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1084 /* Create the window */
1086 cs.lpCreateParams = data;
1087 cs.hInstance = (HINSTANCE)instance;
1088 cs.hMenu = (HMENU)menu;
1089 cs.hwndParent = (HWND)parent;
1090 cs.style = style;
1091 cs.lpszName = windowName;
1092 cs.lpszClass = className;
1093 cs.dwExStyle = exStyle;
1095 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1099 /***********************************************************************
1100 * CreateWindowExA (USER32.83)
1102 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1103 LPCSTR windowName, DWORD style, INT x,
1104 INT y, INT width, INT height,
1105 HWND parent, HMENU menu,
1106 HINSTANCE instance, LPVOID data )
1108 ATOM classAtom;
1109 CREATESTRUCTA cs;
1110 char buffer[256];
1112 if(!instance)
1113 instance=GetModuleHandleA(NULL);
1115 if(exStyle & WS_EX_MDICHILD)
1116 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1118 /* Find the class atom */
1120 if (HIWORD(className))
1122 if (!(classAtom = GlobalFindAtomA( className )))
1124 ERR( "bad class name %s\n", debugres_a(className) );
1125 return 0;
1128 else
1130 classAtom = LOWORD(className);
1131 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1133 ERR( "bad atom %x\n", classAtom);
1134 return 0;
1136 className = buffer;
1139 /* Create the window */
1141 cs.lpCreateParams = data;
1142 cs.hInstance = instance;
1143 cs.hMenu = menu;
1144 cs.hwndParent = parent;
1145 cs.x = x;
1146 cs.y = y;
1147 cs.cx = width;
1148 cs.cy = height;
1149 cs.style = style;
1150 cs.lpszName = windowName;
1151 cs.lpszClass = className;
1152 cs.dwExStyle = exStyle;
1154 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1158 /***********************************************************************
1159 * CreateWindowExW (USER32.84)
1161 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1162 LPCWSTR windowName, DWORD style, INT x,
1163 INT y, INT width, INT height,
1164 HWND parent, HMENU menu,
1165 HINSTANCE instance, LPVOID data )
1167 ATOM classAtom;
1168 CREATESTRUCTW cs;
1169 WCHAR buffer[256];
1171 if(!instance)
1172 instance=GetModuleHandleA(NULL);
1174 if(exStyle & WS_EX_MDICHILD)
1175 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1177 /* Find the class atom */
1179 if (HIWORD(className))
1181 if (!(classAtom = GlobalFindAtomW( className )))
1183 ERR( "bad class name %s\n", debugres_w(className) );
1184 return 0;
1187 else
1189 classAtom = LOWORD(className);
1190 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1192 ERR( "bad atom %x\n", classAtom);
1193 return 0;
1195 className = buffer;
1198 /* Create the window */
1200 cs.lpCreateParams = data;
1201 cs.hInstance = instance;
1202 cs.hMenu = menu;
1203 cs.hwndParent = parent;
1204 cs.x = x;
1205 cs.y = y;
1206 cs.cx = width;
1207 cs.cy = height;
1208 cs.style = style;
1209 cs.lpszName = windowName;
1210 cs.lpszClass = className;
1211 cs.dwExStyle = exStyle;
1213 /* Note: we rely on the fact that CREATESTRUCTA and */
1214 /* CREATESTRUCTW have the same layout. */
1215 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1219 /***********************************************************************
1220 * WIN_CheckFocus
1222 static void WIN_CheckFocus( WND* pWnd )
1224 if( GetFocus16() == pWnd->hwndSelf )
1225 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1228 /***********************************************************************
1229 * WIN_SendDestroyMsg
1231 static void WIN_SendDestroyMsg( WND* pWnd )
1233 WIN_CheckFocus(pWnd);
1235 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1236 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1239 * Send the WM_DESTROY to the window.
1241 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1244 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1245 * make sure that the window still exists when we come back.
1247 if (IsWindow(pWnd->hwndSelf))
1249 HWND* pWndArray = NULL;
1250 WND* pChild = NULL;
1251 int nKidCount = 0;
1254 * Now, if the window has kids, we have to send WM_DESTROY messages
1255 * recursively to it's kids. It seems that those calls can also
1256 * trigger re-entrant calls to DestroyWindow for the kids so we must
1257 * protect against corruption of the list of siblings. We first build
1258 * a list of HWNDs representing all the kids.
1260 pChild = WIN_LockWndPtr(pWnd->child);
1261 while( pChild )
1263 nKidCount++;
1264 WIN_UpdateWndPtr(&pChild,pChild->next);
1268 * If there are no kids, we're done.
1270 if (nKidCount==0)
1271 return;
1273 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1276 * Sanity check
1278 if (pWndArray==NULL)
1279 return;
1282 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1283 * call, our linked list of siblings should be safe.
1285 nKidCount = 0;
1286 pChild = WIN_LockWndPtr(pWnd->child);
1287 while( pChild )
1289 pWndArray[nKidCount] = pChild->hwndSelf;
1290 nKidCount++;
1291 WIN_UpdateWndPtr(&pChild,pChild->next);
1295 * Now that we have a list, go through that list again and send the destroy
1296 * message to those windows. We are using the HWND to retrieve the
1297 * WND pointer so we are effectively checking that all the kid windows are
1298 * still valid before sending the message.
1300 while (nKidCount>0)
1302 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1304 if (pChild!=NULL)
1306 WIN_SendDestroyMsg( pChild );
1307 WIN_ReleaseWndPtr(pChild);
1312 * Cleanup
1314 HeapFree(GetProcessHeap(), 0, pWndArray);
1315 WIN_CheckFocus(pWnd);
1317 else
1318 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1322 /***********************************************************************
1323 * DestroyWindow16 (USER.53)
1325 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1327 return DestroyWindow(hwnd);
1331 /***********************************************************************
1332 * DestroyWindow (USER32.135)
1334 BOOL WINAPI DestroyWindow( HWND hwnd )
1336 WND * wndPtr;
1337 BOOL retvalue;
1339 TRACE("(%04x)\n", hwnd);
1341 /* Initialization */
1343 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1344 if (wndPtr == pWndDesktop)
1346 retvalue = FALSE; /* Can't destroy desktop */
1347 goto end;
1350 /* Call hooks */
1352 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1354 retvalue = FALSE;
1355 goto end;
1358 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1360 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1361 /* FIXME: clean up palette - see "Internals" p.352 */
1364 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1365 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1367 /* Notify the parent window only */
1368 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1369 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1370 if( !IsWindow(hwnd) )
1372 retvalue = TRUE;
1373 goto end;
1377 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1379 /* Hide the window */
1381 if (wndPtr->dwStyle & WS_VISIBLE)
1383 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1384 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1385 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1386 if (!IsWindow(hwnd))
1388 retvalue = TRUE;
1389 goto end;
1393 /* Recursively destroy owned windows */
1395 if( !(wndPtr->dwStyle & WS_CHILD) )
1397 /* make sure top menu popup doesn't get destroyed */
1398 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1400 for (;;)
1402 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1403 while (siblingPtr)
1405 if (siblingPtr->owner == wndPtr)
1407 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1408 break;
1409 else
1410 siblingPtr->owner = NULL;
1412 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1414 if (siblingPtr)
1416 DestroyWindow( siblingPtr->hwndSelf );
1417 WIN_ReleaseWndPtr(siblingPtr);
1419 else break;
1422 if( !Options.managed || EVENT_CheckFocus() )
1423 WINPOS_ActivateOtherWindow(wndPtr);
1425 if( wndPtr->owner &&
1426 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1427 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1430 /* Send destroy messages */
1432 WIN_SendDestroyMsg( wndPtr );
1433 if (!IsWindow(hwnd))
1435 retvalue = TRUE;
1436 goto end;
1439 /* Unlink now so we won't bother with the children later on */
1441 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1443 /* Destroy the window storage */
1445 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1446 retvalue = TRUE;
1447 end:
1448 WIN_ReleaseWndPtr(wndPtr);
1449 return retvalue;
1453 /***********************************************************************
1454 * CloseWindow16 (USER.43)
1456 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1458 return CloseWindow( hwnd );
1462 /***********************************************************************
1463 * CloseWindow (USER32.56)
1465 BOOL WINAPI CloseWindow( HWND hwnd )
1467 WND * wndPtr = WIN_FindWndPtr( hwnd );
1468 BOOL retvalue;
1470 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1472 retvalue = FALSE;
1473 goto end;
1475 ShowWindow( hwnd, SW_MINIMIZE );
1476 retvalue = TRUE;
1477 end:
1478 WIN_ReleaseWndPtr(wndPtr);
1479 return retvalue;
1484 /***********************************************************************
1485 * OpenIcon16 (USER.44)
1487 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1489 return OpenIcon( hwnd );
1493 /***********************************************************************
1494 * OpenIcon (USER32.410)
1496 BOOL WINAPI OpenIcon( HWND hwnd )
1498 if (!IsIconic( hwnd )) return FALSE;
1499 ShowWindow( hwnd, SW_SHOWNORMAL );
1500 return TRUE;
1504 /***********************************************************************
1505 * WIN_FindWindow
1507 * Implementation of FindWindow() and FindWindowEx().
1509 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1510 LPCWSTR title )
1512 WND *pWnd;
1513 HWND retvalue;
1515 if (child)
1517 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1518 if (parent)
1520 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1522 retvalue = 0;
1523 goto end;
1526 else if (pWnd->parent != pWndDesktop)
1528 retvalue = 0;
1529 goto end;
1531 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1533 else
1535 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1537 retvalue = 0;
1538 goto end;
1540 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1542 if (!pWnd)
1544 retvalue = 0;
1545 goto end;
1548 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1550 if (className && (pWnd->class->atomName != className))
1551 continue; /* Not the right class */
1553 /* Now check the title */
1555 if (!title)
1557 retvalue = pWnd->hwndSelf;
1558 goto end;
1560 if (pWnd->text && !strcmpW( pWnd->text, title ))
1562 retvalue = pWnd->hwndSelf;
1563 goto end;
1566 retvalue = 0;
1567 end:
1568 WIN_ReleaseWndPtr(pWnd);
1569 return retvalue;
1574 /***********************************************************************
1575 * FindWindow16 (USER.50)
1577 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1579 return FindWindowA( className, title );
1583 /***********************************************************************
1584 * FindWindowEx16 (USER.427)
1586 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1588 return FindWindowExA( parent, child, className, title );
1592 /***********************************************************************
1593 * FindWindowA (USER32.198)
1595 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1597 HWND ret = FindWindowExA( 0, 0, className, title );
1598 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1599 return ret;
1603 /***********************************************************************
1604 * FindWindowExA (USER32.199)
1606 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1607 LPCSTR className, LPCSTR title )
1609 ATOM atom = 0;
1610 LPWSTR buffer;
1611 HWND hwnd;
1613 if (className)
1615 /* If the atom doesn't exist, then no class */
1616 /* with this name exists either. */
1617 if (!(atom = GlobalFindAtomA( className )))
1619 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1620 return 0;
1624 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1625 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1626 HeapFree( GetProcessHeap(), 0, buffer );
1627 return hwnd;
1631 /***********************************************************************
1632 * FindWindowExW (USER32.200)
1634 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1635 LPCWSTR className, LPCWSTR title )
1637 ATOM atom = 0;
1639 if (className)
1641 /* If the atom doesn't exist, then no class */
1642 /* with this name exists either. */
1643 if (!(atom = GlobalFindAtomW( className )))
1645 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1646 return 0;
1649 return WIN_FindWindow( parent, child, atom, title );
1653 /***********************************************************************
1654 * FindWindowW (USER32.201)
1656 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1658 return FindWindowExW( 0, 0, className, title );
1662 /**********************************************************************
1663 * WIN_GetDesktop
1664 * returns a locked pointer
1666 WND *WIN_GetDesktop(void)
1668 return WIN_LockWndPtr(pWndDesktop);
1670 /**********************************************************************
1671 * WIN_ReleaseDesktop
1672 * unlock the desktop pointer
1674 void WIN_ReleaseDesktop(void)
1676 WIN_ReleaseWndPtr(pWndDesktop);
1680 /**********************************************************************
1681 * GetDesktopWindow16 (USER.286)
1683 HWND16 WINAPI GetDesktopWindow16(void)
1685 return (HWND16)pWndDesktop->hwndSelf;
1689 /**********************************************************************
1690 * GetDesktopWindow (USER32.232)
1692 HWND WINAPI GetDesktopWindow(void)
1694 if (pWndDesktop) return pWndDesktop->hwndSelf;
1695 ERR( "You need the -desktop option when running with native USER\n" );
1696 ExitProcess(1);
1697 return 0;
1701 /**********************************************************************
1702 * GetDesktopHwnd (USER.278)
1704 * Exactly the same thing as GetDesktopWindow(), but not documented.
1705 * Don't ask me why...
1707 HWND16 WINAPI GetDesktopHwnd16(void)
1709 return (HWND16)pWndDesktop->hwndSelf;
1713 /*******************************************************************
1714 * EnableWindow16 (USER.34)
1716 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1718 return EnableWindow( hwnd, enable );
1722 /*******************************************************************
1723 * EnableWindow (USER32.172)
1725 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1727 WND *wndPtr;
1728 BOOL retvalue;
1730 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1732 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1733 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1735 /* Enable window */
1736 wndPtr->dwStyle &= ~WS_DISABLED;
1738 if( wndPtr->flags & WIN_NATIVE )
1739 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1741 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1742 retvalue = TRUE;
1743 goto end;
1745 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1747 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1749 /* Disable window */
1750 wndPtr->dwStyle |= WS_DISABLED;
1752 if( wndPtr->flags & WIN_NATIVE )
1753 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1755 if (hwnd == GetFocus())
1757 SetFocus( 0 ); /* A disabled window can't have the focus */
1759 if (hwnd == GetCapture())
1761 ReleaseCapture(); /* A disabled window can't capture the mouse */
1763 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1764 retvalue = FALSE;
1765 goto end;
1767 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1768 end:
1769 WIN_ReleaseWndPtr(wndPtr);
1770 return retvalue;
1774 /***********************************************************************
1775 * IsWindowEnabled16 (USER.35)
1777 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1779 return IsWindowEnabled(hWnd);
1783 /***********************************************************************
1784 * IsWindowEnabled (USER32.349)
1786 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1788 WND * wndPtr;
1789 BOOL retvalue;
1791 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1792 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1793 WIN_ReleaseWndPtr(wndPtr);
1794 return retvalue;
1799 /***********************************************************************
1800 * IsWindowUnicode (USER32.350)
1802 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1804 WND * wndPtr;
1805 BOOL retvalue;
1807 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1808 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1809 WIN_ReleaseWndPtr(wndPtr);
1810 return retvalue;
1814 /**********************************************************************
1815 * GetWindowWord16 (USER.133)
1817 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1819 return GetWindowWord( hwnd, offset );
1823 /**********************************************************************
1824 * GetWindowWord (USER32.314)
1826 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1828 WORD retvalue;
1829 WND * wndPtr = WIN_FindWndPtr( hwnd );
1830 if (!wndPtr) return 0;
1831 if (offset >= 0)
1833 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1835 WARN("Invalid offset %d\n", offset );
1836 retvalue = 0;
1837 goto end;
1839 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1840 goto end;
1842 switch(offset)
1844 case GWW_ID:
1845 if (HIWORD(wndPtr->wIDmenu))
1846 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1847 wndPtr->wIDmenu);
1848 retvalue = (WORD)wndPtr->wIDmenu;
1849 goto end;
1850 case GWW_HWNDPARENT:
1851 retvalue = GetParent(hwnd);
1852 goto end;
1853 case GWW_HINSTANCE:
1854 if (HIWORD(wndPtr->hInstance))
1855 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1856 wndPtr->hInstance);
1857 retvalue = (WORD)wndPtr->hInstance;
1858 goto end;
1859 default:
1860 WARN("Invalid offset %d\n", offset );
1861 retvalue = 0;
1862 goto end;
1864 end:
1865 WIN_ReleaseWndPtr(wndPtr);
1866 return retvalue;
1869 /**********************************************************************
1870 * SetWindowWord16 (USER.134)
1872 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1874 return SetWindowWord( hwnd, offset, newval );
1878 /**********************************************************************
1879 * SetWindowWord (USER32.524)
1881 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1883 WORD *ptr, retval;
1884 WND * wndPtr = WIN_FindWndPtr( hwnd );
1885 if (!wndPtr) return 0;
1886 if (offset >= 0)
1888 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1890 WARN("Invalid offset %d\n", offset );
1891 retval = 0;
1892 goto end;
1894 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1896 else switch(offset)
1898 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1899 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1900 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1901 goto end;
1902 default:
1903 WARN("Invalid offset %d\n", offset );
1904 retval = 0;
1905 goto end;
1907 retval = *ptr;
1908 *ptr = newval;
1909 end:
1910 WIN_ReleaseWndPtr(wndPtr);
1911 return retval;
1915 /**********************************************************************
1916 * WIN_GetWindowLong
1918 * Helper function for GetWindowLong().
1920 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1922 LONG retvalue;
1923 WND * wndPtr = WIN_FindWndPtr( hwnd );
1924 if (!wndPtr) return 0;
1925 if (offset >= 0)
1927 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1929 WARN("Invalid offset %d\n", offset );
1930 retvalue = 0;
1931 goto end;
1933 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1934 /* Special case for dialog window procedure */
1935 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1937 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1938 goto end;
1940 goto end;
1942 switch(offset)
1944 case GWL_USERDATA: retvalue = wndPtr->userdata;
1945 goto end;
1946 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1947 goto end;
1948 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1949 goto end;
1950 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1951 goto end;
1952 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1953 type );
1954 goto end;
1955 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1956 goto end;
1957 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1958 goto end;
1959 default:
1960 WARN("Unknown offset %d\n", offset );
1962 retvalue = 0;
1963 end:
1964 WIN_ReleaseWndPtr(wndPtr);
1965 return retvalue;
1969 /**********************************************************************
1970 * WIN_SetWindowLong
1972 * Helper function for SetWindowLong().
1974 * 0 is the failure code. However, in the case of failure SetLastError
1975 * must be set to distinguish between a 0 return value and a failure.
1977 * FIXME: The error values for SetLastError may not be right. Can
1978 * someone check with the real thing?
1980 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1981 WINDOWPROCTYPE type )
1983 LONG *ptr, retval;
1984 WND * wndPtr = WIN_FindWndPtr( hwnd );
1985 STYLESTRUCT style;
1987 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1989 if (!wndPtr)
1991 /* Is this the right error? */
1992 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1993 return 0;
1996 if (offset >= 0)
1998 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
2000 WARN("Invalid offset %d\n", offset );
2002 /* Is this the right error? */
2003 SetLastError( ERROR_OUTOFMEMORY );
2005 retval = 0;
2006 goto end;
2008 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2009 /* Special case for dialog window procedure */
2010 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2012 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2013 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2014 type, WIN_PROC_WINDOW );
2015 goto end;
2018 else switch(offset)
2020 case GWL_ID:
2021 ptr = (DWORD*)&wndPtr->wIDmenu;
2022 break;
2023 case GWL_HINSTANCE:
2024 retval = SetWindowWord( hwnd, offset, newval );
2025 goto end;
2026 case GWL_WNDPROC:
2027 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2028 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2029 type, WIN_PROC_WINDOW );
2030 goto end;
2031 case GWL_STYLE:
2032 style.styleOld = wndPtr->dwStyle;
2033 newval &= ~(WS_CHILD); /* this bit can't be changed this way */
2034 style.styleNew = newval | (style.styleOld & (WS_CHILD));
2036 if (wndPtr->flags & WIN_ISWIN32)
2037 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2038 wndPtr->dwStyle = style.styleNew;
2039 if (wndPtr->flags & WIN_ISWIN32)
2040 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2041 retval = style.styleOld;
2042 goto end;
2044 case GWL_USERDATA:
2045 ptr = &wndPtr->userdata;
2046 break;
2047 case GWL_EXSTYLE:
2048 style.styleOld = wndPtr->dwExStyle;
2049 style.styleNew = newval;
2050 if (wndPtr->flags & WIN_ISWIN32)
2051 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2052 wndPtr->dwExStyle = newval;
2053 if (wndPtr->flags & WIN_ISWIN32)
2054 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2055 retval = style.styleOld;
2056 goto end;
2058 default:
2059 WARN("Invalid offset %d\n", offset );
2061 /* Don't think this is right error but it should do */
2062 SetLastError( ERROR_OUTOFMEMORY );
2064 retval = 0;
2065 goto end;
2067 retval = *ptr;
2068 *ptr = newval;
2069 end:
2070 WIN_ReleaseWndPtr(wndPtr);
2071 return retval;
2075 /**********************************************************************
2076 * GetWindowLong16 (USER.135)
2078 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2080 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2084 /**********************************************************************
2085 * GetWindowLongA (USER32.305)
2087 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2089 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2093 /**********************************************************************
2094 * GetWindowLongW (USER32.306)
2096 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2098 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2102 /**********************************************************************
2103 * SetWindowLong16 (USER.136)
2105 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2107 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2111 /**********************************************************************
2112 * SetWindowLongA (USER32.517)
2114 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2116 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2120 /**********************************************************************
2121 * SetWindowLongW (USER32.518) Set window attribute
2123 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2124 * value in a window's extra memory.
2126 * The _hwnd_ parameter specifies the window. is the handle to a
2127 * window that has extra memory. The _newval_ parameter contains the
2128 * new attribute or extra memory value. If positive, the _offset_
2129 * parameter is the byte-addressed location in the window's extra
2130 * memory to set. If negative, _offset_ specifies the window
2131 * attribute to set, and should be one of the following values:
2133 * GWL_EXSTYLE The window's extended window style
2135 * GWL_STYLE The window's window style.
2137 * GWL_WNDPROC Pointer to the window's window procedure.
2139 * GWL_HINSTANCE The window's pplication instance handle.
2141 * GWL_ID The window's identifier.
2143 * GWL_USERDATA The window's user-specified data.
2145 * If the window is a dialog box, the _offset_ parameter can be one of
2146 * the following values:
2148 * DWL_DLGPROC The address of the window's dialog box procedure.
2150 * DWL_MSGRESULT The return value of a message
2151 * that the dialog box procedure processed.
2153 * DWL_USER Application specific information.
2155 * RETURNS
2157 * If successful, returns the previous value located at _offset_. Otherwise,
2158 * returns 0.
2160 * NOTES
2162 * Extra memory for a window class is specified by a nonzero cbWndExtra
2163 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2164 * time of class creation.
2166 * Using GWL_WNDPROC to set a new window procedure effectively creates
2167 * a window subclass. Use CallWindowProc() in the new windows procedure
2168 * to pass messages to the superclass's window procedure.
2170 * The user data is reserved for use by the application which created
2171 * the window.
2173 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2174 * instead, call the EnableWindow() function to change the window's
2175 * disabled state.
2177 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2178 * SetParent() instead.
2180 * Win95:
2181 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2182 * it sends WM_STYLECHANGING before changing the settings
2183 * and WM_STYLECHANGED afterwards.
2184 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2186 * BUGS
2188 * GWL_STYLE does not dispatch WM_STYLE... messages.
2190 * CONFORMANCE
2192 * ECMA-234, Win32
2195 LONG WINAPI SetWindowLongW(
2196 HWND hwnd, /* window to alter */
2197 INT offset, /* offset, in bytes, of location to alter */
2198 LONG newval /* new value of location */
2200 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2204 /*******************************************************************
2205 * GetWindowText16 (USER.36)
2207 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2209 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2213 /*******************************************************************
2214 * GetWindowTextA (USER32.309)
2216 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2218 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2219 (LPARAM)lpString );
2222 /*******************************************************************
2223 * InternalGetWindowText (USER32.326)
2225 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2227 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2228 return GetWindowTextW(hwnd,lpString,nMaxCount);
2232 /*******************************************************************
2233 * GetWindowTextW (USER32.312)
2235 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2237 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2238 (LPARAM)lpString );
2242 /*******************************************************************
2243 * SetWindowText16 (USER.37)
2245 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2247 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2251 /*******************************************************************
2252 * SetWindowTextA (USER32.521)
2254 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2256 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2260 /*******************************************************************
2261 * SetWindowTextW (USER32.523)
2263 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2265 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2269 /*******************************************************************
2270 * GetWindowTextLength16 (USER.38)
2272 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2274 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2278 /*******************************************************************
2279 * GetWindowTextLengthA (USER32.310)
2281 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2283 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2286 /*******************************************************************
2287 * GetWindowTextLengthW (USER32.311)
2289 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2291 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2295 /*******************************************************************
2296 * IsWindow16 (USER.47)
2298 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2300 CURRENT_STACK16->es = USER_HeapSel;
2301 return IsWindow( hwnd );
2305 /*******************************************************************
2306 * IsWindow (USER32.348)
2308 BOOL WINAPI IsWindow( HWND hwnd )
2310 WND * wndPtr;
2311 BOOL retvalue;
2313 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2314 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2315 WIN_ReleaseWndPtr(wndPtr);
2316 return retvalue;
2321 /*****************************************************************
2322 * GetParent16 (USER.46)
2324 HWND16 WINAPI GetParent16( HWND16 hwnd )
2326 return (HWND16)GetParent( hwnd );
2330 /*****************************************************************
2331 * GetParent (USER32.278)
2333 HWND WINAPI GetParent( HWND hwnd )
2335 WND *wndPtr;
2336 HWND retvalue = 0;
2338 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2339 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2340 goto end;
2342 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2343 if (wndPtr)
2344 retvalue = wndPtr->hwndSelf;
2346 end:
2347 WIN_ReleaseWndPtr(wndPtr);
2348 return retvalue;
2352 /*****************************************************************
2353 * WIN_GetTopParent
2355 * Get the top-level parent for a child window.
2356 * returns a locked pointer
2358 WND* WIN_GetTopParentPtr( WND* pWnd )
2360 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2362 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2364 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2366 return tmpWnd;
2369 /*****************************************************************
2370 * WIN_GetTopParent
2372 * Get the top-level parent for a child window.
2374 HWND WIN_GetTopParent( HWND hwnd )
2376 HWND retvalue;
2377 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2378 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2380 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2381 WIN_ReleaseWndPtr(tmpPtr);
2382 WIN_ReleaseWndPtr(wndPtr);
2383 return retvalue;
2387 /*****************************************************************
2388 * SetParent16 (USER.233)
2390 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2392 return SetParent( hwndChild, hwndNewParent );
2396 /*****************************************************************
2397 * SetParent (USER32.495)
2399 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2401 WND *wndPtr;
2402 DWORD dwStyle;
2403 WND *pWndNewParent;
2404 WND *pWndOldParent;
2405 HWND retvalue;
2408 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2410 dwStyle = wndPtr->dwStyle;
2412 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2413 : WIN_LockWndPtr(pWndDesktop);
2415 /* Windows hides the window first, then shows it again
2416 * including the WM_SHOWWINDOW messages and all */
2417 if (dwStyle & WS_VISIBLE)
2418 ShowWindow( hwndChild, SW_HIDE );
2420 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2422 /* SetParent additionally needs to make hwndChild the topmost window
2423 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2424 WM_WINDOWPOSCHANGED notification messages.
2426 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2427 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2428 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2429 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2431 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2433 WIN_ReleaseWndPtr(pWndOldParent);
2434 WIN_ReleaseWndPtr(pWndNewParent);
2435 WIN_ReleaseWndPtr(wndPtr);
2437 return retvalue;
2441 /*******************************************************************
2442 * IsChild16 (USER.48)
2444 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2446 return IsChild(parent,child);
2450 /*******************************************************************
2451 * IsChild (USER32.339)
2453 BOOL WINAPI IsChild( HWND parent, HWND child )
2455 WND * wndPtr = WIN_FindWndPtr( child );
2456 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2458 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2459 if (wndPtr->hwndSelf == parent)
2461 WIN_ReleaseWndPtr(wndPtr);
2462 return TRUE;
2465 WIN_ReleaseWndPtr(wndPtr);
2466 return FALSE;
2470 /***********************************************************************
2471 * IsWindowVisible16 (USER.49)
2473 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2475 return IsWindowVisible(hwnd);
2479 /***********************************************************************
2480 * IsWindowVisible (USER32.351)
2482 BOOL WINAPI IsWindowVisible( HWND hwnd )
2484 BOOL retval;
2485 WND *wndPtr = WIN_FindWndPtr( hwnd );
2486 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2488 if (!(wndPtr->dwStyle & WS_VISIBLE))
2490 WIN_ReleaseWndPtr(wndPtr);
2491 return FALSE;
2493 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2495 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2496 WIN_ReleaseWndPtr(wndPtr);
2497 return retval;
2502 /***********************************************************************
2503 * WIN_IsWindowDrawable
2505 * hwnd is drawable when it is visible, all parents are not
2506 * minimized, and it is itself not minimized unless we are
2507 * trying to draw its default class icon.
2509 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2511 if( (wnd->dwStyle & WS_MINIMIZE &&
2512 icon && wnd->class->hIcon) ||
2513 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2514 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2515 if( wnd->dwStyle & WS_MINIMIZE ||
2516 !(wnd->dwStyle & WS_VISIBLE) ) break;
2517 return (wnd == NULL);
2521 /*******************************************************************
2522 * GetTopWindow16 (USER.229)
2524 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2526 return GetTopWindow(hwnd);
2530 /*******************************************************************
2531 * GetTopWindow (USER.229)
2533 HWND WINAPI GetTopWindow( HWND hwnd )
2535 HWND retval = 0;
2536 WND * wndPtr = (hwnd) ?
2537 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2539 if (wndPtr && wndPtr->child)
2540 retval = wndPtr->child->hwndSelf;
2542 WIN_ReleaseWndPtr(wndPtr);
2543 return retval;
2547 /*******************************************************************
2548 * GetWindow16 (USER.262)
2550 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2552 return GetWindow( hwnd,rel );
2556 /*******************************************************************
2557 * GetWindow (USER32.302)
2559 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2561 HWND retval;
2563 WND * wndPtr = WIN_FindWndPtr( hwnd );
2564 if (!wndPtr) return 0;
2565 switch(rel)
2567 case GW_HWNDFIRST:
2568 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2569 goto end;
2571 case GW_HWNDLAST:
2572 if (!wndPtr->parent)
2574 retval = 0; /* Desktop window */
2575 goto end;
2577 while (wndPtr->next)
2579 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2581 retval = wndPtr->hwndSelf;
2582 goto end;
2584 case GW_HWNDNEXT:
2585 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2586 goto end;
2588 case GW_HWNDPREV:
2589 if (!wndPtr->parent)
2591 retval = 0; /* Desktop window */
2592 goto end;
2594 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2595 if (wndPtr->hwndSelf == hwnd)
2597 retval = 0; /* First in list */
2598 goto end;
2600 while (wndPtr->next)
2602 if (wndPtr->next->hwndSelf == hwnd)
2604 retval = wndPtr->hwndSelf;
2605 goto end;
2607 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2609 retval = 0;
2610 goto end;
2612 case GW_OWNER:
2613 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2614 goto end;
2616 case GW_CHILD:
2617 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2618 goto end;
2620 retval = 0;
2621 end:
2622 WIN_ReleaseWndPtr(wndPtr);
2623 return retval;
2627 /*******************************************************************
2628 * GetNextWindow16 (USER.230)
2630 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2632 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2633 return GetWindow16( hwnd, flag );
2636 /***********************************************************************
2637 * WIN_InternalShowOwnedPopups
2639 * Internal version of ShowOwnedPopups; Wine functions should use this
2640 * to avoid interfering with application calls to ShowOwnedPopups
2641 * and to make sure the application can't prevent showing/hiding.
2643 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2647 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2649 INT totalChild=0, count=0;
2651 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2653 if (!pWnd) return TRUE;
2656 * Show windows Lowest first, Highest last to preserve Z-Order
2658 for (count = totalChild-1 ; count >=0; count--)
2660 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2662 if (fShow)
2664 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2665 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2668 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2670 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2671 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2674 else
2676 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2677 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2678 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2681 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2683 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2684 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2685 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2690 WIN_ReleaseDesktop();
2691 WIN_ReleaseWinArray(pWnd);
2693 return TRUE;
2696 /*******************************************************************
2697 * ShowOwnedPopups16 (USER.265)
2699 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2701 ShowOwnedPopups( owner, fShow );
2705 /*******************************************************************
2706 * ShowOwnedPopups (USER32.531)
2708 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2710 UINT totalChild=0, count=0;
2712 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2714 if (!pWnd) return TRUE;
2716 for (; count < totalChild; count++)
2718 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2720 if (fShow)
2722 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2725 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2726 * regardless of the state of the owner
2728 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2729 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2732 else
2734 if (IsWindowVisible(pWnd[count]->hwndSelf))
2737 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2738 * regardless of the state of the owner
2740 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2741 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2747 WIN_ReleaseDesktop();
2748 WIN_ReleaseWinArray(pWnd);
2749 return TRUE;
2753 /*******************************************************************
2754 * GetLastActivePopup16 (USER.287)
2756 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2758 return GetLastActivePopup( hwnd );
2761 /*******************************************************************
2762 * GetLastActivePopup (USER32.256)
2764 HWND WINAPI GetLastActivePopup( HWND hwnd )
2766 HWND retval;
2767 WND *wndPtr =WIN_FindWndPtr(hwnd);
2768 if (!wndPtr) return hwnd;
2769 retval = wndPtr->hwndLastActive;
2770 WIN_ReleaseWndPtr(wndPtr);
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 = (LPDRAGINFO16) PTR_SEG_TO_LIN(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 = LoadCursor16(0, IDC_BUMMER16);
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);