Implemented SHCreateShellFolderViewEx.
[wine.git] / windows / win.c
blob2b2edf8585f12ab710284e3ce11d7a18b9e31582
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 "wine/winuser16.h"
11 #include "options.h"
12 #include "class.h"
13 #include "win.h"
14 #include "heap.h"
15 #include "user.h"
16 #include "dce.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 "clipboard.h"
25 #include "winproc.h"
26 #include "task.h"
27 #include "thread.h"
28 #include "process.h"
29 #include "winerror.h"
30 #include "mdi.h"
31 #include "local.h"
32 #include "desktop.h"
33 #include "syslevel.h"
34 #include "stackframe.h"
35 #include "debugtools.h"
37 DECLARE_DEBUG_CHANNEL(msg)
38 DECLARE_DEBUG_CHANNEL(win)
40 /**********************************************************************/
42 WND_DRIVER *WND_Driver = NULL;
44 /* Desktop window */
45 static WND *pWndDesktop = NULL;
47 static HWND hwndSysModal = 0;
49 static WORD wDragWidth = 4;
50 static WORD wDragHeight= 3;
52 /* thread safeness */
53 static SYSLEVEL WIN_SysLevel;
55 /***********************************************************************
56 * WIN_Init
57 */
58 void WIN_Init( void )
60 /* Initialisation of the critical section for thread safeness */
61 _CreateSysLevel( &WIN_SysLevel, 2 );
64 /***********************************************************************
65 * WIN_LockWnds
67 * Locks access to all WND structures for thread safeness
69 void WIN_LockWnds( void )
71 _EnterSysLevel( &WIN_SysLevel );
74 /***********************************************************************
75 * WIN_UnlockWnds
77 * Unlocks access to all WND structures
79 void WIN_UnlockWnds( void )
81 _LeaveSysLevel( &WIN_SysLevel );
84 /***********************************************************************
85 * WIN_SuspendWndsLock
87 * Suspend the lock on WND structures.
88 * Returns the number of locks suspended
90 int WIN_SuspendWndsLock( void )
92 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
93 int count = isuspendedLocks;
95 while ( count-- > 0 )
96 _LeaveSysLevel( &WIN_SysLevel );
98 return isuspendedLocks;
101 /***********************************************************************
102 * WIN_RestoreWndsLock
104 * Restore the suspended locks on WND structures
106 void WIN_RestoreWndsLock( int ipreviousLocks )
108 while ( ipreviousLocks-- > 0 )
109 _EnterSysLevel( &WIN_SysLevel );
112 /***********************************************************************
113 * WIN_FindWndPtr
115 * Return a pointer to the WND structure corresponding to a HWND.
117 WND * WIN_FindWndPtr( HWND hwnd )
119 WND * ptr;
121 if (!hwnd || HIWORD(hwnd)) goto error2;
122 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
123 /* Lock all WND structures for thread safeness*/
124 WIN_LockWnds();
125 /*and increment destruction monitoring*/
126 ptr->irefCount++;
128 if (ptr->dwMagic != WND_MAGIC) goto error;
129 if (ptr->hwndSelf != hwnd)
131 ERR_(win)("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
132 goto error;
134 /* returns a locked pointer */
135 return ptr;
136 error:
137 /* Unlock all WND structures for thread safeness*/
138 WIN_UnlockWnds();
139 /* and decrement destruction monitoring value */
140 ptr->irefCount--;
142 error2:
143 if ( hwnd!=0 )
144 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
145 return NULL;
148 /***********************************************************************
149 * WIN_LockWndPtr
151 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
152 * but by initWndPtr;
153 * Returns the locked initialisation pointer
155 WND *WIN_LockWndPtr(WND *initWndPtr)
157 if(!initWndPtr) return 0;
159 /* Lock all WND structures for thread safeness*/
160 WIN_LockWnds();
161 /*and increment destruction monitoring*/
162 initWndPtr->irefCount++;
164 return initWndPtr;
168 /***********************************************************************
169 * WIN_ReleaseWndPtr
171 * Release the pointer to the WND structure.
173 void WIN_ReleaseWndPtr(WND *wndPtr)
175 if(!wndPtr) return;
177 /*Decrement destruction monitoring value*/
178 wndPtr->irefCount--;
179 /* Check if it's time to release the memory*/
180 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
182 /* Release memory */
183 USER_HEAP_FREE( wndPtr->hwndSelf);
184 wndPtr->hwndSelf = 0;
186 else if(wndPtr->irefCount < 0)
188 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
189 ERR_(win)("forgot a Lock on %p somewhere\n",wndPtr);
191 /*unlock all WND structures for thread safeness*/
192 WIN_UnlockWnds();
195 /***********************************************************************
196 * WIN_UpdateWndPtr
198 * Updates the value of oldPtr to newPtr.
200 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
202 WND *tmpWnd = NULL;
204 tmpWnd = WIN_LockWndPtr(newPtr);
205 WIN_ReleaseWndPtr(*oldPtr);
206 *oldPtr = tmpWnd;
210 /***********************************************************************
211 * WIN_DumpWindow
213 * Dump the content of a window structure to stderr.
215 void WIN_DumpWindow( HWND hwnd )
217 WND *ptr;
218 char className[80];
219 int i;
221 if (!(ptr = WIN_FindWndPtr( hwnd )))
223 WARN_(win)("%04x is not a window handle\n", hwnd );
224 return;
227 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
228 strcpy( className, "#NULL#" );
230 TRACE_(win)("Window %04x (%p):\n", hwnd, ptr );
231 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
232 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
233 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
234 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
235 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
236 ptr->next, ptr->child, ptr->parent, ptr->owner,
237 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
238 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
239 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
240 ptr->text ? ptr->text : "",
241 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
242 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
243 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
244 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
246 if (ptr->class->cbWndExtra)
248 DPRINTF( "extra bytes:" );
249 for (i = 0; i < ptr->class->cbWndExtra; i++)
250 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
251 DPRINTF( "\n" );
253 DPRINTF( "\n" );
254 WIN_ReleaseWndPtr(ptr);
258 /***********************************************************************
259 * WIN_WalkWindows
261 * Walk the windows tree and print each window on stderr.
263 void WIN_WalkWindows( HWND hwnd, int indent )
265 WND *ptr;
266 char className[80];
268 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
270 if (!ptr)
272 WARN_(win)("Invalid window handle %04x\n", hwnd );
273 return;
276 if (!indent) /* first time around */
277 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
278 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
279 " Text");
281 while (ptr)
283 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
285 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
287 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
288 (DWORD)ptr, ptr->hmemTaskQ, className,
289 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
290 ptr->text?ptr->text:"<null>");
292 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
293 WIN_UpdateWndPtr(&ptr,ptr->next);
299 /***********************************************************************
300 * WIN_UnlinkWindow
302 * Remove a window from the siblings linked list.
304 BOOL WIN_UnlinkWindow( HWND hwnd )
306 WND *wndPtr, **ppWnd;
307 BOOL ret = FALSE;
309 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
310 else if(!wndPtr->parent)
312 WIN_ReleaseWndPtr(wndPtr);
313 return FALSE;
316 ppWnd = &wndPtr->parent->child;
317 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
318 if (*ppWnd)
320 *ppWnd = wndPtr->next;
321 ret = TRUE;
323 WIN_ReleaseWndPtr(wndPtr);
324 return ret;
328 /***********************************************************************
329 * WIN_LinkWindow
331 * Insert a window into the siblings linked list.
332 * The window is inserted after the specified window, which can also
333 * be specified as HWND_TOP or HWND_BOTTOM.
335 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
337 WND *wndPtr, **ppWnd;
339 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
340 else if(!wndPtr->parent)
342 WIN_ReleaseWndPtr(wndPtr);
343 return FALSE;
345 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
347 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
348 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
349 while (*ppWnd) ppWnd = &(*ppWnd)->next;
351 else /* Normal case */
353 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
354 if (!afterPtr)
356 WIN_ReleaseWndPtr(wndPtr);
357 return FALSE;
359 ppWnd = &afterPtr->next;
360 WIN_ReleaseWndPtr(afterPtr);
362 wndPtr->next = *ppWnd;
363 *ppWnd = wndPtr;
364 WIN_ReleaseWndPtr(wndPtr);
365 return TRUE;
369 /***********************************************************************
370 * WIN_FindWinToRepaint
372 * Find a window that needs repaint.
374 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
376 HWND hwndRet;
377 WND *pWnd;
379 /* Note: the desktop window never gets WM_PAINT messages
380 * The real reason why is because Windows DesktopWndProc
381 * does ValidateRgn inside WM_ERASEBKGND handler.
384 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
386 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
388 if (!(pWnd->dwStyle & WS_VISIBLE))
390 TRACE_(win)("skipping window %04x\n",
391 pWnd->hwndSelf );
393 else if ((pWnd->hmemTaskQ == hQueue) &&
394 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
395 break;
397 else if (pWnd->child )
398 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
400 WIN_ReleaseWndPtr(pWnd);
401 return hwndRet;
406 if(!pWnd)
408 return 0;
411 hwndRet = pWnd->hwndSelf;
413 /* look among siblings if we got a transparent window */
414 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
415 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
417 WIN_UpdateWndPtr(&pWnd,pWnd->next);
419 if (pWnd)
421 hwndRet = pWnd->hwndSelf;
422 WIN_ReleaseWndPtr(pWnd);
424 TRACE_(win)("found %04x\n",hwndRet);
425 return hwndRet;
429 /***********************************************************************
430 * WIN_DestroyWindow
432 * Destroy storage associated to a window. "Internals" p.358
433 * returns a locked wndPtr->next
435 static WND* WIN_DestroyWindow( WND* wndPtr )
437 HWND hwnd = wndPtr->hwndSelf;
438 WND *pWnd;
440 TRACE_(win)("%04x\n", wndPtr->hwndSelf );
442 /* free child windows */
443 WIN_LockWndPtr(wndPtr->child);
444 while ((pWnd = wndPtr->child))
446 wndPtr->child = WIN_DestroyWindow( pWnd );
447 WIN_ReleaseWndPtr(pWnd);
451 * Clear the update region to make sure no WM_PAINT messages will be
452 * generated for this window while processing the WM_NCDESTROY.
454 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
456 if (wndPtr->hrgnUpdate > 1)
457 DeleteObject( wndPtr->hrgnUpdate );
459 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
461 wndPtr->hrgnUpdate = 0;
465 * Send the WM_NCDESTROY to the window being destroyed.
467 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
469 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
471 WINPOS_CheckInternalPos( wndPtr );
472 if( hwnd == GetCapture()) ReleaseCapture();
474 /* free resources associated with the window */
476 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
477 PROPERTY_RemoveWindowProps( wndPtr );
479 wndPtr->dwMagic = 0; /* Mark it as invalid */
481 /* toss stale messages from the queue */
483 if( wndPtr->hmemTaskQ )
485 BOOL bPostQuit = FALSE;
486 WPARAM wQuitParam = 0;
487 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
488 QMSG *qmsg;
490 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
492 if( qmsg->msg.message == WM_QUIT )
494 bPostQuit = TRUE;
495 wQuitParam = qmsg->msg.wParam;
497 QUEUE_RemoveMsg(msgQ, qmsg);
500 QUEUE_Unlock(msgQ);
502 /* repost WM_QUIT to make sure this app exits its message loop */
503 if( bPostQuit ) PostQuitMessage(wQuitParam);
504 wndPtr->hmemTaskQ = 0;
507 if (!(wndPtr->dwStyle & WS_CHILD))
508 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
509 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
510 wndPtr->pDriver->pDestroyWindow( wndPtr );
511 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
512 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
513 wndPtr->class->cWindows--;
514 wndPtr->class = NULL;
516 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
518 wndPtr->pDriver->pFinalize(wndPtr);
520 return pWnd;
523 /***********************************************************************
524 * WIN_ResetQueueWindows
526 * Reset the queue of all the children of a given window.
527 * Return TRUE if something was done.
529 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
531 BOOL ret = FALSE;
533 if (hNew) /* Set a new queue */
535 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
537 if (wnd->hmemTaskQ == hQueue)
539 wnd->hmemTaskQ = hNew;
540 ret = TRUE;
542 if (wnd->child)
544 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
548 else /* Queue is being destroyed */
550 while (wnd->child)
552 WND *tmp = WIN_LockWndPtr(wnd->child);
553 WND *tmp2;
554 ret = FALSE;
555 while (tmp)
557 if (tmp->hmemTaskQ == hQueue)
559 DestroyWindow( tmp->hwndSelf );
560 ret = TRUE;
561 break;
563 tmp2 = WIN_LockWndPtr(tmp->child);
564 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
565 ret = TRUE;
566 else
568 WIN_UpdateWndPtr(&tmp,tmp->next);
570 WIN_ReleaseWndPtr(tmp2);
572 WIN_ReleaseWndPtr(tmp);
573 if (!ret) break;
576 return ret;
579 /***********************************************************************
580 * WIN_CreateDesktopWindow
582 * Create the desktop window.
584 BOOL WIN_CreateDesktopWindow(void)
586 CLASS *class;
587 HWND hwndDesktop;
588 DESKTOP *pDesktop;
590 TRACE_(win)("Creating desktop window\n");
593 if (!ICONTITLE_Init() ||
594 !WINPOS_CreateInternalPosAtom() ||
595 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
596 return FALSE;
598 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
599 if (!hwndDesktop) return FALSE;
600 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
602 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
603 pDesktop->pDriver = DESKTOP_Driver;
604 pWndDesktop->pDriver = WND_Driver;
606 pDesktop->pDriver->pInitialize(pDesktop);
607 pWndDesktop->pDriver->pInitialize(pWndDesktop);
609 pWndDesktop->next = NULL;
610 pWndDesktop->child = NULL;
611 pWndDesktop->parent = NULL;
612 pWndDesktop->owner = NULL;
613 pWndDesktop->class = class;
614 pWndDesktop->dwMagic = WND_MAGIC;
615 pWndDesktop->hwndSelf = hwndDesktop;
616 pWndDesktop->hInstance = 0;
617 pWndDesktop->rectWindow.left = 0;
618 pWndDesktop->rectWindow.top = 0;
619 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
620 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
621 pWndDesktop->rectClient = pWndDesktop->rectWindow;
622 pWndDesktop->text = NULL;
623 pWndDesktop->hmemTaskQ = GetFastQueue16();
624 pWndDesktop->hrgnUpdate = 0;
625 pWndDesktop->hwndLastActive = hwndDesktop;
626 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
627 WS_CLIPSIBLINGS;
628 pWndDesktop->dwExStyle = 0;
629 pWndDesktop->dce = NULL;
630 pWndDesktop->pVScroll = NULL;
631 pWndDesktop->pHScroll = NULL;
632 pWndDesktop->pProp = NULL;
633 pWndDesktop->wIDmenu = 0;
634 pWndDesktop->helpContext = 0;
635 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
636 pWndDesktop->hSysMenu = 0;
637 pWndDesktop->userdata = 0;
638 pWndDesktop->winproc = (WNDPROC16)class->winproc;
639 pWndDesktop->irefCount = 0;
641 /* FIXME: How do we know if it should be Unicode or not */
642 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
643 return FALSE;
645 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
646 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
647 return TRUE;
651 /***********************************************************************
652 * WIN_CreateWindowEx
654 * Implementation of CreateWindowEx().
656 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
657 BOOL win32, BOOL unicode )
659 INT sw = SW_SHOW;
660 CLASS *classPtr;
661 WND *wndPtr;
662 HWND retvalue;
663 HWND16 hwnd, hwndLinkAfter;
664 POINT maxSize, maxPos, minTrack, maxTrack;
665 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
666 char buffer[256];
668 TRACE_(win)("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
669 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
670 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
671 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
672 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
674 /* Find the parent window */
676 if (cs->hwndParent)
678 /* Make sure parent is valid */
679 if (!IsWindow( cs->hwndParent ))
681 WARN_(win)("Bad parent %04x\n", cs->hwndParent );
682 return 0;
684 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
685 WARN_(win)("No parent for child window\n" );
686 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
689 /* Find the window class */
690 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
692 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
693 WARN_(win)("Bad class '%s'\n", buffer );
694 return 0;
697 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
698 * with an atom as the class name, put some programs expect to have a *REAL* string in
699 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
701 if ( !HIWORD(cs->lpszClass) ) {
702 if (unicode) {
703 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
704 } else {
705 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
707 cs->lpszClass = buffer;
710 /* Fix the coordinates */
712 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
714 PDB *pdb = PROCESS_Current();
716 /* Never believe Microsoft's documentation... CreateWindowEx doc says
717 * that if an overlapped window is created with WS_VISIBLE style bit
718 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
719 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
720 * reveals that
722 * 1) not only if checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
723 * 2) it does not ignore the y parameter as the docs claim; instead, it
724 * uses it as second parameter to ShowWindow() unless y is either
725 * CW_USEDEFAULT or CW_USEDEFAULT16.
727 * The fact that we didn't do 2) caused bogus windows pop up when wine
728 * was running apps that were using this obscure feature. Example -
729 * calc.exe that comes with Win98 (only Win98, it's different from
730 * the one that comes with Win95 and NT)
732 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
734 /* We have saved cs->y, now we can trash it */
735 if ( !(cs->style & (WS_CHILD | WS_POPUP))
736 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
738 cs->x = pdb->env_db->startup_info->dwX;
739 cs->y = pdb->env_db->startup_info->dwY;
741 else
743 cs->x = 0;
744 cs->y = 0;
747 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
749 PDB *pdb = PROCESS_Current();
750 if ( !(cs->style & (WS_CHILD | WS_POPUP))
751 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
753 cs->cx = pdb->env_db->startup_info->dwXSize;
754 cs->cy = pdb->env_db->startup_info->dwYSize;
756 else
758 cs->cx = 600; /* FIXME */
759 cs->cy = 400;
763 /* Create the window structure */
765 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
766 - sizeof(wndPtr->wExtra) )))
768 TRACE_(win)("out of memory\n" );
769 return 0;
772 /* Fill the window structure */
774 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
775 wndPtr->next = NULL;
776 wndPtr->child = NULL;
778 if ((cs->style & WS_CHILD) && cs->hwndParent)
780 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
781 wndPtr->owner = NULL;
782 WIN_ReleaseWndPtr(wndPtr->parent);
784 else
786 wndPtr->parent = pWndDesktop;
787 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
788 wndPtr->owner = NULL;
789 else
791 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
792 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
793 WIN_ReleaseWndPtr(wndPtr->owner);
794 WIN_ReleaseWndPtr(tmpWnd);
799 wndPtr->pDriver = wndPtr->parent->pDriver;
800 wndPtr->pDriver->pInitialize(wndPtr);
802 wndPtr->class = classPtr;
803 wndPtr->winproc = classPtr->winproc;
804 wndPtr->dwMagic = WND_MAGIC;
805 wndPtr->hwndSelf = hwnd;
806 wndPtr->hInstance = cs->hInstance;
807 wndPtr->text = NULL;
808 wndPtr->hmemTaskQ = GetFastQueue16();
809 wndPtr->hrgnUpdate = 0;
810 wndPtr->hwndLastActive = hwnd;
811 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
812 wndPtr->dwExStyle = cs->dwExStyle;
813 wndPtr->wIDmenu = 0;
814 wndPtr->helpContext = 0;
815 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
816 wndPtr->pVScroll = NULL;
817 wndPtr->pHScroll = NULL;
818 wndPtr->pProp = NULL;
819 wndPtr->userdata = 0;
820 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
821 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
822 wndPtr->irefCount = 1;
824 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
826 /* Call the WH_CBT hook */
828 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
829 ? HWND_BOTTOM : HWND_TOP;
831 if (HOOK_IsHooked( WH_CBT ))
833 CBT_CREATEWNDA cbtc;
834 LRESULT ret;
836 cbtc.lpcs = cs;
837 cbtc.hwndInsertAfter = hwndLinkAfter;
838 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
839 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
840 if (ret)
842 TRACE_(win)("CBT-hook returned 0\n");
843 wndPtr->pDriver->pFinalize(wndPtr);
844 USER_HEAP_FREE( hwnd );
845 retvalue = 0;
846 goto end;
850 /* Increment class window counter */
852 classPtr->cWindows++;
854 /* Correct the window style */
856 if (!(cs->style & WS_CHILD))
858 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
859 if (!(cs->style & WS_POPUP))
861 wndPtr->dwStyle |= WS_CAPTION;
862 wndPtr->flags |= WIN_NEED_SIZE;
865 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
867 /* Get class or window DC if needed */
869 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
870 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
871 else wndPtr->dce = NULL;
873 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
875 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
877 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
878 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
879 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
880 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
881 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
884 if(cs->style & WS_CHILD)
886 if(cs->cx < 0) cs->cx = 0;
887 if(cs->cy < 0) cs->cy = 0;
889 else
891 if (cs->cx <= 0) cs->cx = 1;
892 if (cs->cy <= 0) cs->cy = 1;
895 wndPtr->rectWindow.left = cs->x;
896 wndPtr->rectWindow.top = cs->y;
897 wndPtr->rectWindow.right = cs->x + cs->cx;
898 wndPtr->rectWindow.bottom = cs->y + cs->cy;
899 wndPtr->rectClient = wndPtr->rectWindow;
901 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
903 retvalue = FALSE;
904 goto end;
907 /* Set the window menu */
909 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
911 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
912 else
914 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
915 if (classPtr->menuNameA)
916 cs->hMenu = HIWORD(classPtr->menuNameA) ?
917 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
918 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
919 #else
920 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
921 if (menuName)
923 if (HIWORD(cs->hInstance))
924 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
925 else
926 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
928 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
930 #endif
933 else wndPtr->wIDmenu = (UINT)cs->hMenu;
935 /* Send the WM_CREATE message
936 * Perhaps we shouldn't allow width/height changes as well.
937 * See p327 in "Internals".
940 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
942 localSend32 = unicode ? SendMessageW : SendMessageA;
943 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
945 /* Insert the window in the linked list */
947 WIN_LinkWindow( hwnd, hwndLinkAfter );
949 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
950 NULL, NULL, 0, &wndPtr->rectClient );
951 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
952 maxPos.y - wndPtr->rectWindow.top);
953 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
955 /* Send the size messages */
957 if (!(wndPtr->flags & WIN_NEED_SIZE))
959 /* send it anyway */
960 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
961 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
962 WARN_(win)("sending bogus WM_SIZE message 0x%08lx\n",
963 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
964 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
965 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
966 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
967 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
968 SendMessageA( hwnd, WM_MOVE, 0,
969 MAKELONG( wndPtr->rectClient.left,
970 wndPtr->rectClient.top ) );
973 /* Show the window, maximizing or minimizing if needed */
975 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
977 RECT16 newPos;
978 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
979 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
980 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
981 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
982 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
983 : SWP_NOZORDER | SWP_FRAMECHANGED;
984 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
985 newPos.right, newPos.bottom, swFlag );
988 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
990 /* Notify the parent window only */
992 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
993 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
994 if( !IsWindow(hwnd) )
996 retvalue = 0;
997 goto end;
1001 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1003 /* Call WH_SHELL hook */
1005 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1006 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1008 TRACE_(win)("created window %04x\n", hwnd);
1009 retvalue = hwnd;
1010 goto end;
1012 WIN_UnlinkWindow( hwnd );
1015 /* Abort window creation */
1017 WARN_(win)("aborted by WM_xxCREATE!\n");
1018 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1019 retvalue = 0;
1020 end:
1021 WIN_ReleaseWndPtr(wndPtr);
1023 return retvalue;
1027 /***********************************************************************
1028 * CreateWindow16 (USER.41)
1030 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1031 DWORD style, INT16 x, INT16 y, INT16 width,
1032 INT16 height, HWND16 parent, HMENU16 menu,
1033 HINSTANCE16 instance, LPVOID data )
1035 return CreateWindowEx16( 0, className, windowName, style,
1036 x, y, width, height, parent, menu, instance, data );
1040 /***********************************************************************
1041 * CreateWindowEx16 (USER.452)
1043 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1044 LPCSTR windowName, DWORD style, INT16 x,
1045 INT16 y, INT16 width, INT16 height,
1046 HWND16 parent, HMENU16 menu,
1047 HINSTANCE16 instance, LPVOID data )
1049 ATOM classAtom;
1050 CREATESTRUCTA cs;
1052 /* Find the class atom */
1054 if (!(classAtom = GlobalFindAtomA( className )))
1056 fprintf( stderr, "CreateWindowEx16: bad class name " );
1057 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1058 else fprintf( stderr, "'%s'\n", className );
1059 return 0;
1062 /* Fix the coordinates */
1064 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1065 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1066 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1067 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1069 /* Create the window */
1071 cs.lpCreateParams = data;
1072 cs.hInstance = (HINSTANCE)instance;
1073 cs.hMenu = (HMENU)menu;
1074 cs.hwndParent = (HWND)parent;
1075 cs.style = style;
1076 cs.lpszName = windowName;
1077 cs.lpszClass = className;
1078 cs.dwExStyle = exStyle;
1079 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1083 /***********************************************************************
1084 * CreateWindowEx32A (USER32.83)
1086 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1087 LPCSTR windowName, DWORD style, INT x,
1088 INT y, INT width, INT height,
1089 HWND parent, HMENU menu,
1090 HINSTANCE instance, LPVOID data )
1092 ATOM classAtom;
1093 CREATESTRUCTA cs;
1095 if(exStyle & WS_EX_MDICHILD)
1096 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1097 /* Find the class atom */
1099 if (!(classAtom = GlobalFindAtomA( className )))
1101 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1102 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1103 else fprintf( stderr, "'%s'\n", className );
1104 return 0;
1107 /* Create the window */
1109 cs.lpCreateParams = data;
1110 cs.hInstance = instance;
1111 cs.hMenu = menu;
1112 cs.hwndParent = parent;
1113 cs.x = x;
1114 cs.y = y;
1115 cs.cx = width;
1116 cs.cy = height;
1117 cs.style = style;
1118 cs.lpszName = windowName;
1119 cs.lpszClass = className;
1120 cs.dwExStyle = exStyle;
1121 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1125 /***********************************************************************
1126 * CreateWindowEx32W (USER32.84)
1128 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1129 LPCWSTR windowName, DWORD style, INT x,
1130 INT y, INT width, INT height,
1131 HWND parent, HMENU menu,
1132 HINSTANCE instance, LPVOID data )
1134 ATOM classAtom;
1135 CREATESTRUCTW cs;
1137 if(exStyle & WS_EX_MDICHILD)
1138 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1140 /* Find the class atom */
1142 if (!(classAtom = GlobalFindAtomW( className )))
1144 if (HIWORD(className))
1146 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1147 WARN_(win)("Bad class name '%s'\n",cn);
1148 HeapFree( GetProcessHeap(), 0, cn );
1150 else
1151 WARN_(win)("Bad class name %p\n", className );
1152 return 0;
1155 /* Create the window */
1157 cs.lpCreateParams = data;
1158 cs.hInstance = instance;
1159 cs.hMenu = menu;
1160 cs.hwndParent = parent;
1161 cs.x = x;
1162 cs.y = y;
1163 cs.cx = width;
1164 cs.cy = height;
1165 cs.style = style;
1166 cs.lpszName = windowName;
1167 cs.lpszClass = className;
1168 cs.dwExStyle = exStyle;
1169 /* Note: we rely on the fact that CREATESTRUCT32A and */
1170 /* CREATESTRUCT32W have the same layout. */
1171 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1175 /***********************************************************************
1176 * WIN_CheckFocus
1178 static void WIN_CheckFocus( WND* pWnd )
1180 if( GetFocus16() == pWnd->hwndSelf )
1181 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1184 /***********************************************************************
1185 * WIN_SendDestroyMsg
1187 static void WIN_SendDestroyMsg( WND* pWnd )
1189 WIN_CheckFocus(pWnd);
1191 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1192 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1195 * Send the WM_DESTROY to the window.
1197 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1200 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1201 * make sure that the window still exists when we come back.
1203 if (IsWindow(pWnd->hwndSelf))
1205 HWND* pWndArray = NULL;
1206 WND* pChild = NULL;
1207 int nKidCount = 0;
1210 * Now, if the window has kids, we have to send WM_DESTROY messages
1211 * recursively to it's kids. It seems that those calls can also
1212 * trigger re-entrant calls to DestroyWindow for the kids so we must
1213 * protect against corruption of the list of siblings. We first build
1214 * a list of HWNDs representing all the kids.
1216 pChild = WIN_LockWndPtr(pWnd->child);
1217 while( pChild )
1219 nKidCount++;
1220 WIN_UpdateWndPtr(&pChild,pChild->next);
1224 * If there are no kids, we're done.
1226 if (nKidCount==0)
1227 return;
1229 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1232 * Sanity check
1234 if (pWndArray==NULL)
1235 return;
1238 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1239 * call, our linked list of siblings should be safe.
1241 nKidCount = 0;
1242 pChild = WIN_LockWndPtr(pWnd->child);
1243 while( pChild )
1245 pWndArray[nKidCount] = pChild->hwndSelf;
1246 nKidCount++;
1247 WIN_UpdateWndPtr(&pChild,pChild->next);
1251 * Now that we have a list, go through that list again and send the destroy
1252 * message to those windows. We are using the HWND to retrieve the
1253 * WND pointer so we are effectively checking that all the kid windows are
1254 * still valid before sending the message.
1256 while (nKidCount>0)
1258 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1260 if (pChild!=NULL)
1262 WIN_SendDestroyMsg( pChild );
1263 WIN_ReleaseWndPtr(pChild);
1268 * Cleanup
1270 HeapFree(GetProcessHeap(), 0, pWndArray);
1271 WIN_CheckFocus(pWnd);
1273 else
1274 WARN_(win)("\tdestroyed itself while in WM_DESTROY!\n");
1278 /***********************************************************************
1279 * DestroyWindow16 (USER.53)
1281 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1283 return DestroyWindow(hwnd);
1287 /***********************************************************************
1288 * DestroyWindow32 (USER32.135)
1290 BOOL WINAPI DestroyWindow( HWND hwnd )
1292 WND * wndPtr;
1293 BOOL retvalue;
1295 TRACE_(win)("(%04x)\n", hwnd);
1297 /* Initialization */
1299 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1300 if (wndPtr == pWndDesktop)
1302 WIN_ReleaseWndPtr(wndPtr);
1303 return FALSE; /* Can't destroy desktop */
1306 /* Call hooks */
1308 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1310 retvalue = FALSE;
1311 goto end;
1314 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1316 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1317 /* FIXME: clean up palette - see "Internals" p.352 */
1320 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1321 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1323 /* Notify the parent window only */
1324 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1325 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1326 if( !IsWindow(hwnd) )
1328 retvalue = TRUE;
1329 goto end;
1333 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1335 /* Hide the window */
1337 if (wndPtr->dwStyle & WS_VISIBLE)
1339 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1340 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1341 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1342 if (!IsWindow(hwnd))
1344 retvalue = TRUE;
1345 goto end;
1349 /* Recursively destroy owned windows */
1351 if( !(wndPtr->dwStyle & WS_CHILD) )
1353 /* make sure top menu popup doesn't get destroyed */
1354 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1356 for (;;)
1358 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1359 while (siblingPtr)
1361 if (siblingPtr->owner == wndPtr)
1363 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1364 break;
1365 else
1366 siblingPtr->owner = NULL;
1368 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1370 if (siblingPtr)
1372 DestroyWindow( siblingPtr->hwndSelf );
1373 WIN_ReleaseWndPtr(siblingPtr);
1375 else break;
1378 if( !Options.managed || EVENT_CheckFocus() )
1379 WINPOS_ActivateOtherWindow(wndPtr);
1381 if( wndPtr->owner &&
1382 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1383 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1386 /* Send destroy messages */
1388 WIN_SendDestroyMsg( wndPtr );
1389 if (!IsWindow(hwnd))
1391 retvalue = TRUE;
1392 goto end;
1395 /* Unlink now so we won't bother with the children later on */
1397 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1399 /* Destroy the window storage */
1401 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1402 retvalue = TRUE;
1403 end:
1404 WIN_ReleaseWndPtr(wndPtr);
1405 return retvalue;
1409 /***********************************************************************
1410 * CloseWindow16 (USER.43)
1412 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1414 return CloseWindow( hwnd );
1418 /***********************************************************************
1419 * CloseWindow32 (USER32.56)
1421 BOOL WINAPI CloseWindow( HWND hwnd )
1423 WND * wndPtr = WIN_FindWndPtr( hwnd );
1424 BOOL retvalue;
1426 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1428 retvalue = FALSE;
1429 goto end;
1431 ShowWindow( hwnd, SW_MINIMIZE );
1432 retvalue = TRUE;
1433 end:
1434 WIN_ReleaseWndPtr(wndPtr);
1435 return retvalue;
1440 /***********************************************************************
1441 * OpenIcon16 (USER.44)
1443 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1445 return OpenIcon( hwnd );
1449 /***********************************************************************
1450 * OpenIcon32 (USER32.410)
1452 BOOL WINAPI OpenIcon( HWND hwnd )
1454 if (!IsIconic( hwnd )) return FALSE;
1455 ShowWindow( hwnd, SW_SHOWNORMAL );
1456 return TRUE;
1460 /***********************************************************************
1461 * WIN_FindWindow
1463 * Implementation of FindWindow() and FindWindowEx().
1465 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1466 LPCSTR title )
1468 WND *pWnd;
1469 HWND retvalue;
1470 CLASS *pClass = NULL;
1472 if (child)
1474 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1475 if (parent)
1477 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1479 retvalue = 0;
1480 goto end;
1483 else if (pWnd->parent != pWndDesktop)
1485 retvalue = 0;
1486 goto end;
1488 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1490 else
1492 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1494 retvalue = 0;
1495 goto end;
1497 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1499 if (!pWnd)
1501 retvalue = 0;
1502 goto end;
1505 /* For a child window, all siblings will have the same hInstance, */
1506 /* so we can look for the class once and for all. */
1508 if (className && (pWnd->dwStyle & WS_CHILD))
1510 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1512 retvalue = 0;
1513 goto end;
1518 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1520 if (className && !(pWnd->dwStyle & WS_CHILD))
1522 if (!((pClass = CLASS_FindClassByAtom( className, pWnd->hInstance))
1523 ||(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1525 continue; /* Skip this window */
1528 if (pClass && (pWnd->class != pClass))
1529 continue; /* Not the right class */
1531 /* Now check the title */
1533 if (!title)
1535 retvalue = pWnd->hwndSelf;
1536 goto end;
1538 if (pWnd->text && !strcmp( pWnd->text, title ))
1540 retvalue = pWnd->hwndSelf;
1541 goto end;
1544 retvalue = 0;
1545 end:
1546 WIN_ReleaseWndPtr(pWnd);
1547 return retvalue;
1552 /***********************************************************************
1553 * FindWindow16 (USER.50)
1555 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1557 return FindWindowEx16( 0, 0, className, title );
1561 /***********************************************************************
1562 * FindWindowEx16 (USER.427)
1564 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1565 SEGPTR className, LPCSTR title )
1567 ATOM atom = 0;
1569 TRACE_(win)("%04x %04x '%s' '%s'\n", parent,
1570 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1571 title ? title : "");
1573 if (className)
1575 /* If the atom doesn't exist, then no class */
1576 /* with this name exists either. */
1577 if (!(atom = GlobalFindAtom16( className ))) return 0;
1579 return WIN_FindWindow( parent, child, atom, title );
1583 /***********************************************************************
1584 * FindWindow32A (USER32.198)
1586 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1588 HWND ret = FindWindowExA( 0, 0, className, title );
1589 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1590 return ret;
1594 /***********************************************************************
1595 * FindWindowEx32A (USER32.199)
1597 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1598 LPCSTR className, LPCSTR title )
1600 ATOM atom = 0;
1602 if (className)
1604 /* If the atom doesn't exist, then no class */
1605 /* with this name exists either. */
1606 if (!(atom = GlobalFindAtomA( className )))
1608 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1609 return 0;
1612 return WIN_FindWindow( parent, child, atom, title );
1616 /***********************************************************************
1617 * FindWindowEx32W (USER32.200)
1619 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1620 LPCWSTR className, LPCWSTR title )
1622 ATOM atom = 0;
1623 char *buffer;
1624 HWND hwnd;
1626 if (className)
1628 /* If the atom doesn't exist, then no class */
1629 /* with this name exists either. */
1630 if (!(atom = GlobalFindAtomW( className )))
1632 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1633 return 0;
1636 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1637 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1638 HeapFree( GetProcessHeap(), 0, buffer );
1639 return hwnd;
1643 /***********************************************************************
1644 * FindWindow32W (USER32.201)
1646 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1648 return FindWindowExW( 0, 0, className, title );
1652 /**********************************************************************
1653 * WIN_GetDesktop
1654 * returns a locked pointer
1656 WND *WIN_GetDesktop(void)
1658 return WIN_LockWndPtr(pWndDesktop);
1660 /**********************************************************************
1661 * WIN_ReleaseDesktop
1662 * unlock the desktop pointer
1664 void WIN_ReleaseDesktop(void)
1666 WIN_ReleaseWndPtr(pWndDesktop);
1670 /**********************************************************************
1671 * GetDesktopWindow16 (USER.286)
1673 HWND16 WINAPI GetDesktopWindow16(void)
1675 return (HWND16)pWndDesktop->hwndSelf;
1679 /**********************************************************************
1680 * GetDesktopWindow32 (USER32.232)
1682 HWND WINAPI GetDesktopWindow(void)
1684 return pWndDesktop->hwndSelf;
1688 /**********************************************************************
1689 * GetDesktopHwnd (USER.278)
1691 * Exactly the same thing as GetDesktopWindow(), but not documented.
1692 * Don't ask me why...
1694 HWND16 WINAPI GetDesktopHwnd16(void)
1696 return (HWND16)pWndDesktop->hwndSelf;
1700 /*******************************************************************
1701 * EnableWindow16 (USER.34)
1703 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1705 return EnableWindow( hwnd, enable );
1709 /*******************************************************************
1710 * EnableWindow32 (USER32.172)
1712 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1714 WND *wndPtr;
1715 BOOL retvalue;
1717 TRACE_(win)("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1719 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1720 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1722 /* Enable window */
1723 wndPtr->dwStyle &= ~WS_DISABLED;
1725 if( wndPtr->flags & WIN_NATIVE )
1726 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1728 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1729 retvalue = TRUE;
1730 goto end;
1732 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1734 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1736 /* Disable window */
1737 wndPtr->dwStyle |= WS_DISABLED;
1739 if( wndPtr->flags & WIN_NATIVE )
1740 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1742 if (hwnd == GetFocus())
1744 SetFocus( 0 ); /* A disabled window can't have the focus */
1746 if (hwnd == GetCapture())
1748 ReleaseCapture(); /* A disabled window can't capture the mouse */
1750 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1751 retvalue = FALSE;
1752 goto end;
1754 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1755 end:
1756 WIN_ReleaseWndPtr(wndPtr);
1757 return retvalue;
1761 /***********************************************************************
1762 * IsWindowEnabled16 (USER.35)
1764 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1766 return IsWindowEnabled(hWnd);
1770 /***********************************************************************
1771 * IsWindowEnabled32 (USER32.349)
1773 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1775 WND * wndPtr;
1776 BOOL retvalue;
1778 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1779 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1780 WIN_ReleaseWndPtr(wndPtr);
1781 return retvalue;
1786 /***********************************************************************
1787 * IsWindowUnicode (USER32.350)
1789 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1791 WND * wndPtr;
1792 BOOL retvalue;
1794 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1795 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1796 WIN_ReleaseWndPtr(wndPtr);
1797 return retvalue;
1801 /**********************************************************************
1802 * GetWindowWord16 (USER.133)
1804 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1806 return GetWindowWord( hwnd, offset );
1810 /**********************************************************************
1811 * GetWindowWord32 (USER32.314)
1813 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1815 WORD retvalue;
1816 WND * wndPtr = WIN_FindWndPtr( hwnd );
1817 if (!wndPtr) return 0;
1818 if (offset >= 0)
1820 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1822 WARN_(win)("Invalid offset %d\n", offset );
1823 retvalue = 0;
1824 goto end;
1826 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1827 goto end;
1829 switch(offset)
1831 case GWW_ID:
1832 if (HIWORD(wndPtr->wIDmenu))
1833 WARN_(win)("GWW_ID: discards high bits of 0x%08x!\n",
1834 wndPtr->wIDmenu);
1835 retvalue = (WORD)wndPtr->wIDmenu;
1836 goto end;
1837 case GWW_HWNDPARENT:
1838 retvalue = GetParent(hwnd);
1839 goto end;
1840 case GWW_HINSTANCE:
1841 if (HIWORD(wndPtr->hInstance))
1842 WARN_(win)("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1843 wndPtr->hInstance);
1844 retvalue = (WORD)wndPtr->hInstance;
1845 goto end;
1846 default:
1847 WARN_(win)("Invalid offset %d\n", offset );
1848 retvalue = 0;
1849 goto end;
1851 end:
1852 WIN_ReleaseWndPtr(wndPtr);
1853 return retvalue;
1856 /**********************************************************************
1857 * SetWindowWord16 (USER.134)
1859 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1861 return SetWindowWord( hwnd, offset, newval );
1865 /**********************************************************************
1866 * SetWindowWord32 (USER32.524)
1868 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1870 WORD *ptr, retval;
1871 WND * wndPtr = WIN_FindWndPtr( hwnd );
1872 if (!wndPtr) return 0;
1873 if (offset >= 0)
1875 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1877 WARN_(win)("Invalid offset %d\n", offset );
1878 retval = 0;
1879 goto end;
1881 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1883 else switch(offset)
1885 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1886 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1887 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1888 goto end;
1889 default:
1890 WARN_(win)("Invalid offset %d\n", offset );
1891 retval = 0;
1892 goto end;
1894 retval = *ptr;
1895 *ptr = newval;
1896 end:
1897 WIN_ReleaseWndPtr(wndPtr);
1898 return retval;
1902 /**********************************************************************
1903 * WIN_GetWindowLong
1905 * Helper function for GetWindowLong().
1907 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1909 LONG retvalue;
1910 WND * wndPtr = WIN_FindWndPtr( hwnd );
1911 if (!wndPtr) return 0;
1912 if (offset >= 0)
1914 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1916 WARN_(win)("Invalid offset %d\n", offset );
1917 retvalue = 0;
1918 goto end;
1920 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1921 /* Special case for dialog window procedure */
1922 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1924 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1925 goto end;
1927 goto end;
1929 switch(offset)
1931 case GWL_USERDATA: retvalue = wndPtr->userdata;
1932 goto end;
1933 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1934 goto end;
1935 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1936 goto end;
1937 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1938 goto end;
1939 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1940 type );
1941 goto end;
1942 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1943 goto end;
1944 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1945 goto end;
1946 default:
1947 WARN_(win)("Unknown offset %d\n", offset );
1949 retvalue = 0;
1950 end:
1951 WIN_ReleaseWndPtr(wndPtr);
1952 return retvalue;
1956 /**********************************************************************
1957 * WIN_SetWindowLong
1959 * Helper function for SetWindowLong().
1961 * 0 is the failure code. However, in the case of failure SetLastError
1962 * must be set to distinguish between a 0 return value and a failure.
1964 * FIXME: The error values for SetLastError may not be right. Can
1965 * someone check with the real thing?
1967 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1968 WINDOWPROCTYPE type )
1970 LONG *ptr, retval;
1971 WND * wndPtr = WIN_FindWndPtr( hwnd );
1972 STYLESTRUCT style;
1974 TRACE_(win)("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1976 if (!wndPtr)
1978 /* Is this the right error? */
1979 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1980 return 0;
1983 if (offset >= 0)
1985 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1987 WARN_(win)("Invalid offset %d\n", offset );
1989 /* Is this the right error? */
1990 SetLastError( ERROR_OUTOFMEMORY );
1992 retval = 0;
1993 goto end;
1995 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1996 /* Special case for dialog window procedure */
1997 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1999 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2000 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2001 type, WIN_PROC_WINDOW );
2002 goto end;
2005 else switch(offset)
2007 case GWL_ID:
2008 ptr = (DWORD*)&wndPtr->wIDmenu;
2009 break;
2010 case GWL_HINSTANCE:
2011 retval = SetWindowWord( hwnd, offset, newval );
2012 goto end;
2013 case GWL_WNDPROC:
2014 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2015 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2016 type, WIN_PROC_WINDOW );
2017 goto end;;
2018 case GWL_STYLE:
2019 style.styleOld = wndPtr->dwStyle;
2020 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2021 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2023 if (wndPtr->flags & WIN_ISWIN32)
2024 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2025 wndPtr->dwStyle = style.styleNew;
2026 if (wndPtr->flags & WIN_ISWIN32)
2027 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2028 retval = style.styleOld;
2029 goto end;
2031 case GWL_USERDATA:
2032 ptr = &wndPtr->userdata;
2033 break;
2034 case GWL_EXSTYLE:
2035 style.styleOld = wndPtr->dwExStyle;
2036 style.styleNew = newval;
2037 if (wndPtr->flags & WIN_ISWIN32)
2038 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2039 wndPtr->dwExStyle = newval;
2040 if (wndPtr->flags & WIN_ISWIN32)
2041 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2042 retval = style.styleOld;
2043 goto end;
2045 default:
2046 WARN_(win)("Invalid offset %d\n", offset );
2048 /* Don't think this is right error but it should do */
2049 SetLastError( ERROR_OUTOFMEMORY );
2051 retval = 0;
2052 goto end;
2054 retval = *ptr;
2055 *ptr = newval;
2056 end:
2057 WIN_ReleaseWndPtr(wndPtr);
2058 return retval;
2062 /**********************************************************************
2063 * GetWindowLong16 (USER.135)
2065 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2067 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2071 /**********************************************************************
2072 * GetWindowLong32A (USER32.305)
2074 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2076 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2080 /**********************************************************************
2081 * GetWindowLong32W (USER32.306)
2083 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2085 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2089 /**********************************************************************
2090 * SetWindowLong16 (USER.136)
2092 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2094 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2098 /**********************************************************************
2099 * SetWindowLong32A (USER32.517)
2101 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2103 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2107 /**********************************************************************
2108 * SetWindowLong32W (USER32.518) Set window attribute
2110 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2111 * value in a window's extra memory.
2113 * The _hwnd_ parameter specifies the window. is the handle to a
2114 * window that has extra memory. The _newval_ parameter contains the
2115 * new attribute or extra memory value. If positive, the _offset_
2116 * parameter is the byte-addressed location in the window's extra
2117 * memory to set. If negative, _offset_ specifies the window
2118 * attribute to set, and should be one of the following values:
2120 * GWL_EXSTYLE The window's extended window style
2122 * GWL_STYLE The window's window style.
2124 * GWL_WNDPROC Pointer to the window's window procedure.
2126 * GWL_HINSTANCE The window's pplication instance handle.
2128 * GWL_ID The window's identifier.
2130 * GWL_USERDATA The window's user-specified data.
2132 * If the window is a dialog box, the _offset_ parameter can be one of
2133 * the following values:
2135 * DWL_DLGPROC The address of the window's dialog box procedure.
2137 * DWL_MSGRESULT The return value of a message
2138 * that the dialog box procedure processed.
2140 * DWL_USER Application specific information.
2142 * RETURNS
2144 * If successful, returns the previous value located at _offset_. Otherwise,
2145 * returns 0.
2147 * NOTES
2149 * Extra memory for a window class is specified by a nonzero cbWndExtra
2150 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2151 * time of class creation.
2153 * Using GWL_WNDPROC to set a new window procedure effectively creates
2154 * a window subclass. Use CallWindowProc() in the new windows procedure
2155 * to pass messages to the superclass's window procedure.
2157 * The user data is reserved for use by the application which created
2158 * the window.
2160 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2161 * instead, call the EnableWindow() function to change the window's
2162 * disabled state.
2164 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2165 * SetParent() instead.
2167 * Win95:
2168 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2169 * it sends WM_STYLECHANGING before changing the settings
2170 * and WM_STYLECHANGED afterwards.
2171 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2173 * BUGS
2175 * GWL_STYLE does not dispatch WM_STYLE... messages.
2177 * CONFORMANCE
2179 * ECMA-234, Win32
2182 LONG WINAPI SetWindowLongW(
2183 HWND hwnd, /* window to alter */
2184 INT offset, /* offset, in bytes, of location to alter */
2185 LONG newval /* new value of location */
2187 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2191 /*******************************************************************
2192 * GetWindowText16 (USER.36)
2194 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2196 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2200 /*******************************************************************
2201 * GetWindowText32A (USER32.309)
2203 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2205 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2206 (LPARAM)lpString );
2209 /*******************************************************************
2210 * InternalGetWindowText (USER32.326)
2212 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2214 FIXME_(win)("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2215 return GetWindowTextW(hwnd,lpString,nMaxCount);
2219 /*******************************************************************
2220 * GetWindowText32W (USER32.312)
2222 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2224 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2225 (LPARAM)lpString );
2229 /*******************************************************************
2230 * SetWindowText16 (USER.37)
2232 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2234 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2238 /*******************************************************************
2239 * SetWindowText32A (USER32.521)
2241 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2243 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2247 /*******************************************************************
2248 * SetWindowText32W (USER32.523)
2250 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2252 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2256 /*******************************************************************
2257 * GetWindowTextLength16 (USER.38)
2259 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2261 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2265 /*******************************************************************
2266 * GetWindowTextLength32A (USER32.310)
2268 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2270 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2273 /*******************************************************************
2274 * GetWindowTextLength32W (USER32.311)
2276 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2278 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2282 /*******************************************************************
2283 * IsWindow16 (USER.47)
2285 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2287 CURRENT_STACK16->es = USER_HeapSel;
2288 return IsWindow( hwnd );
2292 /*******************************************************************
2293 * IsWindow32 (USER32.348)
2295 BOOL WINAPI IsWindow( HWND hwnd )
2297 WND * wndPtr;
2298 BOOL retvalue;
2300 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2301 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2302 WIN_ReleaseWndPtr(wndPtr);
2303 return retvalue;
2308 /*****************************************************************
2309 * GetParent16 (USER.46)
2311 HWND16 WINAPI GetParent16( HWND16 hwnd )
2313 return (HWND16)GetParent( hwnd );
2317 /*****************************************************************
2318 * GetParent32 (USER32.278)
2320 HWND WINAPI GetParent( HWND hwnd )
2322 WND *wndPtr;
2323 HWND retvalue;
2325 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2326 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2328 WIN_ReleaseWndPtr(wndPtr);
2329 return 0;
2331 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2332 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2334 WIN_ReleaseWndPtr(wndPtr);
2335 return retvalue;
2339 /*****************************************************************
2340 * WIN_GetTopParent
2342 * Get the top-level parent for a child window.
2343 * returns a locked pointer
2345 WND* WIN_GetTopParentPtr( WND* pWnd )
2347 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2349 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2351 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2353 return tmpWnd;
2356 /*****************************************************************
2357 * WIN_GetTopParent
2359 * Get the top-level parent for a child window.
2361 HWND WIN_GetTopParent( HWND hwnd )
2363 HWND retvalue;
2364 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2365 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2367 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2368 WIN_ReleaseWndPtr(tmpPtr);
2369 WIN_ReleaseWndPtr(wndPtr);
2370 return retvalue;
2374 /*****************************************************************
2375 * SetParent16 (USER.233)
2377 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2379 return SetParent( hwndChild, hwndNewParent );
2383 /*****************************************************************
2384 * SetParent32 (USER32.495)
2386 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2388 WND *wndPtr;
2389 DWORD dwStyle;
2390 WND *pWndNewParent;
2391 WND *pWndOldParent;
2392 HWND retvalue;
2395 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2397 dwStyle = wndPtr->dwStyle;
2399 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2400 : WIN_LockWndPtr(pWndDesktop);
2402 /* Windows hides the window first, then shows it again
2403 * including the WM_SHOWWINDOW messages and all */
2404 if (dwStyle & WS_VISIBLE)
2405 ShowWindow( hwndChild, SW_HIDE );
2407 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2409 /* SetParent32 additionally needs to make hwndChild the topmost window
2410 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2411 WM_WINDOWPOSCHANGED notification messages.
2413 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2414 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2415 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2416 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2418 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2420 WIN_ReleaseWndPtr(pWndOldParent);
2421 WIN_ReleaseWndPtr(pWndNewParent);
2422 WIN_ReleaseWndPtr(wndPtr);
2424 return retvalue;
2428 /*******************************************************************
2429 * IsChild16 (USER.48)
2431 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2433 return IsChild(parent,child);
2437 /*******************************************************************
2438 * IsChild32 (USER32.339)
2440 BOOL WINAPI IsChild( HWND parent, HWND child )
2442 WND * wndPtr = WIN_FindWndPtr( child );
2443 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2445 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2446 if (wndPtr->hwndSelf == parent)
2448 WIN_ReleaseWndPtr(wndPtr);
2449 return TRUE;
2452 WIN_ReleaseWndPtr(wndPtr);
2453 return FALSE;
2457 /***********************************************************************
2458 * IsWindowVisible16 (USER.49)
2460 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2462 return IsWindowVisible(hwnd);
2466 /***********************************************************************
2467 * IsWindowVisible32 (USER32.351)
2469 BOOL WINAPI IsWindowVisible( HWND hwnd )
2471 BOOL retval;
2472 WND *wndPtr = WIN_FindWndPtr( hwnd );
2473 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2475 if (!(wndPtr->dwStyle & WS_VISIBLE))
2477 WIN_ReleaseWndPtr(wndPtr);
2478 return FALSE;
2480 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2482 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2483 WIN_ReleaseWndPtr(wndPtr);
2484 return retval;
2489 /***********************************************************************
2490 * WIN_IsWindowDrawable
2492 * hwnd is drawable when it is visible, all parents are not
2493 * minimized, and it is itself not minimized unless we are
2494 * trying to draw its default class icon.
2496 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2498 if( (wnd->dwStyle & WS_MINIMIZE &&
2499 icon && wnd->class->hIcon) ||
2500 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2501 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2502 if( wnd->dwStyle & WS_MINIMIZE ||
2503 !(wnd->dwStyle & WS_VISIBLE) ) break;
2504 return (wnd == NULL);
2508 /*******************************************************************
2509 * GetTopWindow16 (USER.229)
2511 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2513 return GetTopWindow(hwnd);
2517 /*******************************************************************
2518 * GetTopWindow32 (USER.229)
2520 HWND WINAPI GetTopWindow( HWND hwnd )
2522 HWND retval;
2523 WND * wndPtr = NULL;
2525 if (hwnd!=0)
2526 wndPtr = WIN_FindWndPtr( hwnd );
2527 else
2528 wndPtr = WIN_GetDesktop();
2530 if (wndPtr && wndPtr->child)
2532 retval = wndPtr->child->hwndSelf;
2534 else retval = 0;
2535 WIN_ReleaseWndPtr(wndPtr);
2536 return retval;
2540 /*******************************************************************
2541 * GetWindow16 (USER.262)
2543 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2545 return GetWindow( hwnd,rel );
2549 /*******************************************************************
2550 * GetWindow32 (USER32.302)
2552 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2554 HWND retval;
2556 WND * wndPtr = WIN_FindWndPtr( hwnd );
2557 if (!wndPtr) return 0;
2558 switch(rel)
2560 case GW_HWNDFIRST:
2561 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2562 else retval = 0;
2563 goto end;
2565 case GW_HWNDLAST:
2566 if (!wndPtr->parent)
2568 retval = 0; /* Desktop window */
2569 goto end;
2571 while (wndPtr->next)
2573 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2575 retval = wndPtr->hwndSelf;
2576 goto end;
2578 case GW_HWNDNEXT:
2579 if (!wndPtr->next) retval = 0;
2580 else retval = wndPtr->next->hwndSelf;
2581 goto end;
2583 case GW_HWNDPREV:
2584 if (!wndPtr->parent)
2586 retval = 0; /* Desktop window */
2587 goto end;
2589 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2590 if (wndPtr->hwndSelf == hwnd)
2592 retval = 0; /* First in list */
2593 goto end;
2595 while (wndPtr->next)
2597 if (wndPtr->next->hwndSelf == hwnd)
2599 retval = wndPtr->hwndSelf;
2600 goto end;
2602 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2604 retval = 0;
2605 goto end;
2607 case GW_OWNER:
2608 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2609 goto end;
2611 case GW_CHILD:
2612 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2613 goto end;
2615 retval = 0;
2616 end:
2617 WIN_ReleaseWndPtr(wndPtr);
2618 return retval;
2622 /*******************************************************************
2623 * GetNextWindow16 (USER.230)
2625 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2627 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2628 return GetWindow16( hwnd, flag );
2631 /*******************************************************************
2632 * ShowOwnedPopups16 (USER.265)
2634 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2636 ShowOwnedPopups( owner, fShow );
2640 /*******************************************************************
2641 * ShowOwnedPopups32 (USER32.531)
2643 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2645 WND *pWnd;
2646 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2647 while (pWnd)
2649 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2650 (pWnd->dwStyle & WS_POPUP))
2651 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2652 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2654 return TRUE;
2658 /*******************************************************************
2659 * GetLastActivePopup16 (USER.287)
2661 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2663 return GetLastActivePopup( hwnd );
2666 /*******************************************************************
2667 * GetLastActivePopup32 (USER32.256)
2669 HWND WINAPI GetLastActivePopup( HWND hwnd )
2671 WND *wndPtr;
2672 HWND retval;
2673 wndPtr = WIN_FindWndPtr(hwnd);
2674 if (!wndPtr) return hwnd;
2675 retval = wndPtr->hwndLastActive;
2676 WIN_ReleaseWndPtr(wndPtr);
2677 return retval;
2681 /*******************************************************************
2682 * WIN_BuildWinArray
2684 * Build an array of pointers to the children of a given window.
2685 * The array must be freed with HeapFree(SystemHeap). Return NULL
2686 * when no windows are found.
2688 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2690 /* Future : this function will lock all windows associated with this array */
2692 WND **list, **ppWnd;
2693 WND *pWnd;
2694 UINT count = 0, skipOwned, skipHidden;
2695 DWORD skipFlags;
2697 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2698 skipOwned = bwaFlags & BWA_SKIPOWNED;
2699 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2700 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2702 /* First count the windows */
2704 if (!wndPtr)
2705 wndPtr = WIN_GetDesktop();
2707 pWnd = WIN_LockWndPtr(wndPtr->child);
2708 while (pWnd)
2710 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2711 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2712 count++;
2713 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2716 if( count )
2718 /* Now build the list of all windows */
2720 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2722 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2724 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2725 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2727 *ppWnd++ = pWnd;
2728 count++;
2731 WIN_ReleaseWndPtr(pWnd);
2732 *ppWnd = NULL;
2734 else count = 0;
2735 } else list = NULL;
2737 if( pTotal ) *pTotal = count;
2738 return list;
2740 /*******************************************************************
2741 * WIN_ReleaseWinArray
2743 void WIN_ReleaseWinArray(WND **wndArray)
2745 /* Future : this function will also unlock all windows associated with wndArray */
2746 HeapFree( SystemHeap, 0, wndArray );
2750 /*******************************************************************
2751 * EnumWindows16 (USER.54)
2753 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2755 WND **list, **ppWnd;
2757 /* We have to build a list of all windows first, to avoid */
2758 /* unpleasant side-effects, for instance if the callback */
2759 /* function changes the Z-order of the windows. */
2761 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2763 WIN_ReleaseDesktop();
2764 return FALSE;
2767 /* Now call the callback function for every window */
2769 for (ppWnd = list; *ppWnd; ppWnd++)
2771 LRESULT lpEnumFuncRetval;
2772 int iWndsLocks = 0;
2773 /* Make sure that the window still exists */
2774 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2776 /* To avoid any deadlocks, all the locks on the windows
2777 structures must be suspended before the control
2778 is passed to the application */
2779 iWndsLocks = WIN_SuspendWndsLock();
2780 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2781 WIN_RestoreWndsLock(iWndsLocks);
2783 if (!lpEnumFuncRetval) break;
2785 WIN_ReleaseWinArray(list);
2786 WIN_ReleaseDesktop();
2787 return TRUE;
2791 /*******************************************************************
2792 * EnumWindows32 (USER32.193)
2794 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2796 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2800 /**********************************************************************
2801 * EnumTaskWindows16 (USER.225)
2803 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2804 LPARAM lParam )
2806 WND **list, **ppWnd;
2808 /* This function is the same as EnumWindows(), */
2809 /* except for an added check on the window's task. */
2811 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2813 WIN_ReleaseDesktop();
2814 return FALSE;
2817 /* Now call the callback function for every window */
2819 for (ppWnd = list; *ppWnd; ppWnd++)
2821 LRESULT funcRetval;
2822 int iWndsLocks = 0;
2823 /* Make sure that the window still exists */
2824 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2825 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2827 /* To avoid any deadlocks, all the locks on the windows
2828 structures must be suspended before the control
2829 is passed to the application */
2830 iWndsLocks = WIN_SuspendWndsLock();
2831 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2832 WIN_RestoreWndsLock(iWndsLocks);
2834 if (!funcRetval) break;
2836 WIN_ReleaseWinArray(list);
2837 WIN_ReleaseDesktop();
2838 return TRUE;
2842 /**********************************************************************
2843 * EnumThreadWindows (USER32.190)
2845 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2847 TEB *teb = THREAD_IdToTEB(id);
2849 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2853 /**********************************************************************
2854 * WIN_EnumChildWindows
2856 * Helper function for EnumChildWindows().
2858 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2859 LPARAM lParam )
2861 WND **childList;
2862 BOOL16 ret = FALSE;
2864 for ( ; *ppWnd; ppWnd++)
2866 int iWndsLocks = 0;
2868 /* Make sure that the window still exists */
2869 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2870 /* Build children list first */
2871 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2873 /* To avoid any deadlocks, all the locks on the windows
2874 structures must be suspended before the control
2875 is passed to the application */
2876 iWndsLocks = WIN_SuspendWndsLock();
2877 ret = func( (*ppWnd)->hwndSelf, lParam );
2878 WIN_RestoreWndsLock(iWndsLocks);
2880 if (childList)
2882 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2883 WIN_ReleaseWinArray(childList);
2885 if (!ret) return FALSE;
2887 return TRUE;
2891 /**********************************************************************
2892 * EnumChildWindows16 (USER.55)
2894 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2895 LPARAM lParam )
2897 WND **list, *pParent;
2899 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2900 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2902 WIN_ReleaseWndPtr(pParent);
2903 return FALSE;
2905 WIN_EnumChildWindows( list, func, lParam );
2906 WIN_ReleaseWinArray(list);
2907 WIN_ReleaseWndPtr(pParent);
2908 return TRUE;
2912 /**********************************************************************
2913 * EnumChildWindows32 (USER32.178)
2915 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2916 LPARAM lParam )
2918 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2919 lParam );
2923 /*******************************************************************
2924 * AnyPopup16 (USER.52)
2926 BOOL16 WINAPI AnyPopup16(void)
2928 return AnyPopup();
2932 /*******************************************************************
2933 * AnyPopup32 (USER32.4)
2935 BOOL WINAPI AnyPopup(void)
2937 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2938 BOOL retvalue;
2940 while (wndPtr)
2942 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2944 retvalue = TRUE;
2945 goto end;
2947 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2949 retvalue = FALSE;
2950 end:
2951 WIN_ReleaseWndPtr(wndPtr);
2952 return retvalue;
2956 /*******************************************************************
2957 * FlashWindow16 (USER.105)
2959 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2961 return FlashWindow( hWnd, bInvert );
2965 /*******************************************************************
2966 * FlashWindow32 (USER32.202)
2968 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2970 WND *wndPtr = WIN_FindWndPtr(hWnd);
2972 TRACE_(win)("%04x\n", hWnd);
2974 if (!wndPtr) return FALSE;
2976 if (wndPtr->dwStyle & WS_MINIMIZE)
2978 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2980 HDC hDC = GetDC(hWnd);
2982 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2983 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2985 ReleaseDC( hWnd, hDC );
2986 wndPtr->flags |= WIN_NCACTIVATED;
2988 else
2990 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2991 RDW_UPDATENOW | RDW_FRAME, 0 );
2992 wndPtr->flags &= ~WIN_NCACTIVATED;
2994 WIN_ReleaseWndPtr(wndPtr);
2995 return TRUE;
2997 else
2999 WPARAM16 wparam;
3000 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3001 else wparam = (hWnd == GetActiveWindow());
3003 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3004 WIN_ReleaseWndPtr(wndPtr);
3005 return wparam;
3010 /*******************************************************************
3011 * SetSysModalWindow16 (USER.188)
3013 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3015 HWND hWndOldModal = hwndSysModal;
3016 hwndSysModal = hWnd;
3017 FIXME_(win)("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3018 return hWndOldModal;
3022 /*******************************************************************
3023 * GetSysModalWindow16 (USER.52)
3025 HWND16 WINAPI GetSysModalWindow16(void)
3027 return hwndSysModal;
3031 /*******************************************************************
3032 * GetWindowContextHelpId (USER32.303)
3034 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3036 DWORD retval;
3037 WND *wnd = WIN_FindWndPtr( hwnd );
3038 if (!wnd) return 0;
3039 retval = wnd->helpContext;
3040 WIN_ReleaseWndPtr(wnd);
3041 return retval;
3045 /*******************************************************************
3046 * SetWindowContextHelpId (USER32.515)
3048 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3050 WND *wnd = WIN_FindWndPtr( hwnd );
3051 if (!wnd) return FALSE;
3052 wnd->helpContext = id;
3053 WIN_ReleaseWndPtr(wnd);
3054 return TRUE;
3058 /*******************************************************************
3059 * DRAG_QueryUpdate
3061 * recursively find a child that contains spDragInfo->pt point
3062 * and send WM_QUERYDROPOBJECT
3064 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3066 BOOL16 wParam,bResult = 0;
3067 POINT pt;
3068 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3069 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3070 RECT tempRect;
3072 if( !ptrQueryWnd || !ptrDragInfo )
3074 WIN_ReleaseWndPtr(ptrQueryWnd);
3075 return 0;
3078 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3080 GetWindowRect(hQueryWnd,&tempRect);
3082 if( !PtInRect(&tempRect,pt) ||
3083 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3085 WIN_ReleaseWndPtr(ptrQueryWnd);
3086 return 0;
3089 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3091 tempRect = ptrQueryWnd->rectClient;
3092 if(ptrQueryWnd->dwStyle & WS_CHILD)
3093 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3094 (LPPOINT)&tempRect, 2 );
3096 if (PtInRect( &tempRect, pt))
3098 wParam = 0;
3100 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3102 if( ptrWnd->dwStyle & WS_VISIBLE )
3104 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3105 if (PtInRect( &tempRect, pt )) break;
3109 if(ptrWnd)
3111 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3112 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3113 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3114 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3115 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3117 WIN_ReleaseWndPtr(ptrWnd);
3120 if(bResult)
3122 WIN_ReleaseWndPtr(ptrQueryWnd);
3123 return bResult;
3126 else wParam = 1;
3128 else wParam = 1;
3130 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3132 ptrDragInfo->hScope = hQueryWnd;
3134 bResult = ( bNoSend )
3135 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3136 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3137 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3138 if( !bResult )
3139 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3141 WIN_ReleaseWndPtr(ptrQueryWnd);
3142 return bResult;
3146 /*******************************************************************
3147 * DragDetect (USER.465)
3149 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3151 POINT pt32;
3152 CONV_POINT16TO32( &pt, &pt32 );
3153 return DragDetect( hWnd, pt32 );
3156 /*******************************************************************
3157 * DragDetect32 (USER32.151)
3159 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3161 MSG16 msg;
3162 RECT16 rect;
3164 rect.left = pt.x - wDragWidth;
3165 rect.right = pt.x + wDragWidth;
3167 rect.top = pt.y - wDragHeight;
3168 rect.bottom = pt.y + wDragHeight;
3170 SetCapture(hWnd);
3172 while(1)
3174 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3176 if( msg.message == WM_LBUTTONUP )
3178 ReleaseCapture();
3179 return 0;
3181 if( msg.message == WM_MOUSEMOVE )
3183 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3185 ReleaseCapture();
3186 return 1;
3190 WaitMessage();
3192 return 0;
3195 /******************************************************************************
3196 * DragObject16 (USER.464)
3198 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3199 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3201 MSG16 msg;
3202 LPDRAGINFO lpDragInfo;
3203 SEGPTR spDragInfo;
3204 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3205 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3206 WND *wndPtr = WIN_FindWndPtr(hWnd);
3207 HCURSOR16 hCurrentCursor = 0;
3208 HWND16 hCurrentWnd = 0;
3210 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3211 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3213 if( !lpDragInfo || !spDragInfo )
3215 WIN_ReleaseWndPtr(wndPtr);
3216 return 0L;
3219 hBummer = LoadCursor16(0, IDC_BUMMER16);
3221 if( !hBummer || !wndPtr )
3223 GlobalFree16(hDragInfo);
3224 WIN_ReleaseWndPtr(wndPtr);
3225 return 0L;
3228 if(hCursor)
3230 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3232 GlobalFree16(hDragInfo);
3233 WIN_ReleaseWndPtr(wndPtr);
3234 return 0L;
3237 if( hDragCursor == hCursor ) hDragCursor = 0;
3238 else hCursor = hDragCursor;
3240 hOldCursor = SetCursor(hDragCursor);
3243 lpDragInfo->hWnd = hWnd;
3244 lpDragInfo->hScope = 0;
3245 lpDragInfo->wFlags = wObj;
3246 lpDragInfo->hList = szList; /* near pointer! */
3247 lpDragInfo->hOfStruct = hOfStruct;
3248 lpDragInfo->l = 0L;
3250 SetCapture(hWnd);
3251 ShowCursor( TRUE );
3255 do{ WaitMessage(); }
3256 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3258 *(lpDragInfo+1) = *lpDragInfo;
3260 lpDragInfo->pt = msg.pt;
3262 /* update DRAGINFO struct */
3263 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3265 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3266 hCurrentCursor = hCursor;
3267 else
3269 hCurrentCursor = hBummer;
3270 lpDragInfo->hScope = 0;
3272 if( hCurrentCursor )
3273 SetCursor(hCurrentCursor);
3275 /* send WM_DRAGLOOP */
3276 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3277 (LPARAM) spDragInfo );
3278 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3279 if( hCurrentWnd != lpDragInfo->hScope )
3281 if( hCurrentWnd )
3282 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3283 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3284 HIWORD(spDragInfo)) );
3285 hCurrentWnd = lpDragInfo->hScope;
3286 if( hCurrentWnd )
3287 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3289 else
3290 if( hCurrentWnd )
3291 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3293 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3295 ReleaseCapture();
3296 ShowCursor( FALSE );
3298 if( hCursor )
3300 SetCursor( hOldCursor );
3301 if (hDragCursor) DestroyCursor( hDragCursor );
3304 if( hCurrentCursor != hBummer )
3305 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3306 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3307 else
3308 msg.lParam = 0;
3309 GlobalFree16(hDragInfo);
3310 WIN_ReleaseWndPtr(wndPtr);
3312 return (DWORD)(msg.lParam);