Disable DONT_RESOLVE_DLL_REFERENCES for builtin dlls.
[wine/multimedia.git] / windows / win.c
blob9ba000ead77e540e6840bad45a52474c607c9f98
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 "thread.h"
25 #include "winerror.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(win);
30 DECLARE_DEBUG_CHANNEL(msg);
32 /**********************************************************************/
34 WND_DRIVER *WND_Driver = NULL;
36 /* Desktop window */
37 static WND *pWndDesktop = NULL;
39 static HWND hwndSysModal = 0;
41 static WORD wDragWidth = 4;
42 static WORD wDragHeight= 3;
44 /* thread safeness */
45 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
47 /***********************************************************************
48 * WIN_LockWnds
50 * Locks access to all WND structures for thread safeness
52 void WIN_LockWnds( void )
54 _EnterSysLevel( &WIN_SysLevel );
57 /***********************************************************************
58 * WIN_UnlockWnds
60 * Unlocks access to all WND structures
62 void WIN_UnlockWnds( void )
64 _LeaveSysLevel( &WIN_SysLevel );
67 /***********************************************************************
68 * WIN_SuspendWndsLock
70 * Suspend the lock on WND structures.
71 * Returns the number of locks suspended
73 int WIN_SuspendWndsLock( void )
75 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
76 int count = isuspendedLocks;
78 while ( count-- > 0 )
79 _LeaveSysLevel( &WIN_SysLevel );
81 return isuspendedLocks;
84 /***********************************************************************
85 * WIN_RestoreWndsLock
87 * Restore the suspended locks on WND structures
89 void WIN_RestoreWndsLock( int ipreviousLocks )
91 while ( ipreviousLocks-- > 0 )
92 _EnterSysLevel( &WIN_SysLevel );
95 /***********************************************************************
96 * WIN_FindWndPtr
98 * Return a pointer to the WND structure corresponding to a HWND.
100 WND * WIN_FindWndPtr( HWND hwnd )
102 WND * ptr;
104 if (!hwnd || HIWORD(hwnd)) goto error2;
105 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
106 /* Lock all WND structures for thread safeness*/
107 WIN_LockWnds();
108 /*and increment destruction monitoring*/
109 ptr->irefCount++;
111 if (ptr->dwMagic != WND_MAGIC) goto error;
112 if (ptr->hwndSelf != hwnd)
114 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
115 goto error;
117 /* returns a locked pointer */
118 return ptr;
119 error:
120 /* Unlock all WND structures for thread safeness*/
121 WIN_UnlockWnds();
122 /* and decrement destruction monitoring value */
123 ptr->irefCount--;
125 error2:
126 if ( hwnd!=0 )
127 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
128 return NULL;
131 /***********************************************************************
132 * WIN_LockWndPtr
134 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
135 * but by initWndPtr;
136 * Returns the locked initialisation pointer
138 WND *WIN_LockWndPtr(WND *initWndPtr)
140 if(!initWndPtr) return 0;
142 /* Lock all WND structures for thread safeness*/
143 WIN_LockWnds();
144 /*and increment destruction monitoring*/
145 initWndPtr->irefCount++;
147 return initWndPtr;
151 /***********************************************************************
152 * WIN_ReleaseWndPtr
154 * Release the pointer to the WND structure.
156 void WIN_ReleaseWndPtr(WND *wndPtr)
158 if(!wndPtr) return;
160 /*Decrement destruction monitoring value*/
161 wndPtr->irefCount--;
162 /* Check if it's time to release the memory*/
163 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
165 /* Release memory */
166 USER_HEAP_FREE( wndPtr->hwndSelf);
167 wndPtr->hwndSelf = 0;
169 else if(wndPtr->irefCount < 0)
171 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
172 ERR("forgot a Lock on %p somewhere\n",wndPtr);
174 /*unlock all WND structures for thread safeness*/
175 WIN_UnlockWnds();
178 /***********************************************************************
179 * WIN_UpdateWndPtr
181 * Updates the value of oldPtr to newPtr.
183 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
185 WND *tmpWnd = NULL;
187 tmpWnd = WIN_LockWndPtr(newPtr);
188 WIN_ReleaseWndPtr(*oldPtr);
189 *oldPtr = tmpWnd;
193 /***********************************************************************
194 * WIN_DumpWindow
196 * Dump the content of a window structure to stderr.
198 void WIN_DumpWindow( HWND hwnd )
200 WND *ptr;
201 char className[80];
202 int i;
204 if (!(ptr = WIN_FindWndPtr( hwnd )))
206 WARN("%04x is not a window handle\n", hwnd );
207 return;
210 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
211 strcpy( className, "#NULL#" );
213 TRACE("Window %04x (%p):\n", hwnd, ptr );
214 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
215 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
216 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
217 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
218 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
219 ptr->next, ptr->child, ptr->parent, ptr->owner,
220 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
221 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
222 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
223 ptr->text ? debugstr_w(ptr->text) : "",
224 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
225 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
226 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
227 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
229 if (ptr->cbWndExtra)
231 DPRINTF( "extra bytes:" );
232 for (i = 0; i < ptr->cbWndExtra; i++)
233 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
234 DPRINTF( "\n" );
236 DPRINTF( "\n" );
237 WIN_ReleaseWndPtr(ptr);
241 /***********************************************************************
242 * WIN_WalkWindows
244 * Walk the windows tree and print each window on stderr.
246 void WIN_WalkWindows( HWND hwnd, int indent )
248 WND *ptr;
249 char className[80];
251 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
253 if (!ptr)
255 WARN("Invalid window handle %04x\n", hwnd );
256 return;
259 if (!indent) /* first time around */
260 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
261 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
262 " Text");
264 while (ptr)
266 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
268 GetClassNameA( hwnd, className, sizeof(className) );
269 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
270 (DWORD)ptr, ptr->hmemTaskQ, className,
271 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
272 ptr->text ? debugstr_w(ptr->text) : "<null>");
274 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
275 WIN_UpdateWndPtr(&ptr,ptr->next);
281 /***********************************************************************
282 * WIN_UnlinkWindow
284 * Remove a window from the siblings linked list.
286 BOOL WIN_UnlinkWindow( HWND hwnd )
288 WND *wndPtr, **ppWnd;
289 BOOL ret = FALSE;
291 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
292 else if(!wndPtr->parent)
294 WIN_ReleaseWndPtr(wndPtr);
295 return FALSE;
298 ppWnd = &wndPtr->parent->child;
299 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
300 if (*ppWnd)
302 *ppWnd = wndPtr->next;
303 ret = TRUE;
305 WIN_ReleaseWndPtr(wndPtr);
306 return ret;
310 /***********************************************************************
311 * WIN_LinkWindow
313 * Insert a window into the siblings linked list.
314 * The window is inserted after the specified window, which can also
315 * be specified as HWND_TOP or HWND_BOTTOM.
317 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
319 WND *wndPtr, **ppWnd;
321 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
322 else if(!wndPtr->parent)
324 WIN_ReleaseWndPtr(wndPtr);
325 return FALSE;
327 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
329 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
330 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
331 while (*ppWnd) ppWnd = &(*ppWnd)->next;
333 else /* Normal case */
335 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
336 if (!afterPtr)
338 WIN_ReleaseWndPtr(wndPtr);
339 return FALSE;
341 ppWnd = &afterPtr->next;
342 WIN_ReleaseWndPtr(afterPtr);
344 wndPtr->next = *ppWnd;
345 *ppWnd = wndPtr;
346 WIN_ReleaseWndPtr(wndPtr);
347 return TRUE;
351 /***********************************************************************
352 * WIN_FindWinToRepaint
354 * Find a window that needs repaint.
356 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
358 HWND hwndRet;
359 WND *pWnd;
361 /* Note: the desktop window never gets WM_PAINT messages
362 * The real reason why is because Windows DesktopWndProc
363 * does ValidateRgn inside WM_ERASEBKGND handler.
366 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
368 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
370 if (!(pWnd->dwStyle & WS_VISIBLE))
372 TRACE("skipping window %04x\n",
373 pWnd->hwndSelf );
375 else if ((pWnd->hmemTaskQ == hQueue) &&
376 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
377 break;
379 else if (pWnd->child )
380 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
382 WIN_ReleaseWndPtr(pWnd);
383 return hwndRet;
388 if(!pWnd)
390 return 0;
393 hwndRet = pWnd->hwndSelf;
395 /* look among siblings if we got a transparent window */
396 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
397 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
399 WIN_UpdateWndPtr(&pWnd,pWnd->next);
401 if (pWnd)
403 hwndRet = pWnd->hwndSelf;
404 WIN_ReleaseWndPtr(pWnd);
406 TRACE("found %04x\n",hwndRet);
407 return hwndRet;
411 /***********************************************************************
412 * WIN_DestroyWindow
414 * Destroy storage associated to a window. "Internals" p.358
415 * returns a locked wndPtr->next
417 static WND* WIN_DestroyWindow( WND* wndPtr )
419 HWND hwnd = wndPtr->hwndSelf;
420 WND *pWnd;
422 TRACE("%04x\n", wndPtr->hwndSelf );
424 /* free child windows */
425 WIN_LockWndPtr(wndPtr->child);
426 while ((pWnd = wndPtr->child))
428 wndPtr->child = WIN_DestroyWindow( pWnd );
429 WIN_ReleaseWndPtr(pWnd);
433 * Clear the update region to make sure no WM_PAINT messages will be
434 * generated for this window while processing the WM_NCDESTROY.
436 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
438 if (wndPtr->hrgnUpdate > 1)
439 DeleteObject( wndPtr->hrgnUpdate );
441 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
443 wndPtr->hrgnUpdate = 0;
447 * Send the WM_NCDESTROY to the window being destroyed.
449 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
451 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
453 WINPOS_CheckInternalPos( wndPtr );
454 if( hwnd == GetCapture()) ReleaseCapture();
456 /* free resources associated with the window */
458 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
459 PROPERTY_RemoveWindowProps( wndPtr );
461 wndPtr->dwMagic = 0; /* Mark it as invalid */
463 /* toss stale messages from the queue */
465 if( wndPtr->hmemTaskQ )
467 BOOL bPostQuit = FALSE;
468 WPARAM wQuitParam = 0;
469 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
470 QMSG *qmsg;
472 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
474 if( qmsg->msg.message == WM_QUIT )
476 bPostQuit = TRUE;
477 wQuitParam = qmsg->msg.wParam;
479 QUEUE_RemoveMsg(msgQ, qmsg);
482 QUEUE_Unlock(msgQ);
484 /* repost WM_QUIT to make sure this app exits its message loop */
485 if( bPostQuit ) PostQuitMessage(wQuitParam);
486 wndPtr->hmemTaskQ = 0;
489 if (!(wndPtr->dwStyle & WS_CHILD))
490 if (wndPtr->wIDmenu)
492 DestroyMenu( wndPtr->wIDmenu );
493 wndPtr->wIDmenu = 0;
495 if (wndPtr->hSysMenu)
497 DestroyMenu( wndPtr->hSysMenu );
498 wndPtr->hSysMenu = 0;
500 wndPtr->pDriver->pDestroyWindow( wndPtr );
501 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
502 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
503 CLASS_RemoveWindow( wndPtr->class );
504 wndPtr->class = NULL;
506 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
508 wndPtr->pDriver->pFinalize(wndPtr);
510 return pWnd;
513 /***********************************************************************
514 * WIN_ResetQueueWindows
516 * Reset the queue of all the children of a given window.
517 * Return TRUE if something was done.
519 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
521 BOOL ret = FALSE;
523 if (hNew) /* Set a new queue */
525 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
527 if (wnd->hmemTaskQ == hQueue)
529 wnd->hmemTaskQ = hNew;
530 ret = TRUE;
532 if (wnd->child)
534 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
538 else /* Queue is being destroyed */
540 while (wnd->child)
542 WND *tmp = WIN_LockWndPtr(wnd->child);
543 WND *tmp2;
544 ret = FALSE;
545 while (tmp)
547 if (tmp->hmemTaskQ == hQueue)
549 DestroyWindow( tmp->hwndSelf );
550 ret = TRUE;
551 break;
553 tmp2 = WIN_LockWndPtr(tmp->child);
554 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
555 ret = TRUE;
556 else
558 WIN_UpdateWndPtr(&tmp,tmp->next);
560 WIN_ReleaseWndPtr(tmp2);
562 WIN_ReleaseWndPtr(tmp);
563 if (!ret) break;
566 return ret;
569 /***********************************************************************
570 * WIN_CreateDesktopWindow
572 * Create the desktop window.
574 BOOL WIN_CreateDesktopWindow(void)
576 struct tagCLASS *class;
577 HWND hwndDesktop;
578 INT wndExtra;
579 DWORD clsStyle;
580 WNDPROC winproc;
581 DCE *dce;
583 TRACE("Creating desktop window\n");
586 if (!WINPOS_CreateInternalPosAtom() ||
587 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
588 &wndExtra, &winproc, &clsStyle, &dce )))
589 return FALSE;
591 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
592 if (!hwndDesktop) return FALSE;
593 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
595 pWndDesktop->pDriver = WND_Driver;
596 pWndDesktop->pDriver->pInitialize(pWndDesktop);
598 pWndDesktop->next = NULL;
599 pWndDesktop->child = NULL;
600 pWndDesktop->parent = NULL;
601 pWndDesktop->owner = NULL;
602 pWndDesktop->class = class;
603 pWndDesktop->dwMagic = WND_MAGIC;
604 pWndDesktop->hwndSelf = hwndDesktop;
605 pWndDesktop->hInstance = 0;
606 pWndDesktop->rectWindow.left = 0;
607 pWndDesktop->rectWindow.top = 0;
608 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
609 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
610 pWndDesktop->rectClient = pWndDesktop->rectWindow;
611 pWndDesktop->text = NULL;
612 pWndDesktop->hmemTaskQ = GetFastQueue16();
613 pWndDesktop->hrgnUpdate = 0;
614 pWndDesktop->hwndLastActive = hwndDesktop;
615 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
616 WS_CLIPSIBLINGS;
617 pWndDesktop->dwExStyle = 0;
618 pWndDesktop->clsStyle = clsStyle;
619 pWndDesktop->dce = NULL;
620 pWndDesktop->pVScroll = NULL;
621 pWndDesktop->pHScroll = NULL;
622 pWndDesktop->pProp = NULL;
623 pWndDesktop->wIDmenu = 0;
624 pWndDesktop->helpContext = 0;
625 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
626 pWndDesktop->hSysMenu = 0;
627 pWndDesktop->userdata = 0;
628 pWndDesktop->winproc = winproc;
629 pWndDesktop->cbWndExtra = wndExtra;
630 pWndDesktop->irefCount = 0;
632 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop)) return FALSE;
634 SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
635 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
636 return TRUE;
640 /***********************************************************************
641 * WIN_FixCoordinates
643 * Fix the coordinates - Helper for WIN_CreateWindowEx.
644 * returns default show mode in sw.
645 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
647 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
649 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
650 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
652 if (cs->style & (WS_CHILD | WS_POPUP))
654 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
655 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
657 else /* overlapped window */
659 STARTUPINFOA info;
661 GetStartupInfoA( &info );
663 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
665 /* Never believe Microsoft's documentation... CreateWindowEx doc says
666 * that if an overlapped window is created with WS_VISIBLE style bit
667 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
668 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
669 * reveals that
671 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
672 * 2) it does not ignore the y parameter as the docs claim; instead, it
673 * uses it as second parameter to ShowWindow() unless y is either
674 * CW_USEDEFAULT or CW_USEDEFAULT16.
676 * The fact that we didn't do 2) caused bogus windows pop up when wine
677 * was running apps that were using this obscure feature. Example -
678 * calc.exe that comes with Win98 (only Win98, it's different from
679 * the one that comes with Win95 and NT)
681 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
682 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
683 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
686 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
688 if (info.dwFlags & STARTF_USESIZE)
690 cs->cx = info.dwXSize;
691 cs->cy = info.dwYSize;
693 else /* if no other hint from the app, pick 3/4 of the screen real estate */
695 RECT r;
696 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
697 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
698 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
705 /***********************************************************************
706 * WIN_CreateWindowEx
708 * Implementation of CreateWindowEx().
710 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
711 WINDOWPROCTYPE type )
713 INT sw = SW_SHOW;
714 struct tagCLASS *classPtr;
715 WND *wndPtr;
716 HWND retvalue;
717 HWND16 hwnd, hwndLinkAfter;
718 POINT maxSize, maxPos, minTrack, maxTrack;
719 INT wndExtra;
720 DWORD clsStyle;
721 WNDPROC winproc;
722 DCE *dce;
723 LRESULT CALLBACK (*localSend32)(HWND, UINT, WPARAM, LPARAM);
725 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
726 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
727 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
728 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
729 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
731 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
732 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
734 /* Find the parent window */
736 if (cs->hwndParent)
738 /* Make sure parent is valid */
739 if (!IsWindow( cs->hwndParent ))
741 WARN("Bad parent %04x\n", cs->hwndParent );
742 return 0;
744 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
745 WARN("No parent for child window\n" );
746 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
749 /* Find the window class */
750 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
751 &wndExtra, &winproc, &clsStyle, &dce )))
753 WARN("Bad class '%s'\n", cs->lpszClass );
754 return 0;
757 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
759 /* Create the window structure */
761 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
763 TRACE("out of memory\n" );
764 return 0;
767 /* Fill the window structure */
769 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
770 wndPtr->next = NULL;
771 wndPtr->child = NULL;
773 if ((cs->style & WS_CHILD) && cs->hwndParent)
775 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
776 wndPtr->owner = NULL;
777 WIN_ReleaseWndPtr(wndPtr->parent);
779 else
781 wndPtr->parent = pWndDesktop;
782 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
783 wndPtr->owner = NULL;
784 else
786 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
787 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
788 WIN_ReleaseWndPtr(wndPtr->owner);
789 WIN_ReleaseWndPtr(tmpWnd);
794 wndPtr->pDriver = wndPtr->parent->pDriver;
795 wndPtr->pDriver->pInitialize(wndPtr);
797 wndPtr->class = classPtr;
798 wndPtr->winproc = winproc;
799 wndPtr->dwMagic = WND_MAGIC;
800 wndPtr->hwndSelf = hwnd;
801 wndPtr->hInstance = cs->hInstance;
802 wndPtr->text = NULL;
803 wndPtr->hmemTaskQ = GetFastQueue16();
804 wndPtr->hrgnUpdate = 0;
805 wndPtr->hrgnWnd = 0;
806 wndPtr->hwndLastActive = hwnd;
807 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
808 wndPtr->dwExStyle = cs->dwExStyle;
809 wndPtr->clsStyle = clsStyle;
810 wndPtr->wIDmenu = 0;
811 wndPtr->helpContext = 0;
812 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
813 wndPtr->pVScroll = NULL;
814 wndPtr->pHScroll = NULL;
815 wndPtr->pProp = NULL;
816 wndPtr->userdata = 0;
817 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
818 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
819 wndPtr->cbWndExtra = wndExtra;
820 wndPtr->irefCount = 1;
822 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
824 /* Call the WH_CBT hook */
826 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
827 ? HWND_BOTTOM : HWND_TOP;
829 if (HOOK_IsHooked( WH_CBT ))
831 CBT_CREATEWNDA cbtc;
832 LRESULT ret;
834 cbtc.lpcs = cs;
835 cbtc.hwndInsertAfter = hwndLinkAfter;
836 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
837 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
838 if (ret)
840 TRACE("CBT-hook returned 0\n");
841 wndPtr->pDriver->pFinalize(wndPtr);
842 USER_HEAP_FREE( hwnd );
843 CLASS_RemoveWindow( classPtr );
844 retvalue = 0;
845 goto end;
849 /* Correct the window style */
851 if (!(cs->style & WS_CHILD))
853 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
854 if (!(cs->style & WS_POPUP))
856 wndPtr->dwStyle |= WS_CAPTION;
857 wndPtr->flags |= WIN_NEED_SIZE;
861 /* Get class or window DC if needed */
863 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
864 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
865 else wndPtr->dce = NULL;
867 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
869 wndPtr->rectWindow.left = cs->x;
870 wndPtr->rectWindow.top = cs->y;
871 wndPtr->rectWindow.right = cs->x + cs->cx;
872 wndPtr->rectWindow.bottom = cs->y + cs->cy;
873 wndPtr->rectClient = wndPtr->rectWindow;
875 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
877 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
879 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
880 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
881 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
882 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
883 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
886 if (cs->cx < 0) cs->cx = 0;
887 if (cs->cy < 0) cs->cy = 0;
889 wndPtr->rectWindow.left = cs->x;
890 wndPtr->rectWindow.top = cs->y;
891 wndPtr->rectWindow.right = cs->x + cs->cx;
892 wndPtr->rectWindow.bottom = cs->y + cs->cy;
893 wndPtr->rectClient = wndPtr->rectWindow;
895 if(!wndPtr->pDriver->pCreateWindow(wndPtr, cs, type == WIN_PROC_32W))
897 retvalue = FALSE;
898 goto end;
901 /* Set the window menu */
903 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
905 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
906 else
908 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
909 if (menuName)
911 if (HIWORD(cs->hInstance))
912 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
913 else
914 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
916 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
920 else wndPtr->wIDmenu = (UINT)cs->hMenu;
922 /* Send the WM_CREATE message
923 * Perhaps we shouldn't allow width/height changes as well.
924 * See p327 in "Internals".
927 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
929 localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
930 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
932 /* Insert the window in the linked list */
934 WIN_LinkWindow( hwnd, hwndLinkAfter );
936 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
937 NULL, NULL, 0, &wndPtr->rectClient );
938 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
939 maxPos.y - wndPtr->rectWindow.top);
940 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
942 /* Send the size messages */
944 if (!(wndPtr->flags & WIN_NEED_SIZE))
946 /* send it anyway */
947 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
948 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
949 WARN("sending bogus WM_SIZE message 0x%08lx\n",
950 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
951 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
952 (*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
953 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
954 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
955 (*localSend32)( hwnd, WM_MOVE, 0,
956 MAKELONG( wndPtr->rectClient.left,
957 wndPtr->rectClient.top ) );
960 /* Show the window, maximizing or minimizing if needed */
962 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
964 RECT16 newPos;
965 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
966 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
967 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
968 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
969 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
970 : SWP_NOZORDER | SWP_FRAMECHANGED;
971 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
972 newPos.right, newPos.bottom, swFlag );
975 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
977 /* Notify the parent window only */
979 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
980 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
981 if( !IsWindow(hwnd) )
983 retvalue = 0;
984 goto end;
988 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
990 /* Call WH_SHELL hook */
992 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
993 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
995 TRACE("created window %04x\n", hwnd);
996 retvalue = hwnd;
997 goto end;
999 WIN_UnlinkWindow( hwnd );
1002 /* Abort window creation */
1004 WARN("aborted by WM_xxCREATE!\n");
1005 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1006 CLASS_RemoveWindow( classPtr );
1007 retvalue = 0;
1008 end:
1009 WIN_ReleaseWndPtr(wndPtr);
1011 return retvalue;
1015 /***********************************************************************
1016 * CreateWindow (USER.41)
1018 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1019 DWORD style, INT16 x, INT16 y, INT16 width,
1020 INT16 height, HWND16 parent, HMENU16 menu,
1021 HINSTANCE16 instance, LPVOID data )
1023 return CreateWindowEx16( 0, className, windowName, style,
1024 x, y, width, height, parent, menu, instance, data );
1028 /***********************************************************************
1029 * CreateWindowEx (USER.452)
1031 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1032 LPCSTR windowName, DWORD style, INT16 x,
1033 INT16 y, INT16 width, INT16 height,
1034 HWND16 parent, HMENU16 menu,
1035 HINSTANCE16 instance, LPVOID data )
1037 ATOM classAtom;
1038 CREATESTRUCTA cs;
1039 char buffer[256];
1041 /* Find the class atom */
1043 if (HIWORD(className))
1045 if (!(classAtom = GlobalFindAtomA( className )))
1047 ERR( "bad class name %s\n", debugres_a(className) );
1048 return 0;
1051 else
1053 classAtom = LOWORD(className);
1054 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1056 ERR( "bad atom %x\n", classAtom);
1057 return 0;
1059 className = buffer;
1062 /* Fix the coordinates */
1064 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1065 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1066 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1067 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1069 /* Create the window */
1071 cs.lpCreateParams = data;
1072 cs.hInstance = (HINSTANCE)instance;
1073 cs.hMenu = (HMENU)menu;
1074 cs.hwndParent = (HWND)parent;
1075 cs.style = style;
1076 cs.lpszName = windowName;
1077 cs.lpszClass = className;
1078 cs.dwExStyle = exStyle;
1080 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1084 /***********************************************************************
1085 * CreateWindowExA (USER32.@)
1087 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1088 LPCSTR windowName, DWORD style, INT x,
1089 INT y, INT width, INT height,
1090 HWND parent, HMENU menu,
1091 HINSTANCE instance, LPVOID data )
1093 ATOM classAtom;
1094 CREATESTRUCTA cs;
1095 char buffer[256];
1097 if(!instance)
1098 instance=GetModuleHandleA(NULL);
1100 if(exStyle & WS_EX_MDICHILD)
1101 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1103 /* Find the class atom */
1105 if (HIWORD(className))
1107 if (!(classAtom = GlobalFindAtomA( className )))
1109 ERR( "bad class name %s\n", debugres_a(className) );
1110 return 0;
1113 else
1115 classAtom = LOWORD(className);
1116 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1118 ERR( "bad atom %x\n", classAtom);
1119 return 0;
1121 className = buffer;
1124 /* Create the window */
1126 cs.lpCreateParams = data;
1127 cs.hInstance = instance;
1128 cs.hMenu = menu;
1129 cs.hwndParent = parent;
1130 cs.x = x;
1131 cs.y = y;
1132 cs.cx = width;
1133 cs.cy = height;
1134 cs.style = style;
1135 cs.lpszName = windowName;
1136 cs.lpszClass = className;
1137 cs.dwExStyle = exStyle;
1139 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1143 /***********************************************************************
1144 * CreateWindowExW (USER32.@)
1146 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1147 LPCWSTR windowName, DWORD style, INT x,
1148 INT y, INT width, INT height,
1149 HWND parent, HMENU menu,
1150 HINSTANCE instance, LPVOID data )
1152 ATOM classAtom;
1153 CREATESTRUCTW cs;
1154 WCHAR buffer[256];
1156 if(!instance)
1157 instance=GetModuleHandleA(NULL);
1159 if(exStyle & WS_EX_MDICHILD)
1160 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1162 /* Find the class atom */
1164 if (HIWORD(className))
1166 if (!(classAtom = GlobalFindAtomW( className )))
1168 ERR( "bad class name %s\n", debugres_w(className) );
1169 return 0;
1172 else
1174 classAtom = LOWORD(className);
1175 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1177 ERR( "bad atom %x\n", classAtom);
1178 return 0;
1180 className = buffer;
1183 /* Create the window */
1185 cs.lpCreateParams = data;
1186 cs.hInstance = instance;
1187 cs.hMenu = menu;
1188 cs.hwndParent = parent;
1189 cs.x = x;
1190 cs.y = y;
1191 cs.cx = width;
1192 cs.cy = height;
1193 cs.style = style;
1194 cs.lpszName = windowName;
1195 cs.lpszClass = className;
1196 cs.dwExStyle = exStyle;
1198 /* Note: we rely on the fact that CREATESTRUCTA and */
1199 /* CREATESTRUCTW have the same layout. */
1200 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1203 /***********************************************************************
1204 * WIN_SendDestroyMsg
1206 static void WIN_SendDestroyMsg( WND* pWnd )
1208 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1209 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1212 * Send the WM_DESTROY to the window.
1214 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1217 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1218 * make sure that the window still exists when we come back.
1220 if (IsWindow(pWnd->hwndSelf))
1222 HWND* pWndArray = NULL;
1223 WND* pChild = NULL;
1224 int nKidCount = 0;
1227 * Now, if the window has kids, we have to send WM_DESTROY messages
1228 * recursively to it's kids. It seems that those calls can also
1229 * trigger re-entrant calls to DestroyWindow for the kids so we must
1230 * protect against corruption of the list of siblings. We first build
1231 * a list of HWNDs representing all the kids.
1233 pChild = WIN_LockWndPtr(pWnd->child);
1234 while( pChild )
1236 nKidCount++;
1237 WIN_UpdateWndPtr(&pChild,pChild->next);
1241 * If there are no kids, we're done.
1243 if (nKidCount==0)
1244 return;
1246 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1249 * Sanity check
1251 if (pWndArray==NULL)
1252 return;
1255 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1256 * call, our linked list of siblings should be safe.
1258 nKidCount = 0;
1259 pChild = WIN_LockWndPtr(pWnd->child);
1260 while( pChild )
1262 pWndArray[nKidCount] = pChild->hwndSelf;
1263 nKidCount++;
1264 WIN_UpdateWndPtr(&pChild,pChild->next);
1268 * Now that we have a list, go through that list again and send the destroy
1269 * message to those windows. We are using the HWND to retrieve the
1270 * WND pointer so we are effectively checking that all the kid windows are
1271 * still valid before sending the message.
1273 while (nKidCount>0)
1275 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1277 if (pChild!=NULL)
1279 WIN_SendDestroyMsg( pChild );
1280 WIN_ReleaseWndPtr(pChild);
1285 * Cleanup
1287 HeapFree(GetProcessHeap(), 0, pWndArray);
1289 else
1290 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1294 /***********************************************************************
1295 * DestroyWindow (USER.53)
1297 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1299 return DestroyWindow(hwnd);
1303 /***********************************************************************
1304 * DestroyWindow (USER32.@)
1306 BOOL WINAPI DestroyWindow( HWND hwnd )
1308 WND * wndPtr;
1309 BOOL retvalue;
1310 HWND h;
1311 BOOL bFocusSet = FALSE;
1313 TRACE("(%04x)\n", hwnd);
1315 /* Initialization */
1317 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1318 if (wndPtr == pWndDesktop)
1320 retvalue = FALSE; /* Can't destroy desktop */
1321 goto end;
1324 /* Look whether the focus is within the tree of windows we will
1325 * be destroying.
1327 h = GetFocus16();
1328 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1330 if (h == hwnd)
1332 SetFocus(GetWindowLongA(hwnd,GWL_HWNDPARENT));
1333 bFocusSet = TRUE;
1334 break;
1336 h = GetWindowLongA(h,GWL_HWNDPARENT);
1338 /* If the focus is on the window we will destroy and it has no parent,
1339 * set the focus to 0.
1341 if (! bFocusSet && (h == hwnd))
1343 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1344 SetFocus(0);
1347 /* Call hooks */
1349 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1351 retvalue = FALSE;
1352 goto end;
1355 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1357 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1358 /* FIXME: clean up palette - see "Internals" p.352 */
1361 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1362 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1364 /* Notify the parent window only */
1365 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1366 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1367 if( !IsWindow(hwnd) )
1369 retvalue = TRUE;
1370 goto end;
1374 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1376 /* Hide the window */
1378 if (wndPtr->dwStyle & WS_VISIBLE)
1380 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1381 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1382 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1383 if (!IsWindow(hwnd))
1385 retvalue = TRUE;
1386 goto end;
1390 /* Recursively destroy owned windows */
1392 if( !(wndPtr->dwStyle & WS_CHILD) )
1394 /* make sure top menu popup doesn't get destroyed */
1395 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1397 for (;;)
1399 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1400 while (siblingPtr)
1402 if (siblingPtr->owner == wndPtr)
1404 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1405 break;
1406 else
1407 siblingPtr->owner = NULL;
1409 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1411 if (siblingPtr)
1413 DestroyWindow( siblingPtr->hwndSelf );
1414 WIN_ReleaseWndPtr(siblingPtr);
1416 else break;
1419 if( !Options.managed || EVENT_CheckFocus() )
1420 WINPOS_ActivateOtherWindow(wndPtr);
1422 if( wndPtr->owner &&
1423 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1424 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1427 /* Send destroy messages */
1429 WIN_SendDestroyMsg( wndPtr );
1430 if (!IsWindow(hwnd))
1432 retvalue = TRUE;
1433 goto end;
1436 /* Unlink now so we won't bother with the children later on */
1438 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1440 /* Destroy the window storage */
1442 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1443 retvalue = TRUE;
1444 end:
1445 WIN_ReleaseWndPtr(wndPtr);
1446 return retvalue;
1450 /***********************************************************************
1451 * CloseWindow (USER.43)
1453 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1455 return CloseWindow( hwnd );
1459 /***********************************************************************
1460 * CloseWindow (USER32.@)
1462 BOOL WINAPI CloseWindow( HWND hwnd )
1464 WND * wndPtr = WIN_FindWndPtr( hwnd );
1465 BOOL retvalue;
1467 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1469 retvalue = FALSE;
1470 goto end;
1472 ShowWindow( hwnd, SW_MINIMIZE );
1473 retvalue = TRUE;
1474 end:
1475 WIN_ReleaseWndPtr(wndPtr);
1476 return retvalue;
1481 /***********************************************************************
1482 * OpenIcon (USER.44)
1484 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1486 return OpenIcon( hwnd );
1490 /***********************************************************************
1491 * OpenIcon (USER32.@)
1493 BOOL WINAPI OpenIcon( HWND hwnd )
1495 if (!IsIconic( hwnd )) return FALSE;
1496 ShowWindow( hwnd, SW_SHOWNORMAL );
1497 return TRUE;
1501 /***********************************************************************
1502 * WIN_FindWindow
1504 * Implementation of FindWindow() and FindWindowEx().
1506 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1507 LPCWSTR title )
1509 WND *pWnd;
1510 HWND retvalue;
1512 if (child)
1514 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1515 if (parent)
1517 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1519 retvalue = 0;
1520 goto end;
1523 else if (pWnd->parent != pWndDesktop)
1525 retvalue = 0;
1526 goto end;
1528 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1530 else
1532 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1534 retvalue = 0;
1535 goto end;
1537 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1539 if (!pWnd)
1541 retvalue = 0;
1542 goto end;
1545 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1547 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1548 continue; /* Not the right class */
1550 /* Now check the title */
1552 if (!title)
1554 retvalue = pWnd->hwndSelf;
1555 goto end;
1557 if (pWnd->text && !strcmpW( pWnd->text, title ))
1559 retvalue = pWnd->hwndSelf;
1560 goto end;
1563 retvalue = 0;
1564 /* In this case we need to check whether other processes
1565 own a window with the given paramters on the Desktop,
1566 but we don't, so let's at least warn about it */
1567 FIXME("Returning 0 without checking other processes\n");
1568 end:
1569 WIN_ReleaseWndPtr(pWnd);
1570 return retvalue;
1575 /***********************************************************************
1576 * FindWindow (USER.50)
1578 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1580 return FindWindowA( className, title );
1584 /***********************************************************************
1585 * FindWindowEx (USER.427)
1587 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1589 return FindWindowExA( parent, child, className, title );
1593 /***********************************************************************
1594 * FindWindowA (USER32.@)
1596 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1598 HWND ret = FindWindowExA( 0, 0, className, title );
1599 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1600 return ret;
1604 /***********************************************************************
1605 * FindWindowExA (USER32.@)
1607 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1608 LPCSTR className, LPCSTR title )
1610 ATOM atom = 0;
1611 LPWSTR buffer;
1612 HWND hwnd;
1614 if (className)
1616 /* If the atom doesn't exist, then no class */
1617 /* with this name exists either. */
1618 if (!(atom = GlobalFindAtomA( className )))
1620 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1621 return 0;
1625 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1626 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1627 HeapFree( GetProcessHeap(), 0, buffer );
1628 return hwnd;
1632 /***********************************************************************
1633 * FindWindowExW (USER32.@)
1635 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1636 LPCWSTR className, LPCWSTR title )
1638 ATOM atom = 0;
1640 if (className)
1642 /* If the atom doesn't exist, then no class */
1643 /* with this name exists either. */
1644 if (!(atom = GlobalFindAtomW( className )))
1646 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1647 return 0;
1650 return WIN_FindWindow( parent, child, atom, title );
1654 /***********************************************************************
1655 * FindWindowW (USER32.@)
1657 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1659 return FindWindowExW( 0, 0, className, title );
1663 /**********************************************************************
1664 * WIN_GetDesktop
1665 * returns a locked pointer
1667 WND *WIN_GetDesktop(void)
1669 return WIN_LockWndPtr(pWndDesktop);
1671 /**********************************************************************
1672 * WIN_ReleaseDesktop
1673 * unlock the desktop pointer
1675 void WIN_ReleaseDesktop(void)
1677 WIN_ReleaseWndPtr(pWndDesktop);
1681 /**********************************************************************
1682 * GetDesktopWindow (USER.286)
1684 HWND16 WINAPI GetDesktopWindow16(void)
1686 return (HWND16)pWndDesktop->hwndSelf;
1690 /**********************************************************************
1691 * GetDesktopWindow (USER32.@)
1693 HWND WINAPI GetDesktopWindow(void)
1695 if (pWndDesktop) return pWndDesktop->hwndSelf;
1696 ERR( "You need the -desktop option when running with native USER\n" );
1697 ExitProcess(1);
1698 return 0;
1702 /**********************************************************************
1703 * GetDesktopHwnd (USER.278)
1705 * Exactly the same thing as GetDesktopWindow(), but not documented.
1706 * Don't ask me why...
1708 HWND16 WINAPI GetDesktopHwnd16(void)
1710 return (HWND16)pWndDesktop->hwndSelf;
1714 /*******************************************************************
1715 * EnableWindow (USER.34)
1717 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1719 return EnableWindow( hwnd, enable );
1723 /*******************************************************************
1724 * EnableWindow (USER32.@)
1726 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1728 WND *wndPtr;
1729 BOOL retvalue;
1731 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1733 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1734 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1736 /* Enable window */
1737 wndPtr->dwStyle &= ~WS_DISABLED;
1739 if( wndPtr->flags & WIN_NATIVE )
1740 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1742 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1743 retvalue = TRUE;
1744 goto end;
1746 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1748 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1750 /* Disable window */
1751 wndPtr->dwStyle |= WS_DISABLED;
1753 if( wndPtr->flags & WIN_NATIVE )
1754 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1756 if (hwnd == GetFocus())
1758 SetFocus( 0 ); /* A disabled window can't have the focus */
1760 if (hwnd == GetCapture())
1762 ReleaseCapture(); /* A disabled window can't capture the mouse */
1764 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1765 retvalue = FALSE;
1766 goto end;
1768 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1769 end:
1770 WIN_ReleaseWndPtr(wndPtr);
1771 return retvalue;
1775 /***********************************************************************
1776 * IsWindowEnabled (USER.35)
1778 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1780 return IsWindowEnabled(hWnd);
1784 /***********************************************************************
1785 * IsWindowEnabled (USER32.@)
1787 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1789 WND * wndPtr;
1790 BOOL retvalue;
1792 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1793 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1794 WIN_ReleaseWndPtr(wndPtr);
1795 return retvalue;
1800 /***********************************************************************
1801 * IsWindowUnicode (USER32.@)
1803 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1805 WND * wndPtr;
1806 BOOL retvalue;
1808 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1809 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1810 WIN_ReleaseWndPtr(wndPtr);
1811 return retvalue;
1815 /**********************************************************************
1816 * GetWindowWord (USER.133)
1818 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1820 return GetWindowWord( hwnd, offset );
1824 /**********************************************************************
1825 * GetWindowWord (USER32.@)
1827 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1829 WORD retvalue;
1830 WND * wndPtr = WIN_FindWndPtr( hwnd );
1831 if (!wndPtr) return 0;
1832 if (offset >= 0)
1834 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1836 WARN("Invalid offset %d\n", offset );
1837 retvalue = 0;
1838 goto end;
1840 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1841 goto end;
1843 switch(offset)
1845 case GWW_ID:
1846 if (HIWORD(wndPtr->wIDmenu))
1847 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1848 wndPtr->wIDmenu);
1849 retvalue = (WORD)wndPtr->wIDmenu;
1850 goto end;
1851 case GWW_HWNDPARENT:
1852 retvalue = GetParent(hwnd);
1853 goto end;
1854 case GWW_HINSTANCE:
1855 if (HIWORD(wndPtr->hInstance))
1856 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1857 wndPtr->hInstance);
1858 retvalue = (WORD)wndPtr->hInstance;
1859 goto end;
1860 default:
1861 WARN("Invalid offset %d\n", offset );
1862 retvalue = 0;
1863 goto end;
1865 end:
1866 WIN_ReleaseWndPtr(wndPtr);
1867 return retvalue;
1870 /**********************************************************************
1871 * SetWindowWord (USER.134)
1873 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1875 return SetWindowWord( hwnd, offset, newval );
1879 /**********************************************************************
1880 * SetWindowWord (USER32.@)
1882 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1884 WORD *ptr, retval;
1885 WND * wndPtr = WIN_FindWndPtr( hwnd );
1886 if (!wndPtr) return 0;
1887 if (offset >= 0)
1889 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1891 WARN("Invalid offset %d\n", offset );
1892 retval = 0;
1893 goto end;
1895 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1897 else switch(offset)
1899 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1900 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1901 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1902 goto end;
1903 default:
1904 WARN("Invalid offset %d\n", offset );
1905 retval = 0;
1906 goto end;
1908 retval = *ptr;
1909 *ptr = newval;
1910 end:
1911 WIN_ReleaseWndPtr(wndPtr);
1912 return retval;
1916 /**********************************************************************
1917 * WIN_GetWindowLong
1919 * Helper function for GetWindowLong().
1921 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1923 LONG retvalue;
1924 WND * wndPtr = WIN_FindWndPtr( hwnd );
1925 if (!wndPtr) return 0;
1926 if (offset >= 0)
1928 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1930 WARN("Invalid offset %d\n", offset );
1931 retvalue = 0;
1932 goto end;
1934 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1935 /* Special case for dialog window procedure */
1936 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1938 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1939 goto end;
1941 goto end;
1943 switch(offset)
1945 case GWL_USERDATA: retvalue = wndPtr->userdata;
1946 goto end;
1947 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1948 goto end;
1949 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1950 goto end;
1951 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1952 goto end;
1953 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1954 type );
1955 goto end;
1956 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1957 goto end;
1958 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1959 goto end;
1960 default:
1961 WARN("Unknown offset %d\n", offset );
1963 retvalue = 0;
1964 end:
1965 WIN_ReleaseWndPtr(wndPtr);
1966 return retvalue;
1970 /**********************************************************************
1971 * WIN_SetWindowLong
1973 * Helper function for SetWindowLong().
1975 * 0 is the failure code. However, in the case of failure SetLastError
1976 * must be set to distinguish between a 0 return value and a failure.
1978 * FIXME: The error values for SetLastError may not be right. Can
1979 * someone check with the real thing?
1981 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1982 WINDOWPROCTYPE type )
1984 LONG *ptr, retval;
1985 WND * wndPtr = WIN_FindWndPtr( hwnd );
1986 STYLESTRUCT style;
1988 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1990 if (!wndPtr)
1992 /* Is this the right error? */
1993 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1994 return 0;
1997 if (offset >= 0)
1999 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
2001 WARN("Invalid offset %d\n", offset );
2003 /* Is this the right error? */
2004 SetLastError( ERROR_OUTOFMEMORY );
2006 retval = 0;
2007 goto end;
2009 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2010 /* Special case for dialog window procedure */
2011 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2013 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2014 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2015 type, WIN_PROC_WINDOW );
2016 goto end;
2019 else switch(offset)
2021 case GWL_ID:
2022 ptr = (DWORD*)&wndPtr->wIDmenu;
2023 break;
2024 case GWL_HINSTANCE:
2025 retval = SetWindowWord( hwnd, offset, newval );
2026 goto end;
2027 case GWL_WNDPROC:
2028 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2029 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2030 type, WIN_PROC_WINDOW );
2031 goto end;
2032 case GWL_STYLE:
2033 style.styleOld = wndPtr->dwStyle;
2034 newval &= ~(WS_CHILD); /* this bit can't be changed this way */
2035 style.styleNew = newval | (style.styleOld & (WS_CHILD));
2037 if (wndPtr->flags & WIN_ISWIN32)
2038 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2039 wndPtr->dwStyle = style.styleNew;
2040 if (wndPtr->flags & WIN_ISWIN32)
2041 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2042 retval = style.styleOld;
2043 goto end;
2045 case GWL_USERDATA:
2046 ptr = &wndPtr->userdata;
2047 break;
2048 case GWL_EXSTYLE:
2049 style.styleOld = wndPtr->dwExStyle;
2050 style.styleNew = newval;
2051 if (wndPtr->flags & WIN_ISWIN32)
2052 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2053 wndPtr->dwExStyle = newval;
2054 if (wndPtr->flags & WIN_ISWIN32)
2055 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2056 retval = style.styleOld;
2057 goto end;
2059 default:
2060 WARN("Invalid offset %d\n", offset );
2062 /* Don't think this is right error but it should do */
2063 SetLastError( ERROR_OUTOFMEMORY );
2065 retval = 0;
2066 goto end;
2068 retval = *ptr;
2069 *ptr = newval;
2070 end:
2071 WIN_ReleaseWndPtr(wndPtr);
2072 return retval;
2076 /**********************************************************************
2077 * GetWindowLong (USER.135)
2079 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2081 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2085 /**********************************************************************
2086 * GetWindowLongA (USER32.@)
2088 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2090 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2094 /**********************************************************************
2095 * GetWindowLongW (USER32.@)
2097 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2099 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2103 /**********************************************************************
2104 * SetWindowLong (USER.136)
2106 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2108 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2112 /**********************************************************************
2113 * SetWindowLongA (USER32.@)
2115 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2117 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2121 /**********************************************************************
2122 * SetWindowLongW (USER32.@) Set window attribute
2124 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2125 * value in a window's extra memory.
2127 * The _hwnd_ parameter specifies the window. is the handle to a
2128 * window that has extra memory. The _newval_ parameter contains the
2129 * new attribute or extra memory value. If positive, the _offset_
2130 * parameter is the byte-addressed location in the window's extra
2131 * memory to set. If negative, _offset_ specifies the window
2132 * attribute to set, and should be one of the following values:
2134 * GWL_EXSTYLE The window's extended window style
2136 * GWL_STYLE The window's window style.
2138 * GWL_WNDPROC Pointer to the window's window procedure.
2140 * GWL_HINSTANCE The window's pplication instance handle.
2142 * GWL_ID The window's identifier.
2144 * GWL_USERDATA The window's user-specified data.
2146 * If the window is a dialog box, the _offset_ parameter can be one of
2147 * the following values:
2149 * DWL_DLGPROC The address of the window's dialog box procedure.
2151 * DWL_MSGRESULT The return value of a message
2152 * that the dialog box procedure processed.
2154 * DWL_USER Application specific information.
2156 * RETURNS
2158 * If successful, returns the previous value located at _offset_. Otherwise,
2159 * returns 0.
2161 * NOTES
2163 * Extra memory for a window class is specified by a nonzero cbWndExtra
2164 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2165 * time of class creation.
2167 * Using GWL_WNDPROC to set a new window procedure effectively creates
2168 * a window subclass. Use CallWindowProc() in the new windows procedure
2169 * to pass messages to the superclass's window procedure.
2171 * The user data is reserved for use by the application which created
2172 * the window.
2174 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2175 * instead, call the EnableWindow() function to change the window's
2176 * disabled state.
2178 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2179 * SetParent() instead.
2181 * Win95:
2182 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2183 * it sends WM_STYLECHANGING before changing the settings
2184 * and WM_STYLECHANGED afterwards.
2185 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2187 * BUGS
2189 * GWL_STYLE does not dispatch WM_STYLE... messages.
2191 * CONFORMANCE
2193 * ECMA-234, Win32
2196 LONG WINAPI SetWindowLongW(
2197 HWND hwnd, /* [in] window to alter */
2198 INT offset, /* [in] offset, in bytes, of location to alter */
2199 LONG newval /* [in] new value of location */
2201 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2205 /*******************************************************************
2206 * GetWindowText (USER.36)
2208 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2210 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2214 /*******************************************************************
2215 * GetWindowTextA (USER32.@)
2217 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2219 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2220 (LPARAM)lpString );
2223 /*******************************************************************
2224 * InternalGetWindowText (USER32.@)
2226 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2228 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2229 return GetWindowTextW(hwnd,lpString,nMaxCount);
2233 /*******************************************************************
2234 * GetWindowTextW (USER32.@)
2236 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2238 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2239 (LPARAM)lpString );
2243 /*******************************************************************
2244 * SetWindowText (USER.37)
2246 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2248 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2252 /*******************************************************************
2253 * SetWindowText (USER32.@)
2255 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2257 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2261 /*******************************************************************
2262 * SetWindowTextW (USER32.@)
2264 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2266 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2270 /*******************************************************************
2271 * GetWindowTextLength (USER.38)
2273 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2275 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2279 /*******************************************************************
2280 * GetWindowTextLengthA (USER32.@)
2282 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2284 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2287 /*******************************************************************
2288 * GetWindowTextLengthW (USER32.@)
2290 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2292 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2296 /*******************************************************************
2297 * IsWindow (USER.47)
2299 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2301 CURRENT_STACK16->es = USER_HeapSel;
2302 return IsWindow( hwnd );
2306 /*******************************************************************
2307 * IsWindow (USER32.@)
2309 BOOL WINAPI IsWindow( HWND hwnd )
2311 WND * wndPtr;
2312 BOOL retvalue;
2314 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2315 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2316 WIN_ReleaseWndPtr(wndPtr);
2317 return retvalue;
2322 /*****************************************************************
2323 * GetParent (USER.46)
2325 HWND16 WINAPI GetParent16( HWND16 hwnd )
2327 return (HWND16)GetParent( hwnd );
2331 /*****************************************************************
2332 * GetParent (USER32.@)
2334 HWND WINAPI GetParent( HWND hwnd )
2336 WND *wndPtr;
2337 HWND retvalue = 0;
2339 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2340 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2341 goto end;
2343 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2344 if (wndPtr)
2345 retvalue = wndPtr->hwndSelf;
2347 end:
2348 WIN_ReleaseWndPtr(wndPtr);
2349 return retvalue;
2353 /*****************************************************************
2354 * WIN_GetTopParent
2356 * Get the top-level parent for a child window.
2357 * returns a locked pointer
2359 WND* WIN_GetTopParentPtr( WND* pWnd )
2361 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2363 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2365 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2367 return tmpWnd;
2370 /*****************************************************************
2371 * WIN_GetTopParent
2373 * Get the top-level parent for a child window.
2375 HWND WIN_GetTopParent( HWND hwnd )
2377 HWND retvalue;
2378 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2379 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2381 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2382 WIN_ReleaseWndPtr(tmpPtr);
2383 WIN_ReleaseWndPtr(wndPtr);
2384 return retvalue;
2388 /*****************************************************************
2389 * SetParent (USER.233)
2391 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2393 return SetParent( hwndChild, hwndNewParent );
2397 /*****************************************************************
2398 * SetParent (USER32.@)
2400 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2402 WND *wndPtr;
2403 DWORD dwStyle;
2404 WND *pWndNewParent;
2405 WND *pWndOldParent;
2406 HWND retvalue;
2409 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2411 dwStyle = wndPtr->dwStyle;
2413 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2414 : WIN_LockWndPtr(pWndDesktop);
2416 /* Windows hides the window first, then shows it again
2417 * including the WM_SHOWWINDOW messages and all */
2418 if (dwStyle & WS_VISIBLE)
2419 ShowWindow( hwndChild, SW_HIDE );
2421 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2423 /* SetParent additionally needs to make hwndChild the topmost window
2424 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2425 WM_WINDOWPOSCHANGED notification messages.
2427 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2428 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2429 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2430 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2432 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2434 WIN_ReleaseWndPtr(pWndOldParent);
2435 WIN_ReleaseWndPtr(pWndNewParent);
2436 WIN_ReleaseWndPtr(wndPtr);
2438 return retvalue;
2442 /*******************************************************************
2443 * IsChild (USER.48)
2445 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2447 return IsChild(parent,child);
2451 /*******************************************************************
2452 * IsChild (USER32.@)
2454 BOOL WINAPI IsChild( HWND parent, HWND child )
2456 WND * wndPtr = WIN_FindWndPtr( child );
2457 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2459 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2460 if (wndPtr->hwndSelf == parent)
2462 WIN_ReleaseWndPtr(wndPtr);
2463 return TRUE;
2466 WIN_ReleaseWndPtr(wndPtr);
2467 return FALSE;
2471 /***********************************************************************
2472 * IsWindowVisible (USER.49)
2474 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2476 return IsWindowVisible(hwnd);
2480 /***********************************************************************
2481 * IsWindowVisible (USER32.@)
2483 BOOL WINAPI IsWindowVisible( HWND hwnd )
2485 BOOL retval;
2486 WND *wndPtr = WIN_FindWndPtr( hwnd );
2487 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2489 if (!(wndPtr->dwStyle & WS_VISIBLE))
2491 WIN_ReleaseWndPtr(wndPtr);
2492 return FALSE;
2494 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2496 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2497 WIN_ReleaseWndPtr(wndPtr);
2498 return retval;
2503 /***********************************************************************
2504 * WIN_IsWindowDrawable
2506 * hwnd is drawable when it is visible, all parents are not
2507 * minimized, and it is itself not minimized unless we are
2508 * trying to draw its default class icon.
2510 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2512 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2513 if ((wnd->dwStyle & WS_MINIMIZE) &&
2514 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2515 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2516 if( wnd->dwStyle & WS_MINIMIZE ||
2517 !(wnd->dwStyle & WS_VISIBLE) ) break;
2518 return (wnd == NULL);
2522 /*******************************************************************
2523 * GetTopWindow (USER.229)
2525 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2527 return GetTopWindow(hwnd);
2531 /*******************************************************************
2532 * GetTopWindow (USER32.@)
2534 HWND WINAPI GetTopWindow( HWND hwnd )
2536 HWND retval = 0;
2537 WND * wndPtr = (hwnd) ?
2538 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2540 if (wndPtr && wndPtr->child)
2541 retval = wndPtr->child->hwndSelf;
2543 WIN_ReleaseWndPtr(wndPtr);
2544 return retval;
2548 /*******************************************************************
2549 * GetWindow (USER.262)
2551 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2553 return GetWindow( hwnd,rel );
2557 /*******************************************************************
2558 * GetWindow (USER32.@)
2560 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2562 HWND retval;
2564 WND * wndPtr = WIN_FindWndPtr( hwnd );
2565 if (!wndPtr) return 0;
2566 switch(rel)
2568 case GW_HWNDFIRST:
2569 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2570 goto end;
2572 case GW_HWNDLAST:
2573 if (!wndPtr->parent)
2575 retval = 0; /* Desktop window */
2576 goto end;
2578 while (wndPtr->next)
2580 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2582 retval = wndPtr->hwndSelf;
2583 goto end;
2585 case GW_HWNDNEXT:
2586 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2587 goto end;
2589 case GW_HWNDPREV:
2590 if (!wndPtr->parent)
2592 retval = 0; /* Desktop window */
2593 goto end;
2595 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2596 if (wndPtr->hwndSelf == hwnd)
2598 retval = 0; /* First in list */
2599 goto end;
2601 while (wndPtr->next)
2603 if (wndPtr->next->hwndSelf == hwnd)
2605 retval = wndPtr->hwndSelf;
2606 goto end;
2608 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2610 retval = 0;
2611 goto end;
2613 case GW_OWNER:
2614 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2615 goto end;
2617 case GW_CHILD:
2618 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2619 goto end;
2621 retval = 0;
2622 end:
2623 WIN_ReleaseWndPtr(wndPtr);
2624 return retval;
2628 /*******************************************************************
2629 * GetNextWindow (USER.230)
2631 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2633 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2634 return GetWindow16( hwnd, flag );
2637 /***********************************************************************
2638 * WIN_InternalShowOwnedPopups
2640 * Internal version of ShowOwnedPopups; Wine functions should use this
2641 * to avoid interfering with application calls to ShowOwnedPopups
2642 * and to make sure the application can't prevent showing/hiding.
2644 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2648 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2650 INT totalChild=0, count=0;
2652 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2654 if (!pWnd) return TRUE;
2657 * Show windows Lowest first, Highest last to preserve Z-Order
2659 for (count = totalChild-1 ; count >=0; count--)
2661 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2663 if (fShow)
2665 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2666 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2669 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2671 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2672 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2675 else
2677 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2678 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2679 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2682 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2684 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2685 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2686 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2691 WIN_ReleaseDesktop();
2692 WIN_ReleaseWinArray(pWnd);
2694 return TRUE;
2697 /*******************************************************************
2698 * ShowOwnedPopups (USER.265)
2700 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2702 ShowOwnedPopups( owner, fShow );
2706 /*******************************************************************
2707 * ShowOwnedPopups (USER32.@)
2709 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2711 UINT totalChild=0, count=0;
2713 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2715 if (!pWnd) return TRUE;
2717 for (; count < totalChild; count++)
2719 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2721 if (fShow)
2723 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2726 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2727 * regardless of the state of the owner
2729 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2730 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2733 else
2735 if (IsWindowVisible(pWnd[count]->hwndSelf))
2738 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2739 * regardless of the state of the owner
2741 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2742 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2748 WIN_ReleaseDesktop();
2749 WIN_ReleaseWinArray(pWnd);
2750 return TRUE;
2754 /*******************************************************************
2755 * GetLastActivePopup (USER.287)
2757 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2759 return GetLastActivePopup( hwnd );
2762 /*******************************************************************
2763 * GetLastActivePopup (USER32.@)
2765 HWND WINAPI GetLastActivePopup( HWND hwnd )
2767 HWND retval;
2768 WND *wndPtr =WIN_FindWndPtr(hwnd);
2769 if (!wndPtr) return hwnd;
2770 retval = wndPtr->hwndLastActive;
2771 WIN_ReleaseWndPtr(wndPtr);
2772 if ((retval != hwnd) && (!IsWindow(retval)))
2773 retval = hwnd;
2774 return retval;
2778 /*******************************************************************
2779 * WIN_BuildWinArray
2781 * Build an array of pointers to the children of a given window.
2782 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2783 * when no windows are found.
2785 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2787 /* Future: this function will lock all windows associated with this array */
2789 WND **list, **ppWnd;
2790 WND *pWnd;
2791 UINT count = 0, skipOwned, skipHidden;
2792 DWORD skipFlags;
2794 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2795 skipOwned = bwaFlags & BWA_SKIPOWNED;
2796 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2797 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2799 /* First count the windows */
2801 if (!wndPtr)
2802 wndPtr = WIN_GetDesktop();
2804 pWnd = WIN_LockWndPtr(wndPtr->child);
2805 while (pWnd)
2807 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2808 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2809 count++;
2810 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2813 if( count )
2815 /* Now build the list of all windows */
2817 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2819 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2821 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2822 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2824 *ppWnd++ = pWnd;
2825 count++;
2828 WIN_ReleaseWndPtr(pWnd);
2829 *ppWnd = NULL;
2831 else count = 0;
2832 } else list = NULL;
2834 if( pTotal ) *pTotal = count;
2835 return list;
2837 /*******************************************************************
2838 * WIN_ReleaseWinArray
2840 void WIN_ReleaseWinArray(WND **wndArray)
2842 /* Future: this function will also unlock all windows associated with wndArray */
2843 HeapFree( GetProcessHeap(), 0, wndArray );
2847 /*******************************************************************
2848 * EnumWindows (USER32.@)
2850 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2852 WND **list, **ppWnd;
2854 /* We have to build a list of all windows first, to avoid */
2855 /* unpleasant side-effects, for instance if the callback */
2856 /* function changes the Z-order of the windows. */
2858 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2860 WIN_ReleaseDesktop();
2861 return FALSE;
2864 /* Now call the callback function for every window */
2866 for (ppWnd = list; *ppWnd; ppWnd++)
2868 LRESULT lpEnumFuncRetval;
2869 int iWndsLocks = 0;
2870 /* Make sure that the window still exists */
2871 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2873 /* To avoid any deadlocks, all the locks on the windows
2874 structures must be suspended before the control
2875 is passed to the application */
2876 iWndsLocks = WIN_SuspendWndsLock();
2877 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2878 WIN_RestoreWndsLock(iWndsLocks);
2880 if (!lpEnumFuncRetval) break;
2882 WIN_ReleaseWinArray(list);
2883 WIN_ReleaseDesktop();
2884 return TRUE;
2888 /**********************************************************************
2889 * EnumTaskWindows (USER.225)
2891 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2892 LPARAM lParam )
2894 WND **list, **ppWnd;
2896 /* This function is the same as EnumWindows(), */
2897 /* except for an added check on the window's task. */
2899 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2901 WIN_ReleaseDesktop();
2902 return FALSE;
2905 /* Now call the callback function for every window */
2907 for (ppWnd = list; *ppWnd; ppWnd++)
2909 LRESULT funcRetval;
2910 int iWndsLocks = 0;
2911 /* Make sure that the window still exists */
2912 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2913 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2915 /* To avoid any deadlocks, all the locks on the windows
2916 structures must be suspended before the control
2917 is passed to the application */
2918 iWndsLocks = WIN_SuspendWndsLock();
2919 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2920 WIN_RestoreWndsLock(iWndsLocks);
2922 if (!funcRetval) break;
2924 WIN_ReleaseWinArray(list);
2925 WIN_ReleaseDesktop();
2926 return TRUE;
2930 /**********************************************************************
2931 * EnumThreadWindows (USER32.@)
2933 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2935 TEB *teb = THREAD_IdToTEB(id);
2937 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2941 /**********************************************************************
2942 * WIN_EnumChildWindows
2944 * Helper function for EnumChildWindows().
2946 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2948 WND **childList;
2949 BOOL16 ret = FALSE;
2951 for ( ; *ppWnd; ppWnd++)
2953 int iWndsLocks = 0;
2955 /* Make sure that the window still exists */
2956 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2957 /* Build children list first */
2958 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2960 /* To avoid any deadlocks, all the locks on the windows
2961 structures must be suspended before the control
2962 is passed to the application */
2963 iWndsLocks = WIN_SuspendWndsLock();
2964 ret = func( (*ppWnd)->hwndSelf, lParam );
2965 WIN_RestoreWndsLock(iWndsLocks);
2967 if (childList)
2969 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2970 WIN_ReleaseWinArray(childList);
2972 if (!ret) return FALSE;
2974 return TRUE;
2978 /**********************************************************************
2979 * EnumChildWindows (USER32.@)
2981 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2982 LPARAM lParam )
2984 WND **list, *pParent;
2986 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2987 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2989 WIN_ReleaseWndPtr(pParent);
2990 return FALSE;
2992 WIN_EnumChildWindows( list, func, lParam );
2993 WIN_ReleaseWinArray(list);
2994 WIN_ReleaseWndPtr(pParent);
2995 return TRUE;
2999 /*******************************************************************
3000 * AnyPopup (USER.52)
3002 BOOL16 WINAPI AnyPopup16(void)
3004 return AnyPopup();
3008 /*******************************************************************
3009 * AnyPopup (USER32.@)
3011 BOOL WINAPI AnyPopup(void)
3013 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3014 BOOL retvalue;
3016 while (wndPtr)
3018 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3020 retvalue = TRUE;
3021 goto end;
3023 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3025 retvalue = FALSE;
3026 end:
3027 WIN_ReleaseWndPtr(wndPtr);
3028 return retvalue;
3032 /*******************************************************************
3033 * FlashWindow (USER.105)
3035 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3037 return FlashWindow( hWnd, bInvert );
3041 /*******************************************************************
3042 * FlashWindow (USER32.@)
3044 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3046 WND *wndPtr = WIN_FindWndPtr(hWnd);
3048 TRACE("%04x\n", hWnd);
3050 if (!wndPtr) return FALSE;
3052 if (wndPtr->dwStyle & WS_MINIMIZE)
3054 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3056 HDC hDC = GetDC(hWnd);
3058 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3059 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3061 ReleaseDC( hWnd, hDC );
3062 wndPtr->flags |= WIN_NCACTIVATED;
3064 else
3066 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3067 RDW_UPDATENOW | RDW_FRAME, 0 );
3068 wndPtr->flags &= ~WIN_NCACTIVATED;
3070 WIN_ReleaseWndPtr(wndPtr);
3071 return TRUE;
3073 else
3075 WPARAM16 wparam;
3076 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3077 else wparam = (hWnd == GetActiveWindow());
3079 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3080 WIN_ReleaseWndPtr(wndPtr);
3081 return wparam;
3086 /*******************************************************************
3087 * SetSysModalWindow (USER.188)
3089 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3091 HWND hWndOldModal = hwndSysModal;
3092 hwndSysModal = hWnd;
3093 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3094 return hWndOldModal;
3098 /*******************************************************************
3099 * GetSysModalWindow (USER.189)
3101 HWND16 WINAPI GetSysModalWindow16(void)
3103 return hwndSysModal;
3107 /*******************************************************************
3108 * GetWindowContextHelpId (USER32.@)
3110 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3112 DWORD retval;
3113 WND *wnd = WIN_FindWndPtr( hwnd );
3114 if (!wnd) return 0;
3115 retval = wnd->helpContext;
3116 WIN_ReleaseWndPtr(wnd);
3117 return retval;
3121 /*******************************************************************
3122 * SetWindowContextHelpId (USER32.@)
3124 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3126 WND *wnd = WIN_FindWndPtr( hwnd );
3127 if (!wnd) return FALSE;
3128 wnd->helpContext = id;
3129 WIN_ReleaseWndPtr(wnd);
3130 return TRUE;
3134 /*******************************************************************
3135 * DRAG_QueryUpdate
3137 * recursively find a child that contains spDragInfo->pt point
3138 * and send WM_QUERYDROPOBJECT
3140 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3142 BOOL16 wParam, bResult = 0;
3143 POINT pt;
3144 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3145 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3146 RECT tempRect;
3148 if( !ptrQueryWnd || !ptrDragInfo )
3149 goto end;
3151 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3153 GetWindowRect(hQueryWnd,&tempRect);
3155 if( !PtInRect(&tempRect,pt) ||
3156 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3157 goto end;
3159 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3161 tempRect = ptrQueryWnd->rectClient;
3162 if(ptrQueryWnd->dwStyle & WS_CHILD)
3163 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3164 (LPPOINT)&tempRect, 2 );
3166 if (PtInRect( &tempRect, pt))
3168 wParam = 0;
3170 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3172 if( ptrWnd->dwStyle & WS_VISIBLE )
3174 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3175 if (PtInRect( &tempRect, pt )) break;
3179 if(ptrWnd)
3181 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3182 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3183 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3184 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3185 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3187 WIN_ReleaseWndPtr(ptrWnd);
3190 if(bResult)
3191 goto end;
3193 else wParam = 1;
3195 else wParam = 1;
3197 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3199 ptrDragInfo->hScope = hQueryWnd;
3201 bResult = ( bNoSend )
3202 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3203 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3204 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3205 if( !bResult )
3206 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3208 end:
3209 WIN_ReleaseWndPtr(ptrQueryWnd);
3210 return bResult;
3214 /*******************************************************************
3215 * DragDetect (USER.465)
3217 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3219 POINT pt32;
3220 CONV_POINT16TO32( &pt, &pt32 );
3221 return DragDetect( hWnd, pt32 );
3224 /*******************************************************************
3225 * DragDetect (USER32.@)
3227 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3229 MSG msg;
3230 RECT rect;
3232 rect.left = pt.x - wDragWidth;
3233 rect.right = pt.x + wDragWidth;
3235 rect.top = pt.y - wDragHeight;
3236 rect.bottom = pt.y + wDragHeight;
3238 SetCapture(hWnd);
3240 while(1)
3242 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3244 if( msg.message == WM_LBUTTONUP )
3246 ReleaseCapture();
3247 return 0;
3249 if( msg.message == WM_MOUSEMOVE )
3251 POINT tmp;
3252 tmp.x = LOWORD(msg.lParam);
3253 tmp.y = HIWORD(msg.lParam);
3254 if( !PtInRect( &rect, tmp ))
3256 ReleaseCapture();
3257 return 1;
3261 WaitMessage();
3263 return 0;
3266 /******************************************************************************
3267 * DragObject (USER.464)
3269 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3270 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3272 MSG msg;
3273 LPDRAGINFO16 lpDragInfo;
3274 SEGPTR spDragInfo;
3275 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3276 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3277 WND *wndPtr = WIN_FindWndPtr(hWnd);
3278 HCURSOR16 hCurrentCursor = 0;
3279 HWND16 hCurrentWnd = 0;
3281 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3282 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3284 if( !lpDragInfo || !spDragInfo )
3286 WIN_ReleaseWndPtr(wndPtr);
3287 return 0L;
3290 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3292 if( !hBummer || !wndPtr )
3294 GlobalFree16(hDragInfo);
3295 WIN_ReleaseWndPtr(wndPtr);
3296 return 0L;
3299 if(hCursor)
3301 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3303 GlobalFree16(hDragInfo);
3304 WIN_ReleaseWndPtr(wndPtr);
3305 return 0L;
3308 if( hDragCursor == hCursor ) hDragCursor = 0;
3309 else hCursor = hDragCursor;
3311 hOldCursor = SetCursor(hDragCursor);
3314 lpDragInfo->hWnd = hWnd;
3315 lpDragInfo->hScope = 0;
3316 lpDragInfo->wFlags = wObj;
3317 lpDragInfo->hList = szList; /* near pointer! */
3318 lpDragInfo->hOfStruct = hOfStruct;
3319 lpDragInfo->l = 0L;
3321 SetCapture(hWnd);
3322 ShowCursor( TRUE );
3326 do{ WaitMessage(); }
3327 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3329 *(lpDragInfo+1) = *lpDragInfo;
3331 lpDragInfo->pt.x = msg.pt.x;
3332 lpDragInfo->pt.y = msg.pt.y;
3334 /* update DRAGINFO struct */
3335 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3337 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3338 hCurrentCursor = hCursor;
3339 else
3341 hCurrentCursor = hBummer;
3342 lpDragInfo->hScope = 0;
3344 if( hCurrentCursor )
3345 SetCursor(hCurrentCursor);
3347 /* send WM_DRAGLOOP */
3348 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3349 (LPARAM) spDragInfo );
3350 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3351 if( hCurrentWnd != lpDragInfo->hScope )
3353 if( hCurrentWnd )
3354 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3355 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3356 HIWORD(spDragInfo)) );
3357 hCurrentWnd = lpDragInfo->hScope;
3358 if( hCurrentWnd )
3359 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3361 else
3362 if( hCurrentWnd )
3363 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3365 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3367 ReleaseCapture();
3368 ShowCursor( FALSE );
3370 if( hCursor )
3372 SetCursor( hOldCursor );
3373 if (hDragCursor) DestroyCursor( hDragCursor );
3376 if( hCurrentCursor != hBummer )
3377 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3378 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3379 else
3380 msg.lParam = 0;
3381 GlobalFree16(hDragInfo);
3382 WIN_ReleaseWndPtr(wndPtr);
3384 return (DWORD)(msg.lParam);
3388 /******************************************************************************
3389 * GetWindowModuleFileNameA (USER32.@)
3391 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3393 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3394 hwnd, lpszFileName, cchFileNameMax);
3395 return 0;
3398 /******************************************************************************
3399 * GetWindowModuleFileNameW (USER32.@)
3401 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3403 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3404 hwnd, lpszFileName, cchFileNameMax);
3405 return 0;