Make sure that HWND comparisons are always done with full 32-bit
[wine/multimedia.git] / windows / win.c
blob5684fb945e4570a9f1f47f3af991f8362af5efb1
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/server.h"
13 #include "wine/unicode.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "controls.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "message.h"
22 #include "queue.h"
23 #include "task.h"
24 #include "winpos.h"
25 #include "winerror.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(win);
30 DECLARE_DEBUG_CHANNEL(msg);
32 /**********************************************************************/
34 /* Desktop window */
35 static WND *pWndDesktop = NULL;
37 static HWND hwndSysModal = 0;
39 static WORD wDragWidth = 4;
40 static WORD wDragHeight= 3;
42 static void *user_handles[65536];
44 /* thread safeness */
45 extern SYSLEVEL USER_SysLevel; /* FIXME */
47 /***********************************************************************
48 * WIN_SuspendWndsLock
50 * Suspend the lock on WND structures.
51 * Returns the number of locks suspended
53 int WIN_SuspendWndsLock( void )
55 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
56 int count = isuspendedLocks;
58 while ( count-- > 0 )
59 _LeaveSysLevel( &USER_SysLevel );
61 return isuspendedLocks;
64 /***********************************************************************
65 * WIN_RestoreWndsLock
67 * Restore the suspended locks on WND structures
69 void WIN_RestoreWndsLock( int ipreviousLocks )
71 while ( ipreviousLocks-- > 0 )
72 _EnterSysLevel( &USER_SysLevel );
75 /***********************************************************************
76 * create_window_handle
78 * Create a window handle with the server.
80 static WND *create_window_handle( BOOL desktop, INT size )
82 BOOL res;
83 unsigned int handle = 0;
84 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
86 if (!win) return NULL;
88 USER_Lock();
90 if (desktop)
92 SERVER_START_REQ( create_desktop_window )
94 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
96 SERVER_END_REQ;
98 else
100 SERVER_START_REQ( create_window )
102 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
104 SERVER_END_REQ;
107 if (!res)
109 USER_Unlock();
110 HeapFree( GetProcessHeap(), 0, win );
111 return NULL;
113 user_handles[LOWORD(handle)] = win;
114 win->hwndSelf = (HWND)handle;
115 win->dwMagic = WND_MAGIC;
116 win->irefCount = 1;
117 return win;
121 /***********************************************************************
122 * free_window_handle
124 * Free a window handle.
126 static WND *free_window_handle( HWND hwnd )
128 WND *ptr;
130 USER_Lock();
131 if ((ptr = user_handles[LOWORD(hwnd)]))
133 SERVER_START_REQ( destroy_window )
135 req->handle = hwnd;
136 if (!SERVER_CALL_ERR())
137 user_handles[LOWORD(hwnd)] = NULL;
138 else
139 ptr = NULL;
141 SERVER_END_REQ;
143 USER_Unlock();
144 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
145 return ptr;
149 /***********************************************************************
150 * get_wnd_ptr
152 * Return a pointer to the WND structure if local to the process.
153 * If ret value is non-NULL, the user lock is held.
155 static WND *get_wnd_ptr( HWND hwnd )
157 WND * ptr;
159 if (!hwnd) return NULL;
161 USER_Lock();
162 if ((ptr = user_handles[LOWORD(hwnd)]))
164 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
165 return ptr;
167 USER_Unlock();
168 return NULL;
172 /***********************************************************************
173 * WIN_Handle32
175 * Convert a 16-bit window handle to a full 32-bit handle.
177 HWND WIN_Handle32( HWND16 hwnd16 )
179 WND *ptr;
180 HWND hwnd = (HWND)hwnd16;
182 if (!hwnd || hwnd == HWND_BROADCAST) return hwnd;
184 if ((ptr = get_wnd_ptr( hwnd )))
186 hwnd = ptr->hwndSelf;
187 USER_Unlock();
189 else /* may belong to another process */
191 SERVER_START_REQ( get_window_info )
193 req->handle = (user_handle_t)hwnd16;
194 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
196 SERVER_END_REQ;
198 return hwnd;
202 /***********************************************************************
203 * WIN_FindWndPtr
205 * Return a pointer to the WND structure corresponding to a HWND.
207 WND * WIN_FindWndPtr( HWND hwnd )
209 WND * ptr;
211 if (!hwnd) return NULL;
213 if ((ptr = get_wnd_ptr( hwnd )))
215 /* increment destruction monitoring */
216 ptr->irefCount++;
217 return ptr;
220 /* check other processes */
221 if (IsWindow( hwnd ))
223 ERR( "window %04x belongs to other process\n", hwnd );
224 /* DbgBreakPoint(); */
226 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
227 return NULL;
231 /***********************************************************************
232 * WIN_LockWndPtr
234 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
235 * but by initWndPtr;
236 * Returns the locked initialisation pointer
238 WND *WIN_LockWndPtr(WND *initWndPtr)
240 if(!initWndPtr) return 0;
242 /* Lock all WND structures for thread safeness*/
243 USER_Lock();
244 /*and increment destruction monitoring*/
245 initWndPtr->irefCount++;
247 return initWndPtr;
251 /***********************************************************************
252 * WIN_ReleaseWndPtr
254 * Release the pointer to the WND structure.
256 void WIN_ReleaseWndPtr(WND *wndPtr)
258 if(!wndPtr) return;
260 /*Decrement destruction monitoring value*/
261 wndPtr->irefCount--;
262 /* Check if it's time to release the memory*/
263 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
265 /* Release memory */
266 free_window_handle( wndPtr->hwndSelf );
268 else if(wndPtr->irefCount < 0)
270 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
271 ERR("forgot a Lock on %p somewhere\n",wndPtr);
273 /*unlock all WND structures for thread safeness*/
274 USER_Unlock();
277 /***********************************************************************
278 * WIN_UpdateWndPtr
280 * Updates the value of oldPtr to newPtr.
282 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
284 WND *tmpWnd = NULL;
286 tmpWnd = WIN_LockWndPtr(newPtr);
287 WIN_ReleaseWndPtr(*oldPtr);
288 *oldPtr = tmpWnd;
293 /***********************************************************************
294 * WIN_UnlinkWindow
296 * Remove a window from the siblings linked list.
298 void WIN_UnlinkWindow( HWND hwnd )
300 WIN_LinkWindow( hwnd, 0, 0 );
304 /***********************************************************************
305 * WIN_LinkWindow
307 * Insert a window into the siblings linked list.
308 * The window is inserted after the specified window, which can also
309 * be specified as HWND_TOP or HWND_BOTTOM.
310 * If parent is 0, window is unlinked from the tree.
312 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
314 WND *wndPtr, **ppWnd, *parentPtr = NULL;
315 BOOL ret;
317 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
318 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
320 WIN_ReleaseWndPtr(wndPtr);
321 return;
324 SERVER_START_REQ( link_window )
326 req->handle = hwnd;
327 req->parent = parent;
328 req->previous = hwndInsertAfter;
329 ret = !SERVER_CALL_ERR();
331 SERVER_END_REQ;
332 if (!ret) goto done;
334 /* first unlink it if it is linked */
335 if (wndPtr->parent)
337 ppWnd = &wndPtr->parent->child;
338 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
339 if (*ppWnd) *ppWnd = wndPtr->next;
342 if (parentPtr)
344 wndPtr->parent = parentPtr;
345 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
347 ppWnd = &parentPtr->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) goto done;
355 ppWnd = &afterPtr->next;
356 WIN_ReleaseWndPtr(afterPtr);
358 wndPtr->next = *ppWnd;
359 *ppWnd = wndPtr;
361 else wndPtr->next = NULL; /* unlinked */
363 done:
364 WIN_ReleaseWndPtr( parentPtr );
365 WIN_ReleaseWndPtr( wndPtr );
369 /***********************************************************************
370 * WIN_FindWinToRepaint
372 * Find a window that needs repaint.
374 HWND WIN_FindWinToRepaint( HWND hwnd )
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.
383 if (hwnd == GetDesktopWindow()) hwnd = 0;
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
390 if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
391 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
392 break;
393 if (pWnd->child )
395 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
397 WIN_ReleaseWndPtr(pWnd);
398 return hwndRet;
403 if(!pWnd)
405 TRACE("nothing found\n");
406 return 0;
408 hwndRet = pWnd->hwndSelf;
410 /* look among siblings if we got a transparent window */
411 while (pWnd)
413 if (!(pWnd->dwExStyle & WS_EX_TRANSPARENT) &&
414 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
415 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
417 hwndRet = pWnd->hwndSelf;
418 WIN_ReleaseWndPtr(pWnd);
419 break;
421 WIN_UpdateWndPtr(&pWnd,pWnd->next);
423 TRACE("found %04x\n",hwndRet);
424 return hwndRet;
428 /***********************************************************************
429 * WIN_DestroyWindow
431 * Destroy storage associated to a window. "Internals" p.358
432 * returns a locked wndPtr->next
434 static WND* WIN_DestroyWindow( WND* wndPtr )
436 HWND hwnd = wndPtr->hwndSelf;
437 WND *pWnd;
439 TRACE("%04x\n", wndPtr->hwndSelf );
441 /* free child windows */
442 WIN_LockWndPtr(wndPtr->child);
443 while ((pWnd = wndPtr->child))
445 wndPtr->child = WIN_DestroyWindow( pWnd );
446 WIN_ReleaseWndPtr(pWnd);
450 * Clear the update region to make sure no WM_PAINT messages will be
451 * generated for this window while processing the WM_NCDESTROY.
453 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
454 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
457 * Send the WM_NCDESTROY to the window being destroyed.
459 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
461 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
463 WINPOS_CheckInternalPos( hwnd );
464 if( hwnd == GetCapture()) ReleaseCapture();
466 /* free resources associated with the window */
468 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
469 PROPERTY_RemoveWindowProps( wndPtr );
471 /* toss stale messages from the queue */
473 QUEUE_CleanupWindow( hwnd );
474 wndPtr->hmemTaskQ = 0;
476 if (!(wndPtr->dwStyle & WS_CHILD))
477 if (wndPtr->wIDmenu)
479 DestroyMenu( wndPtr->wIDmenu );
480 wndPtr->wIDmenu = 0;
482 if (wndPtr->hSysMenu)
484 DestroyMenu( wndPtr->hSysMenu );
485 wndPtr->hSysMenu = 0;
487 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
488 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
489 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
490 CLASS_RemoveWindow( wndPtr->class );
491 wndPtr->class = NULL;
492 wndPtr->dwMagic = 0; /* Mark it as invalid */
494 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
496 return pWnd;
499 /***********************************************************************
500 * WIN_DestroyThreadWindows
502 * Destroy all children of 'wnd' owned by the current thread.
503 * Return TRUE if something was done.
505 void WIN_DestroyThreadWindows( HWND hwnd )
507 HWND *list;
508 int i;
510 if (!(list = WIN_ListChildren( hwnd ))) return;
511 for (i = 0; list[i]; i++)
513 if (!IsWindow( list[i] )) continue;
514 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
515 DestroyWindow( list[i] );
516 else
517 WIN_DestroyThreadWindows( list[i] );
519 HeapFree( GetProcessHeap(), 0, list );
522 /***********************************************************************
523 * WIN_CreateDesktopWindow
525 * Create the desktop window.
527 BOOL WIN_CreateDesktopWindow(void)
529 struct tagCLASS *class;
530 HWND hwndDesktop;
531 INT wndExtra;
532 DWORD clsStyle;
533 WNDPROC winproc;
534 DCE *dce;
535 CREATESTRUCTA cs;
537 TRACE("Creating desktop window\n");
540 if (!WINPOS_CreateInternalPosAtom() ||
541 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
542 &wndExtra, &winproc, &clsStyle, &dce )))
543 return FALSE;
545 pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra );
546 if (!pWndDesktop) return FALSE;
547 hwndDesktop = pWndDesktop->hwndSelf;
549 pWndDesktop->tid = 0; /* nobody owns the desktop */
550 pWndDesktop->next = NULL;
551 pWndDesktop->child = NULL;
552 pWndDesktop->parent = NULL;
553 pWndDesktop->owner = 0;
554 pWndDesktop->class = class;
555 pWndDesktop->hInstance = 0;
556 pWndDesktop->rectWindow.left = 0;
557 pWndDesktop->rectWindow.top = 0;
558 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
559 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
560 pWndDesktop->rectClient = pWndDesktop->rectWindow;
561 pWndDesktop->text = NULL;
562 pWndDesktop->hmemTaskQ = 0;
563 pWndDesktop->hrgnUpdate = 0;
564 pWndDesktop->hwndLastActive = hwndDesktop;
565 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
566 WS_CLIPSIBLINGS;
567 pWndDesktop->dwExStyle = 0;
568 pWndDesktop->clsStyle = clsStyle;
569 pWndDesktop->dce = NULL;
570 pWndDesktop->pVScroll = NULL;
571 pWndDesktop->pHScroll = NULL;
572 pWndDesktop->pProp = NULL;
573 pWndDesktop->wIDmenu = 0;
574 pWndDesktop->helpContext = 0;
575 pWndDesktop->flags = 0;
576 pWndDesktop->hSysMenu = 0;
577 pWndDesktop->userdata = 0;
578 pWndDesktop->winproc = winproc;
579 pWndDesktop->cbWndExtra = wndExtra;
581 cs.lpCreateParams = NULL;
582 cs.hInstance = 0;
583 cs.hMenu = 0;
584 cs.hwndParent = 0;
585 cs.x = 0;
586 cs.y = 0;
587 cs.cx = pWndDesktop->rectWindow.right;
588 cs.cy = pWndDesktop->rectWindow.bottom;
589 cs.style = pWndDesktop->dwStyle;
590 cs.dwExStyle = pWndDesktop->dwExStyle;
591 cs.lpszName = NULL;
592 cs.lpszClass = DESKTOP_CLASS_ATOM;
594 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
596 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
597 WIN_ReleaseWndPtr( pWndDesktop );
598 return TRUE;
602 /***********************************************************************
603 * WIN_FixCoordinates
605 * Fix the coordinates - Helper for WIN_CreateWindowEx.
606 * returns default show mode in sw.
607 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
609 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
611 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
612 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
614 if (cs->style & (WS_CHILD | WS_POPUP))
616 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
617 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
619 else /* overlapped window */
621 STARTUPINFOA info;
623 GetStartupInfoA( &info );
625 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
627 /* Never believe Microsoft's documentation... CreateWindowEx doc says
628 * that if an overlapped window is created with WS_VISIBLE style bit
629 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
630 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
631 * reveals that
633 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
634 * 2) it does not ignore the y parameter as the docs claim; instead, it
635 * uses it as second parameter to ShowWindow() unless y is either
636 * CW_USEDEFAULT or CW_USEDEFAULT16.
638 * The fact that we didn't do 2) caused bogus windows pop up when wine
639 * was running apps that were using this obscure feature. Example -
640 * calc.exe that comes with Win98 (only Win98, it's different from
641 * the one that comes with Win95 and NT)
643 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
644 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
645 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
648 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
650 if (info.dwFlags & STARTF_USESIZE)
652 cs->cx = info.dwXSize;
653 cs->cy = info.dwYSize;
655 else /* if no other hint from the app, pick 3/4 of the screen real estate */
657 RECT r;
658 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
659 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
660 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
667 /***********************************************************************
668 * WIN_CreateWindowEx
670 * Implementation of CreateWindowEx().
672 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
673 WINDOWPROCTYPE type )
675 INT sw = SW_SHOW;
676 struct tagCLASS *classPtr;
677 WND *wndPtr;
678 HWND hwnd, hwndLinkAfter;
679 POINT maxSize, maxPos, minTrack, maxTrack;
680 INT wndExtra;
681 DWORD clsStyle;
682 WNDPROC winproc;
683 DCE *dce;
684 BOOL unicode = (type == WIN_PROC_32W);
686 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
687 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
688 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
689 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
690 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
692 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
693 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
695 /* Find the parent window */
697 if (cs->hwndParent)
699 /* Make sure parent is valid */
700 if (!IsWindow( cs->hwndParent ))
702 WARN("Bad parent %04x\n", cs->hwndParent );
703 return 0;
705 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
706 WARN("No parent for child window\n" );
707 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
710 /* Find the window class */
711 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
712 &wndExtra, &winproc, &clsStyle, &dce )))
714 WARN("Bad class '%s'\n", cs->lpszClass );
715 return 0;
718 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
720 /* Correct the window style - stage 1
722 * These are patches that appear to affect both the style loaded into the
723 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
725 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
726 * why does the user get to set it?
729 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
730 * tested for WS_POPUP
732 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
733 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
734 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
735 cs->dwExStyle |= WS_EX_WINDOWEDGE;
736 else
737 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
739 /* Create the window structure */
741 if (!(wndPtr = create_window_handle( FALSE,
742 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
744 TRACE("out of memory\n" );
745 return 0;
747 hwnd = wndPtr->hwndSelf;
749 /* Fill the window structure */
751 wndPtr->tid = GetCurrentThreadId();
752 wndPtr->next = NULL;
753 wndPtr->child = NULL;
755 if ((cs->style & WS_CHILD) && cs->hwndParent)
757 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
758 wndPtr->owner = 0;
759 WIN_ReleaseWndPtr(wndPtr->parent);
761 else
763 wndPtr->parent = pWndDesktop;
764 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
765 wndPtr->owner = 0;
766 else
767 wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
771 wndPtr->class = classPtr;
772 wndPtr->winproc = winproc;
773 wndPtr->hInstance = cs->hInstance;
774 wndPtr->text = NULL;
775 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
776 wndPtr->hrgnUpdate = 0;
777 wndPtr->hrgnWnd = 0;
778 wndPtr->hwndLastActive = hwnd;
779 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
780 wndPtr->dwExStyle = cs->dwExStyle;
781 wndPtr->clsStyle = clsStyle;
782 wndPtr->wIDmenu = 0;
783 wndPtr->helpContext = 0;
784 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
785 wndPtr->pVScroll = NULL;
786 wndPtr->pHScroll = NULL;
787 wndPtr->pProp = NULL;
788 wndPtr->userdata = 0;
789 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
790 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
791 wndPtr->cbWndExtra = wndExtra;
793 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
795 /* Call the WH_CBT hook */
797 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
798 ? HWND_BOTTOM : HWND_TOP;
800 if (HOOK_IsHooked( WH_CBT ))
802 CBT_CREATEWNDA cbtc;
803 LRESULT ret;
805 cbtc.lpcs = cs;
806 cbtc.hwndInsertAfter = hwndLinkAfter;
807 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
808 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
809 if (ret)
811 TRACE("CBT-hook returned 0\n");
812 free_window_handle( hwnd );
813 CLASS_RemoveWindow( classPtr );
814 hwnd = 0;
815 goto end;
819 /* Correct the window style - stage 2 */
821 if (!(cs->style & WS_CHILD))
823 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
824 if (!(cs->style & WS_POPUP))
826 wndPtr->dwStyle |= WS_CAPTION;
827 wndPtr->flags |= WIN_NEED_SIZE;
831 /* Get class or window DC if needed */
833 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
834 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
835 else wndPtr->dce = NULL;
837 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
839 wndPtr->rectWindow.left = cs->x;
840 wndPtr->rectWindow.top = cs->y;
841 wndPtr->rectWindow.right = cs->x + cs->cx;
842 wndPtr->rectWindow.bottom = cs->y + cs->cy;
843 wndPtr->rectClient = wndPtr->rectWindow;
845 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
847 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
849 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
850 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
851 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
852 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
853 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
856 if (cs->cx < 0) cs->cx = 0;
857 if (cs->cy < 0) cs->cy = 0;
859 wndPtr->rectWindow.left = cs->x;
860 wndPtr->rectWindow.top = cs->y;
861 wndPtr->rectWindow.right = cs->x + cs->cx;
862 wndPtr->rectWindow.bottom = cs->y + cs->cy;
863 wndPtr->rectClient = wndPtr->rectWindow;
865 /* Set the window menu */
867 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
869 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
870 else
872 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
873 if (menuName)
875 if (HIWORD(cs->hInstance))
876 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
877 else
878 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
880 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
884 else wndPtr->wIDmenu = (UINT)cs->hMenu;
886 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
888 WARN("aborted by WM_xxCREATE!\n");
889 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
890 CLASS_RemoveWindow( classPtr );
891 WIN_ReleaseWndPtr(wndPtr);
892 return 0;
895 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
897 /* Notify the parent window only */
899 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
900 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
901 if( !IsWindow(hwnd) )
903 hwnd = 0;
904 goto end;
908 if (cs->style & WS_VISIBLE)
910 /* in case WS_VISIBLE got set in the meantime */
911 wndPtr->dwStyle &= ~WS_VISIBLE;
912 ShowWindow( hwnd, sw );
915 /* Call WH_SHELL hook */
917 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
918 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
920 TRACE("created window %04x\n", hwnd);
921 end:
922 WIN_ReleaseWndPtr(wndPtr);
923 return hwnd;
927 /***********************************************************************
928 * CreateWindow (USER.41)
930 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
931 DWORD style, INT16 x, INT16 y, INT16 width,
932 INT16 height, HWND16 parent, HMENU16 menu,
933 HINSTANCE16 instance, LPVOID data )
935 return CreateWindowEx16( 0, className, windowName, style,
936 x, y, width, height, parent, menu, instance, data );
940 /***********************************************************************
941 * CreateWindowEx (USER.452)
943 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
944 LPCSTR windowName, DWORD style, INT16 x,
945 INT16 y, INT16 width, INT16 height,
946 HWND16 parent, HMENU16 menu,
947 HINSTANCE16 instance, LPVOID data )
949 ATOM classAtom;
950 CREATESTRUCTA cs;
951 char buffer[256];
953 /* Find the class atom */
955 if (HIWORD(className))
957 if (!(classAtom = GlobalFindAtomA( className )))
959 ERR( "bad class name %s\n", debugres_a(className) );
960 return 0;
963 else
965 classAtom = LOWORD(className);
966 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
968 ERR( "bad atom %x\n", classAtom);
969 return 0;
971 className = buffer;
974 /* Fix the coordinates */
976 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
977 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
978 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
979 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
981 /* Create the window */
983 cs.lpCreateParams = data;
984 cs.hInstance = (HINSTANCE)instance;
985 cs.hMenu = (HMENU)menu;
986 cs.hwndParent = (HWND)parent;
987 cs.style = style;
988 cs.lpszName = windowName;
989 cs.lpszClass = className;
990 cs.dwExStyle = exStyle;
992 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
996 /***********************************************************************
997 * CreateWindowExA (USER32.@)
999 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1000 LPCSTR windowName, DWORD style, INT x,
1001 INT y, INT width, INT height,
1002 HWND parent, HMENU menu,
1003 HINSTANCE instance, LPVOID data )
1005 ATOM classAtom;
1006 CREATESTRUCTA cs;
1007 char buffer[256];
1009 if(!instance)
1010 instance=GetModuleHandleA(NULL);
1012 if(exStyle & WS_EX_MDICHILD)
1013 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1015 /* Find the class atom */
1017 if (HIWORD(className))
1019 if (!(classAtom = GlobalFindAtomA( className )))
1021 ERR( "bad class name %s\n", debugres_a(className) );
1022 return 0;
1025 else
1027 classAtom = LOWORD(className);
1028 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1030 ERR( "bad atom %x\n", classAtom);
1031 return 0;
1033 className = buffer;
1036 /* Create the window */
1038 cs.lpCreateParams = data;
1039 cs.hInstance = instance;
1040 cs.hMenu = menu;
1041 cs.hwndParent = parent;
1042 cs.x = x;
1043 cs.y = y;
1044 cs.cx = width;
1045 cs.cy = height;
1046 cs.style = style;
1047 cs.lpszName = windowName;
1048 cs.lpszClass = className;
1049 cs.dwExStyle = exStyle;
1051 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1055 /***********************************************************************
1056 * CreateWindowExW (USER32.@)
1058 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1059 LPCWSTR windowName, DWORD style, INT x,
1060 INT y, INT width, INT height,
1061 HWND parent, HMENU menu,
1062 HINSTANCE instance, LPVOID data )
1064 ATOM classAtom;
1065 CREATESTRUCTW cs;
1066 WCHAR buffer[256];
1068 if(!instance)
1069 instance=GetModuleHandleA(NULL);
1071 if(exStyle & WS_EX_MDICHILD)
1072 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1074 /* Find the class atom */
1076 if (HIWORD(className))
1078 if (!(classAtom = GlobalFindAtomW( className )))
1080 ERR( "bad class name %s\n", debugres_w(className) );
1081 return 0;
1084 else
1086 classAtom = LOWORD(className);
1087 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1089 ERR( "bad atom %x\n", classAtom);
1090 return 0;
1092 className = buffer;
1095 /* Create the window */
1097 cs.lpCreateParams = data;
1098 cs.hInstance = instance;
1099 cs.hMenu = menu;
1100 cs.hwndParent = parent;
1101 cs.x = x;
1102 cs.y = y;
1103 cs.cx = width;
1104 cs.cy = height;
1105 cs.style = style;
1106 cs.lpszName = windowName;
1107 cs.lpszClass = className;
1108 cs.dwExStyle = exStyle;
1110 /* Note: we rely on the fact that CREATESTRUCTA and */
1111 /* CREATESTRUCTW have the same layout. */
1112 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1116 /***********************************************************************
1117 * WIN_SendDestroyMsg
1119 static void WIN_SendDestroyMsg( HWND hwnd )
1121 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1122 if (USER_Driver.pResetSelectionOwner)
1123 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1126 * Send the WM_DESTROY to the window.
1128 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1131 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1132 * make sure that the window still exists when we come back.
1134 if (IsWindow(hwnd))
1136 HWND* pWndArray;
1137 int i;
1139 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1141 /* start from the end (FIXME: is this needed?) */
1142 for (i = 0; pWndArray[i]; i++) ;
1144 while (--i >= 0)
1146 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1148 HeapFree( GetProcessHeap(), 0, pWndArray );
1150 else
1151 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1155 /***********************************************************************
1156 * DestroyWindow (USER.53)
1158 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1160 return DestroyWindow(hwnd);
1164 /***********************************************************************
1165 * DestroyWindow (USER32.@)
1167 BOOL WINAPI DestroyWindow( HWND hwnd )
1169 WND * wndPtr;
1170 BOOL retvalue;
1171 HWND h;
1173 hwnd = WIN_GetFullHandle( hwnd );
1174 TRACE("(%04x)\n", hwnd);
1176 /* Initialization */
1178 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1180 /* Look whether the focus is within the tree of windows we will
1181 * be destroying.
1183 h = GetFocus();
1184 if (h == hwnd || IsChild( hwnd, h ))
1186 HWND parent = GetAncestor( hwnd, GA_PARENT );
1187 if (parent == GetDesktopWindow()) parent = 0;
1188 SetFocus( parent );
1191 /* Call hooks */
1193 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
1195 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1196 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1198 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1199 /* FIXME: clean up palette - see "Internals" p.352 */
1202 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1203 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1205 /* Notify the parent window only */
1206 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1207 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1208 if( !IsWindow(hwnd) )
1210 retvalue = TRUE;
1211 goto end;
1215 if (USER_Driver.pResetSelectionOwner)
1216 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1218 /* Hide the window */
1220 if (wndPtr->dwStyle & WS_VISIBLE)
1222 ShowWindow( hwnd, SW_HIDE );
1223 if (!IsWindow(hwnd))
1225 retvalue = TRUE;
1226 goto end;
1230 /* Recursively destroy owned windows */
1232 if( !(wndPtr->dwStyle & WS_CHILD) )
1234 for (;;)
1236 int i, got_one = 0;
1237 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1238 if (list)
1240 for (i = 0; list[i]; i++)
1242 WND *siblingPtr = WIN_FindWndPtr( list[i] );
1243 if (!siblingPtr) continue;
1244 if (siblingPtr->owner == hwnd)
1246 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1248 WIN_ReleaseWndPtr( siblingPtr );
1249 DestroyWindow( list[i] );
1250 got_one = 1;
1251 continue;
1253 else siblingPtr->owner = 0;
1255 WIN_ReleaseWndPtr( siblingPtr );
1257 HeapFree( GetProcessHeap(), 0, list );
1259 if (!got_one) break;
1262 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1264 if (wndPtr->owner)
1266 WND *owner = WIN_FindWndPtr( wndPtr->owner );
1267 if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
1268 WIN_ReleaseWndPtr( owner );
1272 /* Send destroy messages */
1274 WIN_SendDestroyMsg( hwnd );
1275 if (!IsWindow(hwnd))
1277 retvalue = TRUE;
1278 goto end;
1281 /* Unlink now so we won't bother with the children later on */
1283 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1285 /* Destroy the window storage */
1287 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1288 retvalue = TRUE;
1289 end:
1290 WIN_ReleaseWndPtr(wndPtr);
1291 return retvalue;
1295 /***********************************************************************
1296 * CloseWindow (USER.43)
1298 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1300 return CloseWindow( hwnd );
1304 /***********************************************************************
1305 * CloseWindow (USER32.@)
1307 BOOL WINAPI CloseWindow( HWND hwnd )
1309 WND * wndPtr = WIN_FindWndPtr( hwnd );
1310 BOOL retvalue;
1312 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1314 retvalue = FALSE;
1315 goto end;
1317 ShowWindow( hwnd, SW_MINIMIZE );
1318 retvalue = TRUE;
1319 end:
1320 WIN_ReleaseWndPtr(wndPtr);
1321 return retvalue;
1326 /***********************************************************************
1327 * OpenIcon (USER.44)
1329 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1331 return OpenIcon( hwnd );
1335 /***********************************************************************
1336 * OpenIcon (USER32.@)
1338 BOOL WINAPI OpenIcon( HWND hwnd )
1340 if (!IsIconic( hwnd )) return FALSE;
1341 ShowWindow( hwnd, SW_SHOWNORMAL );
1342 return TRUE;
1346 /***********************************************************************
1347 * WIN_FindWindow
1349 * Implementation of FindWindow() and FindWindowEx().
1351 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1353 HWND *list;
1354 HWND retvalue;
1355 int i = 0, len = 0;
1356 WCHAR *buffer = NULL;
1358 if (!parent) parent = GetDesktopWindow();
1359 if (title)
1361 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1362 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1365 if (!(list = WIN_ListChildren( parent )))
1367 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1368 return 0;
1371 if (child)
1373 child = WIN_GetFullHandle( child );
1374 while (list[i] && list[i] != child) i++;
1375 if (!list[i]) return 0;
1376 i++; /* start from next window */
1379 for ( ; list[i]; i++)
1381 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1382 continue; /* Not the right class */
1384 /* Now check the title */
1385 if (!title) break;
1386 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1388 retvalue = list[i];
1389 HeapFree( GetProcessHeap(), 0, list );
1390 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1392 /* In this case we need to check whether other processes
1393 own a window with the given paramters on the Desktop,
1394 but we don't, so let's at least warn about it */
1395 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1396 return retvalue;
1401 /***********************************************************************
1402 * FindWindow (USER.50)
1404 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1406 return FindWindowA( className, title );
1410 /***********************************************************************
1411 * FindWindowEx (USER.427)
1413 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1415 return FindWindowExA( parent, child, className, title );
1419 /***********************************************************************
1420 * FindWindowA (USER32.@)
1422 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1424 HWND ret = FindWindowExA( 0, 0, className, title );
1425 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1426 return ret;
1430 /***********************************************************************
1431 * FindWindowExA (USER32.@)
1433 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1434 LPCSTR className, LPCSTR title )
1436 ATOM atom = 0;
1437 LPWSTR buffer;
1438 HWND hwnd;
1440 if (className)
1442 /* If the atom doesn't exist, then no class */
1443 /* with this name exists either. */
1444 if (!(atom = GlobalFindAtomA( className )))
1446 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1447 return 0;
1451 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1452 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1453 HeapFree( GetProcessHeap(), 0, buffer );
1454 return hwnd;
1458 /***********************************************************************
1459 * FindWindowExW (USER32.@)
1461 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1462 LPCWSTR className, LPCWSTR title )
1464 ATOM atom = 0;
1466 if (className)
1468 /* If the atom doesn't exist, then no class */
1469 /* with this name exists either. */
1470 if (!(atom = GlobalFindAtomW( className )))
1472 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1473 return 0;
1476 return WIN_FindWindow( parent, child, atom, title );
1480 /***********************************************************************
1481 * FindWindowW (USER32.@)
1483 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1485 return FindWindowExW( 0, 0, className, title );
1489 /**********************************************************************
1490 * GetDesktopWindow (USER.286)
1492 HWND16 WINAPI GetDesktopWindow16(void)
1494 return (HWND16)pWndDesktop->hwndSelf;
1498 /**********************************************************************
1499 * GetDesktopWindow (USER32.@)
1501 HWND WINAPI GetDesktopWindow(void)
1503 if (pWndDesktop) return pWndDesktop->hwndSelf;
1504 ERR( "You need the -desktop option when running with native USER\n" );
1505 ExitProcess(1);
1506 return 0;
1510 /**********************************************************************
1511 * GetDesktopHwnd (USER.278)
1513 * Exactly the same thing as GetDesktopWindow(), but not documented.
1514 * Don't ask me why...
1516 HWND16 WINAPI GetDesktopHwnd16(void)
1518 return (HWND16)pWndDesktop->hwndSelf;
1522 /*******************************************************************
1523 * EnableWindow (USER.34)
1525 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1527 return EnableWindow( hwnd, enable );
1531 /*******************************************************************
1532 * EnableWindow (USER32.@)
1534 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1536 WND *wndPtr;
1537 BOOL retvalue;
1539 TRACE("( %x, %d )\n", hwnd, enable);
1541 if (USER_Driver.pEnableWindow)
1542 return USER_Driver.pEnableWindow( hwnd, enable );
1544 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1545 hwnd = wndPtr->hwndSelf; /* make it a full handle */
1547 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1549 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1551 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1552 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1554 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1556 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1558 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1560 if (hwnd == GetFocus())
1561 SetFocus( 0 ); /* A disabled window can't have the focus */
1563 if (hwnd == GetCapture())
1564 ReleaseCapture(); /* A disabled window can't capture the mouse */
1566 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1568 WIN_ReleaseWndPtr(wndPtr);
1569 return retvalue;
1573 /***********************************************************************
1574 * IsWindowEnabled (USER.35)
1576 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1578 return IsWindowEnabled(hWnd);
1582 /***********************************************************************
1583 * IsWindowEnabled (USER32.@)
1585 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1587 WND * wndPtr;
1588 BOOL retvalue;
1590 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1591 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1592 WIN_ReleaseWndPtr(wndPtr);
1593 return retvalue;
1598 /***********************************************************************
1599 * IsWindowUnicode (USER32.@)
1601 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1603 WND * wndPtr;
1604 BOOL retvalue;
1606 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1607 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1608 WIN_ReleaseWndPtr(wndPtr);
1609 return retvalue;
1613 /**********************************************************************
1614 * GetWindowWord (USER.133)
1616 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1618 return GetWindowWord( hwnd, offset );
1622 /**********************************************************************
1623 * GetWindowWord (USER32.@)
1625 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1627 WORD retvalue;
1628 WND * wndPtr = WIN_FindWndPtr( hwnd );
1629 if (!wndPtr) return 0;
1630 if (offset >= 0)
1632 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1634 WARN("Invalid offset %d\n", offset );
1635 retvalue = 0;
1636 goto end;
1638 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1639 goto end;
1641 switch(offset)
1643 case GWW_ID:
1644 if (HIWORD(wndPtr->wIDmenu))
1645 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1646 wndPtr->wIDmenu);
1647 retvalue = (WORD)wndPtr->wIDmenu;
1648 goto end;
1649 case GWW_HWNDPARENT:
1650 retvalue = GetParent(hwnd);
1651 goto end;
1652 case GWW_HINSTANCE:
1653 if (HIWORD(wndPtr->hInstance))
1654 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1655 wndPtr->hInstance);
1656 retvalue = (WORD)wndPtr->hInstance;
1657 goto end;
1658 default:
1659 WARN("Invalid offset %d\n", offset );
1660 retvalue = 0;
1661 goto end;
1663 end:
1664 WIN_ReleaseWndPtr(wndPtr);
1665 return retvalue;
1668 /**********************************************************************
1669 * SetWindowWord (USER.134)
1671 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1673 return SetWindowWord( hwnd, offset, newval );
1677 /**********************************************************************
1678 * SetWindowWord (USER32.@)
1680 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1682 WORD *ptr, retval;
1683 WND * wndPtr = WIN_FindWndPtr( hwnd );
1684 if (!wndPtr) return 0;
1685 if (offset >= 0)
1687 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1689 WARN("Invalid offset %d\n", offset );
1690 retval = 0;
1691 goto end;
1693 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1695 else switch(offset)
1697 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1698 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1699 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1700 goto end;
1701 default:
1702 WARN("Invalid offset %d\n", offset );
1703 retval = 0;
1704 goto end;
1706 retval = *ptr;
1707 *ptr = newval;
1708 end:
1709 WIN_ReleaseWndPtr(wndPtr);
1710 return retval;
1714 /**********************************************************************
1715 * WIN_GetWindowLong
1717 * Helper function for GetWindowLong().
1719 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1721 LONG retvalue;
1722 WND * wndPtr = WIN_FindWndPtr( hwnd );
1723 if (!wndPtr) return 0;
1724 if (offset >= 0)
1726 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1728 WARN("Invalid offset %d\n", offset );
1729 retvalue = 0;
1730 goto end;
1732 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1733 /* Special case for dialog window procedure */
1734 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1736 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1737 goto end;
1739 goto end;
1741 switch(offset)
1743 case GWL_USERDATA: retvalue = wndPtr->userdata;
1744 goto end;
1745 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1746 goto end;
1747 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1748 goto end;
1749 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1750 goto end;
1751 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1752 type );
1753 goto end;
1754 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1755 goto end;
1756 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1757 goto end;
1758 default:
1759 WARN("Unknown offset %d\n", offset );
1761 retvalue = 0;
1762 end:
1763 WIN_ReleaseWndPtr(wndPtr);
1764 return retvalue;
1768 /**********************************************************************
1769 * WIN_SetWindowLong
1771 * Helper function for SetWindowLong().
1773 * 0 is the failure code. However, in the case of failure SetLastError
1774 * must be set to distinguish between a 0 return value and a failure.
1776 * FIXME: The error values for SetLastError may not be right. Can
1777 * someone check with the real thing?
1779 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1780 WINDOWPROCTYPE type )
1782 LONG *ptr, retval;
1783 WND * wndPtr = WIN_FindWndPtr( hwnd );
1784 STYLESTRUCT style;
1786 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1788 if (!wndPtr)
1790 /* Is this the right error? */
1791 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1792 return 0;
1795 if (offset >= 0)
1797 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1799 WARN("Invalid offset %d\n", offset );
1801 /* Is this the right error? */
1802 SetLastError( ERROR_OUTOFMEMORY );
1804 retval = 0;
1805 goto end;
1807 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1808 /* Special case for dialog window procedure */
1809 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1811 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1812 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1813 type, WIN_PROC_WINDOW );
1814 goto end;
1817 else switch(offset)
1819 case GWL_ID:
1820 ptr = (DWORD*)&wndPtr->wIDmenu;
1821 break;
1822 case GWL_HINSTANCE:
1823 retval = SetWindowWord( hwnd, offset, newval );
1824 goto end;
1825 case GWL_WNDPROC:
1826 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1827 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1828 type, WIN_PROC_WINDOW );
1829 goto end;
1830 case GWL_STYLE:
1831 style.styleOld = wndPtr->dwStyle;
1832 style.styleNew = newval;
1833 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1834 wndPtr->dwStyle = style.styleNew;
1835 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1836 retval = style.styleOld;
1837 goto end;
1839 case GWL_USERDATA:
1840 ptr = &wndPtr->userdata;
1841 break;
1842 case GWL_EXSTYLE:
1843 style.styleOld = wndPtr->dwExStyle;
1844 style.styleNew = newval;
1845 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1846 wndPtr->dwExStyle = style.styleNew;
1847 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1848 retval = style.styleOld;
1849 goto end;
1851 default:
1852 WARN("Invalid offset %d\n", offset );
1854 /* Don't think this is right error but it should do */
1855 SetLastError( ERROR_OUTOFMEMORY );
1857 retval = 0;
1858 goto end;
1860 retval = *ptr;
1861 *ptr = newval;
1862 end:
1863 WIN_ReleaseWndPtr(wndPtr);
1864 return retval;
1868 /**********************************************************************
1869 * GetWindowLong (USER.135)
1871 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1873 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1877 /**********************************************************************
1878 * GetWindowLongA (USER32.@)
1880 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1882 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1886 /**********************************************************************
1887 * GetWindowLongW (USER32.@)
1889 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1891 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1895 /**********************************************************************
1896 * SetWindowLong (USER.136)
1898 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1900 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1904 /**********************************************************************
1905 * SetWindowLongA (USER32.@)
1907 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1909 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1913 /**********************************************************************
1914 * SetWindowLongW (USER32.@) Set window attribute
1916 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1917 * value in a window's extra memory.
1919 * The _hwnd_ parameter specifies the window. is the handle to a
1920 * window that has extra memory. The _newval_ parameter contains the
1921 * new attribute or extra memory value. If positive, the _offset_
1922 * parameter is the byte-addressed location in the window's extra
1923 * memory to set. If negative, _offset_ specifies the window
1924 * attribute to set, and should be one of the following values:
1926 * GWL_EXSTYLE The window's extended window style
1928 * GWL_STYLE The window's window style.
1930 * GWL_WNDPROC Pointer to the window's window procedure.
1932 * GWL_HINSTANCE The window's pplication instance handle.
1934 * GWL_ID The window's identifier.
1936 * GWL_USERDATA The window's user-specified data.
1938 * If the window is a dialog box, the _offset_ parameter can be one of
1939 * the following values:
1941 * DWL_DLGPROC The address of the window's dialog box procedure.
1943 * DWL_MSGRESULT The return value of a message
1944 * that the dialog box procedure processed.
1946 * DWL_USER Application specific information.
1948 * RETURNS
1950 * If successful, returns the previous value located at _offset_. Otherwise,
1951 * returns 0.
1953 * NOTES
1955 * Extra memory for a window class is specified by a nonzero cbWndExtra
1956 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1957 * time of class creation.
1959 * Using GWL_WNDPROC to set a new window procedure effectively creates
1960 * a window subclass. Use CallWindowProc() in the new windows procedure
1961 * to pass messages to the superclass's window procedure.
1963 * The user data is reserved for use by the application which created
1964 * the window.
1966 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1967 * instead, call the EnableWindow() function to change the window's
1968 * disabled state.
1970 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1971 * SetParent() instead.
1973 * Win95:
1974 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1975 * it sends WM_STYLECHANGING before changing the settings
1976 * and WM_STYLECHANGED afterwards.
1977 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1979 * BUGS
1981 * GWL_STYLE does not dispatch WM_STYLE... messages.
1983 * CONFORMANCE
1985 * ECMA-234, Win32
1988 LONG WINAPI SetWindowLongW(
1989 HWND hwnd, /* [in] window to alter */
1990 INT offset, /* [in] offset, in bytes, of location to alter */
1991 LONG newval /* [in] new value of location */
1993 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1997 /*******************************************************************
1998 * GetWindowText (USER.36)
2000 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2002 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2006 /*******************************************************************
2007 * GetWindowTextA (USER32.@)
2009 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2011 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2012 (LPARAM)lpString );
2015 /*******************************************************************
2016 * InternalGetWindowText (USER32.@)
2018 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2020 WND *win = WIN_FindWndPtr( hwnd );
2021 if (!win) return 0;
2022 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2023 else lpString[0] = 0;
2024 WIN_ReleaseWndPtr( win );
2025 return strlenW(lpString);
2029 /*******************************************************************
2030 * GetWindowTextW (USER32.@)
2032 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2034 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2035 (LPARAM)lpString );
2039 /*******************************************************************
2040 * SetWindowText (USER.37)
2042 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2044 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2048 /*******************************************************************
2049 * SetWindowText (USER32.@)
2050 * SetWindowTextA (USER32.@)
2052 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2054 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2058 /*******************************************************************
2059 * SetWindowTextW (USER32.@)
2061 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2063 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2067 /*******************************************************************
2068 * GetWindowTextLength (USER.38)
2070 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2072 return (INT16)GetWindowTextLengthA( hwnd );
2076 /*******************************************************************
2077 * GetWindowTextLengthA (USER32.@)
2079 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2081 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2084 /*******************************************************************
2085 * GetWindowTextLengthW (USER32.@)
2087 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2089 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2093 /*******************************************************************
2094 * IsWindow (USER.47)
2096 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2098 CURRENT_STACK16->es = USER_HeapSel;
2099 return IsWindow( hwnd );
2103 /*******************************************************************
2104 * IsWindow (USER32.@)
2106 BOOL WINAPI IsWindow( HWND hwnd )
2108 WND *ptr;
2109 BOOL ret;
2111 USER_Lock();
2112 if ((ptr = user_handles[LOWORD(hwnd)]))
2114 ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
2115 USER_Unlock();
2116 return ret;
2118 USER_Unlock();
2120 /* check other processes */
2121 SERVER_START_REQ( get_window_info )
2123 req->handle = hwnd;
2124 ret = !SERVER_CALL_ERR();
2126 SERVER_END_REQ;
2127 return ret;
2131 /***********************************************************************
2132 * GetWindowThreadProcessId (USER32.@)
2134 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2136 WND *ptr;
2137 DWORD tid = 0;
2139 USER_Lock();
2140 if ((ptr = user_handles[LOWORD(hwnd)]))
2142 if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
2144 /* got a valid window */
2145 tid = ptr->tid;
2146 if (process) *process = GetCurrentProcessId();
2148 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2149 USER_Unlock();
2150 return tid;
2152 USER_Unlock();
2154 /* check other processes */
2155 SERVER_START_REQ( get_window_info )
2157 req->handle = hwnd;
2158 if (!SERVER_CALL_ERR())
2160 tid = (DWORD)req->tid;
2161 if (process) *process = (DWORD)req->pid;
2164 SERVER_END_REQ;
2165 return tid;
2169 /*****************************************************************
2170 * GetParent (USER.46)
2172 HWND16 WINAPI GetParent16( HWND16 hwnd )
2174 return (HWND16)GetParent( hwnd );
2178 /*****************************************************************
2179 * GetParent (USER32.@)
2181 HWND WINAPI GetParent( HWND hwnd )
2183 WND *wndPtr;
2184 HWND retvalue = 0;
2186 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2188 if (wndPtr->dwStyle & WS_CHILD)
2189 retvalue = wndPtr->parent->hwndSelf;
2190 else if (wndPtr->dwStyle & WS_POPUP)
2191 retvalue = wndPtr->owner;
2192 WIN_ReleaseWndPtr(wndPtr);
2194 return retvalue;
2198 /*****************************************************************
2199 * GetAncestor (USER32.@)
2201 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2203 HWND ret = 0;
2204 WND *wndPtr;
2206 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2207 if (wndPtr->hwndSelf == GetDesktopWindow()) goto done;
2209 switch(type)
2211 case GA_PARENT:
2212 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2213 break;
2214 case GA_ROOT:
2215 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2216 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2217 break;
2218 case GA_ROOTOWNER:
2219 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2220 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2221 while (wndPtr && wndPtr->owner)
2223 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2224 WIN_ReleaseWndPtr( wndPtr );
2225 wndPtr = ptr;
2227 break;
2229 ret = wndPtr ? wndPtr->hwndSelf : 0;
2230 done:
2231 WIN_ReleaseWndPtr( wndPtr );
2232 return ret;
2236 /*****************************************************************
2237 * SetParent (USER.233)
2239 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2241 return SetParent( hwndChild, hwndNewParent );
2245 /*****************************************************************
2246 * SetParent (USER32.@)
2248 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2250 WND *wndPtr;
2251 DWORD dwStyle;
2252 HWND retvalue;
2254 if (!parent) parent = GetDesktopWindow();
2255 else parent = WIN_GetFullHandle( parent );
2257 /* sanity checks */
2258 if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
2260 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2261 return 0;
2264 if (USER_Driver.pSetParent)
2265 return USER_Driver.pSetParent( hwnd, parent );
2267 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2269 dwStyle = wndPtr->dwStyle;
2271 /* Windows hides the window first, then shows it again
2272 * including the WM_SHOWWINDOW messages and all */
2273 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2275 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2276 if (parent != retvalue)
2278 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2280 if (parent != GetDesktopWindow()) /* a child window */
2282 if (!(dwStyle & WS_CHILD))
2284 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2285 if (menu) DestroyMenu( menu );
2289 WIN_ReleaseWndPtr( wndPtr );
2291 /* SetParent additionally needs to make hwnd the topmost window
2292 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2293 WM_WINDOWPOSCHANGED notification messages.
2295 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2296 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2297 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2298 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2299 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2300 return retvalue;
2304 /*******************************************************************
2305 * IsChild (USER.48)
2307 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2309 return IsChild(parent,child);
2313 /*******************************************************************
2314 * IsChild (USER32.@)
2316 BOOL WINAPI IsChild( HWND parent, HWND child )
2318 HWND *list = WIN_ListParents( child );
2319 int i;
2320 BOOL ret;
2322 if (!list) return FALSE;
2323 parent = WIN_GetFullHandle( parent );
2324 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2325 ret = (list[i] != 0);
2326 HeapFree( GetProcessHeap(), 0, list );
2327 return ret;
2331 /***********************************************************************
2332 * IsWindowVisible (USER.49)
2334 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2336 return IsWindowVisible(hwnd);
2340 /***********************************************************************
2341 * IsWindowVisible (USER32.@)
2343 BOOL WINAPI IsWindowVisible( HWND hwnd )
2345 HWND *list;
2346 BOOL retval;
2347 int i;
2349 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2350 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2351 for (i = 0; list[i]; i++)
2352 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2353 retval = !list[i];
2354 HeapFree( GetProcessHeap(), 0, list );
2355 return retval;
2359 /***********************************************************************
2360 * WIN_IsWindowDrawable
2362 * hwnd is drawable when it is visible, all parents are not
2363 * minimized, and it is itself not minimized unless we are
2364 * trying to draw its default class icon.
2366 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2368 HWND *list;
2369 BOOL retval;
2370 int i;
2372 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2373 if ((wnd->dwStyle & WS_MINIMIZE) &&
2374 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2376 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2377 for (i = 0; list[i]; i++)
2378 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2379 break;
2380 retval = !list[i];
2381 HeapFree( GetProcessHeap(), 0, list );
2382 return retval;
2386 /*******************************************************************
2387 * GetTopWindow (USER.229)
2389 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2391 return GetTopWindow(hwnd);
2395 /*******************************************************************
2396 * GetTopWindow (USER32.@)
2398 HWND WINAPI GetTopWindow( HWND hwnd )
2400 if (!hwnd) hwnd = GetDesktopWindow();
2401 return GetWindow( hwnd, GW_CHILD );
2405 /*******************************************************************
2406 * GetWindow (USER.262)
2408 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2410 return GetWindow( hwnd,rel );
2414 /*******************************************************************
2415 * GetWindow (USER32.@)
2417 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2419 HWND retval;
2421 WND * wndPtr = WIN_FindWndPtr( hwnd );
2422 if (!wndPtr) return 0;
2423 hwnd = wndPtr->hwndSelf; /* make it a full handle */
2425 switch(rel)
2427 case GW_HWNDFIRST:
2428 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2429 goto end;
2431 case GW_HWNDLAST:
2432 if (!wndPtr->parent)
2434 retval = 0; /* Desktop window */
2435 goto end;
2437 while (wndPtr->next)
2439 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2441 retval = wndPtr->hwndSelf;
2442 goto end;
2444 case GW_HWNDNEXT:
2445 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2446 goto end;
2448 case GW_HWNDPREV:
2449 if (!wndPtr->parent)
2451 retval = 0; /* Desktop window */
2452 goto end;
2454 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2455 if (wndPtr->hwndSelf == hwnd)
2457 retval = 0; /* First in list */
2458 goto end;
2460 while (wndPtr->next)
2462 if (wndPtr->next->hwndSelf == hwnd)
2464 retval = wndPtr->hwndSelf;
2465 goto end;
2467 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2469 retval = 0;
2470 goto end;
2472 case GW_OWNER:
2473 retval = wndPtr->owner;
2474 goto end;
2476 case GW_CHILD:
2477 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2478 goto end;
2480 retval = 0;
2481 end:
2482 WIN_ReleaseWndPtr(wndPtr);
2483 return retval;
2487 /*******************************************************************
2488 * GetNextWindow (USER.230)
2490 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2492 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2493 return GetWindow16( hwnd, flag );
2496 /***********************************************************************
2497 * WIN_InternalShowOwnedPopups
2499 * Internal version of ShowOwnedPopups; Wine functions should use this
2500 * to avoid interfering with application calls to ShowOwnedPopups
2501 * and to make sure the application can't prevent showing/hiding.
2503 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2507 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2509 int count = 0;
2510 WND *pWnd;
2511 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2513 if (!win_array) return TRUE;
2516 * Show windows Lowest first, Highest last to preserve Z-Order
2518 while (win_array[count]) count++;
2519 while (--count >= 0)
2521 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2522 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2524 if (pWnd->dwStyle & WS_POPUP)
2526 if (fShow)
2528 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2529 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2532 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2534 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2535 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2538 else
2540 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2541 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2542 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2545 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2547 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2548 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2549 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2553 WIN_ReleaseWndPtr( pWnd );
2555 HeapFree( GetProcessHeap(), 0, win_array );
2557 return TRUE;
2560 /*******************************************************************
2561 * ShowOwnedPopups (USER.265)
2563 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2565 ShowOwnedPopups( owner, fShow );
2569 /*******************************************************************
2570 * ShowOwnedPopups (USER32.@)
2572 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2574 int count = 0;
2575 WND *pWnd;
2576 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2578 if (!win_array) return TRUE;
2580 while (win_array[count]) count++;
2581 while (--count >= 0)
2583 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2584 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2586 if (pWnd->dwStyle & WS_POPUP)
2588 if (fShow)
2590 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2592 /* In Windows, ShowOwnedPopups(TRUE) generates
2593 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2594 * regardless of the state of the owner
2596 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2597 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2600 else
2602 if (IsWindowVisible(pWnd->hwndSelf))
2604 /* In Windows, ShowOwnedPopups(FALSE) generates
2605 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2606 * regardless of the state of the owner
2608 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2609 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2613 WIN_ReleaseWndPtr( pWnd );
2615 HeapFree( GetProcessHeap(), 0, win_array );
2616 return TRUE;
2620 /*******************************************************************
2621 * GetLastActivePopup (USER.287)
2623 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2625 return GetLastActivePopup( hwnd );
2628 /*******************************************************************
2629 * GetLastActivePopup (USER32.@)
2631 HWND WINAPI GetLastActivePopup( HWND hwnd )
2633 HWND retval;
2634 WND *wndPtr =WIN_FindWndPtr(hwnd);
2635 if (!wndPtr) return hwnd;
2636 retval = wndPtr->hwndLastActive;
2637 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2638 WIN_ReleaseWndPtr(wndPtr);
2639 return retval;
2643 /*******************************************************************
2644 * WIN_ListParents
2646 * Build an array of all parents of a given window, starting with
2647 * the immediate parent. The array must be freed with HeapFree.
2648 * Returns NULL if window is a top-level window.
2650 HWND *WIN_ListParents( HWND hwnd )
2652 WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
2653 HWND *list = NULL;
2654 UINT i, count = 0;
2656 /* First count the windows */
2658 if (!wndPtr) return NULL;
2660 parent = wndPtr->parent;
2661 while (parent && parent->hwndSelf != GetDesktopWindow())
2663 count++;
2664 parent = parent->parent;
2667 if (count)
2669 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
2671 parent = wndPtr->parent;
2672 for (i = 0; i < count; i++)
2674 list[i] = parent->hwndSelf;
2675 parent = parent->parent;
2677 list[i] = 0;
2681 WIN_ReleaseWndPtr( wndPtr );
2682 return list;
2686 /*******************************************************************
2687 * WIN_ListChildren
2689 * Build an array of the children of a given window. The array must be
2690 * freed with HeapFree. Returns NULL when no windows are found.
2692 HWND *WIN_ListChildren( HWND hwnd )
2694 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2695 HWND *list, *phwnd;
2696 UINT count = 0;
2698 /* First count the windows */
2700 if (!wndPtr) return NULL;
2702 pWnd = WIN_LockWndPtr(wndPtr->child);
2703 while (pWnd)
2705 count++;
2706 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2709 if( count )
2711 /* Now build the list of all windows */
2713 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2715 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2717 *phwnd++ = pWnd->hwndSelf;
2718 count++;
2720 WIN_ReleaseWndPtr(pWnd);
2721 *phwnd = 0;
2723 else count = 0;
2724 } else list = NULL;
2726 WIN_ReleaseWndPtr( wndPtr );
2727 return list;
2731 /*******************************************************************
2732 * EnumWindows (USER32.@)
2734 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2736 HWND *list;
2737 BOOL ret = TRUE;
2738 int i, iWndsLocks;
2740 /* We have to build a list of all windows first, to avoid */
2741 /* unpleasant side-effects, for instance if the callback */
2742 /* function changes the Z-order of the windows. */
2744 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2746 /* Now call the callback function for every window */
2748 iWndsLocks = WIN_SuspendWndsLock();
2749 for (i = 0; list[i]; i++)
2751 /* Make sure that the window still exists */
2752 if (!IsWindow( list[i] )) continue;
2753 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2755 WIN_RestoreWndsLock(iWndsLocks);
2756 HeapFree( GetProcessHeap(), 0, list );
2757 return ret;
2761 /**********************************************************************
2762 * EnumTaskWindows16 (USER.225)
2764 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2765 LPARAM lParam )
2767 TDB *tdb = TASK_GetPtr( hTask );
2768 if (!tdb) return FALSE;
2769 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2773 /**********************************************************************
2774 * EnumThreadWindows (USER32.@)
2776 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2778 HWND *list;
2779 int i, iWndsLocks;
2781 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2783 /* Now call the callback function for every window */
2785 iWndsLocks = WIN_SuspendWndsLock();
2786 for (i = 0; list[i]; i++)
2788 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2789 if (!func( list[i], lParam )) break;
2791 WIN_RestoreWndsLock(iWndsLocks);
2792 HeapFree( GetProcessHeap(), 0, list );
2793 return TRUE;
2797 /**********************************************************************
2798 * WIN_EnumChildWindows
2800 * Helper function for EnumChildWindows().
2802 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2804 HWND *childList;
2805 BOOL ret = FALSE;
2807 for ( ; *list; list++)
2809 /* Make sure that the window still exists */
2810 if (!IsWindow( *list )) continue;
2811 /* skip owned windows */
2812 if (GetWindow( *list, GW_OWNER )) continue;
2813 /* Build children list first */
2814 childList = WIN_ListChildren( *list );
2816 ret = func( *list, lParam );
2818 if (childList)
2820 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2821 HeapFree( GetProcessHeap(), 0, childList );
2823 if (!ret) return FALSE;
2825 return TRUE;
2829 /**********************************************************************
2830 * EnumChildWindows (USER32.@)
2832 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2834 HWND *list;
2835 int iWndsLocks;
2837 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2838 iWndsLocks = WIN_SuspendWndsLock();
2839 WIN_EnumChildWindows( list, func, lParam );
2840 WIN_RestoreWndsLock(iWndsLocks);
2841 HeapFree( GetProcessHeap(), 0, list );
2842 return TRUE;
2846 /*******************************************************************
2847 * AnyPopup (USER.52)
2849 BOOL16 WINAPI AnyPopup16(void)
2851 return AnyPopup();
2855 /*******************************************************************
2856 * AnyPopup (USER32.@)
2858 BOOL WINAPI AnyPopup(void)
2860 int i;
2861 BOOL retvalue;
2862 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2864 if (!list) return FALSE;
2865 for (i = 0; list[i]; i++)
2867 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2869 retvalue = (list[i] != 0);
2870 HeapFree( GetProcessHeap(), 0, list );
2871 return retvalue;
2875 /*******************************************************************
2876 * FlashWindow (USER.105)
2878 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2880 return FlashWindow( hWnd, bInvert );
2884 /*******************************************************************
2885 * FlashWindow (USER32.@)
2887 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2889 WND *wndPtr = WIN_FindWndPtr(hWnd);
2891 TRACE("%04x\n", hWnd);
2893 if (!wndPtr) return FALSE;
2894 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2896 if (wndPtr->dwStyle & WS_MINIMIZE)
2898 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2900 HDC hDC = GetDC(hWnd);
2902 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2903 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2905 ReleaseDC( hWnd, hDC );
2906 wndPtr->flags |= WIN_NCACTIVATED;
2908 else
2910 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2911 wndPtr->flags &= ~WIN_NCACTIVATED;
2913 WIN_ReleaseWndPtr(wndPtr);
2914 return TRUE;
2916 else
2918 WPARAM16 wparam;
2919 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2920 else wparam = (hWnd == GetActiveWindow());
2922 WIN_ReleaseWndPtr(wndPtr);
2923 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2924 return wparam;
2929 /*******************************************************************
2930 * SetSysModalWindow (USER.188)
2932 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2934 HWND hWndOldModal = hwndSysModal;
2935 hwndSysModal = hWnd;
2936 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2937 return hWndOldModal;
2941 /*******************************************************************
2942 * GetSysModalWindow (USER.189)
2944 HWND16 WINAPI GetSysModalWindow16(void)
2946 return hwndSysModal;
2950 /*******************************************************************
2951 * GetWindowContextHelpId (USER32.@)
2953 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2955 DWORD retval;
2956 WND *wnd = WIN_FindWndPtr( hwnd );
2957 if (!wnd) return 0;
2958 retval = wnd->helpContext;
2959 WIN_ReleaseWndPtr(wnd);
2960 return retval;
2964 /*******************************************************************
2965 * SetWindowContextHelpId (USER32.@)
2967 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2969 WND *wnd = WIN_FindWndPtr( hwnd );
2970 if (!wnd) return FALSE;
2971 wnd->helpContext = id;
2972 WIN_ReleaseWndPtr(wnd);
2973 return TRUE;
2977 /*******************************************************************
2978 * DRAG_QueryUpdate
2980 * recursively find a child that contains spDragInfo->pt point
2981 * and send WM_QUERYDROPOBJECT
2983 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2985 BOOL16 wParam, bResult = 0;
2986 POINT pt;
2987 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2988 RECT tempRect;
2990 if (!ptrDragInfo) return FALSE;
2992 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2994 GetWindowRect(hQueryWnd,&tempRect);
2996 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2998 if (!IsIconic( hQueryWnd ))
3000 GetClientRect( hQueryWnd, &tempRect );
3001 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3003 if (PtInRect( &tempRect, pt))
3005 int i;
3006 HWND *list = WIN_ListChildren( hQueryWnd );
3008 wParam = 0;
3010 if (list)
3012 for (i = 0; list[i]; i++)
3014 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3016 GetWindowRect( list[i], &tempRect );
3017 if (PtInRect( &tempRect, pt )) break;
3020 if (list[i])
3022 if (IsWindowEnabled( list[i] ))
3023 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3025 HeapFree( GetProcessHeap(), 0, list );
3027 if(bResult) return bResult;
3029 else wParam = 1;
3031 else wParam = 1;
3033 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3035 ptrDragInfo->hScope = hQueryWnd;
3037 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3038 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3040 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3042 return bResult;
3046 /*******************************************************************
3047 * DragDetect (USER.465)
3049 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3051 POINT pt32;
3052 CONV_POINT16TO32( &pt, &pt32 );
3053 return DragDetect( hWnd, pt32 );
3056 /*******************************************************************
3057 * DragDetect (USER32.@)
3059 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3061 MSG msg;
3062 RECT rect;
3064 rect.left = pt.x - wDragWidth;
3065 rect.right = pt.x + wDragWidth;
3067 rect.top = pt.y - wDragHeight;
3068 rect.bottom = pt.y + wDragHeight;
3070 SetCapture(hWnd);
3072 while(1)
3074 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3076 if( msg.message == WM_LBUTTONUP )
3078 ReleaseCapture();
3079 return 0;
3081 if( msg.message == WM_MOUSEMOVE )
3083 POINT tmp;
3084 tmp.x = LOWORD(msg.lParam);
3085 tmp.y = HIWORD(msg.lParam);
3086 if( !PtInRect( &rect, tmp ))
3088 ReleaseCapture();
3089 return 1;
3093 WaitMessage();
3095 return 0;
3098 /******************************************************************************
3099 * DragObject (USER.464)
3101 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3102 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3104 MSG msg;
3105 LPDRAGINFO16 lpDragInfo;
3106 SEGPTR spDragInfo;
3107 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3108 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3109 HCURSOR16 hCurrentCursor = 0;
3110 HWND16 hCurrentWnd = 0;
3112 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3113 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3115 if( !lpDragInfo || !spDragInfo ) return 0L;
3117 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3119 GlobalFree16(hDragInfo);
3120 return 0L;
3123 if(hCursor)
3125 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3127 GlobalFree16(hDragInfo);
3128 return 0L;
3131 if( hDragCursor == hCursor ) hDragCursor = 0;
3132 else hCursor = hDragCursor;
3134 hOldCursor = SetCursor(hDragCursor);
3137 lpDragInfo->hWnd = hWnd;
3138 lpDragInfo->hScope = 0;
3139 lpDragInfo->wFlags = wObj;
3140 lpDragInfo->hList = szList; /* near pointer! */
3141 lpDragInfo->hOfStruct = hOfStruct;
3142 lpDragInfo->l = 0L;
3144 SetCapture(hWnd);
3145 ShowCursor( TRUE );
3149 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3151 *(lpDragInfo+1) = *lpDragInfo;
3153 lpDragInfo->pt.x = msg.pt.x;
3154 lpDragInfo->pt.y = msg.pt.y;
3156 /* update DRAGINFO struct */
3157 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3159 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3160 hCurrentCursor = hCursor;
3161 else
3163 hCurrentCursor = hBummer;
3164 lpDragInfo->hScope = 0;
3166 if( hCurrentCursor )
3167 SetCursor(hCurrentCursor);
3169 /* send WM_DRAGLOOP */
3170 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3171 (LPARAM) spDragInfo );
3172 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3173 if( hCurrentWnd != lpDragInfo->hScope )
3175 if( hCurrentWnd )
3176 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3177 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3178 HIWORD(spDragInfo)) );
3179 hCurrentWnd = lpDragInfo->hScope;
3180 if( hCurrentWnd )
3181 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3183 else
3184 if( hCurrentWnd )
3185 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3187 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3189 ReleaseCapture();
3190 ShowCursor( FALSE );
3192 if( hCursor )
3194 SetCursor( hOldCursor );
3195 if (hDragCursor) DestroyCursor( hDragCursor );
3198 if( hCurrentCursor != hBummer )
3199 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3200 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3201 else
3202 msg.lParam = 0;
3203 GlobalFree16(hDragInfo);
3205 return (DWORD)(msg.lParam);
3209 /******************************************************************************
3210 * GetWindowModuleFileNameA (USER32.@)
3212 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3214 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3215 hwnd, lpszFileName, cchFileNameMax);
3216 return 0;
3219 /******************************************************************************
3220 * GetWindowModuleFileNameW (USER32.@)
3222 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3224 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3225 hwnd, lpszFileName, cchFileNameMax);
3226 return 0;