- Minor API files update.
[wine.git] / windows / win.c
blobab43058e1f71694037393f4a18f5a92138be35b1
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.
362 if (hwnd == GetDesktopWindow()) hwnd = 0;
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 /* toss stale messages from the queue */
461 QUEUE_CleanupWindow( hwnd );
462 wndPtr->hmemTaskQ = 0;
464 if (!(wndPtr->dwStyle & WS_CHILD))
465 if (wndPtr->wIDmenu)
467 DestroyMenu( wndPtr->wIDmenu );
468 wndPtr->wIDmenu = 0;
470 if (wndPtr->hSysMenu)
472 DestroyMenu( wndPtr->hSysMenu );
473 wndPtr->hSysMenu = 0;
475 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
476 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
477 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
478 CLASS_RemoveWindow( wndPtr->class );
479 wndPtr->class = NULL;
480 wndPtr->dwMagic = 0; /* Mark it as invalid */
482 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
484 return pWnd;
487 /***********************************************************************
488 * WIN_ResetQueueWindows
490 * Reset the queue of all the children of a given window.
491 * Return TRUE if something was done.
493 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
495 BOOL ret = FALSE;
497 if (hNew) /* Set a new queue */
499 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
501 if (wnd->hmemTaskQ == hQueue)
503 wnd->hmemTaskQ = hNew;
504 ret = TRUE;
506 if (wnd->child)
508 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
512 else /* Queue is being destroyed */
514 while (wnd->child)
516 WND *tmp = WIN_LockWndPtr(wnd->child);
517 WND *tmp2;
518 ret = FALSE;
519 while (tmp)
521 if (tmp->hmemTaskQ == hQueue)
523 DestroyWindow( tmp->hwndSelf );
524 ret = TRUE;
525 break;
527 tmp2 = WIN_LockWndPtr(tmp->child);
528 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
529 ret = TRUE;
530 else
532 WIN_UpdateWndPtr(&tmp,tmp->next);
534 WIN_ReleaseWndPtr(tmp2);
536 WIN_ReleaseWndPtr(tmp);
537 if (!ret) break;
540 return ret;
543 /***********************************************************************
544 * WIN_CreateDesktopWindow
546 * Create the desktop window.
548 BOOL WIN_CreateDesktopWindow(void)
550 struct tagCLASS *class;
551 HWND hwndDesktop;
552 INT wndExtra;
553 DWORD clsStyle;
554 WNDPROC winproc;
555 DCE *dce;
556 CREATESTRUCTA cs;
558 TRACE("Creating desktop window\n");
561 if (!WINPOS_CreateInternalPosAtom() ||
562 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
563 &wndExtra, &winproc, &clsStyle, &dce )))
564 return FALSE;
566 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
567 if (!hwndDesktop) return FALSE;
568 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
570 pWndDesktop->pDriver = WND_Driver;
571 pWndDesktop->next = NULL;
572 pWndDesktop->child = NULL;
573 pWndDesktop->parent = NULL;
574 pWndDesktop->owner = NULL;
575 pWndDesktop->class = class;
576 pWndDesktop->dwMagic = WND_MAGIC;
577 pWndDesktop->hwndSelf = hwndDesktop;
578 pWndDesktop->hInstance = 0;
579 pWndDesktop->rectWindow.left = 0;
580 pWndDesktop->rectWindow.top = 0;
581 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
582 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
583 pWndDesktop->rectClient = pWndDesktop->rectWindow;
584 pWndDesktop->text = NULL;
585 pWndDesktop->hmemTaskQ = 0;
586 pWndDesktop->hrgnUpdate = 0;
587 pWndDesktop->hwndLastActive = hwndDesktop;
588 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
589 WS_CLIPSIBLINGS;
590 pWndDesktop->dwExStyle = 0;
591 pWndDesktop->clsStyle = clsStyle;
592 pWndDesktop->dce = NULL;
593 pWndDesktop->pVScroll = NULL;
594 pWndDesktop->pHScroll = NULL;
595 pWndDesktop->pProp = NULL;
596 pWndDesktop->wIDmenu = 0;
597 pWndDesktop->helpContext = 0;
598 pWndDesktop->flags = 0;
599 pWndDesktop->hSysMenu = 0;
600 pWndDesktop->userdata = 0;
601 pWndDesktop->winproc = winproc;
602 pWndDesktop->cbWndExtra = wndExtra;
603 pWndDesktop->irefCount = 0;
605 cs.lpCreateParams = NULL;
606 cs.hInstance = 0;
607 cs.hMenu = 0;
608 cs.hwndParent = 0;
609 cs.x = 0;
610 cs.y = 0;
611 cs.cx = pWndDesktop->rectWindow.right;
612 cs.cy = pWndDesktop->rectWindow.bottom;
613 cs.style = pWndDesktop->dwStyle;
614 cs.dwExStyle = pWndDesktop->dwExStyle;
615 cs.lpszName = NULL;
616 cs.lpszClass = DESKTOP_CLASS_ATOM;
618 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
620 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
621 return TRUE;
625 /***********************************************************************
626 * WIN_FixCoordinates
628 * Fix the coordinates - Helper for WIN_CreateWindowEx.
629 * returns default show mode in sw.
630 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
632 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
634 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
635 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
637 if (cs->style & (WS_CHILD | WS_POPUP))
639 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
640 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
642 else /* overlapped window */
644 STARTUPINFOA info;
646 GetStartupInfoA( &info );
648 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
650 /* Never believe Microsoft's documentation... CreateWindowEx doc says
651 * that if an overlapped window is created with WS_VISIBLE style bit
652 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
653 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
654 * reveals that
656 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
657 * 2) it does not ignore the y parameter as the docs claim; instead, it
658 * uses it as second parameter to ShowWindow() unless y is either
659 * CW_USEDEFAULT or CW_USEDEFAULT16.
661 * The fact that we didn't do 2) caused bogus windows pop up when wine
662 * was running apps that were using this obscure feature. Example -
663 * calc.exe that comes with Win98 (only Win98, it's different from
664 * the one that comes with Win95 and NT)
666 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
667 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
668 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
671 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
673 if (info.dwFlags & STARTF_USESIZE)
675 cs->cx = info.dwXSize;
676 cs->cy = info.dwYSize;
678 else /* if no other hint from the app, pick 3/4 of the screen real estate */
680 RECT r;
681 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
682 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
683 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
690 /***********************************************************************
691 * WIN_CreateWindowEx
693 * Implementation of CreateWindowEx().
695 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
696 WINDOWPROCTYPE type )
698 INT sw = SW_SHOW;
699 struct tagCLASS *classPtr;
700 WND *wndPtr;
701 HWND hwnd, hwndLinkAfter;
702 POINT maxSize, maxPos, minTrack, maxTrack;
703 INT wndExtra;
704 DWORD clsStyle;
705 WNDPROC winproc;
706 DCE *dce;
707 BOOL unicode = (type == WIN_PROC_32W);
709 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
710 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
711 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
712 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
713 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
715 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
716 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
718 /* Find the parent window */
720 if (cs->hwndParent)
722 /* Make sure parent is valid */
723 if (!IsWindow( cs->hwndParent ))
725 WARN("Bad parent %04x\n", cs->hwndParent );
726 return 0;
728 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
729 WARN("No parent for child window\n" );
730 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
733 /* Find the window class */
734 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
735 &wndExtra, &winproc, &clsStyle, &dce )))
737 WARN("Bad class '%s'\n", cs->lpszClass );
738 return 0;
741 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
743 /* Create the window structure */
745 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
747 TRACE("out of memory\n" );
748 return 0;
751 /* Fill the window structure */
753 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
754 wndPtr->next = NULL;
755 wndPtr->child = NULL;
757 if ((cs->style & WS_CHILD) && cs->hwndParent)
759 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
760 wndPtr->owner = NULL;
761 WIN_ReleaseWndPtr(wndPtr->parent);
763 else
765 wndPtr->parent = pWndDesktop;
766 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
767 wndPtr->owner = NULL;
768 else
770 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
771 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
772 WIN_ReleaseWndPtr(wndPtr->owner);
773 WIN_ReleaseWndPtr(tmpWnd);
778 wndPtr->pDriver = wndPtr->parent->pDriver;
780 wndPtr->class = classPtr;
781 wndPtr->winproc = winproc;
782 wndPtr->dwMagic = WND_MAGIC;
783 wndPtr->hwndSelf = hwnd;
784 wndPtr->hInstance = cs->hInstance;
785 wndPtr->text = NULL;
786 wndPtr->hmemTaskQ = GetFastQueue16();
787 wndPtr->hrgnUpdate = 0;
788 wndPtr->hrgnWnd = 0;
789 wndPtr->hwndLastActive = hwnd;
790 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
791 wndPtr->dwExStyle = cs->dwExStyle;
792 wndPtr->clsStyle = clsStyle;
793 wndPtr->wIDmenu = 0;
794 wndPtr->helpContext = 0;
795 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
796 wndPtr->pVScroll = NULL;
797 wndPtr->pHScroll = NULL;
798 wndPtr->pProp = NULL;
799 wndPtr->userdata = 0;
800 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
801 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
802 wndPtr->cbWndExtra = wndExtra;
803 wndPtr->irefCount = 1;
805 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
807 /* Call the WH_CBT hook */
809 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
810 ? HWND_BOTTOM : HWND_TOP;
812 if (HOOK_IsHooked( WH_CBT ))
814 CBT_CREATEWNDA cbtc;
815 LRESULT ret;
817 cbtc.lpcs = cs;
818 cbtc.hwndInsertAfter = hwndLinkAfter;
819 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
820 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
821 if (ret)
823 TRACE("CBT-hook returned 0\n");
824 USER_HEAP_FREE( hwnd );
825 CLASS_RemoveWindow( classPtr );
826 hwnd = 0;
827 goto end;
831 /* Correct the window style */
833 if (!(cs->style & WS_CHILD))
835 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
836 if (!(cs->style & WS_POPUP))
838 wndPtr->dwStyle |= WS_CAPTION;
839 wndPtr->flags |= WIN_NEED_SIZE;
843 /* Get class or window DC if needed */
845 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
846 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
847 else wndPtr->dce = NULL;
849 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
851 wndPtr->rectWindow.left = cs->x;
852 wndPtr->rectWindow.top = cs->y;
853 wndPtr->rectWindow.right = cs->x + cs->cx;
854 wndPtr->rectWindow.bottom = cs->y + cs->cy;
855 wndPtr->rectClient = wndPtr->rectWindow;
857 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
859 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
861 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
862 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
863 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
864 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
865 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
868 if (cs->cx < 0) cs->cx = 0;
869 if (cs->cy < 0) cs->cy = 0;
871 wndPtr->rectWindow.left = cs->x;
872 wndPtr->rectWindow.top = cs->y;
873 wndPtr->rectWindow.right = cs->x + cs->cx;
874 wndPtr->rectWindow.bottom = cs->y + cs->cy;
875 wndPtr->rectClient = wndPtr->rectWindow;
877 /* Set the window menu */
879 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
881 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
882 else
884 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
885 if (menuName)
887 if (HIWORD(cs->hInstance))
888 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
889 else
890 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
892 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
896 else wndPtr->wIDmenu = (UINT)cs->hMenu;
898 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
900 WARN("aborted by WM_xxCREATE!\n");
901 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
902 CLASS_RemoveWindow( classPtr );
903 WIN_ReleaseWndPtr(wndPtr);
904 return 0;
907 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
909 /* Notify the parent window only */
911 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
912 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
913 if( !IsWindow(hwnd) )
915 hwnd = 0;
916 goto end;
920 if (cs->style & WS_VISIBLE)
922 /* in case WS_VISIBLE got set in the meantime */
923 wndPtr->dwStyle &= ~WS_VISIBLE;
924 ShowWindow( hwnd, sw );
927 /* Call WH_SHELL hook */
929 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
930 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
932 TRACE("created window %04x\n", hwnd);
933 end:
934 WIN_ReleaseWndPtr(wndPtr);
935 return hwnd;
939 /***********************************************************************
940 * CreateWindow (USER.41)
942 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
943 DWORD style, INT16 x, INT16 y, INT16 width,
944 INT16 height, HWND16 parent, HMENU16 menu,
945 HINSTANCE16 instance, LPVOID data )
947 return CreateWindowEx16( 0, className, windowName, style,
948 x, y, width, height, parent, menu, instance, data );
952 /***********************************************************************
953 * CreateWindowEx (USER.452)
955 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
956 LPCSTR windowName, DWORD style, INT16 x,
957 INT16 y, INT16 width, INT16 height,
958 HWND16 parent, HMENU16 menu,
959 HINSTANCE16 instance, LPVOID data )
961 ATOM classAtom;
962 CREATESTRUCTA cs;
963 char buffer[256];
965 /* Find the class atom */
967 if (HIWORD(className))
969 if (!(classAtom = GlobalFindAtomA( className )))
971 ERR( "bad class name %s\n", debugres_a(className) );
972 return 0;
975 else
977 classAtom = LOWORD(className);
978 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
980 ERR( "bad atom %x\n", classAtom);
981 return 0;
983 className = buffer;
986 /* Fix the coordinates */
988 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
989 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
990 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
991 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
993 /* Create the window */
995 cs.lpCreateParams = data;
996 cs.hInstance = (HINSTANCE)instance;
997 cs.hMenu = (HMENU)menu;
998 cs.hwndParent = (HWND)parent;
999 cs.style = style;
1000 cs.lpszName = windowName;
1001 cs.lpszClass = className;
1002 cs.dwExStyle = exStyle;
1004 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1008 /***********************************************************************
1009 * CreateWindowExA (USER32.@)
1011 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1012 LPCSTR windowName, DWORD style, INT x,
1013 INT y, INT width, INT height,
1014 HWND parent, HMENU menu,
1015 HINSTANCE instance, LPVOID data )
1017 ATOM classAtom;
1018 CREATESTRUCTA cs;
1019 char buffer[256];
1021 if(!instance)
1022 instance=GetModuleHandleA(NULL);
1024 if(exStyle & WS_EX_MDICHILD)
1025 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1027 /* Find the class atom */
1029 if (HIWORD(className))
1031 if (!(classAtom = GlobalFindAtomA( className )))
1033 ERR( "bad class name %s\n", debugres_a(className) );
1034 return 0;
1037 else
1039 classAtom = LOWORD(className);
1040 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1042 ERR( "bad atom %x\n", classAtom);
1043 return 0;
1045 className = buffer;
1048 /* Create the window */
1050 cs.lpCreateParams = data;
1051 cs.hInstance = instance;
1052 cs.hMenu = menu;
1053 cs.hwndParent = parent;
1054 cs.x = x;
1055 cs.y = y;
1056 cs.cx = width;
1057 cs.cy = height;
1058 cs.style = style;
1059 cs.lpszName = windowName;
1060 cs.lpszClass = className;
1061 cs.dwExStyle = exStyle;
1063 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1067 /***********************************************************************
1068 * CreateWindowExW (USER32.@)
1070 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1071 LPCWSTR windowName, DWORD style, INT x,
1072 INT y, INT width, INT height,
1073 HWND parent, HMENU menu,
1074 HINSTANCE instance, LPVOID data )
1076 ATOM classAtom;
1077 CREATESTRUCTW cs;
1078 WCHAR buffer[256];
1080 if(!instance)
1081 instance=GetModuleHandleA(NULL);
1083 if(exStyle & WS_EX_MDICHILD)
1084 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1086 /* Find the class atom */
1088 if (HIWORD(className))
1090 if (!(classAtom = GlobalFindAtomW( className )))
1092 ERR( "bad class name %s\n", debugres_w(className) );
1093 return 0;
1096 else
1098 classAtom = LOWORD(className);
1099 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1101 ERR( "bad atom %x\n", classAtom);
1102 return 0;
1104 className = buffer;
1107 /* Create the window */
1109 cs.lpCreateParams = data;
1110 cs.hInstance = instance;
1111 cs.hMenu = menu;
1112 cs.hwndParent = parent;
1113 cs.x = x;
1114 cs.y = y;
1115 cs.cx = width;
1116 cs.cy = height;
1117 cs.style = style;
1118 cs.lpszName = windowName;
1119 cs.lpszClass = className;
1120 cs.dwExStyle = exStyle;
1122 /* Note: we rely on the fact that CREATESTRUCTA and */
1123 /* CREATESTRUCTW have the same layout. */
1124 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1127 /***********************************************************************
1128 * WIN_SendDestroyMsg
1130 static void WIN_SendDestroyMsg( WND* pWnd )
1132 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1133 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1136 * Send the WM_DESTROY to the window.
1138 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1141 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1142 * make sure that the window still exists when we come back.
1144 if (IsWindow(pWnd->hwndSelf))
1146 HWND* pWndArray = NULL;
1147 WND* pChild = NULL;
1148 int nKidCount = 0;
1151 * Now, if the window has kids, we have to send WM_DESTROY messages
1152 * recursively to it's kids. It seems that those calls can also
1153 * trigger re-entrant calls to DestroyWindow for the kids so we must
1154 * protect against corruption of the list of siblings. We first build
1155 * a list of HWNDs representing all the kids.
1157 pChild = WIN_LockWndPtr(pWnd->child);
1158 while( pChild )
1160 nKidCount++;
1161 WIN_UpdateWndPtr(&pChild,pChild->next);
1165 * If there are no kids, we're done.
1167 if (nKidCount==0)
1168 return;
1170 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1173 * Sanity check
1175 if (pWndArray==NULL)
1176 return;
1179 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1180 * call, our linked list of siblings should be safe.
1182 nKidCount = 0;
1183 pChild = WIN_LockWndPtr(pWnd->child);
1184 while( pChild )
1186 pWndArray[nKidCount] = pChild->hwndSelf;
1187 nKidCount++;
1188 WIN_UpdateWndPtr(&pChild,pChild->next);
1192 * Now that we have a list, go through that list again and send the destroy
1193 * message to those windows. We are using the HWND to retrieve the
1194 * WND pointer so we are effectively checking that all the kid windows are
1195 * still valid before sending the message.
1197 while (nKidCount>0)
1199 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1201 if (pChild!=NULL)
1203 WIN_SendDestroyMsg( pChild );
1204 WIN_ReleaseWndPtr(pChild);
1209 * Cleanup
1211 HeapFree(GetProcessHeap(), 0, pWndArray);
1213 else
1214 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1218 /***********************************************************************
1219 * DestroyWindow (USER.53)
1221 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1223 return DestroyWindow(hwnd);
1227 /***********************************************************************
1228 * DestroyWindow (USER32.@)
1230 BOOL WINAPI DestroyWindow( HWND hwnd )
1232 WND * wndPtr;
1233 BOOL retvalue;
1234 HWND h;
1235 BOOL bFocusSet = FALSE;
1237 TRACE("(%04x)\n", hwnd);
1239 /* Initialization */
1241 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1242 if (wndPtr == pWndDesktop)
1244 retvalue = FALSE; /* Can't destroy desktop */
1245 goto end;
1248 /* Look whether the focus is within the tree of windows we will
1249 * be destroying.
1251 h = GetFocus16();
1252 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1254 if (h == hwnd)
1256 SetFocus(GetParent(h));
1257 bFocusSet = TRUE;
1258 break;
1260 h = GetParent(h);
1262 /* If the focus is on the window we will destroy and it has no parent,
1263 * set the focus to 0.
1265 if (! bFocusSet && (h == hwnd))
1267 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1268 SetFocus(0);
1271 /* Call hooks */
1273 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1275 retvalue = FALSE;
1276 goto end;
1279 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1281 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1282 /* FIXME: clean up palette - see "Internals" p.352 */
1285 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1286 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1288 /* Notify the parent window only */
1289 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1290 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1291 if( !IsWindow(hwnd) )
1293 retvalue = TRUE;
1294 goto end;
1298 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1300 /* Hide the window */
1302 if (wndPtr->dwStyle & WS_VISIBLE)
1304 ShowWindow( hwnd, SW_HIDE );
1305 if (!IsWindow(hwnd))
1307 retvalue = TRUE;
1308 goto end;
1312 /* Recursively destroy owned windows */
1314 if( !(wndPtr->dwStyle & WS_CHILD) )
1316 for (;;)
1318 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1319 while (siblingPtr)
1321 if (siblingPtr->owner == wndPtr)
1323 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1324 break;
1325 else
1326 siblingPtr->owner = NULL;
1328 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1330 if (siblingPtr)
1332 DestroyWindow( siblingPtr->hwndSelf );
1333 WIN_ReleaseWndPtr(siblingPtr);
1335 else break;
1338 WINPOS_ActivateOtherWindow(wndPtr);
1340 if( wndPtr->owner &&
1341 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1342 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1345 /* Send destroy messages */
1347 WIN_SendDestroyMsg( wndPtr );
1348 if (!IsWindow(hwnd))
1350 retvalue = TRUE;
1351 goto end;
1354 /* Unlink now so we won't bother with the children later on */
1356 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1358 /* Destroy the window storage */
1360 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1361 retvalue = TRUE;
1362 end:
1363 WIN_ReleaseWndPtr(wndPtr);
1364 return retvalue;
1368 /***********************************************************************
1369 * CloseWindow (USER.43)
1371 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1373 return CloseWindow( hwnd );
1377 /***********************************************************************
1378 * CloseWindow (USER32.@)
1380 BOOL WINAPI CloseWindow( HWND hwnd )
1382 WND * wndPtr = WIN_FindWndPtr( hwnd );
1383 BOOL retvalue;
1385 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1387 retvalue = FALSE;
1388 goto end;
1390 ShowWindow( hwnd, SW_MINIMIZE );
1391 retvalue = TRUE;
1392 end:
1393 WIN_ReleaseWndPtr(wndPtr);
1394 return retvalue;
1399 /***********************************************************************
1400 * OpenIcon (USER.44)
1402 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1404 return OpenIcon( hwnd );
1408 /***********************************************************************
1409 * OpenIcon (USER32.@)
1411 BOOL WINAPI OpenIcon( HWND hwnd )
1413 if (!IsIconic( hwnd )) return FALSE;
1414 ShowWindow( hwnd, SW_SHOWNORMAL );
1415 return TRUE;
1419 /***********************************************************************
1420 * WIN_FindWindow
1422 * Implementation of FindWindow() and FindWindowEx().
1424 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1425 LPCWSTR title )
1427 WND *pWnd;
1428 HWND retvalue;
1430 if (child)
1432 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1433 if (parent)
1435 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1437 retvalue = 0;
1438 goto end;
1441 else if (pWnd->parent != pWndDesktop)
1443 retvalue = 0;
1444 goto end;
1446 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1448 else
1450 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1452 retvalue = 0;
1453 goto end;
1455 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1457 if (!pWnd)
1459 retvalue = 0;
1460 goto end;
1463 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1465 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1466 continue; /* Not the right class */
1468 /* Now check the title */
1470 if (!title)
1472 retvalue = pWnd->hwndSelf;
1473 goto end;
1475 if (pWnd->text && !strcmpW( pWnd->text, title ))
1477 retvalue = pWnd->hwndSelf;
1478 goto end;
1481 retvalue = 0;
1482 /* In this case we need to check whether other processes
1483 own a window with the given paramters on the Desktop,
1484 but we don't, so let's at least warn about it */
1485 FIXME("Returning 0 without checking other processes\n");
1486 end:
1487 WIN_ReleaseWndPtr(pWnd);
1488 return retvalue;
1493 /***********************************************************************
1494 * FindWindow (USER.50)
1496 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1498 return FindWindowA( className, title );
1502 /***********************************************************************
1503 * FindWindowEx (USER.427)
1505 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1507 return FindWindowExA( parent, child, className, title );
1511 /***********************************************************************
1512 * FindWindowA (USER32.@)
1514 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1516 HWND ret = FindWindowExA( 0, 0, className, title );
1517 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1518 return ret;
1522 /***********************************************************************
1523 * FindWindowExA (USER32.@)
1525 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1526 LPCSTR className, LPCSTR title )
1528 ATOM atom = 0;
1529 LPWSTR buffer;
1530 HWND hwnd;
1532 if (className)
1534 /* If the atom doesn't exist, then no class */
1535 /* with this name exists either. */
1536 if (!(atom = GlobalFindAtomA( className )))
1538 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1539 return 0;
1543 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1544 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1545 HeapFree( GetProcessHeap(), 0, buffer );
1546 return hwnd;
1550 /***********************************************************************
1551 * FindWindowExW (USER32.@)
1553 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1554 LPCWSTR className, LPCWSTR title )
1556 ATOM atom = 0;
1558 if (className)
1560 /* If the atom doesn't exist, then no class */
1561 /* with this name exists either. */
1562 if (!(atom = GlobalFindAtomW( className )))
1564 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1565 return 0;
1568 return WIN_FindWindow( parent, child, atom, title );
1572 /***********************************************************************
1573 * FindWindowW (USER32.@)
1575 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1577 return FindWindowExW( 0, 0, className, title );
1581 /**********************************************************************
1582 * WIN_GetDesktop
1583 * returns a locked pointer
1585 WND *WIN_GetDesktop(void)
1587 return WIN_LockWndPtr(pWndDesktop);
1589 /**********************************************************************
1590 * WIN_ReleaseDesktop
1591 * unlock the desktop pointer
1593 void WIN_ReleaseDesktop(void)
1595 WIN_ReleaseWndPtr(pWndDesktop);
1599 /**********************************************************************
1600 * GetDesktopWindow (USER.286)
1602 HWND16 WINAPI GetDesktopWindow16(void)
1604 return (HWND16)pWndDesktop->hwndSelf;
1608 /**********************************************************************
1609 * GetDesktopWindow (USER32.@)
1611 HWND WINAPI GetDesktopWindow(void)
1613 if (pWndDesktop) return pWndDesktop->hwndSelf;
1614 ERR( "You need the -desktop option when running with native USER\n" );
1615 ExitProcess(1);
1616 return 0;
1620 /**********************************************************************
1621 * GetDesktopHwnd (USER.278)
1623 * Exactly the same thing as GetDesktopWindow(), but not documented.
1624 * Don't ask me why...
1626 HWND16 WINAPI GetDesktopHwnd16(void)
1628 return (HWND16)pWndDesktop->hwndSelf;
1632 /*******************************************************************
1633 * EnableWindow (USER.34)
1635 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1637 return EnableWindow( hwnd, enable );
1641 /*******************************************************************
1642 * EnableWindow (USER32.@)
1644 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1646 WND *wndPtr;
1647 BOOL retvalue;
1649 TRACE("( %x, %d )\n", hwnd, enable);
1651 if (USER_Driver.pEnableWindow)
1652 return USER_Driver.pEnableWindow( hwnd, enable );
1654 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1656 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1658 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1660 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1661 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1663 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1665 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1667 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1669 if (hwnd == GetFocus())
1670 SetFocus( 0 ); /* A disabled window can't have the focus */
1672 if (hwnd == GetCapture())
1673 ReleaseCapture(); /* A disabled window can't capture the mouse */
1675 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1677 WIN_ReleaseWndPtr(wndPtr);
1678 return retvalue;
1682 /***********************************************************************
1683 * IsWindowEnabled (USER.35)
1685 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1687 return IsWindowEnabled(hWnd);
1691 /***********************************************************************
1692 * IsWindowEnabled (USER32.@)
1694 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1696 WND * wndPtr;
1697 BOOL retvalue;
1699 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1700 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1701 WIN_ReleaseWndPtr(wndPtr);
1702 return retvalue;
1707 /***********************************************************************
1708 * IsWindowUnicode (USER32.@)
1710 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1712 WND * wndPtr;
1713 BOOL retvalue;
1715 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1716 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1717 WIN_ReleaseWndPtr(wndPtr);
1718 return retvalue;
1722 /**********************************************************************
1723 * GetWindowWord (USER.133)
1725 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1727 return GetWindowWord( hwnd, offset );
1731 /**********************************************************************
1732 * GetWindowWord (USER32.@)
1734 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1736 WORD retvalue;
1737 WND * wndPtr = WIN_FindWndPtr( hwnd );
1738 if (!wndPtr) return 0;
1739 if (offset >= 0)
1741 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1743 WARN("Invalid offset %d\n", offset );
1744 retvalue = 0;
1745 goto end;
1747 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1748 goto end;
1750 switch(offset)
1752 case GWW_ID:
1753 if (HIWORD(wndPtr->wIDmenu))
1754 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1755 wndPtr->wIDmenu);
1756 retvalue = (WORD)wndPtr->wIDmenu;
1757 goto end;
1758 case GWW_HWNDPARENT:
1759 retvalue = GetParent(hwnd);
1760 goto end;
1761 case GWW_HINSTANCE:
1762 if (HIWORD(wndPtr->hInstance))
1763 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1764 wndPtr->hInstance);
1765 retvalue = (WORD)wndPtr->hInstance;
1766 goto end;
1767 default:
1768 WARN("Invalid offset %d\n", offset );
1769 retvalue = 0;
1770 goto end;
1772 end:
1773 WIN_ReleaseWndPtr(wndPtr);
1774 return retvalue;
1777 /**********************************************************************
1778 * SetWindowWord (USER.134)
1780 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1782 return SetWindowWord( hwnd, offset, newval );
1786 /**********************************************************************
1787 * SetWindowWord (USER32.@)
1789 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1791 WORD *ptr, retval;
1792 WND * wndPtr = WIN_FindWndPtr( hwnd );
1793 if (!wndPtr) return 0;
1794 if (offset >= 0)
1796 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1798 WARN("Invalid offset %d\n", offset );
1799 retval = 0;
1800 goto end;
1802 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1804 else switch(offset)
1806 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1807 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1808 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1809 goto end;
1810 default:
1811 WARN("Invalid offset %d\n", offset );
1812 retval = 0;
1813 goto end;
1815 retval = *ptr;
1816 *ptr = newval;
1817 end:
1818 WIN_ReleaseWndPtr(wndPtr);
1819 return retval;
1823 /**********************************************************************
1824 * WIN_GetWindowLong
1826 * Helper function for GetWindowLong().
1828 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1830 LONG retvalue;
1831 WND * wndPtr = WIN_FindWndPtr( hwnd );
1832 if (!wndPtr) return 0;
1833 if (offset >= 0)
1835 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1837 WARN("Invalid offset %d\n", offset );
1838 retvalue = 0;
1839 goto end;
1841 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1842 /* Special case for dialog window procedure */
1843 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1845 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1846 goto end;
1848 goto end;
1850 switch(offset)
1852 case GWL_USERDATA: retvalue = wndPtr->userdata;
1853 goto end;
1854 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1855 goto end;
1856 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1857 goto end;
1858 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1859 goto end;
1860 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1861 type );
1862 goto end;
1863 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1864 goto end;
1865 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1866 goto end;
1867 default:
1868 WARN("Unknown offset %d\n", offset );
1870 retvalue = 0;
1871 end:
1872 WIN_ReleaseWndPtr(wndPtr);
1873 return retvalue;
1877 /**********************************************************************
1878 * WIN_SetWindowLong
1880 * Helper function for SetWindowLong().
1882 * 0 is the failure code. However, in the case of failure SetLastError
1883 * must be set to distinguish between a 0 return value and a failure.
1885 * FIXME: The error values for SetLastError may not be right. Can
1886 * someone check with the real thing?
1888 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1889 WINDOWPROCTYPE type )
1891 LONG *ptr, retval;
1892 WND * wndPtr = WIN_FindWndPtr( hwnd );
1893 STYLESTRUCT style;
1895 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1897 if (!wndPtr)
1899 /* Is this the right error? */
1900 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1901 return 0;
1904 if (offset >= 0)
1906 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1908 WARN("Invalid offset %d\n", offset );
1910 /* Is this the right error? */
1911 SetLastError( ERROR_OUTOFMEMORY );
1913 retval = 0;
1914 goto end;
1916 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1917 /* Special case for dialog window procedure */
1918 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1920 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1921 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1922 type, WIN_PROC_WINDOW );
1923 goto end;
1926 else switch(offset)
1928 case GWL_ID:
1929 ptr = (DWORD*)&wndPtr->wIDmenu;
1930 break;
1931 case GWL_HINSTANCE:
1932 retval = SetWindowWord( hwnd, offset, newval );
1933 goto end;
1934 case GWL_WNDPROC:
1935 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1936 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1937 type, WIN_PROC_WINDOW );
1938 goto end;
1939 case GWL_STYLE:
1940 style.styleOld = wndPtr->dwStyle;
1941 style.styleNew = newval;
1942 if (wndPtr->flags & WIN_ISWIN32)
1943 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1944 wndPtr->dwStyle = style.styleNew;
1945 if (wndPtr->flags & WIN_ISWIN32)
1946 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1947 retval = style.styleOld;
1948 goto end;
1950 case GWL_USERDATA:
1951 ptr = &wndPtr->userdata;
1952 break;
1953 case GWL_EXSTYLE:
1954 style.styleOld = wndPtr->dwExStyle;
1955 style.styleNew = newval;
1956 if (wndPtr->flags & WIN_ISWIN32)
1957 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1958 wndPtr->dwExStyle = newval;
1959 if (wndPtr->flags & WIN_ISWIN32)
1960 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1961 retval = style.styleOld;
1962 goto end;
1964 default:
1965 WARN("Invalid offset %d\n", offset );
1967 /* Don't think this is right error but it should do */
1968 SetLastError( ERROR_OUTOFMEMORY );
1970 retval = 0;
1971 goto end;
1973 retval = *ptr;
1974 *ptr = newval;
1975 end:
1976 WIN_ReleaseWndPtr(wndPtr);
1977 return retval;
1981 /**********************************************************************
1982 * GetWindowLong (USER.135)
1984 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1986 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1990 /**********************************************************************
1991 * GetWindowLongA (USER32.@)
1993 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1995 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1999 /**********************************************************************
2000 * GetWindowLongW (USER32.@)
2002 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2004 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2008 /**********************************************************************
2009 * SetWindowLong (USER.136)
2011 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2013 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2017 /**********************************************************************
2018 * SetWindowLongA (USER32.@)
2020 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2022 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2026 /**********************************************************************
2027 * SetWindowLongW (USER32.@) Set window attribute
2029 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2030 * value in a window's extra memory.
2032 * The _hwnd_ parameter specifies the window. is the handle to a
2033 * window that has extra memory. The _newval_ parameter contains the
2034 * new attribute or extra memory value. If positive, the _offset_
2035 * parameter is the byte-addressed location in the window's extra
2036 * memory to set. If negative, _offset_ specifies the window
2037 * attribute to set, and should be one of the following values:
2039 * GWL_EXSTYLE The window's extended window style
2041 * GWL_STYLE The window's window style.
2043 * GWL_WNDPROC Pointer to the window's window procedure.
2045 * GWL_HINSTANCE The window's pplication instance handle.
2047 * GWL_ID The window's identifier.
2049 * GWL_USERDATA The window's user-specified data.
2051 * If the window is a dialog box, the _offset_ parameter can be one of
2052 * the following values:
2054 * DWL_DLGPROC The address of the window's dialog box procedure.
2056 * DWL_MSGRESULT The return value of a message
2057 * that the dialog box procedure processed.
2059 * DWL_USER Application specific information.
2061 * RETURNS
2063 * If successful, returns the previous value located at _offset_. Otherwise,
2064 * returns 0.
2066 * NOTES
2068 * Extra memory for a window class is specified by a nonzero cbWndExtra
2069 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2070 * time of class creation.
2072 * Using GWL_WNDPROC to set a new window procedure effectively creates
2073 * a window subclass. Use CallWindowProc() in the new windows procedure
2074 * to pass messages to the superclass's window procedure.
2076 * The user data is reserved for use by the application which created
2077 * the window.
2079 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2080 * instead, call the EnableWindow() function to change the window's
2081 * disabled state.
2083 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2084 * SetParent() instead.
2086 * Win95:
2087 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2088 * it sends WM_STYLECHANGING before changing the settings
2089 * and WM_STYLECHANGED afterwards.
2090 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2092 * BUGS
2094 * GWL_STYLE does not dispatch WM_STYLE... messages.
2096 * CONFORMANCE
2098 * ECMA-234, Win32
2101 LONG WINAPI SetWindowLongW(
2102 HWND hwnd, /* [in] window to alter */
2103 INT offset, /* [in] offset, in bytes, of location to alter */
2104 LONG newval /* [in] new value of location */
2106 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2110 /*******************************************************************
2111 * GetWindowText (USER.36)
2113 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2115 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2119 /*******************************************************************
2120 * GetWindowTextA (USER32.@)
2122 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2124 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2125 (LPARAM)lpString );
2128 /*******************************************************************
2129 * InternalGetWindowText (USER32.@)
2131 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2133 WND *win = WIN_FindWndPtr( hwnd );
2134 if (!win) return 0;
2135 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2136 else lpString[0] = 0;
2137 WIN_ReleaseWndPtr( win );
2138 return strlenW(lpString);
2142 /*******************************************************************
2143 * GetWindowTextW (USER32.@)
2145 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2147 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2148 (LPARAM)lpString );
2152 /*******************************************************************
2153 * SetWindowText (USER.37)
2155 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2157 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2161 /*******************************************************************
2162 * SetWindowText (USER32.@)
2164 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2166 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2170 /*******************************************************************
2171 * SetWindowTextW (USER32.@)
2173 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2175 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2179 /*******************************************************************
2180 * GetWindowTextLength (USER.38)
2182 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2184 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2188 /*******************************************************************
2189 * GetWindowTextLengthA (USER32.@)
2191 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2193 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2196 /*******************************************************************
2197 * GetWindowTextLengthW (USER32.@)
2199 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2201 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2205 /*******************************************************************
2206 * IsWindow (USER.47)
2208 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2210 CURRENT_STACK16->es = USER_HeapSel;
2211 return IsWindow( hwnd );
2215 /*******************************************************************
2216 * IsWindow (USER32.@)
2218 BOOL WINAPI IsWindow( HWND hwnd )
2220 WND * wndPtr;
2221 BOOL retvalue;
2223 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2224 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2225 WIN_ReleaseWndPtr(wndPtr);
2226 return retvalue;
2231 /*****************************************************************
2232 * GetParent (USER.46)
2234 HWND16 WINAPI GetParent16( HWND16 hwnd )
2236 return (HWND16)GetParent( hwnd );
2240 /*****************************************************************
2241 * GetParent (USER32.@)
2243 HWND WINAPI GetParent( HWND hwnd )
2245 WND *wndPtr;
2246 HWND retvalue = 0;
2248 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2249 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2250 goto end;
2252 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2253 if (wndPtr)
2254 retvalue = wndPtr->hwndSelf;
2256 end:
2257 WIN_ReleaseWndPtr(wndPtr);
2258 return retvalue;
2262 /*****************************************************************
2263 * WIN_GetTopParent
2265 * Get the top-level parent for a child window.
2266 * returns a locked pointer
2268 WND* WIN_GetTopParentPtr( WND* pWnd )
2270 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2272 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2274 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2276 return tmpWnd;
2279 /*****************************************************************
2280 * WIN_GetTopParent
2282 * Get the top-level parent for a child window.
2284 HWND WIN_GetTopParent( HWND hwnd )
2286 HWND retvalue;
2287 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2288 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2290 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2291 WIN_ReleaseWndPtr(tmpPtr);
2292 WIN_ReleaseWndPtr(wndPtr);
2293 return retvalue;
2297 /*****************************************************************
2298 * SetParent (USER.233)
2300 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2302 return SetParent( hwndChild, hwndNewParent );
2306 /*****************************************************************
2307 * SetParent (USER32.@)
2309 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2311 WND *wndPtr;
2312 WND *pWndParent;
2313 DWORD dwStyle;
2314 HWND retvalue;
2316 if (hwnd == GetDesktopWindow()) /* sanity check */
2318 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2319 return 0;
2322 if (USER_Driver.pSetParent)
2323 return USER_Driver.pSetParent( hwnd, parent );
2325 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2327 dwStyle = wndPtr->dwStyle;
2329 if (!parent) parent = GetDesktopWindow();
2331 if (!(pWndParent = WIN_FindWndPtr(parent)))
2333 WIN_ReleaseWndPtr( wndPtr );
2334 return 0;
2337 /* Windows hides the window first, then shows it again
2338 * including the WM_SHOWWINDOW messages and all */
2339 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2341 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2342 if (pWndParent != wndPtr->parent)
2344 WIN_UnlinkWindow(wndPtr->hwndSelf);
2345 wndPtr->parent = pWndParent;
2347 if (parent != GetDesktopWindow()) /* a child window */
2349 if( !( wndPtr->dwStyle & WS_CHILD ) )
2351 if( wndPtr->wIDmenu != 0)
2353 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2354 wndPtr->wIDmenu = 0;
2358 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2360 WIN_ReleaseWndPtr( pWndParent );
2361 WIN_ReleaseWndPtr( wndPtr );
2363 /* SetParent additionally needs to make hwnd the topmost window
2364 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2365 WM_WINDOWPOSCHANGED notification messages.
2367 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2368 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2369 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2370 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2371 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2372 return retvalue;
2376 /*******************************************************************
2377 * IsChild (USER.48)
2379 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2381 return IsChild(parent,child);
2385 /*******************************************************************
2386 * IsChild (USER32.@)
2388 BOOL WINAPI IsChild( HWND parent, HWND child )
2390 WND * wndPtr = WIN_FindWndPtr( child );
2391 while (wndPtr && wndPtr->parent)
2393 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2394 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2395 if (wndPtr->hwndSelf == parent)
2397 WIN_ReleaseWndPtr(wndPtr);
2398 return TRUE;
2401 WIN_ReleaseWndPtr(wndPtr);
2402 return FALSE;
2406 /***********************************************************************
2407 * IsWindowVisible (USER.49)
2409 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2411 return IsWindowVisible(hwnd);
2415 /***********************************************************************
2416 * IsWindowVisible (USER32.@)
2418 BOOL WINAPI IsWindowVisible( HWND hwnd )
2420 BOOL retval;
2421 WND *wndPtr = WIN_FindWndPtr( hwnd );
2422 while (wndPtr && wndPtr->parent)
2424 if (!(wndPtr->dwStyle & WS_VISIBLE))
2426 WIN_ReleaseWndPtr(wndPtr);
2427 return FALSE;
2429 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2431 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2432 WIN_ReleaseWndPtr(wndPtr);
2433 return retval;
2437 /***********************************************************************
2438 * WIN_IsWindowDrawable
2440 * hwnd is drawable when it is visible, all parents are not
2441 * minimized, and it is itself not minimized unless we are
2442 * trying to draw its default class icon.
2444 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2446 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2447 if ((wnd->dwStyle & WS_MINIMIZE) &&
2448 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2449 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2450 if( wnd->dwStyle & WS_MINIMIZE ||
2451 !(wnd->dwStyle & WS_VISIBLE) ) break;
2452 return (wnd == NULL);
2456 /*******************************************************************
2457 * GetTopWindow (USER.229)
2459 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2461 return GetTopWindow(hwnd);
2465 /*******************************************************************
2466 * GetTopWindow (USER32.@)
2468 HWND WINAPI GetTopWindow( HWND hwnd )
2470 HWND retval = 0;
2471 WND * wndPtr = (hwnd) ?
2472 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2474 if (wndPtr && wndPtr->child)
2475 retval = wndPtr->child->hwndSelf;
2477 WIN_ReleaseWndPtr(wndPtr);
2478 return retval;
2482 /*******************************************************************
2483 * GetWindow (USER.262)
2485 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2487 return GetWindow( hwnd,rel );
2491 /*******************************************************************
2492 * GetWindow (USER32.@)
2494 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2496 HWND retval;
2498 WND * wndPtr = WIN_FindWndPtr( hwnd );
2499 if (!wndPtr) return 0;
2500 switch(rel)
2502 case GW_HWNDFIRST:
2503 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2504 goto end;
2506 case GW_HWNDLAST:
2507 if (!wndPtr->parent)
2509 retval = 0; /* Desktop window */
2510 goto end;
2512 while (wndPtr->next)
2514 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2516 retval = wndPtr->hwndSelf;
2517 goto end;
2519 case GW_HWNDNEXT:
2520 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2521 goto end;
2523 case GW_HWNDPREV:
2524 if (!wndPtr->parent)
2526 retval = 0; /* Desktop window */
2527 goto end;
2529 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2530 if (wndPtr->hwndSelf == hwnd)
2532 retval = 0; /* First in list */
2533 goto end;
2535 while (wndPtr->next)
2537 if (wndPtr->next->hwndSelf == hwnd)
2539 retval = wndPtr->hwndSelf;
2540 goto end;
2542 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2544 retval = 0;
2545 goto end;
2547 case GW_OWNER:
2548 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2549 goto end;
2551 case GW_CHILD:
2552 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2553 goto end;
2555 retval = 0;
2556 end:
2557 WIN_ReleaseWndPtr(wndPtr);
2558 return retval;
2562 /*******************************************************************
2563 * GetNextWindow (USER.230)
2565 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2567 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2568 return GetWindow16( hwnd, flag );
2571 /***********************************************************************
2572 * WIN_InternalShowOwnedPopups
2574 * Internal version of ShowOwnedPopups; Wine functions should use this
2575 * to avoid interfering with application calls to ShowOwnedPopups
2576 * and to make sure the application can't prevent showing/hiding.
2578 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2582 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2584 INT totalChild=0, count=0;
2586 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2588 if (!pWnd) return TRUE;
2591 * Show windows Lowest first, Highest last to preserve Z-Order
2593 for (count = totalChild-1 ; count >=0; count--)
2595 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2597 if (fShow)
2599 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2600 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2603 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2605 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2606 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2609 else
2611 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2612 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2613 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2616 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2618 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2619 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2620 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2625 WIN_ReleaseDesktop();
2626 WIN_ReleaseWinArray(pWnd);
2628 return TRUE;
2631 /*******************************************************************
2632 * ShowOwnedPopups (USER.265)
2634 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2636 ShowOwnedPopups( owner, fShow );
2640 /*******************************************************************
2641 * ShowOwnedPopups (USER32.@)
2643 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2645 UINT totalChild=0, count=0;
2647 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2649 if (!pWnd) return TRUE;
2651 for (; count < totalChild; count++)
2653 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2655 if (fShow)
2657 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2660 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2661 * regardless of the state of the owner
2663 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2664 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2667 else
2669 if (IsWindowVisible(pWnd[count]->hwndSelf))
2672 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2673 * regardless of the state of the owner
2675 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2676 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2682 WIN_ReleaseDesktop();
2683 WIN_ReleaseWinArray(pWnd);
2684 return TRUE;
2688 /*******************************************************************
2689 * GetLastActivePopup (USER.287)
2691 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2693 return GetLastActivePopup( hwnd );
2696 /*******************************************************************
2697 * GetLastActivePopup (USER32.@)
2699 HWND WINAPI GetLastActivePopup( HWND hwnd )
2701 HWND retval;
2702 WND *wndPtr =WIN_FindWndPtr(hwnd);
2703 if (!wndPtr) return hwnd;
2704 retval = wndPtr->hwndLastActive;
2705 WIN_ReleaseWndPtr(wndPtr);
2706 if ((retval != hwnd) && (!IsWindow(retval)))
2707 retval = hwnd;
2708 return retval;
2712 /*******************************************************************
2713 * WIN_BuildWinArray
2715 * Build an array of pointers to the children of a given window.
2716 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2717 * when no windows are found.
2719 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2721 /* Future: this function will lock all windows associated with this array */
2723 WND **list, **ppWnd;
2724 WND *pWnd;
2725 UINT count = 0, skipOwned, skipHidden;
2726 DWORD skipFlags;
2728 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2729 skipOwned = bwaFlags & BWA_SKIPOWNED;
2730 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2731 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2733 /* First count the windows */
2735 if (!wndPtr)
2736 wndPtr = WIN_GetDesktop();
2738 pWnd = WIN_LockWndPtr(wndPtr->child);
2739 while (pWnd)
2741 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2742 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2743 count++;
2744 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2747 if( count )
2749 /* Now build the list of all windows */
2751 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2753 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2755 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2756 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2758 *ppWnd++ = pWnd;
2759 count++;
2762 WIN_ReleaseWndPtr(pWnd);
2763 *ppWnd = NULL;
2765 else count = 0;
2766 } else list = NULL;
2768 if( pTotal ) *pTotal = count;
2769 return list;
2771 /*******************************************************************
2772 * WIN_ReleaseWinArray
2774 void WIN_ReleaseWinArray(WND **wndArray)
2776 /* Future: this function will also unlock all windows associated with wndArray */
2777 HeapFree( GetProcessHeap(), 0, wndArray );
2781 /*******************************************************************
2782 * EnumWindows (USER32.@)
2784 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2786 WND **list, **ppWnd;
2788 /* We have to build a list of all windows first, to avoid */
2789 /* unpleasant side-effects, for instance if the callback */
2790 /* function changes the Z-order of the windows. */
2792 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2794 WIN_ReleaseDesktop();
2795 return FALSE;
2798 /* Now call the callback function for every window */
2800 for (ppWnd = list; *ppWnd; ppWnd++)
2802 LRESULT lpEnumFuncRetval;
2803 int iWndsLocks = 0;
2804 /* Make sure that the window still exists */
2805 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2807 /* To avoid any deadlocks, all the locks on the windows
2808 structures must be suspended before the control
2809 is passed to the application */
2810 iWndsLocks = WIN_SuspendWndsLock();
2811 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2812 WIN_RestoreWndsLock(iWndsLocks);
2814 if (!lpEnumFuncRetval) break;
2816 WIN_ReleaseWinArray(list);
2817 WIN_ReleaseDesktop();
2818 return TRUE;
2822 /**********************************************************************
2823 * WIN_EnumQueueWindows
2825 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2827 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2829 WND **list, **ppWnd;
2831 /* This function is the same as EnumWindows(), */
2832 /* except for an added check on the window's task. */
2834 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2836 WIN_ReleaseDesktop();
2837 return FALSE;
2840 /* Now call the callback function for every window */
2842 for (ppWnd = list; *ppWnd; ppWnd++)
2844 LRESULT funcRetval;
2845 int iWndsLocks = 0;
2846 /* Make sure that the window still exists */
2847 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2848 if ((*ppWnd)->hmemTaskQ != queue) continue;
2850 /* To avoid any deadlocks, all the locks on the windows
2851 structures must be suspended before the control
2852 is passed to the application */
2853 iWndsLocks = WIN_SuspendWndsLock();
2854 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2855 WIN_RestoreWndsLock(iWndsLocks);
2857 if (!funcRetval) break;
2859 WIN_ReleaseWinArray(list);
2860 WIN_ReleaseDesktop();
2861 return TRUE;
2865 /**********************************************************************
2866 * EnumTaskWindows16 (USER.225)
2868 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2869 LPARAM lParam )
2871 HQUEUE16 queue = GetTaskQueue16( hTask );
2872 if (!queue) return FALSE;
2873 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2877 /**********************************************************************
2878 * EnumThreadWindows (USER32.@)
2880 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2882 HQUEUE16 queue = GetThreadQueue16( id );
2883 if (!queue) return FALSE;
2884 return WIN_EnumQueueWindows( queue, func, lParam );
2888 /**********************************************************************
2889 * WIN_EnumChildWindows
2891 * Helper function for EnumChildWindows().
2893 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2895 WND **childList;
2896 BOOL16 ret = FALSE;
2898 for ( ; *ppWnd; ppWnd++)
2900 int iWndsLocks = 0;
2902 /* Make sure that the window still exists */
2903 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2904 /* Build children list first */
2905 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2907 /* To avoid any deadlocks, all the locks on the windows
2908 structures must be suspended before the control
2909 is passed to the application */
2910 iWndsLocks = WIN_SuspendWndsLock();
2911 ret = func( (*ppWnd)->hwndSelf, lParam );
2912 WIN_RestoreWndsLock(iWndsLocks);
2914 if (childList)
2916 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2917 WIN_ReleaseWinArray(childList);
2919 if (!ret) return FALSE;
2921 return TRUE;
2925 /**********************************************************************
2926 * EnumChildWindows (USER32.@)
2928 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2929 LPARAM lParam )
2931 WND **list, *pParent;
2933 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2934 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2936 WIN_ReleaseWndPtr(pParent);
2937 return FALSE;
2939 WIN_EnumChildWindows( list, func, lParam );
2940 WIN_ReleaseWinArray(list);
2941 WIN_ReleaseWndPtr(pParent);
2942 return TRUE;
2946 /*******************************************************************
2947 * AnyPopup (USER.52)
2949 BOOL16 WINAPI AnyPopup16(void)
2951 return AnyPopup();
2955 /*******************************************************************
2956 * AnyPopup (USER32.@)
2958 BOOL WINAPI AnyPopup(void)
2960 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2961 BOOL retvalue;
2963 while (wndPtr)
2965 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2967 retvalue = TRUE;
2968 goto end;
2970 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2972 retvalue = FALSE;
2973 end:
2974 WIN_ReleaseWndPtr(wndPtr);
2975 return retvalue;
2979 /*******************************************************************
2980 * FlashWindow (USER.105)
2982 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2984 return FlashWindow( hWnd, bInvert );
2988 /*******************************************************************
2989 * FlashWindow (USER32.@)
2991 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2993 WND *wndPtr = WIN_FindWndPtr(hWnd);
2995 TRACE("%04x\n", hWnd);
2997 if (!wndPtr) return FALSE;
2999 if (wndPtr->dwStyle & WS_MINIMIZE)
3001 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3003 HDC hDC = GetDC(hWnd);
3005 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3006 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3008 ReleaseDC( hWnd, hDC );
3009 wndPtr->flags |= WIN_NCACTIVATED;
3011 else
3013 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3014 wndPtr->flags &= ~WIN_NCACTIVATED;
3016 WIN_ReleaseWndPtr(wndPtr);
3017 return TRUE;
3019 else
3021 WPARAM16 wparam;
3022 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3023 else wparam = (hWnd == GetActiveWindow());
3025 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3026 WIN_ReleaseWndPtr(wndPtr);
3027 return wparam;
3032 /*******************************************************************
3033 * SetSysModalWindow (USER.188)
3035 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3037 HWND hWndOldModal = hwndSysModal;
3038 hwndSysModal = hWnd;
3039 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3040 return hWndOldModal;
3044 /*******************************************************************
3045 * GetSysModalWindow (USER.189)
3047 HWND16 WINAPI GetSysModalWindow16(void)
3049 return hwndSysModal;
3053 /*******************************************************************
3054 * GetWindowContextHelpId (USER32.@)
3056 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3058 DWORD retval;
3059 WND *wnd = WIN_FindWndPtr( hwnd );
3060 if (!wnd) return 0;
3061 retval = wnd->helpContext;
3062 WIN_ReleaseWndPtr(wnd);
3063 return retval;
3067 /*******************************************************************
3068 * SetWindowContextHelpId (USER32.@)
3070 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3072 WND *wnd = WIN_FindWndPtr( hwnd );
3073 if (!wnd) return FALSE;
3074 wnd->helpContext = id;
3075 WIN_ReleaseWndPtr(wnd);
3076 return TRUE;
3080 /*******************************************************************
3081 * DRAG_QueryUpdate
3083 * recursively find a child that contains spDragInfo->pt point
3084 * and send WM_QUERYDROPOBJECT
3086 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3088 BOOL16 wParam, bResult = 0;
3089 POINT pt;
3090 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3091 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3092 RECT tempRect;
3094 if( !ptrQueryWnd || !ptrDragInfo )
3095 goto end;
3097 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3099 GetWindowRect(hQueryWnd,&tempRect);
3101 if( !PtInRect(&tempRect,pt) ||
3102 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3103 goto end;
3105 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3107 tempRect = ptrQueryWnd->rectClient;
3108 if(ptrQueryWnd->parent)
3109 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3110 (LPPOINT)&tempRect, 2 );
3112 if (PtInRect( &tempRect, pt))
3114 wParam = 0;
3116 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3118 if( ptrWnd->dwStyle & WS_VISIBLE )
3120 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3121 if (PtInRect( &tempRect, pt )) break;
3125 if(ptrWnd)
3127 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3128 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3129 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3130 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3131 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3133 WIN_ReleaseWndPtr(ptrWnd);
3136 if(bResult)
3137 goto end;
3139 else wParam = 1;
3141 else wParam = 1;
3143 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3145 ptrDragInfo->hScope = hQueryWnd;
3147 bResult = ( bNoSend )
3148 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3149 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3150 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3151 if( !bResult )
3152 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3154 end:
3155 WIN_ReleaseWndPtr(ptrQueryWnd);
3156 return bResult;
3160 /*******************************************************************
3161 * DragDetect (USER.465)
3163 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3165 POINT pt32;
3166 CONV_POINT16TO32( &pt, &pt32 );
3167 return DragDetect( hWnd, pt32 );
3170 /*******************************************************************
3171 * DragDetect (USER32.@)
3173 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3175 MSG msg;
3176 RECT rect;
3178 rect.left = pt.x - wDragWidth;
3179 rect.right = pt.x + wDragWidth;
3181 rect.top = pt.y - wDragHeight;
3182 rect.bottom = pt.y + wDragHeight;
3184 SetCapture(hWnd);
3186 while(1)
3188 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3190 if( msg.message == WM_LBUTTONUP )
3192 ReleaseCapture();
3193 return 0;
3195 if( msg.message == WM_MOUSEMOVE )
3197 POINT tmp;
3198 tmp.x = LOWORD(msg.lParam);
3199 tmp.y = HIWORD(msg.lParam);
3200 if( !PtInRect( &rect, tmp ))
3202 ReleaseCapture();
3203 return 1;
3207 WaitMessage();
3209 return 0;
3212 /******************************************************************************
3213 * DragObject (USER.464)
3215 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3216 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3218 MSG msg;
3219 LPDRAGINFO16 lpDragInfo;
3220 SEGPTR spDragInfo;
3221 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3222 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3223 WND *wndPtr = WIN_FindWndPtr(hWnd);
3224 HCURSOR16 hCurrentCursor = 0;
3225 HWND16 hCurrentWnd = 0;
3227 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3228 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3230 if( !lpDragInfo || !spDragInfo )
3232 WIN_ReleaseWndPtr(wndPtr);
3233 return 0L;
3236 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3238 if( !hBummer || !wndPtr )
3240 GlobalFree16(hDragInfo);
3241 WIN_ReleaseWndPtr(wndPtr);
3242 return 0L;
3245 if(hCursor)
3247 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3249 GlobalFree16(hDragInfo);
3250 WIN_ReleaseWndPtr(wndPtr);
3251 return 0L;
3254 if( hDragCursor == hCursor ) hDragCursor = 0;
3255 else hCursor = hDragCursor;
3257 hOldCursor = SetCursor(hDragCursor);
3260 lpDragInfo->hWnd = hWnd;
3261 lpDragInfo->hScope = 0;
3262 lpDragInfo->wFlags = wObj;
3263 lpDragInfo->hList = szList; /* near pointer! */
3264 lpDragInfo->hOfStruct = hOfStruct;
3265 lpDragInfo->l = 0L;
3267 SetCapture(hWnd);
3268 ShowCursor( TRUE );
3272 do{ WaitMessage(); }
3273 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3275 *(lpDragInfo+1) = *lpDragInfo;
3277 lpDragInfo->pt.x = msg.pt.x;
3278 lpDragInfo->pt.y = msg.pt.y;
3280 /* update DRAGINFO struct */
3281 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3283 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3284 hCurrentCursor = hCursor;
3285 else
3287 hCurrentCursor = hBummer;
3288 lpDragInfo->hScope = 0;
3290 if( hCurrentCursor )
3291 SetCursor(hCurrentCursor);
3293 /* send WM_DRAGLOOP */
3294 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3295 (LPARAM) spDragInfo );
3296 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3297 if( hCurrentWnd != lpDragInfo->hScope )
3299 if( hCurrentWnd )
3300 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3301 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3302 HIWORD(spDragInfo)) );
3303 hCurrentWnd = lpDragInfo->hScope;
3304 if( hCurrentWnd )
3305 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3307 else
3308 if( hCurrentWnd )
3309 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3311 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3313 ReleaseCapture();
3314 ShowCursor( FALSE );
3316 if( hCursor )
3318 SetCursor( hOldCursor );
3319 if (hDragCursor) DestroyCursor( hDragCursor );
3322 if( hCurrentCursor != hBummer )
3323 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3324 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3325 else
3326 msg.lParam = 0;
3327 GlobalFree16(hDragInfo);
3328 WIN_ReleaseWndPtr(wndPtr);
3330 return (DWORD)(msg.lParam);
3334 /******************************************************************************
3335 * GetWindowModuleFileNameA (USER32.@)
3337 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3339 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3340 hwnd, lpszFileName, cchFileNameMax);
3341 return 0;
3344 /******************************************************************************
3345 * GetWindowModuleFileNameW (USER32.@)
3347 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3349 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3350 hwnd, lpszFileName, cchFileNameMax);
3351 return 0;