Added missing goto.
[wine.git] / windows / win.c
blobd40e3bfa7dfadbde00282295167b5ae52a3cf53d
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "wine/winbase16.h"
10 #include "options.h"
11 #include "class.h"
12 #include "win.h"
13 #include "heap.h"
14 #include "user.h"
15 #include "dce.h"
16 #include "sysmetrics.h"
17 #include "cursoricon.h"
18 #include "hook.h"
19 #include "menu.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "shm_main_blk.h"
25 #include "dde_proc.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "task.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "debug.h"
32 #include "winerror.h"
33 #include "mdi.h"
34 #include "local.h"
35 #include "desktop.h"
37 /**********************************************************************/
39 WND_DRIVER *WND_Driver = NULL;
41 /* Desktop window */
42 static WND *pWndDesktop = NULL;
44 static HWND hwndSysModal = 0;
46 static WORD wDragWidth = 4;
47 static WORD wDragHeight= 3;
49 /* thread safeness */
50 static CRITICAL_SECTION WIN_CritSection;
52 /***********************************************************************
53 * WIN_LockWnds
55 * Locks access to all WND structures for thread safeness
57 void WIN_LockWnds()
60 This code will be released in the future
61 info : francois@macadamian.com
63 EnterCriticalSection(&WIN_CritSection);
67 /***********************************************************************
68 * WIN_UnlockWnds
70 * Unlocks access to all WND structures
72 void WIN_UnlockWnds()
75 This code will be released in the future
76 info : francois@macadamian.com
78 LeaveCriticalSection(&WIN_CritSection);
81 /***********************************************************************
82 * WIN_SuspendWndsLock
84 * Suspend the lock on WND structures.
85 * Returns the number of locks suspended
87 int WIN_SuspendWndsLock()
89 int isuspendedLocks = 0;
91 /* make sure that the lock is not suspended by different thread than
92 the owning thread */
93 if(WIN_CritSection.OwningThread != GetCurrentThreadId())
95 return 0;
97 /* set the value of isuspendedlock to the actual recursion count
98 of the critical section */
99 isuspendedLocks = WIN_CritSection.RecursionCount;
100 /* set the recursion count of the critical section to 1
101 so the owning thread will be able to leave it */
102 WIN_CritSection.RecursionCount = 1;
103 /* leave critical section*/
104 WIN_UnlockWnds();
106 return isuspendedLocks;
109 /***********************************************************************
110 * WIN_RestoreWndsLock
112 * Restore the suspended locks on WND structures
114 void WIN_RestoreWndsLock(int ipreviousLocks)
116 if(!ipreviousLocks)
118 return;
120 /* restore the lock */
121 WIN_LockWnds();
122 /* set the recursion count of the critical section to the
123 value of suspended locks (given by WIN_SuspendWndsLock())*/
124 WIN_CritSection.RecursionCount = ipreviousLocks;
128 /***********************************************************************
129 * WIN_FindWndPtr
131 * Return a pointer to the WND structure corresponding to a HWND.
133 WND * WIN_FindWndPtr( HWND hwnd )
135 WND * ptr;
137 if (!hwnd || HIWORD(hwnd)) goto error2;
138 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
139 /* Lock all WND structures for thread safeness*/
140 WIN_LockWnds();
141 /*and increment destruction monitoring*/
142 ptr->irefCount++;
144 if (ptr->dwMagic != WND_MAGIC) goto error;
145 if (ptr->hwndSelf != hwnd)
147 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
148 goto error;
150 /* returns a locked pointer */
151 return ptr;
152 error:
153 /* Unlock all WND structures for thread safeness*/
154 WIN_UnlockWnds();
155 /* and decrement destruction monitoring value */
156 ptr->irefCount--;
158 error2:
159 if ( hwnd!=0 )
160 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
161 return NULL;
164 /***********************************************************************
165 * WIN_LockWndPtr
167 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
168 * but by initWndPtr;
169 * Returns the locked initialisation pointer
171 WND *WIN_LockWndPtr(WND *initWndPtr)
173 if(!initWndPtr) return 0;
175 /* Lock all WND structures for thread safeness*/
176 WIN_LockWnds();
177 /*and increment destruction monitoring*/
178 initWndPtr->irefCount++;
180 return initWndPtr;
184 /***********************************************************************
185 * WIN_ReleaseWndPtr
187 * Release the pointer to the WND structure.
189 void WIN_ReleaseWndPtr(WND *wndPtr)
191 if(!wndPtr) return;
193 /*Decrement destruction monitoring value*/
194 wndPtr->irefCount--;
195 /* Check if it's time to release the memory*/
196 /* Check if it's time to release the memory*/
197 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
199 /* Release memory */
200 USER_HEAP_FREE( wndPtr->hwndSelf);
202 else if(wndPtr->irefCount < 0)
204 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
205 TRACE(win,"forgot a Lock on %p somewhere\n",wndPtr);
207 /*unlock all WND structures for thread safeness*/
208 WIN_UnlockWnds();
211 /***********************************************************************
212 * WIN_UpdateWndPtr
214 * Updates the value of oldPtr to newPtr.
216 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
218 WND *tmpWnd = NULL;
220 tmpWnd = WIN_LockWndPtr(newPtr);
221 WIN_ReleaseWndPtr(*oldPtr);
222 *oldPtr = tmpWnd;
226 /***********************************************************************
227 * WIN_DumpWindow
229 * Dump the content of a window structure to stderr.
231 void WIN_DumpWindow( HWND hwnd )
233 WND *ptr;
234 char className[80];
235 int i;
237 if (!(ptr = WIN_FindWndPtr( hwnd )))
239 WARN( win, "%04x is not a window handle\n", hwnd );
240 return;
243 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
244 strcpy( className, "#NULL#" );
246 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
247 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
248 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
249 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
250 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
251 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
252 ptr->next, ptr->child, ptr->parent, ptr->owner,
253 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
254 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
255 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
256 ptr->text ? ptr->text : "",
257 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
258 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
259 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
260 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
262 if (ptr->class->cbWndExtra)
264 DUMP( "extra bytes:" );
265 for (i = 0; i < ptr->class->cbWndExtra; i++)
266 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
267 DUMP( "\n" );
269 DUMP( "\n" );
270 WIN_ReleaseWndPtr(ptr);
274 /***********************************************************************
275 * WIN_WalkWindows
277 * Walk the windows tree and print each window on stderr.
279 void WIN_WalkWindows( HWND hwnd, int indent )
281 WND *ptr;
282 char className[80];
284 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
286 if (!ptr)
288 WARN( win, "Invalid window handle %04x\n", hwnd );
289 return;
292 if (!indent) /* first time around */
293 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
294 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
295 " Text");
297 while (ptr)
299 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
301 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
303 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
304 (DWORD)ptr, ptr->hmemTaskQ, className,
305 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
306 ptr->text?ptr->text:"<null>");
308 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
309 WIN_UpdateWndPtr(&ptr,ptr->next);
315 /***********************************************************************
316 * WIN_UnlinkWindow
318 * Remove a window from the siblings linked list.
320 BOOL WIN_UnlinkWindow( HWND hwnd )
322 WND *wndPtr, **ppWnd;
324 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
325 else if(!wndPtr->parent)
327 WIN_ReleaseWndPtr(wndPtr);
328 return FALSE;
330 ppWnd = &wndPtr->parent->child;
331 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
332 *ppWnd = wndPtr->next;
333 WIN_ReleaseWndPtr(wndPtr);
334 return TRUE;
338 /***********************************************************************
339 * WIN_LinkWindow
341 * Insert a window into the siblings linked list.
342 * The window is inserted after the specified window, which can also
343 * be specified as HWND_TOP or HWND_BOTTOM.
345 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
347 WND *wndPtr, **ppWnd;
349 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
350 else if(!wndPtr->parent)
352 WIN_ReleaseWndPtr(wndPtr);
353 return FALSE;
355 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
357 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
358 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
359 while (*ppWnd) ppWnd = &(*ppWnd)->next;
361 else /* Normal case */
363 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
364 if (!afterPtr)
366 WIN_ReleaseWndPtr(wndPtr);
367 return FALSE;
369 ppWnd = &afterPtr->next;
370 WIN_ReleaseWndPtr(afterPtr);
372 wndPtr->next = *ppWnd;
373 *ppWnd = wndPtr;
374 WIN_ReleaseWndPtr(wndPtr);
375 return TRUE;
379 /***********************************************************************
380 * WIN_FindWinToRepaint
382 * Find a window that needs repaint.
384 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
386 HWND hwndRet;
387 WND *pWnd;
389 /* Note: the desktop window never gets WM_PAINT messages
390 * The real reason why is because Windows DesktopWndProc
391 * does ValidateRgn inside WM_ERASEBKGND handler.
394 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
396 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
398 if (!(pWnd->dwStyle & WS_VISIBLE))
400 TRACE(win, "skipping window %04x\n",
401 pWnd->hwndSelf );
403 else if ((pWnd->hmemTaskQ == hQueue) &&
404 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
405 break;
407 else if (pWnd->child )
408 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
410 WIN_ReleaseWndPtr(pWnd);
411 return hwndRet;
416 if(!pWnd)
418 return 0;
421 hwndRet = pWnd->hwndSelf;
423 /* look among siblings if we got a transparent window */
424 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
425 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
427 WIN_UpdateWndPtr(&pWnd,pWnd->next);
429 if (pWnd)
431 hwndRet = pWnd->hwndSelf;
432 WIN_ReleaseWndPtr(pWnd);
434 TRACE(win,"found %04x\n",hwndRet);
435 return hwndRet;
439 /***********************************************************************
440 * WIN_DestroyWindow
442 * Destroy storage associated to a window. "Internals" p.358
443 * returns a locked wndPtr->next
445 static WND* WIN_DestroyWindow( WND* wndPtr )
447 HWND hwnd = wndPtr->hwndSelf;
448 WND *pWnd;
450 TRACE(win, "%04x\n", wndPtr->hwndSelf );
452 #ifdef CONFIG_IPC
453 if (main_block)
454 DDE_DestroyWindow(wndPtr->hwndSelf);
455 #endif /* CONFIG_IPC */
457 /* free child windows */
458 WIN_LockWndPtr(wndPtr->child);
459 while ((pWnd = wndPtr->child))
461 wndPtr->child = WIN_DestroyWindow( pWnd );
462 WIN_ReleaseWndPtr(pWnd);
466 * Clear the update region to make sure no WM_PAINT messages will be
467 * generated for this window while processing the WM_NCDESTROY.
469 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
471 if (wndPtr->hrgnUpdate > 1)
472 DeleteObject( wndPtr->hrgnUpdate );
474 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
476 wndPtr->hrgnUpdate = 0;
480 * Send the WM_NCDESTROY to the window being destroyed.
482 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
484 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
486 WINPOS_CheckInternalPos( wndPtr );
487 if( hwnd == GetCapture()) ReleaseCapture();
489 /* free resources associated with the window */
491 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
492 PROPERTY_RemoveWindowProps( wndPtr );
494 wndPtr->dwMagic = 0; /* Mark it as invalid */
496 /* toss stale messages from the queue */
498 if( wndPtr->hmemTaskQ )
500 BOOL bPostQuit = FALSE;
501 WPARAM wQuitParam = 0;
502 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
503 QMSG *qmsg;
505 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
507 if( qmsg->msg.message == WM_QUIT )
509 bPostQuit = TRUE;
510 wQuitParam = qmsg->msg.wParam;
512 QUEUE_RemoveMsg(msgQ, qmsg);
515 QUEUE_Unlock(msgQ);
517 /* repost WM_QUIT to make sure this app exits its message loop */
518 if( bPostQuit ) PostQuitMessage(wQuitParam);
519 wndPtr->hmemTaskQ = 0;
522 if (!(wndPtr->dwStyle & WS_CHILD))
523 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
524 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
525 wndPtr->pDriver->pDestroyWindow( wndPtr );
526 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
527 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
528 wndPtr->hwndSelf = 0;
529 wndPtr->class->cWindows--;
530 wndPtr->class = NULL;
532 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
534 wndPtr->pDriver->pFinalize(wndPtr);
536 return pWnd;
539 /***********************************************************************
540 * WIN_ResetQueueWindows
542 * Reset the queue of all the children of a given window.
543 * Return TRUE if something was done.
545 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
547 BOOL ret = FALSE;
549 if (hNew) /* Set a new queue */
551 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
553 if (wnd->hmemTaskQ == hQueue)
555 wnd->hmemTaskQ = hNew;
556 ret = TRUE;
558 if (wnd->child)
560 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
564 else /* Queue is being destroyed */
566 while (wnd->child)
568 WND *tmp = WIN_LockWndPtr(wnd->child);
569 WND *tmp2;
570 ret = FALSE;
571 while (tmp)
573 if (tmp->hmemTaskQ == hQueue)
575 DestroyWindow( tmp->hwndSelf );
576 ret = TRUE;
577 break;
579 tmp2 = WIN_LockWndPtr(tmp->child);
580 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
581 ret = TRUE;
582 else
584 WIN_UpdateWndPtr(&tmp,tmp->next);
586 WIN_ReleaseWndPtr(tmp2);
588 WIN_ReleaseWndPtr(tmp);
589 if (!ret) break;
592 return ret;
595 /***********************************************************************
596 * WIN_CreateDesktopWindow
598 * Create the desktop window.
600 BOOL WIN_CreateDesktopWindow(void)
602 CLASS *class;
603 HWND hwndDesktop;
604 DESKTOP *pDesktop;
606 TRACE(win,"Creating desktop window\n");
609 /* Initialisation of the critical section for thread safeness */
610 InitializeCriticalSection(&WIN_CritSection);
611 MakeCriticalSectionGlobal(&WIN_CritSection);
613 if (!ICONTITLE_Init() ||
614 !WINPOS_CreateInternalPosAtom() ||
615 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
616 return FALSE;
618 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
619 if (!hwndDesktop) return FALSE;
620 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
622 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
623 pDesktop->pDriver = DESKTOP_Driver;
624 pWndDesktop->pDriver = WND_Driver;
626 pDesktop->pDriver->pInitialize(pDesktop);
627 pWndDesktop->pDriver->pInitialize(pWndDesktop);
629 pWndDesktop->next = NULL;
630 pWndDesktop->child = NULL;
631 pWndDesktop->parent = NULL;
632 pWndDesktop->owner = NULL;
633 pWndDesktop->class = class;
634 pWndDesktop->dwMagic = WND_MAGIC;
635 pWndDesktop->hwndSelf = hwndDesktop;
636 pWndDesktop->hInstance = 0;
637 pWndDesktop->rectWindow.left = 0;
638 pWndDesktop->rectWindow.top = 0;
639 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
640 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
641 pWndDesktop->rectClient = pWndDesktop->rectWindow;
642 pWndDesktop->text = NULL;
643 pWndDesktop->hmemTaskQ = GetFastQueue16();
644 pWndDesktop->hrgnUpdate = 0;
645 pWndDesktop->hwndLastActive = hwndDesktop;
646 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
647 WS_CLIPSIBLINGS;
648 pWndDesktop->dwExStyle = 0;
649 pWndDesktop->dce = NULL;
650 pWndDesktop->pVScroll = NULL;
651 pWndDesktop->pHScroll = NULL;
652 pWndDesktop->pProp = NULL;
653 pWndDesktop->wIDmenu = 0;
654 pWndDesktop->helpContext = 0;
655 pWndDesktop->flags = 0;
656 pWndDesktop->hSysMenu = 0;
657 pWndDesktop->userdata = 0;
658 pWndDesktop->winproc = (WNDPROC16)class->winproc;
659 pWndDesktop->irefCount = 0;
661 /* FIXME: How do we know if it should be Unicode or not */
662 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
663 return FALSE;
665 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
666 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
667 return TRUE;
671 /***********************************************************************
672 * WIN_CreateWindowEx
674 * Implementation of CreateWindowEx().
676 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
677 BOOL win32, BOOL unicode )
679 CLASS *classPtr;
680 WND *wndPtr;
681 HWND retvalue;
682 HWND16 hwnd, hwndLinkAfter;
683 POINT maxSize, maxPos, minTrack, maxTrack;
684 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
685 char buffer[256];
687 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
688 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
689 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
690 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
691 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
693 /* Find the parent window */
695 if (cs->hwndParent)
697 /* Make sure parent is valid */
698 if (!IsWindow( cs->hwndParent ))
700 WARN( win, "Bad parent %04x\n", cs->hwndParent );
701 return 0;
703 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
704 WARN( win, "No parent for child window\n" );
705 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
708 /* Find the window class */
709 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
711 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
712 WARN( win, "Bad class '%s'\n", buffer );
713 return 0;
716 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
717 * with an atom as the class name, put some programs expect to have a *REAL* string in
718 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
720 if ( !HIWORD(cs->lpszClass) ) {
721 if (unicode) {
722 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
723 } else {
724 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
726 cs->lpszClass = buffer;
729 /* Fix the coordinates */
731 if (cs->x == CW_USEDEFAULT)
733 PDB *pdb = PROCESS_Current();
734 if ( !(cs->style & (WS_CHILD | WS_POPUP))
735 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
737 cs->x = pdb->env_db->startup_info->dwX;
738 cs->y = pdb->env_db->startup_info->dwY;
740 else
742 cs->x = 0;
743 cs->y = 0;
746 if (cs->cx == CW_USEDEFAULT)
748 PDB *pdb = PROCESS_Current();
749 if ( !(cs->style & (WS_CHILD | WS_POPUP))
750 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
752 cs->cx = pdb->env_db->startup_info->dwXSize;
753 cs->cy = pdb->env_db->startup_info->dwYSize;
755 else
757 cs->cx = 600; /* FIXME */
758 cs->cy = 400;
762 /* Create the window structure */
764 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
765 - sizeof(wndPtr->wExtra) )))
767 TRACE(win, "out of memory\n" );
768 return 0;
771 /* Fill the window structure */
773 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
774 wndPtr->next = NULL;
775 wndPtr->child = NULL;
777 if ((cs->style & WS_CHILD) && cs->hwndParent)
779 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
780 wndPtr->owner = NULL;
781 WIN_ReleaseWndPtr(wndPtr->parent);
783 else
785 wndPtr->parent = pWndDesktop;
786 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
787 wndPtr->owner = NULL;
788 else
790 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
791 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
792 WIN_ReleaseWndPtr(wndPtr->owner);
793 WIN_ReleaseWndPtr(tmpWnd);
797 wndPtr->pDriver = wndPtr->parent->pDriver;
798 wndPtr->pDriver->pInitialize(wndPtr);
800 wndPtr->class = classPtr;
801 wndPtr->winproc = classPtr->winproc;
802 wndPtr->dwMagic = WND_MAGIC;
803 wndPtr->hwndSelf = hwnd;
804 wndPtr->hInstance = cs->hInstance;
805 wndPtr->text = NULL;
806 wndPtr->hmemTaskQ = GetFastQueue16();
807 wndPtr->hrgnUpdate = 0;
808 wndPtr->hwndLastActive = hwnd;
809 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
810 wndPtr->dwExStyle = cs->dwExStyle;
811 wndPtr->wIDmenu = 0;
812 wndPtr->helpContext = 0;
813 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
814 wndPtr->pVScroll = NULL;
815 wndPtr->pHScroll = NULL;
816 wndPtr->pProp = NULL;
817 wndPtr->userdata = 0;
818 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
819 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
820 wndPtr->irefCount = 1;
822 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
824 /* Call the WH_CBT hook */
826 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
827 ? HWND_BOTTOM : HWND_TOP;
829 if (HOOK_IsHooked( WH_CBT ))
831 CBT_CREATEWNDA cbtc;
832 LRESULT ret;
834 cbtc.lpcs = cs;
835 cbtc.hwndInsertAfter = hwndLinkAfter;
836 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
837 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
838 if (ret)
840 TRACE(win, "CBT-hook returned 0\n");
841 wndPtr->pDriver->pFinalize(wndPtr);
842 USER_HEAP_FREE( hwnd );
843 retvalue = 0;
844 goto end;
848 /* Increment class window counter */
850 classPtr->cWindows++;
852 /* Correct the window style */
854 if (!(cs->style & WS_CHILD))
856 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
857 if (!(cs->style & WS_POPUP))
859 wndPtr->dwStyle |= WS_CAPTION;
860 wndPtr->flags |= WIN_NEED_SIZE;
863 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
865 /* Get class or window DC if needed */
867 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
868 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
869 else wndPtr->dce = NULL;
871 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
873 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
875 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
876 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
877 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
878 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
879 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
882 if(cs->style & WS_CHILD)
884 if(cs->cx < 0) cs->cx = 0;
885 if(cs->cy < 0) cs->cy = 0;
887 else
889 if (cs->cx <= 0) cs->cx = 1;
890 if (cs->cy <= 0) cs->cy = 1;
893 wndPtr->rectWindow.left = cs->x;
894 wndPtr->rectWindow.top = cs->y;
895 wndPtr->rectWindow.right = cs->x + cs->cx;
896 wndPtr->rectWindow.bottom = cs->y + cs->cy;
897 wndPtr->rectClient = wndPtr->rectWindow;
899 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
901 retvalue = FALSE;
902 goto end;
905 /* Set the window menu */
907 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
909 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
910 else
912 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
913 if (classPtr->menuNameA)
914 cs->hMenu = HIWORD(classPtr->menuNameA) ?
915 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
916 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
917 #else
918 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
919 if (menuName)
921 if (HIWORD(cs->hInstance))
922 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
923 else
924 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
926 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
928 #endif
931 else wndPtr->wIDmenu = (UINT)cs->hMenu;
933 /* Send the WM_CREATE message
934 * Perhaps we shouldn't allow width/height changes as well.
935 * See p327 in "Internals".
938 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
940 localSend32 = unicode ? SendMessageW : SendMessageA;
941 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
943 /* Insert the window in the linked list */
945 WIN_LinkWindow( hwnd, hwndLinkAfter );
947 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
948 NULL, NULL, 0, &wndPtr->rectClient );
949 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
950 maxPos.y - wndPtr->rectWindow.top);
951 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
953 /* Send the size messages */
955 if (!(wndPtr->flags & WIN_NEED_SIZE))
957 /* send it anyway */
958 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
959 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
960 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
961 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
962 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
963 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
964 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
965 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
966 SendMessageA( hwnd, WM_MOVE, 0,
967 MAKELONG( wndPtr->rectClient.left,
968 wndPtr->rectClient.top ) );
971 /* Show the window, maximizing or minimizing if needed */
973 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
975 RECT16 newPos;
976 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
977 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
978 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
979 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
980 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
981 : SWP_NOZORDER | SWP_FRAMECHANGED;
982 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
983 newPos.right, newPos.bottom, swFlag );
986 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
988 /* Notify the parent window only */
990 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
991 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
992 if( !IsWindow(hwnd) )
994 retvalue = 0;
995 goto end;
999 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
1001 /* Call WH_SHELL hook */
1003 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1004 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1006 TRACE(win, "created window %04x\n", hwnd);
1007 retvalue = hwnd;
1008 goto end;
1010 WIN_UnlinkWindow( hwnd );
1013 /* Abort window creation */
1015 WARN(win, "aborted by WM_xxCREATE!\n");
1016 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1017 retvalue = 0;
1018 end:
1019 WIN_ReleaseWndPtr(wndPtr);
1021 return retvalue;
1025 /***********************************************************************
1026 * CreateWindow16 (USER.41)
1028 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1029 DWORD style, INT16 x, INT16 y, INT16 width,
1030 INT16 height, HWND16 parent, HMENU16 menu,
1031 HINSTANCE16 instance, LPVOID data )
1033 return CreateWindowEx16( 0, className, windowName, style,
1034 x, y, width, height, parent, menu, instance, data );
1038 /***********************************************************************
1039 * CreateWindowEx16 (USER.452)
1041 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1042 LPCSTR windowName, DWORD style, INT16 x,
1043 INT16 y, INT16 width, INT16 height,
1044 HWND16 parent, HMENU16 menu,
1045 HINSTANCE16 instance, LPVOID data )
1047 ATOM classAtom;
1048 CREATESTRUCTA cs;
1050 /* Find the class atom */
1052 if (!(classAtom = GlobalFindAtomA( className )))
1054 fprintf( stderr, "CreateWindowEx16: bad class name " );
1055 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1056 else fprintf( stderr, "'%s'\n", className );
1057 return 0;
1060 /* Fix the coordinates */
1062 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1063 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1064 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1065 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1067 /* Create the window */
1069 cs.lpCreateParams = data;
1070 cs.hInstance = (HINSTANCE)instance;
1071 cs.hMenu = (HMENU)menu;
1072 cs.hwndParent = (HWND)parent;
1073 cs.style = style;
1074 cs.lpszName = windowName;
1075 cs.lpszClass = className;
1076 cs.dwExStyle = exStyle;
1077 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1081 /***********************************************************************
1082 * CreateWindowEx32A (USER32.83)
1084 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1085 LPCSTR windowName, DWORD style, INT x,
1086 INT y, INT width, INT height,
1087 HWND parent, HMENU menu,
1088 HINSTANCE instance, LPVOID data )
1090 ATOM classAtom;
1091 CREATESTRUCTA cs;
1093 if(exStyle & WS_EX_MDICHILD)
1094 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1095 /* Find the class atom */
1097 if (!(classAtom = GlobalFindAtomA( className )))
1099 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1100 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1101 else fprintf( stderr, "'%s'\n", className );
1102 return 0;
1105 /* Create the window */
1107 cs.lpCreateParams = data;
1108 cs.hInstance = instance;
1109 cs.hMenu = menu;
1110 cs.hwndParent = parent;
1111 cs.x = x;
1112 cs.y = y;
1113 cs.cx = width;
1114 cs.cy = height;
1115 cs.style = style;
1116 cs.lpszName = windowName;
1117 cs.lpszClass = className;
1118 cs.dwExStyle = exStyle;
1119 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1123 /***********************************************************************
1124 * CreateWindowEx32W (USER32.84)
1126 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1127 LPCWSTR windowName, DWORD style, INT x,
1128 INT y, INT width, INT height,
1129 HWND parent, HMENU menu,
1130 HINSTANCE instance, LPVOID data )
1132 ATOM classAtom;
1133 CREATESTRUCTW cs;
1135 if(exStyle & WS_EX_MDICHILD)
1136 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1138 /* Find the class atom */
1140 if (!(classAtom = GlobalFindAtomW( className )))
1142 if (HIWORD(className))
1144 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1145 WARN( win, "Bad class name '%s'\n",cn);
1146 HeapFree( GetProcessHeap(), 0, cn );
1148 else
1149 WARN( win, "Bad class name %p\n", className );
1150 return 0;
1153 /* Create the window */
1155 cs.lpCreateParams = data;
1156 cs.hInstance = instance;
1157 cs.hMenu = menu;
1158 cs.hwndParent = parent;
1159 cs.x = x;
1160 cs.y = y;
1161 cs.cx = width;
1162 cs.cy = height;
1163 cs.style = style;
1164 cs.lpszName = windowName;
1165 cs.lpszClass = className;
1166 cs.dwExStyle = exStyle;
1167 /* Note: we rely on the fact that CREATESTRUCT32A and */
1168 /* CREATESTRUCT32W have the same layout. */
1169 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1173 /***********************************************************************
1174 * WIN_CheckFocus
1176 static void WIN_CheckFocus( WND* pWnd )
1178 if( GetFocus16() == pWnd->hwndSelf )
1179 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1182 /***********************************************************************
1183 * WIN_SendDestroyMsg
1185 static void WIN_SendDestroyMsg( WND* pWnd )
1187 WIN_CheckFocus(pWnd);
1189 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1190 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1193 * Send the WM_DESTROY to the window.
1195 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1198 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1199 * make sure that the window still exists when we come back.
1201 if (IsWindow(pWnd->hwndSelf))
1203 HWND* pWndArray = NULL;
1204 WND* pChild = NULL;
1205 int nKidCount = 0;
1208 * Now, if the window has kids, we have to send WM_DESTROY messages
1209 * recursively to it's kids. It seems that those calls can also
1210 * trigger re-entrant calls to DestroyWindow for the kids so we must
1211 * protect against corruption of the list of siblings. We first build
1212 * a list of HWNDs representing all the kids.
1214 pChild = WIN_LockWndPtr(pWnd->child);
1215 while( pChild )
1217 nKidCount++;
1218 WIN_UpdateWndPtr(&pChild,pChild->next);
1222 * If there are no kids, we're done.
1224 if (nKidCount==0)
1225 return;
1227 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1230 * Sanity check
1232 if (pWndArray==NULL)
1233 return;
1236 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1237 * call, our linked list of siblings should be safe.
1239 nKidCount = 0;
1240 pChild = WIN_LockWndPtr(pWnd->child);
1241 while( pChild )
1243 pWndArray[nKidCount] = pChild->hwndSelf;
1244 nKidCount++;
1245 WIN_UpdateWndPtr(&pChild,pChild->next);
1249 * Now that we have a list, go through that list again and send the destroy
1250 * message to those windows. We are using the HWND to retrieve the
1251 * WND pointer so we are effectively checking that all the kid windows are
1252 * still valid before sending the message.
1254 while (nKidCount>0)
1256 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1258 if (pChild!=NULL)
1260 WIN_SendDestroyMsg( pChild );
1261 WIN_ReleaseWndPtr(pChild);
1266 * Cleanup
1268 HeapFree(GetProcessHeap(), 0, pWndArray);
1269 WIN_CheckFocus(pWnd);
1271 else
1272 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1276 /***********************************************************************
1277 * DestroyWindow16 (USER.53)
1279 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1281 return DestroyWindow(hwnd);
1285 /***********************************************************************
1286 * DestroyWindow32 (USER32.135)
1288 BOOL WINAPI DestroyWindow( HWND hwnd )
1290 WND * wndPtr;
1291 BOOL retvalue;
1293 TRACE(win, "(%04x)\n", hwnd);
1295 /* Initialization */
1297 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1298 if (wndPtr == pWndDesktop)
1300 WIN_ReleaseWndPtr(wndPtr);
1301 return FALSE; /* Can't destroy desktop */
1304 /* Call hooks */
1306 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1308 retvalue = FALSE;
1309 goto end;
1312 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1314 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1315 /* FIXME: clean up palette - see "Internals" p.352 */
1318 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1319 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1321 /* Notify the parent window only */
1322 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1323 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1324 if( !IsWindow(hwnd) )
1326 retvalue = TRUE;
1327 goto end;
1331 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1333 /* Hide the window */
1335 if (wndPtr->dwStyle & WS_VISIBLE)
1337 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1338 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1339 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1340 if (!IsWindow(hwnd))
1342 retvalue = TRUE;
1343 goto end;
1347 /* Recursively destroy owned windows */
1349 if( !(wndPtr->dwStyle & WS_CHILD) )
1351 /* make sure top menu popup doesn't get destroyed */
1352 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1354 for (;;)
1356 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1357 while (siblingPtr)
1359 if (siblingPtr->owner == wndPtr)
1361 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1362 break;
1363 else
1364 siblingPtr->owner = NULL;
1366 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1368 if (siblingPtr)
1370 DestroyWindow( siblingPtr->hwndSelf );
1371 WIN_ReleaseWndPtr(siblingPtr);
1373 else break;
1376 if( !Options.managed || EVENT_CheckFocus() )
1377 WINPOS_ActivateOtherWindow(wndPtr);
1379 if( wndPtr->owner &&
1380 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1381 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1384 /* Send destroy messages */
1386 WIN_SendDestroyMsg( wndPtr );
1387 if (!IsWindow(hwnd))
1389 retvalue = TRUE;
1390 goto end;
1393 /* Unlink now so we won't bother with the children later on */
1395 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1397 /* Destroy the window storage */
1399 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1400 retvalue = TRUE;
1401 end:
1402 WIN_ReleaseWndPtr(wndPtr);
1403 return retvalue;
1407 /***********************************************************************
1408 * CloseWindow16 (USER.43)
1410 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1412 return CloseWindow( hwnd );
1416 /***********************************************************************
1417 * CloseWindow32 (USER32.56)
1419 BOOL WINAPI CloseWindow( HWND hwnd )
1421 WND * wndPtr = WIN_FindWndPtr( hwnd );
1422 BOOL retvalue;
1424 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1426 retvalue = FALSE;
1427 goto end;
1429 ShowWindow( hwnd, SW_MINIMIZE );
1430 retvalue = TRUE;
1431 end:
1432 WIN_ReleaseWndPtr(wndPtr);
1433 return retvalue;
1438 /***********************************************************************
1439 * OpenIcon16 (USER.44)
1441 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1443 return OpenIcon( hwnd );
1447 /***********************************************************************
1448 * OpenIcon32 (USER32.410)
1450 BOOL WINAPI OpenIcon( HWND hwnd )
1452 if (!IsIconic( hwnd )) return FALSE;
1453 ShowWindow( hwnd, SW_SHOWNORMAL );
1454 return TRUE;
1458 /***********************************************************************
1459 * WIN_FindWindow
1461 * Implementation of FindWindow() and FindWindowEx().
1463 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1464 LPCSTR title )
1466 WND *pWnd;
1467 HWND retvalue;
1468 CLASS *pClass = NULL;
1470 if (child)
1472 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1473 if (parent)
1475 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1477 retvalue = 0;
1478 goto end;
1481 else if (pWnd->parent != pWndDesktop)
1483 retvalue = 0;
1484 goto end;
1486 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1488 else
1490 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1492 retvalue = 0;
1493 goto end;
1495 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1497 if (!pWnd)
1499 retvalue = 0;
1500 goto end;
1503 /* For a child window, all siblings will have the same hInstance, */
1504 /* so we can look for the class once and for all. */
1506 if (className && (pWnd->dwStyle & WS_CHILD))
1508 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1510 retvalue = 0;
1511 goto end;
1516 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1518 if (className && !(pWnd->dwStyle & WS_CHILD))
1520 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1521 continue; /* Skip this window */
1524 if (pClass && (pWnd->class != pClass))
1525 continue; /* Not the right class */
1527 /* Now check the title */
1529 if (!title)
1531 retvalue = pWnd->hwndSelf;
1532 goto end;
1534 if (pWnd->text && !strcmp( pWnd->text, title ))
1536 retvalue = pWnd->hwndSelf;
1537 goto end;
1540 retvalue = 0;
1541 end:
1542 WIN_ReleaseWndPtr(pWnd);
1543 return retvalue;
1548 /***********************************************************************
1549 * FindWindow16 (USER.50)
1551 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1553 return FindWindowEx16( 0, 0, className, title );
1557 /***********************************************************************
1558 * FindWindowEx16 (USER.427)
1560 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1561 SEGPTR className, LPCSTR title )
1563 ATOM atom = 0;
1565 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1566 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1567 title ? title : "");
1569 if (className)
1571 /* If the atom doesn't exist, then no class */
1572 /* with this name exists either. */
1573 if (!(atom = GlobalFindAtom16( className ))) return 0;
1575 return WIN_FindWindow( parent, child, atom, title );
1579 /***********************************************************************
1580 * FindWindow32A (USER32.198)
1582 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1584 HWND ret = FindWindowExA( 0, 0, className, title );
1585 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1586 return ret;
1590 /***********************************************************************
1591 * FindWindowEx32A (USER32.199)
1593 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1594 LPCSTR className, LPCSTR title )
1596 ATOM atom = 0;
1598 if (className)
1600 /* If the atom doesn't exist, then no class */
1601 /* with this name exists either. */
1602 if (!(atom = GlobalFindAtomA( className )))
1604 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1605 return 0;
1608 return WIN_FindWindow( parent, child, atom, title );
1612 /***********************************************************************
1613 * FindWindowEx32W (USER32.200)
1615 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1616 LPCWSTR className, LPCWSTR title )
1618 ATOM atom = 0;
1619 char *buffer;
1620 HWND hwnd;
1622 if (className)
1624 /* If the atom doesn't exist, then no class */
1625 /* with this name exists either. */
1626 if (!(atom = GlobalFindAtomW( className )))
1628 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1629 return 0;
1632 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1633 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1634 HeapFree( GetProcessHeap(), 0, buffer );
1635 return hwnd;
1639 /***********************************************************************
1640 * FindWindow32W (USER32.201)
1642 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1644 return FindWindowExW( 0, 0, className, title );
1648 /**********************************************************************
1649 * WIN_GetDesktop
1650 * returns a locked pointer
1652 WND *WIN_GetDesktop(void)
1654 return WIN_LockWndPtr(pWndDesktop);
1656 /**********************************************************************
1657 * WIN_ReleaseDesktop
1658 * unlock the desktop pointer
1660 void WIN_ReleaseDesktop(void)
1662 WIN_ReleaseWndPtr(pWndDesktop);
1666 /**********************************************************************
1667 * GetDesktopWindow16 (USER.286)
1669 HWND16 WINAPI GetDesktopWindow16(void)
1671 return (HWND16)pWndDesktop->hwndSelf;
1675 /**********************************************************************
1676 * GetDesktopWindow32 (USER32.232)
1678 HWND WINAPI GetDesktopWindow(void)
1680 return pWndDesktop->hwndSelf;
1684 /**********************************************************************
1685 * GetDesktopHwnd (USER.278)
1687 * Exactly the same thing as GetDesktopWindow(), but not documented.
1688 * Don't ask me why...
1690 HWND16 WINAPI GetDesktopHwnd16(void)
1692 return (HWND16)pWndDesktop->hwndSelf;
1696 /*******************************************************************
1697 * EnableWindow16 (USER.34)
1699 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1701 return EnableWindow( hwnd, enable );
1705 /*******************************************************************
1706 * EnableWindow32 (USER32.172)
1708 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1710 WND *wndPtr;
1711 BOOL retvalue;
1713 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1715 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1716 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1718 /* Enable window */
1719 wndPtr->dwStyle &= ~WS_DISABLED;
1721 if( wndPtr->flags & WIN_NATIVE )
1722 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1724 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1725 retvalue = TRUE;
1726 goto end;
1728 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1730 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1732 /* Disable window */
1733 wndPtr->dwStyle |= WS_DISABLED;
1735 if( wndPtr->flags & WIN_NATIVE )
1736 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1738 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1740 SetFocus( 0 ); /* A disabled window can't have the focus */
1742 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1744 ReleaseCapture(); /* A disabled window can't capture the mouse */
1746 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1747 retvalue = FALSE;
1748 goto end;
1750 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1751 end:
1752 WIN_ReleaseWndPtr(wndPtr);
1753 return retvalue;
1757 /***********************************************************************
1758 * IsWindowEnabled16 (USER.35)
1760 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1762 return IsWindowEnabled(hWnd);
1766 /***********************************************************************
1767 * IsWindowEnabled32 (USER32.349)
1769 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1771 WND * wndPtr;
1772 BOOL retvalue;
1774 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1775 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1776 WIN_ReleaseWndPtr(wndPtr);
1777 return retvalue;
1782 /***********************************************************************
1783 * IsWindowUnicode (USER32.350)
1785 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1787 WND * wndPtr;
1788 BOOL retvalue;
1790 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1791 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1792 WIN_ReleaseWndPtr(wndPtr);
1793 return retvalue;
1797 /**********************************************************************
1798 * GetWindowWord16 (USER.133)
1800 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1802 return GetWindowWord( hwnd, offset );
1806 /**********************************************************************
1807 * GetWindowWord32 (USER32.314)
1809 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1811 WORD retvalue;
1812 WND * wndPtr = WIN_FindWndPtr( hwnd );
1813 if (!wndPtr) return 0;
1814 if (offset >= 0)
1816 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1818 WARN( win, "Invalid offset %d\n", offset );
1819 retvalue = 0;
1820 goto end;
1822 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1823 goto end;
1825 switch(offset)
1827 case GWW_ID:
1828 if (HIWORD(wndPtr->wIDmenu))
1829 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1830 wndPtr->wIDmenu);
1831 retvalue = (WORD)wndPtr->wIDmenu;
1832 goto end;
1833 case GWW_HWNDPARENT:
1834 retvalue = GetParent(hwnd);
1835 goto end;
1836 case GWW_HINSTANCE:
1837 if (HIWORD(wndPtr->hInstance))
1838 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1839 wndPtr->hInstance);
1840 retvalue = (WORD)wndPtr->hInstance;
1841 goto end;
1842 default:
1843 WARN( win, "Invalid offset %d\n", offset );
1844 retvalue = 0;
1845 goto end;
1847 end:
1848 WIN_ReleaseWndPtr(wndPtr);
1849 return retvalue;
1853 /**********************************************************************
1854 * WIN_GetWindowInstance
1856 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1859 WND * wndPtr = WIN_FindWndPtr( hwnd );
1860 if (!wndPtr) return (HINSTANCE)0;
1861 WIN_ReleaseWndPtr(wndPtr);
1862 return wndPtr->hInstance;
1867 /**********************************************************************
1868 * SetWindowWord16 (USER.134)
1870 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1872 return SetWindowWord( hwnd, offset, newval );
1876 /**********************************************************************
1877 * SetWindowWord32 (USER32.524)
1879 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1881 WORD *ptr, retval;
1882 WND * wndPtr = WIN_FindWndPtr( hwnd );
1883 if (!wndPtr) return 0;
1884 if (offset >= 0)
1886 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1888 WARN( win, "Invalid offset %d\n", offset );
1889 retval = 0;
1890 goto end;
1892 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1894 else switch(offset)
1896 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1897 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1898 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1899 goto end;
1900 default:
1901 WARN( win, "Invalid offset %d\n", offset );
1902 retval = 0;
1903 goto end;
1905 retval = *ptr;
1906 *ptr = newval;
1907 end:
1908 WIN_ReleaseWndPtr(wndPtr);
1909 return retval;
1913 /**********************************************************************
1914 * WIN_GetWindowLong
1916 * Helper function for GetWindowLong().
1918 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1920 LONG retvalue;
1921 WND * wndPtr = WIN_FindWndPtr( hwnd );
1922 if (!wndPtr) return 0;
1923 if (offset >= 0)
1925 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1927 WARN( win, "Invalid offset %d\n", offset );
1928 retvalue = 0;
1929 goto end;
1931 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1932 /* Special case for dialog window procedure */
1933 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1935 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1936 goto end;
1938 goto end;
1940 switch(offset)
1942 case GWL_USERDATA: retvalue = wndPtr->userdata;
1943 goto end;
1944 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1945 goto end;
1946 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1947 goto end;
1948 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1949 goto end;
1950 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1951 type );
1952 goto end;
1953 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1954 goto end;
1955 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1956 goto end;
1957 default:
1958 WARN( win, "Unknown offset %d\n", offset );
1960 retvalue = 0;
1961 end:
1962 WIN_ReleaseWndPtr(wndPtr);
1963 return retvalue;
1967 /**********************************************************************
1968 * WIN_SetWindowLong
1970 * Helper function for SetWindowLong().
1972 * 0 is the failure code. However, in the case of failure SetLastError
1973 * must be set to distinguish between a 0 return value and a failure.
1975 * FIXME: The error values for SetLastError may not be right. Can
1976 * someone check with the real thing?
1978 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1979 WINDOWPROCTYPE type )
1981 LONG *ptr, retval;
1982 WND * wndPtr = WIN_FindWndPtr( hwnd );
1983 STYLESTRUCT style;
1985 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1987 if (!wndPtr)
1989 /* Is this the right error? */
1990 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1991 return 0;
1994 if (offset >= 0)
1996 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1998 WARN( win, "Invalid offset %d\n", offset );
2000 /* Is this the right error? */
2001 SetLastError( ERROR_OUTOFMEMORY );
2003 retval = 0;
2004 goto end;
2006 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2007 /* Special case for dialog window procedure */
2008 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2010 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2011 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2012 type, WIN_PROC_WINDOW );
2013 goto end;
2016 else switch(offset)
2018 case GWL_ID:
2019 ptr = (DWORD*)&wndPtr->wIDmenu;
2020 break;
2021 case GWL_HINSTANCE:
2022 retval = SetWindowWord( hwnd, offset, newval );
2023 goto end;
2024 case GWL_WNDPROC:
2025 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2026 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2027 type, WIN_PROC_WINDOW );
2028 goto end;;
2029 case GWL_STYLE:
2030 style.styleOld = wndPtr->dwStyle;
2031 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2032 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2034 if (wndPtr->flags & WIN_ISWIN32)
2035 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2036 wndPtr->dwStyle = style.styleNew;
2037 if (wndPtr->flags & WIN_ISWIN32)
2038 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2039 retval = style.styleOld;
2040 goto end;
2042 case GWL_USERDATA:
2043 ptr = &wndPtr->userdata;
2044 break;
2045 case GWL_EXSTYLE:
2046 style.styleOld = wndPtr->dwExStyle;
2047 style.styleNew = newval;
2048 if (wndPtr->flags & WIN_ISWIN32)
2049 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2050 wndPtr->dwExStyle = newval;
2051 if (wndPtr->flags & WIN_ISWIN32)
2052 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2053 retval = style.styleOld;
2054 goto end;
2056 default:
2057 WARN( win, "Invalid offset %d\n", offset );
2059 /* Don't think this is right error but it should do */
2060 SetLastError( ERROR_OUTOFMEMORY );
2062 retval = 0;
2063 goto end;
2065 retval = *ptr;
2066 *ptr = newval;
2067 end:
2068 WIN_ReleaseWndPtr(wndPtr);
2069 return retval;
2073 /**********************************************************************
2074 * GetWindowLong16 (USER.135)
2076 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2078 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2082 /**********************************************************************
2083 * GetWindowLong32A (USER32.305)
2085 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2087 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2091 /**********************************************************************
2092 * GetWindowLong32W (USER32.306)
2094 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2096 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2100 /**********************************************************************
2101 * SetWindowLong16 (USER.136)
2103 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2105 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2109 /**********************************************************************
2110 * SetWindowLong32A (USER32.517)
2112 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2114 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2118 /**********************************************************************
2119 * SetWindowLong32W (USER32.518) Set window attribute
2121 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2122 * value in a window's extra memory.
2124 * The _hwnd_ parameter specifies the window. is the handle to a
2125 * window that has extra memory. The _newval_ parameter contains the
2126 * new attribute or extra memory value. If positive, the _offset_
2127 * parameter is the byte-addressed location in the window's extra
2128 * memory to set. If negative, _offset_ specifies the window
2129 * attribute to set, and should be one of the following values:
2131 * GWL_EXSTYLE The window's extended window style
2133 * GWL_STYLE The window's window style.
2135 * GWL_WNDPROC Pointer to the window's window procedure.
2137 * GWL_HINSTANCE The window's pplication instance handle.
2139 * GWL_ID The window's identifier.
2141 * GWL_USERDATA The window's user-specified data.
2143 * If the window is a dialog box, the _offset_ parameter can be one of
2144 * the following values:
2146 * DWL_DLGPROC The address of the window's dialog box procedure.
2148 * DWL_MSGRESULT The return value of a message
2149 * that the dialog box procedure processed.
2151 * DWL_USER Application specific information.
2153 * RETURNS
2155 * If successful, returns the previous value located at _offset_. Otherwise,
2156 * returns 0.
2158 * NOTES
2160 * Extra memory for a window class is specified by a nonzero cbWndExtra
2161 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2162 * time of class creation.
2164 * Using GWL_WNDPROC to set a new window procedure effectively creates
2165 * a window subclass. Use CallWindowProc() in the new windows procedure
2166 * to pass messages to the superclass's window procedure.
2168 * The user data is reserved for use by the application which created
2169 * the window.
2171 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2172 * instead, call the EnableWindow() function to change the window's
2173 * disabled state.
2175 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2176 * SetParent() instead.
2178 * Win95:
2179 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2180 * it sends WM_STYLECHANGING before changing the settings
2181 * and WM_STYLECHANGED afterwards.
2182 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2184 * BUGS
2186 * GWL_STYLE does not dispatch WM_STYLE... messages.
2188 * CONFORMANCE
2190 * ECMA-234, Win32
2193 LONG WINAPI SetWindowLongW(
2194 HWND hwnd, /* window to alter */
2195 INT offset, /* offset, in bytes, of location to alter */
2196 LONG newval /* new value of location */
2198 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2202 /*******************************************************************
2203 * GetWindowText16 (USER.36)
2205 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2207 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2211 /*******************************************************************
2212 * GetWindowText32A (USER32.309)
2214 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2216 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2217 (LPARAM)lpString );
2220 /*******************************************************************
2221 * InternalGetWindowText (USER32.326)
2223 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2225 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2226 return GetWindowTextW(hwnd,lpString,nMaxCount);
2230 /*******************************************************************
2231 * GetWindowText32W (USER32.312)
2233 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2235 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2236 (LPARAM)lpString );
2240 /*******************************************************************
2241 * SetWindowText16 (USER.37)
2243 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2245 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2249 /*******************************************************************
2250 * SetWindowText32A (USER32.521)
2252 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2254 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2258 /*******************************************************************
2259 * SetWindowText32W (USER32.523)
2261 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2263 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2267 /*******************************************************************
2268 * GetWindowTextLength16 (USER.38)
2270 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2272 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2276 /*******************************************************************
2277 * GetWindowTextLength32A (USER32.310)
2279 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2281 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2284 /*******************************************************************
2285 * GetWindowTextLength32W (USER32.311)
2287 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2289 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2293 /*******************************************************************
2294 * IsWindow16 (USER.47)
2296 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2298 return IsWindow( hwnd );
2301 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2303 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2304 HWND16 hwnd = (HWND16)stack[2];
2306 AX_reg(context) = IsWindow( hwnd );
2307 ES_reg(context) = USER_HeapSel;
2311 /*******************************************************************
2312 * IsWindow32 (USER32.348)
2314 BOOL WINAPI IsWindow( HWND hwnd )
2316 WND * wndPtr;
2317 BOOL retvalue;
2319 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2320 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2321 WIN_ReleaseWndPtr(wndPtr);
2322 return retvalue;
2327 /*****************************************************************
2328 * GetParent16 (USER.46)
2330 HWND16 WINAPI GetParent16( HWND16 hwnd )
2332 return (HWND16)GetParent( hwnd );
2336 /*****************************************************************
2337 * GetParent32 (USER32.278)
2339 HWND WINAPI GetParent( HWND hwnd )
2341 WND *wndPtr;
2342 HWND retvalue;
2344 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2345 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2347 WIN_ReleaseWndPtr(wndPtr);
2348 return 0;
2350 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2351 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2353 WIN_ReleaseWndPtr(wndPtr);
2354 return retvalue;
2358 /*****************************************************************
2359 * WIN_GetTopParent
2361 * Get the top-level parent for a child window.
2362 * returns a locked pointer
2364 WND* WIN_GetTopParentPtr( WND* pWnd )
2366 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2368 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2370 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2372 return tmpWnd;
2375 /*****************************************************************
2376 * WIN_GetTopParent
2378 * Get the top-level parent for a child window.
2380 HWND WIN_GetTopParent( HWND hwnd )
2382 HWND retvalue;
2383 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2384 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2386 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2387 WIN_ReleaseWndPtr(tmpPtr);
2388 WIN_ReleaseWndPtr(wndPtr);
2389 return retvalue;
2393 /*****************************************************************
2394 * SetParent16 (USER.233)
2396 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2398 return SetParent( hwndChild, hwndNewParent );
2402 /*****************************************************************
2403 * SetParent32 (USER32.495)
2405 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2407 WND *wndPtr;
2408 DWORD dwStyle;
2409 WND *pWndNewParent;
2410 WND *pWndOldParent;
2411 HWND retvalue;
2414 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2416 dwStyle = wndPtr->dwStyle;
2418 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2419 : WIN_LockWndPtr(pWndDesktop);
2421 /* Windows hides the window first, then shows it again
2422 * including the WM_SHOWWINDOW messages and all */
2423 if (dwStyle & WS_VISIBLE)
2424 ShowWindow( hwndChild, SW_HIDE );
2426 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2428 /* SetParent32 additionally needs to make hwndChild the topmost window
2429 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2430 WM_WINDOWPOSCHANGED notification messages.
2432 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2433 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2434 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2435 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2437 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2439 WIN_ReleaseWndPtr(pWndOldParent);
2440 WIN_ReleaseWndPtr(pWndNewParent);
2441 WIN_ReleaseWndPtr(wndPtr);
2443 return retvalue;
2447 /*******************************************************************
2448 * IsChild16 (USER.48)
2450 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2452 return IsChild(parent,child);
2456 /*******************************************************************
2457 * IsChild32 (USER32.339)
2459 BOOL WINAPI IsChild( HWND parent, HWND child )
2461 WND * wndPtr = WIN_FindWndPtr( child );
2462 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2464 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2465 if (wndPtr->hwndSelf == parent)
2467 WIN_ReleaseWndPtr(wndPtr);
2468 return TRUE;
2471 WIN_ReleaseWndPtr(wndPtr);
2472 return FALSE;
2476 /***********************************************************************
2477 * IsWindowVisible16 (USER.49)
2479 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2481 return IsWindowVisible(hwnd);
2485 /***********************************************************************
2486 * IsWindowVisible32 (USER32.351)
2488 BOOL WINAPI IsWindowVisible( HWND hwnd )
2490 BOOL retval;
2491 WND *wndPtr = WIN_FindWndPtr( hwnd );
2492 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2494 if (!(wndPtr->dwStyle & WS_VISIBLE))
2496 WIN_ReleaseWndPtr(wndPtr);
2497 return FALSE;
2499 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2501 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2502 WIN_ReleaseWndPtr(wndPtr);
2503 return retval;
2508 /***********************************************************************
2509 * WIN_IsWindowDrawable
2511 * hwnd is drawable when it is visible, all parents are not
2512 * minimized, and it is itself not minimized unless we are
2513 * trying to draw its default class icon.
2515 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2517 if( (wnd->dwStyle & WS_MINIMIZE &&
2518 icon && wnd->class->hIcon) ||
2519 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2520 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2521 if( wnd->dwStyle & WS_MINIMIZE ||
2522 !(wnd->dwStyle & WS_VISIBLE) ) break;
2523 return (wnd == NULL);
2527 /*******************************************************************
2528 * GetTopWindow16 (USER.229)
2530 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2532 return GetTopWindow(hwnd);
2536 /*******************************************************************
2537 * GetTopWindow32 (USER.229)
2539 HWND WINAPI GetTopWindow( HWND hwnd )
2541 HWND retval;
2542 WND * wndPtr = WIN_FindWndPtr( hwnd );
2543 if (wndPtr && wndPtr->child)
2545 retval = wndPtr->child->hwndSelf;
2547 else retval = 0;
2548 WIN_ReleaseWndPtr(wndPtr);
2549 return retval;
2553 /*******************************************************************
2554 * GetWindow16 (USER.262)
2556 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2558 return GetWindow( hwnd,rel );
2562 /*******************************************************************
2563 * GetWindow32 (USER32.302)
2565 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2567 HWND retval;
2569 WND * wndPtr = WIN_FindWndPtr( hwnd );
2570 if (!wndPtr) return 0;
2571 switch(rel)
2573 case GW_HWNDFIRST:
2574 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2575 else retval = 0;
2576 goto end;
2578 case GW_HWNDLAST:
2579 if (!wndPtr->parent)
2581 retval = 0; /* Desktop window */
2582 goto end;
2584 while (wndPtr->next)
2586 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2588 retval = wndPtr->hwndSelf;
2589 goto end;
2591 case GW_HWNDNEXT:
2592 if (!wndPtr->next) retval = 0;
2593 else retval = wndPtr->next->hwndSelf;
2594 goto end;
2596 case GW_HWNDPREV:
2597 if (!wndPtr->parent)
2599 retval = 0; /* Desktop window */
2600 goto end;
2602 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2603 if (wndPtr->hwndSelf == hwnd)
2605 retval = 0; /* First in list */
2606 goto end;
2608 while (wndPtr->next)
2610 if (wndPtr->next->hwndSelf == hwnd)
2612 retval = wndPtr->hwndSelf;
2613 goto end;
2615 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2617 retval = 0;
2618 goto end;
2620 case GW_OWNER:
2621 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2622 goto end;
2624 case GW_CHILD:
2625 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2626 goto end;
2628 retval = 0;
2629 end:
2630 WIN_ReleaseWndPtr(wndPtr);
2631 return retval;
2635 /*******************************************************************
2636 * GetNextWindow16 (USER.230)
2638 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2640 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2641 return GetWindow16( hwnd, flag );
2644 /*******************************************************************
2645 * ShowOwnedPopups16 (USER.265)
2647 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2649 ShowOwnedPopups( owner, fShow );
2653 /*******************************************************************
2654 * ShowOwnedPopups32 (USER32.531)
2656 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2658 WND *pWnd;
2659 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2660 while (pWnd)
2662 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2663 (pWnd->dwStyle & WS_POPUP))
2664 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2665 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2667 return TRUE;
2671 /*******************************************************************
2672 * GetLastActivePopup16 (USER.287)
2674 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2676 return GetLastActivePopup( hwnd );
2679 /*******************************************************************
2680 * GetLastActivePopup32 (USER32.256)
2682 HWND WINAPI GetLastActivePopup( HWND hwnd )
2684 WND *wndPtr;
2685 HWND retval;
2686 wndPtr = WIN_FindWndPtr(hwnd);
2687 if (!wndPtr) return hwnd;
2688 retval = wndPtr->hwndLastActive;
2689 WIN_ReleaseWndPtr(wndPtr);
2690 return retval;
2694 /*******************************************************************
2695 * WIN_BuildWinArray
2697 * Build an array of pointers to the children of a given window.
2698 * The array must be freed with HeapFree(SystemHeap). Return NULL
2699 * when no windows are found.
2701 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2703 /* Future : this function will lock all windows associated with this array */
2705 WND **list, **ppWnd;
2706 WND *pWnd;
2707 UINT count = 0, skipOwned, skipHidden;
2708 DWORD skipFlags;
2710 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2711 skipOwned = bwaFlags & BWA_SKIPOWNED;
2712 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2713 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2715 /* First count the windows */
2717 if (!wndPtr)
2718 wndPtr = WIN_GetDesktop();
2720 pWnd = WIN_LockWndPtr(wndPtr->child);
2721 while (pWnd)
2723 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2724 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2725 count++;
2726 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2729 if( count )
2731 /* Now build the list of all windows */
2733 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2735 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2737 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2738 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2740 *ppWnd++ = pWnd;
2741 count++;
2744 WIN_ReleaseWndPtr(pWnd);
2745 *ppWnd = NULL;
2747 else count = 0;
2748 } else list = NULL;
2750 if( pTotal ) *pTotal = count;
2751 return list;
2753 /*******************************************************************
2754 * WIN_ReleaseWinArray
2756 void WIN_ReleaseWinArray(WND **wndArray)
2758 /* Future : this function will also unlock all windows associated with wndArray */
2759 HeapFree( SystemHeap, 0, wndArray );
2763 /*******************************************************************
2764 * EnumWindows16 (USER.54)
2766 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2768 WND **list, **ppWnd;
2770 /* We have to build a list of all windows first, to avoid */
2771 /* unpleasant side-effects, for instance if the callback */
2772 /* function changes the Z-order of the windows. */
2774 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2776 WIN_ReleaseDesktop();
2777 return FALSE;
2780 /* Now call the callback function for every window */
2782 for (ppWnd = list; *ppWnd; ppWnd++)
2784 LRESULT lpEnumFuncRetval;
2785 int iWndsLocks = 0;
2786 /* Make sure that the window still exists */
2787 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2789 /* To avoid any deadlocks, all the locks on the windows
2790 structures must be suspended before the control
2791 is passed to the application */
2792 iWndsLocks = WIN_SuspendWndsLock();
2793 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2794 WIN_RestoreWndsLock(iWndsLocks);
2796 if (!lpEnumFuncRetval) break;
2798 WIN_ReleaseWinArray(list);
2799 WIN_ReleaseDesktop();
2800 return TRUE;
2804 /*******************************************************************
2805 * EnumWindows32 (USER32.193)
2807 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2809 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2813 /**********************************************************************
2814 * EnumTaskWindows16 (USER.225)
2816 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2817 LPARAM lParam )
2819 WND **list, **ppWnd;
2821 /* This function is the same as EnumWindows(), */
2822 /* except for an added check on the window's task. */
2824 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2826 WIN_ReleaseDesktop();
2827 return FALSE;
2830 /* Now call the callback function for every window */
2832 for (ppWnd = list; *ppWnd; ppWnd++)
2834 LRESULT funcRetval;
2835 int iWndsLocks = 0;
2836 /* Make sure that the window still exists */
2837 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2838 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2840 /* To avoid any deadlocks, all the locks on the windows
2841 structures must be suspended before the control
2842 is passed to the application */
2843 iWndsLocks = WIN_SuspendWndsLock();
2844 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2845 WIN_RestoreWndsLock(iWndsLocks);
2847 if (!funcRetval) break;
2849 WIN_ReleaseWinArray(list);
2850 WIN_ReleaseDesktop();
2851 return TRUE;
2855 /**********************************************************************
2856 * EnumThreadWindows (USER32.190)
2858 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2860 THDB *tdb = THREAD_IdToTHDB(id);
2862 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2866 /**********************************************************************
2867 * WIN_EnumChildWindows
2869 * Helper function for EnumChildWindows().
2871 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2872 LPARAM lParam )
2874 WND **childList;
2875 BOOL16 ret = FALSE;
2877 for ( ; *ppWnd; ppWnd++)
2879 int iWndsLocks = 0;
2881 /* Make sure that the window still exists */
2882 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2883 /* Build children list first */
2884 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2886 /* To avoid any deadlocks, all the locks on the windows
2887 structures must be suspended before the control
2888 is passed to the application */
2889 iWndsLocks = WIN_SuspendWndsLock();
2890 ret = func( (*ppWnd)->hwndSelf, lParam );
2891 WIN_RestoreWndsLock(iWndsLocks);
2893 if (childList)
2895 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2896 WIN_ReleaseWinArray(childList);
2898 if (!ret) return FALSE;
2900 return TRUE;
2904 /**********************************************************************
2905 * EnumChildWindows16 (USER.55)
2907 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2908 LPARAM lParam )
2910 WND **list, *pParent;
2912 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2913 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2915 WIN_ReleaseWndPtr(pParent);
2916 return FALSE;
2918 WIN_EnumChildWindows( list, func, lParam );
2919 WIN_ReleaseWinArray(list);
2920 WIN_ReleaseWndPtr(pParent);
2921 return TRUE;
2925 /**********************************************************************
2926 * EnumChildWindows32 (USER32.178)
2928 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2929 LPARAM lParam )
2931 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2932 lParam );
2936 /*******************************************************************
2937 * AnyPopup16 (USER.52)
2939 BOOL16 WINAPI AnyPopup16(void)
2941 return AnyPopup();
2945 /*******************************************************************
2946 * AnyPopup32 (USER32.4)
2948 BOOL WINAPI AnyPopup(void)
2950 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2951 BOOL retvalue;
2953 while (wndPtr)
2955 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2957 retvalue = TRUE;
2958 goto end;
2960 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2962 retvalue = FALSE;
2963 end:
2964 WIN_ReleaseWndPtr(wndPtr);
2965 return retvalue;
2969 /*******************************************************************
2970 * FlashWindow16 (USER.105)
2972 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2974 return FlashWindow( hWnd, bInvert );
2978 /*******************************************************************
2979 * FlashWindow32 (USER32.202)
2981 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2983 WND *wndPtr = WIN_FindWndPtr(hWnd);
2985 TRACE(win,"%04x\n", hWnd);
2987 if (!wndPtr) return FALSE;
2989 if (wndPtr->dwStyle & WS_MINIMIZE)
2991 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2993 HDC hDC = GetDC(hWnd);
2995 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2996 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2998 ReleaseDC( hWnd, hDC );
2999 wndPtr->flags |= WIN_NCACTIVATED;
3001 else
3003 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3004 RDW_UPDATENOW | RDW_FRAME, 0 );
3005 wndPtr->flags &= ~WIN_NCACTIVATED;
3007 WIN_ReleaseWndPtr(wndPtr);
3008 return TRUE;
3010 else
3012 WPARAM16 wparam;
3013 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3014 else wparam = (hWnd == GetActiveWindow());
3016 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3017 WIN_ReleaseWndPtr(wndPtr);
3018 return wparam;
3023 /*******************************************************************
3024 * SetSysModalWindow16 (USER.188)
3026 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3028 HWND hWndOldModal = hwndSysModal;
3029 hwndSysModal = hWnd;
3030 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3031 return hWndOldModal;
3035 /*******************************************************************
3036 * GetSysModalWindow16 (USER.52)
3038 HWND16 WINAPI GetSysModalWindow16(void)
3040 return hwndSysModal;
3044 /*******************************************************************
3045 * GetWindowContextHelpId (USER32.303)
3047 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3049 DWORD retval;
3050 WND *wnd = WIN_FindWndPtr( hwnd );
3051 if (!wnd) return 0;
3052 retval = wnd->helpContext;
3053 WIN_ReleaseWndPtr(wnd);
3054 return retval;
3058 /*******************************************************************
3059 * SetWindowContextHelpId (USER32.515)
3061 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3063 WND *wnd = WIN_FindWndPtr( hwnd );
3064 if (!wnd) return FALSE;
3065 wnd->helpContext = id;
3066 WIN_ReleaseWndPtr(wnd);
3067 return TRUE;
3071 /*******************************************************************
3072 * DRAG_QueryUpdate
3074 * recursively find a child that contains spDragInfo->pt point
3075 * and send WM_QUERYDROPOBJECT
3077 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3079 BOOL16 wParam,bResult = 0;
3080 POINT pt;
3081 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3082 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3083 RECT tempRect;
3085 if( !ptrQueryWnd || !ptrDragInfo )
3087 WIN_ReleaseWndPtr(ptrQueryWnd);
3088 return 0;
3091 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3093 GetWindowRect(hQueryWnd,&tempRect);
3095 if( !PtInRect(&tempRect,pt) ||
3096 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3098 WIN_ReleaseWndPtr(ptrQueryWnd);
3099 return 0;
3102 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3104 tempRect = ptrQueryWnd->rectClient;
3105 if(ptrQueryWnd->dwStyle & WS_CHILD)
3106 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3107 (LPPOINT)&tempRect, 2 );
3109 if (PtInRect( &tempRect, pt))
3111 wParam = 0;
3113 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3115 if( ptrWnd->dwStyle & WS_VISIBLE )
3117 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3118 if (PtInRect( &tempRect, pt )) break;
3122 if(ptrWnd)
3124 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
3125 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3126 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3127 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3128 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3130 WIN_ReleaseWndPtr(ptrWnd);
3133 if(bResult)
3135 WIN_ReleaseWndPtr(ptrQueryWnd);
3136 return bResult;
3139 else wParam = 1;
3141 else wParam = 1;
3143 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3145 ptrDragInfo->hScope = hQueryWnd;
3147 bResult = ( bNoSend )
3148 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3149 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3150 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3151 if( !bResult )
3152 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3154 WIN_ReleaseWndPtr(ptrQueryWnd);
3155 return bResult;
3159 /*******************************************************************
3160 * DragDetect (USER.465)
3162 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3164 POINT pt32;
3165 CONV_POINT16TO32( &pt, &pt32 );
3166 return DragDetect( hWnd, pt32 );
3169 /*******************************************************************
3170 * DragDetect32 (USER32.151)
3172 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3174 MSG16 msg;
3175 RECT16 rect;
3177 rect.left = pt.x - wDragWidth;
3178 rect.right = pt.x + wDragWidth;
3180 rect.top = pt.y - wDragHeight;
3181 rect.bottom = pt.y + wDragHeight;
3183 SetCapture(hWnd);
3185 while(1)
3187 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3189 if( msg.message == WM_LBUTTONUP )
3191 ReleaseCapture();
3192 return 0;
3194 if( msg.message == WM_MOUSEMOVE )
3196 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3198 ReleaseCapture();
3199 return 1;
3203 WaitMessage();
3205 return 0;
3208 /******************************************************************************
3209 * DragObject16 (USER.464)
3211 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3212 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3214 MSG16 msg;
3215 LPDRAGINFO lpDragInfo;
3216 SEGPTR spDragInfo;
3217 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3218 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3219 WND *wndPtr = WIN_FindWndPtr(hWnd);
3220 HCURSOR16 hCurrentCursor = 0;
3221 HWND16 hCurrentWnd = 0;
3223 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3224 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3226 if( !lpDragInfo || !spDragInfo )
3228 WIN_ReleaseWndPtr(wndPtr);
3229 return 0L;
3232 hBummer = LoadCursor16(0, IDC_BUMMER16);
3234 if( !hBummer || !wndPtr )
3236 GlobalFree16(hDragInfo);
3237 WIN_ReleaseWndPtr(wndPtr);
3238 return 0L;
3241 if(hCursor)
3243 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3245 GlobalFree16(hDragInfo);
3246 WIN_ReleaseWndPtr(wndPtr);
3247 return 0L;
3250 if( hDragCursor == hCursor ) hDragCursor = 0;
3251 else hCursor = hDragCursor;
3253 hOldCursor = SetCursor(hDragCursor);
3256 lpDragInfo->hWnd = hWnd;
3257 lpDragInfo->hScope = 0;
3258 lpDragInfo->wFlags = wObj;
3259 lpDragInfo->hList = szList; /* near pointer! */
3260 lpDragInfo->hOfStruct = hOfStruct;
3261 lpDragInfo->l = 0L;
3263 SetCapture(hWnd);
3264 ShowCursor( TRUE );
3268 do{ WaitMessage(); }
3269 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3271 *(lpDragInfo+1) = *lpDragInfo;
3273 lpDragInfo->pt = msg.pt;
3275 /* update DRAGINFO struct */
3276 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
3278 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3279 hCurrentCursor = hCursor;
3280 else
3282 hCurrentCursor = hBummer;
3283 lpDragInfo->hScope = 0;
3285 if( hCurrentCursor )
3286 SetCursor(hCurrentCursor);
3288 /* send WM_DRAGLOOP */
3289 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3290 (LPARAM) spDragInfo );
3291 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3292 if( hCurrentWnd != lpDragInfo->hScope )
3294 if( hCurrentWnd )
3295 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3296 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3297 HIWORD(spDragInfo)) );
3298 hCurrentWnd = lpDragInfo->hScope;
3299 if( hCurrentWnd )
3300 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3302 else
3303 if( hCurrentWnd )
3304 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3306 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3308 ReleaseCapture();
3309 ShowCursor( FALSE );
3311 if( hCursor )
3313 SetCursor( hOldCursor );
3314 if (hDragCursor) DestroyCursor( hDragCursor );
3317 if( hCurrentCursor != hBummer )
3318 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3319 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3320 else
3321 msg.lParam = 0;
3322 GlobalFree16(hDragInfo);
3323 WIN_ReleaseWndPtr(wndPtr);
3325 return (DWORD)(msg.lParam);