Reject pointer messages in SendNotifyMessage[AW] and
[wine/testsucceed.git] / windows / win.c
blobed9d7a7f5604d5e66180000ffd5638a058ed9317
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 "win.h"
14 #include "heap.h"
15 #include "user.h"
16 #include "dce.h"
17 #include "controls.h"
18 #include "cursoricon.h"
19 #include "hook.h"
20 #include "message.h"
21 #include "queue.h"
22 #include "winpos.h"
23 #include "winerror.h"
24 #include "stackframe.h"
25 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(win);
28 DECLARE_DEBUG_CHANNEL(msg);
30 /**********************************************************************/
32 /* Desktop window */
33 static WND *pWndDesktop = NULL;
35 static HWND hwndSysModal = 0;
37 static WORD wDragWidth = 4;
38 static WORD wDragHeight= 3;
40 /* thread safeness */
41 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
43 /***********************************************************************
44 * WIN_LockWnds
46 * Locks access to all WND structures for thread safeness
48 void WIN_LockWnds( void )
50 _EnterSysLevel( &WIN_SysLevel );
53 /***********************************************************************
54 * WIN_UnlockWnds
56 * Unlocks access to all WND structures
58 void WIN_UnlockWnds( void )
60 _LeaveSysLevel( &WIN_SysLevel );
63 /***********************************************************************
64 * WIN_SuspendWndsLock
66 * Suspend the lock on WND structures.
67 * Returns the number of locks suspended
69 int WIN_SuspendWndsLock( void )
71 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
72 int count = isuspendedLocks;
74 while ( count-- > 0 )
75 _LeaveSysLevel( &WIN_SysLevel );
77 return isuspendedLocks;
80 /***********************************************************************
81 * WIN_RestoreWndsLock
83 * Restore the suspended locks on WND structures
85 void WIN_RestoreWndsLock( int ipreviousLocks )
87 while ( ipreviousLocks-- > 0 )
88 _EnterSysLevel( &WIN_SysLevel );
91 /***********************************************************************
92 * WIN_FindWndPtr
94 * Return a pointer to the WND structure corresponding to a HWND.
96 WND * WIN_FindWndPtr( HWND hwnd )
98 WND * ptr;
100 if (!hwnd || HIWORD(hwnd)) goto error2;
101 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
102 /* Lock all WND structures for thread safeness*/
103 WIN_LockWnds();
104 /*and increment destruction monitoring*/
105 ptr->irefCount++;
107 if (ptr->dwMagic != WND_MAGIC) goto error;
108 if (ptr->hwndSelf != hwnd)
110 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
111 goto error;
113 /* returns a locked pointer */
114 return ptr;
115 error:
116 /* Unlock all WND structures for thread safeness*/
117 WIN_UnlockWnds();
118 /* and decrement destruction monitoring value */
119 ptr->irefCount--;
121 error2:
122 if ( hwnd!=0 )
123 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
124 return NULL;
127 /***********************************************************************
128 * WIN_LockWndPtr
130 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
131 * but by initWndPtr;
132 * Returns the locked initialisation pointer
134 WND *WIN_LockWndPtr(WND *initWndPtr)
136 if(!initWndPtr) return 0;
138 /* Lock all WND structures for thread safeness*/
139 WIN_LockWnds();
140 /*and increment destruction monitoring*/
141 initWndPtr->irefCount++;
143 return initWndPtr;
147 /***********************************************************************
148 * WIN_ReleaseWndPtr
150 * Release the pointer to the WND structure.
152 void WIN_ReleaseWndPtr(WND *wndPtr)
154 if(!wndPtr) return;
156 /*Decrement destruction monitoring value*/
157 wndPtr->irefCount--;
158 /* Check if it's time to release the memory*/
159 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
161 /* Release memory */
162 USER_HEAP_FREE( wndPtr->hwndSelf);
163 wndPtr->hwndSelf = 0;
165 else if(wndPtr->irefCount < 0)
167 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
168 ERR("forgot a Lock on %p somewhere\n",wndPtr);
170 /*unlock all WND structures for thread safeness*/
171 WIN_UnlockWnds();
174 /***********************************************************************
175 * WIN_UpdateWndPtr
177 * Updates the value of oldPtr to newPtr.
179 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
181 WND *tmpWnd = NULL;
183 tmpWnd = WIN_LockWndPtr(newPtr);
184 WIN_ReleaseWndPtr(*oldPtr);
185 *oldPtr = tmpWnd;
189 /***********************************************************************
190 * WIN_DumpWindow
192 * Dump the content of a window structure to stderr.
194 void WIN_DumpWindow( HWND hwnd )
196 WND *ptr;
197 char className[80];
198 int i;
200 if (!(ptr = WIN_FindWndPtr( hwnd )))
202 WARN("%04x is not a window handle\n", hwnd );
203 return;
206 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
207 strcpy( className, "#NULL#" );
209 TRACE("Window %04x (%p):\n", hwnd, ptr );
210 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
211 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
212 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
213 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
214 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
215 ptr->next, ptr->child, ptr->parent, ptr->owner,
216 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
217 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
218 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
219 ptr->text ? debugstr_w(ptr->text) : "",
220 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
221 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
222 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
223 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
225 if (ptr->cbWndExtra)
227 DPRINTF( "extra bytes:" );
228 for (i = 0; i < ptr->cbWndExtra; i++)
229 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
230 DPRINTF( "\n" );
232 DPRINTF( "\n" );
233 WIN_ReleaseWndPtr(ptr);
237 /***********************************************************************
238 * WIN_WalkWindows
240 * Walk the windows tree and print each window on stderr.
242 void WIN_WalkWindows( HWND hwnd, int indent )
244 WND *ptr;
245 char className[80];
247 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
249 if (!ptr)
251 WARN("Invalid window handle %04x\n", hwnd );
252 return;
255 if (!indent) /* first time around */
256 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
257 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
258 " Text");
260 while (ptr)
262 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
264 GetClassNameA( ptr->hwndSelf, className, sizeof(className) );
265 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
266 (DWORD)ptr, ptr->hmemTaskQ, className,
267 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
268 ptr->text ? debugstr_w(ptr->text) : "<null>");
270 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
271 WIN_UpdateWndPtr(&ptr,ptr->next);
275 /***********************************************************************
276 * WIN_UnlinkWindow
278 * Remove a window from the siblings linked list.
280 BOOL WIN_UnlinkWindow( HWND hwnd )
282 WND *wndPtr, **ppWnd;
283 BOOL ret = FALSE;
285 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
286 else if(!wndPtr->parent)
288 WIN_ReleaseWndPtr(wndPtr);
289 return FALSE;
292 ppWnd = &wndPtr->parent->child;
293 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
294 if (*ppWnd)
296 *ppWnd = wndPtr->next;
297 ret = TRUE;
299 WIN_ReleaseWndPtr(wndPtr);
300 return ret;
304 /***********************************************************************
305 * WIN_LinkWindow
307 * Insert a window into the siblings linked list.
308 * The window is inserted after the specified window, which can also
309 * be specified as HWND_TOP or HWND_BOTTOM.
311 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
313 WND *wndPtr, **ppWnd;
315 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
316 else if(!wndPtr->parent)
318 WIN_ReleaseWndPtr(wndPtr);
319 return FALSE;
321 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
323 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
324 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
325 while (*ppWnd) ppWnd = &(*ppWnd)->next;
327 else /* Normal case */
329 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
330 if (!afterPtr)
332 WIN_ReleaseWndPtr(wndPtr);
333 return FALSE;
335 ppWnd = &afterPtr->next;
336 WIN_ReleaseWndPtr(afterPtr);
338 wndPtr->next = *ppWnd;
339 *ppWnd = wndPtr;
340 WIN_ReleaseWndPtr(wndPtr);
341 return TRUE;
345 /***********************************************************************
346 * WIN_FindWinToRepaint
348 * Find a window that needs repaint.
350 HWND WIN_FindWinToRepaint( HWND hwnd )
352 HWND hwndRet;
353 WND *pWnd;
355 /* Note: the desktop window never gets WM_PAINT messages
356 * The real reason why is because Windows DesktopWndProc
357 * does ValidateRgn inside WM_ERASEBKGND handler.
359 if (hwnd == GetDesktopWindow()) hwnd = 0;
361 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
363 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
365 if (!(pWnd->dwStyle & WS_VISIBLE))
367 TRACE("skipping window %04x\n",
368 pWnd->hwndSelf );
370 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
371 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
372 break;
374 else if (pWnd->child )
375 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
377 WIN_ReleaseWndPtr(pWnd);
378 return hwndRet;
383 if(!pWnd)
385 return 0;
388 hwndRet = pWnd->hwndSelf;
390 /* look among siblings if we got a transparent window */
391 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
392 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
394 WIN_UpdateWndPtr(&pWnd,pWnd->next);
396 if (pWnd)
398 hwndRet = pWnd->hwndSelf;
399 WIN_ReleaseWndPtr(pWnd);
401 TRACE("found %04x\n",hwndRet);
402 return hwndRet;
406 /***********************************************************************
407 * WIN_DestroyWindow
409 * Destroy storage associated to a window. "Internals" p.358
410 * returns a locked wndPtr->next
412 static WND* WIN_DestroyWindow( WND* wndPtr )
414 HWND hwnd = wndPtr->hwndSelf;
415 WND *pWnd;
417 TRACE("%04x\n", wndPtr->hwndSelf );
419 /* free child windows */
420 WIN_LockWndPtr(wndPtr->child);
421 while ((pWnd = wndPtr->child))
423 wndPtr->child = WIN_DestroyWindow( pWnd );
424 WIN_ReleaseWndPtr(pWnd);
428 * Clear the update region to make sure no WM_PAINT messages will be
429 * generated for this window while processing the WM_NCDESTROY.
431 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
432 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
435 * Send the WM_NCDESTROY to the window being destroyed.
437 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
439 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
441 WINPOS_CheckInternalPos( wndPtr );
442 if( hwnd == GetCapture()) ReleaseCapture();
444 /* free resources associated with the window */
446 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
447 PROPERTY_RemoveWindowProps( wndPtr );
449 /* toss stale messages from the queue */
451 QUEUE_CleanupWindow( hwnd );
452 wndPtr->hmemTaskQ = 0;
454 if (!(wndPtr->dwStyle & WS_CHILD))
455 if (wndPtr->wIDmenu)
457 DestroyMenu( wndPtr->wIDmenu );
458 wndPtr->wIDmenu = 0;
460 if (wndPtr->hSysMenu)
462 DestroyMenu( wndPtr->hSysMenu );
463 wndPtr->hSysMenu = 0;
465 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
466 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
467 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
468 CLASS_RemoveWindow( wndPtr->class );
469 wndPtr->class = NULL;
470 wndPtr->dwMagic = 0; /* Mark it as invalid */
472 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
474 return pWnd;
477 /***********************************************************************
478 * WIN_DestroyThreadWindows
480 * Destroy all children of 'wnd' owned by the current thread.
481 * Return TRUE if something was done.
483 BOOL WIN_DestroyThreadWindows( HWND hwnd )
485 BOOL ret = FALSE;
486 WND *wnd = WIN_FindWndPtr( hwnd );
488 if (!wnd) return FALSE;
489 while (wnd->child)
491 WND *tmp = WIN_LockWndPtr(wnd->child);
492 ret = FALSE;
493 while (tmp)
495 if (GetWindowThreadProcessId( tmp->hwndSelf, NULL ) == GetCurrentThreadId())
497 DestroyWindow( tmp->hwndSelf );
498 ret = TRUE;
499 break;
501 if (tmp->child && WIN_DestroyThreadWindows( tmp->hwndSelf ))
502 ret = TRUE;
503 else
504 WIN_UpdateWndPtr(&tmp,tmp->next);
506 WIN_ReleaseWndPtr(tmp);
507 if (!ret) break;
509 WIN_ReleaseWndPtr( wnd );
510 return ret;
513 /***********************************************************************
514 * WIN_CreateDesktopWindow
516 * Create the desktop window.
518 BOOL WIN_CreateDesktopWindow(void)
520 struct tagCLASS *class;
521 HWND hwndDesktop;
522 INT wndExtra;
523 DWORD clsStyle;
524 WNDPROC winproc;
525 DCE *dce;
526 CREATESTRUCTA cs;
528 TRACE("Creating desktop window\n");
531 if (!WINPOS_CreateInternalPosAtom() ||
532 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
533 &wndExtra, &winproc, &clsStyle, &dce )))
534 return FALSE;
536 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
537 if (!hwndDesktop) return FALSE;
538 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
540 pWndDesktop->next = NULL;
541 pWndDesktop->child = NULL;
542 pWndDesktop->parent = NULL;
543 pWndDesktop->owner = NULL;
544 pWndDesktop->class = class;
545 pWndDesktop->dwMagic = WND_MAGIC;
546 pWndDesktop->hwndSelf = hwndDesktop;
547 pWndDesktop->hInstance = 0;
548 pWndDesktop->rectWindow.left = 0;
549 pWndDesktop->rectWindow.top = 0;
550 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
551 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
552 pWndDesktop->rectClient = pWndDesktop->rectWindow;
553 pWndDesktop->text = NULL;
554 pWndDesktop->hmemTaskQ = 0;
555 pWndDesktop->hrgnUpdate = 0;
556 pWndDesktop->hwndLastActive = hwndDesktop;
557 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
558 WS_CLIPSIBLINGS;
559 pWndDesktop->dwExStyle = 0;
560 pWndDesktop->clsStyle = clsStyle;
561 pWndDesktop->dce = NULL;
562 pWndDesktop->pVScroll = NULL;
563 pWndDesktop->pHScroll = NULL;
564 pWndDesktop->pProp = NULL;
565 pWndDesktop->wIDmenu = 0;
566 pWndDesktop->helpContext = 0;
567 pWndDesktop->flags = 0;
568 pWndDesktop->hSysMenu = 0;
569 pWndDesktop->userdata = 0;
570 pWndDesktop->winproc = winproc;
571 pWndDesktop->cbWndExtra = wndExtra;
572 pWndDesktop->irefCount = 0;
574 cs.lpCreateParams = NULL;
575 cs.hInstance = 0;
576 cs.hMenu = 0;
577 cs.hwndParent = 0;
578 cs.x = 0;
579 cs.y = 0;
580 cs.cx = pWndDesktop->rectWindow.right;
581 cs.cy = pWndDesktop->rectWindow.bottom;
582 cs.style = pWndDesktop->dwStyle;
583 cs.dwExStyle = pWndDesktop->dwExStyle;
584 cs.lpszName = NULL;
585 cs.lpszClass = DESKTOP_CLASS_ATOM;
587 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
589 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
590 return TRUE;
594 /***********************************************************************
595 * WIN_FixCoordinates
597 * Fix the coordinates - Helper for WIN_CreateWindowEx.
598 * returns default show mode in sw.
599 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
601 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
603 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
604 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
606 if (cs->style & (WS_CHILD | WS_POPUP))
608 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
609 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
611 else /* overlapped window */
613 STARTUPINFOA info;
615 GetStartupInfoA( &info );
617 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
619 /* Never believe Microsoft's documentation... CreateWindowEx doc says
620 * that if an overlapped window is created with WS_VISIBLE style bit
621 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
622 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
623 * reveals that
625 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
626 * 2) it does not ignore the y parameter as the docs claim; instead, it
627 * uses it as second parameter to ShowWindow() unless y is either
628 * CW_USEDEFAULT or CW_USEDEFAULT16.
630 * The fact that we didn't do 2) caused bogus windows pop up when wine
631 * was running apps that were using this obscure feature. Example -
632 * calc.exe that comes with Win98 (only Win98, it's different from
633 * the one that comes with Win95 and NT)
635 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
636 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
637 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
640 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
642 if (info.dwFlags & STARTF_USESIZE)
644 cs->cx = info.dwXSize;
645 cs->cy = info.dwYSize;
647 else /* if no other hint from the app, pick 3/4 of the screen real estate */
649 RECT r;
650 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
651 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
652 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
659 /***********************************************************************
660 * WIN_CreateWindowEx
662 * Implementation of CreateWindowEx().
664 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
665 WINDOWPROCTYPE type )
667 INT sw = SW_SHOW;
668 struct tagCLASS *classPtr;
669 WND *wndPtr;
670 HWND hwnd, hwndLinkAfter;
671 POINT maxSize, maxPos, minTrack, maxTrack;
672 INT wndExtra;
673 DWORD clsStyle;
674 WNDPROC winproc;
675 DCE *dce;
676 BOOL unicode = (type == WIN_PROC_32W);
678 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
679 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
680 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
681 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
682 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
684 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
685 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
687 /* Find the parent window */
689 if (cs->hwndParent)
691 /* Make sure parent is valid */
692 if (!IsWindow( cs->hwndParent ))
694 WARN("Bad parent %04x\n", cs->hwndParent );
695 return 0;
697 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
698 WARN("No parent for child window\n" );
699 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
702 /* Find the window class */
703 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
704 &wndExtra, &winproc, &clsStyle, &dce )))
706 WARN("Bad class '%s'\n", cs->lpszClass );
707 return 0;
710 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
712 /* Create the window structure */
714 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
716 TRACE("out of memory\n" );
717 return 0;
720 /* Fill the window structure */
722 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
723 wndPtr->next = NULL;
724 wndPtr->child = NULL;
726 if ((cs->style & WS_CHILD) && cs->hwndParent)
728 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
729 wndPtr->owner = NULL;
730 WIN_ReleaseWndPtr(wndPtr->parent);
732 else
734 wndPtr->parent = pWndDesktop;
735 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
736 wndPtr->owner = NULL;
737 else
739 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
740 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
741 WIN_ReleaseWndPtr(wndPtr->owner);
742 WIN_ReleaseWndPtr(tmpWnd);
747 wndPtr->class = classPtr;
748 wndPtr->winproc = winproc;
749 wndPtr->dwMagic = WND_MAGIC;
750 wndPtr->hwndSelf = hwnd;
751 wndPtr->hInstance = cs->hInstance;
752 wndPtr->text = NULL;
753 wndPtr->hmemTaskQ = GetFastQueue16();
754 wndPtr->hrgnUpdate = 0;
755 wndPtr->hrgnWnd = 0;
756 wndPtr->hwndLastActive = hwnd;
757 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
758 wndPtr->dwExStyle = cs->dwExStyle;
759 wndPtr->clsStyle = clsStyle;
760 wndPtr->wIDmenu = 0;
761 wndPtr->helpContext = 0;
762 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
763 wndPtr->pVScroll = NULL;
764 wndPtr->pHScroll = NULL;
765 wndPtr->pProp = NULL;
766 wndPtr->userdata = 0;
767 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
768 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
769 wndPtr->cbWndExtra = wndExtra;
770 wndPtr->irefCount = 1;
772 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
774 /* Call the WH_CBT hook */
776 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
777 ? HWND_BOTTOM : HWND_TOP;
779 if (HOOK_IsHooked( WH_CBT ))
781 CBT_CREATEWNDA cbtc;
782 LRESULT ret;
784 cbtc.lpcs = cs;
785 cbtc.hwndInsertAfter = hwndLinkAfter;
786 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
787 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
788 if (ret)
790 TRACE("CBT-hook returned 0\n");
791 USER_HEAP_FREE( hwnd );
792 CLASS_RemoveWindow( classPtr );
793 hwnd = 0;
794 goto end;
798 /* Correct the window style */
800 if (!(cs->style & WS_CHILD))
802 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
803 if (!(cs->style & WS_POPUP))
805 wndPtr->dwStyle |= WS_CAPTION;
806 wndPtr->flags |= WIN_NEED_SIZE;
810 /* Get class or window DC if needed */
812 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
813 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
814 else wndPtr->dce = NULL;
816 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
818 wndPtr->rectWindow.left = cs->x;
819 wndPtr->rectWindow.top = cs->y;
820 wndPtr->rectWindow.right = cs->x + cs->cx;
821 wndPtr->rectWindow.bottom = cs->y + cs->cy;
822 wndPtr->rectClient = wndPtr->rectWindow;
824 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
826 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
828 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
829 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
830 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
831 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
832 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
835 if (cs->cx < 0) cs->cx = 0;
836 if (cs->cy < 0) cs->cy = 0;
838 wndPtr->rectWindow.left = cs->x;
839 wndPtr->rectWindow.top = cs->y;
840 wndPtr->rectWindow.right = cs->x + cs->cx;
841 wndPtr->rectWindow.bottom = cs->y + cs->cy;
842 wndPtr->rectClient = wndPtr->rectWindow;
844 /* Set the window menu */
846 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
848 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
849 else
851 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
852 if (menuName)
854 if (HIWORD(cs->hInstance))
855 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
856 else
857 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
859 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
863 else wndPtr->wIDmenu = (UINT)cs->hMenu;
865 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
867 WARN("aborted by WM_xxCREATE!\n");
868 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
869 CLASS_RemoveWindow( classPtr );
870 WIN_ReleaseWndPtr(wndPtr);
871 return 0;
874 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
876 /* Notify the parent window only */
878 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
879 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
880 if( !IsWindow(hwnd) )
882 hwnd = 0;
883 goto end;
887 if (cs->style & WS_VISIBLE)
889 /* in case WS_VISIBLE got set in the meantime */
890 wndPtr->dwStyle &= ~WS_VISIBLE;
891 ShowWindow( hwnd, sw );
894 /* Call WH_SHELL hook */
896 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
897 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
899 TRACE("created window %04x\n", hwnd);
900 end:
901 WIN_ReleaseWndPtr(wndPtr);
902 return hwnd;
906 /***********************************************************************
907 * CreateWindow (USER.41)
909 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
910 DWORD style, INT16 x, INT16 y, INT16 width,
911 INT16 height, HWND16 parent, HMENU16 menu,
912 HINSTANCE16 instance, LPVOID data )
914 return CreateWindowEx16( 0, className, windowName, style,
915 x, y, width, height, parent, menu, instance, data );
919 /***********************************************************************
920 * CreateWindowEx (USER.452)
922 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
923 LPCSTR windowName, DWORD style, INT16 x,
924 INT16 y, INT16 width, INT16 height,
925 HWND16 parent, HMENU16 menu,
926 HINSTANCE16 instance, LPVOID data )
928 ATOM classAtom;
929 CREATESTRUCTA cs;
930 char buffer[256];
932 /* Find the class atom */
934 if (HIWORD(className))
936 if (!(classAtom = GlobalFindAtomA( className )))
938 ERR( "bad class name %s\n", debugres_a(className) );
939 return 0;
942 else
944 classAtom = LOWORD(className);
945 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
947 ERR( "bad atom %x\n", classAtom);
948 return 0;
950 className = buffer;
953 /* Fix the coordinates */
955 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
956 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
957 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
958 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
960 /* Create the window */
962 cs.lpCreateParams = data;
963 cs.hInstance = (HINSTANCE)instance;
964 cs.hMenu = (HMENU)menu;
965 cs.hwndParent = (HWND)parent;
966 cs.style = style;
967 cs.lpszName = windowName;
968 cs.lpszClass = className;
969 cs.dwExStyle = exStyle;
971 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
975 /***********************************************************************
976 * CreateWindowExA (USER32.@)
978 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
979 LPCSTR windowName, DWORD style, INT x,
980 INT y, INT width, INT height,
981 HWND parent, HMENU menu,
982 HINSTANCE instance, LPVOID data )
984 ATOM classAtom;
985 CREATESTRUCTA cs;
986 char buffer[256];
988 if(!instance)
989 instance=GetModuleHandleA(NULL);
991 if(exStyle & WS_EX_MDICHILD)
992 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
994 /* Find the class atom */
996 if (HIWORD(className))
998 if (!(classAtom = GlobalFindAtomA( className )))
1000 ERR( "bad class name %s\n", debugres_a(className) );
1001 return 0;
1004 else
1006 classAtom = LOWORD(className);
1007 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1009 ERR( "bad atom %x\n", classAtom);
1010 return 0;
1012 className = buffer;
1015 /* Create the window */
1017 cs.lpCreateParams = data;
1018 cs.hInstance = instance;
1019 cs.hMenu = menu;
1020 cs.hwndParent = parent;
1021 cs.x = x;
1022 cs.y = y;
1023 cs.cx = width;
1024 cs.cy = height;
1025 cs.style = style;
1026 cs.lpszName = windowName;
1027 cs.lpszClass = className;
1028 cs.dwExStyle = exStyle;
1030 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1034 /***********************************************************************
1035 * CreateWindowExW (USER32.@)
1037 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1038 LPCWSTR windowName, DWORD style, INT x,
1039 INT y, INT width, INT height,
1040 HWND parent, HMENU menu,
1041 HINSTANCE instance, LPVOID data )
1043 ATOM classAtom;
1044 CREATESTRUCTW cs;
1045 WCHAR buffer[256];
1047 if(!instance)
1048 instance=GetModuleHandleA(NULL);
1050 if(exStyle & WS_EX_MDICHILD)
1051 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1053 /* Find the class atom */
1055 if (HIWORD(className))
1057 if (!(classAtom = GlobalFindAtomW( className )))
1059 ERR( "bad class name %s\n", debugres_w(className) );
1060 return 0;
1063 else
1065 classAtom = LOWORD(className);
1066 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1068 ERR( "bad atom %x\n", classAtom);
1069 return 0;
1071 className = buffer;
1074 /* Create the window */
1076 cs.lpCreateParams = data;
1077 cs.hInstance = instance;
1078 cs.hMenu = menu;
1079 cs.hwndParent = parent;
1080 cs.x = x;
1081 cs.y = y;
1082 cs.cx = width;
1083 cs.cy = height;
1084 cs.style = style;
1085 cs.lpszName = windowName;
1086 cs.lpszClass = className;
1087 cs.dwExStyle = exStyle;
1089 /* Note: we rely on the fact that CREATESTRUCTA and */
1090 /* CREATESTRUCTW have the same layout. */
1091 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1094 /***********************************************************************
1095 * WIN_SendDestroyMsg
1097 static void WIN_SendDestroyMsg( WND* pWnd )
1099 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1100 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1103 * Send the WM_DESTROY to the window.
1105 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1108 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1109 * make sure that the window still exists when we come back.
1111 if (IsWindow(pWnd->hwndSelf))
1113 HWND* pWndArray = NULL;
1114 WND* pChild = NULL;
1115 int nKidCount = 0;
1118 * Now, if the window has kids, we have to send WM_DESTROY messages
1119 * recursively to it's kids. It seems that those calls can also
1120 * trigger re-entrant calls to DestroyWindow for the kids so we must
1121 * protect against corruption of the list of siblings. We first build
1122 * a list of HWNDs representing all the kids.
1124 pChild = WIN_LockWndPtr(pWnd->child);
1125 while( pChild )
1127 nKidCount++;
1128 WIN_UpdateWndPtr(&pChild,pChild->next);
1132 * If there are no kids, we're done.
1134 if (nKidCount==0)
1135 return;
1137 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1140 * Sanity check
1142 if (pWndArray==NULL)
1143 return;
1146 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1147 * call, our linked list of siblings should be safe.
1149 nKidCount = 0;
1150 pChild = WIN_LockWndPtr(pWnd->child);
1151 while( pChild )
1153 pWndArray[nKidCount] = pChild->hwndSelf;
1154 nKidCount++;
1155 WIN_UpdateWndPtr(&pChild,pChild->next);
1159 * Now that we have a list, go through that list again and send the destroy
1160 * message to those windows. We are using the HWND to retrieve the
1161 * WND pointer so we are effectively checking that all the kid windows are
1162 * still valid before sending the message.
1164 while (nKidCount>0)
1166 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1168 if (pChild!=NULL)
1170 WIN_SendDestroyMsg( pChild );
1171 WIN_ReleaseWndPtr(pChild);
1176 * Cleanup
1178 HeapFree(GetProcessHeap(), 0, pWndArray);
1180 else
1181 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1185 /***********************************************************************
1186 * DestroyWindow (USER.53)
1188 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1190 return DestroyWindow(hwnd);
1194 /***********************************************************************
1195 * DestroyWindow (USER32.@)
1197 BOOL WINAPI DestroyWindow( HWND hwnd )
1199 WND * wndPtr;
1200 BOOL retvalue;
1201 HWND h;
1202 BOOL bFocusSet = FALSE;
1204 TRACE("(%04x)\n", hwnd);
1206 /* Initialization */
1208 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1209 if (wndPtr == pWndDesktop)
1211 retvalue = FALSE; /* Can't destroy desktop */
1212 goto end;
1215 /* Look whether the focus is within the tree of windows we will
1216 * be destroying.
1218 h = GetFocus16();
1219 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1221 if (h == hwnd)
1223 SetFocus(GetParent(h));
1224 bFocusSet = TRUE;
1225 break;
1227 h = GetParent(h);
1229 /* If the focus is on the window we will destroy and it has no parent,
1230 * set the focus to 0.
1232 if (! bFocusSet && (h == hwnd))
1234 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1235 SetFocus(0);
1238 /* Call hooks */
1240 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1242 retvalue = FALSE;
1243 goto end;
1246 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1248 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1249 /* FIXME: clean up palette - see "Internals" p.352 */
1252 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1253 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1255 /* Notify the parent window only */
1256 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1257 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1258 if( !IsWindow(hwnd) )
1260 retvalue = TRUE;
1261 goto end;
1265 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1267 /* Hide the window */
1269 if (wndPtr->dwStyle & WS_VISIBLE)
1271 ShowWindow( hwnd, SW_HIDE );
1272 if (!IsWindow(hwnd))
1274 retvalue = TRUE;
1275 goto end;
1279 /* Recursively destroy owned windows */
1281 if( !(wndPtr->dwStyle & WS_CHILD) )
1283 for (;;)
1285 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1286 while (siblingPtr)
1288 if (siblingPtr->owner == wndPtr)
1290 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1291 break;
1292 else
1293 siblingPtr->owner = NULL;
1295 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1297 if (siblingPtr)
1299 DestroyWindow( siblingPtr->hwndSelf );
1300 WIN_ReleaseWndPtr(siblingPtr);
1302 else break;
1305 WINPOS_ActivateOtherWindow(wndPtr);
1307 if( wndPtr->owner &&
1308 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1309 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1312 /* Send destroy messages */
1314 WIN_SendDestroyMsg( wndPtr );
1315 if (!IsWindow(hwnd))
1317 retvalue = TRUE;
1318 goto end;
1321 /* Unlink now so we won't bother with the children later on */
1323 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1325 /* Destroy the window storage */
1327 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1328 retvalue = TRUE;
1329 end:
1330 WIN_ReleaseWndPtr(wndPtr);
1331 return retvalue;
1335 /***********************************************************************
1336 * CloseWindow (USER.43)
1338 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1340 return CloseWindow( hwnd );
1344 /***********************************************************************
1345 * CloseWindow (USER32.@)
1347 BOOL WINAPI CloseWindow( HWND hwnd )
1349 WND * wndPtr = WIN_FindWndPtr( hwnd );
1350 BOOL retvalue;
1352 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1354 retvalue = FALSE;
1355 goto end;
1357 ShowWindow( hwnd, SW_MINIMIZE );
1358 retvalue = TRUE;
1359 end:
1360 WIN_ReleaseWndPtr(wndPtr);
1361 return retvalue;
1366 /***********************************************************************
1367 * OpenIcon (USER.44)
1369 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1371 return OpenIcon( hwnd );
1375 /***********************************************************************
1376 * OpenIcon (USER32.@)
1378 BOOL WINAPI OpenIcon( HWND hwnd )
1380 if (!IsIconic( hwnd )) return FALSE;
1381 ShowWindow( hwnd, SW_SHOWNORMAL );
1382 return TRUE;
1386 /***********************************************************************
1387 * WIN_FindWindow
1389 * Implementation of FindWindow() and FindWindowEx().
1391 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1392 LPCWSTR title )
1394 WND *pWnd;
1395 HWND retvalue;
1397 if (child)
1399 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1400 if (parent)
1402 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1404 retvalue = 0;
1405 goto end;
1408 else if (pWnd->parent != pWndDesktop)
1410 retvalue = 0;
1411 goto end;
1413 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1415 else
1417 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1419 retvalue = 0;
1420 goto end;
1422 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1424 if (!pWnd)
1426 retvalue = 0;
1427 goto end;
1430 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1432 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1433 continue; /* Not the right class */
1435 /* Now check the title */
1437 if (!title)
1439 retvalue = pWnd->hwndSelf;
1440 goto end;
1442 if (pWnd->text && !strcmpW( pWnd->text, title ))
1444 retvalue = pWnd->hwndSelf;
1445 goto end;
1448 retvalue = 0;
1449 /* In this case we need to check whether other processes
1450 own a window with the given paramters on the Desktop,
1451 but we don't, so let's at least warn about it */
1452 FIXME("Returning 0 without checking other processes\n");
1453 end:
1454 WIN_ReleaseWndPtr(pWnd);
1455 return retvalue;
1460 /***********************************************************************
1461 * FindWindow (USER.50)
1463 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1465 return FindWindowA( className, title );
1469 /***********************************************************************
1470 * FindWindowEx (USER.427)
1472 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1474 return FindWindowExA( parent, child, className, title );
1478 /***********************************************************************
1479 * FindWindowA (USER32.@)
1481 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1483 HWND ret = FindWindowExA( 0, 0, className, title );
1484 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1485 return ret;
1489 /***********************************************************************
1490 * FindWindowExA (USER32.@)
1492 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1493 LPCSTR className, LPCSTR title )
1495 ATOM atom = 0;
1496 LPWSTR buffer;
1497 HWND hwnd;
1499 if (className)
1501 /* If the atom doesn't exist, then no class */
1502 /* with this name exists either. */
1503 if (!(atom = GlobalFindAtomA( className )))
1505 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1506 return 0;
1510 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1511 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1512 HeapFree( GetProcessHeap(), 0, buffer );
1513 return hwnd;
1517 /***********************************************************************
1518 * FindWindowExW (USER32.@)
1520 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1521 LPCWSTR className, LPCWSTR title )
1523 ATOM atom = 0;
1525 if (className)
1527 /* If the atom doesn't exist, then no class */
1528 /* with this name exists either. */
1529 if (!(atom = GlobalFindAtomW( className )))
1531 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1532 return 0;
1535 return WIN_FindWindow( parent, child, atom, title );
1539 /***********************************************************************
1540 * FindWindowW (USER32.@)
1542 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1544 return FindWindowExW( 0, 0, className, title );
1548 /**********************************************************************
1549 * WIN_GetDesktop
1550 * returns a locked pointer
1552 WND *WIN_GetDesktop(void)
1554 return WIN_LockWndPtr(pWndDesktop);
1556 /**********************************************************************
1557 * WIN_ReleaseDesktop
1558 * unlock the desktop pointer
1560 void WIN_ReleaseDesktop(void)
1562 WIN_ReleaseWndPtr(pWndDesktop);
1566 /**********************************************************************
1567 * GetDesktopWindow (USER.286)
1569 HWND16 WINAPI GetDesktopWindow16(void)
1571 return (HWND16)pWndDesktop->hwndSelf;
1575 /**********************************************************************
1576 * GetDesktopWindow (USER32.@)
1578 HWND WINAPI GetDesktopWindow(void)
1580 if (pWndDesktop) return pWndDesktop->hwndSelf;
1581 ERR( "You need the -desktop option when running with native USER\n" );
1582 ExitProcess(1);
1583 return 0;
1587 /**********************************************************************
1588 * GetDesktopHwnd (USER.278)
1590 * Exactly the same thing as GetDesktopWindow(), but not documented.
1591 * Don't ask me why...
1593 HWND16 WINAPI GetDesktopHwnd16(void)
1595 return (HWND16)pWndDesktop->hwndSelf;
1599 /*******************************************************************
1600 * EnableWindow (USER.34)
1602 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1604 return EnableWindow( hwnd, enable );
1608 /*******************************************************************
1609 * EnableWindow (USER32.@)
1611 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1613 WND *wndPtr;
1614 BOOL retvalue;
1616 TRACE("( %x, %d )\n", hwnd, enable);
1618 if (USER_Driver.pEnableWindow)
1619 return USER_Driver.pEnableWindow( hwnd, enable );
1621 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1623 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1625 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1627 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1628 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1630 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1632 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1634 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1636 if (hwnd == GetFocus())
1637 SetFocus( 0 ); /* A disabled window can't have the focus */
1639 if (hwnd == GetCapture())
1640 ReleaseCapture(); /* A disabled window can't capture the mouse */
1642 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1644 WIN_ReleaseWndPtr(wndPtr);
1645 return retvalue;
1649 /***********************************************************************
1650 * IsWindowEnabled (USER.35)
1652 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1654 return IsWindowEnabled(hWnd);
1658 /***********************************************************************
1659 * IsWindowEnabled (USER32.@)
1661 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1663 WND * wndPtr;
1664 BOOL retvalue;
1666 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1667 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1668 WIN_ReleaseWndPtr(wndPtr);
1669 return retvalue;
1674 /***********************************************************************
1675 * IsWindowUnicode (USER32.@)
1677 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1679 WND * wndPtr;
1680 BOOL retvalue;
1682 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1683 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1684 WIN_ReleaseWndPtr(wndPtr);
1685 return retvalue;
1689 /**********************************************************************
1690 * GetWindowWord (USER.133)
1692 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1694 return GetWindowWord( hwnd, offset );
1698 /**********************************************************************
1699 * GetWindowWord (USER32.@)
1701 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1703 WORD retvalue;
1704 WND * wndPtr = WIN_FindWndPtr( hwnd );
1705 if (!wndPtr) return 0;
1706 if (offset >= 0)
1708 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1710 WARN("Invalid offset %d\n", offset );
1711 retvalue = 0;
1712 goto end;
1714 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1715 goto end;
1717 switch(offset)
1719 case GWW_ID:
1720 if (HIWORD(wndPtr->wIDmenu))
1721 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1722 wndPtr->wIDmenu);
1723 retvalue = (WORD)wndPtr->wIDmenu;
1724 goto end;
1725 case GWW_HWNDPARENT:
1726 retvalue = GetParent(hwnd);
1727 goto end;
1728 case GWW_HINSTANCE:
1729 if (HIWORD(wndPtr->hInstance))
1730 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1731 wndPtr->hInstance);
1732 retvalue = (WORD)wndPtr->hInstance;
1733 goto end;
1734 default:
1735 WARN("Invalid offset %d\n", offset );
1736 retvalue = 0;
1737 goto end;
1739 end:
1740 WIN_ReleaseWndPtr(wndPtr);
1741 return retvalue;
1744 /**********************************************************************
1745 * SetWindowWord (USER.134)
1747 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1749 return SetWindowWord( hwnd, offset, newval );
1753 /**********************************************************************
1754 * SetWindowWord (USER32.@)
1756 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1758 WORD *ptr, retval;
1759 WND * wndPtr = WIN_FindWndPtr( hwnd );
1760 if (!wndPtr) return 0;
1761 if (offset >= 0)
1763 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1765 WARN("Invalid offset %d\n", offset );
1766 retval = 0;
1767 goto end;
1769 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1771 else switch(offset)
1773 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1774 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1775 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1776 goto end;
1777 default:
1778 WARN("Invalid offset %d\n", offset );
1779 retval = 0;
1780 goto end;
1782 retval = *ptr;
1783 *ptr = newval;
1784 end:
1785 WIN_ReleaseWndPtr(wndPtr);
1786 return retval;
1790 /**********************************************************************
1791 * WIN_GetWindowLong
1793 * Helper function for GetWindowLong().
1795 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1797 LONG retvalue;
1798 WND * wndPtr = WIN_FindWndPtr( hwnd );
1799 if (!wndPtr) return 0;
1800 if (offset >= 0)
1802 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1804 WARN("Invalid offset %d\n", offset );
1805 retvalue = 0;
1806 goto end;
1808 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1809 /* Special case for dialog window procedure */
1810 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1812 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1813 goto end;
1815 goto end;
1817 switch(offset)
1819 case GWL_USERDATA: retvalue = wndPtr->userdata;
1820 goto end;
1821 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1822 goto end;
1823 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1824 goto end;
1825 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1826 goto end;
1827 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1828 type );
1829 goto end;
1830 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1831 goto end;
1832 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1833 goto end;
1834 default:
1835 WARN("Unknown offset %d\n", offset );
1837 retvalue = 0;
1838 end:
1839 WIN_ReleaseWndPtr(wndPtr);
1840 return retvalue;
1844 /**********************************************************************
1845 * WIN_SetWindowLong
1847 * Helper function for SetWindowLong().
1849 * 0 is the failure code. However, in the case of failure SetLastError
1850 * must be set to distinguish between a 0 return value and a failure.
1852 * FIXME: The error values for SetLastError may not be right. Can
1853 * someone check with the real thing?
1855 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1856 WINDOWPROCTYPE type )
1858 LONG *ptr, retval;
1859 WND * wndPtr = WIN_FindWndPtr( hwnd );
1860 STYLESTRUCT style;
1862 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1864 if (!wndPtr)
1866 /* Is this the right error? */
1867 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1868 return 0;
1871 if (offset >= 0)
1873 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1875 WARN("Invalid offset %d\n", offset );
1877 /* Is this the right error? */
1878 SetLastError( ERROR_OUTOFMEMORY );
1880 retval = 0;
1881 goto end;
1883 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1884 /* Special case for dialog window procedure */
1885 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1887 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1888 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1889 type, WIN_PROC_WINDOW );
1890 goto end;
1893 else switch(offset)
1895 case GWL_ID:
1896 ptr = (DWORD*)&wndPtr->wIDmenu;
1897 break;
1898 case GWL_HINSTANCE:
1899 retval = SetWindowWord( hwnd, offset, newval );
1900 goto end;
1901 case GWL_WNDPROC:
1902 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1903 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1904 type, WIN_PROC_WINDOW );
1905 goto end;
1906 case GWL_STYLE:
1907 style.styleOld = wndPtr->dwStyle;
1908 style.styleNew = newval;
1909 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1910 wndPtr->dwStyle = style.styleNew;
1911 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1912 retval = style.styleOld;
1913 goto end;
1915 case GWL_USERDATA:
1916 ptr = &wndPtr->userdata;
1917 break;
1918 case GWL_EXSTYLE:
1919 style.styleOld = wndPtr->dwExStyle;
1920 style.styleNew = newval;
1921 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1922 wndPtr->dwExStyle = newval;
1923 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1924 retval = style.styleOld;
1925 goto end;
1927 default:
1928 WARN("Invalid offset %d\n", offset );
1930 /* Don't think this is right error but it should do */
1931 SetLastError( ERROR_OUTOFMEMORY );
1933 retval = 0;
1934 goto end;
1936 retval = *ptr;
1937 *ptr = newval;
1938 end:
1939 WIN_ReleaseWndPtr(wndPtr);
1940 return retval;
1944 /**********************************************************************
1945 * GetWindowLong (USER.135)
1947 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1949 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1953 /**********************************************************************
1954 * GetWindowLongA (USER32.@)
1956 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1958 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1962 /**********************************************************************
1963 * GetWindowLongW (USER32.@)
1965 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1967 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1971 /**********************************************************************
1972 * SetWindowLong (USER.136)
1974 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1976 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1980 /**********************************************************************
1981 * SetWindowLongA (USER32.@)
1983 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1985 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1989 /**********************************************************************
1990 * SetWindowLongW (USER32.@) Set window attribute
1992 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1993 * value in a window's extra memory.
1995 * The _hwnd_ parameter specifies the window. is the handle to a
1996 * window that has extra memory. The _newval_ parameter contains the
1997 * new attribute or extra memory value. If positive, the _offset_
1998 * parameter is the byte-addressed location in the window's extra
1999 * memory to set. If negative, _offset_ specifies the window
2000 * attribute to set, and should be one of the following values:
2002 * GWL_EXSTYLE The window's extended window style
2004 * GWL_STYLE The window's window style.
2006 * GWL_WNDPROC Pointer to the window's window procedure.
2008 * GWL_HINSTANCE The window's pplication instance handle.
2010 * GWL_ID The window's identifier.
2012 * GWL_USERDATA The window's user-specified data.
2014 * If the window is a dialog box, the _offset_ parameter can be one of
2015 * the following values:
2017 * DWL_DLGPROC The address of the window's dialog box procedure.
2019 * DWL_MSGRESULT The return value of a message
2020 * that the dialog box procedure processed.
2022 * DWL_USER Application specific information.
2024 * RETURNS
2026 * If successful, returns the previous value located at _offset_. Otherwise,
2027 * returns 0.
2029 * NOTES
2031 * Extra memory for a window class is specified by a nonzero cbWndExtra
2032 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2033 * time of class creation.
2035 * Using GWL_WNDPROC to set a new window procedure effectively creates
2036 * a window subclass. Use CallWindowProc() in the new windows procedure
2037 * to pass messages to the superclass's window procedure.
2039 * The user data is reserved for use by the application which created
2040 * the window.
2042 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2043 * instead, call the EnableWindow() function to change the window's
2044 * disabled state.
2046 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2047 * SetParent() instead.
2049 * Win95:
2050 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2051 * it sends WM_STYLECHANGING before changing the settings
2052 * and WM_STYLECHANGED afterwards.
2053 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2055 * BUGS
2057 * GWL_STYLE does not dispatch WM_STYLE... messages.
2059 * CONFORMANCE
2061 * ECMA-234, Win32
2064 LONG WINAPI SetWindowLongW(
2065 HWND hwnd, /* [in] window to alter */
2066 INT offset, /* [in] offset, in bytes, of location to alter */
2067 LONG newval /* [in] new value of location */
2069 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2073 /*******************************************************************
2074 * GetWindowText (USER.36)
2076 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2078 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2082 /*******************************************************************
2083 * GetWindowTextA (USER32.@)
2085 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2087 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2088 (LPARAM)lpString );
2091 /*******************************************************************
2092 * InternalGetWindowText (USER32.@)
2094 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2096 WND *win = WIN_FindWndPtr( hwnd );
2097 if (!win) return 0;
2098 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2099 else lpString[0] = 0;
2100 WIN_ReleaseWndPtr( win );
2101 return strlenW(lpString);
2105 /*******************************************************************
2106 * GetWindowTextW (USER32.@)
2108 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2110 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2111 (LPARAM)lpString );
2115 /*******************************************************************
2116 * SetWindowText (USER.37)
2118 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2120 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2124 /*******************************************************************
2125 * SetWindowText (USER32.@)
2126 * SetWindowTextA (USER32.@)
2128 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2130 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2134 /*******************************************************************
2135 * SetWindowTextW (USER32.@)
2137 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2139 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2143 /*******************************************************************
2144 * GetWindowTextLength (USER.38)
2146 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2148 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2152 /*******************************************************************
2153 * GetWindowTextLengthA (USER32.@)
2155 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2157 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2160 /*******************************************************************
2161 * GetWindowTextLengthW (USER32.@)
2163 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2165 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2169 /*******************************************************************
2170 * IsWindow (USER.47)
2172 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2174 CURRENT_STACK16->es = USER_HeapSel;
2175 return IsWindow( hwnd );
2179 /*******************************************************************
2180 * IsWindow (USER32.@)
2182 BOOL WINAPI IsWindow( HWND hwnd )
2184 WND * wndPtr;
2185 BOOL retvalue;
2187 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2188 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2189 WIN_ReleaseWndPtr(wndPtr);
2190 return retvalue;
2195 /*****************************************************************
2196 * GetParent (USER.46)
2198 HWND16 WINAPI GetParent16( HWND16 hwnd )
2200 return (HWND16)GetParent( hwnd );
2204 /*****************************************************************
2205 * GetParent (USER32.@)
2207 HWND WINAPI GetParent( HWND hwnd )
2209 WND *wndPtr;
2210 HWND retvalue = 0;
2212 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2213 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2214 goto end;
2216 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2217 if (wndPtr)
2218 retvalue = wndPtr->hwndSelf;
2220 end:
2221 WIN_ReleaseWndPtr(wndPtr);
2222 return retvalue;
2226 /*****************************************************************
2227 * WIN_GetTopParent
2229 * Get the top-level parent for a child window.
2230 * returns a locked pointer
2232 WND* WIN_GetTopParentPtr( WND* pWnd )
2234 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2236 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2238 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2240 return tmpWnd;
2243 /*****************************************************************
2244 * WIN_GetTopParent
2246 * Get the top-level parent for a child window.
2248 HWND WIN_GetTopParent( HWND hwnd )
2250 HWND retvalue;
2251 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2252 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2254 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2255 WIN_ReleaseWndPtr(tmpPtr);
2256 WIN_ReleaseWndPtr(wndPtr);
2257 return retvalue;
2261 /*****************************************************************
2262 * SetParent (USER.233)
2264 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2266 return SetParent( hwndChild, hwndNewParent );
2270 /*****************************************************************
2271 * SetParent (USER32.@)
2273 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2275 WND *wndPtr;
2276 WND *pWndParent;
2277 DWORD dwStyle;
2278 HWND retvalue;
2280 if (hwnd == GetDesktopWindow()) /* sanity check */
2282 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2283 return 0;
2286 if (USER_Driver.pSetParent)
2287 return USER_Driver.pSetParent( hwnd, parent );
2289 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2291 dwStyle = wndPtr->dwStyle;
2293 if (!parent) parent = GetDesktopWindow();
2295 if (!(pWndParent = WIN_FindWndPtr(parent)))
2297 WIN_ReleaseWndPtr( wndPtr );
2298 return 0;
2301 /* Windows hides the window first, then shows it again
2302 * including the WM_SHOWWINDOW messages and all */
2303 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2305 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2306 if (pWndParent != wndPtr->parent)
2308 WIN_UnlinkWindow(wndPtr->hwndSelf);
2309 wndPtr->parent = pWndParent;
2311 if (parent != GetDesktopWindow()) /* a child window */
2313 if( !( wndPtr->dwStyle & WS_CHILD ) )
2315 if( wndPtr->wIDmenu != 0)
2317 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2318 wndPtr->wIDmenu = 0;
2322 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2324 WIN_ReleaseWndPtr( pWndParent );
2325 WIN_ReleaseWndPtr( wndPtr );
2327 /* SetParent additionally needs to make hwnd the topmost window
2328 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2329 WM_WINDOWPOSCHANGED notification messages.
2331 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2332 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2333 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2334 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2335 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2336 return retvalue;
2340 /*******************************************************************
2341 * IsChild (USER.48)
2343 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2345 return IsChild(parent,child);
2349 /*******************************************************************
2350 * IsChild (USER32.@)
2352 BOOL WINAPI IsChild( HWND parent, HWND child )
2354 WND * wndPtr = WIN_FindWndPtr( child );
2355 while (wndPtr && wndPtr->parent)
2357 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2358 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2359 if (wndPtr->hwndSelf == parent)
2361 WIN_ReleaseWndPtr(wndPtr);
2362 return TRUE;
2365 WIN_ReleaseWndPtr(wndPtr);
2366 return FALSE;
2370 /***********************************************************************
2371 * IsWindowVisible (USER.49)
2373 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2375 return IsWindowVisible(hwnd);
2379 /***********************************************************************
2380 * IsWindowVisible (USER32.@)
2382 BOOL WINAPI IsWindowVisible( HWND hwnd )
2384 BOOL retval;
2385 WND *wndPtr = WIN_FindWndPtr( hwnd );
2386 while (wndPtr && wndPtr->parent)
2388 if (!(wndPtr->dwStyle & WS_VISIBLE))
2390 WIN_ReleaseWndPtr(wndPtr);
2391 return FALSE;
2393 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2395 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2396 WIN_ReleaseWndPtr(wndPtr);
2397 return retval;
2401 /***********************************************************************
2402 * WIN_IsWindowDrawable
2404 * hwnd is drawable when it is visible, all parents are not
2405 * minimized, and it is itself not minimized unless we are
2406 * trying to draw its default class icon.
2408 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2410 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2411 if ((wnd->dwStyle & WS_MINIMIZE) &&
2412 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2413 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2414 if( wnd->dwStyle & WS_MINIMIZE ||
2415 !(wnd->dwStyle & WS_VISIBLE) ) break;
2416 return (wnd == NULL);
2420 /*******************************************************************
2421 * GetTopWindow (USER.229)
2423 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2425 return GetTopWindow(hwnd);
2429 /*******************************************************************
2430 * GetTopWindow (USER32.@)
2432 HWND WINAPI GetTopWindow( HWND hwnd )
2434 HWND retval = 0;
2435 WND * wndPtr = (hwnd) ?
2436 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2438 if (wndPtr && wndPtr->child)
2439 retval = wndPtr->child->hwndSelf;
2441 WIN_ReleaseWndPtr(wndPtr);
2442 return retval;
2446 /*******************************************************************
2447 * GetWindow (USER.262)
2449 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2451 return GetWindow( hwnd,rel );
2455 /*******************************************************************
2456 * GetWindow (USER32.@)
2458 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2460 HWND retval;
2462 WND * wndPtr = WIN_FindWndPtr( hwnd );
2463 if (!wndPtr) return 0;
2464 switch(rel)
2466 case GW_HWNDFIRST:
2467 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2468 goto end;
2470 case GW_HWNDLAST:
2471 if (!wndPtr->parent)
2473 retval = 0; /* Desktop window */
2474 goto end;
2476 while (wndPtr->next)
2478 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2480 retval = wndPtr->hwndSelf;
2481 goto end;
2483 case GW_HWNDNEXT:
2484 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2485 goto end;
2487 case GW_HWNDPREV:
2488 if (!wndPtr->parent)
2490 retval = 0; /* Desktop window */
2491 goto end;
2493 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2494 if (wndPtr->hwndSelf == hwnd)
2496 retval = 0; /* First in list */
2497 goto end;
2499 while (wndPtr->next)
2501 if (wndPtr->next->hwndSelf == hwnd)
2503 retval = wndPtr->hwndSelf;
2504 goto end;
2506 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2508 retval = 0;
2509 goto end;
2511 case GW_OWNER:
2512 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2513 goto end;
2515 case GW_CHILD:
2516 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2517 goto end;
2519 retval = 0;
2520 end:
2521 WIN_ReleaseWndPtr(wndPtr);
2522 return retval;
2526 /*******************************************************************
2527 * GetNextWindow (USER.230)
2529 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2531 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2532 return GetWindow16( hwnd, flag );
2535 /***********************************************************************
2536 * WIN_InternalShowOwnedPopups
2538 * Internal version of ShowOwnedPopups; Wine functions should use this
2539 * to avoid interfering with application calls to ShowOwnedPopups
2540 * and to make sure the application can't prevent showing/hiding.
2542 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2546 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2548 INT totalChild=0, count=0;
2550 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2552 if (!pWnd) return TRUE;
2555 * Show windows Lowest first, Highest last to preserve Z-Order
2557 for (count = totalChild-1 ; count >=0; count--)
2559 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2561 if (fShow)
2563 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2564 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2567 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2569 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2570 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2573 else
2575 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2576 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2577 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2580 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2582 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2583 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2584 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2589 WIN_ReleaseDesktop();
2590 WIN_ReleaseWinArray(pWnd);
2592 return TRUE;
2595 /*******************************************************************
2596 * ShowOwnedPopups (USER.265)
2598 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2600 ShowOwnedPopups( owner, fShow );
2604 /*******************************************************************
2605 * ShowOwnedPopups (USER32.@)
2607 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2609 UINT totalChild=0, count=0;
2611 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2613 if (!pWnd) return TRUE;
2615 for (; count < totalChild; count++)
2617 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2619 if (fShow)
2621 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2624 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2625 * regardless of the state of the owner
2627 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2628 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2631 else
2633 if (IsWindowVisible(pWnd[count]->hwndSelf))
2636 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2637 * regardless of the state of the owner
2639 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2640 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2646 WIN_ReleaseDesktop();
2647 WIN_ReleaseWinArray(pWnd);
2648 return TRUE;
2652 /*******************************************************************
2653 * GetLastActivePopup (USER.287)
2655 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2657 return GetLastActivePopup( hwnd );
2660 /*******************************************************************
2661 * GetLastActivePopup (USER32.@)
2663 HWND WINAPI GetLastActivePopup( HWND hwnd )
2665 HWND retval;
2666 WND *wndPtr =WIN_FindWndPtr(hwnd);
2667 if (!wndPtr) return hwnd;
2668 retval = wndPtr->hwndLastActive;
2669 WIN_ReleaseWndPtr(wndPtr);
2670 if ((retval != hwnd) && (!IsWindow(retval)))
2671 retval = hwnd;
2672 return retval;
2676 /*******************************************************************
2677 * WIN_BuildWinArray
2679 * Build an array of pointers to the children of a given window.
2680 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2681 * when no windows are found.
2683 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2685 /* Future: this function will lock all windows associated with this array */
2687 WND **list, **ppWnd;
2688 WND *pWnd;
2689 UINT count = 0, skipOwned, skipHidden;
2690 DWORD skipFlags;
2692 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2693 skipOwned = bwaFlags & BWA_SKIPOWNED;
2694 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2695 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2697 /* First count the windows */
2699 if (!wndPtr)
2700 wndPtr = WIN_GetDesktop();
2702 pWnd = WIN_LockWndPtr(wndPtr->child);
2703 while (pWnd)
2705 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2706 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2707 count++;
2708 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2711 if( count )
2713 /* Now build the list of all windows */
2715 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2717 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2719 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2720 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2722 *ppWnd++ = pWnd;
2723 count++;
2726 WIN_ReleaseWndPtr(pWnd);
2727 *ppWnd = NULL;
2729 else count = 0;
2730 } else list = NULL;
2732 if( pTotal ) *pTotal = count;
2733 return list;
2735 /*******************************************************************
2736 * WIN_ReleaseWinArray
2738 void WIN_ReleaseWinArray(WND **wndArray)
2740 /* Future: this function will also unlock all windows associated with wndArray */
2741 HeapFree( GetProcessHeap(), 0, wndArray );
2745 /*******************************************************************
2746 * EnumWindows (USER32.@)
2748 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2750 WND **list, **ppWnd;
2752 /* We have to build a list of all windows first, to avoid */
2753 /* unpleasant side-effects, for instance if the callback */
2754 /* function changes the Z-order of the windows. */
2756 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2758 WIN_ReleaseDesktop();
2759 return FALSE;
2762 /* Now call the callback function for every window */
2764 for (ppWnd = list; *ppWnd; ppWnd++)
2766 LRESULT lpEnumFuncRetval;
2767 int iWndsLocks = 0;
2768 /* Make sure that the window still exists */
2769 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2771 /* To avoid any deadlocks, all the locks on the windows
2772 structures must be suspended before the control
2773 is passed to the application */
2774 iWndsLocks = WIN_SuspendWndsLock();
2775 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2776 WIN_RestoreWndsLock(iWndsLocks);
2778 if (!lpEnumFuncRetval) break;
2780 WIN_ReleaseWinArray(list);
2781 WIN_ReleaseDesktop();
2782 return TRUE;
2786 /**********************************************************************
2787 * WIN_EnumQueueWindows
2789 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2791 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2793 WND **list, **ppWnd;
2795 /* This function is the same as EnumWindows(), */
2796 /* except for an added check on the window's task. */
2798 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2800 WIN_ReleaseDesktop();
2801 return FALSE;
2804 /* Now call the callback function for every window */
2806 for (ppWnd = list; *ppWnd; ppWnd++)
2808 LRESULT funcRetval;
2809 int iWndsLocks = 0;
2810 /* Make sure that the window still exists */
2811 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2812 if ((*ppWnd)->hmemTaskQ != queue) continue;
2814 /* To avoid any deadlocks, all the locks on the windows
2815 structures must be suspended before the control
2816 is passed to the application */
2817 iWndsLocks = WIN_SuspendWndsLock();
2818 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2819 WIN_RestoreWndsLock(iWndsLocks);
2821 if (!funcRetval) break;
2823 WIN_ReleaseWinArray(list);
2824 WIN_ReleaseDesktop();
2825 return TRUE;
2829 /**********************************************************************
2830 * EnumTaskWindows16 (USER.225)
2832 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2833 LPARAM lParam )
2835 HQUEUE16 queue = GetTaskQueue16( hTask );
2836 if (!queue) return FALSE;
2837 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2841 /**********************************************************************
2842 * EnumThreadWindows (USER32.@)
2844 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2846 HQUEUE16 queue = GetThreadQueue16( id );
2847 if (!queue) return FALSE;
2848 return WIN_EnumQueueWindows( queue, func, lParam );
2852 /**********************************************************************
2853 * WIN_EnumChildWindows
2855 * Helper function for EnumChildWindows().
2857 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2859 WND **childList;
2860 BOOL16 ret = FALSE;
2862 for ( ; *ppWnd; ppWnd++)
2864 int iWndsLocks = 0;
2866 /* Make sure that the window still exists */
2867 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2868 /* Build children list first */
2869 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2871 /* To avoid any deadlocks, all the locks on the windows
2872 structures must be suspended before the control
2873 is passed to the application */
2874 iWndsLocks = WIN_SuspendWndsLock();
2875 ret = func( (*ppWnd)->hwndSelf, lParam );
2876 WIN_RestoreWndsLock(iWndsLocks);
2878 if (childList)
2880 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2881 WIN_ReleaseWinArray(childList);
2883 if (!ret) return FALSE;
2885 return TRUE;
2889 /**********************************************************************
2890 * EnumChildWindows (USER32.@)
2892 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2893 LPARAM lParam )
2895 WND **list, *pParent;
2897 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2898 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2900 WIN_ReleaseWndPtr(pParent);
2901 return FALSE;
2903 WIN_EnumChildWindows( list, func, lParam );
2904 WIN_ReleaseWinArray(list);
2905 WIN_ReleaseWndPtr(pParent);
2906 return TRUE;
2910 /*******************************************************************
2911 * AnyPopup (USER.52)
2913 BOOL16 WINAPI AnyPopup16(void)
2915 return AnyPopup();
2919 /*******************************************************************
2920 * AnyPopup (USER32.@)
2922 BOOL WINAPI AnyPopup(void)
2924 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2925 BOOL retvalue;
2927 while (wndPtr)
2929 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2931 retvalue = TRUE;
2932 goto end;
2934 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2936 retvalue = FALSE;
2937 end:
2938 WIN_ReleaseWndPtr(wndPtr);
2939 return retvalue;
2943 /*******************************************************************
2944 * FlashWindow (USER.105)
2946 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2948 return FlashWindow( hWnd, bInvert );
2952 /*******************************************************************
2953 * FlashWindow (USER32.@)
2955 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2957 WND *wndPtr = WIN_FindWndPtr(hWnd);
2959 TRACE("%04x\n", hWnd);
2961 if (!wndPtr) return FALSE;
2963 if (wndPtr->dwStyle & WS_MINIMIZE)
2965 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2967 HDC hDC = GetDC(hWnd);
2969 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2970 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2972 ReleaseDC( hWnd, hDC );
2973 wndPtr->flags |= WIN_NCACTIVATED;
2975 else
2977 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2978 wndPtr->flags &= ~WIN_NCACTIVATED;
2980 WIN_ReleaseWndPtr(wndPtr);
2981 return TRUE;
2983 else
2985 WPARAM16 wparam;
2986 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2987 else wparam = (hWnd == GetActiveWindow());
2989 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2990 WIN_ReleaseWndPtr(wndPtr);
2991 return wparam;
2996 /*******************************************************************
2997 * SetSysModalWindow (USER.188)
2999 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3001 HWND hWndOldModal = hwndSysModal;
3002 hwndSysModal = hWnd;
3003 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3004 return hWndOldModal;
3008 /*******************************************************************
3009 * GetSysModalWindow (USER.189)
3011 HWND16 WINAPI GetSysModalWindow16(void)
3013 return hwndSysModal;
3017 /*******************************************************************
3018 * GetWindowContextHelpId (USER32.@)
3020 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3022 DWORD retval;
3023 WND *wnd = WIN_FindWndPtr( hwnd );
3024 if (!wnd) return 0;
3025 retval = wnd->helpContext;
3026 WIN_ReleaseWndPtr(wnd);
3027 return retval;
3031 /*******************************************************************
3032 * SetWindowContextHelpId (USER32.@)
3034 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3036 WND *wnd = WIN_FindWndPtr( hwnd );
3037 if (!wnd) return FALSE;
3038 wnd->helpContext = id;
3039 WIN_ReleaseWndPtr(wnd);
3040 return TRUE;
3044 /*******************************************************************
3045 * DRAG_QueryUpdate
3047 * recursively find a child that contains spDragInfo->pt point
3048 * and send WM_QUERYDROPOBJECT
3050 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3052 BOOL16 wParam, bResult = 0;
3053 POINT pt;
3054 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3055 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3056 RECT tempRect;
3058 if( !ptrQueryWnd || !ptrDragInfo )
3059 goto end;
3061 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3063 GetWindowRect(hQueryWnd,&tempRect);
3065 if( !PtInRect(&tempRect,pt) ||
3066 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3067 goto end;
3069 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3071 tempRect = ptrQueryWnd->rectClient;
3072 if(ptrQueryWnd->parent)
3073 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3074 (LPPOINT)&tempRect, 2 );
3076 if (PtInRect( &tempRect, pt))
3078 wParam = 0;
3080 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3082 if( ptrWnd->dwStyle & WS_VISIBLE )
3084 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3085 if (PtInRect( &tempRect, pt )) break;
3089 if(ptrWnd)
3091 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3092 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3093 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3094 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3095 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3097 WIN_ReleaseWndPtr(ptrWnd);
3100 if(bResult)
3101 goto end;
3103 else wParam = 1;
3105 else wParam = 1;
3107 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3109 ptrDragInfo->hScope = hQueryWnd;
3111 bResult = ( bNoSend )
3112 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3113 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3114 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3115 if( !bResult )
3116 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3118 end:
3119 WIN_ReleaseWndPtr(ptrQueryWnd);
3120 return bResult;
3124 /*******************************************************************
3125 * DragDetect (USER.465)
3127 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3129 POINT pt32;
3130 CONV_POINT16TO32( &pt, &pt32 );
3131 return DragDetect( hWnd, pt32 );
3134 /*******************************************************************
3135 * DragDetect (USER32.@)
3137 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3139 MSG msg;
3140 RECT rect;
3142 rect.left = pt.x - wDragWidth;
3143 rect.right = pt.x + wDragWidth;
3145 rect.top = pt.y - wDragHeight;
3146 rect.bottom = pt.y + wDragHeight;
3148 SetCapture(hWnd);
3150 while(1)
3152 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3154 if( msg.message == WM_LBUTTONUP )
3156 ReleaseCapture();
3157 return 0;
3159 if( msg.message == WM_MOUSEMOVE )
3161 POINT tmp;
3162 tmp.x = LOWORD(msg.lParam);
3163 tmp.y = HIWORD(msg.lParam);
3164 if( !PtInRect( &rect, tmp ))
3166 ReleaseCapture();
3167 return 1;
3171 WaitMessage();
3173 return 0;
3176 /******************************************************************************
3177 * DragObject (USER.464)
3179 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3180 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3182 MSG msg;
3183 LPDRAGINFO16 lpDragInfo;
3184 SEGPTR spDragInfo;
3185 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3186 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3187 WND *wndPtr = WIN_FindWndPtr(hWnd);
3188 HCURSOR16 hCurrentCursor = 0;
3189 HWND16 hCurrentWnd = 0;
3191 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3192 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3194 if( !lpDragInfo || !spDragInfo )
3196 WIN_ReleaseWndPtr(wndPtr);
3197 return 0L;
3200 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3202 if( !hBummer || !wndPtr )
3204 GlobalFree16(hDragInfo);
3205 WIN_ReleaseWndPtr(wndPtr);
3206 return 0L;
3209 if(hCursor)
3211 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3213 GlobalFree16(hDragInfo);
3214 WIN_ReleaseWndPtr(wndPtr);
3215 return 0L;
3218 if( hDragCursor == hCursor ) hDragCursor = 0;
3219 else hCursor = hDragCursor;
3221 hOldCursor = SetCursor(hDragCursor);
3224 lpDragInfo->hWnd = hWnd;
3225 lpDragInfo->hScope = 0;
3226 lpDragInfo->wFlags = wObj;
3227 lpDragInfo->hList = szList; /* near pointer! */
3228 lpDragInfo->hOfStruct = hOfStruct;
3229 lpDragInfo->l = 0L;
3231 SetCapture(hWnd);
3232 ShowCursor( TRUE );
3236 do{ WaitMessage(); }
3237 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3239 *(lpDragInfo+1) = *lpDragInfo;
3241 lpDragInfo->pt.x = msg.pt.x;
3242 lpDragInfo->pt.y = msg.pt.y;
3244 /* update DRAGINFO struct */
3245 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3247 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3248 hCurrentCursor = hCursor;
3249 else
3251 hCurrentCursor = hBummer;
3252 lpDragInfo->hScope = 0;
3254 if( hCurrentCursor )
3255 SetCursor(hCurrentCursor);
3257 /* send WM_DRAGLOOP */
3258 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3259 (LPARAM) spDragInfo );
3260 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3261 if( hCurrentWnd != lpDragInfo->hScope )
3263 if( hCurrentWnd )
3264 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3265 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3266 HIWORD(spDragInfo)) );
3267 hCurrentWnd = lpDragInfo->hScope;
3268 if( hCurrentWnd )
3269 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3271 else
3272 if( hCurrentWnd )
3273 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3275 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3277 ReleaseCapture();
3278 ShowCursor( FALSE );
3280 if( hCursor )
3282 SetCursor( hOldCursor );
3283 if (hDragCursor) DestroyCursor( hDragCursor );
3286 if( hCurrentCursor != hBummer )
3287 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3288 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3289 else
3290 msg.lParam = 0;
3291 GlobalFree16(hDragInfo);
3292 WIN_ReleaseWndPtr(wndPtr);
3294 return (DWORD)(msg.lParam);
3298 /******************************************************************************
3299 * GetWindowModuleFileNameA (USER32.@)
3301 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3303 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3304 hwnd, lpszFileName, cchFileNameMax);
3305 return 0;
3308 /******************************************************************************
3309 * GetWindowModuleFileNameW (USER32.@)
3311 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3313 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3314 hwnd, lpszFileName, cchFileNameMax);
3315 return 0;