Removed some direct accesses to GDI internal pen/brush/font
[wine/dcerpc.git] / windows / win.c
blob9d38ce134a6e58099c3e6965769b22fa99080dab
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 /* Correct the window style - stage 1
714 * These are patches that appear to affect both the style loaded into the
715 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
717 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
718 * why does the user get to set it?
721 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
722 * tested for WS_POPUP
724 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
725 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
726 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
727 cs->dwExStyle |= WS_EX_WINDOWEDGE;
728 else
729 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
731 /* Create the window structure */
733 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
735 TRACE("out of memory\n" );
736 return 0;
739 /* Fill the window structure */
741 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
742 wndPtr->next = NULL;
743 wndPtr->child = NULL;
745 if ((cs->style & WS_CHILD) && cs->hwndParent)
747 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
748 wndPtr->owner = NULL;
749 WIN_ReleaseWndPtr(wndPtr->parent);
751 else
753 wndPtr->parent = pWndDesktop;
754 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
755 wndPtr->owner = NULL;
756 else
758 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
759 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
760 WIN_ReleaseWndPtr(wndPtr->owner);
761 WIN_ReleaseWndPtr(tmpWnd);
766 wndPtr->class = classPtr;
767 wndPtr->winproc = winproc;
768 wndPtr->dwMagic = WND_MAGIC;
769 wndPtr->hwndSelf = hwnd;
770 wndPtr->hInstance = cs->hInstance;
771 wndPtr->text = NULL;
772 wndPtr->hmemTaskQ = GetFastQueue16();
773 wndPtr->hrgnUpdate = 0;
774 wndPtr->hrgnWnd = 0;
775 wndPtr->hwndLastActive = hwnd;
776 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
777 wndPtr->dwExStyle = cs->dwExStyle;
778 wndPtr->clsStyle = clsStyle;
779 wndPtr->wIDmenu = 0;
780 wndPtr->helpContext = 0;
781 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
782 wndPtr->pVScroll = NULL;
783 wndPtr->pHScroll = NULL;
784 wndPtr->pProp = NULL;
785 wndPtr->userdata = 0;
786 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
787 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
788 wndPtr->cbWndExtra = wndExtra;
789 wndPtr->irefCount = 1;
791 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
793 /* Call the WH_CBT hook */
795 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
796 ? HWND_BOTTOM : HWND_TOP;
798 if (HOOK_IsHooked( WH_CBT ))
800 CBT_CREATEWNDA cbtc;
801 LRESULT ret;
803 cbtc.lpcs = cs;
804 cbtc.hwndInsertAfter = hwndLinkAfter;
805 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
806 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
807 if (ret)
809 TRACE("CBT-hook returned 0\n");
810 USER_HEAP_FREE( hwnd );
811 CLASS_RemoveWindow( classPtr );
812 hwnd = 0;
813 goto end;
817 /* Correct the window style - stage 2 */
819 if (!(cs->style & WS_CHILD))
821 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
822 if (!(cs->style & WS_POPUP))
824 wndPtr->dwStyle |= WS_CAPTION;
825 wndPtr->flags |= WIN_NEED_SIZE;
829 /* Get class or window DC if needed */
831 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
832 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
833 else wndPtr->dce = NULL;
835 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
837 wndPtr->rectWindow.left = cs->x;
838 wndPtr->rectWindow.top = cs->y;
839 wndPtr->rectWindow.right = cs->x + cs->cx;
840 wndPtr->rectWindow.bottom = cs->y + cs->cy;
841 wndPtr->rectClient = wndPtr->rectWindow;
843 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
845 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
847 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
848 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
849 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
850 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
851 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
854 if (cs->cx < 0) cs->cx = 0;
855 if (cs->cy < 0) cs->cy = 0;
857 wndPtr->rectWindow.left = cs->x;
858 wndPtr->rectWindow.top = cs->y;
859 wndPtr->rectWindow.right = cs->x + cs->cx;
860 wndPtr->rectWindow.bottom = cs->y + cs->cy;
861 wndPtr->rectClient = wndPtr->rectWindow;
863 /* Set the window menu */
865 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
867 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
868 else
870 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
871 if (menuName)
873 if (HIWORD(cs->hInstance))
874 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
875 else
876 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
878 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
882 else wndPtr->wIDmenu = (UINT)cs->hMenu;
884 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
886 WARN("aborted by WM_xxCREATE!\n");
887 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
888 CLASS_RemoveWindow( classPtr );
889 WIN_ReleaseWndPtr(wndPtr);
890 return 0;
893 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
895 /* Notify the parent window only */
897 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
898 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
899 if( !IsWindow(hwnd) )
901 hwnd = 0;
902 goto end;
906 if (cs->style & WS_VISIBLE)
908 /* in case WS_VISIBLE got set in the meantime */
909 wndPtr->dwStyle &= ~WS_VISIBLE;
910 ShowWindow( hwnd, sw );
913 /* Call WH_SHELL hook */
915 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
916 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
918 TRACE("created window %04x\n", hwnd);
919 end:
920 WIN_ReleaseWndPtr(wndPtr);
921 return hwnd;
925 /***********************************************************************
926 * CreateWindow (USER.41)
928 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
929 DWORD style, INT16 x, INT16 y, INT16 width,
930 INT16 height, HWND16 parent, HMENU16 menu,
931 HINSTANCE16 instance, LPVOID data )
933 return CreateWindowEx16( 0, className, windowName, style,
934 x, y, width, height, parent, menu, instance, data );
938 /***********************************************************************
939 * CreateWindowEx (USER.452)
941 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
942 LPCSTR windowName, DWORD style, INT16 x,
943 INT16 y, INT16 width, INT16 height,
944 HWND16 parent, HMENU16 menu,
945 HINSTANCE16 instance, LPVOID data )
947 ATOM classAtom;
948 CREATESTRUCTA cs;
949 char buffer[256];
951 /* Find the class atom */
953 if (HIWORD(className))
955 if (!(classAtom = GlobalFindAtomA( className )))
957 ERR( "bad class name %s\n", debugres_a(className) );
958 return 0;
961 else
963 classAtom = LOWORD(className);
964 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
966 ERR( "bad atom %x\n", classAtom);
967 return 0;
969 className = buffer;
972 /* Fix the coordinates */
974 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
975 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
976 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
977 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
979 /* Create the window */
981 cs.lpCreateParams = data;
982 cs.hInstance = (HINSTANCE)instance;
983 cs.hMenu = (HMENU)menu;
984 cs.hwndParent = (HWND)parent;
985 cs.style = style;
986 cs.lpszName = windowName;
987 cs.lpszClass = className;
988 cs.dwExStyle = exStyle;
990 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
994 /***********************************************************************
995 * CreateWindowExA (USER32.@)
997 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
998 LPCSTR windowName, DWORD style, INT x,
999 INT y, INT width, INT height,
1000 HWND parent, HMENU menu,
1001 HINSTANCE instance, LPVOID data )
1003 ATOM classAtom;
1004 CREATESTRUCTA cs;
1005 char buffer[256];
1007 if(!instance)
1008 instance=GetModuleHandleA(NULL);
1010 if(exStyle & WS_EX_MDICHILD)
1011 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1013 /* Find the class atom */
1015 if (HIWORD(className))
1017 if (!(classAtom = GlobalFindAtomA( className )))
1019 ERR( "bad class name %s\n", debugres_a(className) );
1020 return 0;
1023 else
1025 classAtom = LOWORD(className);
1026 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1028 ERR( "bad atom %x\n", classAtom);
1029 return 0;
1031 className = buffer;
1034 /* Create the window */
1036 cs.lpCreateParams = data;
1037 cs.hInstance = instance;
1038 cs.hMenu = menu;
1039 cs.hwndParent = parent;
1040 cs.x = x;
1041 cs.y = y;
1042 cs.cx = width;
1043 cs.cy = height;
1044 cs.style = style;
1045 cs.lpszName = windowName;
1046 cs.lpszClass = className;
1047 cs.dwExStyle = exStyle;
1049 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1053 /***********************************************************************
1054 * CreateWindowExW (USER32.@)
1056 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1057 LPCWSTR windowName, DWORD style, INT x,
1058 INT y, INT width, INT height,
1059 HWND parent, HMENU menu,
1060 HINSTANCE instance, LPVOID data )
1062 ATOM classAtom;
1063 CREATESTRUCTW cs;
1064 WCHAR buffer[256];
1066 if(!instance)
1067 instance=GetModuleHandleA(NULL);
1069 if(exStyle & WS_EX_MDICHILD)
1070 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1072 /* Find the class atom */
1074 if (HIWORD(className))
1076 if (!(classAtom = GlobalFindAtomW( className )))
1078 ERR( "bad class name %s\n", debugres_w(className) );
1079 return 0;
1082 else
1084 classAtom = LOWORD(className);
1085 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1087 ERR( "bad atom %x\n", classAtom);
1088 return 0;
1090 className = buffer;
1093 /* Create the window */
1095 cs.lpCreateParams = data;
1096 cs.hInstance = instance;
1097 cs.hMenu = menu;
1098 cs.hwndParent = parent;
1099 cs.x = x;
1100 cs.y = y;
1101 cs.cx = width;
1102 cs.cy = height;
1103 cs.style = style;
1104 cs.lpszName = windowName;
1105 cs.lpszClass = className;
1106 cs.dwExStyle = exStyle;
1108 /* Note: we rely on the fact that CREATESTRUCTA and */
1109 /* CREATESTRUCTW have the same layout. */
1110 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1113 /***********************************************************************
1114 * WIN_SendDestroyMsg
1116 static void WIN_SendDestroyMsg( WND* pWnd )
1118 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1119 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1122 * Send the WM_DESTROY to the window.
1124 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1127 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1128 * make sure that the window still exists when we come back.
1130 if (IsWindow(pWnd->hwndSelf))
1132 HWND* pWndArray = NULL;
1133 WND* pChild = NULL;
1134 int nKidCount = 0;
1137 * Now, if the window has kids, we have to send WM_DESTROY messages
1138 * recursively to it's kids. It seems that those calls can also
1139 * trigger re-entrant calls to DestroyWindow for the kids so we must
1140 * protect against corruption of the list of siblings. We first build
1141 * a list of HWNDs representing all the kids.
1143 pChild = WIN_LockWndPtr(pWnd->child);
1144 while( pChild )
1146 nKidCount++;
1147 WIN_UpdateWndPtr(&pChild,pChild->next);
1151 * If there are no kids, we're done.
1153 if (nKidCount==0)
1154 return;
1156 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1159 * Sanity check
1161 if (pWndArray==NULL)
1162 return;
1165 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1166 * call, our linked list of siblings should be safe.
1168 nKidCount = 0;
1169 pChild = WIN_LockWndPtr(pWnd->child);
1170 while( pChild )
1172 pWndArray[nKidCount] = pChild->hwndSelf;
1173 nKidCount++;
1174 WIN_UpdateWndPtr(&pChild,pChild->next);
1178 * Now that we have a list, go through that list again and send the destroy
1179 * message to those windows. We are using the HWND to retrieve the
1180 * WND pointer so we are effectively checking that all the kid windows are
1181 * still valid before sending the message.
1183 while (nKidCount>0)
1185 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1187 if (pChild!=NULL)
1189 WIN_SendDestroyMsg( pChild );
1190 WIN_ReleaseWndPtr(pChild);
1195 * Cleanup
1197 HeapFree(GetProcessHeap(), 0, pWndArray);
1199 else
1200 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1204 /***********************************************************************
1205 * DestroyWindow (USER.53)
1207 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1209 return DestroyWindow(hwnd);
1213 /***********************************************************************
1214 * DestroyWindow (USER32.@)
1216 BOOL WINAPI DestroyWindow( HWND hwnd )
1218 WND * wndPtr;
1219 BOOL retvalue;
1220 HWND h;
1221 BOOL bFocusSet = FALSE;
1223 TRACE("(%04x)\n", hwnd);
1225 /* Initialization */
1227 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1228 if (wndPtr == pWndDesktop)
1230 retvalue = FALSE; /* Can't destroy desktop */
1231 goto end;
1234 /* Look whether the focus is within the tree of windows we will
1235 * be destroying.
1237 h = GetFocus16();
1238 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1240 if (h == hwnd)
1242 SetFocus(GetParent(h));
1243 bFocusSet = TRUE;
1244 break;
1246 h = GetParent(h);
1248 /* If the focus is on the window we will destroy and it has no parent,
1249 * set the focus to 0.
1251 if (! bFocusSet && (h == hwnd))
1253 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1254 SetFocus(0);
1257 /* Call hooks */
1259 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1261 retvalue = FALSE;
1262 goto end;
1265 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1267 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1268 /* FIXME: clean up palette - see "Internals" p.352 */
1271 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1272 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1274 /* Notify the parent window only */
1275 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1276 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1277 if( !IsWindow(hwnd) )
1279 retvalue = TRUE;
1280 goto end;
1284 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1286 /* Hide the window */
1288 if (wndPtr->dwStyle & WS_VISIBLE)
1290 ShowWindow( hwnd, SW_HIDE );
1291 if (!IsWindow(hwnd))
1293 retvalue = TRUE;
1294 goto end;
1298 /* Recursively destroy owned windows */
1300 if( !(wndPtr->dwStyle & WS_CHILD) )
1302 for (;;)
1304 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1305 while (siblingPtr)
1307 if (siblingPtr->owner == wndPtr)
1309 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1310 break;
1311 else
1312 siblingPtr->owner = NULL;
1314 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1316 if (siblingPtr)
1318 DestroyWindow( siblingPtr->hwndSelf );
1319 WIN_ReleaseWndPtr(siblingPtr);
1321 else break;
1324 WINPOS_ActivateOtherWindow(wndPtr);
1326 if( wndPtr->owner &&
1327 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1328 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1331 /* Send destroy messages */
1333 WIN_SendDestroyMsg( wndPtr );
1334 if (!IsWindow(hwnd))
1336 retvalue = TRUE;
1337 goto end;
1340 /* Unlink now so we won't bother with the children later on */
1342 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1344 /* Destroy the window storage */
1346 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1347 retvalue = TRUE;
1348 end:
1349 WIN_ReleaseWndPtr(wndPtr);
1350 return retvalue;
1354 /***********************************************************************
1355 * CloseWindow (USER.43)
1357 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1359 return CloseWindow( hwnd );
1363 /***********************************************************************
1364 * CloseWindow (USER32.@)
1366 BOOL WINAPI CloseWindow( HWND hwnd )
1368 WND * wndPtr = WIN_FindWndPtr( hwnd );
1369 BOOL retvalue;
1371 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1373 retvalue = FALSE;
1374 goto end;
1376 ShowWindow( hwnd, SW_MINIMIZE );
1377 retvalue = TRUE;
1378 end:
1379 WIN_ReleaseWndPtr(wndPtr);
1380 return retvalue;
1385 /***********************************************************************
1386 * OpenIcon (USER.44)
1388 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1390 return OpenIcon( hwnd );
1394 /***********************************************************************
1395 * OpenIcon (USER32.@)
1397 BOOL WINAPI OpenIcon( HWND hwnd )
1399 if (!IsIconic( hwnd )) return FALSE;
1400 ShowWindow( hwnd, SW_SHOWNORMAL );
1401 return TRUE;
1405 /***********************************************************************
1406 * WIN_FindWindow
1408 * Implementation of FindWindow() and FindWindowEx().
1410 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1411 LPCWSTR title )
1413 WND *pWnd;
1414 HWND retvalue;
1416 if (child)
1418 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1419 if (parent)
1421 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1423 retvalue = 0;
1424 goto end;
1427 else if (pWnd->parent != pWndDesktop)
1429 retvalue = 0;
1430 goto end;
1432 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1434 else
1436 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1438 retvalue = 0;
1439 goto end;
1441 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1443 if (!pWnd)
1445 retvalue = 0;
1446 goto end;
1449 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1451 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1452 continue; /* Not the right class */
1454 /* Now check the title */
1456 if (!title)
1458 retvalue = pWnd->hwndSelf;
1459 goto end;
1461 if (pWnd->text && !strcmpW( pWnd->text, title ))
1463 retvalue = pWnd->hwndSelf;
1464 goto end;
1467 retvalue = 0;
1468 /* In this case we need to check whether other processes
1469 own a window with the given paramters on the Desktop,
1470 but we don't, so let's at least warn about it */
1471 FIXME("Returning 0 without checking other processes\n");
1472 end:
1473 WIN_ReleaseWndPtr(pWnd);
1474 return retvalue;
1479 /***********************************************************************
1480 * FindWindow (USER.50)
1482 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1484 return FindWindowA( className, title );
1488 /***********************************************************************
1489 * FindWindowEx (USER.427)
1491 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1493 return FindWindowExA( parent, child, className, title );
1497 /***********************************************************************
1498 * FindWindowA (USER32.@)
1500 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1502 HWND ret = FindWindowExA( 0, 0, className, title );
1503 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1504 return ret;
1508 /***********************************************************************
1509 * FindWindowExA (USER32.@)
1511 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1512 LPCSTR className, LPCSTR title )
1514 ATOM atom = 0;
1515 LPWSTR buffer;
1516 HWND hwnd;
1518 if (className)
1520 /* If the atom doesn't exist, then no class */
1521 /* with this name exists either. */
1522 if (!(atom = GlobalFindAtomA( className )))
1524 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1525 return 0;
1529 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1530 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1531 HeapFree( GetProcessHeap(), 0, buffer );
1532 return hwnd;
1536 /***********************************************************************
1537 * FindWindowExW (USER32.@)
1539 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1540 LPCWSTR className, LPCWSTR title )
1542 ATOM atom = 0;
1544 if (className)
1546 /* If the atom doesn't exist, then no class */
1547 /* with this name exists either. */
1548 if (!(atom = GlobalFindAtomW( className )))
1550 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1551 return 0;
1554 return WIN_FindWindow( parent, child, atom, title );
1558 /***********************************************************************
1559 * FindWindowW (USER32.@)
1561 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1563 return FindWindowExW( 0, 0, className, title );
1567 /**********************************************************************
1568 * WIN_GetDesktop
1569 * returns a locked pointer
1571 WND *WIN_GetDesktop(void)
1573 return WIN_LockWndPtr(pWndDesktop);
1575 /**********************************************************************
1576 * WIN_ReleaseDesktop
1577 * unlock the desktop pointer
1579 void WIN_ReleaseDesktop(void)
1581 WIN_ReleaseWndPtr(pWndDesktop);
1585 /**********************************************************************
1586 * GetDesktopWindow (USER.286)
1588 HWND16 WINAPI GetDesktopWindow16(void)
1590 return (HWND16)pWndDesktop->hwndSelf;
1594 /**********************************************************************
1595 * GetDesktopWindow (USER32.@)
1597 HWND WINAPI GetDesktopWindow(void)
1599 if (pWndDesktop) return pWndDesktop->hwndSelf;
1600 ERR( "You need the -desktop option when running with native USER\n" );
1601 ExitProcess(1);
1602 return 0;
1606 /**********************************************************************
1607 * GetDesktopHwnd (USER.278)
1609 * Exactly the same thing as GetDesktopWindow(), but not documented.
1610 * Don't ask me why...
1612 HWND16 WINAPI GetDesktopHwnd16(void)
1614 return (HWND16)pWndDesktop->hwndSelf;
1618 /*******************************************************************
1619 * EnableWindow (USER.34)
1621 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1623 return EnableWindow( hwnd, enable );
1627 /*******************************************************************
1628 * EnableWindow (USER32.@)
1630 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1632 WND *wndPtr;
1633 BOOL retvalue;
1635 TRACE("( %x, %d )\n", hwnd, enable);
1637 if (USER_Driver.pEnableWindow)
1638 return USER_Driver.pEnableWindow( hwnd, enable );
1640 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1642 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1644 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1646 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1647 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1649 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1651 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1653 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1655 if (hwnd == GetFocus())
1656 SetFocus( 0 ); /* A disabled window can't have the focus */
1658 if (hwnd == GetCapture())
1659 ReleaseCapture(); /* A disabled window can't capture the mouse */
1661 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1663 WIN_ReleaseWndPtr(wndPtr);
1664 return retvalue;
1668 /***********************************************************************
1669 * IsWindowEnabled (USER.35)
1671 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1673 return IsWindowEnabled(hWnd);
1677 /***********************************************************************
1678 * IsWindowEnabled (USER32.@)
1680 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1682 WND * wndPtr;
1683 BOOL retvalue;
1685 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1686 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1687 WIN_ReleaseWndPtr(wndPtr);
1688 return retvalue;
1693 /***********************************************************************
1694 * IsWindowUnicode (USER32.@)
1696 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1698 WND * wndPtr;
1699 BOOL retvalue;
1701 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1702 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1703 WIN_ReleaseWndPtr(wndPtr);
1704 return retvalue;
1708 /**********************************************************************
1709 * GetWindowWord (USER.133)
1711 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1713 return GetWindowWord( hwnd, offset );
1717 /**********************************************************************
1718 * GetWindowWord (USER32.@)
1720 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1722 WORD retvalue;
1723 WND * wndPtr = WIN_FindWndPtr( hwnd );
1724 if (!wndPtr) return 0;
1725 if (offset >= 0)
1727 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1729 WARN("Invalid offset %d\n", offset );
1730 retvalue = 0;
1731 goto end;
1733 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1734 goto end;
1736 switch(offset)
1738 case GWW_ID:
1739 if (HIWORD(wndPtr->wIDmenu))
1740 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1741 wndPtr->wIDmenu);
1742 retvalue = (WORD)wndPtr->wIDmenu;
1743 goto end;
1744 case GWW_HWNDPARENT:
1745 retvalue = GetParent(hwnd);
1746 goto end;
1747 case GWW_HINSTANCE:
1748 if (HIWORD(wndPtr->hInstance))
1749 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1750 wndPtr->hInstance);
1751 retvalue = (WORD)wndPtr->hInstance;
1752 goto end;
1753 default:
1754 WARN("Invalid offset %d\n", offset );
1755 retvalue = 0;
1756 goto end;
1758 end:
1759 WIN_ReleaseWndPtr(wndPtr);
1760 return retvalue;
1763 /**********************************************************************
1764 * SetWindowWord (USER.134)
1766 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1768 return SetWindowWord( hwnd, offset, newval );
1772 /**********************************************************************
1773 * SetWindowWord (USER32.@)
1775 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1777 WORD *ptr, retval;
1778 WND * wndPtr = WIN_FindWndPtr( hwnd );
1779 if (!wndPtr) return 0;
1780 if (offset >= 0)
1782 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1784 WARN("Invalid offset %d\n", offset );
1785 retval = 0;
1786 goto end;
1788 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1790 else switch(offset)
1792 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1793 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1794 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1795 goto end;
1796 default:
1797 WARN("Invalid offset %d\n", offset );
1798 retval = 0;
1799 goto end;
1801 retval = *ptr;
1802 *ptr = newval;
1803 end:
1804 WIN_ReleaseWndPtr(wndPtr);
1805 return retval;
1809 /**********************************************************************
1810 * WIN_GetWindowLong
1812 * Helper function for GetWindowLong().
1814 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1816 LONG retvalue;
1817 WND * wndPtr = WIN_FindWndPtr( hwnd );
1818 if (!wndPtr) return 0;
1819 if (offset >= 0)
1821 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1823 WARN("Invalid offset %d\n", offset );
1824 retvalue = 0;
1825 goto end;
1827 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1828 /* Special case for dialog window procedure */
1829 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1831 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1832 goto end;
1834 goto end;
1836 switch(offset)
1838 case GWL_USERDATA: retvalue = wndPtr->userdata;
1839 goto end;
1840 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1841 goto end;
1842 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1843 goto end;
1844 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1845 goto end;
1846 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1847 type );
1848 goto end;
1849 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1850 goto end;
1851 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1852 goto end;
1853 default:
1854 WARN("Unknown offset %d\n", offset );
1856 retvalue = 0;
1857 end:
1858 WIN_ReleaseWndPtr(wndPtr);
1859 return retvalue;
1863 /**********************************************************************
1864 * WIN_SetWindowLong
1866 * Helper function for SetWindowLong().
1868 * 0 is the failure code. However, in the case of failure SetLastError
1869 * must be set to distinguish between a 0 return value and a failure.
1871 * FIXME: The error values for SetLastError may not be right. Can
1872 * someone check with the real thing?
1874 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1875 WINDOWPROCTYPE type )
1877 LONG *ptr, retval;
1878 WND * wndPtr = WIN_FindWndPtr( hwnd );
1879 STYLESTRUCT style;
1881 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1883 if (!wndPtr)
1885 /* Is this the right error? */
1886 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1887 return 0;
1890 if (offset >= 0)
1892 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1894 WARN("Invalid offset %d\n", offset );
1896 /* Is this the right error? */
1897 SetLastError( ERROR_OUTOFMEMORY );
1899 retval = 0;
1900 goto end;
1902 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1903 /* Special case for dialog window procedure */
1904 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1906 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1907 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1908 type, WIN_PROC_WINDOW );
1909 goto end;
1912 else switch(offset)
1914 case GWL_ID:
1915 ptr = (DWORD*)&wndPtr->wIDmenu;
1916 break;
1917 case GWL_HINSTANCE:
1918 retval = SetWindowWord( hwnd, offset, newval );
1919 goto end;
1920 case GWL_WNDPROC:
1921 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1922 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1923 type, WIN_PROC_WINDOW );
1924 goto end;
1925 case GWL_STYLE:
1926 style.styleOld = wndPtr->dwStyle;
1927 style.styleNew = newval;
1928 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1929 wndPtr->dwStyle = style.styleNew;
1930 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1931 retval = style.styleOld;
1932 goto end;
1934 case GWL_USERDATA:
1935 ptr = &wndPtr->userdata;
1936 break;
1937 case GWL_EXSTYLE:
1938 style.styleOld = wndPtr->dwExStyle;
1939 style.styleNew = newval;
1940 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1941 wndPtr->dwExStyle = newval;
1942 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1943 retval = style.styleOld;
1944 goto end;
1946 default:
1947 WARN("Invalid offset %d\n", offset );
1949 /* Don't think this is right error but it should do */
1950 SetLastError( ERROR_OUTOFMEMORY );
1952 retval = 0;
1953 goto end;
1955 retval = *ptr;
1956 *ptr = newval;
1957 end:
1958 WIN_ReleaseWndPtr(wndPtr);
1959 return retval;
1963 /**********************************************************************
1964 * GetWindowLong (USER.135)
1966 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1968 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1972 /**********************************************************************
1973 * GetWindowLongA (USER32.@)
1975 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1977 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1981 /**********************************************************************
1982 * GetWindowLongW (USER32.@)
1984 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1986 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1990 /**********************************************************************
1991 * SetWindowLong (USER.136)
1993 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1995 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1999 /**********************************************************************
2000 * SetWindowLongA (USER32.@)
2002 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2004 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2008 /**********************************************************************
2009 * SetWindowLongW (USER32.@) Set window attribute
2011 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2012 * value in a window's extra memory.
2014 * The _hwnd_ parameter specifies the window. is the handle to a
2015 * window that has extra memory. The _newval_ parameter contains the
2016 * new attribute or extra memory value. If positive, the _offset_
2017 * parameter is the byte-addressed location in the window's extra
2018 * memory to set. If negative, _offset_ specifies the window
2019 * attribute to set, and should be one of the following values:
2021 * GWL_EXSTYLE The window's extended window style
2023 * GWL_STYLE The window's window style.
2025 * GWL_WNDPROC Pointer to the window's window procedure.
2027 * GWL_HINSTANCE The window's pplication instance handle.
2029 * GWL_ID The window's identifier.
2031 * GWL_USERDATA The window's user-specified data.
2033 * If the window is a dialog box, the _offset_ parameter can be one of
2034 * the following values:
2036 * DWL_DLGPROC The address of the window's dialog box procedure.
2038 * DWL_MSGRESULT The return value of a message
2039 * that the dialog box procedure processed.
2041 * DWL_USER Application specific information.
2043 * RETURNS
2045 * If successful, returns the previous value located at _offset_. Otherwise,
2046 * returns 0.
2048 * NOTES
2050 * Extra memory for a window class is specified by a nonzero cbWndExtra
2051 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2052 * time of class creation.
2054 * Using GWL_WNDPROC to set a new window procedure effectively creates
2055 * a window subclass. Use CallWindowProc() in the new windows procedure
2056 * to pass messages to the superclass's window procedure.
2058 * The user data is reserved for use by the application which created
2059 * the window.
2061 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2062 * instead, call the EnableWindow() function to change the window's
2063 * disabled state.
2065 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2066 * SetParent() instead.
2068 * Win95:
2069 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2070 * it sends WM_STYLECHANGING before changing the settings
2071 * and WM_STYLECHANGED afterwards.
2072 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2074 * BUGS
2076 * GWL_STYLE does not dispatch WM_STYLE... messages.
2078 * CONFORMANCE
2080 * ECMA-234, Win32
2083 LONG WINAPI SetWindowLongW(
2084 HWND hwnd, /* [in] window to alter */
2085 INT offset, /* [in] offset, in bytes, of location to alter */
2086 LONG newval /* [in] new value of location */
2088 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2092 /*******************************************************************
2093 * GetWindowText (USER.36)
2095 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2097 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2101 /*******************************************************************
2102 * GetWindowTextA (USER32.@)
2104 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2106 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2107 (LPARAM)lpString );
2110 /*******************************************************************
2111 * InternalGetWindowText (USER32.@)
2113 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2115 WND *win = WIN_FindWndPtr( hwnd );
2116 if (!win) return 0;
2117 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2118 else lpString[0] = 0;
2119 WIN_ReleaseWndPtr( win );
2120 return strlenW(lpString);
2124 /*******************************************************************
2125 * GetWindowTextW (USER32.@)
2127 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2129 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2130 (LPARAM)lpString );
2134 /*******************************************************************
2135 * SetWindowText (USER.37)
2137 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2139 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2143 /*******************************************************************
2144 * SetWindowText (USER32.@)
2145 * SetWindowTextA (USER32.@)
2147 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2149 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2153 /*******************************************************************
2154 * SetWindowTextW (USER32.@)
2156 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2158 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2162 /*******************************************************************
2163 * GetWindowTextLength (USER.38)
2165 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2167 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2171 /*******************************************************************
2172 * GetWindowTextLengthA (USER32.@)
2174 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2176 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2179 /*******************************************************************
2180 * GetWindowTextLengthW (USER32.@)
2182 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2184 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2188 /*******************************************************************
2189 * IsWindow (USER.47)
2191 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2193 CURRENT_STACK16->es = USER_HeapSel;
2194 return IsWindow( hwnd );
2198 /*******************************************************************
2199 * IsWindow (USER32.@)
2201 BOOL WINAPI IsWindow( HWND hwnd )
2203 WND * wndPtr;
2204 BOOL retvalue;
2206 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2207 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2208 WIN_ReleaseWndPtr(wndPtr);
2209 return retvalue;
2214 /*****************************************************************
2215 * GetParent (USER.46)
2217 HWND16 WINAPI GetParent16( HWND16 hwnd )
2219 return (HWND16)GetParent( hwnd );
2223 /*****************************************************************
2224 * GetParent (USER32.@)
2226 HWND WINAPI GetParent( HWND hwnd )
2228 WND *wndPtr;
2229 HWND retvalue = 0;
2231 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2232 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2233 goto end;
2235 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2236 if (wndPtr)
2237 retvalue = wndPtr->hwndSelf;
2239 end:
2240 WIN_ReleaseWndPtr(wndPtr);
2241 return retvalue;
2245 /*****************************************************************
2246 * WIN_GetTopParent
2248 * Get the top-level parent for a child window.
2249 * returns a locked pointer
2251 WND* WIN_GetTopParentPtr( WND* pWnd )
2253 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2255 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2257 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2259 return tmpWnd;
2262 /*****************************************************************
2263 * WIN_GetTopParent
2265 * Get the top-level parent for a child window.
2267 HWND WIN_GetTopParent( HWND hwnd )
2269 HWND retvalue;
2270 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2271 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2273 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2274 WIN_ReleaseWndPtr(tmpPtr);
2275 WIN_ReleaseWndPtr(wndPtr);
2276 return retvalue;
2280 /*****************************************************************
2281 * SetParent (USER.233)
2283 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2285 return SetParent( hwndChild, hwndNewParent );
2289 /*****************************************************************
2290 * SetParent (USER32.@)
2292 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2294 WND *wndPtr;
2295 WND *pWndParent;
2296 DWORD dwStyle;
2297 HWND retvalue;
2299 if (hwnd == GetDesktopWindow()) /* sanity check */
2301 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2302 return 0;
2305 if (USER_Driver.pSetParent)
2306 return USER_Driver.pSetParent( hwnd, parent );
2308 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2310 dwStyle = wndPtr->dwStyle;
2312 if (!parent) parent = GetDesktopWindow();
2314 if (!(pWndParent = WIN_FindWndPtr(parent)))
2316 WIN_ReleaseWndPtr( wndPtr );
2317 return 0;
2320 /* Windows hides the window first, then shows it again
2321 * including the WM_SHOWWINDOW messages and all */
2322 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2324 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2325 if (pWndParent != wndPtr->parent)
2327 WIN_UnlinkWindow(wndPtr->hwndSelf);
2328 wndPtr->parent = pWndParent;
2330 if (parent != GetDesktopWindow()) /* a child window */
2332 if( !( wndPtr->dwStyle & WS_CHILD ) )
2334 if( wndPtr->wIDmenu != 0)
2336 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2337 wndPtr->wIDmenu = 0;
2341 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2343 WIN_ReleaseWndPtr( pWndParent );
2344 WIN_ReleaseWndPtr( wndPtr );
2346 /* SetParent additionally needs to make hwnd the topmost window
2347 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2348 WM_WINDOWPOSCHANGED notification messages.
2350 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2351 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2352 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2353 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2354 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2355 return retvalue;
2359 /*******************************************************************
2360 * IsChild (USER.48)
2362 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2364 return IsChild(parent,child);
2368 /*******************************************************************
2369 * IsChild (USER32.@)
2371 BOOL WINAPI IsChild( HWND parent, HWND child )
2373 WND * wndPtr = WIN_FindWndPtr( child );
2374 while (wndPtr && wndPtr->parent)
2376 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2377 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2378 if (wndPtr->hwndSelf == parent)
2380 WIN_ReleaseWndPtr(wndPtr);
2381 return TRUE;
2384 WIN_ReleaseWndPtr(wndPtr);
2385 return FALSE;
2389 /***********************************************************************
2390 * IsWindowVisible (USER.49)
2392 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2394 return IsWindowVisible(hwnd);
2398 /***********************************************************************
2399 * IsWindowVisible (USER32.@)
2401 BOOL WINAPI IsWindowVisible( HWND hwnd )
2403 BOOL retval;
2404 WND *wndPtr = WIN_FindWndPtr( hwnd );
2405 while (wndPtr && wndPtr->parent)
2407 if (!(wndPtr->dwStyle & WS_VISIBLE))
2409 WIN_ReleaseWndPtr(wndPtr);
2410 return FALSE;
2412 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2414 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2415 WIN_ReleaseWndPtr(wndPtr);
2416 return retval;
2420 /***********************************************************************
2421 * WIN_IsWindowDrawable
2423 * hwnd is drawable when it is visible, all parents are not
2424 * minimized, and it is itself not minimized unless we are
2425 * trying to draw its default class icon.
2427 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2429 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2430 if ((wnd->dwStyle & WS_MINIMIZE) &&
2431 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2432 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2433 if( wnd->dwStyle & WS_MINIMIZE ||
2434 !(wnd->dwStyle & WS_VISIBLE) ) break;
2435 return (wnd == NULL);
2439 /*******************************************************************
2440 * GetTopWindow (USER.229)
2442 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2444 return GetTopWindow(hwnd);
2448 /*******************************************************************
2449 * GetTopWindow (USER32.@)
2451 HWND WINAPI GetTopWindow( HWND hwnd )
2453 HWND retval = 0;
2454 WND * wndPtr = (hwnd) ?
2455 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2457 if (wndPtr && wndPtr->child)
2458 retval = wndPtr->child->hwndSelf;
2460 WIN_ReleaseWndPtr(wndPtr);
2461 return retval;
2465 /*******************************************************************
2466 * GetWindow (USER.262)
2468 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2470 return GetWindow( hwnd,rel );
2474 /*******************************************************************
2475 * GetWindow (USER32.@)
2477 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2479 HWND retval;
2481 WND * wndPtr = WIN_FindWndPtr( hwnd );
2482 if (!wndPtr) return 0;
2483 switch(rel)
2485 case GW_HWNDFIRST:
2486 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2487 goto end;
2489 case GW_HWNDLAST:
2490 if (!wndPtr->parent)
2492 retval = 0; /* Desktop window */
2493 goto end;
2495 while (wndPtr->next)
2497 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2499 retval = wndPtr->hwndSelf;
2500 goto end;
2502 case GW_HWNDNEXT:
2503 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2504 goto end;
2506 case GW_HWNDPREV:
2507 if (!wndPtr->parent)
2509 retval = 0; /* Desktop window */
2510 goto end;
2512 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2513 if (wndPtr->hwndSelf == hwnd)
2515 retval = 0; /* First in list */
2516 goto end;
2518 while (wndPtr->next)
2520 if (wndPtr->next->hwndSelf == hwnd)
2522 retval = wndPtr->hwndSelf;
2523 goto end;
2525 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2527 retval = 0;
2528 goto end;
2530 case GW_OWNER:
2531 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2532 goto end;
2534 case GW_CHILD:
2535 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2536 goto end;
2538 retval = 0;
2539 end:
2540 WIN_ReleaseWndPtr(wndPtr);
2541 return retval;
2545 /*******************************************************************
2546 * GetNextWindow (USER.230)
2548 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2550 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2551 return GetWindow16( hwnd, flag );
2554 /***********************************************************************
2555 * WIN_InternalShowOwnedPopups
2557 * Internal version of ShowOwnedPopups; Wine functions should use this
2558 * to avoid interfering with application calls to ShowOwnedPopups
2559 * and to make sure the application can't prevent showing/hiding.
2561 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2565 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2567 INT totalChild=0, count=0;
2569 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2571 if (!pWnd) return TRUE;
2574 * Show windows Lowest first, Highest last to preserve Z-Order
2576 for (count = totalChild-1 ; count >=0; count--)
2578 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2580 if (fShow)
2582 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2583 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2586 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2588 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2589 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2592 else
2594 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2595 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2596 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2599 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2601 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2602 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2603 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2608 WIN_ReleaseDesktop();
2609 WIN_ReleaseWinArray(pWnd);
2611 return TRUE;
2614 /*******************************************************************
2615 * ShowOwnedPopups (USER.265)
2617 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2619 ShowOwnedPopups( owner, fShow );
2623 /*******************************************************************
2624 * ShowOwnedPopups (USER32.@)
2626 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2628 UINT totalChild=0, count=0;
2630 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2632 if (!pWnd) return TRUE;
2634 for (; count < totalChild; count++)
2636 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2638 if (fShow)
2640 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2643 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2644 * regardless of the state of the owner
2646 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2647 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2650 else
2652 if (IsWindowVisible(pWnd[count]->hwndSelf))
2655 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2656 * regardless of the state of the owner
2658 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2659 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2665 WIN_ReleaseDesktop();
2666 WIN_ReleaseWinArray(pWnd);
2667 return TRUE;
2671 /*******************************************************************
2672 * GetLastActivePopup (USER.287)
2674 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2676 return GetLastActivePopup( hwnd );
2679 /*******************************************************************
2680 * GetLastActivePopup (USER32.@)
2682 HWND WINAPI GetLastActivePopup( HWND hwnd )
2684 HWND retval;
2685 WND *wndPtr =WIN_FindWndPtr(hwnd);
2686 if (!wndPtr) return hwnd;
2687 retval = wndPtr->hwndLastActive;
2688 WIN_ReleaseWndPtr(wndPtr);
2689 if ((retval != hwnd) && (!IsWindow(retval)))
2690 retval = hwnd;
2691 return retval;
2695 /*******************************************************************
2696 * WIN_BuildWinArray
2698 * Build an array of pointers to the children of a given window.
2699 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2700 * when no windows are found.
2702 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2704 /* Future: this function will lock all windows associated with this array */
2706 WND **list, **ppWnd;
2707 WND *pWnd;
2708 UINT count = 0, skipOwned, skipHidden;
2709 DWORD skipFlags;
2711 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2712 skipOwned = bwaFlags & BWA_SKIPOWNED;
2713 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2714 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2716 /* First count the windows */
2718 if (!wndPtr)
2719 wndPtr = WIN_GetDesktop();
2721 pWnd = WIN_LockWndPtr(wndPtr->child);
2722 while (pWnd)
2724 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2725 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2726 count++;
2727 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2730 if( count )
2732 /* Now build the list of all windows */
2734 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2736 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2738 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2739 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2741 *ppWnd++ = pWnd;
2742 count++;
2745 WIN_ReleaseWndPtr(pWnd);
2746 *ppWnd = NULL;
2748 else count = 0;
2749 } else list = NULL;
2751 if( pTotal ) *pTotal = count;
2752 return list;
2754 /*******************************************************************
2755 * WIN_ReleaseWinArray
2757 void WIN_ReleaseWinArray(WND **wndArray)
2759 /* Future: this function will also unlock all windows associated with wndArray */
2760 HeapFree( GetProcessHeap(), 0, wndArray );
2764 /*******************************************************************
2765 * EnumWindows (USER32.@)
2767 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2769 WND **list, **ppWnd;
2771 /* We have to build a list of all windows first, to avoid */
2772 /* unpleasant side-effects, for instance if the callback */
2773 /* function changes the Z-order of the windows. */
2775 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2777 WIN_ReleaseDesktop();
2778 return FALSE;
2781 /* Now call the callback function for every window */
2783 for (ppWnd = list; *ppWnd; ppWnd++)
2785 LRESULT lpEnumFuncRetval;
2786 int iWndsLocks = 0;
2787 /* Make sure that the window still exists */
2788 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2790 /* To avoid any deadlocks, all the locks on the windows
2791 structures must be suspended before the control
2792 is passed to the application */
2793 iWndsLocks = WIN_SuspendWndsLock();
2794 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2795 WIN_RestoreWndsLock(iWndsLocks);
2797 if (!lpEnumFuncRetval) break;
2799 WIN_ReleaseWinArray(list);
2800 WIN_ReleaseDesktop();
2801 return TRUE;
2805 /**********************************************************************
2806 * WIN_EnumQueueWindows
2808 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2810 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2812 WND **list, **ppWnd;
2814 /* This function is the same as EnumWindows(), */
2815 /* except for an added check on the window's task. */
2817 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2819 WIN_ReleaseDesktop();
2820 return FALSE;
2823 /* Now call the callback function for every window */
2825 for (ppWnd = list; *ppWnd; ppWnd++)
2827 LRESULT funcRetval;
2828 int iWndsLocks = 0;
2829 /* Make sure that the window still exists */
2830 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2831 if ((*ppWnd)->hmemTaskQ != queue) continue;
2833 /* To avoid any deadlocks, all the locks on the windows
2834 structures must be suspended before the control
2835 is passed to the application */
2836 iWndsLocks = WIN_SuspendWndsLock();
2837 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2838 WIN_RestoreWndsLock(iWndsLocks);
2840 if (!funcRetval) break;
2842 WIN_ReleaseWinArray(list);
2843 WIN_ReleaseDesktop();
2844 return TRUE;
2848 /**********************************************************************
2849 * EnumTaskWindows16 (USER.225)
2851 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2852 LPARAM lParam )
2854 HQUEUE16 queue = GetTaskQueue16( hTask );
2855 if (!queue) return FALSE;
2856 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2860 /**********************************************************************
2861 * EnumThreadWindows (USER32.@)
2863 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2865 HQUEUE16 queue = GetThreadQueue16( id );
2866 if (!queue) return FALSE;
2867 return WIN_EnumQueueWindows( queue, func, lParam );
2871 /**********************************************************************
2872 * WIN_EnumChildWindows
2874 * Helper function for EnumChildWindows().
2876 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2878 WND **childList;
2879 BOOL16 ret = FALSE;
2881 for ( ; *ppWnd; ppWnd++)
2883 int iWndsLocks = 0;
2885 /* Make sure that the window still exists */
2886 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2887 /* Build children list first */
2888 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2890 /* To avoid any deadlocks, all the locks on the windows
2891 structures must be suspended before the control
2892 is passed to the application */
2893 iWndsLocks = WIN_SuspendWndsLock();
2894 ret = func( (*ppWnd)->hwndSelf, lParam );
2895 WIN_RestoreWndsLock(iWndsLocks);
2897 if (childList)
2899 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2900 WIN_ReleaseWinArray(childList);
2902 if (!ret) return FALSE;
2904 return TRUE;
2908 /**********************************************************************
2909 * EnumChildWindows (USER32.@)
2911 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2912 LPARAM lParam )
2914 WND **list, *pParent;
2916 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2917 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2919 WIN_ReleaseWndPtr(pParent);
2920 return FALSE;
2922 WIN_EnumChildWindows( list, func, lParam );
2923 WIN_ReleaseWinArray(list);
2924 WIN_ReleaseWndPtr(pParent);
2925 return TRUE;
2929 /*******************************************************************
2930 * AnyPopup (USER.52)
2932 BOOL16 WINAPI AnyPopup16(void)
2934 return AnyPopup();
2938 /*******************************************************************
2939 * AnyPopup (USER32.@)
2941 BOOL WINAPI AnyPopup(void)
2943 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2944 BOOL retvalue;
2946 while (wndPtr)
2948 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2950 retvalue = TRUE;
2951 goto end;
2953 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2955 retvalue = FALSE;
2956 end:
2957 WIN_ReleaseWndPtr(wndPtr);
2958 return retvalue;
2962 /*******************************************************************
2963 * FlashWindow (USER.105)
2965 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2967 return FlashWindow( hWnd, bInvert );
2971 /*******************************************************************
2972 * FlashWindow (USER32.@)
2974 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2976 WND *wndPtr = WIN_FindWndPtr(hWnd);
2978 TRACE("%04x\n", hWnd);
2980 if (!wndPtr) return FALSE;
2982 if (wndPtr->dwStyle & WS_MINIMIZE)
2984 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2986 HDC hDC = GetDC(hWnd);
2988 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2989 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2991 ReleaseDC( hWnd, hDC );
2992 wndPtr->flags |= WIN_NCACTIVATED;
2994 else
2996 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2997 wndPtr->flags &= ~WIN_NCACTIVATED;
2999 WIN_ReleaseWndPtr(wndPtr);
3000 return TRUE;
3002 else
3004 WPARAM16 wparam;
3005 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3006 else wparam = (hWnd == GetActiveWindow());
3008 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3009 WIN_ReleaseWndPtr(wndPtr);
3010 return wparam;
3015 /*******************************************************************
3016 * SetSysModalWindow (USER.188)
3018 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3020 HWND hWndOldModal = hwndSysModal;
3021 hwndSysModal = hWnd;
3022 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3023 return hWndOldModal;
3027 /*******************************************************************
3028 * GetSysModalWindow (USER.189)
3030 HWND16 WINAPI GetSysModalWindow16(void)
3032 return hwndSysModal;
3036 /*******************************************************************
3037 * GetWindowContextHelpId (USER32.@)
3039 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3041 DWORD retval;
3042 WND *wnd = WIN_FindWndPtr( hwnd );
3043 if (!wnd) return 0;
3044 retval = wnd->helpContext;
3045 WIN_ReleaseWndPtr(wnd);
3046 return retval;
3050 /*******************************************************************
3051 * SetWindowContextHelpId (USER32.@)
3053 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3055 WND *wnd = WIN_FindWndPtr( hwnd );
3056 if (!wnd) return FALSE;
3057 wnd->helpContext = id;
3058 WIN_ReleaseWndPtr(wnd);
3059 return TRUE;
3063 /*******************************************************************
3064 * DRAG_QueryUpdate
3066 * recursively find a child that contains spDragInfo->pt point
3067 * and send WM_QUERYDROPOBJECT
3069 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3071 BOOL16 wParam, bResult = 0;
3072 POINT pt;
3073 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3074 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3075 RECT tempRect;
3077 if( !ptrQueryWnd || !ptrDragInfo )
3078 goto end;
3080 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3082 GetWindowRect(hQueryWnd,&tempRect);
3084 if( !PtInRect(&tempRect,pt) ||
3085 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3086 goto end;
3088 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3090 tempRect = ptrQueryWnd->rectClient;
3091 if(ptrQueryWnd->parent)
3092 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3093 (LPPOINT)&tempRect, 2 );
3095 if (PtInRect( &tempRect, pt))
3097 wParam = 0;
3099 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3101 if( ptrWnd->dwStyle & WS_VISIBLE )
3103 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3104 if (PtInRect( &tempRect, pt )) break;
3108 if(ptrWnd)
3110 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3111 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3112 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3113 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3114 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3116 WIN_ReleaseWndPtr(ptrWnd);
3119 if(bResult)
3120 goto end;
3122 else wParam = 1;
3124 else wParam = 1;
3126 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3128 ptrDragInfo->hScope = hQueryWnd;
3130 bResult = ( bNoSend )
3131 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3132 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3133 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3134 if( !bResult )
3135 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3137 end:
3138 WIN_ReleaseWndPtr(ptrQueryWnd);
3139 return bResult;
3143 /*******************************************************************
3144 * DragDetect (USER.465)
3146 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3148 POINT pt32;
3149 CONV_POINT16TO32( &pt, &pt32 );
3150 return DragDetect( hWnd, pt32 );
3153 /*******************************************************************
3154 * DragDetect (USER32.@)
3156 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3158 MSG msg;
3159 RECT rect;
3161 rect.left = pt.x - wDragWidth;
3162 rect.right = pt.x + wDragWidth;
3164 rect.top = pt.y - wDragHeight;
3165 rect.bottom = pt.y + wDragHeight;
3167 SetCapture(hWnd);
3169 while(1)
3171 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3173 if( msg.message == WM_LBUTTONUP )
3175 ReleaseCapture();
3176 return 0;
3178 if( msg.message == WM_MOUSEMOVE )
3180 POINT tmp;
3181 tmp.x = LOWORD(msg.lParam);
3182 tmp.y = HIWORD(msg.lParam);
3183 if( !PtInRect( &rect, tmp ))
3185 ReleaseCapture();
3186 return 1;
3190 WaitMessage();
3192 return 0;
3195 /******************************************************************************
3196 * DragObject (USER.464)
3198 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3199 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3201 MSG msg;
3202 LPDRAGINFO16 lpDragInfo;
3203 SEGPTR spDragInfo;
3204 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3205 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3206 WND *wndPtr = WIN_FindWndPtr(hWnd);
3207 HCURSOR16 hCurrentCursor = 0;
3208 HWND16 hCurrentWnd = 0;
3210 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3211 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3213 if( !lpDragInfo || !spDragInfo )
3215 WIN_ReleaseWndPtr(wndPtr);
3216 return 0L;
3219 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3221 if( !hBummer || !wndPtr )
3223 GlobalFree16(hDragInfo);
3224 WIN_ReleaseWndPtr(wndPtr);
3225 return 0L;
3228 if(hCursor)
3230 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3232 GlobalFree16(hDragInfo);
3233 WIN_ReleaseWndPtr(wndPtr);
3234 return 0L;
3237 if( hDragCursor == hCursor ) hDragCursor = 0;
3238 else hCursor = hDragCursor;
3240 hOldCursor = SetCursor(hDragCursor);
3243 lpDragInfo->hWnd = hWnd;
3244 lpDragInfo->hScope = 0;
3245 lpDragInfo->wFlags = wObj;
3246 lpDragInfo->hList = szList; /* near pointer! */
3247 lpDragInfo->hOfStruct = hOfStruct;
3248 lpDragInfo->l = 0L;
3250 SetCapture(hWnd);
3251 ShowCursor( TRUE );
3255 do{ WaitMessage(); }
3256 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3258 *(lpDragInfo+1) = *lpDragInfo;
3260 lpDragInfo->pt.x = msg.pt.x;
3261 lpDragInfo->pt.y = msg.pt.y;
3263 /* update DRAGINFO struct */
3264 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3266 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3267 hCurrentCursor = hCursor;
3268 else
3270 hCurrentCursor = hBummer;
3271 lpDragInfo->hScope = 0;
3273 if( hCurrentCursor )
3274 SetCursor(hCurrentCursor);
3276 /* send WM_DRAGLOOP */
3277 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3278 (LPARAM) spDragInfo );
3279 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3280 if( hCurrentWnd != lpDragInfo->hScope )
3282 if( hCurrentWnd )
3283 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3284 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3285 HIWORD(spDragInfo)) );
3286 hCurrentWnd = lpDragInfo->hScope;
3287 if( hCurrentWnd )
3288 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3290 else
3291 if( hCurrentWnd )
3292 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3294 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3296 ReleaseCapture();
3297 ShowCursor( FALSE );
3299 if( hCursor )
3301 SetCursor( hOldCursor );
3302 if (hDragCursor) DestroyCursor( hDragCursor );
3305 if( hCurrentCursor != hBummer )
3306 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3307 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3308 else
3309 msg.lParam = 0;
3310 GlobalFree16(hDragInfo);
3311 WIN_ReleaseWndPtr(wndPtr);
3313 return (DWORD)(msg.lParam);
3317 /******************************************************************************
3318 * GetWindowModuleFileNameA (USER32.@)
3320 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3322 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3323 hwnd, lpszFileName, cchFileNameMax);
3324 return 0;
3327 /******************************************************************************
3328 * GetWindowModuleFileNameW (USER32.@)
3330 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3332 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3333 hwnd, lpszFileName, cchFileNameMax);
3334 return 0;