2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/server.h"
13 #include "wine/unicode.h"
19 #include "cursoricon.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(win);
30 DECLARE_DEBUG_CHANNEL(msg);
32 /**********************************************************************/
35 static WND *pWndDesktop = NULL;
37 static HWND hwndSysModal = 0;
39 static WORD wDragWidth = 4;
40 static WORD wDragHeight= 3;
42 static void *user_handles[65536];
45 extern SYSLEVEL USER_SysLevel; /* FIXME */
47 /***********************************************************************
50 * Suspend the lock on WND structures.
51 * Returns the number of locks suspended
53 int WIN_SuspendWndsLock( void )
55 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
56 int count = isuspendedLocks;
59 _LeaveSysLevel( &USER_SysLevel );
61 return isuspendedLocks;
64 /***********************************************************************
67 * Restore the suspended locks on WND structures
69 void WIN_RestoreWndsLock( int ipreviousLocks )
71 while ( ipreviousLocks-- > 0 )
72 _EnterSysLevel( &USER_SysLevel );
75 /***********************************************************************
76 * create_window_handle
78 * Create a window handle with the server.
80 static WND *create_window_handle( BOOL desktop, INT size )
83 unsigned int handle = 0;
84 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
86 if (!win) return NULL;
92 SERVER_START_REQ( create_desktop_window )
94 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
100 SERVER_START_REQ( create_window )
102 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
110 HeapFree( GetProcessHeap(), 0, win );
113 user_handles[LOWORD(handle)] = win;
114 win->hwndSelf = (HWND)handle;
115 win->dwMagic = WND_MAGIC;
121 /***********************************************************************
124 * Free a window handle.
126 static WND *free_window_handle( HWND hwnd )
131 if ((ptr = user_handles[LOWORD(hwnd)]))
133 SERVER_START_REQ( destroy_window )
136 if (!SERVER_CALL_ERR())
137 user_handles[LOWORD(hwnd)] = NULL;
144 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
149 /***********************************************************************
152 * Get the full 32-bit window handle from a possibly truncated handle.
154 HWND WIN_GetFullHandle( HWND hwnd )
158 SERVER_START_REQ( get_window_info )
161 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
169 /***********************************************************************
172 * Return a pointer to the WND structure corresponding to a HWND.
174 WND * WIN_FindWndPtr( HWND hwnd )
178 if (!hwnd) return NULL;
181 if (!(ptr = user_handles[LOWORD(hwnd)]))
183 /* check other processes */
184 if (IsWindow( hwnd ))
186 ERR( "window %04x belongs to other process\n", hwnd );
187 /* DbgBreakPoint(); */
191 if (ptr->dwMagic != WND_MAGIC) goto error;
192 /* verify that handle highword (if any) matches the window */
193 if (HIWORD(hwnd) && hwnd != ptr->hwndSelf) goto error;
194 /*and increment destruction monitoring*/
199 /* Unlock all WND structures for thread safeness*/
201 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
206 /***********************************************************************
209 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
211 * Returns the locked initialisation pointer
213 WND *WIN_LockWndPtr(WND *initWndPtr)
215 if(!initWndPtr) return 0;
217 /* Lock all WND structures for thread safeness*/
219 /*and increment destruction monitoring*/
220 initWndPtr->irefCount++;
226 /***********************************************************************
229 * Release the pointer to the WND structure.
231 void WIN_ReleaseWndPtr(WND *wndPtr)
235 /*Decrement destruction monitoring value*/
237 /* Check if it's time to release the memory*/
238 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
241 free_window_handle( wndPtr->hwndSelf );
243 else if(wndPtr->irefCount < 0)
245 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
246 ERR("forgot a Lock on %p somewhere\n",wndPtr);
248 /*unlock all WND structures for thread safeness*/
252 /***********************************************************************
255 * Updates the value of oldPtr to newPtr.
257 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
261 tmpWnd = WIN_LockWndPtr(newPtr);
262 WIN_ReleaseWndPtr(*oldPtr);
268 /***********************************************************************
271 * Remove a window from the siblings linked list.
273 void WIN_UnlinkWindow( HWND hwnd )
275 WIN_LinkWindow( hwnd, 0, 0 );
279 /***********************************************************************
282 * Insert a window into the siblings linked list.
283 * The window is inserted after the specified window, which can also
284 * be specified as HWND_TOP or HWND_BOTTOM.
285 * If parent is 0, window is unlinked from the tree.
287 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
289 WND *wndPtr, **ppWnd, *parentPtr = NULL;
292 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
293 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
295 WIN_ReleaseWndPtr(wndPtr);
299 SERVER_START_REQ( link_window )
302 req->parent = parent;
303 req->previous = hwndInsertAfter;
304 ret = !SERVER_CALL_ERR();
309 /* first unlink it if it is linked */
312 ppWnd = &wndPtr->parent->child;
313 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
314 if (*ppWnd) *ppWnd = wndPtr->next;
319 wndPtr->parent = parentPtr;
320 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
322 ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
323 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
324 while (*ppWnd) ppWnd = &(*ppWnd)->next;
326 else /* Normal case */
328 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
329 if (!afterPtr) goto done;
330 ppWnd = &afterPtr->next;
331 WIN_ReleaseWndPtr(afterPtr);
333 wndPtr->next = *ppWnd;
336 else wndPtr->next = NULL; /* unlinked */
339 WIN_ReleaseWndPtr( parentPtr );
340 WIN_ReleaseWndPtr( wndPtr );
344 /***********************************************************************
345 * WIN_FindWinToRepaint
347 * Find a window that needs repaint.
349 HWND WIN_FindWinToRepaint( HWND hwnd )
354 /* Note: the desktop window never gets WM_PAINT messages
355 * The real reason why is because Windows DesktopWndProc
356 * does ValidateRgn inside WM_ERASEBKGND handler.
358 if (hwnd == GetDesktopWindow()) hwnd = 0;
360 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
362 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
364 if (!(pWnd->dwStyle & WS_VISIBLE))
366 TRACE("skipping window %04x\n",
369 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
370 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
373 else if (pWnd->child )
374 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
376 WIN_ReleaseWndPtr(pWnd);
387 hwndRet = pWnd->hwndSelf;
389 /* look among siblings if we got a transparent window */
390 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
391 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
393 WIN_UpdateWndPtr(&pWnd,pWnd->next);
397 hwndRet = pWnd->hwndSelf;
398 WIN_ReleaseWndPtr(pWnd);
400 TRACE("found %04x\n",hwndRet);
405 /***********************************************************************
408 * Destroy storage associated to a window. "Internals" p.358
409 * returns a locked wndPtr->next
411 static WND* WIN_DestroyWindow( WND* wndPtr )
413 HWND hwnd = wndPtr->hwndSelf;
416 TRACE("%04x\n", wndPtr->hwndSelf );
418 /* free child windows */
419 WIN_LockWndPtr(wndPtr->child);
420 while ((pWnd = wndPtr->child))
422 wndPtr->child = WIN_DestroyWindow( pWnd );
423 WIN_ReleaseWndPtr(pWnd);
427 * Clear the update region to make sure no WM_PAINT messages will be
428 * generated for this window while processing the WM_NCDESTROY.
430 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
431 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
434 * Send the WM_NCDESTROY to the window being destroyed.
436 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
438 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
440 WINPOS_CheckInternalPos( hwnd );
441 if( hwnd == GetCapture()) ReleaseCapture();
443 /* free resources associated with the window */
445 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
446 PROPERTY_RemoveWindowProps( wndPtr );
448 /* toss stale messages from the queue */
450 QUEUE_CleanupWindow( hwnd );
451 wndPtr->hmemTaskQ = 0;
453 if (!(wndPtr->dwStyle & WS_CHILD))
456 DestroyMenu( wndPtr->wIDmenu );
459 if (wndPtr->hSysMenu)
461 DestroyMenu( wndPtr->hSysMenu );
462 wndPtr->hSysMenu = 0;
464 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
465 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
466 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
467 CLASS_RemoveWindow( wndPtr->class );
468 wndPtr->class = NULL;
469 wndPtr->dwMagic = 0; /* Mark it as invalid */
471 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
476 /***********************************************************************
477 * WIN_DestroyThreadWindows
479 * Destroy all children of 'wnd' owned by the current thread.
480 * Return TRUE if something was done.
482 void WIN_DestroyThreadWindows( HWND hwnd )
487 if (!(list = WIN_ListChildren( hwnd ))) return;
488 for (i = 0; list[i]; i++)
490 if (!IsWindow( list[i] )) continue;
491 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
492 DestroyWindow( list[i] );
494 WIN_DestroyThreadWindows( list[i] );
496 HeapFree( GetProcessHeap(), 0, list );
499 /***********************************************************************
500 * WIN_CreateDesktopWindow
502 * Create the desktop window.
504 BOOL WIN_CreateDesktopWindow(void)
506 struct tagCLASS *class;
514 TRACE("Creating desktop window\n");
517 if (!WINPOS_CreateInternalPosAtom() ||
518 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
519 &wndExtra, &winproc, &clsStyle, &dce )))
522 pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra );
523 if (!pWndDesktop) return FALSE;
524 hwndDesktop = pWndDesktop->hwndSelf;
526 pWndDesktop->tid = 0; /* nobody owns the desktop */
527 pWndDesktop->next = NULL;
528 pWndDesktop->child = NULL;
529 pWndDesktop->parent = NULL;
530 pWndDesktop->owner = 0;
531 pWndDesktop->class = class;
532 pWndDesktop->hInstance = 0;
533 pWndDesktop->rectWindow.left = 0;
534 pWndDesktop->rectWindow.top = 0;
535 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
536 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
537 pWndDesktop->rectClient = pWndDesktop->rectWindow;
538 pWndDesktop->text = NULL;
539 pWndDesktop->hmemTaskQ = 0;
540 pWndDesktop->hrgnUpdate = 0;
541 pWndDesktop->hwndLastActive = hwndDesktop;
542 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
544 pWndDesktop->dwExStyle = 0;
545 pWndDesktop->clsStyle = clsStyle;
546 pWndDesktop->dce = NULL;
547 pWndDesktop->pVScroll = NULL;
548 pWndDesktop->pHScroll = NULL;
549 pWndDesktop->pProp = NULL;
550 pWndDesktop->wIDmenu = 0;
551 pWndDesktop->helpContext = 0;
552 pWndDesktop->flags = 0;
553 pWndDesktop->hSysMenu = 0;
554 pWndDesktop->userdata = 0;
555 pWndDesktop->winproc = winproc;
556 pWndDesktop->cbWndExtra = wndExtra;
558 cs.lpCreateParams = NULL;
564 cs.cx = pWndDesktop->rectWindow.right;
565 cs.cy = pWndDesktop->rectWindow.bottom;
566 cs.style = pWndDesktop->dwStyle;
567 cs.dwExStyle = pWndDesktop->dwExStyle;
569 cs.lpszClass = DESKTOP_CLASS_ATOM;
571 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
573 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
574 WIN_ReleaseWndPtr( pWndDesktop );
579 /***********************************************************************
582 * Fix the coordinates - Helper for WIN_CreateWindowEx.
583 * returns default show mode in sw.
584 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
586 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
588 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
589 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
591 if (cs->style & (WS_CHILD | WS_POPUP))
593 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
594 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
596 else /* overlapped window */
600 GetStartupInfoA( &info );
602 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
604 /* Never believe Microsoft's documentation... CreateWindowEx doc says
605 * that if an overlapped window is created with WS_VISIBLE style bit
606 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
607 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
610 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
611 * 2) it does not ignore the y parameter as the docs claim; instead, it
612 * uses it as second parameter to ShowWindow() unless y is either
613 * CW_USEDEFAULT or CW_USEDEFAULT16.
615 * The fact that we didn't do 2) caused bogus windows pop up when wine
616 * was running apps that were using this obscure feature. Example -
617 * calc.exe that comes with Win98 (only Win98, it's different from
618 * the one that comes with Win95 and NT)
620 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
621 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
622 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
625 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
627 if (info.dwFlags & STARTF_USESIZE)
629 cs->cx = info.dwXSize;
630 cs->cy = info.dwYSize;
632 else /* if no other hint from the app, pick 3/4 of the screen real estate */
635 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
636 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
637 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
644 /***********************************************************************
647 * Implementation of CreateWindowEx().
649 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
650 WINDOWPROCTYPE type )
653 struct tagCLASS *classPtr;
655 HWND hwnd, hwndLinkAfter;
656 POINT maxSize, maxPos, minTrack, maxTrack;
661 BOOL unicode = (type == WIN_PROC_32W);
663 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
664 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
665 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
666 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
667 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
669 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
670 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
672 /* Find the parent window */
676 /* Make sure parent is valid */
677 if (!IsWindow( cs->hwndParent ))
679 WARN("Bad parent %04x\n", cs->hwndParent );
682 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
683 WARN("No parent for child window\n" );
684 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
687 /* Find the window class */
688 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
689 &wndExtra, &winproc, &clsStyle, &dce )))
691 WARN("Bad class '%s'\n", cs->lpszClass );
695 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
697 /* Correct the window style - stage 1
699 * These are patches that appear to affect both the style loaded into the
700 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
702 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
703 * why does the user get to set it?
706 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
707 * tested for WS_POPUP
709 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
710 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
711 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
712 cs->dwExStyle |= WS_EX_WINDOWEDGE;
714 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
716 /* Create the window structure */
718 if (!(wndPtr = create_window_handle( FALSE,
719 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
721 TRACE("out of memory\n" );
724 hwnd = wndPtr->hwndSelf;
726 /* Fill the window structure */
728 wndPtr->tid = GetCurrentThreadId();
730 wndPtr->child = NULL;
732 if ((cs->style & WS_CHILD) && cs->hwndParent)
734 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
736 WIN_ReleaseWndPtr(wndPtr->parent);
740 wndPtr->parent = pWndDesktop;
741 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
744 wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
748 wndPtr->class = classPtr;
749 wndPtr->winproc = winproc;
750 wndPtr->hInstance = cs->hInstance;
752 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
753 wndPtr->hrgnUpdate = 0;
755 wndPtr->hwndLastActive = hwnd;
756 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
757 wndPtr->dwExStyle = cs->dwExStyle;
758 wndPtr->clsStyle = clsStyle;
760 wndPtr->helpContext = 0;
761 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
762 wndPtr->pVScroll = NULL;
763 wndPtr->pHScroll = NULL;
764 wndPtr->pProp = NULL;
765 wndPtr->userdata = 0;
766 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
767 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
768 wndPtr->cbWndExtra = wndExtra;
770 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
772 /* Call the WH_CBT hook */
774 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
775 ? HWND_BOTTOM : HWND_TOP;
777 if (HOOK_IsHooked( WH_CBT ))
783 cbtc.hwndInsertAfter = hwndLinkAfter;
784 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
785 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
788 TRACE("CBT-hook returned 0\n");
789 free_window_handle( hwnd );
790 CLASS_RemoveWindow( classPtr );
796 /* Correct the window style - stage 2 */
798 if (!(cs->style & WS_CHILD))
800 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
801 if (!(cs->style & WS_POPUP))
803 wndPtr->dwStyle |= WS_CAPTION;
804 wndPtr->flags |= WIN_NEED_SIZE;
808 /* Get class or window DC if needed */
810 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
811 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
812 else wndPtr->dce = NULL;
814 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
816 wndPtr->rectWindow.left = cs->x;
817 wndPtr->rectWindow.top = cs->y;
818 wndPtr->rectWindow.right = cs->x + cs->cx;
819 wndPtr->rectWindow.bottom = cs->y + cs->cy;
820 wndPtr->rectClient = wndPtr->rectWindow;
822 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
824 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
826 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
827 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
828 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
829 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
830 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
833 if (cs->cx < 0) cs->cx = 0;
834 if (cs->cy < 0) cs->cy = 0;
836 wndPtr->rectWindow.left = cs->x;
837 wndPtr->rectWindow.top = cs->y;
838 wndPtr->rectWindow.right = cs->x + cs->cx;
839 wndPtr->rectWindow.bottom = cs->y + cs->cy;
840 wndPtr->rectClient = wndPtr->rectWindow;
842 /* Set the window menu */
844 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
846 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
849 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
852 if (HIWORD(cs->hInstance))
853 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
855 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
857 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
861 else wndPtr->wIDmenu = (UINT)cs->hMenu;
863 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
865 WARN("aborted by WM_xxCREATE!\n");
866 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
867 CLASS_RemoveWindow( classPtr );
868 WIN_ReleaseWndPtr(wndPtr);
872 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
874 /* Notify the parent window only */
876 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
877 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
878 if( !IsWindow(hwnd) )
885 if (cs->style & WS_VISIBLE)
887 /* in case WS_VISIBLE got set in the meantime */
888 wndPtr->dwStyle &= ~WS_VISIBLE;
889 ShowWindow( hwnd, sw );
892 /* Call WH_SHELL hook */
894 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
895 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
897 TRACE("created window %04x\n", hwnd);
899 WIN_ReleaseWndPtr(wndPtr);
904 /***********************************************************************
905 * CreateWindow (USER.41)
907 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
908 DWORD style, INT16 x, INT16 y, INT16 width,
909 INT16 height, HWND16 parent, HMENU16 menu,
910 HINSTANCE16 instance, LPVOID data )
912 return CreateWindowEx16( 0, className, windowName, style,
913 x, y, width, height, parent, menu, instance, data );
917 /***********************************************************************
918 * CreateWindowEx (USER.452)
920 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
921 LPCSTR windowName, DWORD style, INT16 x,
922 INT16 y, INT16 width, INT16 height,
923 HWND16 parent, HMENU16 menu,
924 HINSTANCE16 instance, LPVOID data )
930 /* Find the class atom */
932 if (HIWORD(className))
934 if (!(classAtom = GlobalFindAtomA( className )))
936 ERR( "bad class name %s\n", debugres_a(className) );
942 classAtom = LOWORD(className);
943 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
945 ERR( "bad atom %x\n", classAtom);
951 /* Fix the coordinates */
953 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
954 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
955 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
956 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
958 /* Create the window */
960 cs.lpCreateParams = data;
961 cs.hInstance = (HINSTANCE)instance;
962 cs.hMenu = (HMENU)menu;
963 cs.hwndParent = (HWND)parent;
965 cs.lpszName = windowName;
966 cs.lpszClass = className;
967 cs.dwExStyle = exStyle;
969 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
973 /***********************************************************************
974 * CreateWindowExA (USER32.@)
976 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
977 LPCSTR windowName, DWORD style, INT x,
978 INT y, INT width, INT height,
979 HWND parent, HMENU menu,
980 HINSTANCE instance, LPVOID data )
987 instance=GetModuleHandleA(NULL);
989 if(exStyle & WS_EX_MDICHILD)
990 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
992 /* Find the class atom */
994 if (HIWORD(className))
996 if (!(classAtom = GlobalFindAtomA( className )))
998 ERR( "bad class name %s\n", debugres_a(className) );
1004 classAtom = LOWORD(className);
1005 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1007 ERR( "bad atom %x\n", classAtom);
1013 /* Create the window */
1015 cs.lpCreateParams = data;
1016 cs.hInstance = instance;
1018 cs.hwndParent = parent;
1024 cs.lpszName = windowName;
1025 cs.lpszClass = className;
1026 cs.dwExStyle = exStyle;
1028 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1032 /***********************************************************************
1033 * CreateWindowExW (USER32.@)
1035 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1036 LPCWSTR windowName, DWORD style, INT x,
1037 INT y, INT width, INT height,
1038 HWND parent, HMENU menu,
1039 HINSTANCE instance, LPVOID data )
1046 instance=GetModuleHandleA(NULL);
1048 if(exStyle & WS_EX_MDICHILD)
1049 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1051 /* Find the class atom */
1053 if (HIWORD(className))
1055 if (!(classAtom = GlobalFindAtomW( className )))
1057 ERR( "bad class name %s\n", debugres_w(className) );
1063 classAtom = LOWORD(className);
1064 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1066 ERR( "bad atom %x\n", classAtom);
1072 /* Create the window */
1074 cs.lpCreateParams = data;
1075 cs.hInstance = instance;
1077 cs.hwndParent = parent;
1083 cs.lpszName = windowName;
1084 cs.lpszClass = className;
1085 cs.dwExStyle = exStyle;
1087 /* Note: we rely on the fact that CREATESTRUCTA and */
1088 /* CREATESTRUCTW have the same layout. */
1089 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1093 /***********************************************************************
1094 * WIN_SendDestroyMsg
1096 static void WIN_SendDestroyMsg( HWND hwnd )
1098 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1099 if (USER_Driver.pResetSelectionOwner)
1100 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1103 * Send the WM_DESTROY to the window.
1105 SendMessageA( hwnd, 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.
1116 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1118 /* start from the end (FIXME: is this needed?) */
1119 for (i = 0; pWndArray[i]; i++) ;
1123 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1125 HeapFree( GetProcessHeap(), 0, pWndArray );
1128 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1132 /***********************************************************************
1133 * DestroyWindow (USER.53)
1135 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1137 return DestroyWindow(hwnd);
1141 /***********************************************************************
1142 * DestroyWindow (USER32.@)
1144 BOOL WINAPI DestroyWindow( HWND hwnd )
1150 TRACE("(%04x)\n", hwnd);
1152 /* Initialization */
1154 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1156 /* Look whether the focus is within the tree of windows we will
1160 if (h == hwnd || IsChild( hwnd, h ))
1162 HWND parent = GetAncestor( hwnd, GA_PARENT );
1163 if (parent == GetDesktopWindow()) parent = 0;
1169 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
1171 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1172 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1174 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1175 /* FIXME: clean up palette - see "Internals" p.352 */
1178 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1179 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1181 /* Notify the parent window only */
1182 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1183 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1184 if( !IsWindow(hwnd) )
1191 if (USER_Driver.pResetSelectionOwner)
1192 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1194 /* Hide the window */
1196 if (wndPtr->dwStyle & WS_VISIBLE)
1198 ShowWindow( hwnd, SW_HIDE );
1199 if (!IsWindow(hwnd))
1206 /* Recursively destroy owned windows */
1208 if( !(wndPtr->dwStyle & WS_CHILD) )
1213 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1216 for (i = 0; list[i]; i++)
1218 WND *siblingPtr = WIN_FindWndPtr( list[i] );
1219 if (!siblingPtr) continue;
1220 if (siblingPtr->owner == hwnd)
1222 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1224 WIN_ReleaseWndPtr( siblingPtr );
1225 DestroyWindow( list[i] );
1229 else siblingPtr->owner = 0;
1231 WIN_ReleaseWndPtr( siblingPtr );
1233 HeapFree( GetProcessHeap(), 0, list );
1235 if (!got_one) break;
1238 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1242 WND *owner = WIN_FindWndPtr( wndPtr->owner );
1243 if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
1244 WIN_ReleaseWndPtr( owner );
1248 /* Send destroy messages */
1250 WIN_SendDestroyMsg( hwnd );
1251 if (!IsWindow(hwnd))
1257 /* Unlink now so we won't bother with the children later on */
1259 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1261 /* Destroy the window storage */
1263 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1266 WIN_ReleaseWndPtr(wndPtr);
1271 /***********************************************************************
1272 * CloseWindow (USER.43)
1274 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1276 return CloseWindow( hwnd );
1280 /***********************************************************************
1281 * CloseWindow (USER32.@)
1283 BOOL WINAPI CloseWindow( HWND hwnd )
1285 WND * wndPtr = WIN_FindWndPtr( hwnd );
1288 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1293 ShowWindow( hwnd, SW_MINIMIZE );
1296 WIN_ReleaseWndPtr(wndPtr);
1302 /***********************************************************************
1303 * OpenIcon (USER.44)
1305 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1307 return OpenIcon( hwnd );
1311 /***********************************************************************
1312 * OpenIcon (USER32.@)
1314 BOOL WINAPI OpenIcon( HWND hwnd )
1316 if (!IsIconic( hwnd )) return FALSE;
1317 ShowWindow( hwnd, SW_SHOWNORMAL );
1322 /***********************************************************************
1325 * Implementation of FindWindow() and FindWindowEx().
1327 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1332 WCHAR *buffer = NULL;
1334 if (!parent) parent = GetDesktopWindow();
1337 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1338 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1341 if (!(list = WIN_ListChildren( parent )))
1343 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1349 while (list[i] && list[i] != child) i++;
1350 if (!list[i]) return 0;
1351 i++; /* start from next window */
1354 for ( ; list[i]; i++)
1356 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1357 continue; /* Not the right class */
1359 /* Now check the title */
1361 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1364 HeapFree( GetProcessHeap(), 0, list );
1365 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1367 /* In this case we need to check whether other processes
1368 own a window with the given paramters on the Desktop,
1369 but we don't, so let's at least warn about it */
1370 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1376 /***********************************************************************
1377 * FindWindow (USER.50)
1379 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1381 return FindWindowA( className, title );
1385 /***********************************************************************
1386 * FindWindowEx (USER.427)
1388 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1390 return FindWindowExA( parent, child, className, title );
1394 /***********************************************************************
1395 * FindWindowA (USER32.@)
1397 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1399 HWND ret = FindWindowExA( 0, 0, className, title );
1400 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1405 /***********************************************************************
1406 * FindWindowExA (USER32.@)
1408 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1409 LPCSTR className, LPCSTR title )
1417 /* If the atom doesn't exist, then no class */
1418 /* with this name exists either. */
1419 if (!(atom = GlobalFindAtomA( className )))
1421 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1426 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1427 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1428 HeapFree( GetProcessHeap(), 0, buffer );
1433 /***********************************************************************
1434 * FindWindowExW (USER32.@)
1436 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1437 LPCWSTR className, LPCWSTR title )
1443 /* If the atom doesn't exist, then no class */
1444 /* with this name exists either. */
1445 if (!(atom = GlobalFindAtomW( className )))
1447 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1451 return WIN_FindWindow( parent, child, atom, title );
1455 /***********************************************************************
1456 * FindWindowW (USER32.@)
1458 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1460 return FindWindowExW( 0, 0, className, title );
1464 /**********************************************************************
1465 * GetDesktopWindow (USER.286)
1467 HWND16 WINAPI GetDesktopWindow16(void)
1469 return (HWND16)pWndDesktop->hwndSelf;
1473 /**********************************************************************
1474 * GetDesktopWindow (USER32.@)
1476 HWND WINAPI GetDesktopWindow(void)
1478 if (pWndDesktop) return pWndDesktop->hwndSelf;
1479 ERR( "You need the -desktop option when running with native USER\n" );
1485 /**********************************************************************
1486 * GetDesktopHwnd (USER.278)
1488 * Exactly the same thing as GetDesktopWindow(), but not documented.
1489 * Don't ask me why...
1491 HWND16 WINAPI GetDesktopHwnd16(void)
1493 return (HWND16)pWndDesktop->hwndSelf;
1497 /*******************************************************************
1498 * EnableWindow (USER.34)
1500 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1502 return EnableWindow( hwnd, enable );
1506 /*******************************************************************
1507 * EnableWindow (USER32.@)
1509 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1514 TRACE("( %x, %d )\n", hwnd, enable);
1516 if (USER_Driver.pEnableWindow)
1517 return USER_Driver.pEnableWindow( hwnd, enable );
1519 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1521 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1523 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1525 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1526 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1528 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1530 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1532 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1534 if (hwnd == GetFocus())
1535 SetFocus( 0 ); /* A disabled window can't have the focus */
1537 if (hwnd == GetCapture())
1538 ReleaseCapture(); /* A disabled window can't capture the mouse */
1540 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1542 WIN_ReleaseWndPtr(wndPtr);
1547 /***********************************************************************
1548 * IsWindowEnabled (USER.35)
1550 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1552 return IsWindowEnabled(hWnd);
1556 /***********************************************************************
1557 * IsWindowEnabled (USER32.@)
1559 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1564 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1565 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1566 WIN_ReleaseWndPtr(wndPtr);
1572 /***********************************************************************
1573 * IsWindowUnicode (USER32.@)
1575 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1580 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1581 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1582 WIN_ReleaseWndPtr(wndPtr);
1587 /**********************************************************************
1588 * GetWindowWord (USER.133)
1590 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1592 return GetWindowWord( hwnd, offset );
1596 /**********************************************************************
1597 * GetWindowWord (USER32.@)
1599 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1602 WND * wndPtr = WIN_FindWndPtr( hwnd );
1603 if (!wndPtr) return 0;
1606 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1608 WARN("Invalid offset %d\n", offset );
1612 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1618 if (HIWORD(wndPtr->wIDmenu))
1619 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1621 retvalue = (WORD)wndPtr->wIDmenu;
1623 case GWW_HWNDPARENT:
1624 retvalue = GetParent(hwnd);
1627 if (HIWORD(wndPtr->hInstance))
1628 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1630 retvalue = (WORD)wndPtr->hInstance;
1633 WARN("Invalid offset %d\n", offset );
1638 WIN_ReleaseWndPtr(wndPtr);
1642 /**********************************************************************
1643 * SetWindowWord (USER.134)
1645 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1647 return SetWindowWord( hwnd, offset, newval );
1651 /**********************************************************************
1652 * SetWindowWord (USER32.@)
1654 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1657 WND * wndPtr = WIN_FindWndPtr( hwnd );
1658 if (!wndPtr) return 0;
1661 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1663 WARN("Invalid offset %d\n", offset );
1667 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1671 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1672 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1673 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1676 WARN("Invalid offset %d\n", offset );
1683 WIN_ReleaseWndPtr(wndPtr);
1688 /**********************************************************************
1691 * Helper function for GetWindowLong().
1693 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1696 WND * wndPtr = WIN_FindWndPtr( hwnd );
1697 if (!wndPtr) return 0;
1700 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1702 WARN("Invalid offset %d\n", offset );
1706 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1707 /* Special case for dialog window procedure */
1708 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1710 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1717 case GWL_USERDATA: retvalue = wndPtr->userdata;
1719 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1721 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1723 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1725 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1728 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1730 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1733 WARN("Unknown offset %d\n", offset );
1737 WIN_ReleaseWndPtr(wndPtr);
1742 /**********************************************************************
1745 * Helper function for SetWindowLong().
1747 * 0 is the failure code. However, in the case of failure SetLastError
1748 * must be set to distinguish between a 0 return value and a failure.
1750 * FIXME: The error values for SetLastError may not be right. Can
1751 * someone check with the real thing?
1753 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1754 WINDOWPROCTYPE type )
1757 WND * wndPtr = WIN_FindWndPtr( hwnd );
1760 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1764 /* Is this the right error? */
1765 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1771 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1773 WARN("Invalid offset %d\n", offset );
1775 /* Is this the right error? */
1776 SetLastError( ERROR_OUTOFMEMORY );
1781 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1782 /* Special case for dialog window procedure */
1783 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1785 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1786 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1787 type, WIN_PROC_WINDOW );
1794 ptr = (DWORD*)&wndPtr->wIDmenu;
1797 retval = SetWindowWord( hwnd, offset, newval );
1800 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1801 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1802 type, WIN_PROC_WINDOW );
1805 style.styleOld = wndPtr->dwStyle;
1806 style.styleNew = newval;
1807 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1808 wndPtr->dwStyle = style.styleNew;
1809 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1810 retval = style.styleOld;
1814 ptr = &wndPtr->userdata;
1817 style.styleOld = wndPtr->dwExStyle;
1818 style.styleNew = newval;
1819 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1820 wndPtr->dwExStyle = style.styleNew;
1821 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1822 retval = style.styleOld;
1826 WARN("Invalid offset %d\n", offset );
1828 /* Don't think this is right error but it should do */
1829 SetLastError( ERROR_OUTOFMEMORY );
1837 WIN_ReleaseWndPtr(wndPtr);
1842 /**********************************************************************
1843 * GetWindowLong (USER.135)
1845 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1847 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1851 /**********************************************************************
1852 * GetWindowLongA (USER32.@)
1854 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1856 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1860 /**********************************************************************
1861 * GetWindowLongW (USER32.@)
1863 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1865 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1869 /**********************************************************************
1870 * SetWindowLong (USER.136)
1872 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1874 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1878 /**********************************************************************
1879 * SetWindowLongA (USER32.@)
1881 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1883 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1887 /**********************************************************************
1888 * SetWindowLongW (USER32.@) Set window attribute
1890 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1891 * value in a window's extra memory.
1893 * The _hwnd_ parameter specifies the window. is the handle to a
1894 * window that has extra memory. The _newval_ parameter contains the
1895 * new attribute or extra memory value. If positive, the _offset_
1896 * parameter is the byte-addressed location in the window's extra
1897 * memory to set. If negative, _offset_ specifies the window
1898 * attribute to set, and should be one of the following values:
1900 * GWL_EXSTYLE The window's extended window style
1902 * GWL_STYLE The window's window style.
1904 * GWL_WNDPROC Pointer to the window's window procedure.
1906 * GWL_HINSTANCE The window's pplication instance handle.
1908 * GWL_ID The window's identifier.
1910 * GWL_USERDATA The window's user-specified data.
1912 * If the window is a dialog box, the _offset_ parameter can be one of
1913 * the following values:
1915 * DWL_DLGPROC The address of the window's dialog box procedure.
1917 * DWL_MSGRESULT The return value of a message
1918 * that the dialog box procedure processed.
1920 * DWL_USER Application specific information.
1924 * If successful, returns the previous value located at _offset_. Otherwise,
1929 * Extra memory for a window class is specified by a nonzero cbWndExtra
1930 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1931 * time of class creation.
1933 * Using GWL_WNDPROC to set a new window procedure effectively creates
1934 * a window subclass. Use CallWindowProc() in the new windows procedure
1935 * to pass messages to the superclass's window procedure.
1937 * The user data is reserved for use by the application which created
1940 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1941 * instead, call the EnableWindow() function to change the window's
1944 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1945 * SetParent() instead.
1948 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1949 * it sends WM_STYLECHANGING before changing the settings
1950 * and WM_STYLECHANGED afterwards.
1951 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1955 * GWL_STYLE does not dispatch WM_STYLE... messages.
1962 LONG WINAPI SetWindowLongW(
1963 HWND hwnd, /* [in] window to alter */
1964 INT offset, /* [in] offset, in bytes, of location to alter */
1965 LONG newval /* [in] new value of location */
1967 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1971 /*******************************************************************
1972 * GetWindowText (USER.36)
1974 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1976 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1980 /*******************************************************************
1981 * GetWindowTextA (USER32.@)
1983 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1985 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1989 /*******************************************************************
1990 * InternalGetWindowText (USER32.@)
1992 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1994 WND *win = WIN_FindWndPtr( hwnd );
1996 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1997 else lpString[0] = 0;
1998 WIN_ReleaseWndPtr( win );
1999 return strlenW(lpString);
2003 /*******************************************************************
2004 * GetWindowTextW (USER32.@)
2006 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2008 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2013 /*******************************************************************
2014 * SetWindowText (USER.37)
2016 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2018 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2022 /*******************************************************************
2023 * SetWindowText (USER32.@)
2024 * SetWindowTextA (USER32.@)
2026 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2028 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2032 /*******************************************************************
2033 * SetWindowTextW (USER32.@)
2035 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2037 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2041 /*******************************************************************
2042 * GetWindowTextLength (USER.38)
2044 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2046 return (INT16)GetWindowTextLengthA( hwnd );
2050 /*******************************************************************
2051 * GetWindowTextLengthA (USER32.@)
2053 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2055 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2058 /*******************************************************************
2059 * GetWindowTextLengthW (USER32.@)
2061 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2063 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2067 /*******************************************************************
2068 * IsWindow (USER.47)
2070 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2072 CURRENT_STACK16->es = USER_HeapSel;
2073 return IsWindow( hwnd );
2077 /*******************************************************************
2078 * IsWindow (USER32.@)
2080 BOOL WINAPI IsWindow( HWND hwnd )
2086 if ((ptr = user_handles[LOWORD(hwnd)]))
2088 ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
2092 if (!ret) /* check other processes */
2094 SERVER_START_REQ( get_window_info )
2097 ret = !SERVER_CALL_ERR();
2105 /***********************************************************************
2106 * GetWindowThreadProcessId (USER32.@)
2108 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2114 if ((ptr = user_handles[LOWORD(hwnd)]))
2116 if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
2118 /* got a valid window */
2120 if (process) *process = GetCurrentProcessId();
2122 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2128 /* check other processes */
2129 SERVER_START_REQ( get_window_info )
2132 if (!SERVER_CALL_ERR())
2134 tid = (DWORD)req->tid;
2135 if (process) *process = (DWORD)req->pid;
2143 /*****************************************************************
2144 * GetParent (USER.46)
2146 HWND16 WINAPI GetParent16( HWND16 hwnd )
2148 return (HWND16)GetParent( hwnd );
2152 /*****************************************************************
2153 * GetParent (USER32.@)
2155 HWND WINAPI GetParent( HWND hwnd )
2160 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2162 if (wndPtr->dwStyle & WS_CHILD)
2163 retvalue = wndPtr->parent->hwndSelf;
2164 else if (wndPtr->dwStyle & WS_POPUP)
2165 retvalue = wndPtr->owner;
2166 WIN_ReleaseWndPtr(wndPtr);
2172 /*****************************************************************
2173 * GetAncestor (USER32.@)
2175 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2180 if (hwnd == GetDesktopWindow()) return 0;
2181 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2186 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2189 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2190 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2193 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2194 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2195 while (wndPtr && wndPtr->owner)
2197 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2198 WIN_ReleaseWndPtr( wndPtr );
2203 ret = wndPtr ? wndPtr->hwndSelf : 0;
2204 WIN_ReleaseWndPtr( wndPtr );
2209 /*****************************************************************
2210 * SetParent (USER.233)
2212 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2214 return SetParent( hwndChild, hwndNewParent );
2218 /*****************************************************************
2219 * SetParent (USER32.@)
2221 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2227 if (!parent) parent = GetDesktopWindow();
2230 if (hwnd == GetDesktopWindow() || !IsWindow( parent ))
2232 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2236 if (USER_Driver.pSetParent)
2237 return USER_Driver.pSetParent( hwnd, parent );
2239 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2241 dwStyle = wndPtr->dwStyle;
2243 /* Windows hides the window first, then shows it again
2244 * including the WM_SHOWWINDOW messages and all */
2245 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2247 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2248 if (parent != retvalue)
2250 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2252 if (parent != GetDesktopWindow()) /* a child window */
2254 if (!(dwStyle & WS_CHILD))
2256 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2257 if (menu) DestroyMenu( menu );
2261 WIN_ReleaseWndPtr( wndPtr );
2263 /* SetParent additionally needs to make hwnd the topmost window
2264 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2265 WM_WINDOWPOSCHANGED notification messages.
2267 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2268 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2269 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2270 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2271 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2276 /*******************************************************************
2279 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2281 return IsChild(parent,child);
2285 /*******************************************************************
2286 * IsChild (USER32.@)
2288 BOOL WINAPI IsChild( HWND parent, HWND child )
2290 HWND *list = WIN_ListParents( child );
2294 if (!list) return FALSE;
2295 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2296 ret = (list[i] != 0);
2297 HeapFree( GetProcessHeap(), 0, list );
2302 /***********************************************************************
2303 * IsWindowVisible (USER.49)
2305 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2307 return IsWindowVisible(hwnd);
2311 /***********************************************************************
2312 * IsWindowVisible (USER32.@)
2314 BOOL WINAPI IsWindowVisible( HWND hwnd )
2320 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2321 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2322 for (i = 0; list[i]; i++)
2323 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2325 HeapFree( GetProcessHeap(), 0, list );
2330 /***********************************************************************
2331 * WIN_IsWindowDrawable
2333 * hwnd is drawable when it is visible, all parents are not
2334 * minimized, and it is itself not minimized unless we are
2335 * trying to draw its default class icon.
2337 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2343 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2344 if ((wnd->dwStyle & WS_MINIMIZE) &&
2345 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2347 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2348 for (i = 0; list[i]; i++)
2349 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2352 HeapFree( GetProcessHeap(), 0, list );
2357 /*******************************************************************
2358 * GetTopWindow (USER.229)
2360 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2362 return GetTopWindow(hwnd);
2366 /*******************************************************************
2367 * GetTopWindow (USER32.@)
2369 HWND WINAPI GetTopWindow( HWND hwnd )
2371 if (!hwnd) hwnd = GetDesktopWindow();
2372 return GetWindow( hwnd, GW_CHILD );
2376 /*******************************************************************
2377 * GetWindow (USER.262)
2379 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2381 return GetWindow( hwnd,rel );
2385 /*******************************************************************
2386 * GetWindow (USER32.@)
2388 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2392 WND * wndPtr = WIN_FindWndPtr( hwnd );
2393 if (!wndPtr) return 0;
2397 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2401 if (!wndPtr->parent)
2403 retval = 0; /* Desktop window */
2406 while (wndPtr->next)
2408 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2410 retval = wndPtr->hwndSelf;
2414 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2418 if (!wndPtr->parent)
2420 retval = 0; /* Desktop window */
2423 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2424 if (wndPtr->hwndSelf == hwnd)
2426 retval = 0; /* First in list */
2429 while (wndPtr->next)
2431 if (wndPtr->next->hwndSelf == hwnd)
2433 retval = wndPtr->hwndSelf;
2436 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2442 retval = wndPtr->owner;
2446 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2451 WIN_ReleaseWndPtr(wndPtr);
2456 /*******************************************************************
2457 * GetNextWindow (USER.230)
2459 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2461 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2462 return GetWindow16( hwnd, flag );
2465 /***********************************************************************
2466 * WIN_InternalShowOwnedPopups
2468 * Internal version of ShowOwnedPopups; Wine functions should use this
2469 * to avoid interfering with application calls to ShowOwnedPopups
2470 * and to make sure the application can't prevent showing/hiding.
2472 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2476 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2480 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2482 if (!win_array) return TRUE;
2485 * Show windows Lowest first, Highest last to preserve Z-Order
2487 while (win_array[count]) count++;
2488 while (--count >= 0)
2490 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2491 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2493 if (pWnd->dwStyle & WS_POPUP)
2497 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2498 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2501 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2503 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2504 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2509 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2510 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2511 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2514 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2516 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2517 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2518 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2522 WIN_ReleaseWndPtr( pWnd );
2524 HeapFree( GetProcessHeap(), 0, win_array );
2529 /*******************************************************************
2530 * ShowOwnedPopups (USER.265)
2532 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2534 ShowOwnedPopups( owner, fShow );
2538 /*******************************************************************
2539 * ShowOwnedPopups (USER32.@)
2541 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2545 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2547 if (!win_array) return TRUE;
2549 while (win_array[count]) count++;
2550 while (--count >= 0)
2552 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2553 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2555 if (pWnd->dwStyle & WS_POPUP)
2559 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2561 /* In Windows, ShowOwnedPopups(TRUE) generates
2562 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2563 * regardless of the state of the owner
2565 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2566 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2571 if (IsWindowVisible(pWnd->hwndSelf))
2573 /* In Windows, ShowOwnedPopups(FALSE) generates
2574 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2575 * regardless of the state of the owner
2577 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2578 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2582 WIN_ReleaseWndPtr( pWnd );
2584 HeapFree( GetProcessHeap(), 0, win_array );
2589 /*******************************************************************
2590 * GetLastActivePopup (USER.287)
2592 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2594 return GetLastActivePopup( hwnd );
2597 /*******************************************************************
2598 * GetLastActivePopup (USER32.@)
2600 HWND WINAPI GetLastActivePopup( HWND hwnd )
2603 WND *wndPtr =WIN_FindWndPtr(hwnd);
2604 if (!wndPtr) return hwnd;
2605 retval = wndPtr->hwndLastActive;
2606 WIN_ReleaseWndPtr(wndPtr);
2607 if ((retval != hwnd) && (!IsWindow(retval)))
2613 /*******************************************************************
2616 * Build an array of all parents of a given window, starting with
2617 * the immediate parent. The array must be freed with HeapFree.
2618 * Returns NULL if window is a top-level window.
2620 HWND *WIN_ListParents( HWND hwnd )
2622 WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
2626 /* First count the windows */
2628 if (!wndPtr) return NULL;
2630 parent = wndPtr->parent;
2631 while (parent && parent->hwndSelf != GetDesktopWindow())
2634 parent = parent->parent;
2639 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
2641 parent = wndPtr->parent;
2642 for (i = 0; i < count; i++)
2644 list[i] = parent->hwndSelf;
2645 parent = parent->parent;
2651 WIN_ReleaseWndPtr( wndPtr );
2656 /*******************************************************************
2659 * Build an array of the children of a given window. The array must be
2660 * freed with HeapFree. Returns NULL when no windows are found.
2662 HWND *WIN_ListChildren( HWND hwnd )
2664 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2668 /* First count the windows */
2670 if (!wndPtr) return NULL;
2672 pWnd = WIN_LockWndPtr(wndPtr->child);
2676 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2681 /* Now build the list of all windows */
2683 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2685 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2687 *phwnd++ = pWnd->hwndSelf;
2690 WIN_ReleaseWndPtr(pWnd);
2696 WIN_ReleaseWndPtr( wndPtr );
2701 /*******************************************************************
2702 * EnumWindows (USER32.@)
2704 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2710 /* We have to build a list of all windows first, to avoid */
2711 /* unpleasant side-effects, for instance if the callback */
2712 /* function changes the Z-order of the windows. */
2714 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2716 /* Now call the callback function for every window */
2718 iWndsLocks = WIN_SuspendWndsLock();
2719 for (i = 0; list[i]; i++)
2721 /* Make sure that the window still exists */
2722 if (!IsWindow( list[i] )) continue;
2723 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2725 WIN_RestoreWndsLock(iWndsLocks);
2726 HeapFree( GetProcessHeap(), 0, list );
2731 /**********************************************************************
2732 * EnumTaskWindows16 (USER.225)
2734 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2737 TDB *tdb = TASK_GetPtr( hTask );
2738 if (!tdb) return FALSE;
2739 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2743 /**********************************************************************
2744 * EnumThreadWindows (USER32.@)
2746 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2751 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2753 /* Now call the callback function for every window */
2755 iWndsLocks = WIN_SuspendWndsLock();
2756 for (i = 0; list[i]; i++)
2758 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2759 if (!func( list[i], lParam )) break;
2761 WIN_RestoreWndsLock(iWndsLocks);
2762 HeapFree( GetProcessHeap(), 0, list );
2767 /**********************************************************************
2768 * WIN_EnumChildWindows
2770 * Helper function for EnumChildWindows().
2772 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2777 for ( ; *list; list++)
2779 /* Make sure that the window still exists */
2780 if (!IsWindow( *list )) continue;
2781 /* skip owned windows */
2782 if (GetWindow( *list, GW_OWNER )) continue;
2783 /* Build children list first */
2784 childList = WIN_ListChildren( *list );
2786 ret = func( *list, lParam );
2790 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2791 HeapFree( GetProcessHeap(), 0, childList );
2793 if (!ret) return FALSE;
2799 /**********************************************************************
2800 * EnumChildWindows (USER32.@)
2802 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2807 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2808 iWndsLocks = WIN_SuspendWndsLock();
2809 WIN_EnumChildWindows( list, func, lParam );
2810 WIN_RestoreWndsLock(iWndsLocks);
2811 HeapFree( GetProcessHeap(), 0, list );
2816 /*******************************************************************
2817 * AnyPopup (USER.52)
2819 BOOL16 WINAPI AnyPopup16(void)
2825 /*******************************************************************
2826 * AnyPopup (USER32.@)
2828 BOOL WINAPI AnyPopup(void)
2832 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2834 if (!list) return FALSE;
2835 for (i = 0; list[i]; i++)
2837 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2839 retvalue = (list[i] != 0);
2840 HeapFree( GetProcessHeap(), 0, list );
2845 /*******************************************************************
2846 * FlashWindow (USER.105)
2848 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2850 return FlashWindow( hWnd, bInvert );
2854 /*******************************************************************
2855 * FlashWindow (USER32.@)
2857 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2859 WND *wndPtr = WIN_FindWndPtr(hWnd);
2861 TRACE("%04x\n", hWnd);
2863 if (!wndPtr) return FALSE;
2865 if (wndPtr->dwStyle & WS_MINIMIZE)
2867 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2869 HDC hDC = GetDC(hWnd);
2871 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2872 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2874 ReleaseDC( hWnd, hDC );
2875 wndPtr->flags |= WIN_NCACTIVATED;
2879 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2880 wndPtr->flags &= ~WIN_NCACTIVATED;
2882 WIN_ReleaseWndPtr(wndPtr);
2888 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2889 else wparam = (hWnd == GetActiveWindow());
2891 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2892 WIN_ReleaseWndPtr(wndPtr);
2898 /*******************************************************************
2899 * SetSysModalWindow (USER.188)
2901 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2903 HWND hWndOldModal = hwndSysModal;
2904 hwndSysModal = hWnd;
2905 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2906 return hWndOldModal;
2910 /*******************************************************************
2911 * GetSysModalWindow (USER.189)
2913 HWND16 WINAPI GetSysModalWindow16(void)
2915 return hwndSysModal;
2919 /*******************************************************************
2920 * GetWindowContextHelpId (USER32.@)
2922 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2925 WND *wnd = WIN_FindWndPtr( hwnd );
2927 retval = wnd->helpContext;
2928 WIN_ReleaseWndPtr(wnd);
2933 /*******************************************************************
2934 * SetWindowContextHelpId (USER32.@)
2936 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2938 WND *wnd = WIN_FindWndPtr( hwnd );
2939 if (!wnd) return FALSE;
2940 wnd->helpContext = id;
2941 WIN_ReleaseWndPtr(wnd);
2946 /*******************************************************************
2949 * recursively find a child that contains spDragInfo->pt point
2950 * and send WM_QUERYDROPOBJECT
2952 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2954 BOOL16 wParam, bResult = 0;
2956 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2959 if (!ptrDragInfo) return FALSE;
2961 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2963 GetWindowRect(hQueryWnd,&tempRect);
2965 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2967 if (!IsIconic( hQueryWnd ))
2969 GetClientRect( hQueryWnd, &tempRect );
2970 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2972 if (PtInRect( &tempRect, pt))
2975 HWND *list = WIN_ListChildren( hQueryWnd );
2981 for (i = 0; list[i]; i++)
2983 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2985 GetWindowRect( list[i], &tempRect );
2986 if (PtInRect( &tempRect, pt )) break;
2991 if (IsWindowEnabled( list[i] ))
2992 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2994 HeapFree( GetProcessHeap(), 0, list );
2996 if(bResult) return bResult;
3002 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3004 ptrDragInfo->hScope = hQueryWnd;
3006 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3007 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3009 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3015 /*******************************************************************
3016 * DragDetect (USER.465)
3018 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3021 CONV_POINT16TO32( &pt, &pt32 );
3022 return DragDetect( hWnd, pt32 );
3025 /*******************************************************************
3026 * DragDetect (USER32.@)
3028 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3033 rect.left = pt.x - wDragWidth;
3034 rect.right = pt.x + wDragWidth;
3036 rect.top = pt.y - wDragHeight;
3037 rect.bottom = pt.y + wDragHeight;
3043 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3045 if( msg.message == WM_LBUTTONUP )
3050 if( msg.message == WM_MOUSEMOVE )
3053 tmp.x = LOWORD(msg.lParam);
3054 tmp.y = HIWORD(msg.lParam);
3055 if( !PtInRect( &rect, tmp ))
3067 /******************************************************************************
3068 * DragObject (USER.464)
3070 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3071 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3074 LPDRAGINFO16 lpDragInfo;
3076 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3077 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3078 HCURSOR16 hCurrentCursor = 0;
3079 HWND16 hCurrentWnd = 0;
3081 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3082 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3084 if( !lpDragInfo || !spDragInfo ) return 0L;
3086 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3088 GlobalFree16(hDragInfo);
3094 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3096 GlobalFree16(hDragInfo);
3100 if( hDragCursor == hCursor ) hDragCursor = 0;
3101 else hCursor = hDragCursor;
3103 hOldCursor = SetCursor(hDragCursor);
3106 lpDragInfo->hWnd = hWnd;
3107 lpDragInfo->hScope = 0;
3108 lpDragInfo->wFlags = wObj;
3109 lpDragInfo->hList = szList; /* near pointer! */
3110 lpDragInfo->hOfStruct = hOfStruct;
3118 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3120 *(lpDragInfo+1) = *lpDragInfo;
3122 lpDragInfo->pt.x = msg.pt.x;
3123 lpDragInfo->pt.y = msg.pt.y;
3125 /* update DRAGINFO struct */
3126 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3128 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3129 hCurrentCursor = hCursor;
3132 hCurrentCursor = hBummer;
3133 lpDragInfo->hScope = 0;
3135 if( hCurrentCursor )
3136 SetCursor(hCurrentCursor);
3138 /* send WM_DRAGLOOP */
3139 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3140 (LPARAM) spDragInfo );
3141 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3142 if( hCurrentWnd != lpDragInfo->hScope )
3145 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3146 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3147 HIWORD(spDragInfo)) );
3148 hCurrentWnd = lpDragInfo->hScope;
3150 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3154 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3156 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3159 ShowCursor( FALSE );
3163 SetCursor( hOldCursor );
3164 if (hDragCursor) DestroyCursor( hDragCursor );
3167 if( hCurrentCursor != hBummer )
3168 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3169 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3172 GlobalFree16(hDragInfo);
3174 return (DWORD)(msg.lParam);
3178 /******************************************************************************
3179 * GetWindowModuleFileNameA (USER32.@)
3181 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3183 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3184 hwnd, lpszFileName, cchFileNameMax);
3188 /******************************************************************************
3189 * GetWindowModuleFileNameW (USER32.@)
3191 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3193 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3194 hwnd, lpszFileName, cchFileNameMax);