Moved most of the implementation of SetWindowPos and SetDrawable into
[wine/multimedia.git] / windows / win.c
blob1d2bfefd46c8f3386242fbae510f6cb635bf3efb
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 "winerror.h"
25 #include "stackframe.h"
26 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(win);
29 DECLARE_DEBUG_CHANNEL(msg);
31 /**********************************************************************/
33 WND_DRIVER *WND_Driver = NULL;
35 /* Desktop window */
36 static WND *pWndDesktop = NULL;
38 static HWND hwndSysModal = 0;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 /* thread safeness */
44 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
46 /***********************************************************************
47 * WIN_LockWnds
49 * Locks access to all WND structures for thread safeness
51 void WIN_LockWnds( void )
53 _EnterSysLevel( &WIN_SysLevel );
56 /***********************************************************************
57 * WIN_UnlockWnds
59 * Unlocks access to all WND structures
61 void WIN_UnlockWnds( void )
63 _LeaveSysLevel( &WIN_SysLevel );
66 /***********************************************************************
67 * WIN_SuspendWndsLock
69 * Suspend the lock on WND structures.
70 * Returns the number of locks suspended
72 int WIN_SuspendWndsLock( void )
74 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
75 int count = isuspendedLocks;
77 while ( count-- > 0 )
78 _LeaveSysLevel( &WIN_SysLevel );
80 return isuspendedLocks;
83 /***********************************************************************
84 * WIN_RestoreWndsLock
86 * Restore the suspended locks on WND structures
88 void WIN_RestoreWndsLock( int ipreviousLocks )
90 while ( ipreviousLocks-- > 0 )
91 _EnterSysLevel( &WIN_SysLevel );
94 /***********************************************************************
95 * WIN_FindWndPtr
97 * Return a pointer to the WND structure corresponding to a HWND.
99 WND * WIN_FindWndPtr( HWND hwnd )
101 WND * ptr;
103 if (!hwnd || HIWORD(hwnd)) goto error2;
104 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
105 /* Lock all WND structures for thread safeness*/
106 WIN_LockWnds();
107 /*and increment destruction monitoring*/
108 ptr->irefCount++;
110 if (ptr->dwMagic != WND_MAGIC) goto error;
111 if (ptr->hwndSelf != hwnd)
113 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
114 goto error;
116 /* returns a locked pointer */
117 return ptr;
118 error:
119 /* Unlock all WND structures for thread safeness*/
120 WIN_UnlockWnds();
121 /* and decrement destruction monitoring value */
122 ptr->irefCount--;
124 error2:
125 if ( hwnd!=0 )
126 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
127 return NULL;
130 /***********************************************************************
131 * WIN_LockWndPtr
133 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
134 * but by initWndPtr;
135 * Returns the locked initialisation pointer
137 WND *WIN_LockWndPtr(WND *initWndPtr)
139 if(!initWndPtr) return 0;
141 /* Lock all WND structures for thread safeness*/
142 WIN_LockWnds();
143 /*and increment destruction monitoring*/
144 initWndPtr->irefCount++;
146 return initWndPtr;
150 /***********************************************************************
151 * WIN_ReleaseWndPtr
153 * Release the pointer to the WND structure.
155 void WIN_ReleaseWndPtr(WND *wndPtr)
157 if(!wndPtr) return;
159 /*Decrement destruction monitoring value*/
160 wndPtr->irefCount--;
161 /* Check if it's time to release the memory*/
162 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
164 /* Release memory */
165 USER_HEAP_FREE( wndPtr->hwndSelf);
166 wndPtr->hwndSelf = 0;
168 else if(wndPtr->irefCount < 0)
170 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
171 ERR("forgot a Lock on %p somewhere\n",wndPtr);
173 /*unlock all WND structures for thread safeness*/
174 WIN_UnlockWnds();
177 /***********************************************************************
178 * WIN_UpdateWndPtr
180 * Updates the value of oldPtr to newPtr.
182 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
184 WND *tmpWnd = NULL;
186 tmpWnd = WIN_LockWndPtr(newPtr);
187 WIN_ReleaseWndPtr(*oldPtr);
188 *oldPtr = tmpWnd;
192 /***********************************************************************
193 * WIN_DumpWindow
195 * Dump the content of a window structure to stderr.
197 void WIN_DumpWindow( HWND hwnd )
199 WND *ptr;
200 char className[80];
201 int i;
203 if (!(ptr = WIN_FindWndPtr( hwnd )))
205 WARN("%04x is not a window handle\n", hwnd );
206 return;
209 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
210 strcpy( className, "#NULL#" );
212 TRACE("Window %04x (%p):\n", hwnd, ptr );
213 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
214 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
215 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
216 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
217 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
218 ptr->next, ptr->child, ptr->parent, ptr->owner,
219 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
220 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
221 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
222 ptr->text ? debugstr_w(ptr->text) : "",
223 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
224 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
225 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
226 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
228 if (ptr->cbWndExtra)
230 DPRINTF( "extra bytes:" );
231 for (i = 0; i < ptr->cbWndExtra; i++)
232 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
233 DPRINTF( "\n" );
235 DPRINTF( "\n" );
236 WIN_ReleaseWndPtr(ptr);
240 /***********************************************************************
241 * WIN_WalkWindows
243 * Walk the windows tree and print each window on stderr.
245 void WIN_WalkWindows( HWND hwnd, int indent )
247 WND *ptr;
248 char className[80];
250 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
252 if (!ptr)
254 WARN("Invalid window handle %04x\n", hwnd );
255 return;
258 if (!indent) /* first time around */
259 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
260 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
261 " Text");
263 while (ptr)
265 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
267 GetClassNameA( ptr->hwndSelf, className, sizeof(className) );
268 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
269 (DWORD)ptr, ptr->hmemTaskQ, className,
270 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
271 ptr->text ? debugstr_w(ptr->text) : "<null>");
273 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
274 WIN_UpdateWndPtr(&ptr,ptr->next);
278 /***********************************************************************
279 * WIN_UnlinkWindow
281 * Remove a window from the siblings linked list.
283 BOOL WIN_UnlinkWindow( HWND hwnd )
285 WND *wndPtr, **ppWnd;
286 BOOL ret = FALSE;
288 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
289 else if(!wndPtr->parent)
291 WIN_ReleaseWndPtr(wndPtr);
292 return FALSE;
295 ppWnd = &wndPtr->parent->child;
296 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
297 if (*ppWnd)
299 *ppWnd = wndPtr->next;
300 ret = TRUE;
302 WIN_ReleaseWndPtr(wndPtr);
303 return ret;
307 /***********************************************************************
308 * WIN_LinkWindow
310 * Insert a window into the siblings linked list.
311 * The window is inserted after the specified window, which can also
312 * be specified as HWND_TOP or HWND_BOTTOM.
314 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
316 WND *wndPtr, **ppWnd;
318 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
319 else if(!wndPtr->parent)
321 WIN_ReleaseWndPtr(wndPtr);
322 return FALSE;
324 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
326 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
327 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
328 while (*ppWnd) ppWnd = &(*ppWnd)->next;
330 else /* Normal case */
332 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
333 if (!afterPtr)
335 WIN_ReleaseWndPtr(wndPtr);
336 return FALSE;
338 ppWnd = &afterPtr->next;
339 WIN_ReleaseWndPtr(afterPtr);
341 wndPtr->next = *ppWnd;
342 *ppWnd = wndPtr;
343 WIN_ReleaseWndPtr(wndPtr);
344 return TRUE;
348 /***********************************************************************
349 * WIN_FindWinToRepaint
351 * Find a window that needs repaint.
353 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
355 HWND hwndRet;
356 WND *pWnd;
358 /* Note: the desktop window never gets WM_PAINT messages
359 * The real reason why is because Windows DesktopWndProc
360 * does ValidateRgn inside WM_ERASEBKGND handler.
363 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
365 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
367 if (!(pWnd->dwStyle & WS_VISIBLE))
369 TRACE("skipping window %04x\n",
370 pWnd->hwndSelf );
372 else if ((pWnd->hmemTaskQ == hQueue) &&
373 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
374 break;
376 else if (pWnd->child )
377 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
379 WIN_ReleaseWndPtr(pWnd);
380 return hwndRet;
385 if(!pWnd)
387 return 0;
390 hwndRet = pWnd->hwndSelf;
392 /* look among siblings if we got a transparent window */
393 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
394 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
396 WIN_UpdateWndPtr(&pWnd,pWnd->next);
398 if (pWnd)
400 hwndRet = pWnd->hwndSelf;
401 WIN_ReleaseWndPtr(pWnd);
403 TRACE("found %04x\n",hwndRet);
404 return hwndRet;
408 /***********************************************************************
409 * WIN_DestroyWindow
411 * Destroy storage associated to a window. "Internals" p.358
412 * returns a locked wndPtr->next
414 static WND* WIN_DestroyWindow( WND* wndPtr )
416 HWND hwnd = wndPtr->hwndSelf;
417 WND *pWnd;
419 TRACE("%04x\n", wndPtr->hwndSelf );
421 /* free child windows */
422 WIN_LockWndPtr(wndPtr->child);
423 while ((pWnd = wndPtr->child))
425 wndPtr->child = WIN_DestroyWindow( pWnd );
426 WIN_ReleaseWndPtr(pWnd);
430 * Clear the update region to make sure no WM_PAINT messages will be
431 * generated for this window while processing the WM_NCDESTROY.
433 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
435 if (wndPtr->hrgnUpdate > 1)
436 DeleteObject( wndPtr->hrgnUpdate );
438 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
440 wndPtr->hrgnUpdate = 0;
444 * Send the WM_NCDESTROY to the window being destroyed.
446 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
448 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
450 WINPOS_CheckInternalPos( wndPtr );
451 if( hwnd == GetCapture()) ReleaseCapture();
453 /* free resources associated with the window */
455 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
456 PROPERTY_RemoveWindowProps( wndPtr );
458 /* toss stale messages from the queue */
460 if( wndPtr->hmemTaskQ )
462 BOOL bPostQuit = FALSE;
463 WPARAM wQuitParam = 0;
464 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
465 QMSG *qmsg;
467 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
469 if( qmsg->msg.message == WM_QUIT )
471 bPostQuit = TRUE;
472 wQuitParam = qmsg->msg.wParam;
474 QUEUE_RemoveMsg(msgQ, qmsg);
477 QUEUE_Unlock(msgQ);
479 /* repost WM_QUIT to make sure this app exits its message loop */
480 if( bPostQuit ) PostQuitMessage(wQuitParam);
481 wndPtr->hmemTaskQ = 0;
484 if (!(wndPtr->dwStyle & WS_CHILD))
485 if (wndPtr->wIDmenu)
487 DestroyMenu( wndPtr->wIDmenu );
488 wndPtr->wIDmenu = 0;
490 if (wndPtr->hSysMenu)
492 DestroyMenu( wndPtr->hSysMenu );
493 wndPtr->hSysMenu = 0;
495 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
496 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
497 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
498 CLASS_RemoveWindow( wndPtr->class );
499 wndPtr->class = NULL;
500 wndPtr->dwMagic = 0; /* Mark it as invalid */
502 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
504 return pWnd;
507 /***********************************************************************
508 * WIN_ResetQueueWindows
510 * Reset the queue of all the children of a given window.
511 * Return TRUE if something was done.
513 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
515 BOOL ret = FALSE;
517 if (hNew) /* Set a new queue */
519 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
521 if (wnd->hmemTaskQ == hQueue)
523 wnd->hmemTaskQ = hNew;
524 ret = TRUE;
526 if (wnd->child)
528 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
532 else /* Queue is being destroyed */
534 while (wnd->child)
536 WND *tmp = WIN_LockWndPtr(wnd->child);
537 WND *tmp2;
538 ret = FALSE;
539 while (tmp)
541 if (tmp->hmemTaskQ == hQueue)
543 DestroyWindow( tmp->hwndSelf );
544 ret = TRUE;
545 break;
547 tmp2 = WIN_LockWndPtr(tmp->child);
548 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
549 ret = TRUE;
550 else
552 WIN_UpdateWndPtr(&tmp,tmp->next);
554 WIN_ReleaseWndPtr(tmp2);
556 WIN_ReleaseWndPtr(tmp);
557 if (!ret) break;
560 return ret;
563 /***********************************************************************
564 * WIN_CreateDesktopWindow
566 * Create the desktop window.
568 BOOL WIN_CreateDesktopWindow(void)
570 struct tagCLASS *class;
571 HWND hwndDesktop;
572 INT wndExtra;
573 DWORD clsStyle;
574 WNDPROC winproc;
575 DCE *dce;
577 TRACE("Creating desktop window\n");
580 if (!WINPOS_CreateInternalPosAtom() ||
581 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
582 &wndExtra, &winproc, &clsStyle, &dce )))
583 return FALSE;
585 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
586 if (!hwndDesktop) return FALSE;
587 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
589 pWndDesktop->pDriver = WND_Driver;
590 pWndDesktop->next = NULL;
591 pWndDesktop->child = NULL;
592 pWndDesktop->parent = NULL;
593 pWndDesktop->owner = NULL;
594 pWndDesktop->class = class;
595 pWndDesktop->dwMagic = WND_MAGIC;
596 pWndDesktop->hwndSelf = hwndDesktop;
597 pWndDesktop->hInstance = 0;
598 pWndDesktop->rectWindow.left = 0;
599 pWndDesktop->rectWindow.top = 0;
600 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
601 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
602 pWndDesktop->rectClient = pWndDesktop->rectWindow;
603 pWndDesktop->text = NULL;
604 pWndDesktop->hmemTaskQ = GetFastQueue16();
605 pWndDesktop->hrgnUpdate = 0;
606 pWndDesktop->hwndLastActive = hwndDesktop;
607 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
608 WS_CLIPSIBLINGS;
609 pWndDesktop->dwExStyle = 0;
610 pWndDesktop->clsStyle = clsStyle;
611 pWndDesktop->dce = NULL;
612 pWndDesktop->pVScroll = NULL;
613 pWndDesktop->pHScroll = NULL;
614 pWndDesktop->pProp = NULL;
615 pWndDesktop->wIDmenu = 0;
616 pWndDesktop->helpContext = 0;
617 pWndDesktop->flags = 0;
618 pWndDesktop->hSysMenu = 0;
619 pWndDesktop->userdata = 0;
620 pWndDesktop->winproc = winproc;
621 pWndDesktop->cbWndExtra = wndExtra;
622 pWndDesktop->irefCount = 0;
624 if (!USER_Driver.pCreateWindow( hwndDesktop )) return FALSE;
626 SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
627 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
628 return TRUE;
632 /***********************************************************************
633 * WIN_FixCoordinates
635 * Fix the coordinates - Helper for WIN_CreateWindowEx.
636 * returns default show mode in sw.
637 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
639 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
641 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
642 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
644 if (cs->style & (WS_CHILD | WS_POPUP))
646 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
647 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
649 else /* overlapped window */
651 STARTUPINFOA info;
653 GetStartupInfoA( &info );
655 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
657 /* Never believe Microsoft's documentation... CreateWindowEx doc says
658 * that if an overlapped window is created with WS_VISIBLE style bit
659 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
660 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
661 * reveals that
663 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
664 * 2) it does not ignore the y parameter as the docs claim; instead, it
665 * uses it as second parameter to ShowWindow() unless y is either
666 * CW_USEDEFAULT or CW_USEDEFAULT16.
668 * The fact that we didn't do 2) caused bogus windows pop up when wine
669 * was running apps that were using this obscure feature. Example -
670 * calc.exe that comes with Win98 (only Win98, it's different from
671 * the one that comes with Win95 and NT)
673 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
674 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
675 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
678 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
680 if (info.dwFlags & STARTF_USESIZE)
682 cs->cx = info.dwXSize;
683 cs->cy = info.dwYSize;
685 else /* if no other hint from the app, pick 3/4 of the screen real estate */
687 RECT r;
688 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
689 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
690 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
697 /***********************************************************************
698 * WIN_CreateWindowEx
700 * Implementation of CreateWindowEx().
702 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
703 WINDOWPROCTYPE type )
705 INT sw = SW_SHOW;
706 struct tagCLASS *classPtr;
707 WND *wndPtr;
708 HWND retvalue;
709 HWND16 hwnd, hwndLinkAfter;
710 POINT maxSize, maxPos, minTrack, maxTrack;
711 INT wndExtra;
712 DWORD clsStyle;
713 WNDPROC winproc;
714 DCE *dce;
715 LRESULT CALLBACK (*localSend32)(HWND, UINT, WPARAM, LPARAM);
717 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
718 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
719 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
720 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
721 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
723 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
724 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
726 /* Find the parent window */
728 if (cs->hwndParent)
730 /* Make sure parent is valid */
731 if (!IsWindow( cs->hwndParent ))
733 WARN("Bad parent %04x\n", cs->hwndParent );
734 return 0;
736 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
737 WARN("No parent for child window\n" );
738 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
741 /* Find the window class */
742 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
743 &wndExtra, &winproc, &clsStyle, &dce )))
745 WARN("Bad class '%s'\n", cs->lpszClass );
746 return 0;
749 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
751 /* Create the window structure */
753 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
755 TRACE("out of memory\n" );
756 return 0;
759 /* Fill the window structure */
761 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
762 wndPtr->next = NULL;
763 wndPtr->child = NULL;
765 if ((cs->style & WS_CHILD) && cs->hwndParent)
767 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
768 wndPtr->owner = NULL;
769 WIN_ReleaseWndPtr(wndPtr->parent);
771 else
773 wndPtr->parent = pWndDesktop;
774 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
775 wndPtr->owner = NULL;
776 else
778 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
779 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
780 WIN_ReleaseWndPtr(wndPtr->owner);
781 WIN_ReleaseWndPtr(tmpWnd);
786 wndPtr->pDriver = wndPtr->parent->pDriver;
788 wndPtr->class = classPtr;
789 wndPtr->winproc = winproc;
790 wndPtr->dwMagic = WND_MAGIC;
791 wndPtr->hwndSelf = hwnd;
792 wndPtr->hInstance = cs->hInstance;
793 wndPtr->text = NULL;
794 wndPtr->hmemTaskQ = GetFastQueue16();
795 wndPtr->hrgnUpdate = 0;
796 wndPtr->hrgnWnd = 0;
797 wndPtr->hwndLastActive = hwnd;
798 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
799 wndPtr->dwExStyle = cs->dwExStyle;
800 wndPtr->clsStyle = clsStyle;
801 wndPtr->wIDmenu = 0;
802 wndPtr->helpContext = 0;
803 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
804 wndPtr->pVScroll = NULL;
805 wndPtr->pHScroll = NULL;
806 wndPtr->pProp = NULL;
807 wndPtr->userdata = 0;
808 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
809 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
810 wndPtr->cbWndExtra = wndExtra;
811 wndPtr->irefCount = 1;
813 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
815 /* Call the WH_CBT hook */
817 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
818 ? HWND_BOTTOM : HWND_TOP;
820 if (HOOK_IsHooked( WH_CBT ))
822 CBT_CREATEWNDA cbtc;
823 LRESULT ret;
825 cbtc.lpcs = cs;
826 cbtc.hwndInsertAfter = hwndLinkAfter;
827 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
828 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
829 if (ret)
831 TRACE("CBT-hook returned 0\n");
832 USER_HEAP_FREE( hwnd );
833 CLASS_RemoveWindow( classPtr );
834 retvalue = 0;
835 goto end;
839 /* Correct the window style */
841 if (!(cs->style & WS_CHILD))
843 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
844 if (!(cs->style & WS_POPUP))
846 wndPtr->dwStyle |= WS_CAPTION;
847 wndPtr->flags |= WIN_NEED_SIZE;
851 /* Get class or window DC if needed */
853 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
854 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
855 else wndPtr->dce = NULL;
857 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
859 wndPtr->rectWindow.left = cs->x;
860 wndPtr->rectWindow.top = cs->y;
861 wndPtr->rectWindow.right = cs->x + cs->cx;
862 wndPtr->rectWindow.bottom = cs->y + cs->cy;
863 wndPtr->rectClient = wndPtr->rectWindow;
865 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
867 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
869 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
870 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
871 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
872 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
873 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
876 if (cs->cx < 0) cs->cx = 0;
877 if (cs->cy < 0) cs->cy = 0;
879 wndPtr->rectWindow.left = cs->x;
880 wndPtr->rectWindow.top = cs->y;
881 wndPtr->rectWindow.right = cs->x + cs->cx;
882 wndPtr->rectWindow.bottom = cs->y + cs->cy;
883 wndPtr->rectClient = wndPtr->rectWindow;
885 if (!USER_Driver.pCreateWindow(wndPtr->hwndSelf))
887 retvalue = FALSE;
888 goto end;
891 /* Set the window menu */
893 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
895 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
896 else
898 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
899 if (menuName)
901 if (HIWORD(cs->hInstance))
902 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
903 else
904 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
906 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
910 else wndPtr->wIDmenu = (UINT)cs->hMenu;
912 /* Send the WM_CREATE message
913 * Perhaps we shouldn't allow width/height changes as well.
914 * See p327 in "Internals".
917 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
919 localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
920 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
922 /* Insert the window in the linked list */
924 WIN_LinkWindow( hwnd, hwndLinkAfter );
926 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
927 NULL, NULL, 0, &wndPtr->rectClient );
928 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
929 maxPos.y - wndPtr->rectWindow.top);
930 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
932 /* Send the size messages */
934 if (!(wndPtr->flags & WIN_NEED_SIZE))
936 /* send it anyway */
937 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
938 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
939 WARN("sending bogus WM_SIZE message 0x%08lx\n",
940 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
941 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
942 (*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
943 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
944 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
945 (*localSend32)( hwnd, WM_MOVE, 0,
946 MAKELONG( wndPtr->rectClient.left,
947 wndPtr->rectClient.top ) );
950 /* Show the window, maximizing or minimizing if needed */
952 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
954 RECT16 newPos;
955 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
956 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
957 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
958 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
959 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
960 : SWP_NOZORDER | SWP_FRAMECHANGED;
961 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
962 newPos.right, newPos.bottom, swFlag );
965 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
967 /* Notify the parent window only */
969 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
970 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
971 if( !IsWindow(hwnd) )
973 retvalue = 0;
974 goto end;
978 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
980 /* Call WH_SHELL hook */
982 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
983 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
985 TRACE("created window %04x\n", hwnd);
986 retvalue = hwnd;
987 goto end;
989 WIN_UnlinkWindow( hwnd );
992 /* Abort window creation */
994 WARN("aborted by WM_xxCREATE!\n");
995 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
996 CLASS_RemoveWindow( classPtr );
997 retvalue = 0;
998 end:
999 WIN_ReleaseWndPtr(wndPtr);
1001 return retvalue;
1005 /***********************************************************************
1006 * CreateWindow (USER.41)
1008 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1009 DWORD style, INT16 x, INT16 y, INT16 width,
1010 INT16 height, HWND16 parent, HMENU16 menu,
1011 HINSTANCE16 instance, LPVOID data )
1013 return CreateWindowEx16( 0, className, windowName, style,
1014 x, y, width, height, parent, menu, instance, data );
1018 /***********************************************************************
1019 * CreateWindowEx (USER.452)
1021 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1022 LPCSTR windowName, DWORD style, INT16 x,
1023 INT16 y, INT16 width, INT16 height,
1024 HWND16 parent, HMENU16 menu,
1025 HINSTANCE16 instance, LPVOID data )
1027 ATOM classAtom;
1028 CREATESTRUCTA cs;
1029 char buffer[256];
1031 /* Find the class atom */
1033 if (HIWORD(className))
1035 if (!(classAtom = GlobalFindAtomA( className )))
1037 ERR( "bad class name %s\n", debugres_a(className) );
1038 return 0;
1041 else
1043 classAtom = LOWORD(className);
1044 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1046 ERR( "bad atom %x\n", classAtom);
1047 return 0;
1049 className = buffer;
1052 /* Fix the coordinates */
1054 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1055 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1056 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1057 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1059 /* Create the window */
1061 cs.lpCreateParams = data;
1062 cs.hInstance = (HINSTANCE)instance;
1063 cs.hMenu = (HMENU)menu;
1064 cs.hwndParent = (HWND)parent;
1065 cs.style = style;
1066 cs.lpszName = windowName;
1067 cs.lpszClass = className;
1068 cs.dwExStyle = exStyle;
1070 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1074 /***********************************************************************
1075 * CreateWindowExA (USER32.@)
1077 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1078 LPCSTR windowName, DWORD style, INT x,
1079 INT y, INT width, INT height,
1080 HWND parent, HMENU menu,
1081 HINSTANCE instance, LPVOID data )
1083 ATOM classAtom;
1084 CREATESTRUCTA cs;
1085 char buffer[256];
1087 if(!instance)
1088 instance=GetModuleHandleA(NULL);
1090 if(exStyle & WS_EX_MDICHILD)
1091 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1093 /* Find the class atom */
1095 if (HIWORD(className))
1097 if (!(classAtom = GlobalFindAtomA( className )))
1099 ERR( "bad class name %s\n", debugres_a(className) );
1100 return 0;
1103 else
1105 classAtom = LOWORD(className);
1106 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1108 ERR( "bad atom %x\n", classAtom);
1109 return 0;
1111 className = buffer;
1114 /* Create the window */
1116 cs.lpCreateParams = data;
1117 cs.hInstance = instance;
1118 cs.hMenu = menu;
1119 cs.hwndParent = parent;
1120 cs.x = x;
1121 cs.y = y;
1122 cs.cx = width;
1123 cs.cy = height;
1124 cs.style = style;
1125 cs.lpszName = windowName;
1126 cs.lpszClass = className;
1127 cs.dwExStyle = exStyle;
1129 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1133 /***********************************************************************
1134 * CreateWindowExW (USER32.@)
1136 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1137 LPCWSTR windowName, DWORD style, INT x,
1138 INT y, INT width, INT height,
1139 HWND parent, HMENU menu,
1140 HINSTANCE instance, LPVOID data )
1142 ATOM classAtom;
1143 CREATESTRUCTW cs;
1144 WCHAR buffer[256];
1146 if(!instance)
1147 instance=GetModuleHandleA(NULL);
1149 if(exStyle & WS_EX_MDICHILD)
1150 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1152 /* Find the class atom */
1154 if (HIWORD(className))
1156 if (!(classAtom = GlobalFindAtomW( className )))
1158 ERR( "bad class name %s\n", debugres_w(className) );
1159 return 0;
1162 else
1164 classAtom = LOWORD(className);
1165 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1167 ERR( "bad atom %x\n", classAtom);
1168 return 0;
1170 className = buffer;
1173 /* Create the window */
1175 cs.lpCreateParams = data;
1176 cs.hInstance = instance;
1177 cs.hMenu = menu;
1178 cs.hwndParent = parent;
1179 cs.x = x;
1180 cs.y = y;
1181 cs.cx = width;
1182 cs.cy = height;
1183 cs.style = style;
1184 cs.lpszName = windowName;
1185 cs.lpszClass = className;
1186 cs.dwExStyle = exStyle;
1188 /* Note: we rely on the fact that CREATESTRUCTA and */
1189 /* CREATESTRUCTW have the same layout. */
1190 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1193 /***********************************************************************
1194 * WIN_SendDestroyMsg
1196 static void WIN_SendDestroyMsg( WND* pWnd )
1198 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1199 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1202 * Send the WM_DESTROY to the window.
1204 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1207 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1208 * make sure that the window still exists when we come back.
1210 if (IsWindow(pWnd->hwndSelf))
1212 HWND* pWndArray = NULL;
1213 WND* pChild = NULL;
1214 int nKidCount = 0;
1217 * Now, if the window has kids, we have to send WM_DESTROY messages
1218 * recursively to it's kids. It seems that those calls can also
1219 * trigger re-entrant calls to DestroyWindow for the kids so we must
1220 * protect against corruption of the list of siblings. We first build
1221 * a list of HWNDs representing all the kids.
1223 pChild = WIN_LockWndPtr(pWnd->child);
1224 while( pChild )
1226 nKidCount++;
1227 WIN_UpdateWndPtr(&pChild,pChild->next);
1231 * If there are no kids, we're done.
1233 if (nKidCount==0)
1234 return;
1236 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1239 * Sanity check
1241 if (pWndArray==NULL)
1242 return;
1245 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1246 * call, our linked list of siblings should be safe.
1248 nKidCount = 0;
1249 pChild = WIN_LockWndPtr(pWnd->child);
1250 while( pChild )
1252 pWndArray[nKidCount] = pChild->hwndSelf;
1253 nKidCount++;
1254 WIN_UpdateWndPtr(&pChild,pChild->next);
1258 * Now that we have a list, go through that list again and send the destroy
1259 * message to those windows. We are using the HWND to retrieve the
1260 * WND pointer so we are effectively checking that all the kid windows are
1261 * still valid before sending the message.
1263 while (nKidCount>0)
1265 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1267 if (pChild!=NULL)
1269 WIN_SendDestroyMsg( pChild );
1270 WIN_ReleaseWndPtr(pChild);
1275 * Cleanup
1277 HeapFree(GetProcessHeap(), 0, pWndArray);
1279 else
1280 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1284 /***********************************************************************
1285 * DestroyWindow (USER.53)
1287 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1289 return DestroyWindow(hwnd);
1293 /***********************************************************************
1294 * DestroyWindow (USER32.@)
1296 BOOL WINAPI DestroyWindow( HWND hwnd )
1298 WND * wndPtr;
1299 BOOL retvalue;
1300 HWND h;
1301 BOOL bFocusSet = FALSE;
1303 TRACE("(%04x)\n", hwnd);
1305 /* Initialization */
1307 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1308 if (wndPtr == pWndDesktop)
1310 retvalue = FALSE; /* Can't destroy desktop */
1311 goto end;
1314 /* Look whether the focus is within the tree of windows we will
1315 * be destroying.
1317 h = GetFocus16();
1318 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1320 if (h == hwnd)
1322 SetFocus(GetParent(h));
1323 bFocusSet = TRUE;
1324 break;
1326 h = GetParent(h);
1328 /* If the focus is on the window we will destroy and it has no parent,
1329 * set the focus to 0.
1331 if (! bFocusSet && (h == hwnd))
1333 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1334 SetFocus(0);
1337 /* Call hooks */
1339 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1341 retvalue = FALSE;
1342 goto end;
1345 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1347 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1348 /* FIXME: clean up palette - see "Internals" p.352 */
1351 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1352 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1354 /* Notify the parent window only */
1355 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1356 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1357 if( !IsWindow(hwnd) )
1359 retvalue = TRUE;
1360 goto end;
1364 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1366 /* Hide the window */
1368 if (wndPtr->dwStyle & WS_VISIBLE)
1370 ShowWindow( hwnd, SW_HIDE );
1371 if (!IsWindow(hwnd))
1373 retvalue = TRUE;
1374 goto end;
1378 /* Recursively destroy owned windows */
1380 if( !(wndPtr->dwStyle & WS_CHILD) )
1382 /* make sure top menu popup doesn't get destroyed */
1383 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1385 for (;;)
1387 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1388 while (siblingPtr)
1390 if (siblingPtr->owner == wndPtr)
1392 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1393 break;
1394 else
1395 siblingPtr->owner = NULL;
1397 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1399 if (siblingPtr)
1401 DestroyWindow( siblingPtr->hwndSelf );
1402 WIN_ReleaseWndPtr(siblingPtr);
1404 else break;
1407 WINPOS_ActivateOtherWindow(wndPtr);
1409 if( wndPtr->owner &&
1410 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1411 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1414 /* Send destroy messages */
1416 WIN_SendDestroyMsg( wndPtr );
1417 if (!IsWindow(hwnd))
1419 retvalue = TRUE;
1420 goto end;
1423 /* Unlink now so we won't bother with the children later on */
1425 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1427 /* Destroy the window storage */
1429 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1430 retvalue = TRUE;
1431 end:
1432 WIN_ReleaseWndPtr(wndPtr);
1433 return retvalue;
1437 /***********************************************************************
1438 * CloseWindow (USER.43)
1440 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1442 return CloseWindow( hwnd );
1446 /***********************************************************************
1447 * CloseWindow (USER32.@)
1449 BOOL WINAPI CloseWindow( HWND hwnd )
1451 WND * wndPtr = WIN_FindWndPtr( hwnd );
1452 BOOL retvalue;
1454 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1456 retvalue = FALSE;
1457 goto end;
1459 ShowWindow( hwnd, SW_MINIMIZE );
1460 retvalue = TRUE;
1461 end:
1462 WIN_ReleaseWndPtr(wndPtr);
1463 return retvalue;
1468 /***********************************************************************
1469 * OpenIcon (USER.44)
1471 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1473 return OpenIcon( hwnd );
1477 /***********************************************************************
1478 * OpenIcon (USER32.@)
1480 BOOL WINAPI OpenIcon( HWND hwnd )
1482 if (!IsIconic( hwnd )) return FALSE;
1483 ShowWindow( hwnd, SW_SHOWNORMAL );
1484 return TRUE;
1488 /***********************************************************************
1489 * WIN_FindWindow
1491 * Implementation of FindWindow() and FindWindowEx().
1493 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1494 LPCWSTR title )
1496 WND *pWnd;
1497 HWND retvalue;
1499 if (child)
1501 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1502 if (parent)
1504 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1506 retvalue = 0;
1507 goto end;
1510 else if (pWnd->parent != pWndDesktop)
1512 retvalue = 0;
1513 goto end;
1515 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1517 else
1519 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1521 retvalue = 0;
1522 goto end;
1524 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1526 if (!pWnd)
1528 retvalue = 0;
1529 goto end;
1532 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1534 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1535 continue; /* Not the right class */
1537 /* Now check the title */
1539 if (!title)
1541 retvalue = pWnd->hwndSelf;
1542 goto end;
1544 if (pWnd->text && !strcmpW( pWnd->text, title ))
1546 retvalue = pWnd->hwndSelf;
1547 goto end;
1550 retvalue = 0;
1551 /* In this case we need to check whether other processes
1552 own a window with the given paramters on the Desktop,
1553 but we don't, so let's at least warn about it */
1554 FIXME("Returning 0 without checking other processes\n");
1555 end:
1556 WIN_ReleaseWndPtr(pWnd);
1557 return retvalue;
1562 /***********************************************************************
1563 * FindWindow (USER.50)
1565 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1567 return FindWindowA( className, title );
1571 /***********************************************************************
1572 * FindWindowEx (USER.427)
1574 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1576 return FindWindowExA( parent, child, className, title );
1580 /***********************************************************************
1581 * FindWindowA (USER32.@)
1583 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1585 HWND ret = FindWindowExA( 0, 0, className, title );
1586 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1587 return ret;
1591 /***********************************************************************
1592 * FindWindowExA (USER32.@)
1594 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1595 LPCSTR className, LPCSTR title )
1597 ATOM atom = 0;
1598 LPWSTR buffer;
1599 HWND hwnd;
1601 if (className)
1603 /* If the atom doesn't exist, then no class */
1604 /* with this name exists either. */
1605 if (!(atom = GlobalFindAtomA( className )))
1607 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1608 return 0;
1612 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1613 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1614 HeapFree( GetProcessHeap(), 0, buffer );
1615 return hwnd;
1619 /***********************************************************************
1620 * FindWindowExW (USER32.@)
1622 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1623 LPCWSTR className, LPCWSTR title )
1625 ATOM atom = 0;
1627 if (className)
1629 /* If the atom doesn't exist, then no class */
1630 /* with this name exists either. */
1631 if (!(atom = GlobalFindAtomW( className )))
1633 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1634 return 0;
1637 return WIN_FindWindow( parent, child, atom, title );
1641 /***********************************************************************
1642 * FindWindowW (USER32.@)
1644 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1646 return FindWindowExW( 0, 0, className, title );
1650 /**********************************************************************
1651 * WIN_GetDesktop
1652 * returns a locked pointer
1654 WND *WIN_GetDesktop(void)
1656 return WIN_LockWndPtr(pWndDesktop);
1658 /**********************************************************************
1659 * WIN_ReleaseDesktop
1660 * unlock the desktop pointer
1662 void WIN_ReleaseDesktop(void)
1664 WIN_ReleaseWndPtr(pWndDesktop);
1668 /**********************************************************************
1669 * GetDesktopWindow (USER.286)
1671 HWND16 WINAPI GetDesktopWindow16(void)
1673 return (HWND16)pWndDesktop->hwndSelf;
1677 /**********************************************************************
1678 * GetDesktopWindow (USER32.@)
1680 HWND WINAPI GetDesktopWindow(void)
1682 if (pWndDesktop) return pWndDesktop->hwndSelf;
1683 ERR( "You need the -desktop option when running with native USER\n" );
1684 ExitProcess(1);
1685 return 0;
1689 /**********************************************************************
1690 * GetDesktopHwnd (USER.278)
1692 * Exactly the same thing as GetDesktopWindow(), but not documented.
1693 * Don't ask me why...
1695 HWND16 WINAPI GetDesktopHwnd16(void)
1697 return (HWND16)pWndDesktop->hwndSelf;
1701 /*******************************************************************
1702 * EnableWindow (USER.34)
1704 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1706 return EnableWindow( hwnd, enable );
1710 /*******************************************************************
1711 * EnableWindow (USER32.@)
1713 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1715 WND *wndPtr;
1716 BOOL retvalue;
1718 TRACE("( %x, %d )\n", hwnd, enable);
1720 if (USER_Driver.pEnableWindow)
1721 return USER_Driver.pEnableWindow( hwnd, enable );
1723 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1725 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1727 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1729 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1730 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1732 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1734 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1736 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1738 if (hwnd == GetFocus())
1739 SetFocus( 0 ); /* A disabled window can't have the focus */
1741 if (hwnd == GetCapture())
1742 ReleaseCapture(); /* A disabled window can't capture the mouse */
1744 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1746 WIN_ReleaseWndPtr(wndPtr);
1747 return retvalue;
1751 /***********************************************************************
1752 * IsWindowEnabled (USER.35)
1754 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1756 return IsWindowEnabled(hWnd);
1760 /***********************************************************************
1761 * IsWindowEnabled (USER32.@)
1763 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1765 WND * wndPtr;
1766 BOOL retvalue;
1768 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1769 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1770 WIN_ReleaseWndPtr(wndPtr);
1771 return retvalue;
1776 /***********************************************************************
1777 * IsWindowUnicode (USER32.@)
1779 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1781 WND * wndPtr;
1782 BOOL retvalue;
1784 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1785 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1786 WIN_ReleaseWndPtr(wndPtr);
1787 return retvalue;
1791 /**********************************************************************
1792 * GetWindowWord (USER.133)
1794 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1796 return GetWindowWord( hwnd, offset );
1800 /**********************************************************************
1801 * GetWindowWord (USER32.@)
1803 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1805 WORD retvalue;
1806 WND * wndPtr = WIN_FindWndPtr( hwnd );
1807 if (!wndPtr) return 0;
1808 if (offset >= 0)
1810 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1812 WARN("Invalid offset %d\n", offset );
1813 retvalue = 0;
1814 goto end;
1816 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1817 goto end;
1819 switch(offset)
1821 case GWW_ID:
1822 if (HIWORD(wndPtr->wIDmenu))
1823 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1824 wndPtr->wIDmenu);
1825 retvalue = (WORD)wndPtr->wIDmenu;
1826 goto end;
1827 case GWW_HWNDPARENT:
1828 retvalue = GetParent(hwnd);
1829 goto end;
1830 case GWW_HINSTANCE:
1831 if (HIWORD(wndPtr->hInstance))
1832 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1833 wndPtr->hInstance);
1834 retvalue = (WORD)wndPtr->hInstance;
1835 goto end;
1836 default:
1837 WARN("Invalid offset %d\n", offset );
1838 retvalue = 0;
1839 goto end;
1841 end:
1842 WIN_ReleaseWndPtr(wndPtr);
1843 return retvalue;
1846 /**********************************************************************
1847 * SetWindowWord (USER.134)
1849 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1851 return SetWindowWord( hwnd, offset, newval );
1855 /**********************************************************************
1856 * SetWindowWord (USER32.@)
1858 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1860 WORD *ptr, retval;
1861 WND * wndPtr = WIN_FindWndPtr( hwnd );
1862 if (!wndPtr) return 0;
1863 if (offset >= 0)
1865 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1867 WARN("Invalid offset %d\n", offset );
1868 retval = 0;
1869 goto end;
1871 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1873 else switch(offset)
1875 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1876 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1877 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1878 goto end;
1879 default:
1880 WARN("Invalid offset %d\n", offset );
1881 retval = 0;
1882 goto end;
1884 retval = *ptr;
1885 *ptr = newval;
1886 end:
1887 WIN_ReleaseWndPtr(wndPtr);
1888 return retval;
1892 /**********************************************************************
1893 * WIN_GetWindowLong
1895 * Helper function for GetWindowLong().
1897 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1899 LONG retvalue;
1900 WND * wndPtr = WIN_FindWndPtr( hwnd );
1901 if (!wndPtr) return 0;
1902 if (offset >= 0)
1904 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1906 WARN("Invalid offset %d\n", offset );
1907 retvalue = 0;
1908 goto end;
1910 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1911 /* Special case for dialog window procedure */
1912 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1914 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1915 goto end;
1917 goto end;
1919 switch(offset)
1921 case GWL_USERDATA: retvalue = wndPtr->userdata;
1922 goto end;
1923 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1924 goto end;
1925 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1926 goto end;
1927 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1928 goto end;
1929 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1930 type );
1931 goto end;
1932 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1933 goto end;
1934 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1935 goto end;
1936 default:
1937 WARN("Unknown offset %d\n", offset );
1939 retvalue = 0;
1940 end:
1941 WIN_ReleaseWndPtr(wndPtr);
1942 return retvalue;
1946 /**********************************************************************
1947 * WIN_SetWindowLong
1949 * Helper function for SetWindowLong().
1951 * 0 is the failure code. However, in the case of failure SetLastError
1952 * must be set to distinguish between a 0 return value and a failure.
1954 * FIXME: The error values for SetLastError may not be right. Can
1955 * someone check with the real thing?
1957 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1958 WINDOWPROCTYPE type )
1960 LONG *ptr, retval;
1961 WND * wndPtr = WIN_FindWndPtr( hwnd );
1962 STYLESTRUCT style;
1964 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1966 if (!wndPtr)
1968 /* Is this the right error? */
1969 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1970 return 0;
1973 if (offset >= 0)
1975 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1977 WARN("Invalid offset %d\n", offset );
1979 /* Is this the right error? */
1980 SetLastError( ERROR_OUTOFMEMORY );
1982 retval = 0;
1983 goto end;
1985 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1986 /* Special case for dialog window procedure */
1987 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1989 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1990 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1991 type, WIN_PROC_WINDOW );
1992 goto end;
1995 else switch(offset)
1997 case GWL_ID:
1998 ptr = (DWORD*)&wndPtr->wIDmenu;
1999 break;
2000 case GWL_HINSTANCE:
2001 retval = SetWindowWord( hwnd, offset, newval );
2002 goto end;
2003 case GWL_WNDPROC:
2004 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2005 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2006 type, WIN_PROC_WINDOW );
2007 goto end;
2008 case GWL_STYLE:
2009 style.styleOld = wndPtr->dwStyle;
2010 style.styleNew = newval;
2011 if (wndPtr->flags & WIN_ISWIN32)
2012 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2013 wndPtr->dwStyle = style.styleNew;
2014 if (wndPtr->flags & WIN_ISWIN32)
2015 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2016 retval = style.styleOld;
2017 goto end;
2019 case GWL_USERDATA:
2020 ptr = &wndPtr->userdata;
2021 break;
2022 case GWL_EXSTYLE:
2023 style.styleOld = wndPtr->dwExStyle;
2024 style.styleNew = newval;
2025 if (wndPtr->flags & WIN_ISWIN32)
2026 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2027 wndPtr->dwExStyle = newval;
2028 if (wndPtr->flags & WIN_ISWIN32)
2029 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2030 retval = style.styleOld;
2031 goto end;
2033 default:
2034 WARN("Invalid offset %d\n", offset );
2036 /* Don't think this is right error but it should do */
2037 SetLastError( ERROR_OUTOFMEMORY );
2039 retval = 0;
2040 goto end;
2042 retval = *ptr;
2043 *ptr = newval;
2044 end:
2045 WIN_ReleaseWndPtr(wndPtr);
2046 return retval;
2050 /**********************************************************************
2051 * GetWindowLong (USER.135)
2053 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2055 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2059 /**********************************************************************
2060 * GetWindowLongA (USER32.@)
2062 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2064 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2068 /**********************************************************************
2069 * GetWindowLongW (USER32.@)
2071 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2073 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2077 /**********************************************************************
2078 * SetWindowLong (USER.136)
2080 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2082 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2086 /**********************************************************************
2087 * SetWindowLongA (USER32.@)
2089 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2091 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2095 /**********************************************************************
2096 * SetWindowLongW (USER32.@) Set window attribute
2098 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2099 * value in a window's extra memory.
2101 * The _hwnd_ parameter specifies the window. is the handle to a
2102 * window that has extra memory. The _newval_ parameter contains the
2103 * new attribute or extra memory value. If positive, the _offset_
2104 * parameter is the byte-addressed location in the window's extra
2105 * memory to set. If negative, _offset_ specifies the window
2106 * attribute to set, and should be one of the following values:
2108 * GWL_EXSTYLE The window's extended window style
2110 * GWL_STYLE The window's window style.
2112 * GWL_WNDPROC Pointer to the window's window procedure.
2114 * GWL_HINSTANCE The window's pplication instance handle.
2116 * GWL_ID The window's identifier.
2118 * GWL_USERDATA The window's user-specified data.
2120 * If the window is a dialog box, the _offset_ parameter can be one of
2121 * the following values:
2123 * DWL_DLGPROC The address of the window's dialog box procedure.
2125 * DWL_MSGRESULT The return value of a message
2126 * that the dialog box procedure processed.
2128 * DWL_USER Application specific information.
2130 * RETURNS
2132 * If successful, returns the previous value located at _offset_. Otherwise,
2133 * returns 0.
2135 * NOTES
2137 * Extra memory for a window class is specified by a nonzero cbWndExtra
2138 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2139 * time of class creation.
2141 * Using GWL_WNDPROC to set a new window procedure effectively creates
2142 * a window subclass. Use CallWindowProc() in the new windows procedure
2143 * to pass messages to the superclass's window procedure.
2145 * The user data is reserved for use by the application which created
2146 * the window.
2148 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2149 * instead, call the EnableWindow() function to change the window's
2150 * disabled state.
2152 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2153 * SetParent() instead.
2155 * Win95:
2156 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2157 * it sends WM_STYLECHANGING before changing the settings
2158 * and WM_STYLECHANGED afterwards.
2159 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2161 * BUGS
2163 * GWL_STYLE does not dispatch WM_STYLE... messages.
2165 * CONFORMANCE
2167 * ECMA-234, Win32
2170 LONG WINAPI SetWindowLongW(
2171 HWND hwnd, /* [in] window to alter */
2172 INT offset, /* [in] offset, in bytes, of location to alter */
2173 LONG newval /* [in] new value of location */
2175 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2179 /*******************************************************************
2180 * GetWindowText (USER.36)
2182 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2184 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2188 /*******************************************************************
2189 * GetWindowTextA (USER32.@)
2191 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2193 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2194 (LPARAM)lpString );
2197 /*******************************************************************
2198 * InternalGetWindowText (USER32.@)
2200 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2202 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2203 return GetWindowTextW(hwnd,lpString,nMaxCount);
2207 /*******************************************************************
2208 * GetWindowTextW (USER32.@)
2210 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2212 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2213 (LPARAM)lpString );
2217 /*******************************************************************
2218 * SetWindowText (USER.37)
2220 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2222 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2226 /*******************************************************************
2227 * SetWindowText (USER32.@)
2229 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2231 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2235 /*******************************************************************
2236 * SetWindowTextW (USER32.@)
2238 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2240 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2244 /*******************************************************************
2245 * GetWindowTextLength (USER.38)
2247 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2249 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2253 /*******************************************************************
2254 * GetWindowTextLengthA (USER32.@)
2256 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2258 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2261 /*******************************************************************
2262 * GetWindowTextLengthW (USER32.@)
2264 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2266 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2270 /*******************************************************************
2271 * IsWindow (USER.47)
2273 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2275 CURRENT_STACK16->es = USER_HeapSel;
2276 return IsWindow( hwnd );
2280 /*******************************************************************
2281 * IsWindow (USER32.@)
2283 BOOL WINAPI IsWindow( HWND hwnd )
2285 WND * wndPtr;
2286 BOOL retvalue;
2288 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2289 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2290 WIN_ReleaseWndPtr(wndPtr);
2291 return retvalue;
2296 /*****************************************************************
2297 * GetParent (USER.46)
2299 HWND16 WINAPI GetParent16( HWND16 hwnd )
2301 return (HWND16)GetParent( hwnd );
2305 /*****************************************************************
2306 * GetParent (USER32.@)
2308 HWND WINAPI GetParent( HWND hwnd )
2310 WND *wndPtr;
2311 HWND retvalue = 0;
2313 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2314 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2315 goto end;
2317 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2318 if (wndPtr)
2319 retvalue = wndPtr->hwndSelf;
2321 end:
2322 WIN_ReleaseWndPtr(wndPtr);
2323 return retvalue;
2327 /*****************************************************************
2328 * WIN_GetTopParent
2330 * Get the top-level parent for a child window.
2331 * returns a locked pointer
2333 WND* WIN_GetTopParentPtr( WND* pWnd )
2335 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2337 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2339 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2341 return tmpWnd;
2344 /*****************************************************************
2345 * WIN_GetTopParent
2347 * Get the top-level parent for a child window.
2349 HWND WIN_GetTopParent( HWND hwnd )
2351 HWND retvalue;
2352 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2353 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2355 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2356 WIN_ReleaseWndPtr(tmpPtr);
2357 WIN_ReleaseWndPtr(wndPtr);
2358 return retvalue;
2362 /*****************************************************************
2363 * SetParent (USER.233)
2365 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2367 return SetParent( hwndChild, hwndNewParent );
2371 /*****************************************************************
2372 * SetParent (USER32.@)
2374 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2376 WND *wndPtr;
2377 WND *pWndParent;
2378 DWORD dwStyle;
2379 HWND retvalue;
2381 if (hwnd == GetDesktopWindow()) /* sanity check */
2383 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2384 return 0;
2387 if (USER_Driver.pSetParent)
2388 return USER_Driver.pSetParent( hwnd, parent );
2390 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2392 dwStyle = wndPtr->dwStyle;
2394 pWndParent = parent ? WIN_FindWndPtr(parent) : WIN_GetDesktop();
2395 if (!pWndParent)
2397 WIN_ReleaseWndPtr( wndPtr );
2398 return 0;
2401 /* Windows hides the window first, then shows it again
2402 * including the WM_SHOWWINDOW messages and all */
2403 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2405 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2406 if (pWndParent != wndPtr->parent)
2408 WIN_UnlinkWindow(wndPtr->hwndSelf);
2409 wndPtr->parent = pWndParent;
2411 if (parent != GetDesktopWindow()) /* a child window */
2413 if( !( wndPtr->dwStyle & WS_CHILD ) )
2415 if( wndPtr->wIDmenu != 0)
2417 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2418 wndPtr->wIDmenu = 0;
2422 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2424 WIN_ReleaseWndPtr( pWndParent );
2425 WIN_ReleaseWndPtr( wndPtr );
2427 /* SetParent additionally needs to make hwnd the topmost window
2428 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2429 WM_WINDOWPOSCHANGED notification messages.
2431 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2432 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2433 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2434 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2435 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2436 return retvalue;
2440 /*******************************************************************
2441 * IsChild (USER.48)
2443 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2445 return IsChild(parent,child);
2449 /*******************************************************************
2450 * IsChild (USER32.@)
2452 BOOL WINAPI IsChild( HWND parent, HWND child )
2454 WND * wndPtr = WIN_FindWndPtr( child );
2455 while (wndPtr && wndPtr->parent)
2457 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2458 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2459 if (wndPtr->hwndSelf == parent)
2461 WIN_ReleaseWndPtr(wndPtr);
2462 return TRUE;
2465 WIN_ReleaseWndPtr(wndPtr);
2466 return FALSE;
2470 /***********************************************************************
2471 * IsWindowVisible (USER.49)
2473 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2475 return IsWindowVisible(hwnd);
2479 /***********************************************************************
2480 * IsWindowVisible (USER32.@)
2482 BOOL WINAPI IsWindowVisible( HWND hwnd )
2484 BOOL retval;
2485 WND *wndPtr = WIN_FindWndPtr( hwnd );
2486 while (wndPtr && wndPtr->parent)
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;
2501 /***********************************************************************
2502 * WIN_IsWindowDrawable
2504 * hwnd is drawable when it is visible, all parents are not
2505 * minimized, and it is itself not minimized unless we are
2506 * trying to draw its default class icon.
2508 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2510 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2511 if ((wnd->dwStyle & WS_MINIMIZE) &&
2512 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2513 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2514 if( wnd->dwStyle & WS_MINIMIZE ||
2515 !(wnd->dwStyle & WS_VISIBLE) ) break;
2516 return (wnd == NULL);
2520 /*******************************************************************
2521 * GetTopWindow (USER.229)
2523 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2525 return GetTopWindow(hwnd);
2529 /*******************************************************************
2530 * GetTopWindow (USER32.@)
2532 HWND WINAPI GetTopWindow( HWND hwnd )
2534 HWND retval = 0;
2535 WND * wndPtr = (hwnd) ?
2536 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2538 if (wndPtr && wndPtr->child)
2539 retval = wndPtr->child->hwndSelf;
2541 WIN_ReleaseWndPtr(wndPtr);
2542 return retval;
2546 /*******************************************************************
2547 * GetWindow (USER.262)
2549 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2551 return GetWindow( hwnd,rel );
2555 /*******************************************************************
2556 * GetWindow (USER32.@)
2558 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2560 HWND retval;
2562 WND * wndPtr = WIN_FindWndPtr( hwnd );
2563 if (!wndPtr) return 0;
2564 switch(rel)
2566 case GW_HWNDFIRST:
2567 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2568 goto end;
2570 case GW_HWNDLAST:
2571 if (!wndPtr->parent)
2573 retval = 0; /* Desktop window */
2574 goto end;
2576 while (wndPtr->next)
2578 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2580 retval = wndPtr->hwndSelf;
2581 goto end;
2583 case GW_HWNDNEXT:
2584 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2585 goto end;
2587 case GW_HWNDPREV:
2588 if (!wndPtr->parent)
2590 retval = 0; /* Desktop window */
2591 goto end;
2593 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2594 if (wndPtr->hwndSelf == hwnd)
2596 retval = 0; /* First in list */
2597 goto end;
2599 while (wndPtr->next)
2601 if (wndPtr->next->hwndSelf == hwnd)
2603 retval = wndPtr->hwndSelf;
2604 goto end;
2606 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2608 retval = 0;
2609 goto end;
2611 case GW_OWNER:
2612 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2613 goto end;
2615 case GW_CHILD:
2616 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2617 goto end;
2619 retval = 0;
2620 end:
2621 WIN_ReleaseWndPtr(wndPtr);
2622 return retval;
2626 /*******************************************************************
2627 * GetNextWindow (USER.230)
2629 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2631 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2632 return GetWindow16( hwnd, flag );
2635 /***********************************************************************
2636 * WIN_InternalShowOwnedPopups
2638 * Internal version of ShowOwnedPopups; Wine functions should use this
2639 * to avoid interfering with application calls to ShowOwnedPopups
2640 * and to make sure the application can't prevent showing/hiding.
2642 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2646 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2648 INT totalChild=0, count=0;
2650 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2652 if (!pWnd) return TRUE;
2655 * Show windows Lowest first, Highest last to preserve Z-Order
2657 for (count = totalChild-1 ; count >=0; count--)
2659 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2661 if (fShow)
2663 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2664 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2667 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2669 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2670 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2673 else
2675 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2676 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2677 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2680 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2682 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2683 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2684 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2689 WIN_ReleaseDesktop();
2690 WIN_ReleaseWinArray(pWnd);
2692 return TRUE;
2695 /*******************************************************************
2696 * ShowOwnedPopups (USER.265)
2698 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2700 ShowOwnedPopups( owner, fShow );
2704 /*******************************************************************
2705 * ShowOwnedPopups (USER32.@)
2707 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2709 UINT totalChild=0, count=0;
2711 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2713 if (!pWnd) return TRUE;
2715 for (; count < totalChild; count++)
2717 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2719 if (fShow)
2721 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2724 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2725 * regardless of the state of the owner
2727 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2728 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2731 else
2733 if (IsWindowVisible(pWnd[count]->hwndSelf))
2736 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2737 * regardless of the state of the owner
2739 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2740 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2746 WIN_ReleaseDesktop();
2747 WIN_ReleaseWinArray(pWnd);
2748 return TRUE;
2752 /*******************************************************************
2753 * GetLastActivePopup (USER.287)
2755 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2757 return GetLastActivePopup( hwnd );
2760 /*******************************************************************
2761 * GetLastActivePopup (USER32.@)
2763 HWND WINAPI GetLastActivePopup( HWND hwnd )
2765 HWND retval;
2766 WND *wndPtr =WIN_FindWndPtr(hwnd);
2767 if (!wndPtr) return hwnd;
2768 retval = wndPtr->hwndLastActive;
2769 WIN_ReleaseWndPtr(wndPtr);
2770 if ((retval != hwnd) && (!IsWindow(retval)))
2771 retval = hwnd;
2772 return retval;
2776 /*******************************************************************
2777 * WIN_BuildWinArray
2779 * Build an array of pointers to the children of a given window.
2780 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2781 * when no windows are found.
2783 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2785 /* Future: this function will lock all windows associated with this array */
2787 WND **list, **ppWnd;
2788 WND *pWnd;
2789 UINT count = 0, skipOwned, skipHidden;
2790 DWORD skipFlags;
2792 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2793 skipOwned = bwaFlags & BWA_SKIPOWNED;
2794 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2795 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2797 /* First count the windows */
2799 if (!wndPtr)
2800 wndPtr = WIN_GetDesktop();
2802 pWnd = WIN_LockWndPtr(wndPtr->child);
2803 while (pWnd)
2805 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2806 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2807 count++;
2808 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2811 if( count )
2813 /* Now build the list of all windows */
2815 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2817 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2819 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2820 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2822 *ppWnd++ = pWnd;
2823 count++;
2826 WIN_ReleaseWndPtr(pWnd);
2827 *ppWnd = NULL;
2829 else count = 0;
2830 } else list = NULL;
2832 if( pTotal ) *pTotal = count;
2833 return list;
2835 /*******************************************************************
2836 * WIN_ReleaseWinArray
2838 void WIN_ReleaseWinArray(WND **wndArray)
2840 /* Future: this function will also unlock all windows associated with wndArray */
2841 HeapFree( GetProcessHeap(), 0, wndArray );
2845 /*******************************************************************
2846 * EnumWindows (USER32.@)
2848 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2850 WND **list, **ppWnd;
2852 /* We have to build a list of all windows first, to avoid */
2853 /* unpleasant side-effects, for instance if the callback */
2854 /* function changes the Z-order of the windows. */
2856 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2858 WIN_ReleaseDesktop();
2859 return FALSE;
2862 /* Now call the callback function for every window */
2864 for (ppWnd = list; *ppWnd; ppWnd++)
2866 LRESULT lpEnumFuncRetval;
2867 int iWndsLocks = 0;
2868 /* Make sure that the window still exists */
2869 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2871 /* To avoid any deadlocks, all the locks on the windows
2872 structures must be suspended before the control
2873 is passed to the application */
2874 iWndsLocks = WIN_SuspendWndsLock();
2875 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2876 WIN_RestoreWndsLock(iWndsLocks);
2878 if (!lpEnumFuncRetval) break;
2880 WIN_ReleaseWinArray(list);
2881 WIN_ReleaseDesktop();
2882 return TRUE;
2886 /**********************************************************************
2887 * WIN_EnumQueueWindows
2889 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2891 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2893 WND **list, **ppWnd;
2895 /* This function is the same as EnumWindows(), */
2896 /* except for an added check on the window's task. */
2898 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2900 WIN_ReleaseDesktop();
2901 return FALSE;
2904 /* Now call the callback function for every window */
2906 for (ppWnd = list; *ppWnd; ppWnd++)
2908 LRESULT funcRetval;
2909 int iWndsLocks = 0;
2910 /* Make sure that the window still exists */
2911 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2912 if ((*ppWnd)->hmemTaskQ != queue) continue;
2914 /* To avoid any deadlocks, all the locks on the windows
2915 structures must be suspended before the control
2916 is passed to the application */
2917 iWndsLocks = WIN_SuspendWndsLock();
2918 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2919 WIN_RestoreWndsLock(iWndsLocks);
2921 if (!funcRetval) break;
2923 WIN_ReleaseWinArray(list);
2924 WIN_ReleaseDesktop();
2925 return TRUE;
2929 /**********************************************************************
2930 * EnumTaskWindows16 (USER.225)
2932 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2933 LPARAM lParam )
2935 HQUEUE16 queue = GetTaskQueue16( hTask );
2936 if (!queue) return FALSE;
2937 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2941 /**********************************************************************
2942 * EnumThreadWindows (USER32.@)
2944 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2946 HQUEUE16 queue = GetThreadQueue16( id );
2947 if (!queue) return FALSE;
2948 return WIN_EnumQueueWindows( queue, func, lParam );
2952 /**********************************************************************
2953 * WIN_EnumChildWindows
2955 * Helper function for EnumChildWindows().
2957 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2959 WND **childList;
2960 BOOL16 ret = FALSE;
2962 for ( ; *ppWnd; ppWnd++)
2964 int iWndsLocks = 0;
2966 /* Make sure that the window still exists */
2967 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2968 /* Build children list first */
2969 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2971 /* To avoid any deadlocks, all the locks on the windows
2972 structures must be suspended before the control
2973 is passed to the application */
2974 iWndsLocks = WIN_SuspendWndsLock();
2975 ret = func( (*ppWnd)->hwndSelf, lParam );
2976 WIN_RestoreWndsLock(iWndsLocks);
2978 if (childList)
2980 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2981 WIN_ReleaseWinArray(childList);
2983 if (!ret) return FALSE;
2985 return TRUE;
2989 /**********************************************************************
2990 * EnumChildWindows (USER32.@)
2992 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2993 LPARAM lParam )
2995 WND **list, *pParent;
2997 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2998 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
3000 WIN_ReleaseWndPtr(pParent);
3001 return FALSE;
3003 WIN_EnumChildWindows( list, func, lParam );
3004 WIN_ReleaseWinArray(list);
3005 WIN_ReleaseWndPtr(pParent);
3006 return TRUE;
3010 /*******************************************************************
3011 * AnyPopup (USER.52)
3013 BOOL16 WINAPI AnyPopup16(void)
3015 return AnyPopup();
3019 /*******************************************************************
3020 * AnyPopup (USER32.@)
3022 BOOL WINAPI AnyPopup(void)
3024 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3025 BOOL retvalue;
3027 while (wndPtr)
3029 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3031 retvalue = TRUE;
3032 goto end;
3034 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3036 retvalue = FALSE;
3037 end:
3038 WIN_ReleaseWndPtr(wndPtr);
3039 return retvalue;
3043 /*******************************************************************
3044 * FlashWindow (USER.105)
3046 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3048 return FlashWindow( hWnd, bInvert );
3052 /*******************************************************************
3053 * FlashWindow (USER32.@)
3055 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3057 WND *wndPtr = WIN_FindWndPtr(hWnd);
3059 TRACE("%04x\n", hWnd);
3061 if (!wndPtr) return FALSE;
3063 if (wndPtr->dwStyle & WS_MINIMIZE)
3065 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3067 HDC hDC = GetDC(hWnd);
3069 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3070 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3072 ReleaseDC( hWnd, hDC );
3073 wndPtr->flags |= WIN_NCACTIVATED;
3075 else
3077 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3078 wndPtr->flags &= ~WIN_NCACTIVATED;
3080 WIN_ReleaseWndPtr(wndPtr);
3081 return TRUE;
3083 else
3085 WPARAM16 wparam;
3086 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3087 else wparam = (hWnd == GetActiveWindow());
3089 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3090 WIN_ReleaseWndPtr(wndPtr);
3091 return wparam;
3096 /*******************************************************************
3097 * SetSysModalWindow (USER.188)
3099 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3101 HWND hWndOldModal = hwndSysModal;
3102 hwndSysModal = hWnd;
3103 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3104 return hWndOldModal;
3108 /*******************************************************************
3109 * GetSysModalWindow (USER.189)
3111 HWND16 WINAPI GetSysModalWindow16(void)
3113 return hwndSysModal;
3117 /*******************************************************************
3118 * GetWindowContextHelpId (USER32.@)
3120 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3122 DWORD retval;
3123 WND *wnd = WIN_FindWndPtr( hwnd );
3124 if (!wnd) return 0;
3125 retval = wnd->helpContext;
3126 WIN_ReleaseWndPtr(wnd);
3127 return retval;
3131 /*******************************************************************
3132 * SetWindowContextHelpId (USER32.@)
3134 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3136 WND *wnd = WIN_FindWndPtr( hwnd );
3137 if (!wnd) return FALSE;
3138 wnd->helpContext = id;
3139 WIN_ReleaseWndPtr(wnd);
3140 return TRUE;
3144 /*******************************************************************
3145 * DRAG_QueryUpdate
3147 * recursively find a child that contains spDragInfo->pt point
3148 * and send WM_QUERYDROPOBJECT
3150 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3152 BOOL16 wParam, bResult = 0;
3153 POINT pt;
3154 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3155 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3156 RECT tempRect;
3158 if( !ptrQueryWnd || !ptrDragInfo )
3159 goto end;
3161 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3163 GetWindowRect(hQueryWnd,&tempRect);
3165 if( !PtInRect(&tempRect,pt) ||
3166 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3167 goto end;
3169 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3171 tempRect = ptrQueryWnd->rectClient;
3172 if(ptrQueryWnd->parent)
3173 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3174 (LPPOINT)&tempRect, 2 );
3176 if (PtInRect( &tempRect, pt))
3178 wParam = 0;
3180 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3182 if( ptrWnd->dwStyle & WS_VISIBLE )
3184 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3185 if (PtInRect( &tempRect, pt )) break;
3189 if(ptrWnd)
3191 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3192 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3193 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3194 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3195 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3197 WIN_ReleaseWndPtr(ptrWnd);
3200 if(bResult)
3201 goto end;
3203 else wParam = 1;
3205 else wParam = 1;
3207 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3209 ptrDragInfo->hScope = hQueryWnd;
3211 bResult = ( bNoSend )
3212 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3213 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3214 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3215 if( !bResult )
3216 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3218 end:
3219 WIN_ReleaseWndPtr(ptrQueryWnd);
3220 return bResult;
3224 /*******************************************************************
3225 * DragDetect (USER.465)
3227 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3229 POINT pt32;
3230 CONV_POINT16TO32( &pt, &pt32 );
3231 return DragDetect( hWnd, pt32 );
3234 /*******************************************************************
3235 * DragDetect (USER32.@)
3237 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3239 MSG msg;
3240 RECT rect;
3242 rect.left = pt.x - wDragWidth;
3243 rect.right = pt.x + wDragWidth;
3245 rect.top = pt.y - wDragHeight;
3246 rect.bottom = pt.y + wDragHeight;
3248 SetCapture(hWnd);
3250 while(1)
3252 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3254 if( msg.message == WM_LBUTTONUP )
3256 ReleaseCapture();
3257 return 0;
3259 if( msg.message == WM_MOUSEMOVE )
3261 POINT tmp;
3262 tmp.x = LOWORD(msg.lParam);
3263 tmp.y = HIWORD(msg.lParam);
3264 if( !PtInRect( &rect, tmp ))
3266 ReleaseCapture();
3267 return 1;
3271 WaitMessage();
3273 return 0;
3276 /******************************************************************************
3277 * DragObject (USER.464)
3279 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3280 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3282 MSG msg;
3283 LPDRAGINFO16 lpDragInfo;
3284 SEGPTR spDragInfo;
3285 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3286 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3287 WND *wndPtr = WIN_FindWndPtr(hWnd);
3288 HCURSOR16 hCurrentCursor = 0;
3289 HWND16 hCurrentWnd = 0;
3291 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3292 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3294 if( !lpDragInfo || !spDragInfo )
3296 WIN_ReleaseWndPtr(wndPtr);
3297 return 0L;
3300 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3302 if( !hBummer || !wndPtr )
3304 GlobalFree16(hDragInfo);
3305 WIN_ReleaseWndPtr(wndPtr);
3306 return 0L;
3309 if(hCursor)
3311 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3313 GlobalFree16(hDragInfo);
3314 WIN_ReleaseWndPtr(wndPtr);
3315 return 0L;
3318 if( hDragCursor == hCursor ) hDragCursor = 0;
3319 else hCursor = hDragCursor;
3321 hOldCursor = SetCursor(hDragCursor);
3324 lpDragInfo->hWnd = hWnd;
3325 lpDragInfo->hScope = 0;
3326 lpDragInfo->wFlags = wObj;
3327 lpDragInfo->hList = szList; /* near pointer! */
3328 lpDragInfo->hOfStruct = hOfStruct;
3329 lpDragInfo->l = 0L;
3331 SetCapture(hWnd);
3332 ShowCursor( TRUE );
3336 do{ WaitMessage(); }
3337 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3339 *(lpDragInfo+1) = *lpDragInfo;
3341 lpDragInfo->pt.x = msg.pt.x;
3342 lpDragInfo->pt.y = msg.pt.y;
3344 /* update DRAGINFO struct */
3345 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3347 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3348 hCurrentCursor = hCursor;
3349 else
3351 hCurrentCursor = hBummer;
3352 lpDragInfo->hScope = 0;
3354 if( hCurrentCursor )
3355 SetCursor(hCurrentCursor);
3357 /* send WM_DRAGLOOP */
3358 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3359 (LPARAM) spDragInfo );
3360 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3361 if( hCurrentWnd != lpDragInfo->hScope )
3363 if( hCurrentWnd )
3364 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3365 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3366 HIWORD(spDragInfo)) );
3367 hCurrentWnd = lpDragInfo->hScope;
3368 if( hCurrentWnd )
3369 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3371 else
3372 if( hCurrentWnd )
3373 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3375 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3377 ReleaseCapture();
3378 ShowCursor( FALSE );
3380 if( hCursor )
3382 SetCursor( hOldCursor );
3383 if (hDragCursor) DestroyCursor( hDragCursor );
3386 if( hCurrentCursor != hBummer )
3387 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3388 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3389 else
3390 msg.lParam = 0;
3391 GlobalFree16(hDragInfo);
3392 WIN_ReleaseWndPtr(wndPtr);
3394 return (DWORD)(msg.lParam);
3398 /******************************************************************************
3399 * GetWindowModuleFileNameA (USER32.@)
3401 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3403 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3404 hwnd, lpszFileName, cchFileNameMax);
3405 return 0;
3408 /******************************************************************************
3409 * GetWindowModuleFileNameW (USER32.@)
3411 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3413 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3414 hwnd, lpszFileName, cchFileNameMax);
3415 return 0;