Removed the chop command that was there to get rid of dos ^M.
[wine/dcerpc.git] / windows / win.c
blob529bb6d09bc880e1f46751416f5b3ef79a901e71
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <string.h>
11 #include "wine/winbase16.h"
12 #include "options.h"
13 #include "class.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "nonclient.h"
24 #include "queue.h"
25 #include "winpos.h"
26 #include "shm_main_blk.h"
27 #include "dde_proc.h"
28 #include "clipboard.h"
29 #include "winproc.h"
30 #include "task.h"
31 #include "thread.h"
32 #include "process.h"
33 #include "debug.h"
34 #include "winerror.h"
35 #include "mdi.h"
36 #include "local.h"
37 #include "desktop.h"
39 #ifndef X_DISPLAY_MISSING
40 extern DESKTOP_DRIVER X11DRV_DESKTOP_Driver;
41 extern WND_DRIVER X11DRV_WND_Driver;
42 #else /* X_DISPLAY_MISSING */
43 extern DESKTOP_DRIVER TTYDRV_DESKTOP_Driver;
44 extern WND_DRIVER TTYDRV_WND_Driver;
45 #endif /* X_DISPLAY_MISSING */
47 /* Desktop window */
48 static WND *pWndDesktop = NULL;
50 static HWND hwndSysModal = 0;
52 static WORD wDragWidth = 4;
53 static WORD wDragHeight= 3;
55 /* thread safeness */
56 static CRITICAL_SECTION WIN_CritSection;
57 static int ilockCounter = 0;
59 /***********************************************************************
60 * WIN_LockWnds
62 * Locks access to all WND structures for thread safeness
64 void WIN_LockWnds()
67 EnterCriticalSection(&WIN_CritSection);
71 /***********************************************************************
72 * WIN_UnlockWnds
74 * Unlocks access to all WND structures
76 void WIN_UnlockWnds()
79 LeaveCriticalSection(&WIN_CritSection);
82 /***********************************************************************
83 * WIN_SuspendWndsLock
85 * Suspend the lock on WND structures.
86 * Returns the number of locks suspended
88 int WIN_SuspendWndsLock()
91 int isuspendedLocks = WIN_CritSection.RecursionCount;
92 WIN_CritSection.RecursionCount = 0;
93 LeaveCriticalSection(&WIN_CritSection);
94 return isuspendedLocks;
98 /***********************************************************************
99 * WIN_RestoreWndsLock
101 * Restore the suspended locks on WND structures
103 void WIN_RestoreWndslock(int ipreviousLocks)
106 EnterCriticalSection(&WIN_CritSection);
107 WIN_CritSection.RecursionCount = ipreviousLocks;
110 /***********************************************************************
111 * WIN_FindWndPtr
113 * Return a pointer to the WND structure corresponding to a HWND.
115 WND * WIN_FindWndPtr( HWND hwnd )
117 WND * ptr;
119 if (!hwnd || HIWORD(hwnd)) goto error2;
120 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
121 /* Lock all WND structures for thread safeness
122 WIN_LockWnds(ptr);
123 and increment destruction monitoring
124 ptr->irefCount++;
126 if (ptr->dwMagic != WND_MAGIC) goto error;
127 if (ptr->hwndSelf != hwnd)
129 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
130 hwnd, ptr->hwndSelf );
131 goto error;
133 return ptr;
134 error:
135 /* Unlock all WND structures for thread safeness
136 WIN_UnlockWnds(ptr);
137 and decrement destruction monitoring value
138 ptr->irefCount--;
140 error2:
141 if ( hwnd!=0 )
142 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
143 return NULL;
146 /***********************************************************************
147 * WIN_LockWndPtr
149 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
150 * but by initWndPtr;
151 * Returns the locked initialisation pointer
153 WND *WIN_LockWndPtr(WND *initWndPtr)
156 if(!initWndPtr) return 0;
158 WIN_LockWnds();
159 initWndPtr->irefCount++;
161 return initWndPtr;
165 /***********************************************************************
166 * WIN_ReleaseWndPtr
168 * Release the pointer to the WND structure.
170 void WIN_ReleaseWndPtr(WND *wndPtr)
173 if(!wndPtr) return;
174 /*Decrement destruction monitoring value
175 wndPtr->irefCount--;
176 Check if it's time to release the memory
177 if(wndPtr->irefCount == 0)
179 Add memory releasing code here
181 unlock all WND structures for thread safeness
182 WIN_UnlockWnds();
186 /***********************************************************************
187 * WIN_ReleaseWndPtr
189 * Updates the value of oldPtr to newPtr.
191 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
193 WND *tmpWnd = NULL;
195 tmpWnd = WIN_LockWndPtr(newPtr);
196 WIN_ReleaseWndPtr(*oldPtr);
197 *oldPtr = tmpWnd;
201 /***********************************************************************
202 * WIN_DumpWindow
204 * Dump the content of a window structure to stderr.
206 void WIN_DumpWindow( HWND hwnd )
208 WND *ptr;
209 char className[80];
210 int i;
212 if (!(ptr = WIN_FindWndPtr( hwnd )))
214 WARN( win, "%04x is not a window handle\n", hwnd );
215 return;
218 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
219 strcpy( className, "#NULL#" );
221 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
222 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
223 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
224 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
225 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
226 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
227 ptr->next, ptr->child, ptr->parent, ptr->owner,
228 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
229 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
230 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
231 ptr->text ? ptr->text : "",
232 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
233 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
234 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
235 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
237 if (ptr->class->cbWndExtra)
239 DUMP( "extra bytes:" );
240 for (i = 0; i < ptr->class->cbWndExtra; i++)
241 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
242 DUMP( "\n" );
244 DUMP( "\n" );
245 WIN_ReleaseWndPtr(ptr);
249 /***********************************************************************
250 * WIN_WalkWindows
252 * Walk the windows tree and print each window on stderr.
254 void WIN_WalkWindows( HWND hwnd, int indent )
256 WND *ptr;
257 char className[80];
259 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
261 if (!ptr)
263 WARN( win, "Invalid window handle %04x\n", hwnd );
264 return;
267 if (!indent) /* first time around */
268 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
269 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
270 " Text");
272 while (ptr)
274 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
276 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
278 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
279 (DWORD)ptr, ptr->hmemTaskQ, className,
280 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
281 ptr->text?ptr->text:"<null>");
283 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
284 WIN_UpdateWndPtr(&ptr,ptr->next);
290 /***********************************************************************
291 * WIN_UnlinkWindow
293 * Remove a window from the siblings linked list.
295 BOOL WIN_UnlinkWindow( HWND hwnd )
297 WND *wndPtr, **ppWnd;
299 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
300 else if(!wndPtr->parent)
302 WIN_ReleaseWndPtr(wndPtr);
303 return FALSE;
305 ppWnd = &wndPtr->parent->child;
306 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
307 *ppWnd = wndPtr->next;
308 WIN_ReleaseWndPtr(wndPtr);
309 return TRUE;
313 /***********************************************************************
314 * WIN_LinkWindow
316 * Insert a window into the siblings linked list.
317 * The window is inserted after the specified window, which can also
318 * be specified as HWND_TOP or HWND_BOTTOM.
320 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
322 WND *wndPtr, **ppWnd;
324 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
325 else if(!wndPtr->parent)
327 WIN_ReleaseWndPtr(wndPtr);
328 return FALSE;
330 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
332 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
333 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
334 while (*ppWnd) ppWnd = &(*ppWnd)->next;
336 else /* Normal case */
338 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
339 if (!afterPtr)
341 WIN_ReleaseWndPtr(wndPtr);
342 return FALSE;
344 ppWnd = &afterPtr->next;
345 WIN_ReleaseWndPtr(afterPtr);
347 wndPtr->next = *ppWnd;
348 *ppWnd = wndPtr;
349 WIN_ReleaseWndPtr(wndPtr);
350 return TRUE;
354 /***********************************************************************
355 * WIN_FindWinToRepaint
357 * Find a window that needs repaint.
359 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
361 HWND hwndRet;
362 WND *pWnd;
364 /* Note: the desktop window never gets WM_PAINT messages
365 * The real reason why is because Windows DesktopWndProc
366 * does ValidateRgn inside WM_ERASEBKGND handler.
369 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
371 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
373 if (!(pWnd->dwStyle & WS_VISIBLE))
375 TRACE(win, "skipping window %04x\n",
376 pWnd->hwndSelf );
378 else if ((pWnd->hmemTaskQ == hQueue) &&
379 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
381 else if (pWnd->child )
382 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
383 goto end;
386 if(!pWnd)
388 hwndRet = 0;
389 goto end;
392 hwndRet = pWnd->hwndSelf;
394 /* look among siblings if we got a transparent window */
395 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
396 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
398 WIN_UpdateWndPtr(&pWnd,pWnd->next);
400 if (pWnd) hwndRet = pWnd->hwndSelf;
401 TRACE(win,"found %04x\n",hwndRet);
402 end:
403 WIN_ReleaseWndPtr(pWnd);
404 return hwndRet;
408 /***********************************************************************
409 * WIN_DestroyWindow
411 * Destroy storage associated to a window. "Internals" p.358
412 * returns a locked wndPtr->next
414 static WND* WIN_DestroyWindow( WND* wndPtr )
416 HWND hwnd = wndPtr->hwndSelf;
417 WND *pWnd;
419 TRACE(win, "%04x\n", wndPtr->hwndSelf );
421 #ifdef CONFIG_IPC
422 if (main_block)
423 DDE_DestroyWindow(wndPtr->hwndSelf);
424 #endif /* CONFIG_IPC */
426 /* free child windows */
427 WIN_LockWndPtr(wndPtr->child);
428 while ((pWnd = wndPtr->child))
430 wndPtr->child = WIN_DestroyWindow( pWnd );
431 WIN_ReleaseWndPtr(pWnd);
434 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
436 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
438 WINPOS_CheckInternalPos( wndPtr );
439 if( hwnd == GetCapture()) ReleaseCapture();
441 /* free resources associated with the window */
443 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
444 PROPERTY_RemoveWindowProps( wndPtr );
446 wndPtr->dwMagic = 0; /* Mark it as invalid */
448 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
450 if (wndPtr->hrgnUpdate > 1) DeleteObject( wndPtr->hrgnUpdate );
451 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
454 /* toss stale messages from the queue */
456 if( wndPtr->hmemTaskQ )
458 BOOL bPostQuit = FALSE;
459 WPARAM wQuitParam = 0;
460 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
461 QMSG *qmsg;
463 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
465 if( qmsg->msg.message == WM_QUIT )
467 bPostQuit = TRUE;
468 wQuitParam = qmsg->msg.wParam;
470 QUEUE_RemoveMsg(msgQ, qmsg);
473 QUEUE_Unlock(msgQ);
475 /* repost WM_QUIT to make sure this app exits its message loop */
476 if( bPostQuit ) PostQuitMessage(wQuitParam);
477 wndPtr->hmemTaskQ = 0;
480 if (!(wndPtr->dwStyle & WS_CHILD))
481 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
482 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
483 wndPtr->pDriver->pDestroyWindow( wndPtr );
484 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
485 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
486 wndPtr->hwndSelf = 0;
487 wndPtr->class->cWindows--;
488 wndPtr->class = NULL;
490 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
492 wndPtr->pDriver->pFinalize(wndPtr);
493 USER_HEAP_FREE( hwnd );
494 return pWnd;
497 /***********************************************************************
498 * WIN_ResetQueueWindows
500 * Reset the queue of all the children of a given window.
501 * Return TRUE if something was done.
503 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
505 BOOL ret = FALSE;
507 if (hNew) /* Set a new queue */
509 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
511 if (wnd->hmemTaskQ == hQueue)
513 wnd->hmemTaskQ = hNew;
514 ret = TRUE;
516 if (wnd->child)
518 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
522 else /* Queue is being destroyed */
524 while (wnd->child)
526 WND *tmp = WIN_LockWndPtr(wnd->child);
527 WND *tmp2;
528 ret = FALSE;
529 while (tmp)
531 if (tmp->hmemTaskQ == hQueue)
533 DestroyWindow( tmp->hwndSelf );
534 ret = TRUE;
535 break;
537 tmp2 = WIN_LockWndPtr(tmp->child);
538 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
539 ret = TRUE;
540 else
542 WIN_UpdateWndPtr(&tmp,tmp->next);
544 WIN_ReleaseWndPtr(tmp2);
546 WIN_ReleaseWndPtr(tmp);
547 if (!ret) break;
550 return ret;
553 /***********************************************************************
554 * WIN_CreateDesktopWindow
556 * Create the desktop window.
558 BOOL WIN_CreateDesktopWindow(void)
560 CLASS *class;
561 HWND hwndDesktop;
562 DESKTOP *pDesktop;
564 TRACE(win,"Creating desktop window\n");
566 if (!ICONTITLE_Init() ||
567 !WINPOS_CreateInternalPosAtom() ||
568 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
569 return FALSE;
571 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
572 if (!hwndDesktop) return FALSE;
573 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
575 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
576 #ifndef X_DISPLAY_MISSING
577 pDesktop->pDriver = &X11DRV_DESKTOP_Driver;
578 pWndDesktop->pDriver = &X11DRV_WND_Driver;
579 #else /* X_DISPLAY_MISSING */
580 pDesktop->pDriver = &TTYDRV_DESKTOP_Driver;
581 pWndDesktop->pDriver = &TTYDRV_WND_Driver;
582 #endif /* X_DISPLAY_MISSING */
584 pDesktop->pDriver->pInitialize(pDesktop);
585 pWndDesktop->pDriver->pInitialize(pWndDesktop);
587 pWndDesktop->next = NULL;
588 pWndDesktop->child = NULL;
589 pWndDesktop->parent = NULL;
590 pWndDesktop->owner = NULL;
591 pWndDesktop->class = class;
592 pWndDesktop->dwMagic = WND_MAGIC;
593 pWndDesktop->hwndSelf = hwndDesktop;
594 pWndDesktop->hInstance = 0;
595 pWndDesktop->rectWindow.left = 0;
596 pWndDesktop->rectWindow.top = 0;
597 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
598 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
599 pWndDesktop->rectClient = pWndDesktop->rectWindow;
600 pWndDesktop->text = NULL;
601 pWndDesktop->hmemTaskQ = GetFastQueue16();
602 pWndDesktop->hrgnUpdate = 0;
603 pWndDesktop->hwndLastActive = hwndDesktop;
604 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
605 WS_CLIPSIBLINGS;
606 pWndDesktop->dwExStyle = 0;
607 pWndDesktop->dce = NULL;
608 pWndDesktop->pVScroll = NULL;
609 pWndDesktop->pHScroll = NULL;
610 pWndDesktop->pProp = NULL;
611 pWndDesktop->wIDmenu = 0;
612 pWndDesktop->helpContext = 0;
613 pWndDesktop->flags = 0;
614 pWndDesktop->hSysMenu = 0;
615 pWndDesktop->userdata = 0;
616 pWndDesktop->winproc = (WNDPROC16)class->winproc;
617 pWndDesktop->irefCount = 0;
619 /* FIXME: How do we know if it should be Unicode or not */
620 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
621 return FALSE;
623 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
625 /* Initialisation of the critical section for thread safeness
626 InitializeCriticalSection(&WIN_CritSection);
627 MakeCriticalSectionGlobal(&WIN_CritSection);
629 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
630 return TRUE;
634 /***********************************************************************
635 * WIN_CreateWindowEx
637 * Implementation of CreateWindowEx().
639 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
640 BOOL win32, BOOL unicode )
642 CLASS *classPtr;
643 WND *wndPtr;
644 HWND retvalue;
645 HWND16 hwnd, hwndLinkAfter;
646 POINT maxSize, maxPos, minTrack, maxTrack;
647 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
649 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
650 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
651 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
652 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
653 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
655 /* Find the parent window */
657 if (cs->hwndParent)
659 /* Make sure parent is valid */
660 if (!IsWindow( cs->hwndParent ))
662 WARN( win, "Bad parent %04x\n", cs->hwndParent );
663 return 0;
665 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
666 WARN( win, "No parent for child window\n" );
667 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
670 /* Find the window class */
671 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
673 char buffer[256];
674 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
675 WARN( win, "Bad class '%s'\n", buffer );
676 return 0;
679 /* Fix the coordinates */
681 if (cs->x == CW_USEDEFAULT)
683 PDB *pdb = PROCESS_Current();
684 if ( !(cs->style & (WS_CHILD | WS_POPUP))
685 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
687 cs->x = pdb->env_db->startup_info->dwX;
688 cs->y = pdb->env_db->startup_info->dwY;
690 else
692 cs->x = 0;
693 cs->y = 0;
696 if (cs->cx == CW_USEDEFAULT)
698 PDB *pdb = PROCESS_Current();
699 if ( !(cs->style & (WS_CHILD | WS_POPUP))
700 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
702 cs->cx = pdb->env_db->startup_info->dwXSize;
703 cs->cy = pdb->env_db->startup_info->dwYSize;
705 else
707 cs->cx = 600; /* FIXME */
708 cs->cy = 400;
712 /* Create the window structure */
714 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
715 - sizeof(wndPtr->wExtra) )))
717 TRACE(win, "out of memory\n" );
718 return 0;
721 /* Fill the window structure */
723 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
724 wndPtr->next = NULL;
725 wndPtr->child = NULL;
727 if ((cs->style & WS_CHILD) && cs->hwndParent)
729 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
730 wndPtr->owner = NULL;
731 WIN_ReleaseWndPtr(wndPtr->parent);
733 else
735 wndPtr->parent = pWndDesktop;
736 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
737 wndPtr->owner = NULL;
738 else
740 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
741 WIN_ReleaseWndPtr(wndPtr->owner);
745 wndPtr->pDriver = wndPtr->parent->pDriver;
746 wndPtr->pDriver->pInitialize(wndPtr);
748 wndPtr->class = classPtr;
749 wndPtr->winproc = classPtr->winproc;
750 wndPtr->dwMagic = WND_MAGIC;
751 wndPtr->hwndSelf = hwnd;
752 wndPtr->hInstance = cs->hInstance;
753 wndPtr->text = NULL;
754 wndPtr->hmemTaskQ = GetFastQueue16();
755 wndPtr->hrgnUpdate = 0;
756 wndPtr->hwndLastActive = hwnd;
757 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
758 wndPtr->dwExStyle = cs->dwExStyle;
759 wndPtr->wIDmenu = 0;
760 wndPtr->helpContext = 0;
761 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
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;
769 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
771 /* Call the WH_CBT hook */
773 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
774 ? HWND_BOTTOM : HWND_TOP;
776 if (HOOK_IsHooked( WH_CBT ))
778 CBT_CREATEWNDA cbtc;
779 LRESULT ret;
781 cbtc.lpcs = cs;
782 cbtc.hwndInsertAfter = hwndLinkAfter;
783 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
784 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
785 if (ret)
787 TRACE(win, "CBT-hook returned 0\n");
788 wndPtr->pDriver->pFinalize(wndPtr);
789 USER_HEAP_FREE( hwnd );
790 retvalue = 0;
791 goto end;
795 /* Increment class window counter */
797 classPtr->cWindows++;
799 /* Correct the window style */
801 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
803 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
804 wndPtr->flags |= WIN_NEED_SIZE;
806 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
808 /* Get class or window DC if needed */
810 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
811 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
812 else wndPtr->dce = NULL;
814 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
816 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
818 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
819 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
820 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
821 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
822 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
825 if(cs->style & WS_CHILD)
827 if(cs->cx < 0) cs->cx = 0;
828 if(cs->cy < 0) cs->cy = 0;
830 else
832 if (cs->cx <= 0) cs->cx = 1;
833 if (cs->cy <= 0) cs->cy = 1;
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 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
844 retvalue = FALSE;
845 goto end;
848 /* Set the window menu */
850 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
852 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
853 else
855 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
856 if (classPtr->menuNameA)
857 cs->hMenu = HIWORD(classPtr->menuNameA) ?
858 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
859 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
860 #else
861 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
862 if (menuName)
864 if (HIWORD(cs->hInstance))
865 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
866 else
867 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
869 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
871 #endif
874 else wndPtr->wIDmenu = (UINT)cs->hMenu;
876 /* Send the WM_CREATE message
877 * Perhaps we shouldn't allow width/height changes as well.
878 * See p327 in "Internals".
881 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
883 localSend32 = unicode ? SendMessageW : SendMessageA;
884 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
886 /* Insert the window in the linked list */
888 WIN_LinkWindow( hwnd, hwndLinkAfter );
890 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
891 NULL, NULL, 0, &wndPtr->rectClient );
892 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
893 maxPos.y - wndPtr->rectWindow.top);
894 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
896 /* Send the size messages */
898 if (!(wndPtr->flags & WIN_NEED_SIZE))
900 /* send it anyway */
901 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
902 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
903 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
904 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
905 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
906 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
907 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
908 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
909 SendMessageA( hwnd, WM_MOVE, 0,
910 MAKELONG( wndPtr->rectClient.left,
911 wndPtr->rectClient.top ) );
914 /* Show the window, maximizing or minimizing if needed */
916 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
918 RECT16 newPos;
919 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
920 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
921 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
922 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
923 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
924 : SWP_NOZORDER | SWP_FRAMECHANGED;
925 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
926 newPos.right, newPos.bottom, swFlag );
929 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
931 /* Notify the parent window only */
933 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
934 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
935 if( !IsWindow(hwnd) )
937 retvalue = 0;
938 goto end;
942 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
944 /* Call WH_SHELL hook */
946 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
947 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
949 TRACE(win, "created window %04x\n", hwnd);
950 retvalue = hwnd;
951 goto end;
953 WIN_UnlinkWindow( hwnd );
956 /* Abort window creation */
958 WARN(win, "aborted by WM_xxCREATE!\n");
959 WIN_DestroyWindow( wndPtr );
960 retvalue = 0;
961 end:
962 WIN_ReleaseWndPtr(wndPtr);
963 return retvalue;
967 /***********************************************************************
968 * CreateWindow16 (USER.41)
970 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
971 DWORD style, INT16 x, INT16 y, INT16 width,
972 INT16 height, HWND16 parent, HMENU16 menu,
973 HINSTANCE16 instance, LPVOID data )
975 return CreateWindowEx16( 0, className, windowName, style,
976 x, y, width, height, parent, menu, instance, data );
980 /***********************************************************************
981 * CreateWindowEx16 (USER.452)
983 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
984 LPCSTR windowName, DWORD style, INT16 x,
985 INT16 y, INT16 width, INT16 height,
986 HWND16 parent, HMENU16 menu,
987 HINSTANCE16 instance, LPVOID data )
989 ATOM classAtom;
990 CREATESTRUCTA cs;
992 /* Find the class atom */
994 if (!(classAtom = GlobalFindAtomA( className )))
996 fprintf( stderr, "CreateWindowEx16: bad class name " );
997 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
998 else fprintf( stderr, "'%s'\n", className );
999 return 0;
1002 /* Fix the coordinates */
1004 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1005 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1006 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1007 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1009 /* Create the window */
1011 cs.lpCreateParams = data;
1012 cs.hInstance = (HINSTANCE)instance;
1013 cs.hMenu = (HMENU)menu;
1014 cs.hwndParent = (HWND)parent;
1015 cs.style = style;
1016 cs.lpszName = windowName;
1017 cs.lpszClass = className;
1018 cs.dwExStyle = exStyle;
1019 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1023 /***********************************************************************
1024 * CreateWindowEx32A (USER32.83)
1026 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1027 LPCSTR windowName, DWORD style, INT x,
1028 INT y, INT width, INT height,
1029 HWND parent, HMENU menu,
1030 HINSTANCE instance, LPVOID data )
1032 ATOM classAtom;
1033 CREATESTRUCTA cs;
1035 if(exStyle & WS_EX_MDICHILD)
1036 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1037 /* Find the class atom */
1039 if (!(classAtom = GlobalFindAtomA( className )))
1041 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1042 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1043 else fprintf( stderr, "'%s'\n", className );
1044 return 0;
1047 /* Create the window */
1049 cs.lpCreateParams = data;
1050 cs.hInstance = instance;
1051 cs.hMenu = menu;
1052 cs.hwndParent = parent;
1053 cs.x = x;
1054 cs.y = y;
1055 cs.cx = width;
1056 cs.cy = height;
1057 cs.style = style;
1058 cs.lpszName = windowName;
1059 cs.lpszClass = className;
1060 cs.dwExStyle = exStyle;
1061 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1065 /***********************************************************************
1066 * CreateWindowEx32W (USER32.84)
1068 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1069 LPCWSTR windowName, DWORD style, INT x,
1070 INT y, INT width, INT height,
1071 HWND parent, HMENU menu,
1072 HINSTANCE instance, LPVOID data )
1074 ATOM classAtom;
1075 CREATESTRUCTW cs;
1077 if(exStyle & WS_EX_MDICHILD)
1078 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1080 /* Find the class atom */
1082 if (!(classAtom = GlobalFindAtomW( className )))
1084 if (HIWORD(className))
1086 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1087 WARN( win, "Bad class name '%s'\n",cn);
1088 HeapFree( GetProcessHeap(), 0, cn );
1090 else
1091 WARN( win, "Bad class name %p\n", className );
1092 return 0;
1095 /* Create the window */
1097 cs.lpCreateParams = data;
1098 cs.hInstance = instance;
1099 cs.hMenu = menu;
1100 cs.hwndParent = parent;
1101 cs.x = x;
1102 cs.y = y;
1103 cs.cx = width;
1104 cs.cy = height;
1105 cs.style = style;
1106 cs.lpszName = windowName;
1107 cs.lpszClass = className;
1108 cs.dwExStyle = exStyle;
1109 /* Note: we rely on the fact that CREATESTRUCT32A and */
1110 /* CREATESTRUCT32W have the same layout. */
1111 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1115 /***********************************************************************
1116 * WIN_CheckFocus
1118 static void WIN_CheckFocus( WND* pWnd )
1120 if( GetFocus16() == pWnd->hwndSelf )
1121 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1124 /***********************************************************************
1125 * WIN_SendDestroyMsg
1127 static void WIN_SendDestroyMsg( WND* pWnd )
1129 WIN_CheckFocus(pWnd);
1131 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1132 CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
1135 * Send the WM_DESTROY to the window.
1137 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1140 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1141 * make sure that the window still exists when we come back.
1143 if (IsWindow(pWnd->hwndSelf))
1145 HWND* pWndArray = NULL;
1146 WND* pChild = NULL;
1147 int nKidCount = 0;
1150 * Now, if the window has kids, we have to send WM_DESTROY messages
1151 * recursively to it's kids. It seems that those calls can also
1152 * trigger re-entrant calls to DestroyWindow for the kids so we must
1153 * protect against corruption of the list of siblings. We first build
1154 * a list of HWNDs representing all the kids.
1156 pChild = WIN_LockWndPtr(pWnd->child);
1157 while( pChild )
1159 nKidCount++;
1160 WIN_UpdateWndPtr(&pChild,pChild->next);
1164 * If there are no kids, we're done.
1166 if (nKidCount==0)
1167 return;
1169 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1172 * Sanity check
1174 if (pWndArray==NULL)
1175 return;
1178 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1179 * call, our linked list of siblings should be safe.
1181 nKidCount = 0;
1182 pChild = WIN_LockWndPtr(pWnd->child);
1183 while( pChild )
1185 pWndArray[nKidCount] = pChild->hwndSelf;
1186 nKidCount++;
1187 WIN_UpdateWndPtr(&pChild,pChild->next);
1191 * Now that we have a list, go through that list again and send the destroy
1192 * message to those windows. We are using the HWND to retrieve the
1193 * WND pointer so we are effectively checking that all the kid windows are
1194 * still valid before sending the message.
1196 while (nKidCount>0)
1198 pChild = WIN_FindWndPtr(pWndArray[nKidCount]);
1200 if (pChild!=NULL)
1202 WIN_SendDestroyMsg( pChild );
1203 WIN_ReleaseWndPtr(pChild);
1206 nKidCount--;
1210 * Cleanup
1212 HeapFree(GetProcessHeap(), 0, pWndArray);
1213 WIN_CheckFocus(pWnd);
1215 else
1216 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1220 /***********************************************************************
1221 * DestroyWindow16 (USER.53)
1223 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1225 return DestroyWindow(hwnd);
1229 /***********************************************************************
1230 * DestroyWindow32 (USER32.135)
1232 BOOL WINAPI DestroyWindow( HWND hwnd )
1234 WND * wndPtr;
1235 BOOL retvalue;
1237 TRACE(win, "(%04x)\n", hwnd);
1239 /* Initialization */
1241 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1242 if (wndPtr == pWndDesktop)
1244 WIN_ReleaseWndPtr(wndPtr);
1245 return FALSE; /* Can't destroy desktop */
1248 /* Call hooks */
1250 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1252 retvalue = FALSE;
1253 goto end;
1256 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1258 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1259 /* FIXME: clean up palette - see "Internals" p.352 */
1262 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1263 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1265 /* Notify the parent window only */
1266 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1267 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1268 if( !IsWindow(hwnd) )
1270 retvalue = TRUE;
1271 goto end;
1275 CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1277 /* Hide the window */
1279 if (wndPtr->dwStyle & WS_VISIBLE)
1281 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1282 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1283 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1284 if (!IsWindow(hwnd))
1286 retvalue = TRUE;
1287 goto end;
1291 /* Recursively destroy owned windows */
1293 if( !(wndPtr->dwStyle & WS_CHILD) )
1295 /* make sure top menu popup doesn't get destroyed */
1296 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1298 for (;;)
1300 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1301 while (siblingPtr)
1303 if (siblingPtr->owner == wndPtr)
1305 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1306 break;
1307 else
1308 siblingPtr->owner = NULL;
1310 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1312 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1313 else break;
1316 if( !Options.managed || EVENT_CheckFocus() )
1317 WINPOS_ActivateOtherWindow(wndPtr);
1319 if( wndPtr->owner &&
1320 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1321 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1324 /* Send destroy messages */
1326 WIN_SendDestroyMsg( wndPtr );
1327 if (!IsWindow(hwnd))
1329 retvalue = TRUE;
1330 goto end;
1333 /* Unlink now so we won't bother with the children later on */
1335 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1337 /* Destroy the window storage */
1339 WIN_DestroyWindow( wndPtr );
1340 retvalue = TRUE;
1341 end:
1342 WIN_ReleaseWndPtr(wndPtr);
1343 return retvalue;
1347 /***********************************************************************
1348 * CloseWindow16 (USER.43)
1350 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1352 return CloseWindow( hwnd );
1356 /***********************************************************************
1357 * CloseWindow32 (USER32.56)
1359 BOOL WINAPI CloseWindow( HWND hwnd )
1361 WND * wndPtr = WIN_FindWndPtr( hwnd );
1362 BOOL retvalue;
1364 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1366 retvalue = FALSE;
1367 goto end;
1369 ShowWindow( hwnd, SW_MINIMIZE );
1370 retvalue = TRUE;
1371 end:
1372 WIN_ReleaseWndPtr(wndPtr);
1373 return retvalue;
1378 /***********************************************************************
1379 * OpenIcon16 (USER.44)
1381 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1383 return OpenIcon( hwnd );
1387 /***********************************************************************
1388 * OpenIcon32 (USER32.410)
1390 BOOL WINAPI OpenIcon( HWND hwnd )
1392 if (!IsIconic( hwnd )) return FALSE;
1393 ShowWindow( hwnd, SW_SHOWNORMAL );
1394 return TRUE;
1398 /***********************************************************************
1399 * WIN_FindWindow
1401 * Implementation of FindWindow() and FindWindowEx().
1403 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1404 LPCSTR title )
1406 WND *pWnd;
1407 HWND retvalue;
1408 CLASS *pClass = NULL;
1410 if (child)
1412 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1413 if (parent)
1415 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1417 retvalue = 0;
1418 goto end;
1421 else if (pWnd->parent != pWndDesktop)
1423 retvalue = 0;
1424 goto end;
1426 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1428 else
1430 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1432 retvalue = 0;
1433 goto end;
1435 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1437 if (!pWnd)
1439 retvalue = 0;
1440 goto end;
1443 /* For a child window, all siblings will have the same hInstance, */
1444 /* so we can look for the class once and for all. */
1446 if (className && (pWnd->dwStyle & WS_CHILD))
1448 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1450 retvalue = 0;
1451 goto end;
1456 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1458 if (className && !(pWnd->dwStyle & WS_CHILD))
1460 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1461 continue; /* Skip this window */
1464 if (pClass && (pWnd->class != pClass))
1465 continue; /* Not the right class */
1467 /* Now check the title */
1469 if (!title)
1471 retvalue = pWnd->hwndSelf;
1472 goto end;
1474 if (pWnd->text && !strcmp( pWnd->text, title ))
1476 retvalue = pWnd->hwndSelf;
1477 goto end;
1480 retvalue = 0;
1481 end:
1482 WIN_ReleaseWndPtr(pWnd);
1483 return retvalue;
1488 /***********************************************************************
1489 * FindWindow16 (USER.50)
1491 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1493 return FindWindowEx16( 0, 0, className, title );
1497 /***********************************************************************
1498 * FindWindowEx16 (USER.427)
1500 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1501 SEGPTR className, LPCSTR title )
1503 ATOM atom = 0;
1505 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1506 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1507 title ? title : "");
1509 if (className)
1511 /* If the atom doesn't exist, then no class */
1512 /* with this name exists either. */
1513 if (!(atom = GlobalFindAtom16( className ))) return 0;
1515 return WIN_FindWindow( parent, child, atom, title );
1519 /***********************************************************************
1520 * FindWindow32A (USER32.198)
1522 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1524 HWND ret = FindWindowExA( 0, 0, className, title );
1525 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1526 return ret;
1530 /***********************************************************************
1531 * FindWindowEx32A (USER32.199)
1533 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1534 LPCSTR className, LPCSTR title )
1536 ATOM atom = 0;
1538 if (className)
1540 /* If the atom doesn't exist, then no class */
1541 /* with this name exists either. */
1542 if (!(atom = GlobalFindAtomA( className )))
1544 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1545 return 0;
1548 return WIN_FindWindow( parent, child, atom, title );
1552 /***********************************************************************
1553 * FindWindowEx32W (USER32.200)
1555 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1556 LPCWSTR className, LPCWSTR title )
1558 ATOM atom = 0;
1559 char *buffer;
1560 HWND hwnd;
1562 if (className)
1564 /* If the atom doesn't exist, then no class */
1565 /* with this name exists either. */
1566 if (!(atom = GlobalFindAtomW( className )))
1568 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1569 return 0;
1572 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1573 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1574 HeapFree( GetProcessHeap(), 0, buffer );
1575 return hwnd;
1579 /***********************************************************************
1580 * FindWindow32W (USER32.201)
1582 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1584 return FindWindowExW( 0, 0, className, title );
1588 /**********************************************************************
1589 * WIN_GetDesktop
1590 * returns a locked pointer
1592 WND *WIN_GetDesktop(void)
1594 return WIN_LockWndPtr(pWndDesktop);
1596 /**********************************************************************
1597 * WIN_ReleaseDesktop
1598 * unlock the desktop pointer
1600 void WIN_ReleaseDesktop(void)
1602 WIN_ReleaseWndPtr(pWndDesktop);
1606 /**********************************************************************
1607 * GetDesktopWindow16 (USER.286)
1609 HWND16 WINAPI GetDesktopWindow16(void)
1611 return (HWND16)pWndDesktop->hwndSelf;
1615 /**********************************************************************
1616 * GetDesktopWindow32 (USER32.232)
1618 HWND WINAPI GetDesktopWindow(void)
1620 return pWndDesktop->hwndSelf;
1624 /**********************************************************************
1625 * GetDesktopHwnd (USER.278)
1627 * Exactly the same thing as GetDesktopWindow(), but not documented.
1628 * Don't ask me why...
1630 HWND16 WINAPI GetDesktopHwnd16(void)
1632 return (HWND16)pWndDesktop->hwndSelf;
1636 /*******************************************************************
1637 * EnableWindow16 (USER.34)
1639 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1641 return EnableWindow( hwnd, enable );
1645 /*******************************************************************
1646 * EnableWindow32 (USER32.172)
1648 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1650 WND *wndPtr;
1651 BOOL retvalue;
1653 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1655 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1656 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1658 /* Enable window */
1659 wndPtr->dwStyle &= ~WS_DISABLED;
1660 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1661 retvalue = TRUE;
1662 goto end;
1664 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1666 /* Disable window */
1667 wndPtr->dwStyle |= WS_DISABLED;
1668 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1670 SetFocus( 0 ); /* A disabled window can't have the focus */
1672 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1674 ReleaseCapture(); /* A disabled window can't capture the mouse */
1676 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1677 retvalue = FALSE;
1678 goto end;
1680 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1681 end:
1682 WIN_ReleaseWndPtr(wndPtr);
1683 return retvalue;
1687 /***********************************************************************
1688 * IsWindowEnabled16 (USER.35)
1690 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1692 return IsWindowEnabled(hWnd);
1696 /***********************************************************************
1697 * IsWindowEnabled32 (USER32.349)
1699 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1701 WND * wndPtr;
1702 BOOL retvalue;
1704 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1705 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1706 WIN_ReleaseWndPtr(wndPtr);
1707 return retvalue;
1712 /***********************************************************************
1713 * IsWindowUnicode (USER32.350)
1715 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1717 WND * wndPtr;
1718 BOOL retvalue;
1720 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1721 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1722 WIN_ReleaseWndPtr(wndPtr);
1723 return retvalue;
1727 /**********************************************************************
1728 * GetWindowWord16 (USER.133)
1730 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1732 return GetWindowWord( hwnd, offset );
1736 /**********************************************************************
1737 * GetWindowWord32 (USER32.314)
1739 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1741 WORD retvalue;
1742 WND * wndPtr = WIN_FindWndPtr( hwnd );
1743 if (!wndPtr) return 0;
1744 if (offset >= 0)
1746 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1748 WARN( win, "Invalid offset %d\n", offset );
1749 retvalue = 0;
1750 goto end;
1752 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1753 goto end;
1755 switch(offset)
1757 case GWW_ID:
1758 if (HIWORD(wndPtr->wIDmenu))
1759 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1760 wndPtr->wIDmenu);
1761 retvalue = (WORD)wndPtr->wIDmenu;
1762 goto end;
1763 case GWW_HWNDPARENT:
1764 retvalue = GetParent(hwnd);
1765 goto end;
1766 case GWW_HINSTANCE:
1767 if (HIWORD(wndPtr->hInstance))
1768 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1769 wndPtr->hInstance);
1770 retvalue = (WORD)wndPtr->hInstance;
1771 goto end;
1772 default:
1773 WARN( win, "Invalid offset %d\n", offset );
1774 retvalue = 0;
1775 goto end;
1777 end:
1778 WIN_ReleaseWndPtr(wndPtr);
1779 return retvalue;
1783 /**********************************************************************
1784 * WIN_GetWindowInstance
1786 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1789 WND * wndPtr = WIN_FindWndPtr( hwnd );
1790 if (!wndPtr) return (HINSTANCE)0;
1791 WIN_ReleaseWndPtr(wndPtr);
1792 return wndPtr->hInstance;
1797 /**********************************************************************
1798 * SetWindowWord16 (USER.134)
1800 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1802 return SetWindowWord( hwnd, offset, newval );
1806 /**********************************************************************
1807 * SetWindowWord32 (USER32.524)
1809 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1811 WORD *ptr, retval;
1812 WND * wndPtr = WIN_FindWndPtr( hwnd );
1813 if (!wndPtr) return 0;
1814 if (offset >= 0)
1816 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1818 WARN( win, "Invalid offset %d\n", offset );
1819 retval = 0;
1820 goto end;
1822 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1824 else switch(offset)
1826 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1827 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1828 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1829 goto end;
1830 default:
1831 WARN( win, "Invalid offset %d\n", offset );
1832 retval = 0;
1833 goto end;
1835 retval = *ptr;
1836 *ptr = newval;
1837 end:
1838 WIN_ReleaseWndPtr(wndPtr);
1839 return retval;
1843 /**********************************************************************
1844 * WIN_GetWindowLong
1846 * Helper function for GetWindowLong().
1848 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1850 LONG retvalue;
1851 WND * wndPtr = WIN_FindWndPtr( hwnd );
1852 if (!wndPtr) return 0;
1853 if (offset >= 0)
1855 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1857 WARN( win, "Invalid offset %d\n", offset );
1858 retvalue = 0;
1859 goto end;
1861 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1862 /* Special case for dialog window procedure */
1863 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1865 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1866 goto end;
1868 goto end;
1870 switch(offset)
1872 case GWL_USERDATA: retvalue = wndPtr->userdata;
1873 goto end;
1874 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1875 goto end;
1876 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1877 goto end;
1878 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1879 goto end;
1880 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1881 type );
1882 goto end;
1883 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1884 goto end;
1885 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1886 goto end;
1887 default:
1888 WARN( win, "Unknown offset %d\n", offset );
1890 retvalue = 0;
1891 end:
1892 WIN_ReleaseWndPtr(wndPtr);
1893 return retvalue;
1897 /**********************************************************************
1898 * WIN_SetWindowLong
1900 * Helper function for SetWindowLong().
1902 * 0 is the failure code. However, in the case of failure SetLastError
1903 * must be set to distinguish between a 0 return value and a failure.
1905 * FIXME: The error values for SetLastError may not be right. Can
1906 * someone check with the real thing?
1908 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1909 WINDOWPROCTYPE type )
1911 LONG *ptr, retval;
1912 WND * wndPtr = WIN_FindWndPtr( hwnd );
1913 STYLESTRUCT style;
1915 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1917 if (!wndPtr)
1919 /* Is this the right error? */
1920 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1921 return 0;
1924 if (offset >= 0)
1926 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1928 WARN( win, "Invalid offset %d\n", offset );
1930 /* Is this the right error? */
1931 SetLastError( ERROR_OUTOFMEMORY );
1933 retval = 0;
1934 goto end;
1936 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1937 /* Special case for dialog window procedure */
1938 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1940 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1941 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1942 type, WIN_PROC_WINDOW );
1943 goto end;
1946 else switch(offset)
1948 case GWL_ID:
1949 ptr = (DWORD*)&wndPtr->wIDmenu;
1950 break;
1951 case GWL_HINSTANCE:
1952 retval = SetWindowWord( hwnd, offset, newval );
1953 goto end;
1954 case GWL_WNDPROC:
1955 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1956 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1957 type, WIN_PROC_WINDOW );
1958 goto end;;
1959 case GWL_STYLE:
1960 style.styleOld = wndPtr->dwStyle;
1961 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1962 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1964 if (wndPtr->flags & WIN_ISWIN32)
1965 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1966 wndPtr->dwStyle = style.styleNew;
1967 if (wndPtr->flags & WIN_ISWIN32)
1968 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1969 retval = style.styleOld;
1970 goto end;
1972 case GWL_USERDATA:
1973 ptr = &wndPtr->userdata;
1974 break;
1975 case GWL_EXSTYLE:
1976 style.styleOld = wndPtr->dwExStyle;
1977 style.styleNew = newval;
1978 if (wndPtr->flags & WIN_ISWIN32)
1979 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1980 wndPtr->dwExStyle = newval;
1981 if (wndPtr->flags & WIN_ISWIN32)
1982 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1983 retval = style.styleOld;
1984 goto end;
1986 default:
1987 WARN( win, "Invalid offset %d\n", offset );
1989 /* Don't think this is right error but it should do */
1990 SetLastError( ERROR_OUTOFMEMORY );
1992 retval = 0;
1993 goto end;
1995 retval = *ptr;
1996 *ptr = newval;
1997 end:
1998 WIN_ReleaseWndPtr(wndPtr);
1999 return retval;
2003 /**********************************************************************
2004 * GetWindowLong16 (USER.135)
2006 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2008 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2012 /**********************************************************************
2013 * GetWindowLong32A (USER32.305)
2015 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2017 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2021 /**********************************************************************
2022 * GetWindowLong32W (USER32.306)
2024 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2026 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2030 /**********************************************************************
2031 * SetWindowLong16 (USER.136)
2033 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2035 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2039 /**********************************************************************
2040 * SetWindowLong32A (USER32.517)
2042 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2044 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2048 /**********************************************************************
2049 * SetWindowLong32W (USER32.518) Set window attribute
2051 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2052 * value in a window's extra memory.
2054 * The _hwnd_ parameter specifies the window. is the handle to a
2055 * window that has extra memory. The _newval_ parameter contains the
2056 * new attribute or extra memory value. If positive, the _offset_
2057 * parameter is the byte-addressed location in the window's extra
2058 * memory to set. If negative, _offset_ specifies the window
2059 * attribute to set, and should be one of the following values:
2061 * GWL_EXSTYLE The window's extended window style
2063 * GWL_STYLE The window's window style.
2065 * GWL_WNDPROC Pointer to the window's window procedure.
2067 * GWL_HINSTANCE The window's pplication instance handle.
2069 * GWL_ID The window's identifier.
2071 * GWL_USERDATA The window's user-specified data.
2073 * If the window is a dialog box, the _offset_ parameter can be one of
2074 * the following values:
2076 * DWL_DLGPROC The address of the window's dialog box procedure.
2078 * DWL_MSGRESULT The return value of a message
2079 * that the dialog box procedure processed.
2081 * DWL_USER Application specific information.
2083 * RETURNS
2085 * If successful, returns the previous value located at _offset_. Otherwise,
2086 * returns 0.
2088 * NOTES
2090 * Extra memory for a window class is specified by a nonzero cbWndExtra
2091 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2092 * time of class creation.
2094 * Using GWL_WNDPROC to set a new window procedure effectively creates
2095 * a window subclass. Use CallWindowProc() in the new windows procedure
2096 * to pass messages to the superclass's window procedure.
2098 * The user data is reserved for use by the application which created
2099 * the window.
2101 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2102 * instead, call the EnableWindow() function to change the window's
2103 * disabled state.
2105 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2106 * SetParent() instead.
2108 * Win95:
2109 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2110 * it sends WM_STYLECHANGING before changing the settings
2111 * and WM_STYLECHANGED afterwards.
2112 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2114 * BUGS
2116 * GWL_STYLE does not dispatch WM_STYLE... messages.
2118 * CONFORMANCE
2120 * ECMA-234, Win32
2123 LONG WINAPI SetWindowLongW(
2124 HWND hwnd, /* window to alter */
2125 INT offset, /* offset, in bytes, of location to alter */
2126 LONG newval /* new value of location */
2128 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2132 /*******************************************************************
2133 * GetWindowText16 (USER.36)
2135 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2137 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2141 /*******************************************************************
2142 * GetWindowText32A (USER32.309)
2144 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2146 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2147 (LPARAM)lpString );
2150 /*******************************************************************
2151 * InternalGetWindowText (USER32.326)
2153 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2155 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2156 return GetWindowTextW(hwnd,lpString,nMaxCount);
2160 /*******************************************************************
2161 * GetWindowText32W (USER32.312)
2163 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2165 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2166 (LPARAM)lpString );
2170 /*******************************************************************
2171 * SetWindowText16 (USER.37)
2173 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2175 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2179 /*******************************************************************
2180 * SetWindowText32A (USER32.521)
2182 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2184 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2188 /*******************************************************************
2189 * SetWindowText32W (USER32.523)
2191 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2193 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2197 /*******************************************************************
2198 * GetWindowTextLength16 (USER.38)
2200 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2202 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2206 /*******************************************************************
2207 * GetWindowTextLength32A (USER32.310)
2209 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2211 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2214 /*******************************************************************
2215 * GetWindowTextLength32W (USER32.311)
2217 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2219 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2223 /*******************************************************************
2224 * IsWindow16 (USER.47)
2226 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2228 return IsWindow( hwnd );
2231 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2233 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2234 HWND16 hwnd = (HWND16)stack[2];
2236 AX_reg(context) = IsWindow( hwnd );
2237 ES_reg(context) = USER_HeapSel;
2241 /*******************************************************************
2242 * IsWindow32 (USER32.348)
2244 BOOL WINAPI IsWindow( HWND hwnd )
2246 WND * wndPtr;
2247 BOOL retvalue;
2249 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2250 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2251 WIN_ReleaseWndPtr(wndPtr);
2252 return retvalue;
2257 /*****************************************************************
2258 * GetParent16 (USER.46)
2260 HWND16 WINAPI GetParent16( HWND16 hwnd )
2262 return (HWND16)GetParent( hwnd );
2266 /*****************************************************************
2267 * GetParent32 (USER32.278)
2269 HWND WINAPI GetParent( HWND hwnd )
2271 WND *wndPtr;
2272 HWND retvalue;
2274 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2275 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2277 WIN_ReleaseWndPtr(wndPtr);
2278 return 0;
2280 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2281 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2283 WIN_ReleaseWndPtr(wndPtr);
2284 return retvalue;
2288 /*****************************************************************
2289 * WIN_GetTopParent
2291 * Get the top-level parent for a child window.
2292 * returns a locked pointer
2294 WND* WIN_GetTopParentPtr( WND* pWnd )
2296 while( pWnd && (pWnd->dwStyle & WS_CHILD))
2298 WIN_UpdateWndPtr(&pWnd,pWnd->parent);
2300 return pWnd;
2303 /*****************************************************************
2304 * WIN_GetTopParent
2306 * Get the top-level parent for a child window.
2308 HWND WIN_GetTopParent( HWND hwnd )
2310 HWND retvalue;
2311 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2312 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2314 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2315 WIN_ReleaseWndPtr(tmpPtr);
2316 WIN_ReleaseWndPtr(wndPtr);
2317 return retvalue;
2321 /*****************************************************************
2322 * SetParent16 (USER.233)
2324 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2326 return SetParent( hwndChild, hwndNewParent );
2330 /*****************************************************************
2331 * SetParent32 (USER32.495)
2333 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2335 WND *wndPtr;
2336 DWORD dwStyle;
2337 WND *pWndNewParent;
2338 WND *pWndOldParent;
2339 HWND retvalue;
2342 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2344 dwStyle = wndPtr->dwStyle;
2346 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2347 : WIN_LockWndPtr(pWndDesktop);
2349 /* Windows hides the window first, then shows it again
2350 * including the WM_SHOWWINDOW messages and all */
2351 if (dwStyle & WS_VISIBLE)
2352 ShowWindow( hwndChild, SW_HIDE );
2354 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2356 /* SetParent32 additionally needs to make hwndChild the topmost window
2357 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2358 WM_WINDOWPOSCHANGED notification messages.
2360 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2361 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2362 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2363 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2365 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2367 WIN_ReleaseWndPtr(pWndOldParent);
2368 WIN_ReleaseWndPtr(pWndNewParent);
2369 WIN_ReleaseWndPtr(wndPtr);
2371 return retvalue;
2375 /*******************************************************************
2376 * IsChild16 (USER.48)
2378 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2380 return IsChild(parent,child);
2384 /*******************************************************************
2385 * IsChild32 (USER32.339)
2387 BOOL WINAPI IsChild( HWND parent, HWND child )
2389 WND * wndPtr = WIN_FindWndPtr( child );
2390 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2392 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2393 if (wndPtr->hwndSelf == parent)
2395 WIN_ReleaseWndPtr(wndPtr);
2396 return TRUE;
2399 WIN_ReleaseWndPtr(wndPtr);
2400 return FALSE;
2404 /***********************************************************************
2405 * IsWindowVisible16 (USER.49)
2407 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2409 return IsWindowVisible(hwnd);
2413 /***********************************************************************
2414 * IsWindowVisible32 (USER32.351)
2416 BOOL WINAPI IsWindowVisible( HWND hwnd )
2418 BOOL retval;
2419 WND *wndPtr = WIN_FindWndPtr( hwnd );
2420 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2422 if (!(wndPtr->dwStyle & WS_VISIBLE))
2424 WIN_ReleaseWndPtr(wndPtr);
2425 return FALSE;
2427 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2429 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2430 WIN_ReleaseWndPtr(wndPtr);
2431 return retval;
2436 /***********************************************************************
2437 * WIN_IsWindowDrawable
2439 * hwnd is drawable when it is visible, all parents are not
2440 * minimized, and it is itself not minimized unless we are
2441 * trying to draw its default class icon.
2443 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2445 if( (wnd->dwStyle & WS_MINIMIZE &&
2446 icon && wnd->class->hIcon) ||
2447 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2448 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2449 if( wnd->dwStyle & WS_MINIMIZE ||
2450 !(wnd->dwStyle & WS_VISIBLE) ) break;
2451 return (wnd == NULL);
2455 /*******************************************************************
2456 * GetTopWindow16 (USER.229)
2458 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2460 return GetTopWindow(hwnd);
2464 /*******************************************************************
2465 * GetTopWindow32 (USER.229)
2467 HWND WINAPI GetTopWindow( HWND hwnd )
2469 HWND retval;
2470 WND * wndPtr = WIN_FindWndPtr( hwnd );
2471 if (wndPtr && wndPtr->child)
2473 retval = wndPtr->child->hwndSelf;
2475 else retval = 0;
2476 WIN_ReleaseWndPtr(wndPtr);
2477 return retval;
2481 /*******************************************************************
2482 * GetWindow16 (USER.262)
2484 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2486 return GetWindow( hwnd,rel );
2490 /*******************************************************************
2491 * GetWindow32 (USER32.302)
2493 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2495 HWND retval;
2497 WND * wndPtr = WIN_FindWndPtr( hwnd );
2498 if (!wndPtr) return 0;
2499 switch(rel)
2501 case GW_HWNDFIRST:
2502 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2503 else retval = 0;
2504 goto end;
2506 case GW_HWNDLAST:
2507 if (!wndPtr->parent)
2509 retval = 0; /* Desktop window */
2510 goto end;
2512 while (wndPtr->next)
2514 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2516 retval = wndPtr->hwndSelf;
2517 goto end;
2519 case GW_HWNDNEXT:
2520 if (!wndPtr->next) retval = 0;
2521 else retval = wndPtr->next->hwndSelf;
2522 goto end;
2524 case GW_HWNDPREV:
2525 if (!wndPtr->parent)
2527 retval = 0; /* Desktop window */
2528 goto end;
2530 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2531 if (wndPtr->hwndSelf == hwnd)
2533 retval = 0; /* First in list */
2534 goto end;
2536 while (wndPtr->next)
2538 if (wndPtr->next->hwndSelf == hwnd)
2540 retval = wndPtr->hwndSelf;
2541 goto end;
2543 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2545 retval = 0;
2546 goto end;
2548 case GW_OWNER:
2549 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2550 goto end;
2552 case GW_CHILD:
2553 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2554 goto end;
2556 retval = 0;
2557 end:
2558 WIN_ReleaseWndPtr(wndPtr);
2559 return retval;
2563 /*******************************************************************
2564 * GetNextWindow16 (USER.230)
2566 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2568 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2569 return GetWindow16( hwnd, flag );
2572 /*******************************************************************
2573 * ShowOwnedPopups16 (USER.265)
2575 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2577 ShowOwnedPopups( owner, fShow );
2581 /*******************************************************************
2582 * ShowOwnedPopups32 (USER32.531)
2584 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2586 WND *pWnd;
2587 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2588 while (pWnd)
2590 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2591 (pWnd->dwStyle & WS_POPUP))
2592 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2593 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2595 return TRUE;
2599 /*******************************************************************
2600 * GetLastActivePopup16 (USER.287)
2602 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2604 return GetLastActivePopup( hwnd );
2607 /*******************************************************************
2608 * GetLastActivePopup32 (USER32.256)
2610 HWND WINAPI GetLastActivePopup( HWND hwnd )
2612 WND *wndPtr;
2613 HWND retval;
2614 wndPtr = WIN_FindWndPtr(hwnd);
2615 if (!wndPtr) return hwnd;
2616 retval = wndPtr->hwndLastActive;
2617 WIN_ReleaseWndPtr(wndPtr);
2618 return retval;
2622 /*******************************************************************
2623 * WIN_BuildWinArray
2625 * Build an array of pointers to the children of a given window.
2626 * The array must be freed with HeapFree(SystemHeap). Return NULL
2627 * when no windows are found.
2629 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2631 /* Future : this function will lock all windows associated with this array */
2633 WND **list, **ppWnd;
2634 WND *pWnd;
2635 UINT count = 0, skipOwned, skipHidden;
2636 DWORD skipFlags;
2638 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2639 skipOwned = bwaFlags & BWA_SKIPOWNED;
2640 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2641 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2643 /* First count the windows */
2645 if (!wndPtr)
2646 wndPtr = WIN_GetDesktop();
2648 pWnd = WIN_LockWndPtr(wndPtr->child);
2649 while (pWnd)
2651 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2652 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2654 count++;
2655 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2660 if( count )
2662 /* Now build the list of all windows */
2664 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2666 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2668 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2669 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2671 *ppWnd++ = pWnd;
2672 count++;
2675 WIN_ReleaseWndPtr(pWnd);
2676 *ppWnd = NULL;
2678 else count = 0;
2679 } else list = NULL;
2681 if( pTotal ) *pTotal = count;
2682 return list;
2684 /*******************************************************************
2685 * WIN_ReleaseWinArray
2687 void WIN_ReleaseWinArray(WND **wndArray)
2689 /* Future : this function will also unlock all windows associated with wndArray */
2690 HeapFree( SystemHeap, 0, wndArray );
2694 /*******************************************************************
2695 * EnumWindows16 (USER.54)
2697 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2699 WND **list, **ppWnd;
2701 /* We have to build a list of all windows first, to avoid */
2702 /* unpleasant side-effects, for instance if the callback */
2703 /* function changes the Z-order of the windows. */
2705 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2707 WIN_ReleaseDesktop();
2708 return FALSE;
2711 /* Now call the callback function for every window */
2713 for (ppWnd = list; *ppWnd; ppWnd++)
2715 /* Make sure that the window still exists */
2716 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2717 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2719 WIN_ReleaseWinArray(list);
2720 WIN_ReleaseDesktop();
2721 return TRUE;
2725 /*******************************************************************
2726 * EnumWindows32 (USER32.193)
2728 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2730 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2734 /**********************************************************************
2735 * EnumTaskWindows16 (USER.225)
2737 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2738 LPARAM lParam )
2740 WND **list, **ppWnd;
2742 /* This function is the same as EnumWindows(), */
2743 /* except for an added check on the window's task. */
2745 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2747 WIN_ReleaseDesktop();
2748 return FALSE;
2751 /* Now call the callback function for every window */
2753 for (ppWnd = list; *ppWnd; ppWnd++)
2755 /* Make sure that the window still exists */
2756 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2757 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2758 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2760 WIN_ReleaseWinArray(list);
2761 WIN_ReleaseDesktop();
2762 return TRUE;
2766 /**********************************************************************
2767 * EnumThreadWindows (USER32.190)
2769 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2771 THDB *tdb = THREAD_IdToTHDB(id);
2773 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2777 /**********************************************************************
2778 * WIN_EnumChildWindows
2780 * Helper function for EnumChildWindows().
2782 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2783 LPARAM lParam )
2785 WND **childList;
2786 BOOL16 ret = FALSE;
2788 for ( ; *ppWnd; ppWnd++)
2790 /* Make sure that the window still exists */
2791 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2792 /* Build children list first */
2793 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2794 ret = func( (*ppWnd)->hwndSelf, lParam );
2795 if (childList)
2797 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2798 WIN_ReleaseWinArray(childList);
2800 if (!ret) return FALSE;
2802 return TRUE;
2806 /**********************************************************************
2807 * EnumChildWindows16 (USER.55)
2809 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2810 LPARAM lParam )
2812 WND **list, *pParent;
2814 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2815 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2817 WIN_ReleaseWndPtr(pParent);
2818 return FALSE;
2820 WIN_EnumChildWindows( list, func, lParam );
2821 WIN_ReleaseWinArray(list);
2822 WIN_ReleaseWndPtr(pParent);
2823 return TRUE;
2827 /**********************************************************************
2828 * EnumChildWindows32 (USER32.178)
2830 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2831 LPARAM lParam )
2833 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2834 lParam );
2838 /*******************************************************************
2839 * AnyPopup16 (USER.52)
2841 BOOL16 WINAPI AnyPopup16(void)
2843 return AnyPopup();
2847 /*******************************************************************
2848 * AnyPopup32 (USER32.4)
2850 BOOL WINAPI AnyPopup(void)
2852 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2853 BOOL retvalue;
2855 while (wndPtr)
2857 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2859 retvalue = TRUE;
2860 goto end;
2862 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2864 retvalue = FALSE;
2865 end:
2866 WIN_ReleaseWndPtr(wndPtr);
2867 return retvalue;
2871 /*******************************************************************
2872 * FlashWindow16 (USER.105)
2874 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2876 return FlashWindow( hWnd, bInvert );
2880 /*******************************************************************
2881 * FlashWindow32 (USER32.202)
2883 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2885 WND *wndPtr = WIN_FindWndPtr(hWnd);
2887 TRACE(win,"%04x\n", hWnd);
2889 if (!wndPtr) return FALSE;
2891 if (wndPtr->dwStyle & WS_MINIMIZE)
2893 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2895 HDC hDC = GetDC(hWnd);
2897 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2898 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2900 ReleaseDC( hWnd, hDC );
2901 wndPtr->flags |= WIN_NCACTIVATED;
2903 else
2905 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2906 RDW_UPDATENOW | RDW_FRAME, 0 );
2907 wndPtr->flags &= ~WIN_NCACTIVATED;
2909 WIN_ReleaseWndPtr(wndPtr);
2910 return TRUE;
2912 else
2914 WPARAM16 wparam;
2915 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2916 else wparam = (hWnd == GetActiveWindow());
2918 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2919 WIN_ReleaseWndPtr(wndPtr);
2920 return wparam;
2925 /*******************************************************************
2926 * SetSysModalWindow16 (USER.188)
2928 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2930 HWND hWndOldModal = hwndSysModal;
2931 hwndSysModal = hWnd;
2932 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2933 return hWndOldModal;
2937 /*******************************************************************
2938 * GetSysModalWindow16 (USER.52)
2940 HWND16 WINAPI GetSysModalWindow16(void)
2942 return hwndSysModal;
2946 /*******************************************************************
2947 * GetWindowContextHelpId (USER32.303)
2949 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2951 DWORD retval;
2952 WND *wnd = WIN_FindWndPtr( hwnd );
2953 if (!wnd) return 0;
2954 retval = wnd->helpContext;
2955 WIN_ReleaseWndPtr(wnd);
2956 return retval;
2960 /*******************************************************************
2961 * SetWindowContextHelpId (USER32.515)
2963 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2965 WND *wnd = WIN_FindWndPtr( hwnd );
2966 if (!wnd) return FALSE;
2967 wnd->helpContext = id;
2968 WIN_ReleaseWndPtr(wnd);
2969 return TRUE;
2973 /*******************************************************************
2974 * DRAG_QueryUpdate
2976 * recursively find a child that contains spDragInfo->pt point
2977 * and send WM_QUERYDROPOBJECT
2979 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2981 BOOL16 wParam,bResult = 0;
2982 POINT pt;
2983 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2984 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2985 RECT tempRect;
2987 if( !ptrQueryWnd || !ptrDragInfo )
2989 WIN_ReleaseWndPtr(ptrQueryWnd);
2990 return 0;
2993 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2995 GetWindowRect(hQueryWnd,&tempRect);
2997 if( !PtInRect(&tempRect,pt) ||
2998 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3000 WIN_ReleaseWndPtr(ptrQueryWnd);
3001 return 0;
3004 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3006 tempRect = ptrQueryWnd->rectClient;
3007 if(ptrQueryWnd->dwStyle & WS_CHILD)
3008 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3009 (LPPOINT)&tempRect, 2 );
3011 if (PtInRect( &tempRect, pt))
3013 wParam = 0;
3015 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3017 if( ptrWnd->dwStyle & WS_VISIBLE )
3019 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3020 if (PtInRect( &tempRect, pt )) break;
3024 if(ptrWnd)
3026 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
3027 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3028 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3029 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3030 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3032 WIN_ReleaseWndPtr(ptrWnd);
3035 if(bResult)
3037 WIN_ReleaseWndPtr(ptrQueryWnd);
3038 return bResult;
3041 else wParam = 1;
3043 else wParam = 1;
3045 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3047 ptrDragInfo->hScope = hQueryWnd;
3049 bResult = ( bNoSend )
3050 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3051 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3052 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3053 if( !bResult )
3054 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3056 WIN_ReleaseWndPtr(ptrQueryWnd);
3057 return bResult;
3061 /*******************************************************************
3062 * DragDetect (USER.465)
3064 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3066 POINT pt32;
3067 CONV_POINT16TO32( &pt, &pt32 );
3068 return DragDetect( hWnd, pt32 );
3071 /*******************************************************************
3072 * DragDetect32 (USER32.151)
3074 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3076 MSG16 msg;
3077 RECT16 rect;
3079 rect.left = pt.x - wDragWidth;
3080 rect.right = pt.x + wDragWidth;
3082 rect.top = pt.y - wDragHeight;
3083 rect.bottom = pt.y + wDragHeight;
3085 SetCapture(hWnd);
3087 while(1)
3089 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3091 if( msg.message == WM_LBUTTONUP )
3093 ReleaseCapture();
3094 return 0;
3096 if( msg.message == WM_MOUSEMOVE )
3098 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3100 ReleaseCapture();
3101 return 1;
3105 WaitMessage();
3107 return 0;
3110 /******************************************************************************
3111 * DragObject16 (USER.464)
3113 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3114 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3116 MSG16 msg;
3117 LPDRAGINFO lpDragInfo;
3118 SEGPTR spDragInfo;
3119 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3120 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3121 WND *wndPtr = WIN_FindWndPtr(hWnd);
3122 HCURSOR16 hCurrentCursor = 0;
3123 HWND16 hCurrentWnd = 0;
3125 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3126 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3128 if( !lpDragInfo || !spDragInfo )
3130 WIN_ReleaseWndPtr(wndPtr);
3131 return 0L;
3134 hBummer = LoadCursor16(0, IDC_BUMMER16);
3136 if( !hBummer || !wndPtr )
3138 GlobalFree16(hDragInfo);
3139 WIN_ReleaseWndPtr(wndPtr);
3140 return 0L;
3143 if(hCursor)
3145 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3147 GlobalFree16(hDragInfo);
3148 WIN_ReleaseWndPtr(wndPtr);
3149 return 0L;
3152 if( hDragCursor == hCursor ) hDragCursor = 0;
3153 else hCursor = hDragCursor;
3155 hOldCursor = SetCursor(hDragCursor);
3158 lpDragInfo->hWnd = hWnd;
3159 lpDragInfo->hScope = 0;
3160 lpDragInfo->wFlags = wObj;
3161 lpDragInfo->hList = szList; /* near pointer! */
3162 lpDragInfo->hOfStruct = hOfStruct;
3163 lpDragInfo->l = 0L;
3165 SetCapture(hWnd);
3166 ShowCursor( TRUE );
3170 do{ WaitMessage(); }
3171 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3173 *(lpDragInfo+1) = *lpDragInfo;
3175 lpDragInfo->pt = msg.pt;
3177 /* update DRAGINFO struct */
3178 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
3180 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3181 hCurrentCursor = hCursor;
3182 else
3184 hCurrentCursor = hBummer;
3185 lpDragInfo->hScope = 0;
3187 if( hCurrentCursor )
3188 SetCursor(hCurrentCursor);
3190 /* send WM_DRAGLOOP */
3191 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3192 (LPARAM) spDragInfo );
3193 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3194 if( hCurrentWnd != lpDragInfo->hScope )
3196 if( hCurrentWnd )
3197 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3198 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3199 HIWORD(spDragInfo)) );
3200 hCurrentWnd = lpDragInfo->hScope;
3201 if( hCurrentWnd )
3202 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3204 else
3205 if( hCurrentWnd )
3206 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3208 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3210 ReleaseCapture();
3211 ShowCursor( FALSE );
3213 if( hCursor )
3215 SetCursor( hOldCursor );
3216 if (hDragCursor) DestroyCursor( hDragCursor );
3219 if( hCurrentCursor != hBummer )
3220 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3221 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3222 else
3223 msg.lParam = 0;
3224 GlobalFree16(hDragInfo);
3225 WIN_ReleaseWndPtr(wndPtr);
3227 return (DWORD)(msg.lParam);