Added global management of user handles in the server.
[wine/multimedia.git] / windows / win.c
blob7985360f32a4d32f87c87399243e1450f5b37279
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 * WIN_FindWndPtr
152 * Return a pointer to the WND structure corresponding to a HWND.
154 WND * WIN_FindWndPtr( HWND hwnd )
156 WND * ptr;
158 if (!hwnd) return NULL;
160 USER_Lock();
161 if (!(ptr = user_handles[LOWORD(hwnd)]))
163 /* check other processes */
164 if (IsWindow( hwnd ))
166 ERR( "window %04x belongs to other process\n", hwnd );
167 /* DbgBreakPoint(); */
169 goto error;
171 if (ptr->dwMagic != WND_MAGIC) goto error;
172 /* verify that handle highword (if any) matches the window */
173 if (HIWORD(hwnd) && hwnd != ptr->hwndSelf) goto error;
174 /*and increment destruction monitoring*/
175 ptr->irefCount++;
176 return ptr;
178 error:
179 /* Unlock all WND structures for thread safeness*/
180 USER_Unlock();
181 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
182 return NULL;
186 /***********************************************************************
187 * WIN_LockWndPtr
189 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
190 * but by initWndPtr;
191 * Returns the locked initialisation pointer
193 WND *WIN_LockWndPtr(WND *initWndPtr)
195 if(!initWndPtr) return 0;
197 /* Lock all WND structures for thread safeness*/
198 USER_Lock();
199 /*and increment destruction monitoring*/
200 initWndPtr->irefCount++;
202 return initWndPtr;
206 /***********************************************************************
207 * WIN_ReleaseWndPtr
209 * Release the pointer to the WND structure.
211 void WIN_ReleaseWndPtr(WND *wndPtr)
213 if(!wndPtr) return;
215 /*Decrement destruction monitoring value*/
216 wndPtr->irefCount--;
217 /* Check if it's time to release the memory*/
218 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
220 /* Release memory */
221 free_window_handle( wndPtr->hwndSelf );
223 else if(wndPtr->irefCount < 0)
225 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
226 ERR("forgot a Lock on %p somewhere\n",wndPtr);
228 /*unlock all WND structures for thread safeness*/
229 USER_Unlock();
232 /***********************************************************************
233 * WIN_UpdateWndPtr
235 * Updates the value of oldPtr to newPtr.
237 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
239 WND *tmpWnd = NULL;
241 tmpWnd = WIN_LockWndPtr(newPtr);
242 WIN_ReleaseWndPtr(*oldPtr);
243 *oldPtr = tmpWnd;
248 /***********************************************************************
249 * WIN_UnlinkWindow
251 * Remove a window from the siblings linked list.
253 void WIN_UnlinkWindow( HWND hwnd )
255 WIN_LinkWindow( hwnd, 0, 0 );
259 /***********************************************************************
260 * WIN_LinkWindow
262 * Insert a window into the siblings linked list.
263 * The window is inserted after the specified window, which can also
264 * be specified as HWND_TOP or HWND_BOTTOM.
265 * If parent is 0, window is unlinked from the tree.
267 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
269 WND *wndPtr, **ppWnd, *parentPtr = NULL;
270 BOOL ret;
272 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
273 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
275 WIN_ReleaseWndPtr(wndPtr);
276 return;
279 SERVER_START_REQ( link_window )
281 req->handle = hwnd;
282 req->parent = parent;
283 req->previous = hwndInsertAfter;
284 ret = !SERVER_CALL_ERR();
286 SERVER_END_REQ;
287 if (!ret) goto done;
289 /* first unlink it if it is linked */
290 if (wndPtr->parent)
292 ppWnd = &wndPtr->parent->child;
293 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
294 if (*ppWnd) *ppWnd = wndPtr->next;
297 wndPtr->parent = parentPtr;
299 if (parentPtr)
301 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
303 ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
304 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
305 while (*ppWnd) ppWnd = &(*ppWnd)->next;
307 else /* Normal case */
309 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
310 if (!afterPtr) goto done;
311 ppWnd = &afterPtr->next;
312 WIN_ReleaseWndPtr(afterPtr);
314 wndPtr->next = *ppWnd;
315 *ppWnd = wndPtr;
318 done:
319 WIN_ReleaseWndPtr( parentPtr );
320 WIN_ReleaseWndPtr( wndPtr );
324 /***********************************************************************
325 * WIN_FindWinToRepaint
327 * Find a window that needs repaint.
329 HWND WIN_FindWinToRepaint( HWND hwnd )
331 HWND hwndRet;
332 WND *pWnd;
334 /* Note: the desktop window never gets WM_PAINT messages
335 * The real reason why is because Windows DesktopWndProc
336 * does ValidateRgn inside WM_ERASEBKGND handler.
338 if (hwnd == GetDesktopWindow()) hwnd = 0;
340 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
342 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
344 if (!(pWnd->dwStyle & WS_VISIBLE))
346 TRACE("skipping window %04x\n",
347 pWnd->hwndSelf );
349 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
350 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
351 break;
353 else if (pWnd->child )
354 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
356 WIN_ReleaseWndPtr(pWnd);
357 return hwndRet;
362 if(!pWnd)
364 return 0;
367 hwndRet = pWnd->hwndSelf;
369 /* look among siblings if we got a transparent window */
370 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
371 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
373 WIN_UpdateWndPtr(&pWnd,pWnd->next);
375 if (pWnd)
377 hwndRet = pWnd->hwndSelf;
378 WIN_ReleaseWndPtr(pWnd);
380 TRACE("found %04x\n",hwndRet);
381 return hwndRet;
385 /***********************************************************************
386 * WIN_DestroyWindow
388 * Destroy storage associated to a window. "Internals" p.358
389 * returns a locked wndPtr->next
391 static WND* WIN_DestroyWindow( WND* wndPtr )
393 HWND hwnd = wndPtr->hwndSelf;
394 WND *pWnd;
396 TRACE("%04x\n", wndPtr->hwndSelf );
398 /* free child windows */
399 WIN_LockWndPtr(wndPtr->child);
400 while ((pWnd = wndPtr->child))
402 wndPtr->child = WIN_DestroyWindow( pWnd );
403 WIN_ReleaseWndPtr(pWnd);
407 * Clear the update region to make sure no WM_PAINT messages will be
408 * generated for this window while processing the WM_NCDESTROY.
410 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
411 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
414 * Send the WM_NCDESTROY to the window being destroyed.
416 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
418 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
420 WINPOS_CheckInternalPos( hwnd );
421 if( hwnd == GetCapture()) ReleaseCapture();
423 /* free resources associated with the window */
425 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
426 PROPERTY_RemoveWindowProps( wndPtr );
428 /* toss stale messages from the queue */
430 QUEUE_CleanupWindow( hwnd );
431 wndPtr->hmemTaskQ = 0;
433 if (!(wndPtr->dwStyle & WS_CHILD))
434 if (wndPtr->wIDmenu)
436 DestroyMenu( wndPtr->wIDmenu );
437 wndPtr->wIDmenu = 0;
439 if (wndPtr->hSysMenu)
441 DestroyMenu( wndPtr->hSysMenu );
442 wndPtr->hSysMenu = 0;
444 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
445 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
446 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
447 CLASS_RemoveWindow( wndPtr->class );
448 wndPtr->class = NULL;
449 wndPtr->dwMagic = 0; /* Mark it as invalid */
451 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
453 return pWnd;
456 /***********************************************************************
457 * WIN_DestroyThreadWindows
459 * Destroy all children of 'wnd' owned by the current thread.
460 * Return TRUE if something was done.
462 void WIN_DestroyThreadWindows( HWND hwnd )
464 HWND *list;
465 int i;
467 if (!(list = WIN_ListChildren( hwnd ))) return;
468 for (i = 0; list[i]; i++)
470 if (!IsWindow( list[i] )) continue;
471 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
472 DestroyWindow( list[i] );
473 else
474 WIN_DestroyThreadWindows( list[i] );
476 HeapFree( GetProcessHeap(), 0, list );
479 /***********************************************************************
480 * WIN_CreateDesktopWindow
482 * Create the desktop window.
484 BOOL WIN_CreateDesktopWindow(void)
486 struct tagCLASS *class;
487 HWND hwndDesktop;
488 INT wndExtra;
489 DWORD clsStyle;
490 WNDPROC winproc;
491 DCE *dce;
492 CREATESTRUCTA cs;
494 TRACE("Creating desktop window\n");
497 if (!WINPOS_CreateInternalPosAtom() ||
498 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
499 &wndExtra, &winproc, &clsStyle, &dce )))
500 return FALSE;
502 pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra );
503 if (!pWndDesktop) return FALSE;
504 hwndDesktop = pWndDesktop->hwndSelf;
506 pWndDesktop->tid = 0; /* nobody owns the desktop */
507 pWndDesktop->next = NULL;
508 pWndDesktop->child = NULL;
509 pWndDesktop->parent = NULL;
510 pWndDesktop->owner = 0;
511 pWndDesktop->class = class;
512 pWndDesktop->hInstance = 0;
513 pWndDesktop->rectWindow.left = 0;
514 pWndDesktop->rectWindow.top = 0;
515 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
516 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
517 pWndDesktop->rectClient = pWndDesktop->rectWindow;
518 pWndDesktop->text = NULL;
519 pWndDesktop->hmemTaskQ = 0;
520 pWndDesktop->hrgnUpdate = 0;
521 pWndDesktop->hwndLastActive = hwndDesktop;
522 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
523 WS_CLIPSIBLINGS;
524 pWndDesktop->dwExStyle = 0;
525 pWndDesktop->clsStyle = clsStyle;
526 pWndDesktop->dce = NULL;
527 pWndDesktop->pVScroll = NULL;
528 pWndDesktop->pHScroll = NULL;
529 pWndDesktop->pProp = NULL;
530 pWndDesktop->wIDmenu = 0;
531 pWndDesktop->helpContext = 0;
532 pWndDesktop->flags = 0;
533 pWndDesktop->hSysMenu = 0;
534 pWndDesktop->userdata = 0;
535 pWndDesktop->winproc = winproc;
536 pWndDesktop->cbWndExtra = wndExtra;
538 cs.lpCreateParams = NULL;
539 cs.hInstance = 0;
540 cs.hMenu = 0;
541 cs.hwndParent = 0;
542 cs.x = 0;
543 cs.y = 0;
544 cs.cx = pWndDesktop->rectWindow.right;
545 cs.cy = pWndDesktop->rectWindow.bottom;
546 cs.style = pWndDesktop->dwStyle;
547 cs.dwExStyle = pWndDesktop->dwExStyle;
548 cs.lpszName = NULL;
549 cs.lpszClass = DESKTOP_CLASS_ATOM;
551 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
553 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
554 WIN_ReleaseWndPtr( pWndDesktop );
555 return TRUE;
559 /***********************************************************************
560 * WIN_FixCoordinates
562 * Fix the coordinates - Helper for WIN_CreateWindowEx.
563 * returns default show mode in sw.
564 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
566 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
568 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
569 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
571 if (cs->style & (WS_CHILD | WS_POPUP))
573 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
574 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
576 else /* overlapped window */
578 STARTUPINFOA info;
580 GetStartupInfoA( &info );
582 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
584 /* Never believe Microsoft's documentation... CreateWindowEx doc says
585 * that if an overlapped window is created with WS_VISIBLE style bit
586 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
587 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
588 * reveals that
590 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
591 * 2) it does not ignore the y parameter as the docs claim; instead, it
592 * uses it as second parameter to ShowWindow() unless y is either
593 * CW_USEDEFAULT or CW_USEDEFAULT16.
595 * The fact that we didn't do 2) caused bogus windows pop up when wine
596 * was running apps that were using this obscure feature. Example -
597 * calc.exe that comes with Win98 (only Win98, it's different from
598 * the one that comes with Win95 and NT)
600 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
601 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
602 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
605 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
607 if (info.dwFlags & STARTF_USESIZE)
609 cs->cx = info.dwXSize;
610 cs->cy = info.dwYSize;
612 else /* if no other hint from the app, pick 3/4 of the screen real estate */
614 RECT r;
615 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
616 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
617 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
624 /***********************************************************************
625 * WIN_CreateWindowEx
627 * Implementation of CreateWindowEx().
629 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
630 WINDOWPROCTYPE type )
632 INT sw = SW_SHOW;
633 struct tagCLASS *classPtr;
634 WND *wndPtr;
635 HWND hwnd, hwndLinkAfter;
636 POINT maxSize, maxPos, minTrack, maxTrack;
637 INT wndExtra;
638 DWORD clsStyle;
639 WNDPROC winproc;
640 DCE *dce;
641 BOOL unicode = (type == WIN_PROC_32W);
643 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
644 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
645 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
646 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
647 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
649 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
650 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
652 /* Find the parent window */
654 if (cs->hwndParent)
656 /* Make sure parent is valid */
657 if (!IsWindow( cs->hwndParent ))
659 WARN("Bad parent %04x\n", cs->hwndParent );
660 return 0;
662 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
663 WARN("No parent for child window\n" );
664 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
667 /* Find the window class */
668 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
669 &wndExtra, &winproc, &clsStyle, &dce )))
671 WARN("Bad class '%s'\n", cs->lpszClass );
672 return 0;
675 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
677 /* Correct the window style - stage 1
679 * These are patches that appear to affect both the style loaded into the
680 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
682 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
683 * why does the user get to set it?
686 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
687 * tested for WS_POPUP
689 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
690 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
691 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
692 cs->dwExStyle |= WS_EX_WINDOWEDGE;
693 else
694 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
696 /* Create the window structure */
698 if (!(wndPtr = create_window_handle( FALSE,
699 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
701 TRACE("out of memory\n" );
702 return 0;
704 hwnd = wndPtr->hwndSelf;
706 /* Fill the window structure */
708 wndPtr->tid = GetCurrentThreadId();
709 wndPtr->next = NULL;
710 wndPtr->child = NULL;
712 if ((cs->style & WS_CHILD) && cs->hwndParent)
714 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
715 wndPtr->owner = 0;
716 WIN_ReleaseWndPtr(wndPtr->parent);
718 else
720 wndPtr->parent = pWndDesktop;
721 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
722 wndPtr->owner = 0;
723 else
724 wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
728 wndPtr->class = classPtr;
729 wndPtr->winproc = winproc;
730 wndPtr->hInstance = cs->hInstance;
731 wndPtr->text = NULL;
732 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
733 wndPtr->hrgnUpdate = 0;
734 wndPtr->hrgnWnd = 0;
735 wndPtr->hwndLastActive = hwnd;
736 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
737 wndPtr->dwExStyle = cs->dwExStyle;
738 wndPtr->clsStyle = clsStyle;
739 wndPtr->wIDmenu = 0;
740 wndPtr->helpContext = 0;
741 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
742 wndPtr->pVScroll = NULL;
743 wndPtr->pHScroll = NULL;
744 wndPtr->pProp = NULL;
745 wndPtr->userdata = 0;
746 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
747 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
748 wndPtr->cbWndExtra = wndExtra;
750 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
752 /* Call the WH_CBT hook */
754 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
755 ? HWND_BOTTOM : HWND_TOP;
757 if (HOOK_IsHooked( WH_CBT ))
759 CBT_CREATEWNDA cbtc;
760 LRESULT ret;
762 cbtc.lpcs = cs;
763 cbtc.hwndInsertAfter = hwndLinkAfter;
764 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
765 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
766 if (ret)
768 TRACE("CBT-hook returned 0\n");
769 free_window_handle( hwnd );
770 CLASS_RemoveWindow( classPtr );
771 hwnd = 0;
772 goto end;
776 /* Correct the window style - stage 2 */
778 if (!(cs->style & WS_CHILD))
780 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
781 if (!(cs->style & WS_POPUP))
783 wndPtr->dwStyle |= WS_CAPTION;
784 wndPtr->flags |= WIN_NEED_SIZE;
788 /* Get class or window DC if needed */
790 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
791 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
792 else wndPtr->dce = NULL;
794 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
796 wndPtr->rectWindow.left = cs->x;
797 wndPtr->rectWindow.top = cs->y;
798 wndPtr->rectWindow.right = cs->x + cs->cx;
799 wndPtr->rectWindow.bottom = cs->y + cs->cy;
800 wndPtr->rectClient = wndPtr->rectWindow;
802 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
804 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
806 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
807 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
808 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
809 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
810 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
813 if (cs->cx < 0) cs->cx = 0;
814 if (cs->cy < 0) cs->cy = 0;
816 wndPtr->rectWindow.left = cs->x;
817 wndPtr->rectWindow.top = cs->y;
818 wndPtr->rectWindow.right = cs->x + cs->cx;
819 wndPtr->rectWindow.bottom = cs->y + cs->cy;
820 wndPtr->rectClient = wndPtr->rectWindow;
822 /* Set the window menu */
824 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
826 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
827 else
829 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
830 if (menuName)
832 if (HIWORD(cs->hInstance))
833 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
834 else
835 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
837 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
841 else wndPtr->wIDmenu = (UINT)cs->hMenu;
843 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
845 WARN("aborted by WM_xxCREATE!\n");
846 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
847 CLASS_RemoveWindow( classPtr );
848 WIN_ReleaseWndPtr(wndPtr);
849 return 0;
852 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
854 /* Notify the parent window only */
856 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
857 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
858 if( !IsWindow(hwnd) )
860 hwnd = 0;
861 goto end;
865 if (cs->style & WS_VISIBLE)
867 /* in case WS_VISIBLE got set in the meantime */
868 wndPtr->dwStyle &= ~WS_VISIBLE;
869 ShowWindow( hwnd, sw );
872 /* Call WH_SHELL hook */
874 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
875 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
877 TRACE("created window %04x\n", hwnd);
878 end:
879 WIN_ReleaseWndPtr(wndPtr);
880 return hwnd;
884 /***********************************************************************
885 * CreateWindow (USER.41)
887 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
888 DWORD style, INT16 x, INT16 y, INT16 width,
889 INT16 height, HWND16 parent, HMENU16 menu,
890 HINSTANCE16 instance, LPVOID data )
892 return CreateWindowEx16( 0, className, windowName, style,
893 x, y, width, height, parent, menu, instance, data );
897 /***********************************************************************
898 * CreateWindowEx (USER.452)
900 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
901 LPCSTR windowName, DWORD style, INT16 x,
902 INT16 y, INT16 width, INT16 height,
903 HWND16 parent, HMENU16 menu,
904 HINSTANCE16 instance, LPVOID data )
906 ATOM classAtom;
907 CREATESTRUCTA cs;
908 char buffer[256];
910 /* Find the class atom */
912 if (HIWORD(className))
914 if (!(classAtom = GlobalFindAtomA( className )))
916 ERR( "bad class name %s\n", debugres_a(className) );
917 return 0;
920 else
922 classAtom = LOWORD(className);
923 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
925 ERR( "bad atom %x\n", classAtom);
926 return 0;
928 className = buffer;
931 /* Fix the coordinates */
933 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
934 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
935 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
936 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
938 /* Create the window */
940 cs.lpCreateParams = data;
941 cs.hInstance = (HINSTANCE)instance;
942 cs.hMenu = (HMENU)menu;
943 cs.hwndParent = (HWND)parent;
944 cs.style = style;
945 cs.lpszName = windowName;
946 cs.lpszClass = className;
947 cs.dwExStyle = exStyle;
949 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
953 /***********************************************************************
954 * CreateWindowExA (USER32.@)
956 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
957 LPCSTR windowName, DWORD style, INT x,
958 INT y, INT width, INT height,
959 HWND parent, HMENU menu,
960 HINSTANCE instance, LPVOID data )
962 ATOM classAtom;
963 CREATESTRUCTA cs;
964 char buffer[256];
966 if(!instance)
967 instance=GetModuleHandleA(NULL);
969 if(exStyle & WS_EX_MDICHILD)
970 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
972 /* Find the class atom */
974 if (HIWORD(className))
976 if (!(classAtom = GlobalFindAtomA( className )))
978 ERR( "bad class name %s\n", debugres_a(className) );
979 return 0;
982 else
984 classAtom = LOWORD(className);
985 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
987 ERR( "bad atom %x\n", classAtom);
988 return 0;
990 className = buffer;
993 /* Create the window */
995 cs.lpCreateParams = data;
996 cs.hInstance = instance;
997 cs.hMenu = menu;
998 cs.hwndParent = parent;
999 cs.x = x;
1000 cs.y = y;
1001 cs.cx = width;
1002 cs.cy = height;
1003 cs.style = style;
1004 cs.lpszName = windowName;
1005 cs.lpszClass = className;
1006 cs.dwExStyle = exStyle;
1008 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1012 /***********************************************************************
1013 * CreateWindowExW (USER32.@)
1015 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1016 LPCWSTR windowName, DWORD style, INT x,
1017 INT y, INT width, INT height,
1018 HWND parent, HMENU menu,
1019 HINSTANCE instance, LPVOID data )
1021 ATOM classAtom;
1022 CREATESTRUCTW cs;
1023 WCHAR buffer[256];
1025 if(!instance)
1026 instance=GetModuleHandleA(NULL);
1028 if(exStyle & WS_EX_MDICHILD)
1029 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1031 /* Find the class atom */
1033 if (HIWORD(className))
1035 if (!(classAtom = GlobalFindAtomW( className )))
1037 ERR( "bad class name %s\n", debugres_w(className) );
1038 return 0;
1041 else
1043 classAtom = LOWORD(className);
1044 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1046 ERR( "bad atom %x\n", classAtom);
1047 return 0;
1049 className = buffer;
1052 /* Create the window */
1054 cs.lpCreateParams = data;
1055 cs.hInstance = instance;
1056 cs.hMenu = menu;
1057 cs.hwndParent = parent;
1058 cs.x = x;
1059 cs.y = y;
1060 cs.cx = width;
1061 cs.cy = height;
1062 cs.style = style;
1063 cs.lpszName = windowName;
1064 cs.lpszClass = className;
1065 cs.dwExStyle = exStyle;
1067 /* Note: we rely on the fact that CREATESTRUCTA and */
1068 /* CREATESTRUCTW have the same layout. */
1069 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1073 /***********************************************************************
1074 * WIN_SendDestroyMsg
1076 static void WIN_SendDestroyMsg( HWND hwnd )
1078 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1079 if (USER_Driver.pResetSelectionOwner)
1080 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1083 * Send the WM_DESTROY to the window.
1085 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1088 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1089 * make sure that the window still exists when we come back.
1091 if (IsWindow(hwnd))
1093 HWND* pWndArray;
1094 int i;
1096 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1098 /* start from the end (FIXME: is this needed?) */
1099 for (i = 0; pWndArray[i]; i++) ;
1101 while (--i >= 0)
1103 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1105 HeapFree( GetProcessHeap(), 0, pWndArray );
1107 else
1108 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1112 /***********************************************************************
1113 * DestroyWindow (USER.53)
1115 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1117 return DestroyWindow(hwnd);
1121 /***********************************************************************
1122 * DestroyWindow (USER32.@)
1124 BOOL WINAPI DestroyWindow( HWND hwnd )
1126 WND * wndPtr;
1127 BOOL retvalue;
1128 HWND h;
1130 TRACE("(%04x)\n", hwnd);
1132 /* Initialization */
1134 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1136 /* Look whether the focus is within the tree of windows we will
1137 * be destroying.
1139 h = GetFocus();
1140 if (h == hwnd || IsChild( hwnd, h ))
1142 HWND parent = GetAncestor( hwnd, GA_PARENT );
1143 if (parent == GetDesktopWindow()) parent = 0;
1144 SetFocus( parent );
1147 /* Call hooks */
1149 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
1151 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1152 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1154 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1155 /* FIXME: clean up palette - see "Internals" p.352 */
1158 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1159 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1161 /* Notify the parent window only */
1162 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1163 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1164 if( !IsWindow(hwnd) )
1166 retvalue = TRUE;
1167 goto end;
1171 if (USER_Driver.pResetSelectionOwner)
1172 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1174 /* Hide the window */
1176 if (wndPtr->dwStyle & WS_VISIBLE)
1178 ShowWindow( hwnd, SW_HIDE );
1179 if (!IsWindow(hwnd))
1181 retvalue = TRUE;
1182 goto end;
1186 /* Recursively destroy owned windows */
1188 if( !(wndPtr->dwStyle & WS_CHILD) )
1190 for (;;)
1192 int i, got_one = 0;
1193 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1194 if (list)
1196 for (i = 0; list[i]; i++)
1198 WND *siblingPtr = WIN_FindWndPtr( list[i] );
1199 if (!siblingPtr) continue;
1200 if (siblingPtr->owner == hwnd)
1202 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1204 WIN_ReleaseWndPtr( siblingPtr );
1205 DestroyWindow( list[i] );
1206 got_one = 1;
1207 continue;
1209 else siblingPtr->owner = 0;
1211 WIN_ReleaseWndPtr( siblingPtr );
1213 HeapFree( GetProcessHeap(), 0, list );
1215 if (!got_one) break;
1218 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1220 if (wndPtr->owner)
1222 WND *owner = WIN_FindWndPtr( wndPtr->owner );
1223 if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
1224 WIN_ReleaseWndPtr( owner );
1228 /* Send destroy messages */
1230 WIN_SendDestroyMsg( hwnd );
1231 if (!IsWindow(hwnd))
1233 retvalue = TRUE;
1234 goto end;
1237 /* Unlink now so we won't bother with the children later on */
1239 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1241 /* Destroy the window storage */
1243 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1244 retvalue = TRUE;
1245 end:
1246 WIN_ReleaseWndPtr(wndPtr);
1247 return retvalue;
1251 /***********************************************************************
1252 * CloseWindow (USER.43)
1254 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1256 return CloseWindow( hwnd );
1260 /***********************************************************************
1261 * CloseWindow (USER32.@)
1263 BOOL WINAPI CloseWindow( HWND hwnd )
1265 WND * wndPtr = WIN_FindWndPtr( hwnd );
1266 BOOL retvalue;
1268 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1270 retvalue = FALSE;
1271 goto end;
1273 ShowWindow( hwnd, SW_MINIMIZE );
1274 retvalue = TRUE;
1275 end:
1276 WIN_ReleaseWndPtr(wndPtr);
1277 return retvalue;
1282 /***********************************************************************
1283 * OpenIcon (USER.44)
1285 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1287 return OpenIcon( hwnd );
1291 /***********************************************************************
1292 * OpenIcon (USER32.@)
1294 BOOL WINAPI OpenIcon( HWND hwnd )
1296 if (!IsIconic( hwnd )) return FALSE;
1297 ShowWindow( hwnd, SW_SHOWNORMAL );
1298 return TRUE;
1302 /***********************************************************************
1303 * WIN_FindWindow
1305 * Implementation of FindWindow() and FindWindowEx().
1307 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1309 HWND *list;
1310 HWND retvalue;
1311 int i = 0, len = 0;
1312 WCHAR *buffer = NULL;
1314 if (!parent) parent = GetDesktopWindow();
1315 if (title)
1317 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1318 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1321 if (!(list = WIN_ListChildren( parent )))
1323 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1324 return 0;
1327 if (child)
1329 while (list[i] && list[i] != child) i++;
1330 if (!list[i]) return 0;
1331 i++; /* start from next window */
1334 for ( ; list[i]; i++)
1336 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1337 continue; /* Not the right class */
1339 /* Now check the title */
1340 if (!title) break;
1341 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1343 retvalue = list[i];
1344 HeapFree( GetProcessHeap(), 0, list );
1345 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1347 /* In this case we need to check whether other processes
1348 own a window with the given paramters on the Desktop,
1349 but we don't, so let's at least warn about it */
1350 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1351 return retvalue;
1356 /***********************************************************************
1357 * FindWindow (USER.50)
1359 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1361 return FindWindowA( className, title );
1365 /***********************************************************************
1366 * FindWindowEx (USER.427)
1368 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1370 return FindWindowExA( parent, child, className, title );
1374 /***********************************************************************
1375 * FindWindowA (USER32.@)
1377 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1379 HWND ret = FindWindowExA( 0, 0, className, title );
1380 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1381 return ret;
1385 /***********************************************************************
1386 * FindWindowExA (USER32.@)
1388 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1389 LPCSTR className, LPCSTR title )
1391 ATOM atom = 0;
1392 LPWSTR buffer;
1393 HWND hwnd;
1395 if (className)
1397 /* If the atom doesn't exist, then no class */
1398 /* with this name exists either. */
1399 if (!(atom = GlobalFindAtomA( className )))
1401 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1402 return 0;
1406 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1407 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1408 HeapFree( GetProcessHeap(), 0, buffer );
1409 return hwnd;
1413 /***********************************************************************
1414 * FindWindowExW (USER32.@)
1416 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1417 LPCWSTR className, LPCWSTR title )
1419 ATOM atom = 0;
1421 if (className)
1423 /* If the atom doesn't exist, then no class */
1424 /* with this name exists either. */
1425 if (!(atom = GlobalFindAtomW( className )))
1427 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1428 return 0;
1431 return WIN_FindWindow( parent, child, atom, title );
1435 /***********************************************************************
1436 * FindWindowW (USER32.@)
1438 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1440 return FindWindowExW( 0, 0, className, title );
1444 /**********************************************************************
1445 * GetDesktopWindow (USER.286)
1447 HWND16 WINAPI GetDesktopWindow16(void)
1449 return (HWND16)pWndDesktop->hwndSelf;
1453 /**********************************************************************
1454 * GetDesktopWindow (USER32.@)
1456 HWND WINAPI GetDesktopWindow(void)
1458 if (pWndDesktop) return pWndDesktop->hwndSelf;
1459 ERR( "You need the -desktop option when running with native USER\n" );
1460 ExitProcess(1);
1461 return 0;
1465 /**********************************************************************
1466 * GetDesktopHwnd (USER.278)
1468 * Exactly the same thing as GetDesktopWindow(), but not documented.
1469 * Don't ask me why...
1471 HWND16 WINAPI GetDesktopHwnd16(void)
1473 return (HWND16)pWndDesktop->hwndSelf;
1477 /*******************************************************************
1478 * EnableWindow (USER.34)
1480 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1482 return EnableWindow( hwnd, enable );
1486 /*******************************************************************
1487 * EnableWindow (USER32.@)
1489 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1491 WND *wndPtr;
1492 BOOL retvalue;
1494 TRACE("( %x, %d )\n", hwnd, enable);
1496 if (USER_Driver.pEnableWindow)
1497 return USER_Driver.pEnableWindow( hwnd, enable );
1499 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1501 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1503 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1505 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1506 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1508 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1510 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1512 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1514 if (hwnd == GetFocus())
1515 SetFocus( 0 ); /* A disabled window can't have the focus */
1517 if (hwnd == GetCapture())
1518 ReleaseCapture(); /* A disabled window can't capture the mouse */
1520 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1522 WIN_ReleaseWndPtr(wndPtr);
1523 return retvalue;
1527 /***********************************************************************
1528 * IsWindowEnabled (USER.35)
1530 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1532 return IsWindowEnabled(hWnd);
1536 /***********************************************************************
1537 * IsWindowEnabled (USER32.@)
1539 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1541 WND * wndPtr;
1542 BOOL retvalue;
1544 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1545 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1546 WIN_ReleaseWndPtr(wndPtr);
1547 return retvalue;
1552 /***********************************************************************
1553 * IsWindowUnicode (USER32.@)
1555 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1557 WND * wndPtr;
1558 BOOL retvalue;
1560 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1561 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1562 WIN_ReleaseWndPtr(wndPtr);
1563 return retvalue;
1567 /**********************************************************************
1568 * GetWindowWord (USER.133)
1570 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1572 return GetWindowWord( hwnd, offset );
1576 /**********************************************************************
1577 * GetWindowWord (USER32.@)
1579 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1581 WORD retvalue;
1582 WND * wndPtr = WIN_FindWndPtr( hwnd );
1583 if (!wndPtr) return 0;
1584 if (offset >= 0)
1586 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1588 WARN("Invalid offset %d\n", offset );
1589 retvalue = 0;
1590 goto end;
1592 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1593 goto end;
1595 switch(offset)
1597 case GWW_ID:
1598 if (HIWORD(wndPtr->wIDmenu))
1599 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1600 wndPtr->wIDmenu);
1601 retvalue = (WORD)wndPtr->wIDmenu;
1602 goto end;
1603 case GWW_HWNDPARENT:
1604 retvalue = GetParent(hwnd);
1605 goto end;
1606 case GWW_HINSTANCE:
1607 if (HIWORD(wndPtr->hInstance))
1608 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1609 wndPtr->hInstance);
1610 retvalue = (WORD)wndPtr->hInstance;
1611 goto end;
1612 default:
1613 WARN("Invalid offset %d\n", offset );
1614 retvalue = 0;
1615 goto end;
1617 end:
1618 WIN_ReleaseWndPtr(wndPtr);
1619 return retvalue;
1622 /**********************************************************************
1623 * SetWindowWord (USER.134)
1625 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1627 return SetWindowWord( hwnd, offset, newval );
1631 /**********************************************************************
1632 * SetWindowWord (USER32.@)
1634 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1636 WORD *ptr, retval;
1637 WND * wndPtr = WIN_FindWndPtr( hwnd );
1638 if (!wndPtr) return 0;
1639 if (offset >= 0)
1641 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1643 WARN("Invalid offset %d\n", offset );
1644 retval = 0;
1645 goto end;
1647 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1649 else switch(offset)
1651 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1652 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1653 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1654 goto end;
1655 default:
1656 WARN("Invalid offset %d\n", offset );
1657 retval = 0;
1658 goto end;
1660 retval = *ptr;
1661 *ptr = newval;
1662 end:
1663 WIN_ReleaseWndPtr(wndPtr);
1664 return retval;
1668 /**********************************************************************
1669 * WIN_GetWindowLong
1671 * Helper function for GetWindowLong().
1673 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1675 LONG retvalue;
1676 WND * wndPtr = WIN_FindWndPtr( hwnd );
1677 if (!wndPtr) return 0;
1678 if (offset >= 0)
1680 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1682 WARN("Invalid offset %d\n", offset );
1683 retvalue = 0;
1684 goto end;
1686 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1687 /* Special case for dialog window procedure */
1688 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1690 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1691 goto end;
1693 goto end;
1695 switch(offset)
1697 case GWL_USERDATA: retvalue = wndPtr->userdata;
1698 goto end;
1699 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1700 goto end;
1701 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1702 goto end;
1703 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1704 goto end;
1705 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1706 type );
1707 goto end;
1708 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1709 goto end;
1710 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1711 goto end;
1712 default:
1713 WARN("Unknown offset %d\n", offset );
1715 retvalue = 0;
1716 end:
1717 WIN_ReleaseWndPtr(wndPtr);
1718 return retvalue;
1722 /**********************************************************************
1723 * WIN_SetWindowLong
1725 * Helper function for SetWindowLong().
1727 * 0 is the failure code. However, in the case of failure SetLastError
1728 * must be set to distinguish between a 0 return value and a failure.
1730 * FIXME: The error values for SetLastError may not be right. Can
1731 * someone check with the real thing?
1733 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1734 WINDOWPROCTYPE type )
1736 LONG *ptr, retval;
1737 WND * wndPtr = WIN_FindWndPtr( hwnd );
1738 STYLESTRUCT style;
1740 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1742 if (!wndPtr)
1744 /* Is this the right error? */
1745 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1746 return 0;
1749 if (offset >= 0)
1751 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1753 WARN("Invalid offset %d\n", offset );
1755 /* Is this the right error? */
1756 SetLastError( ERROR_OUTOFMEMORY );
1758 retval = 0;
1759 goto end;
1761 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1762 /* Special case for dialog window procedure */
1763 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1765 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1766 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1767 type, WIN_PROC_WINDOW );
1768 goto end;
1771 else switch(offset)
1773 case GWL_ID:
1774 ptr = (DWORD*)&wndPtr->wIDmenu;
1775 break;
1776 case GWL_HINSTANCE:
1777 retval = SetWindowWord( hwnd, offset, newval );
1778 goto end;
1779 case GWL_WNDPROC:
1780 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1781 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1782 type, WIN_PROC_WINDOW );
1783 goto end;
1784 case GWL_STYLE:
1785 style.styleOld = wndPtr->dwStyle;
1786 style.styleNew = newval;
1787 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1788 wndPtr->dwStyle = style.styleNew;
1789 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1790 retval = style.styleOld;
1791 goto end;
1793 case GWL_USERDATA:
1794 ptr = &wndPtr->userdata;
1795 break;
1796 case GWL_EXSTYLE:
1797 style.styleOld = wndPtr->dwExStyle;
1798 style.styleNew = newval;
1799 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1800 wndPtr->dwExStyle = newval;
1801 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1802 retval = style.styleOld;
1803 goto end;
1805 default:
1806 WARN("Invalid offset %d\n", offset );
1808 /* Don't think this is right error but it should do */
1809 SetLastError( ERROR_OUTOFMEMORY );
1811 retval = 0;
1812 goto end;
1814 retval = *ptr;
1815 *ptr = newval;
1816 end:
1817 WIN_ReleaseWndPtr(wndPtr);
1818 return retval;
1822 /**********************************************************************
1823 * GetWindowLong (USER.135)
1825 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1827 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1831 /**********************************************************************
1832 * GetWindowLongA (USER32.@)
1834 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1836 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1840 /**********************************************************************
1841 * GetWindowLongW (USER32.@)
1843 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1845 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1849 /**********************************************************************
1850 * SetWindowLong (USER.136)
1852 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1854 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1858 /**********************************************************************
1859 * SetWindowLongA (USER32.@)
1861 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1863 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1867 /**********************************************************************
1868 * SetWindowLongW (USER32.@) Set window attribute
1870 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1871 * value in a window's extra memory.
1873 * The _hwnd_ parameter specifies the window. is the handle to a
1874 * window that has extra memory. The _newval_ parameter contains the
1875 * new attribute or extra memory value. If positive, the _offset_
1876 * parameter is the byte-addressed location in the window's extra
1877 * memory to set. If negative, _offset_ specifies the window
1878 * attribute to set, and should be one of the following values:
1880 * GWL_EXSTYLE The window's extended window style
1882 * GWL_STYLE The window's window style.
1884 * GWL_WNDPROC Pointer to the window's window procedure.
1886 * GWL_HINSTANCE The window's pplication instance handle.
1888 * GWL_ID The window's identifier.
1890 * GWL_USERDATA The window's user-specified data.
1892 * If the window is a dialog box, the _offset_ parameter can be one of
1893 * the following values:
1895 * DWL_DLGPROC The address of the window's dialog box procedure.
1897 * DWL_MSGRESULT The return value of a message
1898 * that the dialog box procedure processed.
1900 * DWL_USER Application specific information.
1902 * RETURNS
1904 * If successful, returns the previous value located at _offset_. Otherwise,
1905 * returns 0.
1907 * NOTES
1909 * Extra memory for a window class is specified by a nonzero cbWndExtra
1910 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1911 * time of class creation.
1913 * Using GWL_WNDPROC to set a new window procedure effectively creates
1914 * a window subclass. Use CallWindowProc() in the new windows procedure
1915 * to pass messages to the superclass's window procedure.
1917 * The user data is reserved for use by the application which created
1918 * the window.
1920 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1921 * instead, call the EnableWindow() function to change the window's
1922 * disabled state.
1924 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1925 * SetParent() instead.
1927 * Win95:
1928 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1929 * it sends WM_STYLECHANGING before changing the settings
1930 * and WM_STYLECHANGED afterwards.
1931 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1933 * BUGS
1935 * GWL_STYLE does not dispatch WM_STYLE... messages.
1937 * CONFORMANCE
1939 * ECMA-234, Win32
1942 LONG WINAPI SetWindowLongW(
1943 HWND hwnd, /* [in] window to alter */
1944 INT offset, /* [in] offset, in bytes, of location to alter */
1945 LONG newval /* [in] new value of location */
1947 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1951 /*******************************************************************
1952 * GetWindowText (USER.36)
1954 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1956 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1960 /*******************************************************************
1961 * GetWindowTextA (USER32.@)
1963 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1965 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1966 (LPARAM)lpString );
1969 /*******************************************************************
1970 * InternalGetWindowText (USER32.@)
1972 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1974 WND *win = WIN_FindWndPtr( hwnd );
1975 if (!win) return 0;
1976 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1977 else lpString[0] = 0;
1978 WIN_ReleaseWndPtr( win );
1979 return strlenW(lpString);
1983 /*******************************************************************
1984 * GetWindowTextW (USER32.@)
1986 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1988 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1989 (LPARAM)lpString );
1993 /*******************************************************************
1994 * SetWindowText (USER.37)
1996 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1998 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2002 /*******************************************************************
2003 * SetWindowText (USER32.@)
2004 * SetWindowTextA (USER32.@)
2006 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2008 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2012 /*******************************************************************
2013 * SetWindowTextW (USER32.@)
2015 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2017 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2021 /*******************************************************************
2022 * GetWindowTextLength (USER.38)
2024 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2026 return (INT16)GetWindowTextLengthA( hwnd );
2030 /*******************************************************************
2031 * GetWindowTextLengthA (USER32.@)
2033 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2035 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2038 /*******************************************************************
2039 * GetWindowTextLengthW (USER32.@)
2041 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2043 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2047 /*******************************************************************
2048 * IsWindow (USER.47)
2050 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2052 CURRENT_STACK16->es = USER_HeapSel;
2053 return IsWindow( hwnd );
2057 /*******************************************************************
2058 * IsWindow (USER32.@)
2060 BOOL WINAPI IsWindow( HWND hwnd )
2062 WND *ptr;
2063 BOOL ret = FALSE;
2065 USER_Lock();
2066 if ((ptr = user_handles[LOWORD(hwnd)]))
2068 ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
2070 USER_Unlock();
2072 if (!ret) /* check other processes */
2074 SERVER_START_REQ( get_window_info )
2076 req->handle = hwnd;
2077 ret = !SERVER_CALL_ERR();
2079 SERVER_END_REQ;
2081 return ret;
2085 /***********************************************************************
2086 * GetWindowThreadProcessId (USER32.@)
2088 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2090 WND *ptr;
2091 DWORD tid = 0;
2093 USER_Lock();
2094 if ((ptr = user_handles[LOWORD(hwnd)]))
2096 if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
2098 /* got a valid window */
2099 tid = ptr->tid;
2100 if (process) *process = GetCurrentProcessId();
2102 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2103 USER_Unlock();
2104 return tid;
2106 USER_Unlock();
2108 /* check other processes */
2109 SERVER_START_REQ( get_window_info )
2111 req->handle = hwnd;
2112 if (!SERVER_CALL_ERR())
2114 tid = (DWORD)req->tid;
2115 if (process) *process = (DWORD)req->pid;
2118 SERVER_END_REQ;
2119 return tid;
2123 /*****************************************************************
2124 * GetParent (USER.46)
2126 HWND16 WINAPI GetParent16( HWND16 hwnd )
2128 return (HWND16)GetParent( hwnd );
2132 /*****************************************************************
2133 * GetParent (USER32.@)
2135 HWND WINAPI GetParent( HWND hwnd )
2137 WND *wndPtr;
2138 HWND retvalue = 0;
2140 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2142 if (wndPtr->dwStyle & WS_CHILD)
2143 retvalue = wndPtr->parent->hwndSelf;
2144 else if (wndPtr->dwStyle & WS_POPUP)
2145 retvalue = wndPtr->owner;
2146 WIN_ReleaseWndPtr(wndPtr);
2148 return retvalue;
2152 /*****************************************************************
2153 * GetAncestor (USER32.@)
2155 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2157 HWND ret;
2158 WND *wndPtr, *parent;
2160 if (hwnd == GetDesktopWindow()) return 0;
2161 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2162 parent = wndPtr->parent;
2164 switch(type)
2166 case GA_PARENT:
2167 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2168 break;
2169 case GA_ROOT:
2170 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2171 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2172 break;
2173 case GA_ROOTOWNER:
2174 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2175 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2176 while (wndPtr->owner)
2178 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2179 WIN_ReleaseWndPtr( wndPtr );
2180 wndPtr = ptr;
2182 break;
2184 ret = wndPtr->hwndSelf;
2185 WIN_ReleaseWndPtr( wndPtr );
2186 return ret;
2190 /*****************************************************************
2191 * SetParent (USER.233)
2193 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2195 return SetParent( hwndChild, hwndNewParent );
2199 /*****************************************************************
2200 * SetParent (USER32.@)
2202 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2204 WND *wndPtr;
2205 DWORD dwStyle;
2206 HWND retvalue;
2208 if (!parent) parent = GetDesktopWindow();
2210 /* sanity checks */
2211 if (hwnd == GetDesktopWindow() || !IsWindow( parent ))
2213 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2214 return 0;
2217 if (USER_Driver.pSetParent)
2218 return USER_Driver.pSetParent( hwnd, parent );
2220 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2222 dwStyle = wndPtr->dwStyle;
2224 /* Windows hides the window first, then shows it again
2225 * including the WM_SHOWWINDOW messages and all */
2226 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2228 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2229 if (parent != retvalue)
2231 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2233 if (parent != GetDesktopWindow()) /* a child window */
2235 if (!(dwStyle & WS_CHILD))
2237 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2238 if (menu) DestroyMenu( menu );
2242 WIN_ReleaseWndPtr( wndPtr );
2244 /* SetParent additionally needs to make hwnd the topmost window
2245 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2246 WM_WINDOWPOSCHANGED notification messages.
2248 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2249 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2250 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2251 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2252 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2253 return retvalue;
2257 /*******************************************************************
2258 * IsChild (USER.48)
2260 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2262 return IsChild(parent,child);
2266 /*******************************************************************
2267 * IsChild (USER32.@)
2269 BOOL WINAPI IsChild( HWND parent, HWND child )
2271 HWND *list = WIN_ListParents( child );
2272 int i;
2273 BOOL ret;
2275 if (!list) return FALSE;
2276 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2277 ret = (list[i] != 0);
2278 HeapFree( GetProcessHeap(), 0, list );
2279 return ret;
2283 /***********************************************************************
2284 * IsWindowVisible (USER.49)
2286 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2288 return IsWindowVisible(hwnd);
2292 /***********************************************************************
2293 * IsWindowVisible (USER32.@)
2295 BOOL WINAPI IsWindowVisible( HWND hwnd )
2297 HWND *list;
2298 BOOL retval;
2299 int i;
2301 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2302 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2303 for (i = 0; list[i]; i++)
2304 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2305 retval = !list[i];
2306 HeapFree( GetProcessHeap(), 0, list );
2307 return retval;
2311 /***********************************************************************
2312 * WIN_IsWindowDrawable
2314 * hwnd is drawable when it is visible, all parents are not
2315 * minimized, and it is itself not minimized unless we are
2316 * trying to draw its default class icon.
2318 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2320 HWND *list;
2321 BOOL retval;
2322 int i;
2324 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2325 if ((wnd->dwStyle & WS_MINIMIZE) &&
2326 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2328 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2329 for (i = 0; list[i]; i++)
2330 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2331 break;
2332 retval = !list[i];
2333 HeapFree( GetProcessHeap(), 0, list );
2334 return retval;
2338 /*******************************************************************
2339 * GetTopWindow (USER.229)
2341 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2343 return GetTopWindow(hwnd);
2347 /*******************************************************************
2348 * GetTopWindow (USER32.@)
2350 HWND WINAPI GetTopWindow( HWND hwnd )
2352 if (!hwnd) hwnd = GetDesktopWindow();
2353 return GetWindow( hwnd, GW_CHILD );
2357 /*******************************************************************
2358 * GetWindow (USER.262)
2360 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2362 return GetWindow( hwnd,rel );
2366 /*******************************************************************
2367 * GetWindow (USER32.@)
2369 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2371 HWND retval;
2373 WND * wndPtr = WIN_FindWndPtr( hwnd );
2374 if (!wndPtr) return 0;
2375 switch(rel)
2377 case GW_HWNDFIRST:
2378 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2379 goto end;
2381 case GW_HWNDLAST:
2382 if (!wndPtr->parent)
2384 retval = 0; /* Desktop window */
2385 goto end;
2387 while (wndPtr->next)
2389 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2391 retval = wndPtr->hwndSelf;
2392 goto end;
2394 case GW_HWNDNEXT:
2395 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2396 goto end;
2398 case GW_HWNDPREV:
2399 if (!wndPtr->parent)
2401 retval = 0; /* Desktop window */
2402 goto end;
2404 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2405 if (wndPtr->hwndSelf == hwnd)
2407 retval = 0; /* First in list */
2408 goto end;
2410 while (wndPtr->next)
2412 if (wndPtr->next->hwndSelf == hwnd)
2414 retval = wndPtr->hwndSelf;
2415 goto end;
2417 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2419 retval = 0;
2420 goto end;
2422 case GW_OWNER:
2423 retval = wndPtr->owner;
2424 goto end;
2426 case GW_CHILD:
2427 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2428 goto end;
2430 retval = 0;
2431 end:
2432 WIN_ReleaseWndPtr(wndPtr);
2433 return retval;
2437 /*******************************************************************
2438 * GetNextWindow (USER.230)
2440 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2442 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2443 return GetWindow16( hwnd, flag );
2446 /***********************************************************************
2447 * WIN_InternalShowOwnedPopups
2449 * Internal version of ShowOwnedPopups; Wine functions should use this
2450 * to avoid interfering with application calls to ShowOwnedPopups
2451 * and to make sure the application can't prevent showing/hiding.
2453 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2457 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2459 int count = 0;
2460 WND *pWnd;
2461 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2463 if (!win_array) return TRUE;
2466 * Show windows Lowest first, Highest last to preserve Z-Order
2468 while (win_array[count]) count++;
2469 while (--count >= 0)
2471 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2472 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2474 if (pWnd->dwStyle & WS_POPUP)
2476 if (fShow)
2478 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2479 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2482 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2484 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2485 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2488 else
2490 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2491 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2492 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2495 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2497 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2498 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2499 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2503 WIN_ReleaseWndPtr( pWnd );
2505 HeapFree( GetProcessHeap(), 0, win_array );
2507 return TRUE;
2510 /*******************************************************************
2511 * ShowOwnedPopups (USER.265)
2513 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2515 ShowOwnedPopups( owner, fShow );
2519 /*******************************************************************
2520 * ShowOwnedPopups (USER32.@)
2522 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2524 int count = 0;
2525 WND *pWnd;
2526 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2528 if (!win_array) return TRUE;
2530 while (win_array[count]) count++;
2531 while (--count >= 0)
2533 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2534 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2536 if (pWnd->dwStyle & WS_POPUP)
2538 if (fShow)
2540 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2542 /* In Windows, ShowOwnedPopups(TRUE) generates
2543 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2544 * regardless of the state of the owner
2546 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2547 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2550 else
2552 if (IsWindowVisible(pWnd->hwndSelf))
2554 /* In Windows, ShowOwnedPopups(FALSE) generates
2555 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2556 * regardless of the state of the owner
2558 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2559 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2563 WIN_ReleaseWndPtr( pWnd );
2565 HeapFree( GetProcessHeap(), 0, win_array );
2566 return TRUE;
2570 /*******************************************************************
2571 * GetLastActivePopup (USER.287)
2573 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2575 return GetLastActivePopup( hwnd );
2578 /*******************************************************************
2579 * GetLastActivePopup (USER32.@)
2581 HWND WINAPI GetLastActivePopup( HWND hwnd )
2583 HWND retval;
2584 WND *wndPtr =WIN_FindWndPtr(hwnd);
2585 if (!wndPtr) return hwnd;
2586 retval = wndPtr->hwndLastActive;
2587 WIN_ReleaseWndPtr(wndPtr);
2588 if ((retval != hwnd) && (!IsWindow(retval)))
2589 retval = hwnd;
2590 return retval;
2594 /*******************************************************************
2595 * WIN_ListParents
2597 * Build an array of all parents of a given window, starting with
2598 * the immediate parent. The array must be freed with HeapFree.
2599 * Returns NULL if window is a top-level window.
2601 HWND *WIN_ListParents( HWND hwnd )
2603 WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
2604 HWND *list = NULL;
2605 UINT i, count = 0;
2607 /* First count the windows */
2609 if (!wndPtr) return NULL;
2611 parent = wndPtr->parent;
2612 while (parent && parent->hwndSelf != GetDesktopWindow())
2614 count++;
2615 parent = parent->parent;
2618 if (count)
2620 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
2622 parent = wndPtr->parent;
2623 for (i = 0; i < count; i++)
2625 list[i] = parent->hwndSelf;
2626 parent = parent->parent;
2628 list[i] = 0;
2632 WIN_ReleaseWndPtr( wndPtr );
2633 return list;
2637 /*******************************************************************
2638 * WIN_ListChildren
2640 * Build an array of the children of a given window. The array must be
2641 * freed with HeapFree. Returns NULL when no windows are found.
2643 HWND *WIN_ListChildren( HWND hwnd )
2645 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2646 HWND *list, *phwnd;
2647 UINT count = 0;
2649 /* First count the windows */
2651 if (!wndPtr) return NULL;
2653 pWnd = WIN_LockWndPtr(wndPtr->child);
2654 while (pWnd)
2656 count++;
2657 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2660 if( count )
2662 /* Now build the list of all windows */
2664 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2666 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2668 *phwnd++ = pWnd->hwndSelf;
2669 count++;
2671 WIN_ReleaseWndPtr(pWnd);
2672 *phwnd = 0;
2674 else count = 0;
2675 } else list = NULL;
2677 WIN_ReleaseWndPtr( wndPtr );
2678 return list;
2682 /*******************************************************************
2683 * EnumWindows (USER32.@)
2685 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2687 HWND *list;
2688 BOOL ret = TRUE;
2689 int i, iWndsLocks;
2691 /* We have to build a list of all windows first, to avoid */
2692 /* unpleasant side-effects, for instance if the callback */
2693 /* function changes the Z-order of the windows. */
2695 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2697 /* Now call the callback function for every window */
2699 iWndsLocks = WIN_SuspendWndsLock();
2700 for (i = 0; list[i]; i++)
2702 /* Make sure that the window still exists */
2703 if (!IsWindow( list[i] )) continue;
2704 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2706 WIN_RestoreWndsLock(iWndsLocks);
2707 HeapFree( GetProcessHeap(), 0, list );
2708 return ret;
2712 /**********************************************************************
2713 * EnumTaskWindows16 (USER.225)
2715 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2716 LPARAM lParam )
2718 TDB *tdb = TASK_GetPtr( hTask );
2719 if (!tdb) return FALSE;
2720 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2724 /**********************************************************************
2725 * EnumThreadWindows (USER32.@)
2727 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2729 HWND *list;
2730 int i, iWndsLocks;
2732 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2734 /* Now call the callback function for every window */
2736 iWndsLocks = WIN_SuspendWndsLock();
2737 for (i = 0; list[i]; i++)
2739 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2740 if (!func( list[i], lParam )) break;
2742 WIN_RestoreWndsLock(iWndsLocks);
2743 HeapFree( GetProcessHeap(), 0, list );
2744 return TRUE;
2748 /**********************************************************************
2749 * WIN_EnumChildWindows
2751 * Helper function for EnumChildWindows().
2753 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2755 HWND *childList;
2756 BOOL ret = FALSE;
2758 for ( ; *list; list++)
2760 /* Make sure that the window still exists */
2761 if (!IsWindow( *list )) continue;
2762 /* skip owned windows */
2763 if (GetWindow( *list, GW_OWNER )) continue;
2764 /* Build children list first */
2765 childList = WIN_ListChildren( *list );
2767 ret = func( *list, lParam );
2769 if (childList)
2771 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2772 HeapFree( GetProcessHeap(), 0, childList );
2774 if (!ret) return FALSE;
2776 return TRUE;
2780 /**********************************************************************
2781 * EnumChildWindows (USER32.@)
2783 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2785 HWND *list;
2786 int iWndsLocks;
2788 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2789 iWndsLocks = WIN_SuspendWndsLock();
2790 WIN_EnumChildWindows( list, func, lParam );
2791 WIN_RestoreWndsLock(iWndsLocks);
2792 HeapFree( GetProcessHeap(), 0, list );
2793 return TRUE;
2797 /*******************************************************************
2798 * AnyPopup (USER.52)
2800 BOOL16 WINAPI AnyPopup16(void)
2802 return AnyPopup();
2806 /*******************************************************************
2807 * AnyPopup (USER32.@)
2809 BOOL WINAPI AnyPopup(void)
2811 int i;
2812 BOOL retvalue;
2813 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2815 if (!list) return FALSE;
2816 for (i = 0; list[i]; i++)
2818 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2820 retvalue = (list[i] != 0);
2821 HeapFree( GetProcessHeap(), 0, list );
2822 return retvalue;
2826 /*******************************************************************
2827 * FlashWindow (USER.105)
2829 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2831 return FlashWindow( hWnd, bInvert );
2835 /*******************************************************************
2836 * FlashWindow (USER32.@)
2838 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2840 WND *wndPtr = WIN_FindWndPtr(hWnd);
2842 TRACE("%04x\n", hWnd);
2844 if (!wndPtr) return FALSE;
2846 if (wndPtr->dwStyle & WS_MINIMIZE)
2848 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2850 HDC hDC = GetDC(hWnd);
2852 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2853 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2855 ReleaseDC( hWnd, hDC );
2856 wndPtr->flags |= WIN_NCACTIVATED;
2858 else
2860 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2861 wndPtr->flags &= ~WIN_NCACTIVATED;
2863 WIN_ReleaseWndPtr(wndPtr);
2864 return TRUE;
2866 else
2868 WPARAM16 wparam;
2869 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2870 else wparam = (hWnd == GetActiveWindow());
2872 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2873 WIN_ReleaseWndPtr(wndPtr);
2874 return wparam;
2879 /*******************************************************************
2880 * SetSysModalWindow (USER.188)
2882 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2884 HWND hWndOldModal = hwndSysModal;
2885 hwndSysModal = hWnd;
2886 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2887 return hWndOldModal;
2891 /*******************************************************************
2892 * GetSysModalWindow (USER.189)
2894 HWND16 WINAPI GetSysModalWindow16(void)
2896 return hwndSysModal;
2900 /*******************************************************************
2901 * GetWindowContextHelpId (USER32.@)
2903 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2905 DWORD retval;
2906 WND *wnd = WIN_FindWndPtr( hwnd );
2907 if (!wnd) return 0;
2908 retval = wnd->helpContext;
2909 WIN_ReleaseWndPtr(wnd);
2910 return retval;
2914 /*******************************************************************
2915 * SetWindowContextHelpId (USER32.@)
2917 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2919 WND *wnd = WIN_FindWndPtr( hwnd );
2920 if (!wnd) return FALSE;
2921 wnd->helpContext = id;
2922 WIN_ReleaseWndPtr(wnd);
2923 return TRUE;
2927 /*******************************************************************
2928 * DRAG_QueryUpdate
2930 * recursively find a child that contains spDragInfo->pt point
2931 * and send WM_QUERYDROPOBJECT
2933 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2935 BOOL16 wParam, bResult = 0;
2936 POINT pt;
2937 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2938 RECT tempRect;
2940 if (!ptrDragInfo) return FALSE;
2942 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2944 GetWindowRect(hQueryWnd,&tempRect);
2946 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2948 if (!IsIconic( hQueryWnd ))
2950 GetClientRect( hQueryWnd, &tempRect );
2951 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2953 if (PtInRect( &tempRect, pt))
2955 int i;
2956 HWND *list = WIN_ListChildren( hQueryWnd );
2958 wParam = 0;
2960 if (list)
2962 for (i = 0; list[i]; i++)
2964 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2966 GetWindowRect( list[i], &tempRect );
2967 if (PtInRect( &tempRect, pt )) break;
2970 if (list[i])
2972 if (IsWindowEnabled( list[i] ))
2973 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2975 HeapFree( GetProcessHeap(), 0, list );
2977 if(bResult) return bResult;
2979 else wParam = 1;
2981 else wParam = 1;
2983 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2985 ptrDragInfo->hScope = hQueryWnd;
2987 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2988 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2990 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2992 return bResult;
2996 /*******************************************************************
2997 * DragDetect (USER.465)
2999 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3001 POINT pt32;
3002 CONV_POINT16TO32( &pt, &pt32 );
3003 return DragDetect( hWnd, pt32 );
3006 /*******************************************************************
3007 * DragDetect (USER32.@)
3009 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3011 MSG msg;
3012 RECT rect;
3014 rect.left = pt.x - wDragWidth;
3015 rect.right = pt.x + wDragWidth;
3017 rect.top = pt.y - wDragHeight;
3018 rect.bottom = pt.y + wDragHeight;
3020 SetCapture(hWnd);
3022 while(1)
3024 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3026 if( msg.message == WM_LBUTTONUP )
3028 ReleaseCapture();
3029 return 0;
3031 if( msg.message == WM_MOUSEMOVE )
3033 POINT tmp;
3034 tmp.x = LOWORD(msg.lParam);
3035 tmp.y = HIWORD(msg.lParam);
3036 if( !PtInRect( &rect, tmp ))
3038 ReleaseCapture();
3039 return 1;
3043 WaitMessage();
3045 return 0;
3048 /******************************************************************************
3049 * DragObject (USER.464)
3051 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3052 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3054 MSG msg;
3055 LPDRAGINFO16 lpDragInfo;
3056 SEGPTR spDragInfo;
3057 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3058 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3059 HCURSOR16 hCurrentCursor = 0;
3060 HWND16 hCurrentWnd = 0;
3062 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3063 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3065 if( !lpDragInfo || !spDragInfo ) return 0L;
3067 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3069 GlobalFree16(hDragInfo);
3070 return 0L;
3073 if(hCursor)
3075 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3077 GlobalFree16(hDragInfo);
3078 return 0L;
3081 if( hDragCursor == hCursor ) hDragCursor = 0;
3082 else hCursor = hDragCursor;
3084 hOldCursor = SetCursor(hDragCursor);
3087 lpDragInfo->hWnd = hWnd;
3088 lpDragInfo->hScope = 0;
3089 lpDragInfo->wFlags = wObj;
3090 lpDragInfo->hList = szList; /* near pointer! */
3091 lpDragInfo->hOfStruct = hOfStruct;
3092 lpDragInfo->l = 0L;
3094 SetCapture(hWnd);
3095 ShowCursor( TRUE );
3099 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3101 *(lpDragInfo+1) = *lpDragInfo;
3103 lpDragInfo->pt.x = msg.pt.x;
3104 lpDragInfo->pt.y = msg.pt.y;
3106 /* update DRAGINFO struct */
3107 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3109 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3110 hCurrentCursor = hCursor;
3111 else
3113 hCurrentCursor = hBummer;
3114 lpDragInfo->hScope = 0;
3116 if( hCurrentCursor )
3117 SetCursor(hCurrentCursor);
3119 /* send WM_DRAGLOOP */
3120 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3121 (LPARAM) spDragInfo );
3122 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3123 if( hCurrentWnd != lpDragInfo->hScope )
3125 if( hCurrentWnd )
3126 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3127 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3128 HIWORD(spDragInfo)) );
3129 hCurrentWnd = lpDragInfo->hScope;
3130 if( hCurrentWnd )
3131 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3133 else
3134 if( hCurrentWnd )
3135 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3137 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3139 ReleaseCapture();
3140 ShowCursor( FALSE );
3142 if( hCursor )
3144 SetCursor( hOldCursor );
3145 if (hDragCursor) DestroyCursor( hDragCursor );
3148 if( hCurrentCursor != hBummer )
3149 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3150 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3151 else
3152 msg.lParam = 0;
3153 GlobalFree16(hDragInfo);
3155 return (DWORD)(msg.lParam);
3159 /******************************************************************************
3160 * GetWindowModuleFileNameA (USER32.@)
3162 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3164 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3165 hwnd, lpszFileName, cchFileNameMax);
3166 return 0;
3169 /******************************************************************************
3170 * GetWindowModuleFileNameW (USER32.@)
3172 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3174 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3175 hwnd, lpszFileName, cchFileNameMax);
3176 return 0;