Fixes buffer overrun problems with GetDIBits.
[wine.git] / windows / win.c
blobf5ef21457aca0a42d570801a0c0a2f704da61e00
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <string.h>
11 #include "wine/winbase16.h"
12 #include "options.h"
13 #include "class.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "nonclient.h"
24 #include "queue.h"
25 #include "winpos.h"
26 #include "shm_main_blk.h"
27 #include "dde_proc.h"
28 #include "clipboard.h"
29 #include "winproc.h"
30 #include "task.h"
31 #include "thread.h"
32 #include "process.h"
33 #include "debug.h"
34 #include "winerror.h"
35 #include "mdi.h"
36 #include "local.h"
37 #include "desktop.h"
39 #ifndef X_DISPLAY_MISSING
40 extern DESKTOP_DRIVER X11DRV_DESKTOP_Driver;
41 extern WND_DRIVER X11DRV_WND_Driver;
42 #else /* X_DISPLAY_MISSING */
43 extern DESKTOP_DRIVER TTYDRV_DESKTOP_Driver;
44 extern WND_DRIVER TTYDRV_WND_Driver;
45 #endif /* X_DISPLAY_MISSING */
47 /* Desktop window */
48 static WND *pWndDesktop = NULL;
50 static HWND32 hwndSysModal = 0;
52 static WORD wDragWidth = 4;
53 static WORD wDragHeight= 3;
55 /***********************************************************************
56 * WIN_FindWndPtr
58 * Return a pointer to the WND structure corresponding to a HWND.
60 WND * WIN_FindWndPtr( HWND32 hwnd )
62 WND * ptr;
64 if (!hwnd || HIWORD(hwnd)) goto error;
65 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
66 if (ptr->dwMagic != WND_MAGIC) goto error;
67 if (ptr->hwndSelf != hwnd)
69 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
70 hwnd, ptr->hwndSelf );
71 goto error;
73 return ptr;
74 error:
75 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
76 return NULL;
80 /***********************************************************************
81 * WIN_DumpWindow
83 * Dump the content of a window structure to stderr.
85 void WIN_DumpWindow( HWND32 hwnd )
87 WND *ptr;
88 char className[80];
89 int i;
91 if (!(ptr = WIN_FindWndPtr( hwnd )))
93 WARN( win, "%04x is not a window handle\n", hwnd );
94 return;
97 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
98 strcpy( className, "#NULL#" );
100 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
101 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
102 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
103 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
104 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
105 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
106 ptr->next, ptr->child, ptr->parent, ptr->owner,
107 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
108 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
109 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
110 ptr->text ? ptr->text : "",
111 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
112 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
113 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
114 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
116 if (ptr->class->cbWndExtra)
118 DUMP( "extra bytes:" );
119 for (i = 0; i < ptr->class->cbWndExtra; i++)
120 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
121 DUMP( "\n" );
123 DUMP( "\n" );
127 /***********************************************************************
128 * WIN_WalkWindows
130 * Walk the windows tree and print each window on stderr.
132 void WIN_WalkWindows( HWND32 hwnd, int indent )
134 WND *ptr;
135 char className[80];
137 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
138 if (!ptr)
140 WARN( win, "Invalid window handle %04x\n", hwnd );
141 return;
144 if (!indent) /* first time around */
145 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
146 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
147 " Text");
149 while (ptr)
151 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
153 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
155 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
156 (DWORD)ptr, ptr->hmemTaskQ, className,
157 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
158 ptr->text?ptr->text:"<null>");
160 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
161 ptr = ptr->next;
165 /***********************************************************************
166 * WIN_UnlinkWindow
168 * Remove a window from the siblings linked list.
170 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
172 WND *wndPtr, **ppWnd;
174 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
175 ppWnd = &wndPtr->parent->child;
176 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
177 *ppWnd = wndPtr->next;
178 return TRUE;
182 /***********************************************************************
183 * WIN_LinkWindow
185 * Insert a window into the siblings linked list.
186 * The window is inserted after the specified window, which can also
187 * be specified as HWND_TOP or HWND_BOTTOM.
189 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
191 WND *wndPtr, **ppWnd;
193 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
195 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
197 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
198 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
199 while (*ppWnd) ppWnd = &(*ppWnd)->next;
201 else /* Normal case */
203 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
204 if (!afterPtr) return FALSE;
205 ppWnd = &afterPtr->next;
207 wndPtr->next = *ppWnd;
208 *ppWnd = wndPtr;
209 return TRUE;
213 /***********************************************************************
214 * WIN_FindWinToRepaint
216 * Find a window that needs repaint.
218 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
220 HWND32 hwndRet;
221 WND *pWnd = pWndDesktop;
223 /* Note: the desktop window never gets WM_PAINT messages
224 * The real reason why is because Windows DesktopWndProc
225 * does ValidateRgn inside WM_ERASEBKGND handler.
228 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
230 for ( ; pWnd ; pWnd = pWnd->next )
232 if (!(pWnd->dwStyle & WS_VISIBLE))
234 TRACE(win, "skipping window %04x\n",
235 pWnd->hwndSelf );
236 continue;
238 if ((pWnd->hmemTaskQ == hQueue) &&
239 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
241 if (pWnd->child )
242 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
243 return hwndRet;
246 if (!pWnd) return 0;
248 hwndRet = pWnd->hwndSelf;
250 /* look among siblings if we got a transparent window */
251 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
252 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
254 pWnd = pWnd->next;
256 if (pWnd) hwndRet = pWnd->hwndSelf;
257 TRACE(win,"found %04x\n",hwndRet);
258 return hwndRet;
262 /***********************************************************************
263 * WIN_DestroyWindow
265 * Destroy storage associated to a window. "Internals" p.358
267 static WND* WIN_DestroyWindow( WND* wndPtr )
269 HWND32 hwnd = wndPtr->hwndSelf;
270 WND *pWnd;
272 TRACE(win, "%04x\n", wndPtr->hwndSelf );
274 #ifdef CONFIG_IPC
275 if (main_block)
276 DDE_DestroyWindow(wndPtr->hwndSelf);
277 #endif /* CONFIG_IPC */
279 /* free child windows */
281 while ((pWnd = wndPtr->child))
282 wndPtr->child = WIN_DestroyWindow( pWnd );
284 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
286 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
288 WINPOS_CheckInternalPos( wndPtr );
289 if( hwnd == GetCapture32()) ReleaseCapture();
291 /* free resources associated with the window */
293 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
294 PROPERTY_RemoveWindowProps( wndPtr );
296 wndPtr->dwMagic = 0; /* Mark it as invalid */
298 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
300 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
301 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
304 /* toss stale messages from the queue */
306 if( wndPtr->hmemTaskQ )
308 BOOL32 bPostQuit = FALSE;
309 WPARAM32 wQuitParam = 0;
310 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
311 QMSG *qmsg;
313 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
315 if( qmsg->msg.message == WM_QUIT )
317 bPostQuit = TRUE;
318 wQuitParam = qmsg->msg.wParam;
320 QUEUE_RemoveMsg(msgQ, qmsg);
323 QUEUE_Unlock(msgQ);
325 /* repost WM_QUIT to make sure this app exits its message loop */
326 if( bPostQuit ) PostQuitMessage32(wQuitParam);
327 wndPtr->hmemTaskQ = 0;
330 if (!(wndPtr->dwStyle & WS_CHILD))
331 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
332 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
333 wndPtr->pDriver->pDestroyWindow( wndPtr );
334 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
335 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
336 wndPtr->hwndSelf = 0;
337 wndPtr->class->cWindows--;
338 wndPtr->class = NULL;
339 pWnd = wndPtr->next;
341 wndPtr->pDriver->pFinalize(wndPtr);
342 USER_HEAP_FREE( hwnd );
343 return pWnd;
346 /***********************************************************************
347 * WIN_ResetQueueWindows
349 * Reset the queue of all the children of a given window.
350 * Return TRUE if something was done.
352 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
354 BOOL32 ret = FALSE;
356 if (hNew) /* Set a new queue */
358 for (wnd = wnd->child; (wnd); wnd = wnd->next)
360 if (wnd->hmemTaskQ == hQueue)
362 wnd->hmemTaskQ = hNew;
363 ret = TRUE;
365 if (wnd->child)
366 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
369 else /* Queue is being destroyed */
371 while (wnd->child)
373 WND *tmp = wnd->child;
374 ret = FALSE;
375 while (tmp)
377 if (tmp->hmemTaskQ == hQueue)
379 DestroyWindow32( tmp->hwndSelf );
380 ret = TRUE;
381 break;
383 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
384 ret = TRUE;
385 else
386 tmp = tmp->next;
388 if (!ret) break;
391 return ret;
394 /***********************************************************************
395 * WIN_CreateDesktopWindow
397 * Create the desktop window.
399 BOOL32 WIN_CreateDesktopWindow(void)
401 CLASS *class;
402 HWND32 hwndDesktop;
403 DESKTOP *pDesktop;
405 TRACE(win,"Creating desktop window\n");
407 if (!ICONTITLE_Init() ||
408 !WINPOS_CreateInternalPosAtom() ||
409 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
410 return FALSE;
412 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
413 if (!hwndDesktop) return FALSE;
414 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
416 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
417 #ifndef X_DISPLAY_MISSING
418 pDesktop->pDriver = &X11DRV_DESKTOP_Driver;
419 pWndDesktop->pDriver = &X11DRV_WND_Driver;
420 #else /* X_DISPLAY_MISSING */
421 pDesktop->pDriver = &TTYDRV_DESKTOP_Driver;
422 pWndDesktop->pDriver = &TTYDRV_WND_Driver;
423 #endif /* X_DISPLAY_MISSING */
425 pDesktop->pDriver->pInitialize(pDesktop);
426 pWndDesktop->pDriver->pInitialize(pWndDesktop);
428 pWndDesktop->next = NULL;
429 pWndDesktop->child = NULL;
430 pWndDesktop->parent = NULL;
431 pWndDesktop->owner = NULL;
432 pWndDesktop->class = class;
433 pWndDesktop->dwMagic = WND_MAGIC;
434 pWndDesktop->hwndSelf = hwndDesktop;
435 pWndDesktop->hInstance = 0;
436 pWndDesktop->rectWindow.left = 0;
437 pWndDesktop->rectWindow.top = 0;
438 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
439 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
440 pWndDesktop->rectClient = pWndDesktop->rectWindow;
441 pWndDesktop->text = NULL;
442 pWndDesktop->hmemTaskQ = GetFastQueue();
443 pWndDesktop->hrgnUpdate = 0;
444 pWndDesktop->hwndLastActive = hwndDesktop;
445 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
446 WS_CLIPSIBLINGS;
447 pWndDesktop->dwExStyle = 0;
448 pWndDesktop->dce = NULL;
449 pWndDesktop->pVScroll = NULL;
450 pWndDesktop->pHScroll = NULL;
451 pWndDesktop->pProp = NULL;
452 pWndDesktop->wIDmenu = 0;
453 pWndDesktop->helpContext = 0;
454 pWndDesktop->flags = 0;
455 pWndDesktop->hSysMenu = 0;
456 pWndDesktop->userdata = 0;
457 pWndDesktop->winproc = (WNDPROC16)class->winproc;
459 /* FIXME: How do we know if it should be Unicode or not */
460 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
461 return FALSE;
463 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
464 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
465 return TRUE;
469 /***********************************************************************
470 * WIN_CreateWindowEx
472 * Implementation of CreateWindowEx().
474 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
475 BOOL32 win32, BOOL32 unicode )
477 CLASS *classPtr;
478 WND *wndPtr;
479 HWND16 hwnd, hwndLinkAfter;
480 POINT32 maxSize, maxPos, minTrack, maxTrack;
481 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
483 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
484 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
485 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
486 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
487 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
489 /* Find the parent window */
491 if (cs->hwndParent)
493 /* Make sure parent is valid */
494 if (!IsWindow32( cs->hwndParent ))
496 WARN( win, "Bad parent %04x\n", cs->hwndParent );
497 return 0;
499 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
500 WARN( win, "No parent for child window\n" );
501 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
504 /* Find the window class */
505 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
507 char buffer[256];
508 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
509 WARN( win, "Bad class '%s'\n", buffer );
510 return 0;
513 /* Fix the coordinates */
515 if (cs->x == CW_USEDEFAULT32)
517 PDB32 *pdb = PROCESS_Current();
518 if ( !(cs->style & (WS_CHILD | WS_POPUP))
519 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
521 cs->x = pdb->env_db->startup_info->dwX;
522 cs->y = pdb->env_db->startup_info->dwY;
524 else
526 cs->x = 0;
527 cs->y = 0;
530 if (cs->cx == CW_USEDEFAULT32)
532 PDB32 *pdb = PROCESS_Current();
533 if ( !(cs->style & (WS_CHILD | WS_POPUP))
534 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
536 cs->cx = pdb->env_db->startup_info->dwXSize;
537 cs->cy = pdb->env_db->startup_info->dwYSize;
539 else
541 cs->cx = 600; /* FIXME */
542 cs->cy = 400;
546 /* Create the window structure */
548 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
549 - sizeof(wndPtr->wExtra) )))
551 TRACE(win, "out of memory\n" );
552 return 0;
555 /* Fill the window structure */
557 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
558 wndPtr->next = NULL;
559 wndPtr->child = NULL;
561 if ((cs->style & WS_CHILD) && cs->hwndParent)
563 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
564 wndPtr->owner = NULL;
566 else
568 wndPtr->parent = pWndDesktop;
569 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
570 wndPtr->owner = NULL;
571 else
572 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
575 wndPtr->pDriver = wndPtr->parent->pDriver;
576 wndPtr->pDriver->pInitialize(wndPtr);
578 wndPtr->class = classPtr;
579 wndPtr->winproc = classPtr->winproc;
580 wndPtr->dwMagic = WND_MAGIC;
581 wndPtr->hwndSelf = hwnd;
582 wndPtr->hInstance = cs->hInstance;
583 wndPtr->text = NULL;
584 wndPtr->hmemTaskQ = GetFastQueue();
585 wndPtr->hrgnUpdate = 0;
586 wndPtr->hwndLastActive = hwnd;
587 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
588 wndPtr->dwExStyle = cs->dwExStyle;
589 wndPtr->wIDmenu = 0;
590 wndPtr->helpContext = 0;
591 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
592 wndPtr->pVScroll = NULL;
593 wndPtr->pHScroll = NULL;
594 wndPtr->pProp = NULL;
595 wndPtr->userdata = 0;
596 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
597 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
599 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
601 /* Call the WH_CBT hook */
603 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
604 ? HWND_BOTTOM : HWND_TOP;
606 if (HOOK_IsHooked( WH_CBT ))
608 CBT_CREATEWND32A cbtc;
609 LRESULT ret;
611 cbtc.lpcs = cs;
612 cbtc.hwndInsertAfter = hwndLinkAfter;
613 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
614 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
615 if (ret)
617 TRACE(win, "CBT-hook returned 0\n");
618 wndPtr->pDriver->pFinalize(wndPtr);
619 USER_HEAP_FREE( hwnd );
620 return 0;
624 /* Increment class window counter */
626 classPtr->cWindows++;
628 /* Correct the window style */
630 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
632 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
633 wndPtr->flags |= WIN_NEED_SIZE;
635 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
637 /* Get class or window DC if needed */
639 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
640 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
641 else wndPtr->dce = NULL;
643 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
645 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
647 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
648 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
649 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
650 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
651 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
654 if(cs->style & WS_CHILD)
656 if(cs->cx < 0) cs->cx = 0;
657 if(cs->cy < 0) cs->cy = 0;
659 else
661 if (cs->cx <= 0) cs->cx = 1;
662 if (cs->cy <= 0) cs->cy = 1;
665 wndPtr->rectWindow.left = cs->x;
666 wndPtr->rectWindow.top = cs->y;
667 wndPtr->rectWindow.right = cs->x + cs->cx;
668 wndPtr->rectWindow.bottom = cs->y + cs->cy;
669 wndPtr->rectClient = wndPtr->rectWindow;
671 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
672 return FALSE;
674 /* Set the window menu */
676 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
678 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
679 else
681 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
682 if (classPtr->menuNameA)
683 cs->hMenu = HIWORD(classPtr->menuNameA) ?
684 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
685 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
686 #else
687 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
688 if (menuName)
690 if (HIWORD(cs->hInstance))
691 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
692 else
693 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
695 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
697 #endif
700 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
702 /* Send the WM_CREATE message
703 * Perhaps we shouldn't allow width/height changes as well.
704 * See p327 in "Internals".
707 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
709 localSend32 = unicode ? SendMessage32W : SendMessage32A;
710 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
712 /* Insert the window in the linked list */
714 WIN_LinkWindow( hwnd, hwndLinkAfter );
716 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
717 NULL, NULL, 0, &wndPtr->rectClient );
718 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
719 maxPos.y - wndPtr->rectWindow.top);
720 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
722 /* Send the size messages */
724 if (!(wndPtr->flags & WIN_NEED_SIZE))
726 /* send it anyway */
727 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
728 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
729 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
730 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
731 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
732 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
733 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
734 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
735 SendMessage32A( hwnd, WM_MOVE, 0,
736 MAKELONG( wndPtr->rectClient.left,
737 wndPtr->rectClient.top ) );
740 /* Show the window, maximizing or minimizing if needed */
742 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
744 RECT16 newPos;
745 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
746 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
747 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
748 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32())
749 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
750 : SWP_NOZORDER | SWP_FRAMECHANGED;
751 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
752 newPos.right, newPos.bottom, swFlag );
755 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
757 /* Notify the parent window only */
759 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
760 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
761 if( !IsWindow32(hwnd) ) return 0;
764 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
766 /* Call WH_SHELL hook */
768 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
769 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
771 TRACE(win, "created window %04x\n", hwnd);
772 return hwnd;
774 WIN_UnlinkWindow( hwnd );
777 /* Abort window creation */
779 WARN(win, "aborted by WM_xxCREATE!\n");
780 WIN_DestroyWindow( wndPtr );
781 return 0;
785 /***********************************************************************
786 * CreateWindow16 (USER.41)
788 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
789 DWORD style, INT16 x, INT16 y, INT16 width,
790 INT16 height, HWND16 parent, HMENU16 menu,
791 HINSTANCE16 instance, LPVOID data )
793 return CreateWindowEx16( 0, className, windowName, style,
794 x, y, width, height, parent, menu, instance, data );
798 /***********************************************************************
799 * CreateWindowEx16 (USER.452)
801 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
802 LPCSTR windowName, DWORD style, INT16 x,
803 INT16 y, INT16 width, INT16 height,
804 HWND16 parent, HMENU16 menu,
805 HINSTANCE16 instance, LPVOID data )
807 ATOM classAtom;
808 CREATESTRUCT32A cs;
810 /* Find the class atom */
812 if (!(classAtom = GlobalFindAtom32A( className )))
814 fprintf( stderr, "CreateWindowEx16: bad class name " );
815 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
816 else fprintf( stderr, "'%s'\n", className );
817 return 0;
820 /* Fix the coordinates */
822 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
823 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
824 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
825 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
827 /* Create the window */
829 cs.lpCreateParams = data;
830 cs.hInstance = (HINSTANCE32)instance;
831 cs.hMenu = (HMENU32)menu;
832 cs.hwndParent = (HWND32)parent;
833 cs.style = style;
834 cs.lpszName = windowName;
835 cs.lpszClass = className;
836 cs.dwExStyle = exStyle;
837 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
841 /***********************************************************************
842 * CreateWindowEx32A (USER32.83)
844 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
845 LPCSTR windowName, DWORD style, INT32 x,
846 INT32 y, INT32 width, INT32 height,
847 HWND32 parent, HMENU32 menu,
848 HINSTANCE32 instance, LPVOID data )
850 ATOM classAtom;
851 CREATESTRUCT32A cs;
853 if(exStyle & WS_EX_MDICHILD)
854 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
855 /* Find the class atom */
857 if (!(classAtom = GlobalFindAtom32A( className )))
859 fprintf( stderr, "CreateWindowEx32A: bad class name " );
860 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
861 else fprintf( stderr, "'%s'\n", className );
862 return 0;
865 /* Create the window */
867 cs.lpCreateParams = data;
868 cs.hInstance = instance;
869 cs.hMenu = menu;
870 cs.hwndParent = parent;
871 cs.x = x;
872 cs.y = y;
873 cs.cx = width;
874 cs.cy = height;
875 cs.style = style;
876 cs.lpszName = windowName;
877 cs.lpszClass = className;
878 cs.dwExStyle = exStyle;
879 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
883 /***********************************************************************
884 * CreateWindowEx32W (USER32.84)
886 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
887 LPCWSTR windowName, DWORD style, INT32 x,
888 INT32 y, INT32 width, INT32 height,
889 HWND32 parent, HMENU32 menu,
890 HINSTANCE32 instance, LPVOID data )
892 ATOM classAtom;
893 CREATESTRUCT32W cs;
895 if(exStyle & WS_EX_MDICHILD)
896 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
898 /* Find the class atom */
900 if (!(classAtom = GlobalFindAtom32W( className )))
902 if (HIWORD(className))
904 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
905 WARN( win, "Bad class name '%s'\n",cn);
906 HeapFree( GetProcessHeap(), 0, cn );
908 else
909 WARN( win, "Bad class name %p\n", className );
910 return 0;
913 /* Create the window */
915 cs.lpCreateParams = data;
916 cs.hInstance = instance;
917 cs.hMenu = menu;
918 cs.hwndParent = parent;
919 cs.x = x;
920 cs.y = y;
921 cs.cx = width;
922 cs.cy = height;
923 cs.style = style;
924 cs.lpszName = windowName;
925 cs.lpszClass = className;
926 cs.dwExStyle = exStyle;
927 /* Note: we rely on the fact that CREATESTRUCT32A and */
928 /* CREATESTRUCT32W have the same layout. */
929 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
933 /***********************************************************************
934 * WIN_CheckFocus
936 static void WIN_CheckFocus( WND* pWnd )
938 if( GetFocus16() == pWnd->hwndSelf )
939 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
942 /***********************************************************************
943 * WIN_SendDestroyMsg
945 static void WIN_SendDestroyMsg( WND* pWnd )
947 WIN_CheckFocus(pWnd);
949 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
950 CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
952 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
954 if( IsWindow32(pWnd->hwndSelf) )
956 WND* pChild = pWnd->child;
957 while( pChild )
959 WIN_SendDestroyMsg( pChild );
960 pChild = pChild->next;
962 WIN_CheckFocus(pWnd);
964 else
965 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
969 /***********************************************************************
970 * DestroyWindow16 (USER.53)
972 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
974 return DestroyWindow32(hwnd);
978 /***********************************************************************
979 * DestroyWindow32 (USER32.135)
981 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
983 WND * wndPtr;
985 TRACE(win, "(%04x)\n", hwnd);
987 /* Initialization */
989 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
990 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
992 /* Call hooks */
994 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
995 return FALSE;
997 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
999 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1000 /* FIXME: clean up palette - see "Internals" p.352 */
1003 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1004 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1006 /* Notify the parent window only */
1007 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1008 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1009 if( !IsWindow32(hwnd) ) return TRUE;
1012 CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1014 /* Hide the window */
1016 if (wndPtr->dwStyle & WS_VISIBLE)
1018 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1019 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1020 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1021 if (!IsWindow32(hwnd)) return TRUE;
1024 /* Recursively destroy owned windows */
1026 if( !(wndPtr->dwStyle & WS_CHILD) )
1028 /* make sure top menu popup doesn't get destroyed */
1029 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1031 for (;;)
1033 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1034 while (siblingPtr)
1036 if (siblingPtr->owner == wndPtr)
1038 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1039 break;
1040 else
1041 siblingPtr->owner = NULL;
1043 siblingPtr = siblingPtr->next;
1045 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1046 else break;
1049 if( !Options.managed || EVENT_CheckFocus() )
1050 WINPOS_ActivateOtherWindow(wndPtr);
1052 if( wndPtr->owner &&
1053 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1054 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1057 /* Send destroy messages */
1059 WIN_SendDestroyMsg( wndPtr );
1060 if (!IsWindow32(hwnd)) return TRUE;
1062 /* Unlink now so we won't bother with the children later on */
1064 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1066 /* Destroy the window storage */
1068 WIN_DestroyWindow( wndPtr );
1069 return TRUE;
1073 /***********************************************************************
1074 * CloseWindow16 (USER.43)
1076 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1078 return CloseWindow32( hwnd );
1082 /***********************************************************************
1083 * CloseWindow32 (USER32.56)
1085 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1087 WND * wndPtr = WIN_FindWndPtr( hwnd );
1088 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1089 ShowWindow32( hwnd, SW_MINIMIZE );
1090 return TRUE;
1094 /***********************************************************************
1095 * OpenIcon16 (USER.44)
1097 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1099 return OpenIcon32( hwnd );
1103 /***********************************************************************
1104 * OpenIcon32 (USER32.410)
1106 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1108 if (!IsIconic32( hwnd )) return FALSE;
1109 ShowWindow32( hwnd, SW_SHOWNORMAL );
1110 return TRUE;
1114 /***********************************************************************
1115 * WIN_FindWindow
1117 * Implementation of FindWindow() and FindWindowEx().
1119 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1120 LPCSTR title )
1122 WND *pWnd;
1123 CLASS *pClass = NULL;
1125 if (child)
1127 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1128 if (parent)
1130 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1132 else if (pWnd->parent != pWndDesktop) return 0;
1133 pWnd = pWnd->next;
1135 else
1137 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1138 pWnd = pWnd->child;
1140 if (!pWnd) return 0;
1142 /* For a child window, all siblings will have the same hInstance, */
1143 /* so we can look for the class once and for all. */
1145 if (className && (pWnd->dwStyle & WS_CHILD))
1147 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1148 return 0;
1152 for ( ; pWnd; pWnd = pWnd->next)
1154 if (className && !(pWnd->dwStyle & WS_CHILD))
1156 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1157 continue; /* Skip this window */
1160 if (pClass && (pWnd->class != pClass))
1161 continue; /* Not the right class */
1163 /* Now check the title */
1165 if (!title) return pWnd->hwndSelf;
1166 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1168 return 0;
1173 /***********************************************************************
1174 * FindWindow16 (USER.50)
1176 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1178 return FindWindowEx16( 0, 0, className, title );
1182 /***********************************************************************
1183 * FindWindowEx16 (USER.427)
1185 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1186 SEGPTR className, LPCSTR title )
1188 ATOM atom = 0;
1190 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1191 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1192 title ? title : "");
1194 if (className)
1196 /* If the atom doesn't exist, then no class */
1197 /* with this name exists either. */
1198 if (!(atom = GlobalFindAtom16( className ))) return 0;
1200 return WIN_FindWindow( parent, child, atom, title );
1204 /***********************************************************************
1205 * FindWindow32A (USER32.198)
1207 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1209 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1210 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1211 return ret;
1215 /***********************************************************************
1216 * FindWindowEx32A (USER32.199)
1218 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1219 LPCSTR className, LPCSTR title )
1221 ATOM atom = 0;
1223 if (className)
1225 /* If the atom doesn't exist, then no class */
1226 /* with this name exists either. */
1227 if (!(atom = GlobalFindAtom32A( className )))
1229 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1230 return 0;
1233 return WIN_FindWindow( parent, child, atom, title );
1237 /***********************************************************************
1238 * FindWindowEx32W (USER32.200)
1240 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1241 LPCWSTR className, LPCWSTR title )
1243 ATOM atom = 0;
1244 char *buffer;
1245 HWND32 hwnd;
1247 if (className)
1249 /* If the atom doesn't exist, then no class */
1250 /* with this name exists either. */
1251 if (!(atom = GlobalFindAtom32W( className )))
1253 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1254 return 0;
1257 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1258 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1259 HeapFree( GetProcessHeap(), 0, buffer );
1260 return hwnd;
1264 /***********************************************************************
1265 * FindWindow32W (USER32.201)
1267 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1269 return FindWindowEx32W( 0, 0, className, title );
1273 /**********************************************************************
1274 * WIN_GetDesktop
1276 WND *WIN_GetDesktop(void)
1278 return pWndDesktop;
1282 /**********************************************************************
1283 * GetDesktopWindow16 (USER.286)
1285 HWND16 WINAPI GetDesktopWindow16(void)
1287 return (HWND16)pWndDesktop->hwndSelf;
1291 /**********************************************************************
1292 * GetDesktopWindow32 (USER32.232)
1294 HWND32 WINAPI GetDesktopWindow32(void)
1296 return pWndDesktop->hwndSelf;
1300 /**********************************************************************
1301 * GetDesktopHwnd (USER.278)
1303 * Exactly the same thing as GetDesktopWindow(), but not documented.
1304 * Don't ask me why...
1306 HWND16 WINAPI GetDesktopHwnd(void)
1308 return (HWND16)pWndDesktop->hwndSelf;
1312 /*******************************************************************
1313 * EnableWindow16 (USER.34)
1315 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1317 return EnableWindow32( hwnd, enable );
1321 /*******************************************************************
1322 * EnableWindow32 (USER32.172)
1324 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1326 WND *wndPtr;
1328 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1330 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1331 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1333 /* Enable window */
1334 wndPtr->dwStyle &= ~WS_DISABLED;
1335 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1336 return TRUE;
1338 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1340 /* Disable window */
1341 wndPtr->dwStyle |= WS_DISABLED;
1342 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1344 SetFocus32( 0 ); /* A disabled window can't have the focus */
1346 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1348 ReleaseCapture(); /* A disabled window can't capture the mouse */
1350 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1351 return FALSE;
1353 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1357 /***********************************************************************
1358 * IsWindowEnabled16 (USER.35)
1360 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1362 return IsWindowEnabled32(hWnd);
1366 /***********************************************************************
1367 * IsWindowEnabled32 (USER32.349)
1369 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1371 WND * wndPtr;
1373 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1374 return !(wndPtr->dwStyle & WS_DISABLED);
1378 /***********************************************************************
1379 * IsWindowUnicode (USER32.350)
1381 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1383 WND * wndPtr;
1385 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1386 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1390 /**********************************************************************
1391 * GetWindowWord16 (USER.133)
1393 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1395 return GetWindowWord32( hwnd, offset );
1399 /**********************************************************************
1400 * GetWindowWord32 (USER32.314)
1402 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1404 WND * wndPtr = WIN_FindWndPtr( hwnd );
1405 if (!wndPtr) return 0;
1406 if (offset >= 0)
1408 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1410 WARN( win, "Invalid offset %d\n", offset );
1411 return 0;
1413 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1415 switch(offset)
1417 case GWW_ID:
1418 if (HIWORD(wndPtr->wIDmenu))
1419 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1420 wndPtr->wIDmenu);
1421 return (WORD)wndPtr->wIDmenu;
1422 case GWW_HWNDPARENT:
1423 return wndPtr->parent ?
1424 wndPtr->parent->hwndSelf : (
1425 wndPtr->owner ?
1426 wndPtr->owner->hwndSelf :
1428 case GWW_HINSTANCE:
1429 if (HIWORD(wndPtr->hInstance))
1430 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1431 wndPtr->hInstance);
1432 return (WORD)wndPtr->hInstance;
1433 default:
1434 WARN( win, "Invalid offset %d\n", offset );
1435 return 0;
1440 /**********************************************************************
1441 * WIN_GetWindowInstance
1443 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1445 WND * wndPtr = WIN_FindWndPtr( hwnd );
1446 if (!wndPtr) return (HINSTANCE32)0;
1447 return wndPtr->hInstance;
1451 /**********************************************************************
1452 * SetWindowWord16 (USER.134)
1454 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1456 return SetWindowWord32( hwnd, offset, newval );
1460 /**********************************************************************
1461 * SetWindowWord32 (USER32.524)
1463 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1465 WORD *ptr, retval;
1466 WND * wndPtr = WIN_FindWndPtr( hwnd );
1467 if (!wndPtr) return 0;
1468 if (offset >= 0)
1470 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1472 WARN( win, "Invalid offset %d\n", offset );
1473 return 0;
1475 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1477 else switch(offset)
1479 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1480 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1481 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1482 default:
1483 WARN( win, "Invalid offset %d\n", offset );
1484 return 0;
1486 retval = *ptr;
1487 *ptr = newval;
1488 return retval;
1492 /**********************************************************************
1493 * WIN_GetWindowLong
1495 * Helper function for GetWindowLong().
1497 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1499 LONG retval;
1500 WND * wndPtr = WIN_FindWndPtr( hwnd );
1501 if (!wndPtr) return 0;
1502 if (offset >= 0)
1504 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1506 WARN( win, "Invalid offset %d\n", offset );
1507 return 0;
1509 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1510 /* Special case for dialog window procedure */
1511 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1512 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1513 return retval;
1515 switch(offset)
1517 case GWL_USERDATA: return wndPtr->userdata;
1518 case GWL_STYLE: return wndPtr->dwStyle;
1519 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1520 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1521 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1522 type );
1523 case GWL_HWNDPARENT: return wndPtr->parent ?
1524 (HWND32)wndPtr->parent->hwndSelf : 0;
1525 case GWL_HINSTANCE: return wndPtr->hInstance;
1526 default:
1527 WARN( win, "Unknown offset %d\n", offset );
1529 return 0;
1533 /**********************************************************************
1534 * WIN_SetWindowLong
1536 * Helper function for SetWindowLong().
1538 * 0 is the failure code. However, in the case of failure SetLastError
1539 * must be set to distinguish between a 0 return value and a failure.
1541 * FIXME: The error values for SetLastError may not be right. Can
1542 * someone check with the real thing?
1544 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1545 WINDOWPROCTYPE type )
1547 LONG *ptr, retval;
1548 WND * wndPtr = WIN_FindWndPtr( hwnd );
1549 STYLESTRUCT style;
1551 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1553 if (!wndPtr)
1555 /* Is this the right error? */
1556 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1557 return 0;
1560 if (offset >= 0)
1562 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1564 WARN( win, "Invalid offset %d\n", offset );
1566 /* Is this the right error? */
1567 SetLastError( ERROR_OUTOFMEMORY );
1569 return 0;
1571 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1572 /* Special case for dialog window procedure */
1573 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1575 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1576 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1577 type, WIN_PROC_WINDOW );
1578 return retval;
1581 else switch(offset)
1583 case GWL_ID:
1584 ptr = (DWORD*)&wndPtr->wIDmenu;
1585 break;
1586 case GWL_HINSTANCE:
1587 return SetWindowWord32( hwnd, offset, newval );
1588 case GWL_WNDPROC:
1589 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1590 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1591 type, WIN_PROC_WINDOW );
1592 return retval;
1593 case GWL_STYLE:
1594 style.styleOld = wndPtr->dwStyle;
1595 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1596 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1598 if (wndPtr->flags & WIN_ISWIN32)
1599 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1600 wndPtr->dwStyle = style.styleNew;
1601 if (wndPtr->flags & WIN_ISWIN32)
1602 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1603 return style.styleOld;
1605 case GWL_USERDATA:
1606 ptr = &wndPtr->userdata;
1607 break;
1608 case GWL_EXSTYLE:
1609 style.styleOld = wndPtr->dwExStyle;
1610 style.styleNew = newval;
1611 if (wndPtr->flags & WIN_ISWIN32)
1612 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1613 wndPtr->dwExStyle = newval;
1614 if (wndPtr->flags & WIN_ISWIN32)
1615 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1616 return style.styleOld;
1618 default:
1619 WARN( win, "Invalid offset %d\n", offset );
1621 /* Don't think this is right error but it should do */
1622 SetLastError( ERROR_OUTOFMEMORY );
1624 return 0;
1626 retval = *ptr;
1627 *ptr = newval;
1628 return retval;
1632 /**********************************************************************
1633 * GetWindowLong16 (USER.135)
1635 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1637 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1641 /**********************************************************************
1642 * GetWindowLong32A (USER32.305)
1644 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1646 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1650 /**********************************************************************
1651 * GetWindowLong32W (USER32.306)
1653 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1655 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1659 /**********************************************************************
1660 * SetWindowLong16 (USER.136)
1662 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1664 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1668 /**********************************************************************
1669 * SetWindowLong32A (USER32.517)
1671 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1673 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1677 /**********************************************************************
1678 * SetWindowLong32W (USER32.518) Set window attribute
1680 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1681 * value in a window's extra memory.
1683 * The _hwnd_ parameter specifies the window. is the handle to a
1684 * window that has extra memory. The _newval_ parameter contains the
1685 * new attribute or extra memory value. If positive, the _offset_
1686 * parameter is the byte-addressed location in the window's extra
1687 * memory to set. If negative, _offset_ specifies the window
1688 * attribute to set, and should be one of the following values:
1690 * GWL_EXSTYLE The window's extended window style
1692 * GWL_STYLE The window's window style.
1694 * GWL_WNDPROC Pointer to the window's window procedure.
1696 * GWL_HINSTANCE The window's pplication instance handle.
1698 * GWL_ID The window's identifier.
1700 * GWL_USERDATA The window's user-specified data.
1702 * If the window is a dialog box, the _offset_ parameter can be one of
1703 * the following values:
1705 * DWL_DLGPROC The address of the window's dialog box procedure.
1707 * DWL_MSGRESULT The return value of a message
1708 * that the dialog box procedure processed.
1710 * DWL_USER Application specific information.
1712 * RETURNS
1714 * If successful, returns the previous value located at _offset_. Otherwise,
1715 * returns 0.
1717 * NOTES
1719 * Extra memory for a window class is specified by a nonzero cbWndExtra
1720 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1721 * time of class creation.
1723 * Using GWL_WNDPROC to set a new window procedure effectively creates
1724 * a window subclass. Use CallWindowProc() in the new windows procedure
1725 * to pass messages to the superclass's window procedure.
1727 * The user data is reserved for use by the application which created
1728 * the window.
1730 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1731 * instead, call the EnableWindow() function to change the window's
1732 * disabled state.
1734 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1735 * SetParent() instead.
1737 * Win95:
1738 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1739 * it sends WM_STYLECHANGING before changing the settings
1740 * and WM_STYLECHANGED afterwards.
1741 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1743 * BUGS
1745 * GWL_STYLE does not dispatch WM_STYLE... messages.
1747 * CONFORMANCE
1749 * ECMA-234, Win32
1752 LONG WINAPI SetWindowLong32W(
1753 HWND32 hwnd, /* window to alter */
1754 INT32 offset, /* offset, in bytes, of location to alter */
1755 LONG newval /* new value of location */
1757 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1761 /*******************************************************************
1762 * GetWindowText16 (USER.36)
1764 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1766 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1770 /*******************************************************************
1771 * GetWindowText32A (USER32.309)
1773 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1775 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1776 (LPARAM)lpString );
1779 /*******************************************************************
1780 * InternalGetWindowText (USER32.326)
1782 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1784 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1785 return GetWindowText32W(hwnd,lpString,nMaxCount);
1789 /*******************************************************************
1790 * GetWindowText32W (USER32.312)
1792 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1794 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1795 (LPARAM)lpString );
1799 /*******************************************************************
1800 * SetWindowText16 (USER.37)
1802 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1804 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1808 /*******************************************************************
1809 * SetWindowText32A (USER32.521)
1811 BOOL32 WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1813 return (BOOL32)SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1817 /*******************************************************************
1818 * SetWindowText32W (USER32.523)
1820 BOOL32 WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1822 return (BOOL32)SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1826 /*******************************************************************
1827 * GetWindowTextLength16 (USER.38)
1829 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1831 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1835 /*******************************************************************
1836 * GetWindowTextLength32A (USER32.310)
1838 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1840 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1843 /*******************************************************************
1844 * GetWindowTextLength32W (USER32.311)
1846 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1848 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1852 /*******************************************************************
1853 * IsWindow16 (USER.47)
1855 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1857 return IsWindow32( hwnd );
1860 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1862 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1863 HWND16 hwnd = (HWND16)stack[2];
1865 AX_reg(context) = IsWindow32( hwnd );
1866 ES_reg(context) = USER_HeapSel;
1870 /*******************************************************************
1871 * IsWindow32 (USER32.348)
1873 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1875 WND * wndPtr = WIN_FindWndPtr( hwnd );
1876 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1880 /*****************************************************************
1881 * GetParent16 (USER.46)
1883 HWND16 WINAPI GetParent16( HWND16 hwnd )
1885 return (HWND16)GetParent32( hwnd );
1889 /*****************************************************************
1890 * GetParent32 (USER32.278)
1892 HWND32 WINAPI GetParent32( HWND32 hwnd )
1894 WND *wndPtr = WIN_FindWndPtr(hwnd);
1895 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1896 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1897 return wndPtr ? wndPtr->hwndSelf : 0;
1900 /*****************************************************************
1901 * WIN_GetTopParent
1903 * Get the top-level parent for a child window.
1905 WND* WIN_GetTopParentPtr( WND* pWnd )
1907 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1908 return pWnd;
1911 /*****************************************************************
1912 * WIN_GetTopParent
1914 * Get the top-level parent for a child window.
1916 HWND32 WIN_GetTopParent( HWND32 hwnd )
1918 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1919 return wndPtr ? wndPtr->hwndSelf : 0;
1923 /*****************************************************************
1924 * SetParent16 (USER.233)
1926 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1928 return SetParent32( hwndChild, hwndNewParent );
1932 /*****************************************************************
1933 * SetParent32 (USER32.495)
1935 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1937 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1938 DWORD dwStyle = (wndPtr)?(wndPtr->dwStyle):0;
1939 WND *pWndNewParent =
1940 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1941 WND *pWndOldParent;
1943 /* Windows hides the window first, then shows it again
1944 * including the WM_SHOWWINDOW messages and all */
1945 if (dwStyle & WS_VISIBLE)
1946 ShowWindow32( hwndChild, SW_HIDE );
1948 pWndOldParent = (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1950 /* SetParent32 additionally needs to make hwndChild the topmost window
1951 in the x-order and send the expected WM_WINDOWPOSCHANGING and
1952 WM_WINDOWPOSCHANGED notification messages.
1954 SetWindowPos32( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
1955 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
1956 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1957 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
1959 return pWndOldParent?pWndOldParent->hwndSelf:0;
1962 /*******************************************************************
1963 * IsChild16 (USER.48)
1965 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1967 return IsChild32(parent,child);
1971 /*******************************************************************
1972 * IsChild32 (USER32.339)
1974 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1976 WND * wndPtr = WIN_FindWndPtr( child );
1977 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1979 wndPtr = wndPtr->parent;
1980 if (wndPtr->hwndSelf == parent) return TRUE;
1982 return FALSE;
1986 /***********************************************************************
1987 * IsWindowVisible16 (USER.49)
1989 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1991 return IsWindowVisible32(hwnd);
1995 /***********************************************************************
1996 * IsWindowVisible32 (USER32.351)
1998 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
2000 WND *wndPtr = WIN_FindWndPtr( hwnd );
2001 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2003 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
2004 wndPtr = wndPtr->parent;
2006 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2010 /***********************************************************************
2011 * WIN_IsWindowDrawable
2013 * hwnd is drawable when it is visible, all parents are not
2014 * minimized, and it is itself not minimized unless we are
2015 * trying to draw its default class icon.
2017 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
2019 if( (wnd->dwStyle & WS_MINIMIZE &&
2020 icon && wnd->class->hIcon) ||
2021 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2022 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2023 if( wnd->dwStyle & WS_MINIMIZE ||
2024 !(wnd->dwStyle & WS_VISIBLE) ) break;
2025 return (wnd == NULL);
2029 /*******************************************************************
2030 * GetTopWindow16 (USER.229)
2032 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2034 return GetTopWindow32(hwnd);
2038 /*******************************************************************
2039 * GetTopWindow32 (USER.229)
2041 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
2043 WND * wndPtr = WIN_FindWndPtr( hwnd );
2044 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2045 else return 0;
2049 /*******************************************************************
2050 * GetWindow16 (USER.262)
2052 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2054 return GetWindow32( hwnd,rel );
2058 /*******************************************************************
2059 * GetWindow32 (USER32.302)
2061 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2063 WND * wndPtr = WIN_FindWndPtr( hwnd );
2064 if (!wndPtr) return 0;
2065 switch(rel)
2067 case GW_HWNDFIRST:
2068 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2069 else return 0;
2071 case GW_HWNDLAST:
2072 if (!wndPtr->parent) return 0; /* Desktop window */
2073 while (wndPtr->next) wndPtr = wndPtr->next;
2074 return wndPtr->hwndSelf;
2076 case GW_HWNDNEXT:
2077 if (!wndPtr->next) return 0;
2078 return wndPtr->next->hwndSelf;
2080 case GW_HWNDPREV:
2081 if (!wndPtr->parent) return 0; /* Desktop window */
2082 wndPtr = wndPtr->parent->child; /* First sibling */
2083 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2084 while (wndPtr->next)
2086 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2087 wndPtr = wndPtr->next;
2089 return 0;
2091 case GW_OWNER:
2092 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2094 case GW_CHILD:
2095 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2097 return 0;
2101 /*******************************************************************
2102 * GetNextWindow16 (USER.230)
2104 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2106 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2107 return GetWindow16( hwnd, flag );
2110 /*******************************************************************
2111 * ShowOwnedPopups16 (USER.265)
2113 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2115 ShowOwnedPopups32( owner, fShow );
2119 /*******************************************************************
2120 * ShowOwnedPopups32 (USER32.531)
2122 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2124 WND *pWnd = pWndDesktop->child;
2125 while (pWnd)
2127 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2128 (pWnd->dwStyle & WS_POPUP))
2129 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2130 pWnd = pWnd->next;
2132 return TRUE;
2136 /*******************************************************************
2137 * GetLastActivePopup16 (USER.287)
2139 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2141 return GetLastActivePopup32( hwnd );
2144 /*******************************************************************
2145 * GetLastActivePopup32 (USER32.256)
2147 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2149 WND *wndPtr;
2150 wndPtr = WIN_FindWndPtr(hwnd);
2151 if (wndPtr == NULL) return hwnd;
2152 return wndPtr->hwndLastActive;
2156 /*******************************************************************
2157 * WIN_BuildWinArray
2159 * Build an array of pointers to the children of a given window.
2160 * The array must be freed with HeapFree(SystemHeap). Return NULL
2161 * when no windows are found.
2163 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2165 WND **list, **ppWnd;
2166 WND *pWnd;
2167 UINT32 count, skipOwned, skipHidden;
2168 DWORD skipFlags;
2170 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2171 skipOwned = bwaFlags & BWA_SKIPOWNED;
2172 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2173 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2175 /* First count the windows */
2177 if (!wndPtr) wndPtr = pWndDesktop;
2178 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2180 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2181 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2184 if( count )
2186 /* Now build the list of all windows */
2188 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2190 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2192 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2193 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2195 *ppWnd++ = pWnd;
2196 count++;
2199 *ppWnd = NULL;
2201 else count = 0;
2202 } else list = NULL;
2204 if( pTotal ) *pTotal = count;
2205 return list;
2209 /*******************************************************************
2210 * EnumWindows16 (USER.54)
2212 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2214 WND **list, **ppWnd;
2216 /* We have to build a list of all windows first, to avoid */
2217 /* unpleasant side-effects, for instance if the callback */
2218 /* function changes the Z-order of the windows. */
2220 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2222 /* Now call the callback function for every window */
2224 for (ppWnd = list; *ppWnd; ppWnd++)
2226 /* Make sure that the window still exists */
2227 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2228 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2230 HeapFree( SystemHeap, 0, list );
2231 return TRUE;
2235 /*******************************************************************
2236 * EnumWindows32 (USER32.193)
2238 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2240 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2244 /**********************************************************************
2245 * EnumTaskWindows16 (USER.225)
2247 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2248 LPARAM lParam )
2250 WND **list, **ppWnd;
2252 /* This function is the same as EnumWindows(), */
2253 /* except for an added check on the window's task. */
2255 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2257 /* Now call the callback function for every window */
2259 for (ppWnd = list; *ppWnd; ppWnd++)
2261 /* Make sure that the window still exists */
2262 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2263 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2264 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2266 HeapFree( SystemHeap, 0, list );
2267 return TRUE;
2271 /**********************************************************************
2272 * EnumThreadWindows (USER32.190)
2274 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2276 THDB *tdb = THREAD_ID_TO_THDB(id);
2278 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2282 /**********************************************************************
2283 * WIN_EnumChildWindows
2285 * Helper function for EnumChildWindows().
2287 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2288 LPARAM lParam )
2290 WND **childList;
2291 BOOL16 ret = FALSE;
2293 for ( ; *ppWnd; ppWnd++)
2295 /* Make sure that the window still exists */
2296 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2297 /* Build children list first */
2298 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2299 ret = func( (*ppWnd)->hwndSelf, lParam );
2300 if (childList)
2302 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2303 HeapFree( SystemHeap, 0, childList );
2305 if (!ret) return FALSE;
2307 return TRUE;
2311 /**********************************************************************
2312 * EnumChildWindows16 (USER.55)
2314 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2315 LPARAM lParam )
2317 WND **list, *pParent;
2319 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2320 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2321 WIN_EnumChildWindows( list, func, lParam );
2322 HeapFree( SystemHeap, 0, list );
2323 return TRUE;
2327 /**********************************************************************
2328 * EnumChildWindows32 (USER32.178)
2330 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2331 LPARAM lParam )
2333 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2334 lParam );
2338 /*******************************************************************
2339 * AnyPopup16 (USER.52)
2341 BOOL16 WINAPI AnyPopup16(void)
2343 return AnyPopup32();
2347 /*******************************************************************
2348 * AnyPopup32 (USER32.4)
2350 BOOL32 WINAPI AnyPopup32(void)
2352 WND *wndPtr;
2353 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2354 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2355 return FALSE;
2359 /*******************************************************************
2360 * FlashWindow16 (USER.105)
2362 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2364 return FlashWindow32( hWnd, bInvert );
2368 /*******************************************************************
2369 * FlashWindow32 (USER32.202)
2371 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2373 WND *wndPtr = WIN_FindWndPtr(hWnd);
2375 TRACE(win,"%04x\n", hWnd);
2377 if (!wndPtr) return FALSE;
2379 if (wndPtr->dwStyle & WS_MINIMIZE)
2381 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2383 HDC32 hDC = GetDC32(hWnd);
2385 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2386 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2388 ReleaseDC32( hWnd, hDC );
2389 wndPtr->flags |= WIN_NCACTIVATED;
2391 else
2393 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2394 RDW_UPDATENOW | RDW_FRAME, 0 );
2395 wndPtr->flags &= ~WIN_NCACTIVATED;
2397 return TRUE;
2399 else
2401 WPARAM16 wparam;
2402 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2403 else wparam = (hWnd == GetActiveWindow32());
2405 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2406 return wparam;
2411 /*******************************************************************
2412 * SetSysModalWindow16 (USER.188)
2414 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2416 HWND32 hWndOldModal = hwndSysModal;
2417 hwndSysModal = hWnd;
2418 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2419 return hWndOldModal;
2423 /*******************************************************************
2424 * GetSysModalWindow16 (USER.52)
2426 HWND16 WINAPI GetSysModalWindow16(void)
2428 return hwndSysModal;
2432 /*******************************************************************
2433 * GetWindowContextHelpId (USER32.303)
2435 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2437 WND *wnd = WIN_FindWndPtr( hwnd );
2438 if (!wnd) return 0;
2439 return wnd->helpContext;
2443 /*******************************************************************
2444 * SetWindowContextHelpId (USER32.515)
2446 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2448 WND *wnd = WIN_FindWndPtr( hwnd );
2449 if (!wnd) return FALSE;
2450 wnd->helpContext = id;
2451 return TRUE;
2455 /*******************************************************************
2456 * DRAG_QueryUpdate
2458 * recursively find a child that contains spDragInfo->pt point
2459 * and send WM_QUERYDROPOBJECT
2461 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2463 BOOL16 wParam,bResult = 0;
2464 POINT32 pt;
2465 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2466 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2467 RECT32 tempRect;
2469 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2471 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2473 GetWindowRect32(hQueryWnd,&tempRect);
2475 if( !PtInRect32(&tempRect,pt) ||
2476 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2477 return 0;
2479 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2481 tempRect = ptrQueryWnd->rectClient;
2482 if(ptrQueryWnd->dwStyle & WS_CHILD)
2483 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2484 (LPPOINT32)&tempRect, 2 );
2486 if (PtInRect32( &tempRect, pt))
2488 wParam = 0;
2490 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2491 if( ptrWnd->dwStyle & WS_VISIBLE )
2493 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2494 if (PtInRect32( &tempRect, pt )) break;
2497 if(ptrWnd)
2499 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2500 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2501 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2502 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2503 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2506 if(bResult) return bResult;
2508 else wParam = 1;
2510 else wParam = 1;
2512 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2514 ptrDragInfo->hScope = hQueryWnd;
2516 bResult = ( bNoSend )
2517 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2518 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2519 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2520 if( !bResult )
2521 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2523 return bResult;
2527 /*******************************************************************
2528 * DragDetect (USER.465)
2530 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2532 POINT32 pt32;
2533 CONV_POINT16TO32( &pt, &pt32 );
2534 return DragDetect32( hWnd, pt32 );
2537 /*******************************************************************
2538 * DragDetect32 (USER32.151)
2540 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2542 MSG16 msg;
2543 RECT16 rect;
2545 rect.left = pt.x - wDragWidth;
2546 rect.right = pt.x + wDragWidth;
2548 rect.top = pt.y - wDragHeight;
2549 rect.bottom = pt.y + wDragHeight;
2551 SetCapture32(hWnd);
2553 while(1)
2555 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2557 if( msg.message == WM_LBUTTONUP )
2559 ReleaseCapture();
2560 return 0;
2562 if( msg.message == WM_MOUSEMOVE )
2564 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2566 ReleaseCapture();
2567 return 1;
2571 WaitMessage();
2573 return 0;
2576 /******************************************************************************
2577 * DragObject16 (USER.464)
2579 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2580 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2582 MSG16 msg;
2583 LPDRAGINFO lpDragInfo;
2584 SEGPTR spDragInfo;
2585 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2586 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2587 WND *wndPtr = WIN_FindWndPtr(hWnd);
2588 HCURSOR16 hCurrentCursor = 0;
2589 HWND16 hCurrentWnd = 0;
2591 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2592 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2594 if( !lpDragInfo || !spDragInfo ) return 0L;
2596 hBummer = LoadCursor16(0, IDC_BUMMER16);
2598 if( !hBummer || !wndPtr )
2600 GlobalFree16(hDragInfo);
2601 return 0L;
2604 if(hCursor)
2606 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2608 GlobalFree16(hDragInfo);
2609 return 0L;
2612 if( hDragCursor == hCursor ) hDragCursor = 0;
2613 else hCursor = hDragCursor;
2615 hOldCursor = SetCursor32(hDragCursor);
2618 lpDragInfo->hWnd = hWnd;
2619 lpDragInfo->hScope = 0;
2620 lpDragInfo->wFlags = wObj;
2621 lpDragInfo->hList = szList; /* near pointer! */
2622 lpDragInfo->hOfStruct = hOfStruct;
2623 lpDragInfo->l = 0L;
2625 SetCapture32(hWnd);
2626 ShowCursor32( TRUE );
2630 do{ WaitMessage(); }
2631 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2633 *(lpDragInfo+1) = *lpDragInfo;
2635 lpDragInfo->pt = msg.pt;
2637 /* update DRAGINFO struct */
2638 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2640 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2641 hCurrentCursor = hCursor;
2642 else
2644 hCurrentCursor = hBummer;
2645 lpDragInfo->hScope = 0;
2647 if( hCurrentCursor )
2648 SetCursor32(hCurrentCursor);
2650 /* send WM_DRAGLOOP */
2651 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2652 (LPARAM) spDragInfo );
2653 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2654 if( hCurrentWnd != lpDragInfo->hScope )
2656 if( hCurrentWnd )
2657 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2658 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2659 HIWORD(spDragInfo)) );
2660 hCurrentWnd = lpDragInfo->hScope;
2661 if( hCurrentWnd )
2662 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2664 else
2665 if( hCurrentWnd )
2666 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2668 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2670 ReleaseCapture();
2671 ShowCursor32( FALSE );
2673 if( hCursor )
2675 SetCursor32( hOldCursor );
2676 if (hDragCursor) DestroyCursor32( hDragCursor );
2679 if( hCurrentCursor != hBummer )
2680 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2681 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2682 else
2683 msg.lParam = 0;
2684 GlobalFree16(hDragInfo);
2686 return (DWORD)(msg.lParam);