Various registry-related PostScript driver enhancements.
[wine.git] / windows / win.c
blobb9ec8565912f6361a7c763a7da2fbb6b6e4f017d
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( ptr->hwndSelf, 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);
279 /***********************************************************************
280 * WIN_UnlinkWindow
282 * Remove a window from the siblings linked list.
284 BOOL WIN_UnlinkWindow( HWND hwnd )
286 WND *wndPtr, **ppWnd;
287 BOOL ret = FALSE;
289 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
290 else if(!wndPtr->parent)
292 WIN_ReleaseWndPtr(wndPtr);
293 return FALSE;
296 ppWnd = &wndPtr->parent->child;
297 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
298 if (*ppWnd)
300 *ppWnd = wndPtr->next;
301 ret = TRUE;
303 WIN_ReleaseWndPtr(wndPtr);
304 return ret;
308 /***********************************************************************
309 * WIN_LinkWindow
311 * Insert a window into the siblings linked list.
312 * The window is inserted after the specified window, which can also
313 * be specified as HWND_TOP or HWND_BOTTOM.
315 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
317 WND *wndPtr, **ppWnd;
319 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
320 else if(!wndPtr->parent)
322 WIN_ReleaseWndPtr(wndPtr);
323 return FALSE;
325 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
327 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
328 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
329 while (*ppWnd) ppWnd = &(*ppWnd)->next;
331 else /* Normal case */
333 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
334 if (!afterPtr)
336 WIN_ReleaseWndPtr(wndPtr);
337 return FALSE;
339 ppWnd = &afterPtr->next;
340 WIN_ReleaseWndPtr(afterPtr);
342 wndPtr->next = *ppWnd;
343 *ppWnd = wndPtr;
344 WIN_ReleaseWndPtr(wndPtr);
345 return TRUE;
349 /***********************************************************************
350 * WIN_FindWinToRepaint
352 * Find a window that needs repaint.
354 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
356 HWND hwndRet;
357 WND *pWnd;
359 /* Note: the desktop window never gets WM_PAINT messages
360 * The real reason why is because Windows DesktopWndProc
361 * does ValidateRgn inside WM_ERASEBKGND handler.
364 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
366 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
368 if (!(pWnd->dwStyle & WS_VISIBLE))
370 TRACE("skipping window %04x\n",
371 pWnd->hwndSelf );
373 else if ((pWnd->hmemTaskQ == hQueue) &&
374 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
375 break;
377 else if (pWnd->child )
378 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
380 WIN_ReleaseWndPtr(pWnd);
381 return hwndRet;
386 if(!pWnd)
388 return 0;
391 hwndRet = pWnd->hwndSelf;
393 /* look among siblings if we got a transparent window */
394 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
395 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
397 WIN_UpdateWndPtr(&pWnd,pWnd->next);
399 if (pWnd)
401 hwndRet = pWnd->hwndSelf;
402 WIN_ReleaseWndPtr(pWnd);
404 TRACE("found %04x\n",hwndRet);
405 return hwndRet;
409 /***********************************************************************
410 * WIN_DestroyWindow
412 * Destroy storage associated to a window. "Internals" p.358
413 * returns a locked wndPtr->next
415 static WND* WIN_DestroyWindow( WND* wndPtr )
417 HWND hwnd = wndPtr->hwndSelf;
418 WND *pWnd;
420 TRACE("%04x\n", wndPtr->hwndSelf );
422 /* free child windows */
423 WIN_LockWndPtr(wndPtr->child);
424 while ((pWnd = wndPtr->child))
426 wndPtr->child = WIN_DestroyWindow( pWnd );
427 WIN_ReleaseWndPtr(pWnd);
431 * Clear the update region to make sure no WM_PAINT messages will be
432 * generated for this window while processing the WM_NCDESTROY.
434 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
436 if (wndPtr->hrgnUpdate > 1)
437 DeleteObject( wndPtr->hrgnUpdate );
439 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
441 wndPtr->hrgnUpdate = 0;
445 * Send the WM_NCDESTROY to the window being destroyed.
447 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
449 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
451 WINPOS_CheckInternalPos( wndPtr );
452 if( hwnd == GetCapture()) ReleaseCapture();
454 /* free resources associated with the window */
456 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
457 PROPERTY_RemoveWindowProps( wndPtr );
459 wndPtr->dwMagic = 0; /* Mark it as invalid */
461 /* toss stale messages from the queue */
463 if( wndPtr->hmemTaskQ )
465 BOOL bPostQuit = FALSE;
466 WPARAM wQuitParam = 0;
467 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
468 QMSG *qmsg;
470 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
472 if( qmsg->msg.message == WM_QUIT )
474 bPostQuit = TRUE;
475 wQuitParam = qmsg->msg.wParam;
477 QUEUE_RemoveMsg(msgQ, qmsg);
480 QUEUE_Unlock(msgQ);
482 /* repost WM_QUIT to make sure this app exits its message loop */
483 if( bPostQuit ) PostQuitMessage(wQuitParam);
484 wndPtr->hmemTaskQ = 0;
487 if (!(wndPtr->dwStyle & WS_CHILD))
488 if (wndPtr->wIDmenu)
490 DestroyMenu( wndPtr->wIDmenu );
491 wndPtr->wIDmenu = 0;
493 if (wndPtr->hSysMenu)
495 DestroyMenu( wndPtr->hSysMenu );
496 wndPtr->hSysMenu = 0;
498 wndPtr->pDriver->pDestroyWindow( wndPtr );
499 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
500 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
501 CLASS_RemoveWindow( wndPtr->class );
502 wndPtr->class = NULL;
504 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
506 wndPtr->pDriver->pFinalize(wndPtr);
508 return pWnd;
511 /***********************************************************************
512 * WIN_ResetQueueWindows
514 * Reset the queue of all the children of a given window.
515 * Return TRUE if something was done.
517 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
519 BOOL ret = FALSE;
521 if (hNew) /* Set a new queue */
523 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
525 if (wnd->hmemTaskQ == hQueue)
527 wnd->hmemTaskQ = hNew;
528 ret = TRUE;
530 if (wnd->child)
532 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
536 else /* Queue is being destroyed */
538 while (wnd->child)
540 WND *tmp = WIN_LockWndPtr(wnd->child);
541 WND *tmp2;
542 ret = FALSE;
543 while (tmp)
545 if (tmp->hmemTaskQ == hQueue)
547 DestroyWindow( tmp->hwndSelf );
548 ret = TRUE;
549 break;
551 tmp2 = WIN_LockWndPtr(tmp->child);
552 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
553 ret = TRUE;
554 else
556 WIN_UpdateWndPtr(&tmp,tmp->next);
558 WIN_ReleaseWndPtr(tmp2);
560 WIN_ReleaseWndPtr(tmp);
561 if (!ret) break;
564 return ret;
567 /***********************************************************************
568 * WIN_CreateDesktopWindow
570 * Create the desktop window.
572 BOOL WIN_CreateDesktopWindow(void)
574 struct tagCLASS *class;
575 HWND hwndDesktop;
576 INT wndExtra;
577 DWORD clsStyle;
578 WNDPROC winproc;
579 DCE *dce;
581 TRACE("Creating desktop window\n");
584 if (!WINPOS_CreateInternalPosAtom() ||
585 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
586 &wndExtra, &winproc, &clsStyle, &dce )))
587 return FALSE;
589 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
590 if (!hwndDesktop) return FALSE;
591 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
593 pWndDesktop->pDriver = WND_Driver;
594 pWndDesktop->pDriver->pInitialize(pWndDesktop);
596 pWndDesktop->next = NULL;
597 pWndDesktop->child = NULL;
598 pWndDesktop->parent = NULL;
599 pWndDesktop->owner = NULL;
600 pWndDesktop->class = class;
601 pWndDesktop->dwMagic = WND_MAGIC;
602 pWndDesktop->hwndSelf = hwndDesktop;
603 pWndDesktop->hInstance = 0;
604 pWndDesktop->rectWindow.left = 0;
605 pWndDesktop->rectWindow.top = 0;
606 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
607 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
608 pWndDesktop->rectClient = pWndDesktop->rectWindow;
609 pWndDesktop->text = NULL;
610 pWndDesktop->hmemTaskQ = GetFastQueue16();
611 pWndDesktop->hrgnUpdate = 0;
612 pWndDesktop->hwndLastActive = hwndDesktop;
613 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
614 WS_CLIPSIBLINGS;
615 pWndDesktop->dwExStyle = 0;
616 pWndDesktop->clsStyle = clsStyle;
617 pWndDesktop->dce = NULL;
618 pWndDesktop->pVScroll = NULL;
619 pWndDesktop->pHScroll = NULL;
620 pWndDesktop->pProp = NULL;
621 pWndDesktop->wIDmenu = 0;
622 pWndDesktop->helpContext = 0;
623 pWndDesktop->flags = 0;
624 pWndDesktop->hSysMenu = 0;
625 pWndDesktop->userdata = 0;
626 pWndDesktop->winproc = winproc;
627 pWndDesktop->cbWndExtra = wndExtra;
628 pWndDesktop->irefCount = 0;
630 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop)) return FALSE;
632 SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
633 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
634 return TRUE;
638 /***********************************************************************
639 * WIN_FixCoordinates
641 * Fix the coordinates - Helper for WIN_CreateWindowEx.
642 * returns default show mode in sw.
643 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
645 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
647 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
648 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
650 if (cs->style & (WS_CHILD | WS_POPUP))
652 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
653 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
655 else /* overlapped window */
657 STARTUPINFOA info;
659 GetStartupInfoA( &info );
661 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
663 /* Never believe Microsoft's documentation... CreateWindowEx doc says
664 * that if an overlapped window is created with WS_VISIBLE style bit
665 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
666 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
667 * reveals that
669 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
670 * 2) it does not ignore the y parameter as the docs claim; instead, it
671 * uses it as second parameter to ShowWindow() unless y is either
672 * CW_USEDEFAULT or CW_USEDEFAULT16.
674 * The fact that we didn't do 2) caused bogus windows pop up when wine
675 * was running apps that were using this obscure feature. Example -
676 * calc.exe that comes with Win98 (only Win98, it's different from
677 * the one that comes with Win95 and NT)
679 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
680 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
681 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
684 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
686 if (info.dwFlags & STARTF_USESIZE)
688 cs->cx = info.dwXSize;
689 cs->cy = info.dwYSize;
691 else /* if no other hint from the app, pick 3/4 of the screen real estate */
693 RECT r;
694 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
695 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
696 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
703 /***********************************************************************
704 * WIN_CreateWindowEx
706 * Implementation of CreateWindowEx().
708 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
709 WINDOWPROCTYPE type )
711 INT sw = SW_SHOW;
712 struct tagCLASS *classPtr;
713 WND *wndPtr;
714 HWND retvalue;
715 HWND16 hwnd, hwndLinkAfter;
716 POINT maxSize, maxPos, minTrack, maxTrack;
717 INT wndExtra;
718 DWORD clsStyle;
719 WNDPROC winproc;
720 DCE *dce;
721 LRESULT CALLBACK (*localSend32)(HWND, UINT, WPARAM, LPARAM);
723 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
724 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
725 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
726 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
727 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
729 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
730 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
732 /* Find the parent window */
734 if (cs->hwndParent)
736 /* Make sure parent is valid */
737 if (!IsWindow( cs->hwndParent ))
739 WARN("Bad parent %04x\n", cs->hwndParent );
740 return 0;
742 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
743 WARN("No parent for child window\n" );
744 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
747 /* Find the window class */
748 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
749 &wndExtra, &winproc, &clsStyle, &dce )))
751 WARN("Bad class '%s'\n", cs->lpszClass );
752 return 0;
755 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
757 /* Create the window structure */
759 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
761 TRACE("out of memory\n" );
762 return 0;
765 /* Fill the window structure */
767 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
768 wndPtr->next = NULL;
769 wndPtr->child = NULL;
771 if ((cs->style & WS_CHILD) && cs->hwndParent)
773 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
774 wndPtr->owner = NULL;
775 WIN_ReleaseWndPtr(wndPtr->parent);
777 else
779 wndPtr->parent = pWndDesktop;
780 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
781 wndPtr->owner = NULL;
782 else
784 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
785 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
786 WIN_ReleaseWndPtr(wndPtr->owner);
787 WIN_ReleaseWndPtr(tmpWnd);
792 wndPtr->pDriver = wndPtr->parent->pDriver;
793 wndPtr->pDriver->pInitialize(wndPtr);
795 wndPtr->class = classPtr;
796 wndPtr->winproc = winproc;
797 wndPtr->dwMagic = WND_MAGIC;
798 wndPtr->hwndSelf = hwnd;
799 wndPtr->hInstance = cs->hInstance;
800 wndPtr->text = NULL;
801 wndPtr->hmemTaskQ = GetFastQueue16();
802 wndPtr->hrgnUpdate = 0;
803 wndPtr->hrgnWnd = 0;
804 wndPtr->hwndLastActive = hwnd;
805 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
806 wndPtr->dwExStyle = cs->dwExStyle;
807 wndPtr->clsStyle = clsStyle;
808 wndPtr->wIDmenu = 0;
809 wndPtr->helpContext = 0;
810 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
811 wndPtr->pVScroll = NULL;
812 wndPtr->pHScroll = NULL;
813 wndPtr->pProp = NULL;
814 wndPtr->userdata = 0;
815 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
816 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
817 wndPtr->cbWndExtra = wndExtra;
818 wndPtr->irefCount = 1;
820 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
822 /* Call the WH_CBT hook */
824 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
825 ? HWND_BOTTOM : HWND_TOP;
827 if (HOOK_IsHooked( WH_CBT ))
829 CBT_CREATEWNDA cbtc;
830 LRESULT ret;
832 cbtc.lpcs = cs;
833 cbtc.hwndInsertAfter = hwndLinkAfter;
834 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
835 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
836 if (ret)
838 TRACE("CBT-hook returned 0\n");
839 wndPtr->pDriver->pFinalize(wndPtr);
840 USER_HEAP_FREE( hwnd );
841 CLASS_RemoveWindow( classPtr );
842 retvalue = 0;
843 goto end;
847 /* Correct the window style */
849 if (!(cs->style & WS_CHILD))
851 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
852 if (!(cs->style & WS_POPUP))
854 wndPtr->dwStyle |= WS_CAPTION;
855 wndPtr->flags |= WIN_NEED_SIZE;
859 /* Get class or window DC if needed */
861 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
862 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
863 else wndPtr->dce = NULL;
865 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
867 wndPtr->rectWindow.left = cs->x;
868 wndPtr->rectWindow.top = cs->y;
869 wndPtr->rectWindow.right = cs->x + cs->cx;
870 wndPtr->rectWindow.bottom = cs->y + cs->cy;
871 wndPtr->rectClient = wndPtr->rectWindow;
873 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
875 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
877 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
878 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
879 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
880 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
881 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
884 if (cs->cx < 0) cs->cx = 0;
885 if (cs->cy < 0) cs->cy = 0;
887 wndPtr->rectWindow.left = cs->x;
888 wndPtr->rectWindow.top = cs->y;
889 wndPtr->rectWindow.right = cs->x + cs->cx;
890 wndPtr->rectWindow.bottom = cs->y + cs->cy;
891 wndPtr->rectClient = wndPtr->rectWindow;
893 if(!wndPtr->pDriver->pCreateWindow(wndPtr, cs, type == WIN_PROC_32W))
895 retvalue = FALSE;
896 goto end;
899 /* Set the window menu */
901 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
903 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
904 else
906 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
907 if (menuName)
909 if (HIWORD(cs->hInstance))
910 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
911 else
912 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
914 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
918 else wndPtr->wIDmenu = (UINT)cs->hMenu;
920 /* Send the WM_CREATE message
921 * Perhaps we shouldn't allow width/height changes as well.
922 * See p327 in "Internals".
925 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
927 localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
928 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
930 /* Insert the window in the linked list */
932 WIN_LinkWindow( hwnd, hwndLinkAfter );
934 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
935 NULL, NULL, 0, &wndPtr->rectClient );
936 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
937 maxPos.y - wndPtr->rectWindow.top);
938 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
940 /* Send the size messages */
942 if (!(wndPtr->flags & WIN_NEED_SIZE))
944 /* send it anyway */
945 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
946 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
947 WARN("sending bogus WM_SIZE message 0x%08lx\n",
948 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
949 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
950 (*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
951 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
952 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
953 (*localSend32)( hwnd, WM_MOVE, 0,
954 MAKELONG( wndPtr->rectClient.left,
955 wndPtr->rectClient.top ) );
958 /* Show the window, maximizing or minimizing if needed */
960 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
962 RECT16 newPos;
963 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
964 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
965 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
966 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
967 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
968 : SWP_NOZORDER | SWP_FRAMECHANGED;
969 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
970 newPos.right, newPos.bottom, swFlag );
973 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
975 /* Notify the parent window only */
977 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
978 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
979 if( !IsWindow(hwnd) )
981 retvalue = 0;
982 goto end;
986 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
988 /* Call WH_SHELL hook */
990 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
991 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
993 TRACE("created window %04x\n", hwnd);
994 retvalue = hwnd;
995 goto end;
997 WIN_UnlinkWindow( hwnd );
1000 /* Abort window creation */
1002 WARN("aborted by WM_xxCREATE!\n");
1003 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1004 CLASS_RemoveWindow( classPtr );
1005 retvalue = 0;
1006 end:
1007 WIN_ReleaseWndPtr(wndPtr);
1009 return retvalue;
1013 /***********************************************************************
1014 * CreateWindow (USER.41)
1016 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1017 DWORD style, INT16 x, INT16 y, INT16 width,
1018 INT16 height, HWND16 parent, HMENU16 menu,
1019 HINSTANCE16 instance, LPVOID data )
1021 return CreateWindowEx16( 0, className, windowName, style,
1022 x, y, width, height, parent, menu, instance, data );
1026 /***********************************************************************
1027 * CreateWindowEx (USER.452)
1029 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1030 LPCSTR windowName, DWORD style, INT16 x,
1031 INT16 y, INT16 width, INT16 height,
1032 HWND16 parent, HMENU16 menu,
1033 HINSTANCE16 instance, LPVOID data )
1035 ATOM classAtom;
1036 CREATESTRUCTA cs;
1037 char buffer[256];
1039 /* Find the class atom */
1041 if (HIWORD(className))
1043 if (!(classAtom = GlobalFindAtomA( className )))
1045 ERR( "bad class name %s\n", debugres_a(className) );
1046 return 0;
1049 else
1051 classAtom = LOWORD(className);
1052 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1054 ERR( "bad atom %x\n", classAtom);
1055 return 0;
1057 className = buffer;
1060 /* Fix the coordinates */
1062 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1063 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1064 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1065 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1067 /* Create the window */
1069 cs.lpCreateParams = data;
1070 cs.hInstance = (HINSTANCE)instance;
1071 cs.hMenu = (HMENU)menu;
1072 cs.hwndParent = (HWND)parent;
1073 cs.style = style;
1074 cs.lpszName = windowName;
1075 cs.lpszClass = className;
1076 cs.dwExStyle = exStyle;
1078 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1082 /***********************************************************************
1083 * CreateWindowExA (USER32.@)
1085 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1086 LPCSTR windowName, DWORD style, INT x,
1087 INT y, INT width, INT height,
1088 HWND parent, HMENU menu,
1089 HINSTANCE instance, LPVOID data )
1091 ATOM classAtom;
1092 CREATESTRUCTA cs;
1093 char buffer[256];
1095 if(!instance)
1096 instance=GetModuleHandleA(NULL);
1098 if(exStyle & WS_EX_MDICHILD)
1099 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1101 /* Find the class atom */
1103 if (HIWORD(className))
1105 if (!(classAtom = GlobalFindAtomA( className )))
1107 ERR( "bad class name %s\n", debugres_a(className) );
1108 return 0;
1111 else
1113 classAtom = LOWORD(className);
1114 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1116 ERR( "bad atom %x\n", classAtom);
1117 return 0;
1119 className = buffer;
1122 /* Create the window */
1124 cs.lpCreateParams = data;
1125 cs.hInstance = instance;
1126 cs.hMenu = menu;
1127 cs.hwndParent = parent;
1128 cs.x = x;
1129 cs.y = y;
1130 cs.cx = width;
1131 cs.cy = height;
1132 cs.style = style;
1133 cs.lpszName = windowName;
1134 cs.lpszClass = className;
1135 cs.dwExStyle = exStyle;
1137 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1141 /***********************************************************************
1142 * CreateWindowExW (USER32.@)
1144 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1145 LPCWSTR windowName, DWORD style, INT x,
1146 INT y, INT width, INT height,
1147 HWND parent, HMENU menu,
1148 HINSTANCE instance, LPVOID data )
1150 ATOM classAtom;
1151 CREATESTRUCTW cs;
1152 WCHAR buffer[256];
1154 if(!instance)
1155 instance=GetModuleHandleA(NULL);
1157 if(exStyle & WS_EX_MDICHILD)
1158 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1160 /* Find the class atom */
1162 if (HIWORD(className))
1164 if (!(classAtom = GlobalFindAtomW( className )))
1166 ERR( "bad class name %s\n", debugres_w(className) );
1167 return 0;
1170 else
1172 classAtom = LOWORD(className);
1173 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1175 ERR( "bad atom %x\n", classAtom);
1176 return 0;
1178 className = buffer;
1181 /* Create the window */
1183 cs.lpCreateParams = data;
1184 cs.hInstance = instance;
1185 cs.hMenu = menu;
1186 cs.hwndParent = parent;
1187 cs.x = x;
1188 cs.y = y;
1189 cs.cx = width;
1190 cs.cy = height;
1191 cs.style = style;
1192 cs.lpszName = windowName;
1193 cs.lpszClass = className;
1194 cs.dwExStyle = exStyle;
1196 /* Note: we rely on the fact that CREATESTRUCTA and */
1197 /* CREATESTRUCTW have the same layout. */
1198 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1201 /***********************************************************************
1202 * WIN_SendDestroyMsg
1204 static void WIN_SendDestroyMsg( WND* pWnd )
1206 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1207 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1210 * Send the WM_DESTROY to the window.
1212 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1215 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1216 * make sure that the window still exists when we come back.
1218 if (IsWindow(pWnd->hwndSelf))
1220 HWND* pWndArray = NULL;
1221 WND* pChild = NULL;
1222 int nKidCount = 0;
1225 * Now, if the window has kids, we have to send WM_DESTROY messages
1226 * recursively to it's kids. It seems that those calls can also
1227 * trigger re-entrant calls to DestroyWindow for the kids so we must
1228 * protect against corruption of the list of siblings. We first build
1229 * a list of HWNDs representing all the kids.
1231 pChild = WIN_LockWndPtr(pWnd->child);
1232 while( pChild )
1234 nKidCount++;
1235 WIN_UpdateWndPtr(&pChild,pChild->next);
1239 * If there are no kids, we're done.
1241 if (nKidCount==0)
1242 return;
1244 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1247 * Sanity check
1249 if (pWndArray==NULL)
1250 return;
1253 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1254 * call, our linked list of siblings should be safe.
1256 nKidCount = 0;
1257 pChild = WIN_LockWndPtr(pWnd->child);
1258 while( pChild )
1260 pWndArray[nKidCount] = pChild->hwndSelf;
1261 nKidCount++;
1262 WIN_UpdateWndPtr(&pChild,pChild->next);
1266 * Now that we have a list, go through that list again and send the destroy
1267 * message to those windows. We are using the HWND to retrieve the
1268 * WND pointer so we are effectively checking that all the kid windows are
1269 * still valid before sending the message.
1271 while (nKidCount>0)
1273 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1275 if (pChild!=NULL)
1277 WIN_SendDestroyMsg( pChild );
1278 WIN_ReleaseWndPtr(pChild);
1283 * Cleanup
1285 HeapFree(GetProcessHeap(), 0, pWndArray);
1287 else
1288 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1292 /***********************************************************************
1293 * DestroyWindow (USER.53)
1295 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1297 return DestroyWindow(hwnd);
1301 /***********************************************************************
1302 * DestroyWindow (USER32.@)
1304 BOOL WINAPI DestroyWindow( HWND hwnd )
1306 WND * wndPtr;
1307 BOOL retvalue;
1308 HWND h;
1309 BOOL bFocusSet = FALSE;
1311 TRACE("(%04x)\n", hwnd);
1313 /* Initialization */
1315 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1316 if (wndPtr == pWndDesktop)
1318 retvalue = FALSE; /* Can't destroy desktop */
1319 goto end;
1322 /* Look whether the focus is within the tree of windows we will
1323 * be destroying.
1325 h = GetFocus16();
1326 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1328 if (h == hwnd)
1330 SetFocus(GetParent(h));
1331 bFocusSet = TRUE;
1332 break;
1334 h = GetParent(h);
1336 /* If the focus is on the window we will destroy and it has no parent,
1337 * set the focus to 0.
1339 if (! bFocusSet && (h == hwnd))
1341 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1342 SetFocus(0);
1345 /* Call hooks */
1347 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1349 retvalue = FALSE;
1350 goto end;
1353 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1355 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1356 /* FIXME: clean up palette - see "Internals" p.352 */
1359 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1360 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1362 /* Notify the parent window only */
1363 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1364 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1365 if( !IsWindow(hwnd) )
1367 retvalue = TRUE;
1368 goto end;
1372 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1374 /* Hide the window */
1376 if (wndPtr->dwStyle & WS_VISIBLE)
1378 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1379 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1380 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1381 if (!IsWindow(hwnd))
1383 retvalue = TRUE;
1384 goto end;
1388 /* Recursively destroy owned windows */
1390 if( !(wndPtr->dwStyle & WS_CHILD) )
1392 /* make sure top menu popup doesn't get destroyed */
1393 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1395 for (;;)
1397 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1398 while (siblingPtr)
1400 if (siblingPtr->owner == wndPtr)
1402 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1403 break;
1404 else
1405 siblingPtr->owner = NULL;
1407 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1409 if (siblingPtr)
1411 DestroyWindow( siblingPtr->hwndSelf );
1412 WIN_ReleaseWndPtr(siblingPtr);
1414 else break;
1417 if( !Options.managed || EVENT_CheckFocus() )
1418 WINPOS_ActivateOtherWindow(wndPtr);
1420 if( wndPtr->owner &&
1421 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1422 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1425 /* Send destroy messages */
1427 WIN_SendDestroyMsg( wndPtr );
1428 if (!IsWindow(hwnd))
1430 retvalue = TRUE;
1431 goto end;
1434 /* Unlink now so we won't bother with the children later on */
1436 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1438 /* Destroy the window storage */
1440 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1441 retvalue = TRUE;
1442 end:
1443 WIN_ReleaseWndPtr(wndPtr);
1444 return retvalue;
1448 /***********************************************************************
1449 * CloseWindow (USER.43)
1451 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1453 return CloseWindow( hwnd );
1457 /***********************************************************************
1458 * CloseWindow (USER32.@)
1460 BOOL WINAPI CloseWindow( HWND hwnd )
1462 WND * wndPtr = WIN_FindWndPtr( hwnd );
1463 BOOL retvalue;
1465 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1467 retvalue = FALSE;
1468 goto end;
1470 ShowWindow( hwnd, SW_MINIMIZE );
1471 retvalue = TRUE;
1472 end:
1473 WIN_ReleaseWndPtr(wndPtr);
1474 return retvalue;
1479 /***********************************************************************
1480 * OpenIcon (USER.44)
1482 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1484 return OpenIcon( hwnd );
1488 /***********************************************************************
1489 * OpenIcon (USER32.@)
1491 BOOL WINAPI OpenIcon( HWND hwnd )
1493 if (!IsIconic( hwnd )) return FALSE;
1494 ShowWindow( hwnd, SW_SHOWNORMAL );
1495 return TRUE;
1499 /***********************************************************************
1500 * WIN_FindWindow
1502 * Implementation of FindWindow() and FindWindowEx().
1504 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1505 LPCWSTR title )
1507 WND *pWnd;
1508 HWND retvalue;
1510 if (child)
1512 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1513 if (parent)
1515 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1517 retvalue = 0;
1518 goto end;
1521 else if (pWnd->parent != pWndDesktop)
1523 retvalue = 0;
1524 goto end;
1526 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1528 else
1530 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1532 retvalue = 0;
1533 goto end;
1535 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1537 if (!pWnd)
1539 retvalue = 0;
1540 goto end;
1543 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1545 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1546 continue; /* Not the right class */
1548 /* Now check the title */
1550 if (!title)
1552 retvalue = pWnd->hwndSelf;
1553 goto end;
1555 if (pWnd->text && !strcmpW( pWnd->text, title ))
1557 retvalue = pWnd->hwndSelf;
1558 goto end;
1561 retvalue = 0;
1562 /* In this case we need to check whether other processes
1563 own a window with the given paramters on the Desktop,
1564 but we don't, so let's at least warn about it */
1565 FIXME("Returning 0 without checking other processes\n");
1566 end:
1567 WIN_ReleaseWndPtr(pWnd);
1568 return retvalue;
1573 /***********************************************************************
1574 * FindWindow (USER.50)
1576 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1578 return FindWindowA( className, title );
1582 /***********************************************************************
1583 * FindWindowEx (USER.427)
1585 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1587 return FindWindowExA( parent, child, className, title );
1591 /***********************************************************************
1592 * FindWindowA (USER32.@)
1594 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1596 HWND ret = FindWindowExA( 0, 0, className, title );
1597 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1598 return ret;
1602 /***********************************************************************
1603 * FindWindowExA (USER32.@)
1605 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1606 LPCSTR className, LPCSTR title )
1608 ATOM atom = 0;
1609 LPWSTR buffer;
1610 HWND hwnd;
1612 if (className)
1614 /* If the atom doesn't exist, then no class */
1615 /* with this name exists either. */
1616 if (!(atom = GlobalFindAtomA( className )))
1618 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1619 return 0;
1623 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1624 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1625 HeapFree( GetProcessHeap(), 0, buffer );
1626 return hwnd;
1630 /***********************************************************************
1631 * FindWindowExW (USER32.@)
1633 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1634 LPCWSTR className, LPCWSTR title )
1636 ATOM atom = 0;
1638 if (className)
1640 /* If the atom doesn't exist, then no class */
1641 /* with this name exists either. */
1642 if (!(atom = GlobalFindAtomW( className )))
1644 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1645 return 0;
1648 return WIN_FindWindow( parent, child, atom, title );
1652 /***********************************************************************
1653 * FindWindowW (USER32.@)
1655 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1657 return FindWindowExW( 0, 0, className, title );
1661 /**********************************************************************
1662 * WIN_GetDesktop
1663 * returns a locked pointer
1665 WND *WIN_GetDesktop(void)
1667 return WIN_LockWndPtr(pWndDesktop);
1669 /**********************************************************************
1670 * WIN_ReleaseDesktop
1671 * unlock the desktop pointer
1673 void WIN_ReleaseDesktop(void)
1675 WIN_ReleaseWndPtr(pWndDesktop);
1679 /**********************************************************************
1680 * GetDesktopWindow (USER.286)
1682 HWND16 WINAPI GetDesktopWindow16(void)
1684 return (HWND16)pWndDesktop->hwndSelf;
1688 /**********************************************************************
1689 * GetDesktopWindow (USER32.@)
1691 HWND WINAPI GetDesktopWindow(void)
1693 if (pWndDesktop) return pWndDesktop->hwndSelf;
1694 ERR( "You need the -desktop option when running with native USER\n" );
1695 ExitProcess(1);
1696 return 0;
1700 /**********************************************************************
1701 * GetDesktopHwnd (USER.278)
1703 * Exactly the same thing as GetDesktopWindow(), but not documented.
1704 * Don't ask me why...
1706 HWND16 WINAPI GetDesktopHwnd16(void)
1708 return (HWND16)pWndDesktop->hwndSelf;
1712 /*******************************************************************
1713 * EnableWindow (USER.34)
1715 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1717 return EnableWindow( hwnd, enable );
1721 /*******************************************************************
1722 * EnableWindow (USER32.@)
1724 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1726 WND *wndPtr;
1727 BOOL retvalue;
1729 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1731 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1732 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1734 /* Enable window */
1735 wndPtr->dwStyle &= ~WS_DISABLED;
1737 if( wndPtr->flags & WIN_NATIVE )
1738 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1740 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1741 retvalue = TRUE;
1742 goto end;
1744 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1746 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1748 /* Disable window */
1749 wndPtr->dwStyle |= WS_DISABLED;
1751 if( wndPtr->flags & WIN_NATIVE )
1752 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1754 if (hwnd == GetFocus())
1756 SetFocus( 0 ); /* A disabled window can't have the focus */
1758 if (hwnd == GetCapture())
1760 ReleaseCapture(); /* A disabled window can't capture the mouse */
1762 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1763 retvalue = FALSE;
1764 goto end;
1766 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1767 end:
1768 WIN_ReleaseWndPtr(wndPtr);
1769 return retvalue;
1773 /***********************************************************************
1774 * IsWindowEnabled (USER.35)
1776 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1778 return IsWindowEnabled(hWnd);
1782 /***********************************************************************
1783 * IsWindowEnabled (USER32.@)
1785 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1787 WND * wndPtr;
1788 BOOL retvalue;
1790 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1791 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1792 WIN_ReleaseWndPtr(wndPtr);
1793 return retvalue;
1798 /***********************************************************************
1799 * IsWindowUnicode (USER32.@)
1801 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1803 WND * wndPtr;
1804 BOOL retvalue;
1806 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1807 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1808 WIN_ReleaseWndPtr(wndPtr);
1809 return retvalue;
1813 /**********************************************************************
1814 * GetWindowWord (USER.133)
1816 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1818 return GetWindowWord( hwnd, offset );
1822 /**********************************************************************
1823 * GetWindowWord (USER32.@)
1825 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1827 WORD retvalue;
1828 WND * wndPtr = WIN_FindWndPtr( hwnd );
1829 if (!wndPtr) return 0;
1830 if (offset >= 0)
1832 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1834 WARN("Invalid offset %d\n", offset );
1835 retvalue = 0;
1836 goto end;
1838 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1839 goto end;
1841 switch(offset)
1843 case GWW_ID:
1844 if (HIWORD(wndPtr->wIDmenu))
1845 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1846 wndPtr->wIDmenu);
1847 retvalue = (WORD)wndPtr->wIDmenu;
1848 goto end;
1849 case GWW_HWNDPARENT:
1850 retvalue = GetParent(hwnd);
1851 goto end;
1852 case GWW_HINSTANCE:
1853 if (HIWORD(wndPtr->hInstance))
1854 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1855 wndPtr->hInstance);
1856 retvalue = (WORD)wndPtr->hInstance;
1857 goto end;
1858 default:
1859 WARN("Invalid offset %d\n", offset );
1860 retvalue = 0;
1861 goto end;
1863 end:
1864 WIN_ReleaseWndPtr(wndPtr);
1865 return retvalue;
1868 /**********************************************************************
1869 * SetWindowWord (USER.134)
1871 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1873 return SetWindowWord( hwnd, offset, newval );
1877 /**********************************************************************
1878 * SetWindowWord (USER32.@)
1880 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1882 WORD *ptr, retval;
1883 WND * wndPtr = WIN_FindWndPtr( hwnd );
1884 if (!wndPtr) return 0;
1885 if (offset >= 0)
1887 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1889 WARN("Invalid offset %d\n", offset );
1890 retval = 0;
1891 goto end;
1893 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1895 else switch(offset)
1897 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1898 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1899 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1900 goto end;
1901 default:
1902 WARN("Invalid offset %d\n", offset );
1903 retval = 0;
1904 goto end;
1906 retval = *ptr;
1907 *ptr = newval;
1908 end:
1909 WIN_ReleaseWndPtr(wndPtr);
1910 return retval;
1914 /**********************************************************************
1915 * WIN_GetWindowLong
1917 * Helper function for GetWindowLong().
1919 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1921 LONG retvalue;
1922 WND * wndPtr = WIN_FindWndPtr( hwnd );
1923 if (!wndPtr) return 0;
1924 if (offset >= 0)
1926 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1928 WARN("Invalid offset %d\n", offset );
1929 retvalue = 0;
1930 goto end;
1932 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1933 /* Special case for dialog window procedure */
1934 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1936 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1937 goto end;
1939 goto end;
1941 switch(offset)
1943 case GWL_USERDATA: retvalue = wndPtr->userdata;
1944 goto end;
1945 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1946 goto end;
1947 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1948 goto end;
1949 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1950 goto end;
1951 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1952 type );
1953 goto end;
1954 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1955 goto end;
1956 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1957 goto end;
1958 default:
1959 WARN("Unknown offset %d\n", offset );
1961 retvalue = 0;
1962 end:
1963 WIN_ReleaseWndPtr(wndPtr);
1964 return retvalue;
1968 /**********************************************************************
1969 * WIN_SetWindowLong
1971 * Helper function for SetWindowLong().
1973 * 0 is the failure code. However, in the case of failure SetLastError
1974 * must be set to distinguish between a 0 return value and a failure.
1976 * FIXME: The error values for SetLastError may not be right. Can
1977 * someone check with the real thing?
1979 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1980 WINDOWPROCTYPE type )
1982 LONG *ptr, retval;
1983 WND * wndPtr = WIN_FindWndPtr( hwnd );
1984 STYLESTRUCT style;
1986 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1988 if (!wndPtr)
1990 /* Is this the right error? */
1991 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1992 return 0;
1995 if (offset >= 0)
1997 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1999 WARN("Invalid offset %d\n", offset );
2001 /* Is this the right error? */
2002 SetLastError( ERROR_OUTOFMEMORY );
2004 retval = 0;
2005 goto end;
2007 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2008 /* Special case for dialog window procedure */
2009 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2011 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2012 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2013 type, WIN_PROC_WINDOW );
2014 goto end;
2017 else switch(offset)
2019 case GWL_ID:
2020 ptr = (DWORD*)&wndPtr->wIDmenu;
2021 break;
2022 case GWL_HINSTANCE:
2023 retval = SetWindowWord( hwnd, offset, newval );
2024 goto end;
2025 case GWL_WNDPROC:
2026 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2027 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2028 type, WIN_PROC_WINDOW );
2029 goto end;
2030 case GWL_STYLE:
2031 style.styleOld = wndPtr->dwStyle;
2032 style.styleNew = newval;
2033 if (wndPtr->flags & WIN_ISWIN32)
2034 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2035 wndPtr->dwStyle = style.styleNew;
2036 if (wndPtr->flags & WIN_ISWIN32)
2037 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2038 retval = style.styleOld;
2039 goto end;
2041 case GWL_USERDATA:
2042 ptr = &wndPtr->userdata;
2043 break;
2044 case GWL_EXSTYLE:
2045 style.styleOld = wndPtr->dwExStyle;
2046 style.styleNew = newval;
2047 if (wndPtr->flags & WIN_ISWIN32)
2048 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2049 wndPtr->dwExStyle = newval;
2050 if (wndPtr->flags & WIN_ISWIN32)
2051 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2052 retval = style.styleOld;
2053 goto end;
2055 default:
2056 WARN("Invalid offset %d\n", offset );
2058 /* Don't think this is right error but it should do */
2059 SetLastError( ERROR_OUTOFMEMORY );
2061 retval = 0;
2062 goto end;
2064 retval = *ptr;
2065 *ptr = newval;
2066 end:
2067 WIN_ReleaseWndPtr(wndPtr);
2068 return retval;
2072 /**********************************************************************
2073 * GetWindowLong (USER.135)
2075 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2077 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2081 /**********************************************************************
2082 * GetWindowLongA (USER32.@)
2084 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2086 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2090 /**********************************************************************
2091 * GetWindowLongW (USER32.@)
2093 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2095 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2099 /**********************************************************************
2100 * SetWindowLong (USER.136)
2102 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2104 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2108 /**********************************************************************
2109 * SetWindowLongA (USER32.@)
2111 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2113 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2117 /**********************************************************************
2118 * SetWindowLongW (USER32.@) Set window attribute
2120 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2121 * value in a window's extra memory.
2123 * The _hwnd_ parameter specifies the window. is the handle to a
2124 * window that has extra memory. The _newval_ parameter contains the
2125 * new attribute or extra memory value. If positive, the _offset_
2126 * parameter is the byte-addressed location in the window's extra
2127 * memory to set. If negative, _offset_ specifies the window
2128 * attribute to set, and should be one of the following values:
2130 * GWL_EXSTYLE The window's extended window style
2132 * GWL_STYLE The window's window style.
2134 * GWL_WNDPROC Pointer to the window's window procedure.
2136 * GWL_HINSTANCE The window's pplication instance handle.
2138 * GWL_ID The window's identifier.
2140 * GWL_USERDATA The window's user-specified data.
2142 * If the window is a dialog box, the _offset_ parameter can be one of
2143 * the following values:
2145 * DWL_DLGPROC The address of the window's dialog box procedure.
2147 * DWL_MSGRESULT The return value of a message
2148 * that the dialog box procedure processed.
2150 * DWL_USER Application specific information.
2152 * RETURNS
2154 * If successful, returns the previous value located at _offset_. Otherwise,
2155 * returns 0.
2157 * NOTES
2159 * Extra memory for a window class is specified by a nonzero cbWndExtra
2160 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2161 * time of class creation.
2163 * Using GWL_WNDPROC to set a new window procedure effectively creates
2164 * a window subclass. Use CallWindowProc() in the new windows procedure
2165 * to pass messages to the superclass's window procedure.
2167 * The user data is reserved for use by the application which created
2168 * the window.
2170 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2171 * instead, call the EnableWindow() function to change the window's
2172 * disabled state.
2174 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2175 * SetParent() instead.
2177 * Win95:
2178 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2179 * it sends WM_STYLECHANGING before changing the settings
2180 * and WM_STYLECHANGED afterwards.
2181 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2183 * BUGS
2185 * GWL_STYLE does not dispatch WM_STYLE... messages.
2187 * CONFORMANCE
2189 * ECMA-234, Win32
2192 LONG WINAPI SetWindowLongW(
2193 HWND hwnd, /* [in] window to alter */
2194 INT offset, /* [in] offset, in bytes, of location to alter */
2195 LONG newval /* [in] new value of location */
2197 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2201 /*******************************************************************
2202 * GetWindowText (USER.36)
2204 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2206 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2210 /*******************************************************************
2211 * GetWindowTextA (USER32.@)
2213 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2215 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2216 (LPARAM)lpString );
2219 /*******************************************************************
2220 * InternalGetWindowText (USER32.@)
2222 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2224 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2225 return GetWindowTextW(hwnd,lpString,nMaxCount);
2229 /*******************************************************************
2230 * GetWindowTextW (USER32.@)
2232 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2234 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2235 (LPARAM)lpString );
2239 /*******************************************************************
2240 * SetWindowText (USER.37)
2242 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2244 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2248 /*******************************************************************
2249 * SetWindowText (USER32.@)
2251 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2253 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2257 /*******************************************************************
2258 * SetWindowTextW (USER32.@)
2260 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2262 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2266 /*******************************************************************
2267 * GetWindowTextLength (USER.38)
2269 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2271 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2275 /*******************************************************************
2276 * GetWindowTextLengthA (USER32.@)
2278 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2280 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2283 /*******************************************************************
2284 * GetWindowTextLengthW (USER32.@)
2286 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2288 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2292 /*******************************************************************
2293 * IsWindow (USER.47)
2295 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2297 CURRENT_STACK16->es = USER_HeapSel;
2298 return IsWindow( hwnd );
2302 /*******************************************************************
2303 * IsWindow (USER32.@)
2305 BOOL WINAPI IsWindow( HWND hwnd )
2307 WND * wndPtr;
2308 BOOL retvalue;
2310 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2311 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2312 WIN_ReleaseWndPtr(wndPtr);
2313 return retvalue;
2318 /*****************************************************************
2319 * GetParent (USER.46)
2321 HWND16 WINAPI GetParent16( HWND16 hwnd )
2323 return (HWND16)GetParent( hwnd );
2327 /*****************************************************************
2328 * GetParent (USER32.@)
2330 HWND WINAPI GetParent( HWND hwnd )
2332 WND *wndPtr;
2333 HWND retvalue = 0;
2335 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2336 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2337 goto end;
2339 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2340 if (wndPtr)
2341 retvalue = wndPtr->hwndSelf;
2343 end:
2344 WIN_ReleaseWndPtr(wndPtr);
2345 return retvalue;
2349 /*****************************************************************
2350 * WIN_GetTopParent
2352 * Get the top-level parent for a child window.
2353 * returns a locked pointer
2355 WND* WIN_GetTopParentPtr( WND* pWnd )
2357 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2359 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2361 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2363 return tmpWnd;
2366 /*****************************************************************
2367 * WIN_GetTopParent
2369 * Get the top-level parent for a child window.
2371 HWND WIN_GetTopParent( HWND hwnd )
2373 HWND retvalue;
2374 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2375 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2377 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2378 WIN_ReleaseWndPtr(tmpPtr);
2379 WIN_ReleaseWndPtr(wndPtr);
2380 return retvalue;
2384 /*****************************************************************
2385 * SetParent (USER.233)
2387 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2389 return SetParent( hwndChild, hwndNewParent );
2393 /*****************************************************************
2394 * SetParent (USER32.@)
2396 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2398 WND *wndPtr;
2399 DWORD dwStyle;
2400 WND *pWndNewParent;
2401 WND *pWndOldParent;
2402 HWND retvalue;
2405 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2407 dwStyle = wndPtr->dwStyle;
2409 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2410 : WIN_LockWndPtr(pWndDesktop);
2412 /* Windows hides the window first, then shows it again
2413 * including the WM_SHOWWINDOW messages and all */
2414 if (dwStyle & WS_VISIBLE)
2415 ShowWindow( hwndChild, SW_HIDE );
2417 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2419 /* SetParent additionally needs to make hwndChild the topmost window
2420 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2421 WM_WINDOWPOSCHANGED notification messages.
2423 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2424 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2425 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2426 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2428 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2430 WIN_ReleaseWndPtr(pWndOldParent);
2431 WIN_ReleaseWndPtr(pWndNewParent);
2432 WIN_ReleaseWndPtr(wndPtr);
2434 return retvalue;
2438 /*******************************************************************
2439 * IsChild (USER.48)
2441 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2443 return IsChild(parent,child);
2447 /*******************************************************************
2448 * IsChild (USER32.@)
2450 BOOL WINAPI IsChild( HWND parent, HWND child )
2452 WND * wndPtr = WIN_FindWndPtr( child );
2453 while (wndPtr && wndPtr->parent)
2455 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2456 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2457 if (wndPtr->hwndSelf == parent)
2459 WIN_ReleaseWndPtr(wndPtr);
2460 return TRUE;
2463 WIN_ReleaseWndPtr(wndPtr);
2464 return FALSE;
2468 /***********************************************************************
2469 * IsWindowVisible (USER.49)
2471 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2473 return IsWindowVisible(hwnd);
2477 /***********************************************************************
2478 * IsWindowVisible (USER32.@)
2480 BOOL WINAPI IsWindowVisible( HWND hwnd )
2482 BOOL retval;
2483 WND *wndPtr = WIN_FindWndPtr( hwnd );
2484 while (wndPtr && wndPtr->parent)
2486 if (!(wndPtr->dwStyle & WS_VISIBLE))
2488 WIN_ReleaseWndPtr(wndPtr);
2489 return FALSE;
2491 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2493 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2494 WIN_ReleaseWndPtr(wndPtr);
2495 return retval;
2499 /***********************************************************************
2500 * WIN_IsWindowDrawable
2502 * hwnd is drawable when it is visible, all parents are not
2503 * minimized, and it is itself not minimized unless we are
2504 * trying to draw its default class icon.
2506 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2508 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2509 if ((wnd->dwStyle & WS_MINIMIZE) &&
2510 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2511 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2512 if( wnd->dwStyle & WS_MINIMIZE ||
2513 !(wnd->dwStyle & WS_VISIBLE) ) break;
2514 return (wnd == NULL);
2518 /*******************************************************************
2519 * GetTopWindow (USER.229)
2521 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2523 return GetTopWindow(hwnd);
2527 /*******************************************************************
2528 * GetTopWindow (USER32.@)
2530 HWND WINAPI GetTopWindow( HWND hwnd )
2532 HWND retval = 0;
2533 WND * wndPtr = (hwnd) ?
2534 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2536 if (wndPtr && wndPtr->child)
2537 retval = wndPtr->child->hwndSelf;
2539 WIN_ReleaseWndPtr(wndPtr);
2540 return retval;
2544 /*******************************************************************
2545 * GetWindow (USER.262)
2547 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2549 return GetWindow( hwnd,rel );
2553 /*******************************************************************
2554 * GetWindow (USER32.@)
2556 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2558 HWND retval;
2560 WND * wndPtr = WIN_FindWndPtr( hwnd );
2561 if (!wndPtr) return 0;
2562 switch(rel)
2564 case GW_HWNDFIRST:
2565 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2566 goto end;
2568 case GW_HWNDLAST:
2569 if (!wndPtr->parent)
2571 retval = 0; /* Desktop window */
2572 goto end;
2574 while (wndPtr->next)
2576 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2578 retval = wndPtr->hwndSelf;
2579 goto end;
2581 case GW_HWNDNEXT:
2582 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2583 goto end;
2585 case GW_HWNDPREV:
2586 if (!wndPtr->parent)
2588 retval = 0; /* Desktop window */
2589 goto end;
2591 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2592 if (wndPtr->hwndSelf == hwnd)
2594 retval = 0; /* First in list */
2595 goto end;
2597 while (wndPtr->next)
2599 if (wndPtr->next->hwndSelf == hwnd)
2601 retval = wndPtr->hwndSelf;
2602 goto end;
2604 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2606 retval = 0;
2607 goto end;
2609 case GW_OWNER:
2610 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2611 goto end;
2613 case GW_CHILD:
2614 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2615 goto end;
2617 retval = 0;
2618 end:
2619 WIN_ReleaseWndPtr(wndPtr);
2620 return retval;
2624 /*******************************************************************
2625 * GetNextWindow (USER.230)
2627 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2629 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2630 return GetWindow16( hwnd, flag );
2633 /***********************************************************************
2634 * WIN_InternalShowOwnedPopups
2636 * Internal version of ShowOwnedPopups; Wine functions should use this
2637 * to avoid interfering with application calls to ShowOwnedPopups
2638 * and to make sure the application can't prevent showing/hiding.
2640 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2644 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2646 INT totalChild=0, count=0;
2648 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2650 if (!pWnd) return TRUE;
2653 * Show windows Lowest first, Highest last to preserve Z-Order
2655 for (count = totalChild-1 ; count >=0; count--)
2657 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2659 if (fShow)
2661 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2662 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2665 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2667 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2668 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2671 else
2673 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2674 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2675 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2678 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2680 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2681 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2682 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2687 WIN_ReleaseDesktop();
2688 WIN_ReleaseWinArray(pWnd);
2690 return TRUE;
2693 /*******************************************************************
2694 * ShowOwnedPopups (USER.265)
2696 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2698 ShowOwnedPopups( owner, fShow );
2702 /*******************************************************************
2703 * ShowOwnedPopups (USER32.@)
2705 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2707 UINT totalChild=0, count=0;
2709 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2711 if (!pWnd) return TRUE;
2713 for (; count < totalChild; count++)
2715 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2717 if (fShow)
2719 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2722 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2723 * regardless of the state of the owner
2725 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2726 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2729 else
2731 if (IsWindowVisible(pWnd[count]->hwndSelf))
2734 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2735 * regardless of the state of the owner
2737 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2738 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2744 WIN_ReleaseDesktop();
2745 WIN_ReleaseWinArray(pWnd);
2746 return TRUE;
2750 /*******************************************************************
2751 * GetLastActivePopup (USER.287)
2753 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2755 return GetLastActivePopup( hwnd );
2758 /*******************************************************************
2759 * GetLastActivePopup (USER32.@)
2761 HWND WINAPI GetLastActivePopup( HWND hwnd )
2763 HWND retval;
2764 WND *wndPtr =WIN_FindWndPtr(hwnd);
2765 if (!wndPtr) return hwnd;
2766 retval = wndPtr->hwndLastActive;
2767 WIN_ReleaseWndPtr(wndPtr);
2768 if ((retval != hwnd) && (!IsWindow(retval)))
2769 retval = hwnd;
2770 return retval;
2774 /*******************************************************************
2775 * WIN_BuildWinArray
2777 * Build an array of pointers to the children of a given window.
2778 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2779 * when no windows are found.
2781 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2783 /* Future: this function will lock all windows associated with this array */
2785 WND **list, **ppWnd;
2786 WND *pWnd;
2787 UINT count = 0, skipOwned, skipHidden;
2788 DWORD skipFlags;
2790 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2791 skipOwned = bwaFlags & BWA_SKIPOWNED;
2792 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2793 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2795 /* First count the windows */
2797 if (!wndPtr)
2798 wndPtr = WIN_GetDesktop();
2800 pWnd = WIN_LockWndPtr(wndPtr->child);
2801 while (pWnd)
2803 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2804 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2805 count++;
2806 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2809 if( count )
2811 /* Now build the list of all windows */
2813 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2815 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2817 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2818 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2820 *ppWnd++ = pWnd;
2821 count++;
2824 WIN_ReleaseWndPtr(pWnd);
2825 *ppWnd = NULL;
2827 else count = 0;
2828 } else list = NULL;
2830 if( pTotal ) *pTotal = count;
2831 return list;
2833 /*******************************************************************
2834 * WIN_ReleaseWinArray
2836 void WIN_ReleaseWinArray(WND **wndArray)
2838 /* Future: this function will also unlock all windows associated with wndArray */
2839 HeapFree( GetProcessHeap(), 0, wndArray );
2843 /*******************************************************************
2844 * EnumWindows (USER32.@)
2846 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2848 WND **list, **ppWnd;
2850 /* We have to build a list of all windows first, to avoid */
2851 /* unpleasant side-effects, for instance if the callback */
2852 /* function changes the Z-order of the windows. */
2854 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2856 WIN_ReleaseDesktop();
2857 return FALSE;
2860 /* Now call the callback function for every window */
2862 for (ppWnd = list; *ppWnd; ppWnd++)
2864 LRESULT lpEnumFuncRetval;
2865 int iWndsLocks = 0;
2866 /* Make sure that the window still exists */
2867 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2869 /* To avoid any deadlocks, all the locks on the windows
2870 structures must be suspended before the control
2871 is passed to the application */
2872 iWndsLocks = WIN_SuspendWndsLock();
2873 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2874 WIN_RestoreWndsLock(iWndsLocks);
2876 if (!lpEnumFuncRetval) break;
2878 WIN_ReleaseWinArray(list);
2879 WIN_ReleaseDesktop();
2880 return TRUE;
2884 /**********************************************************************
2885 * EnumTaskWindows (USER.225)
2887 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2888 LPARAM lParam )
2890 WND **list, **ppWnd;
2892 /* This function is the same as EnumWindows(), */
2893 /* except for an added check on the window's task. */
2895 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2897 WIN_ReleaseDesktop();
2898 return FALSE;
2901 /* Now call the callback function for every window */
2903 for (ppWnd = list; *ppWnd; ppWnd++)
2905 LRESULT funcRetval;
2906 int iWndsLocks = 0;
2907 /* Make sure that the window still exists */
2908 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2909 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2911 /* To avoid any deadlocks, all the locks on the windows
2912 structures must be suspended before the control
2913 is passed to the application */
2914 iWndsLocks = WIN_SuspendWndsLock();
2915 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2916 WIN_RestoreWndsLock(iWndsLocks);
2918 if (!funcRetval) break;
2920 WIN_ReleaseWinArray(list);
2921 WIN_ReleaseDesktop();
2922 return TRUE;
2926 /**********************************************************************
2927 * EnumThreadWindows (USER32.@)
2929 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2931 TEB *teb = THREAD_IdToTEB(id);
2933 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2937 /**********************************************************************
2938 * WIN_EnumChildWindows
2940 * Helper function for EnumChildWindows().
2942 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2944 WND **childList;
2945 BOOL16 ret = FALSE;
2947 for ( ; *ppWnd; ppWnd++)
2949 int iWndsLocks = 0;
2951 /* Make sure that the window still exists */
2952 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2953 /* Build children list first */
2954 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2956 /* To avoid any deadlocks, all the locks on the windows
2957 structures must be suspended before the control
2958 is passed to the application */
2959 iWndsLocks = WIN_SuspendWndsLock();
2960 ret = func( (*ppWnd)->hwndSelf, lParam );
2961 WIN_RestoreWndsLock(iWndsLocks);
2963 if (childList)
2965 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2966 WIN_ReleaseWinArray(childList);
2968 if (!ret) return FALSE;
2970 return TRUE;
2974 /**********************************************************************
2975 * EnumChildWindows (USER32.@)
2977 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2978 LPARAM lParam )
2980 WND **list, *pParent;
2982 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2983 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2985 WIN_ReleaseWndPtr(pParent);
2986 return FALSE;
2988 WIN_EnumChildWindows( list, func, lParam );
2989 WIN_ReleaseWinArray(list);
2990 WIN_ReleaseWndPtr(pParent);
2991 return TRUE;
2995 /*******************************************************************
2996 * AnyPopup (USER.52)
2998 BOOL16 WINAPI AnyPopup16(void)
3000 return AnyPopup();
3004 /*******************************************************************
3005 * AnyPopup (USER32.@)
3007 BOOL WINAPI AnyPopup(void)
3009 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3010 BOOL retvalue;
3012 while (wndPtr)
3014 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3016 retvalue = TRUE;
3017 goto end;
3019 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3021 retvalue = FALSE;
3022 end:
3023 WIN_ReleaseWndPtr(wndPtr);
3024 return retvalue;
3028 /*******************************************************************
3029 * FlashWindow (USER.105)
3031 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3033 return FlashWindow( hWnd, bInvert );
3037 /*******************************************************************
3038 * FlashWindow (USER32.@)
3040 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3042 WND *wndPtr = WIN_FindWndPtr(hWnd);
3044 TRACE("%04x\n", hWnd);
3046 if (!wndPtr) return FALSE;
3048 if (wndPtr->dwStyle & WS_MINIMIZE)
3050 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3052 HDC hDC = GetDC(hWnd);
3054 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3055 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3057 ReleaseDC( hWnd, hDC );
3058 wndPtr->flags |= WIN_NCACTIVATED;
3060 else
3062 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3063 RDW_UPDATENOW | RDW_FRAME, 0 );
3064 wndPtr->flags &= ~WIN_NCACTIVATED;
3066 WIN_ReleaseWndPtr(wndPtr);
3067 return TRUE;
3069 else
3071 WPARAM16 wparam;
3072 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3073 else wparam = (hWnd == GetActiveWindow());
3075 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3076 WIN_ReleaseWndPtr(wndPtr);
3077 return wparam;
3082 /*******************************************************************
3083 * SetSysModalWindow (USER.188)
3085 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3087 HWND hWndOldModal = hwndSysModal;
3088 hwndSysModal = hWnd;
3089 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3090 return hWndOldModal;
3094 /*******************************************************************
3095 * GetSysModalWindow (USER.189)
3097 HWND16 WINAPI GetSysModalWindow16(void)
3099 return hwndSysModal;
3103 /*******************************************************************
3104 * GetWindowContextHelpId (USER32.@)
3106 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3108 DWORD retval;
3109 WND *wnd = WIN_FindWndPtr( hwnd );
3110 if (!wnd) return 0;
3111 retval = wnd->helpContext;
3112 WIN_ReleaseWndPtr(wnd);
3113 return retval;
3117 /*******************************************************************
3118 * SetWindowContextHelpId (USER32.@)
3120 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3122 WND *wnd = WIN_FindWndPtr( hwnd );
3123 if (!wnd) return FALSE;
3124 wnd->helpContext = id;
3125 WIN_ReleaseWndPtr(wnd);
3126 return TRUE;
3130 /*******************************************************************
3131 * DRAG_QueryUpdate
3133 * recursively find a child that contains spDragInfo->pt point
3134 * and send WM_QUERYDROPOBJECT
3136 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3138 BOOL16 wParam, bResult = 0;
3139 POINT pt;
3140 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3141 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3142 RECT tempRect;
3144 if( !ptrQueryWnd || !ptrDragInfo )
3145 goto end;
3147 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3149 GetWindowRect(hQueryWnd,&tempRect);
3151 if( !PtInRect(&tempRect,pt) ||
3152 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3153 goto end;
3155 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3157 tempRect = ptrQueryWnd->rectClient;
3158 if(ptrQueryWnd->parent)
3159 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3160 (LPPOINT)&tempRect, 2 );
3162 if (PtInRect( &tempRect, pt))
3164 wParam = 0;
3166 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3168 if( ptrWnd->dwStyle & WS_VISIBLE )
3170 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3171 if (PtInRect( &tempRect, pt )) break;
3175 if(ptrWnd)
3177 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3178 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3179 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3180 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3181 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3183 WIN_ReleaseWndPtr(ptrWnd);
3186 if(bResult)
3187 goto end;
3189 else wParam = 1;
3191 else wParam = 1;
3193 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3195 ptrDragInfo->hScope = hQueryWnd;
3197 bResult = ( bNoSend )
3198 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3199 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3200 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3201 if( !bResult )
3202 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3204 end:
3205 WIN_ReleaseWndPtr(ptrQueryWnd);
3206 return bResult;
3210 /*******************************************************************
3211 * DragDetect (USER.465)
3213 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3215 POINT pt32;
3216 CONV_POINT16TO32( &pt, &pt32 );
3217 return DragDetect( hWnd, pt32 );
3220 /*******************************************************************
3221 * DragDetect (USER32.@)
3223 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3225 MSG msg;
3226 RECT rect;
3228 rect.left = pt.x - wDragWidth;
3229 rect.right = pt.x + wDragWidth;
3231 rect.top = pt.y - wDragHeight;
3232 rect.bottom = pt.y + wDragHeight;
3234 SetCapture(hWnd);
3236 while(1)
3238 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3240 if( msg.message == WM_LBUTTONUP )
3242 ReleaseCapture();
3243 return 0;
3245 if( msg.message == WM_MOUSEMOVE )
3247 POINT tmp;
3248 tmp.x = LOWORD(msg.lParam);
3249 tmp.y = HIWORD(msg.lParam);
3250 if( !PtInRect( &rect, tmp ))
3252 ReleaseCapture();
3253 return 1;
3257 WaitMessage();
3259 return 0;
3262 /******************************************************************************
3263 * DragObject (USER.464)
3265 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3266 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3268 MSG msg;
3269 LPDRAGINFO16 lpDragInfo;
3270 SEGPTR spDragInfo;
3271 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3272 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3273 WND *wndPtr = WIN_FindWndPtr(hWnd);
3274 HCURSOR16 hCurrentCursor = 0;
3275 HWND16 hCurrentWnd = 0;
3277 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3278 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3280 if( !lpDragInfo || !spDragInfo )
3282 WIN_ReleaseWndPtr(wndPtr);
3283 return 0L;
3286 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3288 if( !hBummer || !wndPtr )
3290 GlobalFree16(hDragInfo);
3291 WIN_ReleaseWndPtr(wndPtr);
3292 return 0L;
3295 if(hCursor)
3297 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3299 GlobalFree16(hDragInfo);
3300 WIN_ReleaseWndPtr(wndPtr);
3301 return 0L;
3304 if( hDragCursor == hCursor ) hDragCursor = 0;
3305 else hCursor = hDragCursor;
3307 hOldCursor = SetCursor(hDragCursor);
3310 lpDragInfo->hWnd = hWnd;
3311 lpDragInfo->hScope = 0;
3312 lpDragInfo->wFlags = wObj;
3313 lpDragInfo->hList = szList; /* near pointer! */
3314 lpDragInfo->hOfStruct = hOfStruct;
3315 lpDragInfo->l = 0L;
3317 SetCapture(hWnd);
3318 ShowCursor( TRUE );
3322 do{ WaitMessage(); }
3323 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3325 *(lpDragInfo+1) = *lpDragInfo;
3327 lpDragInfo->pt.x = msg.pt.x;
3328 lpDragInfo->pt.y = msg.pt.y;
3330 /* update DRAGINFO struct */
3331 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3333 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3334 hCurrentCursor = hCursor;
3335 else
3337 hCurrentCursor = hBummer;
3338 lpDragInfo->hScope = 0;
3340 if( hCurrentCursor )
3341 SetCursor(hCurrentCursor);
3343 /* send WM_DRAGLOOP */
3344 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3345 (LPARAM) spDragInfo );
3346 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3347 if( hCurrentWnd != lpDragInfo->hScope )
3349 if( hCurrentWnd )
3350 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3351 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3352 HIWORD(spDragInfo)) );
3353 hCurrentWnd = lpDragInfo->hScope;
3354 if( hCurrentWnd )
3355 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3357 else
3358 if( hCurrentWnd )
3359 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3361 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3363 ReleaseCapture();
3364 ShowCursor( FALSE );
3366 if( hCursor )
3368 SetCursor( hOldCursor );
3369 if (hDragCursor) DestroyCursor( hDragCursor );
3372 if( hCurrentCursor != hBummer )
3373 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3374 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3375 else
3376 msg.lParam = 0;
3377 GlobalFree16(hDragInfo);
3378 WIN_ReleaseWndPtr(wndPtr);
3380 return (DWORD)(msg.lParam);
3384 /******************************************************************************
3385 * GetWindowModuleFileNameA (USER32.@)
3387 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3389 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3390 hwnd, lpszFileName, cchFileNameMax);
3391 return 0;
3394 /******************************************************************************
3395 * GetWindowModuleFileNameW (USER32.@)
3397 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3399 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3400 hwnd, lpszFileName, cchFileNameMax);
3401 return 0;