The [windows] section is in win.ini not in ~/.wine/config.
[wine.git] / windows / win.c
blob6a7927705668e9ab34d4e941a9dc8c4a0c29e289
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_GetFullHandle
152 * Get the full 32-bit window handle from a possibly truncated handle.
154 HWND WIN_GetFullHandle( HWND hwnd )
156 if (!HIWORD(hwnd))
158 SERVER_START_REQ( get_window_info )
160 req->handle = hwnd;
161 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
163 SERVER_END_REQ;
165 return hwnd;
169 /***********************************************************************
170 * WIN_FindWndPtr
172 * Return a pointer to the WND structure corresponding to a HWND.
174 WND * WIN_FindWndPtr( HWND hwnd )
176 WND * ptr;
178 if (!hwnd) return NULL;
180 USER_Lock();
181 if (!(ptr = user_handles[LOWORD(hwnd)]))
183 /* check other processes */
184 if (IsWindow( hwnd ))
186 ERR( "window %04x belongs to other process\n", hwnd );
187 /* DbgBreakPoint(); */
189 goto error;
191 if (ptr->dwMagic != WND_MAGIC) goto error;
192 /* verify that handle highword (if any) matches the window */
193 if (HIWORD(hwnd) && hwnd != ptr->hwndSelf) goto error;
194 /*and increment destruction monitoring*/
195 ptr->irefCount++;
196 return ptr;
198 error:
199 /* Unlock all WND structures for thread safeness*/
200 USER_Unlock();
201 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
202 return NULL;
206 /***********************************************************************
207 * WIN_LockWndPtr
209 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
210 * but by initWndPtr;
211 * Returns the locked initialisation pointer
213 WND *WIN_LockWndPtr(WND *initWndPtr)
215 if(!initWndPtr) return 0;
217 /* Lock all WND structures for thread safeness*/
218 USER_Lock();
219 /*and increment destruction monitoring*/
220 initWndPtr->irefCount++;
222 return initWndPtr;
226 /***********************************************************************
227 * WIN_ReleaseWndPtr
229 * Release the pointer to the WND structure.
231 void WIN_ReleaseWndPtr(WND *wndPtr)
233 if(!wndPtr) return;
235 /*Decrement destruction monitoring value*/
236 wndPtr->irefCount--;
237 /* Check if it's time to release the memory*/
238 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
240 /* Release memory */
241 free_window_handle( wndPtr->hwndSelf );
243 else if(wndPtr->irefCount < 0)
245 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
246 ERR("forgot a Lock on %p somewhere\n",wndPtr);
248 /*unlock all WND structures for thread safeness*/
249 USER_Unlock();
252 /***********************************************************************
253 * WIN_UpdateWndPtr
255 * Updates the value of oldPtr to newPtr.
257 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
259 WND *tmpWnd = NULL;
261 tmpWnd = WIN_LockWndPtr(newPtr);
262 WIN_ReleaseWndPtr(*oldPtr);
263 *oldPtr = tmpWnd;
268 /***********************************************************************
269 * WIN_UnlinkWindow
271 * Remove a window from the siblings linked list.
273 void WIN_UnlinkWindow( HWND hwnd )
275 WIN_LinkWindow( hwnd, 0, 0 );
279 /***********************************************************************
280 * WIN_LinkWindow
282 * Insert a window into the siblings linked list.
283 * The window is inserted after the specified window, which can also
284 * be specified as HWND_TOP or HWND_BOTTOM.
285 * If parent is 0, window is unlinked from the tree.
287 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
289 WND *wndPtr, **ppWnd, *parentPtr = NULL;
290 BOOL ret;
292 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
293 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
295 WIN_ReleaseWndPtr(wndPtr);
296 return;
299 SERVER_START_REQ( link_window )
301 req->handle = hwnd;
302 req->parent = parent;
303 req->previous = hwndInsertAfter;
304 ret = !SERVER_CALL_ERR();
306 SERVER_END_REQ;
307 if (!ret) goto done;
309 /* first unlink it if it is linked */
310 if (wndPtr->parent)
312 ppWnd = &wndPtr->parent->child;
313 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
314 if (*ppWnd) *ppWnd = wndPtr->next;
317 if (parentPtr)
319 wndPtr->parent = parentPtr;
320 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
322 ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
323 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
324 while (*ppWnd) ppWnd = &(*ppWnd)->next;
326 else /* Normal case */
328 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
329 if (!afterPtr) goto done;
330 ppWnd = &afterPtr->next;
331 WIN_ReleaseWndPtr(afterPtr);
333 wndPtr->next = *ppWnd;
334 *ppWnd = wndPtr;
336 else wndPtr->next = NULL; /* unlinked */
338 done:
339 WIN_ReleaseWndPtr( parentPtr );
340 WIN_ReleaseWndPtr( wndPtr );
344 /***********************************************************************
345 * WIN_FindWinToRepaint
347 * Find a window that needs repaint.
349 HWND WIN_FindWinToRepaint( HWND hwnd )
351 HWND hwndRet;
352 WND *pWnd;
354 /* Note: the desktop window never gets WM_PAINT messages
355 * The real reason why is because Windows DesktopWndProc
356 * does ValidateRgn inside WM_ERASEBKGND handler.
358 if (hwnd == GetDesktopWindow()) hwnd = 0;
360 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
362 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
364 if (!(pWnd->dwStyle & WS_VISIBLE))
366 TRACE("skipping window %04x\n",
367 pWnd->hwndSelf );
369 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
370 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
371 break;
373 else if (pWnd->child )
374 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
376 WIN_ReleaseWndPtr(pWnd);
377 return hwndRet;
382 if(!pWnd)
384 return 0;
387 hwndRet = pWnd->hwndSelf;
389 /* look among siblings if we got a transparent window */
390 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
391 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
393 WIN_UpdateWndPtr(&pWnd,pWnd->next);
395 if (pWnd)
397 hwndRet = pWnd->hwndSelf;
398 WIN_ReleaseWndPtr(pWnd);
400 TRACE("found %04x\n",hwndRet);
401 return hwndRet;
405 /***********************************************************************
406 * WIN_DestroyWindow
408 * Destroy storage associated to a window. "Internals" p.358
409 * returns a locked wndPtr->next
411 static WND* WIN_DestroyWindow( WND* wndPtr )
413 HWND hwnd = wndPtr->hwndSelf;
414 WND *pWnd;
416 TRACE("%04x\n", wndPtr->hwndSelf );
418 /* free child windows */
419 WIN_LockWndPtr(wndPtr->child);
420 while ((pWnd = wndPtr->child))
422 wndPtr->child = WIN_DestroyWindow( pWnd );
423 WIN_ReleaseWndPtr(pWnd);
427 * Clear the update region to make sure no WM_PAINT messages will be
428 * generated for this window while processing the WM_NCDESTROY.
430 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
431 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
434 * Send the WM_NCDESTROY to the window being destroyed.
436 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
438 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
440 WINPOS_CheckInternalPos( hwnd );
441 if( hwnd == GetCapture()) ReleaseCapture();
443 /* free resources associated with the window */
445 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
446 PROPERTY_RemoveWindowProps( wndPtr );
448 /* toss stale messages from the queue */
450 QUEUE_CleanupWindow( hwnd );
451 wndPtr->hmemTaskQ = 0;
453 if (!(wndPtr->dwStyle & WS_CHILD))
454 if (wndPtr->wIDmenu)
456 DestroyMenu( wndPtr->wIDmenu );
457 wndPtr->wIDmenu = 0;
459 if (wndPtr->hSysMenu)
461 DestroyMenu( wndPtr->hSysMenu );
462 wndPtr->hSysMenu = 0;
464 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
465 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
466 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
467 CLASS_RemoveWindow( wndPtr->class );
468 wndPtr->class = NULL;
469 wndPtr->dwMagic = 0; /* Mark it as invalid */
471 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
473 return pWnd;
476 /***********************************************************************
477 * WIN_DestroyThreadWindows
479 * Destroy all children of 'wnd' owned by the current thread.
480 * Return TRUE if something was done.
482 void WIN_DestroyThreadWindows( HWND hwnd )
484 HWND *list;
485 int i;
487 if (!(list = WIN_ListChildren( hwnd ))) return;
488 for (i = 0; list[i]; i++)
490 if (!IsWindow( list[i] )) continue;
491 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
492 DestroyWindow( list[i] );
493 else
494 WIN_DestroyThreadWindows( list[i] );
496 HeapFree( GetProcessHeap(), 0, list );
499 /***********************************************************************
500 * WIN_CreateDesktopWindow
502 * Create the desktop window.
504 BOOL WIN_CreateDesktopWindow(void)
506 struct tagCLASS *class;
507 HWND hwndDesktop;
508 INT wndExtra;
509 DWORD clsStyle;
510 WNDPROC winproc;
511 DCE *dce;
512 CREATESTRUCTA cs;
514 TRACE("Creating desktop window\n");
517 if (!WINPOS_CreateInternalPosAtom() ||
518 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
519 &wndExtra, &winproc, &clsStyle, &dce )))
520 return FALSE;
522 pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra );
523 if (!pWndDesktop) return FALSE;
524 hwndDesktop = pWndDesktop->hwndSelf;
526 pWndDesktop->tid = 0; /* nobody owns the desktop */
527 pWndDesktop->next = NULL;
528 pWndDesktop->child = NULL;
529 pWndDesktop->parent = NULL;
530 pWndDesktop->owner = 0;
531 pWndDesktop->class = class;
532 pWndDesktop->hInstance = 0;
533 pWndDesktop->rectWindow.left = 0;
534 pWndDesktop->rectWindow.top = 0;
535 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
536 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
537 pWndDesktop->rectClient = pWndDesktop->rectWindow;
538 pWndDesktop->text = NULL;
539 pWndDesktop->hmemTaskQ = 0;
540 pWndDesktop->hrgnUpdate = 0;
541 pWndDesktop->hwndLastActive = hwndDesktop;
542 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
543 WS_CLIPSIBLINGS;
544 pWndDesktop->dwExStyle = 0;
545 pWndDesktop->clsStyle = clsStyle;
546 pWndDesktop->dce = NULL;
547 pWndDesktop->pVScroll = NULL;
548 pWndDesktop->pHScroll = NULL;
549 pWndDesktop->pProp = NULL;
550 pWndDesktop->wIDmenu = 0;
551 pWndDesktop->helpContext = 0;
552 pWndDesktop->flags = 0;
553 pWndDesktop->hSysMenu = 0;
554 pWndDesktop->userdata = 0;
555 pWndDesktop->winproc = winproc;
556 pWndDesktop->cbWndExtra = wndExtra;
558 cs.lpCreateParams = NULL;
559 cs.hInstance = 0;
560 cs.hMenu = 0;
561 cs.hwndParent = 0;
562 cs.x = 0;
563 cs.y = 0;
564 cs.cx = pWndDesktop->rectWindow.right;
565 cs.cy = pWndDesktop->rectWindow.bottom;
566 cs.style = pWndDesktop->dwStyle;
567 cs.dwExStyle = pWndDesktop->dwExStyle;
568 cs.lpszName = NULL;
569 cs.lpszClass = DESKTOP_CLASS_ATOM;
571 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
573 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
574 WIN_ReleaseWndPtr( pWndDesktop );
575 return TRUE;
579 /***********************************************************************
580 * WIN_FixCoordinates
582 * Fix the coordinates - Helper for WIN_CreateWindowEx.
583 * returns default show mode in sw.
584 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
586 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
588 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
589 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
591 if (cs->style & (WS_CHILD | WS_POPUP))
593 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
594 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
596 else /* overlapped window */
598 STARTUPINFOA info;
600 GetStartupInfoA( &info );
602 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
604 /* Never believe Microsoft's documentation... CreateWindowEx doc says
605 * that if an overlapped window is created with WS_VISIBLE style bit
606 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
607 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
608 * reveals that
610 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
611 * 2) it does not ignore the y parameter as the docs claim; instead, it
612 * uses it as second parameter to ShowWindow() unless y is either
613 * CW_USEDEFAULT or CW_USEDEFAULT16.
615 * The fact that we didn't do 2) caused bogus windows pop up when wine
616 * was running apps that were using this obscure feature. Example -
617 * calc.exe that comes with Win98 (only Win98, it's different from
618 * the one that comes with Win95 and NT)
620 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
621 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
622 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
625 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
627 if (info.dwFlags & STARTF_USESIZE)
629 cs->cx = info.dwXSize;
630 cs->cy = info.dwYSize;
632 else /* if no other hint from the app, pick 3/4 of the screen real estate */
634 RECT r;
635 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
636 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
637 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
644 /***********************************************************************
645 * WIN_CreateWindowEx
647 * Implementation of CreateWindowEx().
649 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
650 WINDOWPROCTYPE type )
652 INT sw = SW_SHOW;
653 struct tagCLASS *classPtr;
654 WND *wndPtr;
655 HWND hwnd, hwndLinkAfter;
656 POINT maxSize, maxPos, minTrack, maxTrack;
657 INT wndExtra;
658 DWORD clsStyle;
659 WNDPROC winproc;
660 DCE *dce;
661 BOOL unicode = (type == WIN_PROC_32W);
663 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
664 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
665 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
666 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
667 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
669 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
670 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
672 /* Find the parent window */
674 if (cs->hwndParent)
676 /* Make sure parent is valid */
677 if (!IsWindow( cs->hwndParent ))
679 WARN("Bad parent %04x\n", cs->hwndParent );
680 return 0;
682 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
683 WARN("No parent for child window\n" );
684 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
687 /* Find the window class */
688 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
689 &wndExtra, &winproc, &clsStyle, &dce )))
691 WARN("Bad class '%s'\n", cs->lpszClass );
692 return 0;
695 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
697 /* Correct the window style - stage 1
699 * These are patches that appear to affect both the style loaded into the
700 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
702 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
703 * why does the user get to set it?
706 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
707 * tested for WS_POPUP
709 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
710 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
711 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
712 cs->dwExStyle |= WS_EX_WINDOWEDGE;
713 else
714 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
716 /* Create the window structure */
718 if (!(wndPtr = create_window_handle( FALSE,
719 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
721 TRACE("out of memory\n" );
722 return 0;
724 hwnd = wndPtr->hwndSelf;
726 /* Fill the window structure */
728 wndPtr->tid = GetCurrentThreadId();
729 wndPtr->next = NULL;
730 wndPtr->child = NULL;
732 if ((cs->style & WS_CHILD) && cs->hwndParent)
734 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
735 wndPtr->owner = 0;
736 WIN_ReleaseWndPtr(wndPtr->parent);
738 else
740 wndPtr->parent = pWndDesktop;
741 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
742 wndPtr->owner = 0;
743 else
744 wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
748 wndPtr->class = classPtr;
749 wndPtr->winproc = winproc;
750 wndPtr->hInstance = cs->hInstance;
751 wndPtr->text = NULL;
752 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
753 wndPtr->hrgnUpdate = 0;
754 wndPtr->hrgnWnd = 0;
755 wndPtr->hwndLastActive = hwnd;
756 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
757 wndPtr->dwExStyle = cs->dwExStyle;
758 wndPtr->clsStyle = clsStyle;
759 wndPtr->wIDmenu = 0;
760 wndPtr->helpContext = 0;
761 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
762 wndPtr->pVScroll = NULL;
763 wndPtr->pHScroll = NULL;
764 wndPtr->pProp = NULL;
765 wndPtr->userdata = 0;
766 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
767 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
768 wndPtr->cbWndExtra = wndExtra;
770 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
772 /* Call the WH_CBT hook */
774 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
775 ? HWND_BOTTOM : HWND_TOP;
777 if (HOOK_IsHooked( WH_CBT ))
779 CBT_CREATEWNDA cbtc;
780 LRESULT ret;
782 cbtc.lpcs = cs;
783 cbtc.hwndInsertAfter = hwndLinkAfter;
784 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
785 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
786 if (ret)
788 TRACE("CBT-hook returned 0\n");
789 free_window_handle( hwnd );
790 CLASS_RemoveWindow( classPtr );
791 hwnd = 0;
792 goto end;
796 /* Correct the window style - stage 2 */
798 if (!(cs->style & WS_CHILD))
800 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
801 if (!(cs->style & WS_POPUP))
803 wndPtr->dwStyle |= WS_CAPTION;
804 wndPtr->flags |= WIN_NEED_SIZE;
808 /* Get class or window DC if needed */
810 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
811 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
812 else wndPtr->dce = NULL;
814 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
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 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
824 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
826 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
827 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
828 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
829 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
830 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
833 if (cs->cx < 0) cs->cx = 0;
834 if (cs->cy < 0) cs->cy = 0;
836 wndPtr->rectWindow.left = cs->x;
837 wndPtr->rectWindow.top = cs->y;
838 wndPtr->rectWindow.right = cs->x + cs->cx;
839 wndPtr->rectWindow.bottom = cs->y + cs->cy;
840 wndPtr->rectClient = wndPtr->rectWindow;
842 /* Set the window menu */
844 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
846 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
847 else
849 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
850 if (menuName)
852 if (HIWORD(cs->hInstance))
853 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
854 else
855 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
857 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
861 else wndPtr->wIDmenu = (UINT)cs->hMenu;
863 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
865 WARN("aborted by WM_xxCREATE!\n");
866 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
867 CLASS_RemoveWindow( classPtr );
868 WIN_ReleaseWndPtr(wndPtr);
869 return 0;
872 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
874 /* Notify the parent window only */
876 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
877 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
878 if( !IsWindow(hwnd) )
880 hwnd = 0;
881 goto end;
885 if (cs->style & WS_VISIBLE)
887 /* in case WS_VISIBLE got set in the meantime */
888 wndPtr->dwStyle &= ~WS_VISIBLE;
889 ShowWindow( hwnd, sw );
892 /* Call WH_SHELL hook */
894 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
895 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
897 TRACE("created window %04x\n", hwnd);
898 end:
899 WIN_ReleaseWndPtr(wndPtr);
900 return hwnd;
904 /***********************************************************************
905 * CreateWindow (USER.41)
907 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
908 DWORD style, INT16 x, INT16 y, INT16 width,
909 INT16 height, HWND16 parent, HMENU16 menu,
910 HINSTANCE16 instance, LPVOID data )
912 return CreateWindowEx16( 0, className, windowName, style,
913 x, y, width, height, parent, menu, instance, data );
917 /***********************************************************************
918 * CreateWindowEx (USER.452)
920 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
921 LPCSTR windowName, DWORD style, INT16 x,
922 INT16 y, INT16 width, INT16 height,
923 HWND16 parent, HMENU16 menu,
924 HINSTANCE16 instance, LPVOID data )
926 ATOM classAtom;
927 CREATESTRUCTA cs;
928 char buffer[256];
930 /* Find the class atom */
932 if (HIWORD(className))
934 if (!(classAtom = GlobalFindAtomA( className )))
936 ERR( "bad class name %s\n", debugres_a(className) );
937 return 0;
940 else
942 classAtom = LOWORD(className);
943 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
945 ERR( "bad atom %x\n", classAtom);
946 return 0;
948 className = buffer;
951 /* Fix the coordinates */
953 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
954 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
955 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
956 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
958 /* Create the window */
960 cs.lpCreateParams = data;
961 cs.hInstance = (HINSTANCE)instance;
962 cs.hMenu = (HMENU)menu;
963 cs.hwndParent = (HWND)parent;
964 cs.style = style;
965 cs.lpszName = windowName;
966 cs.lpszClass = className;
967 cs.dwExStyle = exStyle;
969 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
973 /***********************************************************************
974 * CreateWindowExA (USER32.@)
976 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
977 LPCSTR windowName, DWORD style, INT x,
978 INT y, INT width, INT height,
979 HWND parent, HMENU menu,
980 HINSTANCE instance, LPVOID data )
982 ATOM classAtom;
983 CREATESTRUCTA cs;
984 char buffer[256];
986 if(!instance)
987 instance=GetModuleHandleA(NULL);
989 if(exStyle & WS_EX_MDICHILD)
990 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
992 /* Find the class atom */
994 if (HIWORD(className))
996 if (!(classAtom = GlobalFindAtomA( className )))
998 ERR( "bad class name %s\n", debugres_a(className) );
999 return 0;
1002 else
1004 classAtom = LOWORD(className);
1005 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1007 ERR( "bad atom %x\n", classAtom);
1008 return 0;
1010 className = buffer;
1013 /* Create the window */
1015 cs.lpCreateParams = data;
1016 cs.hInstance = instance;
1017 cs.hMenu = menu;
1018 cs.hwndParent = parent;
1019 cs.x = x;
1020 cs.y = y;
1021 cs.cx = width;
1022 cs.cy = height;
1023 cs.style = style;
1024 cs.lpszName = windowName;
1025 cs.lpszClass = className;
1026 cs.dwExStyle = exStyle;
1028 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1032 /***********************************************************************
1033 * CreateWindowExW (USER32.@)
1035 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1036 LPCWSTR windowName, DWORD style, INT x,
1037 INT y, INT width, INT height,
1038 HWND parent, HMENU menu,
1039 HINSTANCE instance, LPVOID data )
1041 ATOM classAtom;
1042 CREATESTRUCTW cs;
1043 WCHAR buffer[256];
1045 if(!instance)
1046 instance=GetModuleHandleA(NULL);
1048 if(exStyle & WS_EX_MDICHILD)
1049 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1051 /* Find the class atom */
1053 if (HIWORD(className))
1055 if (!(classAtom = GlobalFindAtomW( className )))
1057 ERR( "bad class name %s\n", debugres_w(className) );
1058 return 0;
1061 else
1063 classAtom = LOWORD(className);
1064 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1066 ERR( "bad atom %x\n", classAtom);
1067 return 0;
1069 className = buffer;
1072 /* Create the window */
1074 cs.lpCreateParams = data;
1075 cs.hInstance = instance;
1076 cs.hMenu = menu;
1077 cs.hwndParent = parent;
1078 cs.x = x;
1079 cs.y = y;
1080 cs.cx = width;
1081 cs.cy = height;
1082 cs.style = style;
1083 cs.lpszName = windowName;
1084 cs.lpszClass = className;
1085 cs.dwExStyle = exStyle;
1087 /* Note: we rely on the fact that CREATESTRUCTA and */
1088 /* CREATESTRUCTW have the same layout. */
1089 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1093 /***********************************************************************
1094 * WIN_SendDestroyMsg
1096 static void WIN_SendDestroyMsg( HWND hwnd )
1098 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1099 if (USER_Driver.pResetSelectionOwner)
1100 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1103 * Send the WM_DESTROY to the window.
1105 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1108 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1109 * make sure that the window still exists when we come back.
1111 if (IsWindow(hwnd))
1113 HWND* pWndArray;
1114 int i;
1116 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1118 /* start from the end (FIXME: is this needed?) */
1119 for (i = 0; pWndArray[i]; i++) ;
1121 while (--i >= 0)
1123 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1125 HeapFree( GetProcessHeap(), 0, pWndArray );
1127 else
1128 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1132 /***********************************************************************
1133 * DestroyWindow (USER.53)
1135 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1137 return DestroyWindow(hwnd);
1141 /***********************************************************************
1142 * DestroyWindow (USER32.@)
1144 BOOL WINAPI DestroyWindow( HWND hwnd )
1146 WND * wndPtr;
1147 BOOL retvalue;
1148 HWND h;
1150 TRACE("(%04x)\n", hwnd);
1152 /* Initialization */
1154 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1156 /* Look whether the focus is within the tree of windows we will
1157 * be destroying.
1159 h = GetFocus();
1160 if (h == hwnd || IsChild( hwnd, h ))
1162 HWND parent = GetAncestor( hwnd, GA_PARENT );
1163 if (parent == GetDesktopWindow()) parent = 0;
1164 SetFocus( parent );
1167 /* Call hooks */
1169 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
1171 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1172 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1174 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1175 /* FIXME: clean up palette - see "Internals" p.352 */
1178 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1179 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1181 /* Notify the parent window only */
1182 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1183 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1184 if( !IsWindow(hwnd) )
1186 retvalue = TRUE;
1187 goto end;
1191 if (USER_Driver.pResetSelectionOwner)
1192 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1194 /* Hide the window */
1196 if (wndPtr->dwStyle & WS_VISIBLE)
1198 ShowWindow( hwnd, SW_HIDE );
1199 if (!IsWindow(hwnd))
1201 retvalue = TRUE;
1202 goto end;
1206 /* Recursively destroy owned windows */
1208 if( !(wndPtr->dwStyle & WS_CHILD) )
1210 for (;;)
1212 int i, got_one = 0;
1213 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1214 if (list)
1216 for (i = 0; list[i]; i++)
1218 WND *siblingPtr = WIN_FindWndPtr( list[i] );
1219 if (!siblingPtr) continue;
1220 if (siblingPtr->owner == hwnd)
1222 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1224 WIN_ReleaseWndPtr( siblingPtr );
1225 DestroyWindow( list[i] );
1226 got_one = 1;
1227 continue;
1229 else siblingPtr->owner = 0;
1231 WIN_ReleaseWndPtr( siblingPtr );
1233 HeapFree( GetProcessHeap(), 0, list );
1235 if (!got_one) break;
1238 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1240 if (wndPtr->owner)
1242 WND *owner = WIN_FindWndPtr( wndPtr->owner );
1243 if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
1244 WIN_ReleaseWndPtr( owner );
1248 /* Send destroy messages */
1250 WIN_SendDestroyMsg( hwnd );
1251 if (!IsWindow(hwnd))
1253 retvalue = TRUE;
1254 goto end;
1257 /* Unlink now so we won't bother with the children later on */
1259 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1261 /* Destroy the window storage */
1263 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1264 retvalue = TRUE;
1265 end:
1266 WIN_ReleaseWndPtr(wndPtr);
1267 return retvalue;
1271 /***********************************************************************
1272 * CloseWindow (USER.43)
1274 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1276 return CloseWindow( hwnd );
1280 /***********************************************************************
1281 * CloseWindow (USER32.@)
1283 BOOL WINAPI CloseWindow( HWND hwnd )
1285 WND * wndPtr = WIN_FindWndPtr( hwnd );
1286 BOOL retvalue;
1288 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1290 retvalue = FALSE;
1291 goto end;
1293 ShowWindow( hwnd, SW_MINIMIZE );
1294 retvalue = TRUE;
1295 end:
1296 WIN_ReleaseWndPtr(wndPtr);
1297 return retvalue;
1302 /***********************************************************************
1303 * OpenIcon (USER.44)
1305 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1307 return OpenIcon( hwnd );
1311 /***********************************************************************
1312 * OpenIcon (USER32.@)
1314 BOOL WINAPI OpenIcon( HWND hwnd )
1316 if (!IsIconic( hwnd )) return FALSE;
1317 ShowWindow( hwnd, SW_SHOWNORMAL );
1318 return TRUE;
1322 /***********************************************************************
1323 * WIN_FindWindow
1325 * Implementation of FindWindow() and FindWindowEx().
1327 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1329 HWND *list;
1330 HWND retvalue;
1331 int i = 0, len = 0;
1332 WCHAR *buffer = NULL;
1334 if (!parent) parent = GetDesktopWindow();
1335 if (title)
1337 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1338 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1341 if (!(list = WIN_ListChildren( parent )))
1343 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1344 return 0;
1347 if (child)
1349 while (list[i] && list[i] != child) i++;
1350 if (!list[i]) return 0;
1351 i++; /* start from next window */
1354 for ( ; list[i]; i++)
1356 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1357 continue; /* Not the right class */
1359 /* Now check the title */
1360 if (!title) break;
1361 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1363 retvalue = list[i];
1364 HeapFree( GetProcessHeap(), 0, list );
1365 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1367 /* In this case we need to check whether other processes
1368 own a window with the given paramters on the Desktop,
1369 but we don't, so let's at least warn about it */
1370 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1371 return retvalue;
1376 /***********************************************************************
1377 * FindWindow (USER.50)
1379 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1381 return FindWindowA( className, title );
1385 /***********************************************************************
1386 * FindWindowEx (USER.427)
1388 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1390 return FindWindowExA( parent, child, className, title );
1394 /***********************************************************************
1395 * FindWindowA (USER32.@)
1397 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1399 HWND ret = FindWindowExA( 0, 0, className, title );
1400 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1401 return ret;
1405 /***********************************************************************
1406 * FindWindowExA (USER32.@)
1408 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1409 LPCSTR className, LPCSTR title )
1411 ATOM atom = 0;
1412 LPWSTR buffer;
1413 HWND hwnd;
1415 if (className)
1417 /* If the atom doesn't exist, then no class */
1418 /* with this name exists either. */
1419 if (!(atom = GlobalFindAtomA( className )))
1421 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1422 return 0;
1426 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1427 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1428 HeapFree( GetProcessHeap(), 0, buffer );
1429 return hwnd;
1433 /***********************************************************************
1434 * FindWindowExW (USER32.@)
1436 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1437 LPCWSTR className, LPCWSTR title )
1439 ATOM atom = 0;
1441 if (className)
1443 /* If the atom doesn't exist, then no class */
1444 /* with this name exists either. */
1445 if (!(atom = GlobalFindAtomW( className )))
1447 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1448 return 0;
1451 return WIN_FindWindow( parent, child, atom, title );
1455 /***********************************************************************
1456 * FindWindowW (USER32.@)
1458 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1460 return FindWindowExW( 0, 0, className, title );
1464 /**********************************************************************
1465 * GetDesktopWindow (USER.286)
1467 HWND16 WINAPI GetDesktopWindow16(void)
1469 return (HWND16)pWndDesktop->hwndSelf;
1473 /**********************************************************************
1474 * GetDesktopWindow (USER32.@)
1476 HWND WINAPI GetDesktopWindow(void)
1478 if (pWndDesktop) return pWndDesktop->hwndSelf;
1479 ERR( "You need the -desktop option when running with native USER\n" );
1480 ExitProcess(1);
1481 return 0;
1485 /**********************************************************************
1486 * GetDesktopHwnd (USER.278)
1488 * Exactly the same thing as GetDesktopWindow(), but not documented.
1489 * Don't ask me why...
1491 HWND16 WINAPI GetDesktopHwnd16(void)
1493 return (HWND16)pWndDesktop->hwndSelf;
1497 /*******************************************************************
1498 * EnableWindow (USER.34)
1500 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1502 return EnableWindow( hwnd, enable );
1506 /*******************************************************************
1507 * EnableWindow (USER32.@)
1509 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1511 WND *wndPtr;
1512 BOOL retvalue;
1514 TRACE("( %x, %d )\n", hwnd, enable);
1516 if (USER_Driver.pEnableWindow)
1517 return USER_Driver.pEnableWindow( hwnd, enable );
1519 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1521 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1523 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1525 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1526 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1528 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1530 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1532 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1534 if (hwnd == GetFocus())
1535 SetFocus( 0 ); /* A disabled window can't have the focus */
1537 if (hwnd == GetCapture())
1538 ReleaseCapture(); /* A disabled window can't capture the mouse */
1540 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1542 WIN_ReleaseWndPtr(wndPtr);
1543 return retvalue;
1547 /***********************************************************************
1548 * IsWindowEnabled (USER.35)
1550 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1552 return IsWindowEnabled(hWnd);
1556 /***********************************************************************
1557 * IsWindowEnabled (USER32.@)
1559 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1561 WND * wndPtr;
1562 BOOL retvalue;
1564 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1565 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1566 WIN_ReleaseWndPtr(wndPtr);
1567 return retvalue;
1572 /***********************************************************************
1573 * IsWindowUnicode (USER32.@)
1575 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1577 WND * wndPtr;
1578 BOOL retvalue;
1580 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1581 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1582 WIN_ReleaseWndPtr(wndPtr);
1583 return retvalue;
1587 /**********************************************************************
1588 * GetWindowWord (USER.133)
1590 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1592 return GetWindowWord( hwnd, offset );
1596 /**********************************************************************
1597 * GetWindowWord (USER32.@)
1599 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1601 WORD retvalue;
1602 WND * wndPtr = WIN_FindWndPtr( hwnd );
1603 if (!wndPtr) return 0;
1604 if (offset >= 0)
1606 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1608 WARN("Invalid offset %d\n", offset );
1609 retvalue = 0;
1610 goto end;
1612 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1613 goto end;
1615 switch(offset)
1617 case GWW_ID:
1618 if (HIWORD(wndPtr->wIDmenu))
1619 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1620 wndPtr->wIDmenu);
1621 retvalue = (WORD)wndPtr->wIDmenu;
1622 goto end;
1623 case GWW_HWNDPARENT:
1624 retvalue = GetParent(hwnd);
1625 goto end;
1626 case GWW_HINSTANCE:
1627 if (HIWORD(wndPtr->hInstance))
1628 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1629 wndPtr->hInstance);
1630 retvalue = (WORD)wndPtr->hInstance;
1631 goto end;
1632 default:
1633 WARN("Invalid offset %d\n", offset );
1634 retvalue = 0;
1635 goto end;
1637 end:
1638 WIN_ReleaseWndPtr(wndPtr);
1639 return retvalue;
1642 /**********************************************************************
1643 * SetWindowWord (USER.134)
1645 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1647 return SetWindowWord( hwnd, offset, newval );
1651 /**********************************************************************
1652 * SetWindowWord (USER32.@)
1654 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1656 WORD *ptr, retval;
1657 WND * wndPtr = WIN_FindWndPtr( hwnd );
1658 if (!wndPtr) return 0;
1659 if (offset >= 0)
1661 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1663 WARN("Invalid offset %d\n", offset );
1664 retval = 0;
1665 goto end;
1667 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1669 else switch(offset)
1671 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1672 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1673 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1674 goto end;
1675 default:
1676 WARN("Invalid offset %d\n", offset );
1677 retval = 0;
1678 goto end;
1680 retval = *ptr;
1681 *ptr = newval;
1682 end:
1683 WIN_ReleaseWndPtr(wndPtr);
1684 return retval;
1688 /**********************************************************************
1689 * WIN_GetWindowLong
1691 * Helper function for GetWindowLong().
1693 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1695 LONG retvalue;
1696 WND * wndPtr = WIN_FindWndPtr( hwnd );
1697 if (!wndPtr) return 0;
1698 if (offset >= 0)
1700 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1702 WARN("Invalid offset %d\n", offset );
1703 retvalue = 0;
1704 goto end;
1706 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1707 /* Special case for dialog window procedure */
1708 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1710 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1711 goto end;
1713 goto end;
1715 switch(offset)
1717 case GWL_USERDATA: retvalue = wndPtr->userdata;
1718 goto end;
1719 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1720 goto end;
1721 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1722 goto end;
1723 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1724 goto end;
1725 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1726 type );
1727 goto end;
1728 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1729 goto end;
1730 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1731 goto end;
1732 default:
1733 WARN("Unknown offset %d\n", offset );
1735 retvalue = 0;
1736 end:
1737 WIN_ReleaseWndPtr(wndPtr);
1738 return retvalue;
1742 /**********************************************************************
1743 * WIN_SetWindowLong
1745 * Helper function for SetWindowLong().
1747 * 0 is the failure code. However, in the case of failure SetLastError
1748 * must be set to distinguish between a 0 return value and a failure.
1750 * FIXME: The error values for SetLastError may not be right. Can
1751 * someone check with the real thing?
1753 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1754 WINDOWPROCTYPE type )
1756 LONG *ptr, retval;
1757 WND * wndPtr = WIN_FindWndPtr( hwnd );
1758 STYLESTRUCT style;
1760 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1762 if (!wndPtr)
1764 /* Is this the right error? */
1765 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1766 return 0;
1769 if (offset >= 0)
1771 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1773 WARN("Invalid offset %d\n", offset );
1775 /* Is this the right error? */
1776 SetLastError( ERROR_OUTOFMEMORY );
1778 retval = 0;
1779 goto end;
1781 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1782 /* Special case for dialog window procedure */
1783 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1785 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1786 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1787 type, WIN_PROC_WINDOW );
1788 goto end;
1791 else switch(offset)
1793 case GWL_ID:
1794 ptr = (DWORD*)&wndPtr->wIDmenu;
1795 break;
1796 case GWL_HINSTANCE:
1797 retval = SetWindowWord( hwnd, offset, newval );
1798 goto end;
1799 case GWL_WNDPROC:
1800 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1801 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1802 type, WIN_PROC_WINDOW );
1803 goto end;
1804 case GWL_STYLE:
1805 style.styleOld = wndPtr->dwStyle;
1806 style.styleNew = newval;
1807 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1808 wndPtr->dwStyle = style.styleNew;
1809 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1810 retval = style.styleOld;
1811 goto end;
1813 case GWL_USERDATA:
1814 ptr = &wndPtr->userdata;
1815 break;
1816 case GWL_EXSTYLE:
1817 style.styleOld = wndPtr->dwExStyle;
1818 style.styleNew = newval;
1819 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1820 wndPtr->dwExStyle = style.styleNew;
1821 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1822 retval = style.styleOld;
1823 goto end;
1825 default:
1826 WARN("Invalid offset %d\n", offset );
1828 /* Don't think this is right error but it should do */
1829 SetLastError( ERROR_OUTOFMEMORY );
1831 retval = 0;
1832 goto end;
1834 retval = *ptr;
1835 *ptr = newval;
1836 end:
1837 WIN_ReleaseWndPtr(wndPtr);
1838 return retval;
1842 /**********************************************************************
1843 * GetWindowLong (USER.135)
1845 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1847 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1851 /**********************************************************************
1852 * GetWindowLongA (USER32.@)
1854 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1856 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1860 /**********************************************************************
1861 * GetWindowLongW (USER32.@)
1863 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1865 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1869 /**********************************************************************
1870 * SetWindowLong (USER.136)
1872 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1874 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1878 /**********************************************************************
1879 * SetWindowLongA (USER32.@)
1881 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1883 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1887 /**********************************************************************
1888 * SetWindowLongW (USER32.@) Set window attribute
1890 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1891 * value in a window's extra memory.
1893 * The _hwnd_ parameter specifies the window. is the handle to a
1894 * window that has extra memory. The _newval_ parameter contains the
1895 * new attribute or extra memory value. If positive, the _offset_
1896 * parameter is the byte-addressed location in the window's extra
1897 * memory to set. If negative, _offset_ specifies the window
1898 * attribute to set, and should be one of the following values:
1900 * GWL_EXSTYLE The window's extended window style
1902 * GWL_STYLE The window's window style.
1904 * GWL_WNDPROC Pointer to the window's window procedure.
1906 * GWL_HINSTANCE The window's pplication instance handle.
1908 * GWL_ID The window's identifier.
1910 * GWL_USERDATA The window's user-specified data.
1912 * If the window is a dialog box, the _offset_ parameter can be one of
1913 * the following values:
1915 * DWL_DLGPROC The address of the window's dialog box procedure.
1917 * DWL_MSGRESULT The return value of a message
1918 * that the dialog box procedure processed.
1920 * DWL_USER Application specific information.
1922 * RETURNS
1924 * If successful, returns the previous value located at _offset_. Otherwise,
1925 * returns 0.
1927 * NOTES
1929 * Extra memory for a window class is specified by a nonzero cbWndExtra
1930 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1931 * time of class creation.
1933 * Using GWL_WNDPROC to set a new window procedure effectively creates
1934 * a window subclass. Use CallWindowProc() in the new windows procedure
1935 * to pass messages to the superclass's window procedure.
1937 * The user data is reserved for use by the application which created
1938 * the window.
1940 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1941 * instead, call the EnableWindow() function to change the window's
1942 * disabled state.
1944 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1945 * SetParent() instead.
1947 * Win95:
1948 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1949 * it sends WM_STYLECHANGING before changing the settings
1950 * and WM_STYLECHANGED afterwards.
1951 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1953 * BUGS
1955 * GWL_STYLE does not dispatch WM_STYLE... messages.
1957 * CONFORMANCE
1959 * ECMA-234, Win32
1962 LONG WINAPI SetWindowLongW(
1963 HWND hwnd, /* [in] window to alter */
1964 INT offset, /* [in] offset, in bytes, of location to alter */
1965 LONG newval /* [in] new value of location */
1967 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1971 /*******************************************************************
1972 * GetWindowText (USER.36)
1974 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1976 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1980 /*******************************************************************
1981 * GetWindowTextA (USER32.@)
1983 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1985 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1986 (LPARAM)lpString );
1989 /*******************************************************************
1990 * InternalGetWindowText (USER32.@)
1992 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1994 WND *win = WIN_FindWndPtr( hwnd );
1995 if (!win) return 0;
1996 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1997 else lpString[0] = 0;
1998 WIN_ReleaseWndPtr( win );
1999 return strlenW(lpString);
2003 /*******************************************************************
2004 * GetWindowTextW (USER32.@)
2006 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2008 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2009 (LPARAM)lpString );
2013 /*******************************************************************
2014 * SetWindowText (USER.37)
2016 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2018 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2022 /*******************************************************************
2023 * SetWindowText (USER32.@)
2024 * SetWindowTextA (USER32.@)
2026 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2028 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2032 /*******************************************************************
2033 * SetWindowTextW (USER32.@)
2035 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2037 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2041 /*******************************************************************
2042 * GetWindowTextLength (USER.38)
2044 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2046 return (INT16)GetWindowTextLengthA( hwnd );
2050 /*******************************************************************
2051 * GetWindowTextLengthA (USER32.@)
2053 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2055 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2058 /*******************************************************************
2059 * GetWindowTextLengthW (USER32.@)
2061 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2063 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2067 /*******************************************************************
2068 * IsWindow (USER.47)
2070 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2072 CURRENT_STACK16->es = USER_HeapSel;
2073 return IsWindow( hwnd );
2077 /*******************************************************************
2078 * IsWindow (USER32.@)
2080 BOOL WINAPI IsWindow( HWND hwnd )
2082 WND *ptr;
2083 BOOL ret = FALSE;
2085 USER_Lock();
2086 if ((ptr = user_handles[LOWORD(hwnd)]))
2088 ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
2090 USER_Unlock();
2092 if (!ret) /* check other processes */
2094 SERVER_START_REQ( get_window_info )
2096 req->handle = hwnd;
2097 ret = !SERVER_CALL_ERR();
2099 SERVER_END_REQ;
2101 return ret;
2105 /***********************************************************************
2106 * GetWindowThreadProcessId (USER32.@)
2108 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2110 WND *ptr;
2111 DWORD tid = 0;
2113 USER_Lock();
2114 if ((ptr = user_handles[LOWORD(hwnd)]))
2116 if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
2118 /* got a valid window */
2119 tid = ptr->tid;
2120 if (process) *process = GetCurrentProcessId();
2122 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2123 USER_Unlock();
2124 return tid;
2126 USER_Unlock();
2128 /* check other processes */
2129 SERVER_START_REQ( get_window_info )
2131 req->handle = hwnd;
2132 if (!SERVER_CALL_ERR())
2134 tid = (DWORD)req->tid;
2135 if (process) *process = (DWORD)req->pid;
2138 SERVER_END_REQ;
2139 return tid;
2143 /*****************************************************************
2144 * GetParent (USER.46)
2146 HWND16 WINAPI GetParent16( HWND16 hwnd )
2148 return (HWND16)GetParent( hwnd );
2152 /*****************************************************************
2153 * GetParent (USER32.@)
2155 HWND WINAPI GetParent( HWND hwnd )
2157 WND *wndPtr;
2158 HWND retvalue = 0;
2160 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2162 if (wndPtr->dwStyle & WS_CHILD)
2163 retvalue = wndPtr->parent->hwndSelf;
2164 else if (wndPtr->dwStyle & WS_POPUP)
2165 retvalue = wndPtr->owner;
2166 WIN_ReleaseWndPtr(wndPtr);
2168 return retvalue;
2172 /*****************************************************************
2173 * GetAncestor (USER32.@)
2175 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2177 HWND ret;
2178 WND *wndPtr;
2180 if (hwnd == GetDesktopWindow()) return 0;
2181 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2183 switch(type)
2185 case GA_PARENT:
2186 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2187 break;
2188 case GA_ROOT:
2189 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2190 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2191 break;
2192 case GA_ROOTOWNER:
2193 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2194 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2195 while (wndPtr && wndPtr->owner)
2197 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2198 WIN_ReleaseWndPtr( wndPtr );
2199 wndPtr = ptr;
2201 break;
2203 ret = wndPtr ? wndPtr->hwndSelf : 0;
2204 WIN_ReleaseWndPtr( wndPtr );
2205 return ret;
2209 /*****************************************************************
2210 * SetParent (USER.233)
2212 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2214 return SetParent( hwndChild, hwndNewParent );
2218 /*****************************************************************
2219 * SetParent (USER32.@)
2221 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2223 WND *wndPtr;
2224 DWORD dwStyle;
2225 HWND retvalue;
2227 if (!parent) parent = GetDesktopWindow();
2229 /* sanity checks */
2230 if (hwnd == GetDesktopWindow() || !IsWindow( parent ))
2232 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2233 return 0;
2236 if (USER_Driver.pSetParent)
2237 return USER_Driver.pSetParent( hwnd, parent );
2239 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2241 dwStyle = wndPtr->dwStyle;
2243 /* Windows hides the window first, then shows it again
2244 * including the WM_SHOWWINDOW messages and all */
2245 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2247 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2248 if (parent != retvalue)
2250 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2252 if (parent != GetDesktopWindow()) /* a child window */
2254 if (!(dwStyle & WS_CHILD))
2256 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2257 if (menu) DestroyMenu( menu );
2261 WIN_ReleaseWndPtr( wndPtr );
2263 /* SetParent additionally needs to make hwnd the topmost window
2264 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2265 WM_WINDOWPOSCHANGED notification messages.
2267 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2268 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2269 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2270 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2271 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2272 return retvalue;
2276 /*******************************************************************
2277 * IsChild (USER.48)
2279 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2281 return IsChild(parent,child);
2285 /*******************************************************************
2286 * IsChild (USER32.@)
2288 BOOL WINAPI IsChild( HWND parent, HWND child )
2290 HWND *list = WIN_ListParents( child );
2291 int i;
2292 BOOL ret;
2294 if (!list) return FALSE;
2295 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2296 ret = (list[i] != 0);
2297 HeapFree( GetProcessHeap(), 0, list );
2298 return ret;
2302 /***********************************************************************
2303 * IsWindowVisible (USER.49)
2305 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2307 return IsWindowVisible(hwnd);
2311 /***********************************************************************
2312 * IsWindowVisible (USER32.@)
2314 BOOL WINAPI IsWindowVisible( HWND hwnd )
2316 HWND *list;
2317 BOOL retval;
2318 int i;
2320 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2321 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2322 for (i = 0; list[i]; i++)
2323 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2324 retval = !list[i];
2325 HeapFree( GetProcessHeap(), 0, list );
2326 return retval;
2330 /***********************************************************************
2331 * WIN_IsWindowDrawable
2333 * hwnd is drawable when it is visible, all parents are not
2334 * minimized, and it is itself not minimized unless we are
2335 * trying to draw its default class icon.
2337 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2339 HWND *list;
2340 BOOL retval;
2341 int i;
2343 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2344 if ((wnd->dwStyle & WS_MINIMIZE) &&
2345 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2347 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2348 for (i = 0; list[i]; i++)
2349 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2350 break;
2351 retval = !list[i];
2352 HeapFree( GetProcessHeap(), 0, list );
2353 return retval;
2357 /*******************************************************************
2358 * GetTopWindow (USER.229)
2360 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2362 return GetTopWindow(hwnd);
2366 /*******************************************************************
2367 * GetTopWindow (USER32.@)
2369 HWND WINAPI GetTopWindow( HWND hwnd )
2371 if (!hwnd) hwnd = GetDesktopWindow();
2372 return GetWindow( hwnd, GW_CHILD );
2376 /*******************************************************************
2377 * GetWindow (USER.262)
2379 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2381 return GetWindow( hwnd,rel );
2385 /*******************************************************************
2386 * GetWindow (USER32.@)
2388 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2390 HWND retval;
2392 WND * wndPtr = WIN_FindWndPtr( hwnd );
2393 if (!wndPtr) return 0;
2394 switch(rel)
2396 case GW_HWNDFIRST:
2397 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2398 goto end;
2400 case GW_HWNDLAST:
2401 if (!wndPtr->parent)
2403 retval = 0; /* Desktop window */
2404 goto end;
2406 while (wndPtr->next)
2408 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2410 retval = wndPtr->hwndSelf;
2411 goto end;
2413 case GW_HWNDNEXT:
2414 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2415 goto end;
2417 case GW_HWNDPREV:
2418 if (!wndPtr->parent)
2420 retval = 0; /* Desktop window */
2421 goto end;
2423 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2424 if (wndPtr->hwndSelf == hwnd)
2426 retval = 0; /* First in list */
2427 goto end;
2429 while (wndPtr->next)
2431 if (wndPtr->next->hwndSelf == hwnd)
2433 retval = wndPtr->hwndSelf;
2434 goto end;
2436 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2438 retval = 0;
2439 goto end;
2441 case GW_OWNER:
2442 retval = wndPtr->owner;
2443 goto end;
2445 case GW_CHILD:
2446 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2447 goto end;
2449 retval = 0;
2450 end:
2451 WIN_ReleaseWndPtr(wndPtr);
2452 return retval;
2456 /*******************************************************************
2457 * GetNextWindow (USER.230)
2459 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2461 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2462 return GetWindow16( hwnd, flag );
2465 /***********************************************************************
2466 * WIN_InternalShowOwnedPopups
2468 * Internal version of ShowOwnedPopups; Wine functions should use this
2469 * to avoid interfering with application calls to ShowOwnedPopups
2470 * and to make sure the application can't prevent showing/hiding.
2472 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2476 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2478 int count = 0;
2479 WND *pWnd;
2480 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2482 if (!win_array) return TRUE;
2485 * Show windows Lowest first, Highest last to preserve Z-Order
2487 while (win_array[count]) count++;
2488 while (--count >= 0)
2490 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2491 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2493 if (pWnd->dwStyle & WS_POPUP)
2495 if (fShow)
2497 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2498 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2501 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2503 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2504 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2507 else
2509 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2510 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2511 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2514 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2516 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2517 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2518 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2522 WIN_ReleaseWndPtr( pWnd );
2524 HeapFree( GetProcessHeap(), 0, win_array );
2526 return TRUE;
2529 /*******************************************************************
2530 * ShowOwnedPopups (USER.265)
2532 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2534 ShowOwnedPopups( owner, fShow );
2538 /*******************************************************************
2539 * ShowOwnedPopups (USER32.@)
2541 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2543 int count = 0;
2544 WND *pWnd;
2545 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2547 if (!win_array) return TRUE;
2549 while (win_array[count]) count++;
2550 while (--count >= 0)
2552 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2553 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2555 if (pWnd->dwStyle & WS_POPUP)
2557 if (fShow)
2559 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2561 /* In Windows, ShowOwnedPopups(TRUE) generates
2562 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2563 * regardless of the state of the owner
2565 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2566 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2569 else
2571 if (IsWindowVisible(pWnd->hwndSelf))
2573 /* In Windows, ShowOwnedPopups(FALSE) generates
2574 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2575 * regardless of the state of the owner
2577 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2578 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2582 WIN_ReleaseWndPtr( pWnd );
2584 HeapFree( GetProcessHeap(), 0, win_array );
2585 return TRUE;
2589 /*******************************************************************
2590 * GetLastActivePopup (USER.287)
2592 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2594 return GetLastActivePopup( hwnd );
2597 /*******************************************************************
2598 * GetLastActivePopup (USER32.@)
2600 HWND WINAPI GetLastActivePopup( HWND hwnd )
2602 HWND retval;
2603 WND *wndPtr =WIN_FindWndPtr(hwnd);
2604 if (!wndPtr) return hwnd;
2605 retval = wndPtr->hwndLastActive;
2606 WIN_ReleaseWndPtr(wndPtr);
2607 if ((retval != hwnd) && (!IsWindow(retval)))
2608 retval = hwnd;
2609 return retval;
2613 /*******************************************************************
2614 * WIN_ListParents
2616 * Build an array of all parents of a given window, starting with
2617 * the immediate parent. The array must be freed with HeapFree.
2618 * Returns NULL if window is a top-level window.
2620 HWND *WIN_ListParents( HWND hwnd )
2622 WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
2623 HWND *list = NULL;
2624 UINT i, count = 0;
2626 /* First count the windows */
2628 if (!wndPtr) return NULL;
2630 parent = wndPtr->parent;
2631 while (parent && parent->hwndSelf != GetDesktopWindow())
2633 count++;
2634 parent = parent->parent;
2637 if (count)
2639 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
2641 parent = wndPtr->parent;
2642 for (i = 0; i < count; i++)
2644 list[i] = parent->hwndSelf;
2645 parent = parent->parent;
2647 list[i] = 0;
2651 WIN_ReleaseWndPtr( wndPtr );
2652 return list;
2656 /*******************************************************************
2657 * WIN_ListChildren
2659 * Build an array of the children of a given window. The array must be
2660 * freed with HeapFree. Returns NULL when no windows are found.
2662 HWND *WIN_ListChildren( HWND hwnd )
2664 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2665 HWND *list, *phwnd;
2666 UINT count = 0;
2668 /* First count the windows */
2670 if (!wndPtr) return NULL;
2672 pWnd = WIN_LockWndPtr(wndPtr->child);
2673 while (pWnd)
2675 count++;
2676 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2679 if( count )
2681 /* Now build the list of all windows */
2683 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2685 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2687 *phwnd++ = pWnd->hwndSelf;
2688 count++;
2690 WIN_ReleaseWndPtr(pWnd);
2691 *phwnd = 0;
2693 else count = 0;
2694 } else list = NULL;
2696 WIN_ReleaseWndPtr( wndPtr );
2697 return list;
2701 /*******************************************************************
2702 * EnumWindows (USER32.@)
2704 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2706 HWND *list;
2707 BOOL ret = TRUE;
2708 int i, iWndsLocks;
2710 /* We have to build a list of all windows first, to avoid */
2711 /* unpleasant side-effects, for instance if the callback */
2712 /* function changes the Z-order of the windows. */
2714 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2716 /* Now call the callback function for every window */
2718 iWndsLocks = WIN_SuspendWndsLock();
2719 for (i = 0; list[i]; i++)
2721 /* Make sure that the window still exists */
2722 if (!IsWindow( list[i] )) continue;
2723 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2725 WIN_RestoreWndsLock(iWndsLocks);
2726 HeapFree( GetProcessHeap(), 0, list );
2727 return ret;
2731 /**********************************************************************
2732 * EnumTaskWindows16 (USER.225)
2734 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2735 LPARAM lParam )
2737 TDB *tdb = TASK_GetPtr( hTask );
2738 if (!tdb) return FALSE;
2739 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2743 /**********************************************************************
2744 * EnumThreadWindows (USER32.@)
2746 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2748 HWND *list;
2749 int i, iWndsLocks;
2751 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2753 /* Now call the callback function for every window */
2755 iWndsLocks = WIN_SuspendWndsLock();
2756 for (i = 0; list[i]; i++)
2758 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2759 if (!func( list[i], lParam )) break;
2761 WIN_RestoreWndsLock(iWndsLocks);
2762 HeapFree( GetProcessHeap(), 0, list );
2763 return TRUE;
2767 /**********************************************************************
2768 * WIN_EnumChildWindows
2770 * Helper function for EnumChildWindows().
2772 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2774 HWND *childList;
2775 BOOL ret = FALSE;
2777 for ( ; *list; list++)
2779 /* Make sure that the window still exists */
2780 if (!IsWindow( *list )) continue;
2781 /* skip owned windows */
2782 if (GetWindow( *list, GW_OWNER )) continue;
2783 /* Build children list first */
2784 childList = WIN_ListChildren( *list );
2786 ret = func( *list, lParam );
2788 if (childList)
2790 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2791 HeapFree( GetProcessHeap(), 0, childList );
2793 if (!ret) return FALSE;
2795 return TRUE;
2799 /**********************************************************************
2800 * EnumChildWindows (USER32.@)
2802 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2804 HWND *list;
2805 int iWndsLocks;
2807 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2808 iWndsLocks = WIN_SuspendWndsLock();
2809 WIN_EnumChildWindows( list, func, lParam );
2810 WIN_RestoreWndsLock(iWndsLocks);
2811 HeapFree( GetProcessHeap(), 0, list );
2812 return TRUE;
2816 /*******************************************************************
2817 * AnyPopup (USER.52)
2819 BOOL16 WINAPI AnyPopup16(void)
2821 return AnyPopup();
2825 /*******************************************************************
2826 * AnyPopup (USER32.@)
2828 BOOL WINAPI AnyPopup(void)
2830 int i;
2831 BOOL retvalue;
2832 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2834 if (!list) return FALSE;
2835 for (i = 0; list[i]; i++)
2837 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2839 retvalue = (list[i] != 0);
2840 HeapFree( GetProcessHeap(), 0, list );
2841 return retvalue;
2845 /*******************************************************************
2846 * FlashWindow (USER.105)
2848 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2850 return FlashWindow( hWnd, bInvert );
2854 /*******************************************************************
2855 * FlashWindow (USER32.@)
2857 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2859 WND *wndPtr = WIN_FindWndPtr(hWnd);
2861 TRACE("%04x\n", hWnd);
2863 if (!wndPtr) return FALSE;
2865 if (wndPtr->dwStyle & WS_MINIMIZE)
2867 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2869 HDC hDC = GetDC(hWnd);
2871 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2872 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2874 ReleaseDC( hWnd, hDC );
2875 wndPtr->flags |= WIN_NCACTIVATED;
2877 else
2879 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2880 wndPtr->flags &= ~WIN_NCACTIVATED;
2882 WIN_ReleaseWndPtr(wndPtr);
2883 return TRUE;
2885 else
2887 WPARAM16 wparam;
2888 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2889 else wparam = (hWnd == GetActiveWindow());
2891 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2892 WIN_ReleaseWndPtr(wndPtr);
2893 return wparam;
2898 /*******************************************************************
2899 * SetSysModalWindow (USER.188)
2901 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2903 HWND hWndOldModal = hwndSysModal;
2904 hwndSysModal = hWnd;
2905 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2906 return hWndOldModal;
2910 /*******************************************************************
2911 * GetSysModalWindow (USER.189)
2913 HWND16 WINAPI GetSysModalWindow16(void)
2915 return hwndSysModal;
2919 /*******************************************************************
2920 * GetWindowContextHelpId (USER32.@)
2922 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2924 DWORD retval;
2925 WND *wnd = WIN_FindWndPtr( hwnd );
2926 if (!wnd) return 0;
2927 retval = wnd->helpContext;
2928 WIN_ReleaseWndPtr(wnd);
2929 return retval;
2933 /*******************************************************************
2934 * SetWindowContextHelpId (USER32.@)
2936 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2938 WND *wnd = WIN_FindWndPtr( hwnd );
2939 if (!wnd) return FALSE;
2940 wnd->helpContext = id;
2941 WIN_ReleaseWndPtr(wnd);
2942 return TRUE;
2946 /*******************************************************************
2947 * DRAG_QueryUpdate
2949 * recursively find a child that contains spDragInfo->pt point
2950 * and send WM_QUERYDROPOBJECT
2952 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2954 BOOL16 wParam, bResult = 0;
2955 POINT pt;
2956 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2957 RECT tempRect;
2959 if (!ptrDragInfo) return FALSE;
2961 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2963 GetWindowRect(hQueryWnd,&tempRect);
2965 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2967 if (!IsIconic( hQueryWnd ))
2969 GetClientRect( hQueryWnd, &tempRect );
2970 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2972 if (PtInRect( &tempRect, pt))
2974 int i;
2975 HWND *list = WIN_ListChildren( hQueryWnd );
2977 wParam = 0;
2979 if (list)
2981 for (i = 0; list[i]; i++)
2983 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2985 GetWindowRect( list[i], &tempRect );
2986 if (PtInRect( &tempRect, pt )) break;
2989 if (list[i])
2991 if (IsWindowEnabled( list[i] ))
2992 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2994 HeapFree( GetProcessHeap(), 0, list );
2996 if(bResult) return bResult;
2998 else wParam = 1;
3000 else wParam = 1;
3002 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3004 ptrDragInfo->hScope = hQueryWnd;
3006 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3007 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3009 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3011 return bResult;
3015 /*******************************************************************
3016 * DragDetect (USER.465)
3018 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3020 POINT pt32;
3021 CONV_POINT16TO32( &pt, &pt32 );
3022 return DragDetect( hWnd, pt32 );
3025 /*******************************************************************
3026 * DragDetect (USER32.@)
3028 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3030 MSG msg;
3031 RECT rect;
3033 rect.left = pt.x - wDragWidth;
3034 rect.right = pt.x + wDragWidth;
3036 rect.top = pt.y - wDragHeight;
3037 rect.bottom = pt.y + wDragHeight;
3039 SetCapture(hWnd);
3041 while(1)
3043 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3045 if( msg.message == WM_LBUTTONUP )
3047 ReleaseCapture();
3048 return 0;
3050 if( msg.message == WM_MOUSEMOVE )
3052 POINT tmp;
3053 tmp.x = LOWORD(msg.lParam);
3054 tmp.y = HIWORD(msg.lParam);
3055 if( !PtInRect( &rect, tmp ))
3057 ReleaseCapture();
3058 return 1;
3062 WaitMessage();
3064 return 0;
3067 /******************************************************************************
3068 * DragObject (USER.464)
3070 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3071 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3073 MSG msg;
3074 LPDRAGINFO16 lpDragInfo;
3075 SEGPTR spDragInfo;
3076 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3077 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3078 HCURSOR16 hCurrentCursor = 0;
3079 HWND16 hCurrentWnd = 0;
3081 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3082 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3084 if( !lpDragInfo || !spDragInfo ) return 0L;
3086 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3088 GlobalFree16(hDragInfo);
3089 return 0L;
3092 if(hCursor)
3094 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3096 GlobalFree16(hDragInfo);
3097 return 0L;
3100 if( hDragCursor == hCursor ) hDragCursor = 0;
3101 else hCursor = hDragCursor;
3103 hOldCursor = SetCursor(hDragCursor);
3106 lpDragInfo->hWnd = hWnd;
3107 lpDragInfo->hScope = 0;
3108 lpDragInfo->wFlags = wObj;
3109 lpDragInfo->hList = szList; /* near pointer! */
3110 lpDragInfo->hOfStruct = hOfStruct;
3111 lpDragInfo->l = 0L;
3113 SetCapture(hWnd);
3114 ShowCursor( TRUE );
3118 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3120 *(lpDragInfo+1) = *lpDragInfo;
3122 lpDragInfo->pt.x = msg.pt.x;
3123 lpDragInfo->pt.y = msg.pt.y;
3125 /* update DRAGINFO struct */
3126 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3128 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3129 hCurrentCursor = hCursor;
3130 else
3132 hCurrentCursor = hBummer;
3133 lpDragInfo->hScope = 0;
3135 if( hCurrentCursor )
3136 SetCursor(hCurrentCursor);
3138 /* send WM_DRAGLOOP */
3139 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3140 (LPARAM) spDragInfo );
3141 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3142 if( hCurrentWnd != lpDragInfo->hScope )
3144 if( hCurrentWnd )
3145 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3146 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3147 HIWORD(spDragInfo)) );
3148 hCurrentWnd = lpDragInfo->hScope;
3149 if( hCurrentWnd )
3150 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3152 else
3153 if( hCurrentWnd )
3154 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3156 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3158 ReleaseCapture();
3159 ShowCursor( FALSE );
3161 if( hCursor )
3163 SetCursor( hOldCursor );
3164 if (hDragCursor) DestroyCursor( hDragCursor );
3167 if( hCurrentCursor != hBummer )
3168 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3169 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3170 else
3171 msg.lParam = 0;
3172 GlobalFree16(hDragInfo);
3174 return (DWORD)(msg.lParam);
3178 /******************************************************************************
3179 * GetWindowModuleFileNameA (USER32.@)
3181 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3183 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3184 hwnd, lpszFileName, cchFileNameMax);
3185 return 0;
3188 /******************************************************************************
3189 * GetWindowModuleFileNameW (USER32.@)
3191 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3193 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3194 hwnd, lpszFileName, cchFileNameMax);
3195 return 0;