Warn users to use -the -desktop option together with the native user DLLs.
[wine/multimedia.git] / windows / win.c
blobc5d910d212da2bac8178d6ef0c34339445d2cec6
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;
866 /* Get class or window DC if needed */
868 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
869 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
870 else wndPtr->dce = NULL;
872 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
874 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
876 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
877 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
878 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
879 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
880 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
883 if(cs->style & WS_CHILD)
885 if(cs->cx < 0) cs->cx = 0;
886 if(cs->cy < 0) cs->cy = 0;
888 else
890 if (cs->cx <= 0) cs->cx = 1;
891 if (cs->cy <= 0) cs->cy = 1;
894 wndPtr->rectWindow.left = cs->x;
895 wndPtr->rectWindow.top = cs->y;
896 wndPtr->rectWindow.right = cs->x + cs->cx;
897 wndPtr->rectWindow.bottom = cs->y + cs->cy;
898 wndPtr->rectClient = wndPtr->rectWindow;
900 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
902 retvalue = FALSE;
903 goto end;
906 /* Set the window menu */
908 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
910 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
911 else
913 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
914 if (classPtr->menuNameA)
915 cs->hMenu = HIWORD(classPtr->menuNameA) ?
916 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
917 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
918 #else
919 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
920 if (menuName)
922 if (HIWORD(cs->hInstance))
923 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
924 else
925 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
927 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
929 #endif
932 else wndPtr->wIDmenu = (UINT)cs->hMenu;
934 /* Send the WM_CREATE message
935 * Perhaps we shouldn't allow width/height changes as well.
936 * See p327 in "Internals".
939 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
941 localSend32 = unicode ? SendMessageW : SendMessageA;
942 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
944 /* Insert the window in the linked list */
946 WIN_LinkWindow( hwnd, hwndLinkAfter );
948 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
949 NULL, NULL, 0, &wndPtr->rectClient );
950 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
951 maxPos.y - wndPtr->rectWindow.top);
952 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
954 /* Send the size messages */
956 if (!(wndPtr->flags & WIN_NEED_SIZE))
958 /* send it anyway */
959 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
960 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
961 WARN_(win)("sending bogus WM_SIZE message 0x%08lx\n",
962 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
963 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
964 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
965 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
966 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
967 SendMessageA( hwnd, WM_MOVE, 0,
968 MAKELONG( wndPtr->rectClient.left,
969 wndPtr->rectClient.top ) );
972 /* Show the window, maximizing or minimizing if needed */
974 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
976 RECT16 newPos;
977 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
978 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
979 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
980 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
981 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
982 : SWP_NOZORDER | SWP_FRAMECHANGED;
983 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
984 newPos.right, newPos.bottom, swFlag );
987 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
989 /* Notify the parent window only */
991 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
992 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
993 if( !IsWindow(hwnd) )
995 retvalue = 0;
996 goto end;
1000 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1002 /* Call WH_SHELL hook */
1004 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1005 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1007 TRACE_(win)("created window %04x\n", hwnd);
1008 retvalue = hwnd;
1009 goto end;
1011 WIN_UnlinkWindow( hwnd );
1014 /* Abort window creation */
1016 WARN_(win)("aborted by WM_xxCREATE!\n");
1017 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1018 retvalue = 0;
1019 end:
1020 WIN_ReleaseWndPtr(wndPtr);
1022 return retvalue;
1026 /***********************************************************************
1027 * CreateWindow16 (USER.41)
1029 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1030 DWORD style, INT16 x, INT16 y, INT16 width,
1031 INT16 height, HWND16 parent, HMENU16 menu,
1032 HINSTANCE16 instance, LPVOID data )
1034 return CreateWindowEx16( 0, className, windowName, style,
1035 x, y, width, height, parent, menu, instance, data );
1039 /***********************************************************************
1040 * CreateWindowEx16 (USER.452)
1042 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1043 LPCSTR windowName, DWORD style, INT16 x,
1044 INT16 y, INT16 width, INT16 height,
1045 HWND16 parent, HMENU16 menu,
1046 HINSTANCE16 instance, LPVOID data )
1048 ATOM classAtom;
1049 CREATESTRUCTA cs;
1051 /* Find the class atom */
1053 if (!(classAtom = GlobalFindAtomA( className )))
1055 fprintf( stderr, "CreateWindowEx16: bad class name " );
1056 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1057 else fprintf( stderr, "'%s'\n", className );
1058 return 0;
1061 /* Fix the coordinates */
1063 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1064 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1065 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1066 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1068 /* Create the window */
1070 cs.lpCreateParams = data;
1071 cs.hInstance = (HINSTANCE)instance;
1072 cs.hMenu = (HMENU)menu;
1073 cs.hwndParent = (HWND)parent;
1074 cs.style = style;
1075 cs.lpszName = windowName;
1076 cs.lpszClass = className;
1077 cs.dwExStyle = exStyle;
1078 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1082 /***********************************************************************
1083 * CreateWindowEx32A (USER32.83)
1085 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1086 LPCSTR windowName, DWORD style, INT x,
1087 INT y, INT width, INT height,
1088 HWND parent, HMENU menu,
1089 HINSTANCE instance, LPVOID data )
1091 ATOM classAtom;
1092 CREATESTRUCTA cs;
1094 if(!instance)
1095 instance=GetModuleHandleA(NULL);
1097 if(exStyle & WS_EX_MDICHILD)
1098 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1099 /* Find the class atom */
1101 if (!(classAtom = GlobalFindAtomA( className )))
1103 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1104 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1105 else fprintf( stderr, "'%s'\n", className );
1106 return 0;
1109 /* Create the window */
1111 cs.lpCreateParams = data;
1112 cs.hInstance = instance;
1113 cs.hMenu = menu;
1114 cs.hwndParent = parent;
1115 cs.x = x;
1116 cs.y = y;
1117 cs.cx = width;
1118 cs.cy = height;
1119 cs.style = style;
1120 cs.lpszName = windowName;
1121 cs.lpszClass = className;
1122 cs.dwExStyle = exStyle;
1123 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1127 /***********************************************************************
1128 * CreateWindowEx32W (USER32.84)
1130 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1131 LPCWSTR windowName, DWORD style, INT x,
1132 INT y, INT width, INT height,
1133 HWND parent, HMENU menu,
1134 HINSTANCE instance, LPVOID data )
1136 ATOM classAtom;
1137 CREATESTRUCTW cs;
1139 if(!instance)
1140 instance=GetModuleHandleA(NULL);
1142 if(exStyle & WS_EX_MDICHILD)
1143 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1145 /* Find the class atom */
1147 if (!(classAtom = GlobalFindAtomW( className )))
1149 if (HIWORD(className))
1151 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1152 WARN_(win)("Bad class name '%s'\n",cn);
1153 HeapFree( GetProcessHeap(), 0, cn );
1155 else
1156 WARN_(win)("Bad class name %p\n", className );
1157 return 0;
1160 /* Create the window */
1162 cs.lpCreateParams = data;
1163 cs.hInstance = instance;
1164 cs.hMenu = menu;
1165 cs.hwndParent = parent;
1166 cs.x = x;
1167 cs.y = y;
1168 cs.cx = width;
1169 cs.cy = height;
1170 cs.style = style;
1171 cs.lpszName = windowName;
1172 cs.lpszClass = className;
1173 cs.dwExStyle = exStyle;
1174 /* Note: we rely on the fact that CREATESTRUCT32A and */
1175 /* CREATESTRUCT32W have the same layout. */
1176 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1180 /***********************************************************************
1181 * WIN_CheckFocus
1183 static void WIN_CheckFocus( WND* pWnd )
1185 if( GetFocus16() == pWnd->hwndSelf )
1186 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1189 /***********************************************************************
1190 * WIN_SendDestroyMsg
1192 static void WIN_SendDestroyMsg( WND* pWnd )
1194 WIN_CheckFocus(pWnd);
1196 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1197 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1200 * Send the WM_DESTROY to the window.
1202 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1205 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1206 * make sure that the window still exists when we come back.
1208 if (IsWindow(pWnd->hwndSelf))
1210 HWND* pWndArray = NULL;
1211 WND* pChild = NULL;
1212 int nKidCount = 0;
1215 * Now, if the window has kids, we have to send WM_DESTROY messages
1216 * recursively to it's kids. It seems that those calls can also
1217 * trigger re-entrant calls to DestroyWindow for the kids so we must
1218 * protect against corruption of the list of siblings. We first build
1219 * a list of HWNDs representing all the kids.
1221 pChild = WIN_LockWndPtr(pWnd->child);
1222 while( pChild )
1224 nKidCount++;
1225 WIN_UpdateWndPtr(&pChild,pChild->next);
1229 * If there are no kids, we're done.
1231 if (nKidCount==0)
1232 return;
1234 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1237 * Sanity check
1239 if (pWndArray==NULL)
1240 return;
1243 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1244 * call, our linked list of siblings should be safe.
1246 nKidCount = 0;
1247 pChild = WIN_LockWndPtr(pWnd->child);
1248 while( pChild )
1250 pWndArray[nKidCount] = pChild->hwndSelf;
1251 nKidCount++;
1252 WIN_UpdateWndPtr(&pChild,pChild->next);
1256 * Now that we have a list, go through that list again and send the destroy
1257 * message to those windows. We are using the HWND to retrieve the
1258 * WND pointer so we are effectively checking that all the kid windows are
1259 * still valid before sending the message.
1261 while (nKidCount>0)
1263 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1265 if (pChild!=NULL)
1267 WIN_SendDestroyMsg( pChild );
1268 WIN_ReleaseWndPtr(pChild);
1273 * Cleanup
1275 HeapFree(GetProcessHeap(), 0, pWndArray);
1276 WIN_CheckFocus(pWnd);
1278 else
1279 WARN_(win)("\tdestroyed itself while in WM_DESTROY!\n");
1283 /***********************************************************************
1284 * DestroyWindow16 (USER.53)
1286 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1288 return DestroyWindow(hwnd);
1292 /***********************************************************************
1293 * DestroyWindow32 (USER32.135)
1295 BOOL WINAPI DestroyWindow( HWND hwnd )
1297 WND * wndPtr;
1298 BOOL retvalue;
1300 TRACE_(win)("(%04x)\n", hwnd);
1302 /* Initialization */
1304 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1305 if (wndPtr == pWndDesktop)
1307 WIN_ReleaseWndPtr(wndPtr);
1308 return FALSE; /* Can't destroy desktop */
1311 /* Call hooks */
1313 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1315 retvalue = FALSE;
1316 goto end;
1319 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1321 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1322 /* FIXME: clean up palette - see "Internals" p.352 */
1325 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1326 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1328 /* Notify the parent window only */
1329 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1330 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1331 if( !IsWindow(hwnd) )
1333 retvalue = TRUE;
1334 goto end;
1338 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1340 /* Hide the window */
1342 if (wndPtr->dwStyle & WS_VISIBLE)
1344 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1345 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1346 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1347 if (!IsWindow(hwnd))
1349 retvalue = TRUE;
1350 goto end;
1354 /* Recursively destroy owned windows */
1356 if( !(wndPtr->dwStyle & WS_CHILD) )
1358 /* make sure top menu popup doesn't get destroyed */
1359 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1361 for (;;)
1363 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1364 while (siblingPtr)
1366 if (siblingPtr->owner == wndPtr)
1368 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1369 break;
1370 else
1371 siblingPtr->owner = NULL;
1373 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1375 if (siblingPtr)
1377 DestroyWindow( siblingPtr->hwndSelf );
1378 WIN_ReleaseWndPtr(siblingPtr);
1380 else break;
1383 if( !Options.managed || EVENT_CheckFocus() )
1384 WINPOS_ActivateOtherWindow(wndPtr);
1386 if( wndPtr->owner &&
1387 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1388 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1391 /* Send destroy messages */
1393 WIN_SendDestroyMsg( wndPtr );
1394 if (!IsWindow(hwnd))
1396 retvalue = TRUE;
1397 goto end;
1400 /* Unlink now so we won't bother with the children later on */
1402 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1404 /* Destroy the window storage */
1406 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1407 retvalue = TRUE;
1408 end:
1409 WIN_ReleaseWndPtr(wndPtr);
1410 return retvalue;
1414 /***********************************************************************
1415 * CloseWindow16 (USER.43)
1417 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1419 return CloseWindow( hwnd );
1423 /***********************************************************************
1424 * CloseWindow32 (USER32.56)
1426 BOOL WINAPI CloseWindow( HWND hwnd )
1428 WND * wndPtr = WIN_FindWndPtr( hwnd );
1429 BOOL retvalue;
1431 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1433 retvalue = FALSE;
1434 goto end;
1436 ShowWindow( hwnd, SW_MINIMIZE );
1437 retvalue = TRUE;
1438 end:
1439 WIN_ReleaseWndPtr(wndPtr);
1440 return retvalue;
1445 /***********************************************************************
1446 * OpenIcon16 (USER.44)
1448 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1450 return OpenIcon( hwnd );
1454 /***********************************************************************
1455 * OpenIcon32 (USER32.410)
1457 BOOL WINAPI OpenIcon( HWND hwnd )
1459 if (!IsIconic( hwnd )) return FALSE;
1460 ShowWindow( hwnd, SW_SHOWNORMAL );
1461 return TRUE;
1465 /***********************************************************************
1466 * WIN_FindWindow
1468 * Implementation of FindWindow() and FindWindowEx().
1470 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1471 LPCSTR title )
1473 WND *pWnd;
1474 HWND retvalue;
1475 CLASS *pClass = NULL;
1477 if (child)
1479 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1480 if (parent)
1482 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1484 retvalue = 0;
1485 goto end;
1488 else if (pWnd->parent != pWndDesktop)
1490 retvalue = 0;
1491 goto end;
1493 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1495 else
1497 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1499 retvalue = 0;
1500 goto end;
1502 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1504 if (!pWnd)
1506 retvalue = 0;
1507 goto end;
1510 /* For a child window, all siblings will have the same hInstance, */
1511 /* so we can look for the class once and for all. */
1513 if (className && (pWnd->dwStyle & WS_CHILD))
1515 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1517 retvalue = 0;
1518 goto end;
1523 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1525 if (className && !(pWnd->dwStyle & WS_CHILD))
1527 if (!((pClass = CLASS_FindClassByAtom( className, pWnd->hInstance))
1528 ||(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1530 continue; /* Skip this window */
1533 if (pClass && (pWnd->class != pClass))
1534 continue; /* Not the right class */
1536 /* Now check the title */
1538 if (!title)
1540 retvalue = pWnd->hwndSelf;
1541 goto end;
1543 if (pWnd->text && !strcmp( pWnd->text, title ))
1545 retvalue = pWnd->hwndSelf;
1546 goto end;
1549 retvalue = 0;
1550 end:
1551 WIN_ReleaseWndPtr(pWnd);
1552 return retvalue;
1557 /***********************************************************************
1558 * FindWindow16 (USER.50)
1560 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1562 return FindWindowEx16( 0, 0, className, title );
1566 /***********************************************************************
1567 * FindWindowEx16 (USER.427)
1569 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1570 SEGPTR className, LPCSTR title )
1572 ATOM atom = 0;
1574 TRACE_(win)("%04x %04x '%s' '%s'\n", parent,
1575 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1576 title ? title : "");
1578 if (className)
1580 /* If the atom doesn't exist, then no class */
1581 /* with this name exists either. */
1582 if (!(atom = GlobalFindAtom16( className ))) return 0;
1584 return WIN_FindWindow( parent, child, atom, title );
1588 /***********************************************************************
1589 * FindWindow32A (USER32.198)
1591 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1593 HWND ret = FindWindowExA( 0, 0, className, title );
1594 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1595 return ret;
1599 /***********************************************************************
1600 * FindWindowEx32A (USER32.199)
1602 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1603 LPCSTR className, LPCSTR title )
1605 ATOM atom = 0;
1607 if (className)
1609 /* If the atom doesn't exist, then no class */
1610 /* with this name exists either. */
1611 if (!(atom = GlobalFindAtomA( className )))
1613 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1614 return 0;
1617 return WIN_FindWindow( parent, child, atom, title );
1621 /***********************************************************************
1622 * FindWindowEx32W (USER32.200)
1624 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1625 LPCWSTR className, LPCWSTR title )
1627 ATOM atom = 0;
1628 char *buffer;
1629 HWND hwnd;
1631 if (className)
1633 /* If the atom doesn't exist, then no class */
1634 /* with this name exists either. */
1635 if (!(atom = GlobalFindAtomW( className )))
1637 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1638 return 0;
1641 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1642 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1643 HeapFree( GetProcessHeap(), 0, buffer );
1644 return hwnd;
1648 /***********************************************************************
1649 * FindWindow32W (USER32.201)
1651 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1653 return FindWindowExW( 0, 0, className, title );
1657 /**********************************************************************
1658 * WIN_GetDesktop
1659 * returns a locked pointer
1661 WND *WIN_GetDesktop(void)
1663 return WIN_LockWndPtr(pWndDesktop);
1665 /**********************************************************************
1666 * WIN_ReleaseDesktop
1667 * unlock the desktop pointer
1669 void WIN_ReleaseDesktop(void)
1671 WIN_ReleaseWndPtr(pWndDesktop);
1675 /**********************************************************************
1676 * GetDesktopWindow16 (USER.286)
1678 HWND16 WINAPI GetDesktopWindow16(void)
1680 return (HWND16)pWndDesktop->hwndSelf;
1684 /**********************************************************************
1685 * GetDesktopWindow32 (USER32.232)
1687 HWND WINAPI GetDesktopWindow(void)
1689 if (pWndDesktop) return pWndDesktop->hwndSelf;
1690 ERR_(win)( "You need the -desktop option when running with native USER\n" );
1691 ExitProcess(1);
1695 /**********************************************************************
1696 * GetDesktopHwnd (USER.278)
1698 * Exactly the same thing as GetDesktopWindow(), but not documented.
1699 * Don't ask me why...
1701 HWND16 WINAPI GetDesktopHwnd16(void)
1703 return (HWND16)pWndDesktop->hwndSelf;
1707 /*******************************************************************
1708 * EnableWindow16 (USER.34)
1710 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1712 return EnableWindow( hwnd, enable );
1716 /*******************************************************************
1717 * EnableWindow32 (USER32.172)
1719 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1721 WND *wndPtr;
1722 BOOL retvalue;
1724 TRACE_(win)("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1726 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1727 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1729 /* Enable window */
1730 wndPtr->dwStyle &= ~WS_DISABLED;
1732 if( wndPtr->flags & WIN_NATIVE )
1733 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1735 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1736 retvalue = TRUE;
1737 goto end;
1739 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1741 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1743 /* Disable window */
1744 wndPtr->dwStyle |= WS_DISABLED;
1746 if( wndPtr->flags & WIN_NATIVE )
1747 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1749 if (hwnd == GetFocus())
1751 SetFocus( 0 ); /* A disabled window can't have the focus */
1753 if (hwnd == GetCapture())
1755 ReleaseCapture(); /* A disabled window can't capture the mouse */
1757 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1758 retvalue = FALSE;
1759 goto end;
1761 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1762 end:
1763 WIN_ReleaseWndPtr(wndPtr);
1764 return retvalue;
1768 /***********************************************************************
1769 * IsWindowEnabled16 (USER.35)
1771 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1773 return IsWindowEnabled(hWnd);
1777 /***********************************************************************
1778 * IsWindowEnabled32 (USER32.349)
1780 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1782 WND * wndPtr;
1783 BOOL retvalue;
1785 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1786 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1787 WIN_ReleaseWndPtr(wndPtr);
1788 return retvalue;
1793 /***********************************************************************
1794 * IsWindowUnicode (USER32.350)
1796 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1798 WND * wndPtr;
1799 BOOL retvalue;
1801 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1802 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1803 WIN_ReleaseWndPtr(wndPtr);
1804 return retvalue;
1808 /**********************************************************************
1809 * GetWindowWord16 (USER.133)
1811 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1813 return GetWindowWord( hwnd, offset );
1817 /**********************************************************************
1818 * GetWindowWord32 (USER32.314)
1820 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1822 WORD retvalue;
1823 WND * wndPtr = WIN_FindWndPtr( hwnd );
1824 if (!wndPtr) return 0;
1825 if (offset >= 0)
1827 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1829 WARN_(win)("Invalid offset %d\n", offset );
1830 retvalue = 0;
1831 goto end;
1833 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1834 goto end;
1836 switch(offset)
1838 case GWW_ID:
1839 if (HIWORD(wndPtr->wIDmenu))
1840 WARN_(win)("GWW_ID: discards high bits of 0x%08x!\n",
1841 wndPtr->wIDmenu);
1842 retvalue = (WORD)wndPtr->wIDmenu;
1843 goto end;
1844 case GWW_HWNDPARENT:
1845 retvalue = GetParent(hwnd);
1846 goto end;
1847 case GWW_HINSTANCE:
1848 if (HIWORD(wndPtr->hInstance))
1849 WARN_(win)("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1850 wndPtr->hInstance);
1851 retvalue = (WORD)wndPtr->hInstance;
1852 goto end;
1853 default:
1854 WARN_(win)("Invalid offset %d\n", offset );
1855 retvalue = 0;
1856 goto end;
1858 end:
1859 WIN_ReleaseWndPtr(wndPtr);
1860 return retvalue;
1863 /**********************************************************************
1864 * SetWindowWord16 (USER.134)
1866 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1868 return SetWindowWord( hwnd, offset, newval );
1872 /**********************************************************************
1873 * SetWindowWord32 (USER32.524)
1875 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1877 WORD *ptr, retval;
1878 WND * wndPtr = WIN_FindWndPtr( hwnd );
1879 if (!wndPtr) return 0;
1880 if (offset >= 0)
1882 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1884 WARN_(win)("Invalid offset %d\n", offset );
1885 retval = 0;
1886 goto end;
1888 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1890 else switch(offset)
1892 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1893 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1894 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1895 goto end;
1896 default:
1897 WARN_(win)("Invalid offset %d\n", offset );
1898 retval = 0;
1899 goto end;
1901 retval = *ptr;
1902 *ptr = newval;
1903 end:
1904 WIN_ReleaseWndPtr(wndPtr);
1905 return retval;
1909 /**********************************************************************
1910 * WIN_GetWindowLong
1912 * Helper function for GetWindowLong().
1914 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1916 LONG retvalue;
1917 WND * wndPtr = WIN_FindWndPtr( hwnd );
1918 if (!wndPtr) return 0;
1919 if (offset >= 0)
1921 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1923 WARN_(win)("Invalid offset %d\n", offset );
1924 retvalue = 0;
1925 goto end;
1927 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1928 /* Special case for dialog window procedure */
1929 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1931 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1932 goto end;
1934 goto end;
1936 switch(offset)
1938 case GWL_USERDATA: retvalue = wndPtr->userdata;
1939 goto end;
1940 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1941 goto end;
1942 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1943 goto end;
1944 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1945 goto end;
1946 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1947 type );
1948 goto end;
1949 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1950 goto end;
1951 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1952 goto end;
1953 default:
1954 WARN_(win)("Unknown offset %d\n", offset );
1956 retvalue = 0;
1957 end:
1958 WIN_ReleaseWndPtr(wndPtr);
1959 return retvalue;
1963 /**********************************************************************
1964 * WIN_SetWindowLong
1966 * Helper function for SetWindowLong().
1968 * 0 is the failure code. However, in the case of failure SetLastError
1969 * must be set to distinguish between a 0 return value and a failure.
1971 * FIXME: The error values for SetLastError may not be right. Can
1972 * someone check with the real thing?
1974 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1975 WINDOWPROCTYPE type )
1977 LONG *ptr, retval;
1978 WND * wndPtr = WIN_FindWndPtr( hwnd );
1979 STYLESTRUCT style;
1981 TRACE_(win)("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1983 if (!wndPtr)
1985 /* Is this the right error? */
1986 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1987 return 0;
1990 if (offset >= 0)
1992 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1994 WARN_(win)("Invalid offset %d\n", offset );
1996 /* Is this the right error? */
1997 SetLastError( ERROR_OUTOFMEMORY );
1999 retval = 0;
2000 goto end;
2002 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2003 /* Special case for dialog window procedure */
2004 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2006 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2007 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2008 type, WIN_PROC_WINDOW );
2009 goto end;
2012 else switch(offset)
2014 case GWL_ID:
2015 ptr = (DWORD*)&wndPtr->wIDmenu;
2016 break;
2017 case GWL_HINSTANCE:
2018 retval = SetWindowWord( hwnd, offset, newval );
2019 goto end;
2020 case GWL_WNDPROC:
2021 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2022 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2023 type, WIN_PROC_WINDOW );
2024 goto end;;
2025 case GWL_STYLE:
2026 style.styleOld = wndPtr->dwStyle;
2027 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2028 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2030 if (wndPtr->flags & WIN_ISWIN32)
2031 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2032 wndPtr->dwStyle = style.styleNew;
2033 if (wndPtr->flags & WIN_ISWIN32)
2034 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2035 retval = style.styleOld;
2036 goto end;
2038 case GWL_USERDATA:
2039 ptr = &wndPtr->userdata;
2040 break;
2041 case GWL_EXSTYLE:
2042 style.styleOld = wndPtr->dwExStyle;
2043 style.styleNew = newval;
2044 if (wndPtr->flags & WIN_ISWIN32)
2045 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2046 wndPtr->dwExStyle = newval;
2047 if (wndPtr->flags & WIN_ISWIN32)
2048 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2049 retval = style.styleOld;
2050 goto end;
2052 default:
2053 WARN_(win)("Invalid offset %d\n", offset );
2055 /* Don't think this is right error but it should do */
2056 SetLastError( ERROR_OUTOFMEMORY );
2058 retval = 0;
2059 goto end;
2061 retval = *ptr;
2062 *ptr = newval;
2063 end:
2064 WIN_ReleaseWndPtr(wndPtr);
2065 return retval;
2069 /**********************************************************************
2070 * GetWindowLong16 (USER.135)
2072 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2074 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2078 /**********************************************************************
2079 * GetWindowLong32A (USER32.305)
2081 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2083 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2087 /**********************************************************************
2088 * GetWindowLong32W (USER32.306)
2090 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2092 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2096 /**********************************************************************
2097 * SetWindowLong16 (USER.136)
2099 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2101 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2105 /**********************************************************************
2106 * SetWindowLong32A (USER32.517)
2108 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2110 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2114 /**********************************************************************
2115 * SetWindowLong32W (USER32.518) Set window attribute
2117 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2118 * value in a window's extra memory.
2120 * The _hwnd_ parameter specifies the window. is the handle to a
2121 * window that has extra memory. The _newval_ parameter contains the
2122 * new attribute or extra memory value. If positive, the _offset_
2123 * parameter is the byte-addressed location in the window's extra
2124 * memory to set. If negative, _offset_ specifies the window
2125 * attribute to set, and should be one of the following values:
2127 * GWL_EXSTYLE The window's extended window style
2129 * GWL_STYLE The window's window style.
2131 * GWL_WNDPROC Pointer to the window's window procedure.
2133 * GWL_HINSTANCE The window's pplication instance handle.
2135 * GWL_ID The window's identifier.
2137 * GWL_USERDATA The window's user-specified data.
2139 * If the window is a dialog box, the _offset_ parameter can be one of
2140 * the following values:
2142 * DWL_DLGPROC The address of the window's dialog box procedure.
2144 * DWL_MSGRESULT The return value of a message
2145 * that the dialog box procedure processed.
2147 * DWL_USER Application specific information.
2149 * RETURNS
2151 * If successful, returns the previous value located at _offset_. Otherwise,
2152 * returns 0.
2154 * NOTES
2156 * Extra memory for a window class is specified by a nonzero cbWndExtra
2157 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2158 * time of class creation.
2160 * Using GWL_WNDPROC to set a new window procedure effectively creates
2161 * a window subclass. Use CallWindowProc() in the new windows procedure
2162 * to pass messages to the superclass's window procedure.
2164 * The user data is reserved for use by the application which created
2165 * the window.
2167 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2168 * instead, call the EnableWindow() function to change the window's
2169 * disabled state.
2171 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2172 * SetParent() instead.
2174 * Win95:
2175 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2176 * it sends WM_STYLECHANGING before changing the settings
2177 * and WM_STYLECHANGED afterwards.
2178 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2180 * BUGS
2182 * GWL_STYLE does not dispatch WM_STYLE... messages.
2184 * CONFORMANCE
2186 * ECMA-234, Win32
2189 LONG WINAPI SetWindowLongW(
2190 HWND hwnd, /* window to alter */
2191 INT offset, /* offset, in bytes, of location to alter */
2192 LONG newval /* new value of location */
2194 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2198 /*******************************************************************
2199 * GetWindowText16 (USER.36)
2201 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2203 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2207 /*******************************************************************
2208 * GetWindowText32A (USER32.309)
2210 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2212 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2213 (LPARAM)lpString );
2216 /*******************************************************************
2217 * InternalGetWindowText (USER32.326)
2219 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2221 FIXME_(win)("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2222 return GetWindowTextW(hwnd,lpString,nMaxCount);
2226 /*******************************************************************
2227 * GetWindowText32W (USER32.312)
2229 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2231 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2232 (LPARAM)lpString );
2236 /*******************************************************************
2237 * SetWindowText16 (USER.37)
2239 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2241 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2245 /*******************************************************************
2246 * SetWindowText32A (USER32.521)
2248 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2250 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2254 /*******************************************************************
2255 * SetWindowText32W (USER32.523)
2257 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2259 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2263 /*******************************************************************
2264 * GetWindowTextLength16 (USER.38)
2266 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2268 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2272 /*******************************************************************
2273 * GetWindowTextLength32A (USER32.310)
2275 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2277 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2280 /*******************************************************************
2281 * GetWindowTextLength32W (USER32.311)
2283 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2285 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2289 /*******************************************************************
2290 * IsWindow16 (USER.47)
2292 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2294 CURRENT_STACK16->es = USER_HeapSel;
2295 return IsWindow( hwnd );
2299 /*******************************************************************
2300 * IsWindow32 (USER32.348)
2302 BOOL WINAPI IsWindow( HWND hwnd )
2304 WND * wndPtr;
2305 BOOL retvalue;
2307 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2308 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2309 WIN_ReleaseWndPtr(wndPtr);
2310 return retvalue;
2315 /*****************************************************************
2316 * GetParent16 (USER.46)
2318 HWND16 WINAPI GetParent16( HWND16 hwnd )
2320 return (HWND16)GetParent( hwnd );
2324 /*****************************************************************
2325 * GetParent32 (USER32.278)
2327 HWND WINAPI GetParent( HWND hwnd )
2329 WND *wndPtr;
2330 HWND retvalue;
2332 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2333 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2335 WIN_ReleaseWndPtr(wndPtr);
2336 return 0;
2338 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2339 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2341 WIN_ReleaseWndPtr(wndPtr);
2342 return retvalue;
2346 /*****************************************************************
2347 * WIN_GetTopParent
2349 * Get the top-level parent for a child window.
2350 * returns a locked pointer
2352 WND* WIN_GetTopParentPtr( WND* pWnd )
2354 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2356 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2358 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2360 return tmpWnd;
2363 /*****************************************************************
2364 * WIN_GetTopParent
2366 * Get the top-level parent for a child window.
2368 HWND WIN_GetTopParent( HWND hwnd )
2370 HWND retvalue;
2371 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2372 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2374 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2375 WIN_ReleaseWndPtr(tmpPtr);
2376 WIN_ReleaseWndPtr(wndPtr);
2377 return retvalue;
2381 /*****************************************************************
2382 * SetParent16 (USER.233)
2384 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2386 return SetParent( hwndChild, hwndNewParent );
2390 /*****************************************************************
2391 * SetParent32 (USER32.495)
2393 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2395 WND *wndPtr;
2396 DWORD dwStyle;
2397 WND *pWndNewParent;
2398 WND *pWndOldParent;
2399 HWND retvalue;
2402 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2404 dwStyle = wndPtr->dwStyle;
2406 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2407 : WIN_LockWndPtr(pWndDesktop);
2409 /* Windows hides the window first, then shows it again
2410 * including the WM_SHOWWINDOW messages and all */
2411 if (dwStyle & WS_VISIBLE)
2412 ShowWindow( hwndChild, SW_HIDE );
2414 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2416 /* SetParent32 additionally needs to make hwndChild the topmost window
2417 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2418 WM_WINDOWPOSCHANGED notification messages.
2420 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2421 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2422 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2423 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2425 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2427 WIN_ReleaseWndPtr(pWndOldParent);
2428 WIN_ReleaseWndPtr(pWndNewParent);
2429 WIN_ReleaseWndPtr(wndPtr);
2431 return retvalue;
2435 /*******************************************************************
2436 * IsChild16 (USER.48)
2438 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2440 return IsChild(parent,child);
2444 /*******************************************************************
2445 * IsChild32 (USER32.339)
2447 BOOL WINAPI IsChild( HWND parent, HWND child )
2449 WND * wndPtr = WIN_FindWndPtr( child );
2450 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2452 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2453 if (wndPtr->hwndSelf == parent)
2455 WIN_ReleaseWndPtr(wndPtr);
2456 return TRUE;
2459 WIN_ReleaseWndPtr(wndPtr);
2460 return FALSE;
2464 /***********************************************************************
2465 * IsWindowVisible16 (USER.49)
2467 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2469 return IsWindowVisible(hwnd);
2473 /***********************************************************************
2474 * IsWindowVisible32 (USER32.351)
2476 BOOL WINAPI IsWindowVisible( HWND hwnd )
2478 BOOL retval;
2479 WND *wndPtr = WIN_FindWndPtr( hwnd );
2480 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2482 if (!(wndPtr->dwStyle & WS_VISIBLE))
2484 WIN_ReleaseWndPtr(wndPtr);
2485 return FALSE;
2487 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2489 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2490 WIN_ReleaseWndPtr(wndPtr);
2491 return retval;
2496 /***********************************************************************
2497 * WIN_IsWindowDrawable
2499 * hwnd is drawable when it is visible, all parents are not
2500 * minimized, and it is itself not minimized unless we are
2501 * trying to draw its default class icon.
2503 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2505 if( (wnd->dwStyle & WS_MINIMIZE &&
2506 icon && wnd->class->hIcon) ||
2507 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2508 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2509 if( wnd->dwStyle & WS_MINIMIZE ||
2510 !(wnd->dwStyle & WS_VISIBLE) ) break;
2511 return (wnd == NULL);
2515 /*******************************************************************
2516 * GetTopWindow16 (USER.229)
2518 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2520 return GetTopWindow(hwnd);
2524 /*******************************************************************
2525 * GetTopWindow32 (USER.229)
2527 HWND WINAPI GetTopWindow( HWND hwnd )
2529 HWND retval;
2530 WND * wndPtr = NULL;
2532 if (hwnd!=0)
2533 wndPtr = WIN_FindWndPtr( hwnd );
2534 else
2535 wndPtr = WIN_GetDesktop();
2537 if (wndPtr && wndPtr->child)
2539 retval = wndPtr->child->hwndSelf;
2541 else retval = 0;
2542 WIN_ReleaseWndPtr(wndPtr);
2543 return retval;
2547 /*******************************************************************
2548 * GetWindow16 (USER.262)
2550 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2552 return GetWindow( hwnd,rel );
2556 /*******************************************************************
2557 * GetWindow32 (USER32.302)
2559 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2561 HWND retval;
2563 WND * wndPtr = WIN_FindWndPtr( hwnd );
2564 if (!wndPtr) return 0;
2565 switch(rel)
2567 case GW_HWNDFIRST:
2568 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2569 else retval = 0;
2570 goto end;
2572 case GW_HWNDLAST:
2573 if (!wndPtr->parent)
2575 retval = 0; /* Desktop window */
2576 goto end;
2578 while (wndPtr->next)
2580 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2582 retval = wndPtr->hwndSelf;
2583 goto end;
2585 case GW_HWNDNEXT:
2586 if (!wndPtr->next) retval = 0;
2587 else retval = wndPtr->next->hwndSelf;
2588 goto end;
2590 case GW_HWNDPREV:
2591 if (!wndPtr->parent)
2593 retval = 0; /* Desktop window */
2594 goto end;
2596 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2597 if (wndPtr->hwndSelf == hwnd)
2599 retval = 0; /* First in list */
2600 goto end;
2602 while (wndPtr->next)
2604 if (wndPtr->next->hwndSelf == hwnd)
2606 retval = wndPtr->hwndSelf;
2607 goto end;
2609 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2611 retval = 0;
2612 goto end;
2614 case GW_OWNER:
2615 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2616 goto end;
2618 case GW_CHILD:
2619 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2620 goto end;
2622 retval = 0;
2623 end:
2624 WIN_ReleaseWndPtr(wndPtr);
2625 return retval;
2629 /*******************************************************************
2630 * GetNextWindow16 (USER.230)
2632 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2634 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2635 return GetWindow16( hwnd, flag );
2638 /*******************************************************************
2639 * ShowOwnedPopups16 (USER.265)
2641 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2643 ShowOwnedPopups( owner, fShow );
2647 /*******************************************************************
2648 * ShowOwnedPopups32 (USER32.531)
2650 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2652 UINT totalChild=0, count=0;
2654 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2656 if (!pWnd) return TRUE;
2658 for (; count < totalChild; count++)
2660 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2661 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, fShow ? SW_SHOW : SW_HIDE,IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2664 WIN_ReleaseDesktop();
2665 WIN_ReleaseWinArray(pWnd);
2666 return TRUE;
2670 /*******************************************************************
2671 * GetLastActivePopup16 (USER.287)
2673 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2675 return GetLastActivePopup( hwnd );
2678 /*******************************************************************
2679 * GetLastActivePopup32 (USER32.256)
2681 HWND WINAPI GetLastActivePopup( HWND hwnd )
2683 WND *wndPtr;
2684 HWND retval;
2685 wndPtr = WIN_FindWndPtr(hwnd);
2686 if (!wndPtr) return hwnd;
2687 retval = wndPtr->hwndLastActive;
2688 WIN_ReleaseWndPtr(wndPtr);
2689 return retval;
2693 /*******************************************************************
2694 * WIN_BuildWinArray
2696 * Build an array of pointers to the children of a given window.
2697 * The array must be freed with HeapFree(SystemHeap). Return NULL
2698 * when no windows are found.
2700 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2702 /* Future : this function will lock all windows associated with this array */
2704 WND **list, **ppWnd;
2705 WND *pWnd;
2706 UINT count = 0, skipOwned, skipHidden;
2707 DWORD skipFlags;
2709 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2710 skipOwned = bwaFlags & BWA_SKIPOWNED;
2711 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2712 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2714 /* First count the windows */
2716 if (!wndPtr)
2717 wndPtr = WIN_GetDesktop();
2719 pWnd = WIN_LockWndPtr(wndPtr->child);
2720 while (pWnd)
2722 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2723 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2724 count++;
2725 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2728 if( count )
2730 /* Now build the list of all windows */
2732 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2734 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2736 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2737 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2739 *ppWnd++ = pWnd;
2740 count++;
2743 WIN_ReleaseWndPtr(pWnd);
2744 *ppWnd = NULL;
2746 else count = 0;
2747 } else list = NULL;
2749 if( pTotal ) *pTotal = count;
2750 return list;
2752 /*******************************************************************
2753 * WIN_ReleaseWinArray
2755 void WIN_ReleaseWinArray(WND **wndArray)
2757 /* Future : this function will also unlock all windows associated with wndArray */
2758 HeapFree( SystemHeap, 0, wndArray );
2762 /*******************************************************************
2763 * EnumWindows16 (USER.54)
2765 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2767 WND **list, **ppWnd;
2769 /* We have to build a list of all windows first, to avoid */
2770 /* unpleasant side-effects, for instance if the callback */
2771 /* function changes the Z-order of the windows. */
2773 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2775 WIN_ReleaseDesktop();
2776 return FALSE;
2779 /* Now call the callback function for every window */
2781 for (ppWnd = list; *ppWnd; ppWnd++)
2783 LRESULT lpEnumFuncRetval;
2784 int iWndsLocks = 0;
2785 /* Make sure that the window still exists */
2786 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2788 /* To avoid any deadlocks, all the locks on the windows
2789 structures must be suspended before the control
2790 is passed to the application */
2791 iWndsLocks = WIN_SuspendWndsLock();
2792 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2793 WIN_RestoreWndsLock(iWndsLocks);
2795 if (!lpEnumFuncRetval) break;
2797 WIN_ReleaseWinArray(list);
2798 WIN_ReleaseDesktop();
2799 return TRUE;
2803 /*******************************************************************
2804 * EnumWindows32 (USER32.193)
2806 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2808 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2812 /**********************************************************************
2813 * EnumTaskWindows16 (USER.225)
2815 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2816 LPARAM lParam )
2818 WND **list, **ppWnd;
2820 /* This function is the same as EnumWindows(), */
2821 /* except for an added check on the window's task. */
2823 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2825 WIN_ReleaseDesktop();
2826 return FALSE;
2829 /* Now call the callback function for every window */
2831 for (ppWnd = list; *ppWnd; ppWnd++)
2833 LRESULT funcRetval;
2834 int iWndsLocks = 0;
2835 /* Make sure that the window still exists */
2836 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2837 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2839 /* To avoid any deadlocks, all the locks on the windows
2840 structures must be suspended before the control
2841 is passed to the application */
2842 iWndsLocks = WIN_SuspendWndsLock();
2843 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2844 WIN_RestoreWndsLock(iWndsLocks);
2846 if (!funcRetval) break;
2848 WIN_ReleaseWinArray(list);
2849 WIN_ReleaseDesktop();
2850 return TRUE;
2854 /**********************************************************************
2855 * EnumThreadWindows (USER32.190)
2857 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2859 TEB *teb = THREAD_IdToTEB(id);
2861 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2865 /**********************************************************************
2866 * WIN_EnumChildWindows
2868 * Helper function for EnumChildWindows().
2870 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2871 LPARAM lParam )
2873 WND **childList;
2874 BOOL16 ret = FALSE;
2876 for ( ; *ppWnd; ppWnd++)
2878 int iWndsLocks = 0;
2880 /* Make sure that the window still exists */
2881 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2882 /* Build children list first */
2883 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2885 /* To avoid any deadlocks, all the locks on the windows
2886 structures must be suspended before the control
2887 is passed to the application */
2888 iWndsLocks = WIN_SuspendWndsLock();
2889 ret = func( (*ppWnd)->hwndSelf, lParam );
2890 WIN_RestoreWndsLock(iWndsLocks);
2892 if (childList)
2894 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2895 WIN_ReleaseWinArray(childList);
2897 if (!ret) return FALSE;
2899 return TRUE;
2903 /**********************************************************************
2904 * EnumChildWindows16 (USER.55)
2906 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2907 LPARAM lParam )
2909 WND **list, *pParent;
2911 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2912 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2914 WIN_ReleaseWndPtr(pParent);
2915 return FALSE;
2917 WIN_EnumChildWindows( list, func, lParam );
2918 WIN_ReleaseWinArray(list);
2919 WIN_ReleaseWndPtr(pParent);
2920 return TRUE;
2924 /**********************************************************************
2925 * EnumChildWindows32 (USER32.178)
2927 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2928 LPARAM lParam )
2930 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2931 lParam );
2935 /*******************************************************************
2936 * AnyPopup16 (USER.52)
2938 BOOL16 WINAPI AnyPopup16(void)
2940 return AnyPopup();
2944 /*******************************************************************
2945 * AnyPopup32 (USER32.4)
2947 BOOL WINAPI AnyPopup(void)
2949 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2950 BOOL retvalue;
2952 while (wndPtr)
2954 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2956 retvalue = TRUE;
2957 goto end;
2959 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2961 retvalue = FALSE;
2962 end:
2963 WIN_ReleaseWndPtr(wndPtr);
2964 return retvalue;
2968 /*******************************************************************
2969 * FlashWindow16 (USER.105)
2971 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2973 return FlashWindow( hWnd, bInvert );
2977 /*******************************************************************
2978 * FlashWindow32 (USER32.202)
2980 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2982 WND *wndPtr = WIN_FindWndPtr(hWnd);
2984 TRACE_(win)("%04x\n", hWnd);
2986 if (!wndPtr) return FALSE;
2988 if (wndPtr->dwStyle & WS_MINIMIZE)
2990 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2992 HDC hDC = GetDC(hWnd);
2994 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2995 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2997 ReleaseDC( hWnd, hDC );
2998 wndPtr->flags |= WIN_NCACTIVATED;
3000 else
3002 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3003 RDW_UPDATENOW | RDW_FRAME, 0 );
3004 wndPtr->flags &= ~WIN_NCACTIVATED;
3006 WIN_ReleaseWndPtr(wndPtr);
3007 return TRUE;
3009 else
3011 WPARAM16 wparam;
3012 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3013 else wparam = (hWnd == GetActiveWindow());
3015 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3016 WIN_ReleaseWndPtr(wndPtr);
3017 return wparam;
3022 /*******************************************************************
3023 * SetSysModalWindow16 (USER.188)
3025 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3027 HWND hWndOldModal = hwndSysModal;
3028 hwndSysModal = hWnd;
3029 FIXME_(win)("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3030 return hWndOldModal;
3034 /*******************************************************************
3035 * GetSysModalWindow16 (USER.52)
3037 HWND16 WINAPI GetSysModalWindow16(void)
3039 return hwndSysModal;
3043 /*******************************************************************
3044 * GetWindowContextHelpId (USER32.303)
3046 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3048 DWORD retval;
3049 WND *wnd = WIN_FindWndPtr( hwnd );
3050 if (!wnd) return 0;
3051 retval = wnd->helpContext;
3052 WIN_ReleaseWndPtr(wnd);
3053 return retval;
3057 /*******************************************************************
3058 * SetWindowContextHelpId (USER32.515)
3060 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3062 WND *wnd = WIN_FindWndPtr( hwnd );
3063 if (!wnd) return FALSE;
3064 wnd->helpContext = id;
3065 WIN_ReleaseWndPtr(wnd);
3066 return TRUE;
3070 /*******************************************************************
3071 * DRAG_QueryUpdate
3073 * recursively find a child that contains spDragInfo->pt point
3074 * and send WM_QUERYDROPOBJECT
3076 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3078 BOOL16 wParam,bResult = 0;
3079 POINT pt;
3080 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3081 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3082 RECT tempRect;
3084 if( !ptrQueryWnd || !ptrDragInfo )
3086 WIN_ReleaseWndPtr(ptrQueryWnd);
3087 return 0;
3090 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3092 GetWindowRect(hQueryWnd,&tempRect);
3094 if( !PtInRect(&tempRect,pt) ||
3095 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3097 WIN_ReleaseWndPtr(ptrQueryWnd);
3098 return 0;
3101 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3103 tempRect = ptrQueryWnd->rectClient;
3104 if(ptrQueryWnd->dwStyle & WS_CHILD)
3105 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3106 (LPPOINT)&tempRect, 2 );
3108 if (PtInRect( &tempRect, pt))
3110 wParam = 0;
3112 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3114 if( ptrWnd->dwStyle & WS_VISIBLE )
3116 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3117 if (PtInRect( &tempRect, pt )) break;
3121 if(ptrWnd)
3123 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3124 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3125 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3126 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3127 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3129 WIN_ReleaseWndPtr(ptrWnd);
3132 if(bResult)
3134 WIN_ReleaseWndPtr(ptrQueryWnd);
3135 return bResult;
3138 else wParam = 1;
3140 else wParam = 1;
3142 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3144 ptrDragInfo->hScope = hQueryWnd;
3146 bResult = ( bNoSend )
3147 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3148 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3149 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3150 if( !bResult )
3151 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3153 WIN_ReleaseWndPtr(ptrQueryWnd);
3154 return bResult;
3158 /*******************************************************************
3159 * DragDetect (USER.465)
3161 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3163 POINT pt32;
3164 CONV_POINT16TO32( &pt, &pt32 );
3165 return DragDetect( hWnd, pt32 );
3168 /*******************************************************************
3169 * DragDetect32 (USER32.151)
3171 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3173 MSG16 msg;
3174 RECT16 rect;
3176 rect.left = pt.x - wDragWidth;
3177 rect.right = pt.x + wDragWidth;
3179 rect.top = pt.y - wDragHeight;
3180 rect.bottom = pt.y + wDragHeight;
3182 SetCapture(hWnd);
3184 while(1)
3186 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3188 if( msg.message == WM_LBUTTONUP )
3190 ReleaseCapture();
3191 return 0;
3193 if( msg.message == WM_MOUSEMOVE )
3195 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3197 ReleaseCapture();
3198 return 1;
3202 WaitMessage();
3204 return 0;
3207 /******************************************************************************
3208 * DragObject16 (USER.464)
3210 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3211 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3213 MSG16 msg;
3214 LPDRAGINFO lpDragInfo;
3215 SEGPTR spDragInfo;
3216 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3217 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3218 WND *wndPtr = WIN_FindWndPtr(hWnd);
3219 HCURSOR16 hCurrentCursor = 0;
3220 HWND16 hCurrentWnd = 0;
3222 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3223 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3225 if( !lpDragInfo || !spDragInfo )
3227 WIN_ReleaseWndPtr(wndPtr);
3228 return 0L;
3231 hBummer = LoadCursor16(0, IDC_BUMMER16);
3233 if( !hBummer || !wndPtr )
3235 GlobalFree16(hDragInfo);
3236 WIN_ReleaseWndPtr(wndPtr);
3237 return 0L;
3240 if(hCursor)
3242 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3244 GlobalFree16(hDragInfo);
3245 WIN_ReleaseWndPtr(wndPtr);
3246 return 0L;
3249 if( hDragCursor == hCursor ) hDragCursor = 0;
3250 else hCursor = hDragCursor;
3252 hOldCursor = SetCursor(hDragCursor);
3255 lpDragInfo->hWnd = hWnd;
3256 lpDragInfo->hScope = 0;
3257 lpDragInfo->wFlags = wObj;
3258 lpDragInfo->hList = szList; /* near pointer! */
3259 lpDragInfo->hOfStruct = hOfStruct;
3260 lpDragInfo->l = 0L;
3262 SetCapture(hWnd);
3263 ShowCursor( TRUE );
3267 do{ WaitMessage(); }
3268 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3270 *(lpDragInfo+1) = *lpDragInfo;
3272 lpDragInfo->pt = msg.pt;
3274 /* update DRAGINFO struct */
3275 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3277 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3278 hCurrentCursor = hCursor;
3279 else
3281 hCurrentCursor = hBummer;
3282 lpDragInfo->hScope = 0;
3284 if( hCurrentCursor )
3285 SetCursor(hCurrentCursor);
3287 /* send WM_DRAGLOOP */
3288 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3289 (LPARAM) spDragInfo );
3290 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3291 if( hCurrentWnd != lpDragInfo->hScope )
3293 if( hCurrentWnd )
3294 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3295 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3296 HIWORD(spDragInfo)) );
3297 hCurrentWnd = lpDragInfo->hScope;
3298 if( hCurrentWnd )
3299 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3301 else
3302 if( hCurrentWnd )
3303 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3305 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3307 ReleaseCapture();
3308 ShowCursor( FALSE );
3310 if( hCursor )
3312 SetCursor( hOldCursor );
3313 if (hDragCursor) DestroyCursor( hDragCursor );
3316 if( hCurrentCursor != hBummer )
3317 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3318 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3319 else
3320 msg.lParam = 0;
3321 GlobalFree16(hDragInfo);
3322 WIN_ReleaseWndPtr(wndPtr);
3324 return (DWORD)(msg.lParam);