blob: b2a135311f6d5ae6ce890dbe8044192e140e0169 [file] [log] [blame]
Alexandre Julliard401710d1993-09-04 10:09:32 +00001/*
2 * Window related functions
3 *
Alexandre Julliardaca05781994-10-17 18:12:41 +00004 * Copyright 1993, 1994 Alexandre Julliard
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliard401710d1993-09-04 10:09:32 +000019 */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000020
Alexandre Julliard5769d1d2002-04-26 19:05:15 +000021#include "config.h"
22#include "wine/port.h"
23
Alexandre Julliard7695d692001-09-24 01:19:59 +000024#include <assert.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000025#include <stdlib.h>
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000026#include <string.h>
Jeremy Whited3e22d92000-02-10 19:03:02 +000027#include "windef.h"
Marcus Meissner317af321999-02-17 13:51:06 +000028#include "wine/winbase16.h"
Michael Veksler9d14a001999-05-08 12:40:24 +000029#include "wine/winuser16.h"
Alexandre Julliard0ca051e2002-10-17 16:43:42 +000030#include "wownt32.h"
Alexandre Julliard1a66d222001-08-28 18:44:52 +000031#include "wine/server.h"
Alexandre Julliardcb10fda2000-08-06 02:41:16 +000032#include "wine/unicode.h"
Alexandre Julliard401710d1993-09-04 10:09:32 +000033#include "win.h"
Alexandre Julliardf0b23541993-09-29 12:21:49 +000034#include "user.h"
Alexandre Julliard5f721f81994-01-04 20:14:34 +000035#include "dce.h"
Alexandre Julliard91222da2000-12-10 23:01:33 +000036#include "controls.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000037#include "cursoricon.h"
Alexandre Julliardef702d81996-05-28 18:54:58 +000038#include "message.h"
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000039#include "queue.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000040#include "winpos.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000041#include "winerror.h"
Alexandre Julliard4220b291999-07-11 17:20:01 +000042#include "stackframe.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000043#include "wine/debug.h"
Alexandre Julliard401710d1993-09-04 10:09:32 +000044
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000045WINE_DEFAULT_DEBUG_CHANNEL(win);
46WINE_DECLARE_DEBUG_CHANNEL(msg);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000047
Alexandre Julliard7695d692001-09-24 01:19:59 +000048#define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
49
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +000050/**********************************************************************/
51
Alexandre Julliard59730ae1996-03-24 16:20:51 +000052/* Desktop window */
53static WND *pWndDesktop = NULL;
54
Alexandre Julliardd4719651995-12-12 18:49:11 +000055static WORD wDragWidth = 4;
56static WORD wDragHeight= 3;
Alexandre Julliardade697e1995-11-26 13:59:11 +000057
Alexandre Julliard7695d692001-09-24 01:19:59 +000058static void *user_handles[NB_USER_HANDLES];
Alexandre Julliard1a66d222001-08-28 18:44:52 +000059
Francois Boisvert93e3f901999-02-25 17:32:31 +000060/* thread safeness */
Alexandre Julliard6837b9c2001-08-16 18:14:22 +000061extern SYSLEVEL USER_SysLevel; /* FIXME */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000062
Francois Boisvert93e3f901999-02-25 17:32:31 +000063/***********************************************************************
64 * WIN_SuspendWndsLock
65 *
66 * Suspend the lock on WND structures.
67 * Returns the number of locks suspended
68 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000069int WIN_SuspendWndsLock( void )
Francois Boisvert93e3f901999-02-25 17:32:31 +000070{
Alexandre Julliard6837b9c2001-08-16 18:14:22 +000071 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000072 int count = isuspendedLocks;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +000073
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000074 while ( count-- > 0 )
Alexandre Julliard6837b9c2001-08-16 18:14:22 +000075 _LeaveSysLevel( &USER_SysLevel );
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +000076
Francois Boisvert93e3f901999-02-25 17:32:31 +000077 return isuspendedLocks;
Francois Boisvert93e3f901999-02-25 17:32:31 +000078}
79
80/***********************************************************************
81 * WIN_RestoreWndsLock
82 *
83 * Restore the suspended locks on WND structures
84 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000085void WIN_RestoreWndsLock( int ipreviousLocks )
Francois Boisvert93e3f901999-02-25 17:32:31 +000086{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000087 while ( ipreviousLocks-- > 0 )
Alexandre Julliard6837b9c2001-08-16 18:14:22 +000088 _EnterSysLevel( &USER_SysLevel );
Francois Boisvert93e3f901999-02-25 17:32:31 +000089}
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +000090
Alexandre Julliard401710d1993-09-04 10:09:32 +000091/***********************************************************************
Alexandre Julliard1a66d222001-08-28 18:44:52 +000092 * create_window_handle
93 *
94 * Create a window handle with the server.
95 */
Alexandre Julliard844ceb92001-10-09 23:26:40 +000096static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
Alexandre Julliard1a66d222001-08-28 18:44:52 +000097{
98 BOOL res;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +000099 user_handle_t handle = 0;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000100 WORD index;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000101 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
102
103 if (!win) return NULL;
104
105 USER_Lock();
106
Alexandre Julliarda09da0c2001-09-21 21:08:40 +0000107 SERVER_START_REQ( create_window )
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000108 {
Alexandre Julliarda09da0c2001-09-21 21:08:40 +0000109 req->parent = parent;
110 req->owner = owner;
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000111 req->atom = atom;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000112 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000113 }
Alexandre Julliarda09da0c2001-09-21 21:08:40 +0000114 SERVER_END_REQ;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000115
116 if (!res)
117 {
118 USER_Unlock();
119 HeapFree( GetProcessHeap(), 0, win );
120 return NULL;
121 }
Alexandre Julliard7695d692001-09-24 01:19:59 +0000122 index = LOWORD(handle) - FIRST_USER_HANDLE;
123 assert( index < NB_USER_HANDLES );
124 user_handles[index] = win;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000125 win->hwndSelf = handle;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000126 win->dwMagic = WND_MAGIC;
127 win->irefCount = 1;
128 return win;
129}
130
131
132/***********************************************************************
133 * free_window_handle
134 *
135 * Free a window handle.
136 */
137static WND *free_window_handle( HWND hwnd )
138{
139 WND *ptr;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000140 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000141
Alexandre Julliard7695d692001-09-24 01:19:59 +0000142 if (index >= NB_USER_HANDLES) return NULL;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000143 USER_Lock();
Alexandre Julliard7695d692001-09-24 01:19:59 +0000144 if ((ptr = user_handles[index]))
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000145 {
146 SERVER_START_REQ( destroy_window )
147 {
148 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000149 if (!wine_server_call_err( req ))
Alexandre Julliard7695d692001-09-24 01:19:59 +0000150 user_handles[index] = NULL;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000151 else
152 ptr = NULL;
153 }
154 SERVER_END_REQ;
155 }
156 USER_Unlock();
157 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
158 return ptr;
159}
160
161
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000162/*******************************************************************
163 * list_window_children
164 *
165 * Build an array of the children of a given window. The array must be
166 * freed with HeapFree. Returns NULL when no windows are found.
167 */
168static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
169{
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000170 HWND *list;
171 int size = 32;
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000172
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000173 for (;;)
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000174 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000175 int count = 0;
176
177 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
178
179 SERVER_START_REQ( get_window_children )
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000180 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000181 req->parent = hwnd;
182 req->atom = atom;
Alexandre Julliard54f22872002-10-03 19:54:57 +0000183 req->tid = tid;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000184 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
185 if (!wine_server_call( req )) count = reply->count;
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000186 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000187 SERVER_END_REQ;
188 if (count && count < size)
189 {
190 list[count] = 0;
191 return list;
192 }
193 HeapFree( GetProcessHeap(), 0, list );
194 if (!count) break;
195 size = count + 1; /* restart with a large enough buffer */
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000196 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000197 return NULL;
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000198}
199
200
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000201/*******************************************************************
202 * send_parent_notify
203 */
204static void send_parent_notify( HWND hwnd, UINT msg )
205{
206 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
207 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
208 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
209 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
210}
211
212
Alexandre Julliard805bdc52001-11-13 22:23:48 +0000213/*******************************************************************
214 * get_server_window_text
215 *
216 * Retrieve the window text from the server.
217 */
218static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
219{
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000220 size_t len = 0;
221
222 SERVER_START_REQ( get_window_text )
Alexandre Julliard805bdc52001-11-13 22:23:48 +0000223 {
224 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000225 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
226 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
Alexandre Julliard805bdc52001-11-13 22:23:48 +0000227 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000228 SERVER_END_REQ;
Alexandre Julliard805bdc52001-11-13 22:23:48 +0000229 text[len / sizeof(WCHAR)] = 0;
230}
231
232
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000233/***********************************************************************
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000234 * WIN_GetPtr
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000235 *
Alexandre Julliard7695d692001-09-24 01:19:59 +0000236 * Return a pointer to the WND structure if local to the process,
Andreas Mohr7df2d9f2002-07-24 19:02:50 +0000237 * or WND_OTHER_PROCESS if handle may be valid in other process.
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000238 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000239 */
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000240WND *WIN_GetPtr( HWND hwnd )
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000241{
Alexandre Julliard37a46392001-09-12 17:19:13 +0000242 WND * ptr;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000243 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000244
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000245 if (index >= NB_USER_HANDLES) return NULL;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000246
247 USER_Lock();
Alexandre Julliard7695d692001-09-24 01:19:59 +0000248 if ((ptr = user_handles[index]))
Alexandre Julliard37a46392001-09-12 17:19:13 +0000249 {
250 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
251 return ptr;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000252 ptr = NULL;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000253 }
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000254 else ptr = WND_OTHER_PROCESS;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000255 USER_Unlock();
Alexandre Julliard7695d692001-09-24 01:19:59 +0000256 return ptr;
257}
258
259
260/***********************************************************************
261 * WIN_IsCurrentProcess
262 *
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000263 * Check whether a given window belongs to the current process (and return the full handle).
Alexandre Julliard7695d692001-09-24 01:19:59 +0000264 */
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000265HWND WIN_IsCurrentProcess( HWND hwnd )
Alexandre Julliard7695d692001-09-24 01:19:59 +0000266{
267 WND *ptr;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000268 HWND ret;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000269
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000270 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
271 ret = ptr->hwndSelf;
272 WIN_ReleasePtr( ptr );
273 return ret;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000274}
275
276
277/***********************************************************************
278 * WIN_IsCurrentThread
279 *
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000280 * Check whether a given window belongs to the current thread (and return the full handle).
Alexandre Julliard7695d692001-09-24 01:19:59 +0000281 */
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000282HWND WIN_IsCurrentThread( HWND hwnd )
Alexandre Julliard7695d692001-09-24 01:19:59 +0000283{
284 WND *ptr;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000285 HWND ret = 0;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000286
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000287 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
Alexandre Julliard7695d692001-09-24 01:19:59 +0000288 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000289 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
290 WIN_ReleasePtr( ptr );
Alexandre Julliard7695d692001-09-24 01:19:59 +0000291 }
292 return ret;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000293}
294
295
296/***********************************************************************
297 * WIN_Handle32
298 *
299 * Convert a 16-bit window handle to a full 32-bit handle.
300 */
301HWND WIN_Handle32( HWND16 hwnd16 )
302{
303 WND *ptr;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000304 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000305
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000306 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
307 /* do sign extension for -2 and -3 */
308 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000309
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000310 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
311
312 if (ptr != WND_OTHER_PROCESS)
Alexandre Julliard37a46392001-09-12 17:19:13 +0000313 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000314 hwnd = ptr->hwndSelf;
315 WIN_ReleasePtr( ptr );
Alexandre Julliard37a46392001-09-12 17:19:13 +0000316 }
317 else /* may belong to another process */
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000318 {
319 SERVER_START_REQ( get_window_info )
320 {
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000321 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000322 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000323 }
324 SERVER_END_REQ;
325 }
326 return hwnd;
327}
328
329
330/***********************************************************************
Alexandre Julliard401710d1993-09-04 10:09:32 +0000331 * WIN_FindWndPtr
332 *
333 * Return a pointer to the WND structure corresponding to a HWND.
Alexandre Julliard401710d1993-09-04 10:09:32 +0000334 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000335WND * WIN_FindWndPtr( HWND hwnd )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000336{
337 WND * ptr;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000338
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000339 if (!hwnd) return NULL;
340
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000341 if ((ptr = WIN_GetPtr( hwnd )))
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000342 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000343 if (ptr != WND_OTHER_PROCESS)
Alexandre Julliard7695d692001-09-24 01:19:59 +0000344 {
345 /* increment destruction monitoring */
346 ptr->irefCount++;
347 return ptr;
348 }
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000349 if (IsWindow( hwnd )) /* check other processes */
350 {
351 ERR( "window %04x belongs to other process\n", hwnd );
352 /* DbgBreakPoint(); */
353 }
Alexandre Julliard37a46392001-09-12 17:19:13 +0000354 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000355 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
Eric Pouechb9544f11999-02-14 14:09:42 +0000356 return NULL;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000357}
358
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000359
Francois Boisvert93e3f901999-02-25 17:32:31 +0000360/***********************************************************************
361 * WIN_ReleaseWndPtr
362 *
363 * Release the pointer to the WND structure.
364 */
365void WIN_ReleaseWndPtr(WND *wndPtr)
366{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000367 if(!wndPtr) return;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000368
Andreas Mohre15badb2001-10-21 15:18:15 +0000369 /* Decrement destruction monitoring value */
Francois Boisvert93e3f901999-02-25 17:32:31 +0000370 wndPtr->irefCount--;
Andreas Mohre15badb2001-10-21 15:18:15 +0000371 /* Check if it's time to release the memory */
Francois Boisvert86e2e111999-04-03 11:13:33 +0000372 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
Francois Boisvert93e3f901999-02-25 17:32:31 +0000373 {
Francois Boisvert86e2e111999-04-03 11:13:33 +0000374 /* Release memory */
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000375 free_window_handle( wndPtr->hwndSelf );
Francois Boisvert93e3f901999-02-25 17:32:31 +0000376 }
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000377 else if(wndPtr->irefCount < 0)
378 {
379 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000380 ERR("forgot a Lock on %p somewhere\n",wndPtr);
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000381 }
Andreas Mohre15badb2001-10-21 15:18:15 +0000382 /* unlock all WND structures for thread safeness */
Alexandre Julliard6837b9c2001-08-16 18:14:22 +0000383 USER_Unlock();
Francois Boisvert93e3f901999-02-25 17:32:31 +0000384}
385
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000386
387/***********************************************************************
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000388 * WIN_UnlinkWindow
389 *
390 * Remove a window from the siblings linked list.
391 */
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000392void WIN_UnlinkWindow( HWND hwnd )
393{
394 WIN_LinkWindow( hwnd, 0, 0 );
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000395}
396
397
398/***********************************************************************
399 * WIN_LinkWindow
400 *
401 * Insert a window into the siblings linked list.
402 * The window is inserted after the specified window, which can also
403 * be specified as HWND_TOP or HWND_BOTTOM.
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000404 * If parent is 0, window is unlinked from the tree.
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000405 */
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000406void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
407{
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000408 WND *wndPtr = WIN_GetPtr( hwnd );
409
410 if (!wndPtr) return;
411 if (wndPtr == WND_OTHER_PROCESS)
412 {
413 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
414 return;
415 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000416
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000417 SERVER_START_REQ( link_window )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000418 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000419 req->handle = hwnd;
420 req->parent = parent;
421 req->previous = hwndInsertAfter;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000422 if (!wine_server_call( req ))
Alexandre Julliardddc33172001-10-22 19:08:33 +0000423 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000424 if (reply->full_parent) wndPtr->parent = reply->full_parent;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000425 }
426
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000427 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000428 SERVER_END_REQ;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000429 WIN_ReleasePtr( wndPtr );
430}
431
432
433/***********************************************************************
434 * WIN_SetOwner
435 *
436 * Change the owner of a window.
437 */
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000438HWND WIN_SetOwner( HWND hwnd, HWND owner )
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000439{
Alexandre Julliardddc33172001-10-22 19:08:33 +0000440 WND *win = WIN_GetPtr( hwnd );
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000441 HWND ret = 0;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000442
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000443 if (!win) return 0;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000444 if (win == WND_OTHER_PROCESS)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000445 {
Alexandre Julliardddc33172001-10-22 19:08:33 +0000446 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000447 return 0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000448 }
Alexandre Julliardddc33172001-10-22 19:08:33 +0000449 SERVER_START_REQ( set_window_owner )
450 {
451 req->handle = hwnd;
452 req->owner = owner;
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000453 if (!wine_server_call( req ))
454 {
455 win->owner = reply->full_owner;
456 ret = reply->prev_owner;
457 }
Alexandre Julliardddc33172001-10-22 19:08:33 +0000458 }
459 SERVER_END_REQ;
460 WIN_ReleasePtr( win );
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000461 return ret;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000462}
463
464
465/***********************************************************************
466 * WIN_SetStyle
467 *
468 * Change the style of a window.
469 */
470LONG WIN_SetStyle( HWND hwnd, LONG style )
471{
472 BOOL ok;
473 LONG ret = 0;
474 WND *win = WIN_GetPtr( hwnd );
475
476 if (!win) return 0;
477 if (win == WND_OTHER_PROCESS)
478 {
479 if (IsWindow(hwnd))
480 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
481 return 0;
482 }
483 if (style == win->dwStyle)
484 {
485 WIN_ReleasePtr( win );
486 return style;
487 }
488 SERVER_START_REQ( set_window_info )
489 {
490 req->handle = hwnd;
491 req->flags = SET_WIN_STYLE;
492 req->style = style;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000493 if ((ok = !wine_server_call( req )))
Alexandre Julliardddc33172001-10-22 19:08:33 +0000494 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000495 ret = reply->old_style;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000496 win->dwStyle = style;
497 }
498 }
499 SERVER_END_REQ;
500 WIN_ReleasePtr( win );
501 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
502 return ret;
503}
504
505
506/***********************************************************************
507 * WIN_SetExStyle
508 *
509 * Change the extended style of a window.
510 */
511LONG WIN_SetExStyle( HWND hwnd, LONG style )
512{
513 LONG ret = 0;
514 WND *win = WIN_GetPtr( hwnd );
515
516 if (!win) return 0;
517 if (win == WND_OTHER_PROCESS)
518 {
519 if (IsWindow(hwnd))
520 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
521 return 0;
522 }
523 if (style == win->dwExStyle)
524 {
525 WIN_ReleasePtr( win );
526 return style;
527 }
528 SERVER_START_REQ( set_window_info )
529 {
530 req->handle = hwnd;
531 req->flags = SET_WIN_EXSTYLE;
532 req->ex_style = style;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000533 if (!wine_server_call( req ))
Alexandre Julliardddc33172001-10-22 19:08:33 +0000534 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000535 ret = reply->old_ex_style;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000536 win->dwExStyle = style;
537 }
538 }
539 SERVER_END_REQ;
540 WIN_ReleasePtr( win );
541 return ret;
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000542}
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000543
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000544
545/***********************************************************************
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000546 * WIN_SetRectangles
547 *
548 * Set the window and client rectangles.
549 */
550void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
551{
552 WND *win = WIN_GetPtr( hwnd );
553 BOOL ret;
554
555 if (!win) return;
556 if (win == WND_OTHER_PROCESS)
557 {
558 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
559 return;
560 }
561 SERVER_START_REQ( set_window_rectangles )
562 {
563 req->handle = hwnd;
564 req->window.left = rectWindow->left;
565 req->window.top = rectWindow->top;
566 req->window.right = rectWindow->right;
567 req->window.bottom = rectWindow->bottom;
568 req->client.left = rectClient->left;
569 req->client.top = rectClient->top;
570 req->client.right = rectClient->right;
571 req->client.bottom = rectClient->bottom;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000572 ret = !wine_server_call( req );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000573 }
574 SERVER_END_REQ;
575 if (ret)
576 {
577 win->rectWindow = *rectWindow;
578 win->rectClient = *rectClient;
579
580 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
581 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
582 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
583 }
584 WIN_ReleasePtr( win );
585}
586
587
588/***********************************************************************
Alexandre Julliard5797fbb2001-12-06 22:33:58 +0000589 * WIN_GetRectangles
590 *
591 * Get the window and client rectangles.
592 */
593BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
594{
595 WND *win = WIN_GetPtr( hwnd );
596 BOOL ret = TRUE;
597
598 if (!win) return FALSE;
599 if (win == WND_OTHER_PROCESS)
600 {
601 SERVER_START_REQ( get_window_rectangles )
602 {
603 req->handle = hwnd;
604 if ((ret = !wine_server_call( req )))
605 {
606 if (rectWindow)
607 {
608 rectWindow->left = reply->window.left;
609 rectWindow->top = reply->window.top;
610 rectWindow->right = reply->window.right;
611 rectWindow->bottom = reply->window.bottom;
612 }
613 if (rectClient)
614 {
615 rectClient->left = reply->client.left;
616 rectClient->top = reply->client.top;
617 rectClient->right = reply->client.right;
618 rectClient->bottom = reply->client.bottom;
619 }
620 }
621 }
622 SERVER_END_REQ;
623 }
624 else
625 {
626 if (rectWindow) *rectWindow = win->rectWindow;
627 if (rectClient) *rectClient = win->rectClient;
628 WIN_ReleasePtr( win );
629 }
630 return ret;
631}
632
633
634/***********************************************************************
Alexandre Julliardaca05781994-10-17 18:12:41 +0000635 * WIN_DestroyWindow
636 *
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000637 * Destroy storage associated to a window. "Internals" p.358
Alexandre Julliardaca05781994-10-17 18:12:41 +0000638 */
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000639LRESULT WIN_DestroyWindow( HWND hwnd )
Alexandre Julliardaca05781994-10-17 18:12:41 +0000640{
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000641 WND *wndPtr;
642 HWND *list;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000643
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000644 TRACE("%04x\n", hwnd );
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000645
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000646 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
647 {
648 ERR( "window doesn't belong to current thread\n" );
649 return 0;
650 }
651
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000652 /* free child windows */
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000653 if ((list = WIN_ListChildren( hwnd )))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000654 {
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000655 int i;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000656 for (i = 0; list[i]; i++)
657 {
658 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
659 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
660 }
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000661 HeapFree( GetProcessHeap(), 0, list );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000662 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000663
Francis Beaudet7c2f0fe1999-03-21 08:50:41 +0000664 /*
665 * Clear the update region to make sure no WM_PAINT messages will be
666 * generated for this window while processing the WM_NCDESTROY.
667 */
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000668 RedrawWindow( hwnd, NULL, 0,
Alexandre Julliard4b0343d2001-06-20 22:55:31 +0000669 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
Francis Beaudet7c2f0fe1999-03-21 08:50:41 +0000670
671 /*
672 * Send the WM_NCDESTROY to the window being destroyed.
673 */
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000674 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000675
676 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
677
Alexandre Julliardde424282001-08-10 22:51:42 +0000678 WINPOS_CheckInternalPos( hwnd );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000679 if( hwnd == GetCapture()) ReleaseCapture();
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000680
681 /* free resources associated with the window */
682
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000683 TIMER_RemoveWindowTimers( hwnd );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000684
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000685 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000686
687 if (!(wndPtr->dwStyle & WS_CHILD))
Alexandre Julliardddc33172001-10-22 19:08:33 +0000688 {
689 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
690 if (menu) DestroyMenu( menu );
691 }
Guy Albertelli38db0982000-05-11 00:06:38 +0000692 if (wndPtr->hSysMenu)
693 {
694 DestroyMenu( wndPtr->hSysMenu );
695 wndPtr->hSysMenu = 0;
696 }
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000697 USER_Driver.pDestroyWindow( hwnd );
698 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000699 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
Alexandre Julliard98779062000-12-07 23:39:16 +0000700 CLASS_RemoveWindow( wndPtr->class );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000701 wndPtr->class = NULL;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000702 wndPtr->dwMagic = 0; /* Mark it as invalid */
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000703 WIN_ReleaseWndPtr( wndPtr );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000704 return 0;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000705}
706
Alexandre Julliardaca05781994-10-17 18:12:41 +0000707/***********************************************************************
Alexandre Julliard4b0343d2001-06-20 22:55:31 +0000708 * WIN_DestroyThreadWindows
Alexandre Julliard77b99181997-09-14 17:17:23 +0000709 *
Alexandre Julliard4b0343d2001-06-20 22:55:31 +0000710 * Destroy all children of 'wnd' owned by the current thread.
Alexandre Julliard77b99181997-09-14 17:17:23 +0000711 * Return TRUE if something was done.
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000712 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000713void WIN_DestroyThreadWindows( HWND hwnd )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000714{
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000715 HWND *list;
716 int i;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000717
Alexandre Julliard9d9dac02001-08-24 19:28:21 +0000718 if (!(list = WIN_ListChildren( hwnd ))) return;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000719 for (i = 0; list[i]; i++)
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000720 {
Alexandre Julliard7695d692001-09-24 01:19:59 +0000721 if (WIN_IsCurrentThread( list[i] ))
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000722 DestroyWindow( list[i] );
723 else
724 WIN_DestroyThreadWindows( list[i] );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000725 }
Alexandre Julliard9d9dac02001-08-24 19:28:21 +0000726 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000727}
728
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000729/***********************************************************************
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000730 * WIN_CreateDesktopWindow
731 *
732 * Create the desktop window.
733 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000734BOOL WIN_CreateDesktopWindow(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000735{
Alexandre Julliard98779062000-12-07 23:39:16 +0000736 struct tagCLASS *class;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000737 HWND hwndDesktop;
Alexandre Julliard98779062000-12-07 23:39:16 +0000738 INT wndExtra;
739 DWORD clsStyle;
740 WNDPROC winproc;
741 DCE *dce;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000742 CREATESTRUCTA cs;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000743 RECT rect;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000744
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000745 TRACE("Creating desktop window\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000746
Alexandre Julliard91222da2000-12-10 23:01:33 +0000747 if (!WINPOS_CreateInternalPosAtom() ||
748 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
Alexandre Julliard98779062000-12-07 23:39:16 +0000749 &wndExtra, &winproc, &clsStyle, &dce )))
750 return FALSE;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000751
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000752 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
753 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000754 if (!pWndDesktop) return FALSE;
755 hwndDesktop = pWndDesktop->hwndSelf;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000756
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000757 pWndDesktop->tid = 0; /* nobody owns the desktop */
Alexandre Julliard556607a2001-10-10 20:28:17 +0000758 pWndDesktop->parent = 0;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +0000759 pWndDesktop->owner = 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000760 pWndDesktop->class = class;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000761 pWndDesktop->text = NULL;
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000762 pWndDesktop->hrgnUpdate = 0;
Alexandre Julliard98779062000-12-07 23:39:16 +0000763 pWndDesktop->clsStyle = clsStyle;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000764 pWndDesktop->dce = NULL;
Alexandre Julliardca22b331996-07-12 19:02:39 +0000765 pWndDesktop->pVScroll = NULL;
766 pWndDesktop->pHScroll = NULL;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000767 pWndDesktop->helpContext = 0;
Alexandre Julliard26320d12001-03-23 23:45:45 +0000768 pWndDesktop->flags = 0;
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000769 pWndDesktop->hSysMenu = 0;
Alexandre Julliard98779062000-12-07 23:39:16 +0000770 pWndDesktop->winproc = winproc;
771 pWndDesktop->cbWndExtra = wndExtra;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000772
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000773 cs.lpCreateParams = NULL;
774 cs.hInstance = 0;
775 cs.hMenu = 0;
776 cs.hwndParent = 0;
777 cs.x = 0;
778 cs.y = 0;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000779 cs.cx = GetSystemMetrics( SM_CXSCREEN );
780 cs.cy = GetSystemMetrics( SM_CYSCREEN );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000781 cs.style = pWndDesktop->dwStyle;
782 cs.dwExStyle = pWndDesktop->dwExStyle;
783 cs.lpszName = NULL;
784 cs.lpszClass = DESKTOP_CLASS_ATOM;
Alexandre Julliard91222da2000-12-10 23:01:33 +0000785
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000786 SetRect( &rect, 0, 0, cs.cx, cs.cy );
787 WIN_SetRectangles( hwndDesktop, &rect, &rect );
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000788
789 SERVER_START_REQ( set_window_info )
790 {
791 req->handle = hwndDesktop;
792 req->flags = 0; /* don't set anything, just retrieve */
793 wine_server_call( req );
794 pWndDesktop->dwStyle = reply->old_style;
795 pWndDesktop->dwExStyle = reply->old_ex_style;
796 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
797 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
798 pWndDesktop->wIDmenu = reply->old_id;
799 }
800 SERVER_END_REQ;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000801
Francois Gouget69e35002002-05-19 22:20:31 +0000802 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
803 {
804 WIN_ReleaseWndPtr( pWndDesktop );
805 return FALSE;
806 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000807
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000808 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000809 WIN_ReleaseWndPtr( pWndDesktop );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000810 return TRUE;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000811}
812
813
814/***********************************************************************
Dmitry Timoshkov5956b982000-11-28 23:53:08 +0000815 * WIN_FixCoordinates
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000816 *
Gerard Patel78f52b52000-05-31 19:23:20 +0000817 * Fix the coordinates - Helper for WIN_CreateWindowEx.
818 * returns default show mode in sw.
819 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
820 */
821static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
822{
823 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
824 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
825 {
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000826 if (cs->style & (WS_CHILD | WS_POPUP))
Gerard Patel78f52b52000-05-31 19:23:20 +0000827 {
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000828 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
829 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
Gerard Patel78f52b52000-05-31 19:23:20 +0000830 }
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000831 else /* overlapped window */
Gerard Patel78f52b52000-05-31 19:23:20 +0000832 {
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000833 STARTUPINFOA info;
834
835 GetStartupInfoA( &info );
836
837 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
838 {
Alexandre Julliard0d92fe22001-09-10 23:26:42 +0000839 /* Never believe Microsoft's documentation... CreateWindowEx doc says
840 * that if an overlapped window is created with WS_VISIBLE style bit
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000841 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
842 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
843 * reveals that
844 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +0000845 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
846 * 2) it does not ignore the y parameter as the docs claim; instead, it
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000847 * uses it as second parameter to ShowWindow() unless y is either
848 * CW_USEDEFAULT or CW_USEDEFAULT16.
Alexandre Julliard0d92fe22001-09-10 23:26:42 +0000849 *
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000850 * The fact that we didn't do 2) caused bogus windows pop up when wine
Alexandre Julliard0d92fe22001-09-10 23:26:42 +0000851 * was running apps that were using this obscure feature. Example -
852 * calc.exe that comes with Win98 (only Win98, it's different from
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000853 * the one that comes with Win95 and NT)
854 */
855 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
856 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
857 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
858 }
859
860 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
861 {
862 if (info.dwFlags & STARTF_USESIZE)
863 {
864 cs->cx = info.dwXSize;
865 cs->cy = info.dwYSize;
866 }
867 else /* if no other hint from the app, pick 3/4 of the screen real estate */
868 {
869 RECT r;
870 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
871 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
872 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
873 }
874 }
Gerard Patel78f52b52000-05-31 19:23:20 +0000875 }
876 }
Guy L. Albertellif1a624d2002-02-27 01:20:54 +0000877 else
878 {
879 /* neither x nor cx are default. Check the y values .
Vincent Béron9a624912002-05-31 23:06:46 +0000880 * In the trace we see Outlook and Outlook Express using
Guy L. Albertellif1a624d2002-02-27 01:20:54 +0000881 * cy set to CW_USEDEFAULT when opening the address book.
882 */
883 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
884 RECT r;
885 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
886 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
887 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
888 }
889 }
Gerard Patel78f52b52000-05-31 19:23:20 +0000890}
891
892/***********************************************************************
Dmitry Timoshkov5d3e1f72001-11-07 21:52:24 +0000893 * dump_window_styles
894 */
895static void dump_window_styles( DWORD style, DWORD exstyle )
896{
897 TRACE( "style:" );
898 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
899 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
900 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
901 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
902 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
903 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
904 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
905 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
906 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
907 else
908 {
909 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
910 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
911 }
912 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
913 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
914 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
915 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
916 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
917 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
918 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
919 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
920
921 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
922#define DUMPED_STYLES \
923 (WS_POPUP | \
924 WS_CHILD | \
925 WS_MINIMIZE | \
926 WS_VISIBLE | \
927 WS_DISABLED | \
928 WS_CLIPSIBLINGS | \
929 WS_CLIPCHILDREN | \
930 WS_MAXIMIZE | \
931 WS_BORDER | \
932 WS_DLGFRAME | \
933 WS_VSCROLL | \
934 WS_HSCROLL | \
935 WS_SYSMENU | \
936 WS_THICKFRAME | \
937 WS_GROUP | \
938 WS_TABSTOP | \
939 WS_MINIMIZEBOX | \
940 WS_MAXIMIZEBOX)
941
942 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
943 DPRINTF("\n");
944#undef DUMPED_STYLES
945
946 TRACE( "exstyle:" );
947 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
948 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
949 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
950 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
951 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
952 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
953 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
954 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
955 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
956 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
957 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
958 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
959 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
960 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
961 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
962 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
963 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
964 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
965
966#define DUMPED_EX_STYLES \
967 (WS_EX_DLGMODALFRAME | \
968 WS_EX_DRAGDETECT | \
969 WS_EX_NOPARENTNOTIFY | \
970 WS_EX_TOPMOST | \
971 WS_EX_ACCEPTFILES | \
972 WS_EX_TRANSPARENT | \
973 WS_EX_MDICHILD | \
974 WS_EX_TOOLWINDOW | \
975 WS_EX_WINDOWEDGE | \
976 WS_EX_CLIENTEDGE | \
977 WS_EX_CONTEXTHELP | \
978 WS_EX_RIGHT | \
979 WS_EX_RTLREADING | \
980 WS_EX_LEFTSCROLLBAR | \
981 WS_EX_CONTROLPARENT | \
982 WS_EX_STATICEDGE | \
983 WS_EX_APPWINDOW | \
984 WS_EX_LAYERED)
985
986 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
987 DPRINTF("\n");
988#undef DUMPED_EX_STYLES
989}
990
991
992/***********************************************************************
Gerard Patel78f52b52000-05-31 19:23:20 +0000993 * WIN_CreateWindowEx
994 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000995 * Implementation of CreateWindowEx().
Alexandre Julliard401710d1993-09-04 10:09:32 +0000996 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000997static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
Dmitry Timoshkov5956b982000-11-28 23:53:08 +0000998 WINDOWPROCTYPE type )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000999{
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001000 INT sw = SW_SHOW;
Alexandre Julliard98779062000-12-07 23:39:16 +00001001 struct tagCLASS *classPtr;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +00001002 WND *wndPtr;
Rein Klazes0f2f2b32002-01-09 19:09:06 +00001003 HWND hwnd, parent, owner;
Alexandre Julliard98779062000-12-07 23:39:16 +00001004 INT wndExtra;
1005 DWORD clsStyle;
1006 WNDPROC winproc;
1007 DCE *dce;
Gerard Patelad363032001-06-06 21:26:50 +00001008 BOOL unicode = (type == WIN_PROC_32W);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001009
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00001010 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
Alexandre Julliard0aa28b52002-05-17 02:55:48 +00001011 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1012 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001013 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1014 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
Alexandre Julliard401710d1993-09-04 10:09:32 +00001015
Dmitry Timoshkov5d3e1f72001-11-07 21:52:24 +00001016 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1017
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001018 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1019 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1020
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001021 /* Find the parent window */
Alexandre Julliard401710d1993-09-04 10:09:32 +00001022
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00001023 parent = GetDesktopWindow();
1024 owner = 0;
Juergen Schmiedeb2db1a2002-08-29 01:49:46 +00001025
1026 if (cs->hwndParent == HWND_MESSAGE)
1027 {
1028 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1029 * message window (style: WS_POPUP|WS_DISABLED)
1030 */
1031 FIXME("Parent is HWND_MESSAGE\n");
1032 }
1033 else if (cs->hwndParent)
Alexandre Julliard401710d1993-09-04 10:09:32 +00001034 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001035 /* Make sure parent is valid */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001036 if (!IsWindow( cs->hwndParent ))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001037 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001038 WARN("Bad parent %04x\n", cs->hwndParent );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001039 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001040 }
Alexandre Julliard7dafa612002-09-25 00:21:56 +00001041 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1042 parent = WIN_GetFullHandle(cs->hwndParent);
1043 else
1044 owner = GetAncestor( cs->hwndParent, GA_ROOT );
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00001045 }
Alexandre Julliard7dafa612002-09-25 00:21:56 +00001046 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00001047 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001048 WARN("No parent for child window\n" );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001049 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001050 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001051
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001052 /* Find the window class */
Alexandre Julliard98779062000-12-07 23:39:16 +00001053 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1054 &wndExtra, &winproc, &clsStyle, &dce )))
Alexandre Julliard808cb041995-08-17 17:11:36 +00001055 {
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001056 WARN("Bad class '%s'\n", cs->lpszClass );
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001057 return 0;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001058 }
Alexandre Julliardcdd09231994-01-12 11:12:51 +00001059
Gerard Patel78f52b52000-05-31 19:23:20 +00001060 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
Alexandre Julliardcdd09231994-01-12 11:12:51 +00001061
Bill Medland3f68bc92001-07-20 18:36:25 +00001062 /* Correct the window style - stage 1
1063 *
1064 * These are patches that appear to affect both the style loaded into the
1065 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1066 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001067 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
Bill Medland3f68bc92001-07-20 18:36:25 +00001068 * why does the user get to set it?
1069 */
1070
1071 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1072 * tested for WS_POPUP
1073 */
1074 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1075 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1076 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1077 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1078 else
1079 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1080
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001081 /* Create the window structure */
Alexandre Julliard401710d1993-09-04 10:09:32 +00001082
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001083 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
Alexandre Julliard1a66d222001-08-28 18:44:52 +00001084 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001085 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001086 TRACE("out of memory\n" );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001087 return 0;
1088 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00001089 hwnd = wndPtr->hwndSelf;
Alexandre Julliard401710d1993-09-04 10:09:32 +00001090
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001091 /* Fill the window structure */
Alexandre Julliard401710d1993-09-04 10:09:32 +00001092
Alexandre Julliard80593bf2001-10-11 20:49:40 +00001093 wndPtr->tid = GetCurrentThreadId();
1094 wndPtr->owner = owner;
Alexandre Julliard556607a2001-10-10 20:28:17 +00001095 wndPtr->parent = parent;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001096 wndPtr->class = classPtr;
Alexandre Julliard98779062000-12-07 23:39:16 +00001097 wndPtr->winproc = winproc;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001098 wndPtr->hInstance = cs->hInstance;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001099 wndPtr->text = NULL;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001100 wndPtr->hrgnUpdate = 0;
Huw D M Daviesa14ca862000-07-29 11:31:29 +00001101 wndPtr->hrgnWnd = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001102 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1103 wndPtr->dwExStyle = cs->dwExStyle;
Alexandre Julliard98779062000-12-07 23:39:16 +00001104 wndPtr->clsStyle = clsStyle;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001105 wndPtr->wIDmenu = 0;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001106 wndPtr->helpContext = 0;
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001107 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
Alexandre Julliardca22b331996-07-12 19:02:39 +00001108 wndPtr->pVScroll = NULL;
1109 wndPtr->pHScroll = NULL;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001110 wndPtr->userdata = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001111 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1112 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
Alexandre Julliard98779062000-12-07 23:39:16 +00001113 wndPtr->cbWndExtra = wndExtra;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001114
Alexandre Julliard98779062000-12-07 23:39:16 +00001115 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001116
Bill Medland3f68bc92001-07-20 18:36:25 +00001117 /* Correct the window style - stage 2 */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001118
Alex Korobka44a1b591999-04-01 12:03:52 +00001119 if (!(cs->style & WS_CHILD))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001120 {
Alex Korobka44a1b591999-04-01 12:03:52 +00001121 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1122 if (!(cs->style & WS_POPUP))
1123 {
1124 wndPtr->dwStyle |= WS_CAPTION;
1125 wndPtr->flags |= WIN_NEED_SIZE;
1126 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001127 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001128 SERVER_START_REQ( set_window_info )
1129 {
1130 req->handle = hwnd;
1131 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1132 req->style = wndPtr->dwStyle;
1133 req->ex_style = wndPtr->dwExStyle;
1134 req->instance = (void *)wndPtr->hInstance;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00001135 wine_server_call( req );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001136 }
1137 SERVER_END_REQ;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001138
1139 /* Get class or window DC if needed */
Alexandre Julliardaca05781994-10-17 18:12:41 +00001140
Alexandre Julliard98779062000-12-07 23:39:16 +00001141 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1142 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001143 else wndPtr->dce = NULL;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001144
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001145 /* Set the window menu */
1146
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001147 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001148 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001149 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001150 else
1151 {
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001152 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
Alexandre Julliard54c27111998-03-29 19:44:57 +00001153 if (menuName)
1154 {
Ulrich Weigand7df1fbb1998-11-01 18:01:53 +00001155 if (HIWORD(cs->hInstance))
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001156 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
Alexandre Julliard54c27111998-03-29 19:44:57 +00001157 else
Alexandre Julliard54c27111998-03-29 19:44:57 +00001158 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1159
Alexandre Julliarda3960291999-02-26 11:11:13 +00001160 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
Alexandre Julliard54c27111998-03-29 19:44:57 +00001161 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001162 }
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001163 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001164 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1165 WIN_ReleaseWndPtr( wndPtr );
Alexandre Julliard490a27e1994-06-08 13:57:50 +00001166
Alexandre Julliard80593bf2001-10-11 20:49:40 +00001167 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001168 {
Alexandre Julliard80593bf2001-10-11 20:49:40 +00001169 WIN_DestroyWindow( hwnd );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001170 return 0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001171 }
Alexandre Julliard401710d1993-09-04 10:09:32 +00001172
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001173 /* Notify the parent window only */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001174
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001175 send_parent_notify( hwnd, WM_CREATE );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001176 if (!IsWindow( hwnd )) return 0;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001177
1178 if (cs->style & WS_VISIBLE)
1179 {
1180 /* in case WS_VISIBLE got set in the meantime */
Alexandre Julliardddc33172001-10-22 19:08:33 +00001181 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1182 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1183 WIN_ReleasePtr( wndPtr );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001184 ShowWindow( hwnd, sw );
1185 }
1186
1187 /* Call WH_SHELL hook */
1188
Alexandre Julliardddc33172001-10-22 19:08:33 +00001189 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
Alexandre Julliard02861352002-10-29 00:41:42 +00001190 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001191
1192 TRACE("created window %04x\n", hwnd);
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001193 return hwnd;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001194}
1195
1196
1197/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001198 * CreateWindow (USER.41)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001199 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001200HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1201 DWORD style, INT16 x, INT16 y, INT16 width,
1202 INT16 height, HWND16 parent, HMENU16 menu,
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001203 HINSTANCE16 instance, LPVOID data )
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001204{
1205 return CreateWindowEx16( 0, className, windowName, style,
1206 x, y, width, height, parent, menu, instance, data );
1207}
1208
1209
1210/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001211 * CreateWindowEx (USER.452)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001212 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001213HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1214 LPCSTR windowName, DWORD style, INT16 x,
1215 INT16 y, INT16 width, INT16 height,
1216 HWND16 parent, HMENU16 menu,
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001217 HINSTANCE16 instance, LPVOID data )
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001218{
1219 ATOM classAtom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001220 CREATESTRUCTA cs;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001221 char buffer[256];
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001222
1223 /* Find the class atom */
1224
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001225 if (HIWORD(className))
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001226 {
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001227 if (!(classAtom = GlobalFindAtomA( className )))
1228 {
Alexandre Julliard0aa28b52002-05-17 02:55:48 +00001229 ERR( "bad class name %s\n", debugstr_a(className) );
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001230 return 0;
1231 }
1232 }
1233 else
1234 {
1235 classAtom = LOWORD(className);
1236 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1237 {
1238 ERR( "bad atom %x\n", classAtom);
1239 return 0;
1240 }
1241 className = buffer;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001242 }
1243
1244 /* Fix the coordinates */
1245
Alexandre Julliarda3960291999-02-26 11:11:13 +00001246 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1247 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1248 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1249 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001250
1251 /* Create the window */
1252
1253 cs.lpCreateParams = data;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001254 cs.hInstance = (HINSTANCE)instance;
1255 cs.hMenu = (HMENU)menu;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001256 cs.hwndParent = WIN_Handle32( parent );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001257 cs.style = style;
1258 cs.lpszName = windowName;
1259 cs.lpszClass = className;
1260 cs.dwExStyle = exStyle;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001261
Michael Stefaniuc2247af32002-09-04 19:37:01 +00001262 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001263}
1264
1265
1266/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001267 * CreateWindowExA (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001268 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001269HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1270 LPCSTR windowName, DWORD style, INT x,
1271 INT y, INT width, INT height,
1272 HWND parent, HMENU menu,
1273 HINSTANCE instance, LPVOID data )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001274{
1275 ATOM classAtom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001276 CREATESTRUCTA cs;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001277 char buffer[256];
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001278
Rein Klazesd4a2cee1999-10-23 13:57:36 +00001279 if(!instance)
1280 instance=GetModuleHandleA(NULL);
1281
Rein Klazes5c6fc1b1998-11-01 14:50:06 +00001282 if(exStyle & WS_EX_MDICHILD)
Dmitry Timoshkov91adf0a2001-02-12 03:40:41 +00001283 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001284
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001285 /* Find the class atom */
1286
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001287 if (HIWORD(className))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001288 {
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001289 if (!(classAtom = GlobalFindAtomA( className )))
1290 {
Alexandre Julliard0aa28b52002-05-17 02:55:48 +00001291 ERR( "bad class name %s\n", debugstr_a(className) );
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001292 return 0;
1293 }
1294 }
1295 else
1296 {
1297 classAtom = LOWORD(className);
1298 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1299 {
1300 ERR( "bad atom %x\n", classAtom);
1301 return 0;
1302 }
1303 className = buffer;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001304 }
1305
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001306 /* Create the window */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001307
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001308 cs.lpCreateParams = data;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001309 cs.hInstance = instance;
1310 cs.hMenu = menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001311 cs.hwndParent = parent;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001312 cs.x = x;
1313 cs.y = y;
1314 cs.cx = width;
1315 cs.cy = height;
1316 cs.style = style;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001317 cs.lpszName = windowName;
1318 cs.lpszClass = className;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001319 cs.dwExStyle = exStyle;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001320
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001321 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001322}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001323
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001324
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001325/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001326 * CreateWindowExW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001327 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001328HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1329 LPCWSTR windowName, DWORD style, INT x,
1330 INT y, INT width, INT height,
1331 HWND parent, HMENU menu,
1332 HINSTANCE instance, LPVOID data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001333{
1334 ATOM classAtom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001335 CREATESTRUCTW cs;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001336 WCHAR buffer[256];
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001337
Rein Klazesd4a2cee1999-10-23 13:57:36 +00001338 if(!instance)
1339 instance=GetModuleHandleA(NULL);
1340
Rein Klazes5c6fc1b1998-11-01 14:50:06 +00001341 if(exStyle & WS_EX_MDICHILD)
Dmitry Timoshkov91adf0a2001-02-12 03:40:41 +00001342 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
Rein Klazes5c6fc1b1998-11-01 14:50:06 +00001343
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001344 /* Find the class atom */
1345
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001346 if (HIWORD(className))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001347 {
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001348 if (!(classAtom = GlobalFindAtomW( className )))
1349 {
Alexandre Julliard0aa28b52002-05-17 02:55:48 +00001350 ERR( "bad class name %s\n", debugstr_w(className) );
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001351 return 0;
1352 }
1353 }
1354 else
1355 {
1356 classAtom = LOWORD(className);
1357 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1358 {
1359 ERR( "bad atom %x\n", classAtom);
1360 return 0;
1361 }
1362 className = buffer;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001363 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001364
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001365 /* Create the window */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001366
1367 cs.lpCreateParams = data;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001368 cs.hInstance = instance;
1369 cs.hMenu = menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001370 cs.hwndParent = parent;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001371 cs.x = x;
1372 cs.y = y;
1373 cs.cx = width;
1374 cs.cy = height;
1375 cs.style = style;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001376 cs.lpszName = windowName;
1377 cs.lpszClass = className;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001378 cs.dwExStyle = exStyle;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001379
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001380 /* Note: we rely on the fact that CREATESTRUCTA and */
1381 /* CREATESTRUCTW have the same layout. */
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001382 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
Alexandre Julliard401710d1993-09-04 10:09:32 +00001383}
1384
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001385
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001386/***********************************************************************
1387 * WIN_SendDestroyMsg
1388 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001389static void WIN_SendDestroyMsg( HWND hwnd )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001390{
Alexandre Julliard11e35232002-10-17 01:24:33 +00001391 GUITHREADINFO info;
1392
1393 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1394 {
1395 if (hwnd == info.hwndCaret) DestroyCaret();
1396 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00001397 if (USER_Driver.pResetSelectionOwner)
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001398 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001399
1400 /*
1401 * Send the WM_DESTROY to the window.
1402 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001403 SendMessageA( hwnd, WM_DESTROY, 0, 0);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001404
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001405 /*
1406 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1407 * make sure that the window still exists when we come back.
1408 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001409 if (IsWindow(hwnd))
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001410 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001411 HWND* pWndArray;
1412 int i;
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001413
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00001414 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001415
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001416 /* start from the end (FIXME: is this needed?) */
1417 for (i = 0; pWndArray[i]; i++) ;
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001418
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001419 while (--i >= 0)
1420 {
1421 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1422 }
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00001423 HeapFree( GetProcessHeap(), 0, pWndArray );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001424 }
1425 else
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001426 WARN("\tdestroyed itself while in WM_DESTROY!\n");
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001427}
1428
1429
1430/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001431 * DestroyWindow (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00001432 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001433BOOL WINAPI DestroyWindow( HWND hwnd )
Alexandre Julliard401710d1993-09-04 10:09:32 +00001434{
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001435 BOOL is_child;
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001436 HWND h;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +00001437
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001438 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1439 {
1440 SetLastError( ERROR_ACCESS_DENIED );
1441 return FALSE;
1442 }
1443
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001444 TRACE("(%04x)\n", hwnd);
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001445
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001446 /* Look whether the focus is within the tree of windows we will
1447 * be destroying.
1448 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001449 h = GetFocus();
1450 if (h == hwnd || IsChild( hwnd, h ))
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001451 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001452 HWND parent = GetAncestor( hwnd, GA_PARENT );
1453 if (parent == GetDesktopWindow()) parent = 0;
1454 SetFocus( parent );
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001455 }
1456
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001457 /* Call hooks */
1458
Alexandre Julliard02861352002-10-29 00:41:42 +00001459 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001460
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001461 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1462
1463 if (is_child)
1464 {
1465 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1466 send_parent_notify( hwnd, WM_DESTROY );
1467 }
1468 else if (!GetWindow( hwnd, GW_OWNER ))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001469 {
Alexandre Julliard02861352002-10-29 00:41:42 +00001470 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001471 /* FIXME: clean up palette - see "Internals" p.352 */
1472 }
1473
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001474 if (!IsWindow(hwnd)) return TRUE;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001475
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00001476 if (USER_Driver.pResetSelectionOwner)
1477 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001478
Alexandre Julliard58199531994-04-21 01:20:00 +00001479 /* Hide the window */
1480
Alexandre Julliard5030bda2002-10-11 23:41:06 +00001481 if (!ShowWindow( hwnd, SW_HIDE ))
1482 {
1483 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1484 }
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001485 if (!IsWindow(hwnd)) return TRUE;
Alexandre Julliard0e607781993-11-03 19:23:37 +00001486
Alexandre Julliard22945d51995-03-02 17:44:29 +00001487 /* Recursively destroy owned windows */
1488
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001489 if (!is_child)
Alexandre Julliard22945d51995-03-02 17:44:29 +00001490 {
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001491 for (;;)
1492 {
1493 int i, got_one = 0;
1494 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1495 if (list)
1496 {
1497 for (i = 0; list[i]; i++)
1498 {
1499 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1500 if (WIN_IsCurrentThread( list[i] ))
1501 {
1502 DestroyWindow( list[i] );
1503 got_one = 1;
1504 continue;
1505 }
1506 WIN_SetOwner( list[i], 0 );
1507 }
1508 HeapFree( GetProcessHeap(), 0, list );
1509 }
1510 if (!got_one) break;
1511 }
Alexandre Julliard22945d51995-03-02 17:44:29 +00001512 }
1513
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001514 /* Send destroy messages */
Alexandre Julliard0e607781993-11-03 19:23:37 +00001515
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001516 WIN_SendDestroyMsg( hwnd );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001517 if (!IsWindow( hwnd )) return TRUE;
Alexandre Julliard401710d1993-09-04 10:09:32 +00001518
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001519 /* Unlink now so we won't bother with the children later on */
Alexandre Julliard401710d1993-09-04 10:09:32 +00001520
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001521 WIN_UnlinkWindow( hwnd );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001522
1523 /* Destroy the window storage */
1524
Alexandre Julliard80593bf2001-10-11 20:49:40 +00001525 WIN_DestroyWindow( hwnd );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001526 return TRUE;
Alexandre Julliard401710d1993-09-04 10:09:32 +00001527}
1528
1529
1530/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001531 * CloseWindow (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001532 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001533BOOL WINAPI CloseWindow( HWND hwnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001534{
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001535 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001536 ShowWindow( hwnd, SW_MINIMIZE );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001537 return TRUE;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001538}
1539
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001540
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001541/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001542 * OpenIcon (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001543 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001544BOOL WINAPI OpenIcon( HWND hwnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001545{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001546 if (!IsIconic( hwnd )) return FALSE;
1547 ShowWindow( hwnd, SW_SHOWNORMAL );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001548 return TRUE;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001549}
1550
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001551
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001552/***********************************************************************
1553 * WIN_FindWindow
1554 *
1555 * Implementation of FindWindow() and FindWindowEx().
1556 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001557static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001558{
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001559 HWND *list = NULL;
1560 HWND retvalue = 0;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001561 int i = 0, len = 0;
1562 WCHAR *buffer = NULL;
1563
1564 if (!parent) parent = GetDesktopWindow();
1565 if (title)
1566 {
1567 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1568 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1569 }
1570
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001571 if (!(list = list_window_children( parent, className, 0 ))) goto done;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001572
1573 if (child)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001574 {
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00001575 child = WIN_GetFullHandle( child );
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001576 while (list[i] && list[i] != child) i++;
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001577 if (!list[i]) goto done;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001578 i++; /* start from next window */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001579 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001580
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001581 if (title)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001582 {
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001583 while (list[i])
1584 {
1585 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1586 i++;
1587 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001588 }
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001589 retvalue = list[i];
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001590
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001591 done:
1592 if (list) HeapFree( GetProcessHeap(), 0, list );
1593 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001594 return retvalue;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001595}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001596
1597
1598
1599/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001600 * FindWindowA (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001601 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001602HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001603{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001604 HWND ret = FindWindowExA( 0, 0, className, title );
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001605 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1606 return ret;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001607}
1608
1609
1610/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001611 * FindWindowExA (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001612 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001613HWND WINAPI FindWindowExA( HWND parent, HWND child,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001614 LPCSTR className, LPCSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001615{
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001616 ATOM atom = 0;
Dmitry Timoshkov04da8b82000-07-10 12:09:31 +00001617 LPWSTR buffer;
1618 HWND hwnd;
Alexandre Julliard193cf502002-01-01 00:24:30 +00001619 INT len;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001620
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001621 if (className)
1622 {
1623 /* If the atom doesn't exist, then no class */
1624 /* with this name exists either. */
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001625 if (!(atom = GlobalFindAtomA( className )))
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001626 {
1627 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1628 return 0;
1629 }
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001630 }
Alexandre Julliard193cf502002-01-01 00:24:30 +00001631 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
Dmitry Timoshkov04da8b82000-07-10 12:09:31 +00001632
Alexandre Julliard193cf502002-01-01 00:24:30 +00001633 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1634 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1635 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
Dmitry Timoshkov04da8b82000-07-10 12:09:31 +00001636 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1637 HeapFree( GetProcessHeap(), 0, buffer );
1638 return hwnd;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001639}
1640
1641
1642/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001643 * FindWindowExW (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001644 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001645HWND WINAPI FindWindowExW( HWND parent, HWND child,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001646 LPCWSTR className, LPCWSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001647{
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001648 ATOM atom = 0;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001649
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001650 if (className)
1651 {
1652 /* If the atom doesn't exist, then no class */
1653 /* with this name exists either. */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001654 if (!(atom = GlobalFindAtomW( className )))
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001655 {
1656 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1657 return 0;
1658 }
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001659 }
Dmitry Timoshkov04da8b82000-07-10 12:09:31 +00001660 return WIN_FindWindow( parent, child, atom, title );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001661}
1662
1663
1664/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001665 * FindWindowW (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001666 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001667HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001668{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001669 return FindWindowExW( 0, 0, className, title );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001670}
1671
1672
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001673/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001674 * GetDesktopWindow (USER32.@)
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001675 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001676HWND WINAPI GetDesktopWindow(void)
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001677{
Uwe Bonnes73619161999-10-24 20:42:39 +00001678 if (pWndDesktop) return pWndDesktop->hwndSelf;
Gerard Patele717b1b2001-11-19 02:07:11 +00001679 ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
Uwe Bonnes73619161999-10-24 20:42:39 +00001680 ExitProcess(1);
Huw D M Davies238b6d71999-10-31 01:56:51 +00001681 return 0;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001682}
1683
1684
Alexandre Julliard01d63461997-01-20 19:43:45 +00001685/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001686 * EnableWindow (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00001687 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001688BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001689{
1690 WND *wndPtr;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001691 BOOL retvalue;
Alexandre Julliardddc33172001-10-22 19:08:33 +00001692 LONG style;
1693 HWND full_handle;
1694
1695 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1696 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1697
1698 hwnd = full_handle;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001699
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001700 TRACE("( %x, %d )\n", hwnd, enable);
1701
Alexandre Julliardddc33172001-10-22 19:08:33 +00001702 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1703 style = wndPtr->dwStyle;
1704 retvalue = ((style & WS_DISABLED) != 0);
1705 WIN_ReleasePtr( wndPtr );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001706
Alexandre Julliardddc33172001-10-22 19:08:33 +00001707 if (enable && retvalue)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001708 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00001709 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001710 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001711 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001712 else if (!enable && !retvalue)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001713 {
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00001714 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
Alex Korobka4f1ac051999-03-28 09:37:57 +00001715
Alexandre Julliardddc33172001-10-22 19:08:33 +00001716 WIN_SetStyle( hwnd, style | WS_DISABLED );
Alex Korobka4f1ac051999-03-28 09:37:57 +00001717
Alexandre Julliard481f8ff2002-04-08 23:57:08 +00001718 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001719 SetFocus( 0 ); /* A disabled window can't have the focus */
Alex Korobka4f1ac051999-03-28 09:37:57 +00001720
Alexandre Julliard481f8ff2002-04-08 23:57:08 +00001721 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001722 ReleaseCapture(); /* A disabled window can't capture the mouse */
1723
1724 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001725 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001726 return retvalue;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001727}
1728
1729
1730/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001731 * IsWindowEnabled (USER32.@)
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001732 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001733BOOL WINAPI IsWindowEnabled(HWND hWnd)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001734{
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001735 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001736}
1737
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001738
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001739/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001740 * IsWindowUnicode (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001741 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001742BOOL WINAPI IsWindowUnicode( HWND hwnd )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001743{
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001744 WND * wndPtr;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001745 BOOL retvalue;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001746
1747 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001748 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1749 WIN_ReleaseWndPtr(wndPtr);
1750 return retvalue;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001751}
1752
1753
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001754/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001755 * GetWindowWord (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00001756 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001757WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001758{
Alexandre Julliard3051b641996-07-05 17:14:13 +00001759 if (offset >= 0)
1760 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00001761 WORD retvalue = 0;
1762 WND *wndPtr = WIN_GetPtr( hwnd );
1763 if (!wndPtr)
1764 {
1765 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1766 return 0;
1767 }
1768 if (wndPtr == WND_OTHER_PROCESS)
1769 {
1770 if (IsWindow( hwnd ))
1771 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1772 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1773 return 0;
1774 }
1775 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
Alexandre Julliard3051b641996-07-05 17:14:13 +00001776 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001777 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001778 SetLastError( ERROR_INVALID_INDEX );
Alexandre Julliard3051b641996-07-05 17:14:13 +00001779 }
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001780 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
Alexandre Julliardddc33172001-10-22 19:08:33 +00001781 WIN_ReleasePtr( wndPtr );
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001782 return retvalue;
Alexandre Julliard3051b641996-07-05 17:14:13 +00001783 }
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001784
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001785 switch(offset)
1786 {
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001787 case GWL_HWNDPARENT:
1788 return GetWindowLongW( hwnd, offset );
1789 case GWL_ID:
1790 case GWL_HINSTANCE:
1791 {
1792 LONG ret = GetWindowLongW( hwnd, offset );
1793 if (HIWORD(ret))
1794 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1795 return LOWORD(ret);
1796 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001797 default:
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001798 WARN("Invalid offset %d\n", offset );
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001799 return 0;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001800 }
Alexandre Julliard21979011997-03-05 08:22:35 +00001801}
1802
1803
1804/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001805 * SetWindowWord (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00001806 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001807WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001808{
1809 WORD *ptr, retval;
Alexandre Julliardddc33172001-10-22 19:08:33 +00001810 WND * wndPtr;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001811
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001812 switch(offset)
1813 {
1814 case GWL_ID:
1815 case GWL_HINSTANCE:
1816 case GWL_HWNDPARENT:
1817 return SetWindowLongW( hwnd, offset, (UINT)newval );
1818 default:
Alexandre Julliardddc33172001-10-22 19:08:33 +00001819 if (offset < 0)
1820 {
1821 WARN("Invalid offset %d\n", offset );
1822 SetLastError( ERROR_INVALID_INDEX );
1823 return 0;
1824 }
1825 }
1826
1827 wndPtr = WIN_GetPtr( hwnd );
1828 if (wndPtr == WND_OTHER_PROCESS)
1829 {
1830 if (IsWindow(hwnd))
1831 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1832 offset, newval, hwnd );
1833 wndPtr = NULL;
1834 }
1835 if (!wndPtr)
1836 {
1837 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1838 return 0;
1839 }
1840
1841 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1842 {
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001843 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001844 WIN_ReleasePtr(wndPtr);
1845 SetLastError( ERROR_INVALID_INDEX );
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001846 return 0;
1847 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001848 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1849 retval = *ptr;
1850 *ptr = newval;
1851 WIN_ReleasePtr(wndPtr);
1852 return retval;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001853}
1854
1855
1856/**********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +00001857 * WIN_GetWindowLong
1858 *
1859 * Helper function for GetWindowLong().
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001860 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001861static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001862{
Alexandre Julliardddc33172001-10-22 19:08:33 +00001863 LONG retvalue = 0;
1864 WND *wndPtr;
1865
Alexandre Julliard7dafa612002-09-25 00:21:56 +00001866 if (offset == GWL_HWNDPARENT)
1867 {
1868 HWND parent = GetAncestor( hwnd, GA_PARENT );
1869 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1870 return (LONG)parent;
1871 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001872
1873 if (!(wndPtr = WIN_GetPtr( hwnd )))
1874 {
1875 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1876 return 0;
1877 }
1878
1879 if (wndPtr == WND_OTHER_PROCESS)
1880 {
1881 if (offset >= 0)
1882 {
Alexandre Julliard96ebfa92001-10-23 20:35:44 +00001883 if (IsWindow(hwnd))
1884 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001885 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1886 return 0;
1887 }
1888 if (offset == GWL_WNDPROC)
1889 {
1890 SetLastError( ERROR_ACCESS_DENIED );
1891 return 0;
1892 }
1893 SERVER_START_REQ( set_window_info )
1894 {
1895 req->handle = hwnd;
1896 req->flags = 0; /* don't set anything, just retrieve */
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00001897 if (!wine_server_call_err( req ))
Alexandre Julliardddc33172001-10-22 19:08:33 +00001898 {
1899 switch(offset)
1900 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00001901 case GWL_STYLE: retvalue = reply->old_style; break;
1902 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1903 case GWL_ID: retvalue = reply->old_id; break;
1904 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1905 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
Alexandre Julliardddc33172001-10-22 19:08:33 +00001906 default:
1907 SetLastError( ERROR_INVALID_INDEX );
1908 break;
1909 }
1910 }
1911 }
1912 SERVER_END_REQ;
1913 return retvalue;
1914 }
1915
1916 /* now we have a valid wndPtr */
1917
Alexandre Julliard3051b641996-07-05 17:14:13 +00001918 if (offset >= 0)
1919 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00001920 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
Alexandre Julliard3051b641996-07-05 17:14:13 +00001921 {
Jukka Heinonen3fead8f2002-02-15 18:22:23 +00001922 /*
1923 * Some programs try to access last element from 16 bit
1924 * code using illegal offset value. Hopefully this is
1925 * what those programs really expect.
1926 */
Vincent Béron9a624912002-05-31 23:06:46 +00001927 if (type == WIN_PROC_16 &&
Jukka Heinonen3fead8f2002-02-15 18:22:23 +00001928 wndPtr->cbWndExtra >= 4 &&
1929 offset == wndPtr->cbWndExtra - sizeof(WORD))
1930 {
1931 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
Vincent Béron9a624912002-05-31 23:06:46 +00001932
Jukka Heinonen3fead8f2002-02-15 18:22:23 +00001933 ERR( "- replaced invalid offset %d with %d\n",
1934 offset, offset2 );
Vincent Béron9a624912002-05-31 23:06:46 +00001935
Jukka Heinonen3fead8f2002-02-15 18:22:23 +00001936 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1937 WIN_ReleasePtr( wndPtr );
1938 return retvalue;
1939 }
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001940 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001941 WIN_ReleasePtr( wndPtr );
1942 SetLastError( ERROR_INVALID_INDEX );
1943 return 0;
Alexandre Julliard3051b641996-07-05 17:14:13 +00001944 }
Gerard Patele717b1b2001-11-19 02:07:11 +00001945 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
Alexandre Julliard3051b641996-07-05 17:14:13 +00001946 /* Special case for dialog window procedure */
1947 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001948 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001949 WIN_ReleasePtr( wndPtr );
1950 return retvalue;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001951 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001952
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001953 switch(offset)
1954 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00001955 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1956 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1957 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1958 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1959 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1960 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1961 default:
1962 WARN("Unknown offset %d\n", offset );
1963 SetLastError( ERROR_INVALID_INDEX );
1964 break;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001965 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001966 WIN_ReleasePtr(wndPtr);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001967 return retvalue;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001968}
1969
1970
1971/**********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +00001972 * WIN_SetWindowLong
1973 *
1974 * Helper function for SetWindowLong().
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001975 *
1976 * 0 is the failure code. However, in the case of failure SetLastError
1977 * must be set to distinguish between a 0 return value and a failure.
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001978 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001979static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
Alexandre Julliard3051b641996-07-05 17:14:13 +00001980 WINDOWPROCTYPE type )
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001981{
Alexandre Julliardddc33172001-10-22 19:08:33 +00001982 LONG retval = 0;
1983 WND *wndPtr;
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001984
Alexandre Julliardddc33172001-10-22 19:08:33 +00001985 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001986
Alexandre Julliard55557312001-10-23 00:26:10 +00001987 if (!WIN_IsCurrentProcess( hwnd ))
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001988 {
Alexandre Julliard55557312001-10-23 00:26:10 +00001989 if (offset == GWL_WNDPROC)
1990 {
1991 SetLastError( ERROR_ACCESS_DENIED );
1992 return 0;
1993 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001994 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001995 }
1996
Alexandre Julliardddc33172001-10-22 19:08:33 +00001997 wndPtr = WIN_GetPtr( hwnd );
Alexandre Julliard7dafa612002-09-25 00:21:56 +00001998 if (wndPtr->hwndSelf == GetDesktopWindow())
1999 {
2000 /* can't change anything on the desktop window */
Alexandre Julliard02b8cb72002-09-25 03:25:43 +00002001 WIN_ReleasePtr( wndPtr );
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002002 SetLastError( ERROR_ACCESS_DENIED );
2003 return 0;
2004 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002005
Alexandre Julliard3051b641996-07-05 17:14:13 +00002006 if (offset >= 0)
2007 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00002008 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2009 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
Alexandre Julliard3051b641996-07-05 17:14:13 +00002010 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00002011 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002012 WIN_ReleasePtr( wndPtr );
2013 SetLastError( ERROR_INVALID_INDEX );
2014 return 0;
Alexandre Julliard3051b641996-07-05 17:14:13 +00002015 }
Alexandre Julliard3051b641996-07-05 17:14:13 +00002016 /* Special case for dialog window procedure */
2017 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2018 {
2019 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002020 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002021 type, WIN_PROC_WINDOW );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002022 WIN_ReleasePtr( wndPtr );
2023 return retval;
Alexandre Julliard3051b641996-07-05 17:14:13 +00002024 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002025 retval = *ptr;
2026 *ptr = newval;
2027 WIN_ReleasePtr( wndPtr );
Alexandre Julliard3051b641996-07-05 17:14:13 +00002028 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002029 else
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002030 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00002031 STYLESTRUCT style;
2032 BOOL ok;
2033
2034 /* first some special cases */
2035 switch( offset )
2036 {
2037 case GWL_STYLE:
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002038 case GWL_EXSTYLE:
Alexandre Julliardddc33172001-10-22 19:08:33 +00002039 style.styleOld = wndPtr->dwStyle;
2040 style.styleNew = newval;
2041 WIN_ReleasePtr( wndPtr );
2042 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2043 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2044 newval = style.styleNew;
2045 break;
2046 case GWL_HWNDPARENT:
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002047 if (wndPtr->parent == GetDesktopWindow())
2048 {
2049 WIN_ReleasePtr( wndPtr );
2050 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2051 }
2052 else
2053 {
2054 WIN_ReleasePtr( wndPtr );
2055 return (LONG)SetParent( hwnd, (HWND)newval );
2056 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002057 case GWL_WNDPROC:
2058 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2059 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2060 type, WIN_PROC_WINDOW );
2061 WIN_ReleasePtr( wndPtr );
2062 return retval;
2063 case GWL_ID:
2064 case GWL_HINSTANCE:
2065 case GWL_USERDATA:
2066 break;
2067 default:
2068 WIN_ReleasePtr( wndPtr );
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00002069 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002070 SetLastError( ERROR_INVALID_INDEX );
2071 return 0;
2072 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002073
Alexandre Julliardddc33172001-10-22 19:08:33 +00002074 SERVER_START_REQ( set_window_info )
2075 {
2076 req->handle = hwnd;
2077 switch(offset)
2078 {
2079 case GWL_STYLE:
2080 req->flags = SET_WIN_STYLE;
2081 req->style = newval;
2082 break;
2083 case GWL_EXSTYLE:
2084 req->flags = SET_WIN_EXSTYLE;
2085 req->ex_style = newval;
2086 break;
2087 case GWL_ID:
2088 req->flags = SET_WIN_ID;
2089 req->id = newval;
2090 break;
2091 case GWL_HINSTANCE:
2092 req->flags = SET_WIN_INSTANCE;
2093 req->instance = (void *)newval;
2094 break;
2095 case GWL_USERDATA:
2096 req->flags = SET_WIN_USERDATA;
2097 req->user_data = (void *)newval;
2098 break;
2099 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002100 if ((ok = !wine_server_call_err( req )))
Alexandre Julliardddc33172001-10-22 19:08:33 +00002101 {
2102 switch(offset)
2103 {
2104 case GWL_STYLE:
2105 wndPtr->dwStyle = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002106 retval = reply->old_style;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002107 break;
2108 case GWL_EXSTYLE:
2109 wndPtr->dwExStyle = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002110 retval = reply->old_ex_style;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002111 break;
2112 case GWL_ID:
2113 wndPtr->wIDmenu = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002114 retval = reply->old_id;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002115 break;
2116 case GWL_HINSTANCE:
2117 wndPtr->hInstance = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002118 retval = (HINSTANCE)reply->old_instance;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002119 break;
2120 case GWL_USERDATA:
2121 wndPtr->userdata = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002122 retval = (ULONG_PTR)reply->old_user_data;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002123 break;
2124 }
2125 }
2126 }
2127 SERVER_END_REQ;
2128 WIN_ReleasePtr( wndPtr );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002129
Alexandre Julliardddc33172001-10-22 19:08:33 +00002130 if (!ok) return 0;
2131
2132 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2133 USER_Driver.pSetWindowStyle( hwnd, retval );
2134
2135 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2136 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2137
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002138 }
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002139 return retval;
2140}
2141
2142
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002143/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002144 * GetWindowLong (USER.135)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002145 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002146LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002147{
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00002148 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
Alexandre Julliard3051b641996-07-05 17:14:13 +00002149}
2150
2151
2152/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002153 * GetWindowLongA (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002154 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002155LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002156{
2157 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2158}
2159
2160
2161/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002162 * GetWindowLongW (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002163 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002164LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002165{
2166 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2167}
2168
2169
2170/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002171 * SetWindowLong (USER.136)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002172 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002173LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002174{
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00002175 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
Alexandre Julliard3051b641996-07-05 17:14:13 +00002176}
2177
2178
2179/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002180 * SetWindowLongA (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002181 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002182LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002183{
2184 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2185}
2186
2187
2188/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002189 * SetWindowLongW (USER32.@) Set window attribute
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002190 *
2191 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002192 * value in a window's extra memory.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002193 *
2194 * The _hwnd_ parameter specifies the window. is the handle to a
2195 * window that has extra memory. The _newval_ parameter contains the
2196 * new attribute or extra memory value. If positive, the _offset_
2197 * parameter is the byte-addressed location in the window's extra
2198 * memory to set. If negative, _offset_ specifies the window
2199 * attribute to set, and should be one of the following values:
2200 *
2201 * GWL_EXSTYLE The window's extended window style
2202 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002203 * GWL_STYLE The window's window style.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002204 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002205 * GWL_WNDPROC Pointer to the window's window procedure.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002206 *
2207 * GWL_HINSTANCE The window's pplication instance handle.
2208 *
2209 * GWL_ID The window's identifier.
2210 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002211 * GWL_USERDATA The window's user-specified data.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002212 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002213 * If the window is a dialog box, the _offset_ parameter can be one of
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002214 * the following values:
2215 *
2216 * DWL_DLGPROC The address of the window's dialog box procedure.
2217 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002218 * DWL_MSGRESULT The return value of a message
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002219 * that the dialog box procedure processed.
2220 *
2221 * DWL_USER Application specific information.
2222 *
2223 * RETURNS
2224 *
2225 * If successful, returns the previous value located at _offset_. Otherwise,
2226 * returns 0.
2227 *
2228 * NOTES
2229 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002230 * Extra memory for a window class is specified by a nonzero cbWndExtra
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002231 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2232 * time of class creation.
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002233 *
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002234 * Using GWL_WNDPROC to set a new window procedure effectively creates
2235 * a window subclass. Use CallWindowProc() in the new windows procedure
2236 * to pass messages to the superclass's window procedure.
2237 *
2238 * The user data is reserved for use by the application which created
2239 * the window.
2240 *
Gerard Patele717b1b2001-11-19 02:07:11 +00002241 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002242 * instead, call the EnableWindow() function to change the window's
2243 * disabled state.
2244 *
2245 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2246 * SetParent() instead.
2247 *
Alexandre Julliard638f1691999-01-17 16:32:32 +00002248 * Win95:
2249 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2250 * it sends WM_STYLECHANGING before changing the settings
2251 * and WM_STYLECHANGED afterwards.
2252 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002253 */
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002254LONG WINAPI SetWindowLongW(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00002255 HWND hwnd, /* [in] window to alter */
2256 INT offset, /* [in] offset, in bytes, of location to alter */
2257 LONG newval /* [in] new value of location */
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002258) {
Alexandre Julliard3051b641996-07-05 17:14:13 +00002259 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002260}
2261
2262
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002263/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002264 * GetWindowTextA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002265 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002266INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002267{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002268 WCHAR *buffer;
2269
2270 if (WIN_IsCurrentProcess( hwnd ))
2271 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2272
2273 /* when window belongs to other process, don't send a message */
2274 if (nMaxCount <= 0) return 0;
2275 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2276 get_server_window_text( hwnd, buffer, nMaxCount );
2277 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2278 lpString[nMaxCount-1] = 0;
2279 HeapFree( GetProcessHeap(), 0, buffer );
2280 return strlen(lpString);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002281}
2282
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002283
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002284/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002285 * InternalGetWindowText (USER32.@)
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002286 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002287INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002288{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002289 WND *win;
2290
2291 if (nMaxCount <= 0) return 0;
2292 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2293 if (win != WND_OTHER_PROCESS)
2294 {
2295 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2296 else lpString[0] = 0;
2297 WIN_ReleasePtr( win );
2298 }
2299 else
2300 {
2301 get_server_window_text( hwnd, lpString, nMaxCount );
2302 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00002303 return strlenW(lpString);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002304}
2305
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002306
2307/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002308 * GetWindowTextW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002309 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002310INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002311{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002312 if (WIN_IsCurrentProcess( hwnd ))
2313 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2314
2315 /* when window belongs to other process, don't send a message */
2316 if (nMaxCount <= 0) return 0;
2317 get_server_window_text( hwnd, lpString, nMaxCount );
2318 return strlenW(lpString);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002319}
2320
2321
2322/*******************************************************************
Patrik Stridvall17fd4e32001-06-28 18:04:41 +00002323 * SetWindowText (USER32.@)
2324 * SetWindowTextA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002325 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002326BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002327{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002328 if (!WIN_IsCurrentProcess( hwnd ))
2329 {
2330 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2331 SetLastError( ERROR_ACCESS_DENIED );
2332 return FALSE;
2333 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002334 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002335}
2336
2337
2338/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002339 * SetWindowTextW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002340 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002341BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002342{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002343 if (!WIN_IsCurrentProcess( hwnd ))
2344 {
2345 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2346 SetLastError( ERROR_ACCESS_DENIED );
2347 return FALSE;
2348 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002349 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002350}
2351
2352
Alexandre Julliard0e607781993-11-03 19:23:37 +00002353/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002354 * GetWindowTextLengthA (USER32.@)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002355 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002356INT WINAPI GetWindowTextLengthA( HWND hwnd )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002357{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002358 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002359}
2360
2361/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002362 * GetWindowTextLengthW (USER32.@)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002363 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002364INT WINAPI GetWindowTextLengthW( HWND hwnd )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002365{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002366 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002367}
2368
Alexandre Julliard21979011997-03-05 08:22:35 +00002369
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002370/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002371 * IsWindow (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00002372 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002373BOOL WINAPI IsWindow( HWND hwnd )
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002374{
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002375 WND *ptr;
Alexandre Julliard37a46392001-09-12 17:19:13 +00002376 BOOL ret;
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002377
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002378 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2379
2380 if (ptr != WND_OTHER_PROCESS)
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002381 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002382 WIN_ReleasePtr( ptr );
Alexandre Julliard7695d692001-09-24 01:19:59 +00002383 return TRUE;
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002384 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002385
Alexandre Julliard37a46392001-09-12 17:19:13 +00002386 /* check other processes */
2387 SERVER_START_REQ( get_window_info )
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002388 {
Alexandre Julliard37a46392001-09-12 17:19:13 +00002389 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002390 ret = !wine_server_call_err( req );
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002391 }
Alexandre Julliard37a46392001-09-12 17:19:13 +00002392 SERVER_END_REQ;
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002393 return ret;
2394}
2395
2396
2397/***********************************************************************
2398 * GetWindowThreadProcessId (USER32.@)
2399 */
2400DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2401{
2402 WND *ptr;
2403 DWORD tid = 0;
2404
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002405 if (!(ptr = WIN_GetPtr( hwnd )))
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002406 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002407 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2408 return 0;
2409 }
2410
2411 if (ptr != WND_OTHER_PROCESS)
2412 {
2413 /* got a valid window */
2414 tid = ptr->tid;
2415 if (process) *process = GetCurrentProcessId();
2416 WIN_ReleasePtr( ptr );
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002417 return tid;
2418 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002419
2420 /* check other processes */
2421 SERVER_START_REQ( get_window_info )
2422 {
2423 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002424 if (!wine_server_call_err( req ))
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002425 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002426 tid = (DWORD)reply->tid;
2427 if (process) *process = (DWORD)reply->pid;
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002428 }
2429 }
2430 SERVER_END_REQ;
2431 return tid;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002432}
2433
2434
2435/*****************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002436 * GetParent (USER32.@)
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +00002437 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002438HWND WINAPI GetParent( HWND hwnd )
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002439{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002440 WND *wndPtr;
Andreas Mohr1c20b392000-02-20 19:17:35 +00002441 HWND retvalue = 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002442
Alexandre Julliardddc33172001-10-22 19:08:33 +00002443 if (!(wndPtr = WIN_GetPtr( hwnd )))
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002444 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00002445 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2446 return 0;
2447 }
2448 if (wndPtr == WND_OTHER_PROCESS)
2449 {
2450 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2451 if (style & (WS_POPUP | WS_CHILD))
2452 {
2453 SERVER_START_REQ( get_window_tree )
2454 {
2455 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002456 if (!wine_server_call_err( req ))
Alexandre Julliardddc33172001-10-22 19:08:33 +00002457 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002458 if (style & WS_POPUP) retvalue = reply->owner;
2459 else if (style & WS_CHILD) retvalue = reply->parent;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002460 }
2461 }
2462 SERVER_END_REQ;
2463 }
2464 }
2465 else
2466 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002467 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2468 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002469 WIN_ReleasePtr( wndPtr );
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002470 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002471 return retvalue;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002472}
2473
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002474
2475/*****************************************************************
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002476 * GetAncestor (USER32.@)
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002477 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002478HWND WINAPI GetAncestor( HWND hwnd, UINT type )
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002479{
Alexandre Julliardddc33172001-10-22 19:08:33 +00002480 WND *win;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002481 HWND *list, ret = 0;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002482
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002483 switch(type)
Alexandre Julliardddc33172001-10-22 19:08:33 +00002484 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002485 case GA_PARENT:
Alexandre Julliardddc33172001-10-22 19:08:33 +00002486 if (!(win = WIN_GetPtr( hwnd )))
2487 {
2488 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2489 return 0;
2490 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002491 if (win != WND_OTHER_PROCESS)
Alexandre Julliardddc33172001-10-22 19:08:33 +00002492 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002493 ret = win->parent;
2494 WIN_ReleasePtr( win );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002495 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002496 else /* need to query the server */
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002497 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002498 SERVER_START_REQ( get_window_tree )
Alexandre Julliard556607a2001-10-10 20:28:17 +00002499 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002500 req->handle = hwnd;
2501 if (!wine_server_call_err( req )) ret = reply->parent;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002502 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002503 SERVER_END_REQ;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002504 }
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002505 break;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002506
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002507 case GA_ROOT:
2508 if (!(list = WIN_ListParents( hwnd ))) return 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002509
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002510 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2511 else
2512 {
2513 int count = 2;
2514 while (list[count]) count++;
2515 ret = list[count - 2]; /* get the one before the desktop */
2516 }
2517 HeapFree( GetProcessHeap(), 0, list );
2518 break;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002519
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002520 case GA_ROOTOWNER:
2521 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002522 for (;;)
2523 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002524 HWND parent = GetParent( ret );
2525 if (!parent) break;
2526 ret = parent;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002527 }
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002528 break;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002529 }
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002530 return ret;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002531}
2532
2533
Alexandre Julliard940d58c1994-09-16 09:24:37 +00002534/*****************************************************************
Alexandre Julliardddc33172001-10-22 19:08:33 +00002535 * SetParent (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002536 */
Alexandre Julliardddc33172001-10-22 19:08:33 +00002537HWND WINAPI SetParent( HWND hwnd, HWND parent )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002538{
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002539 WND *wndPtr;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002540 HWND retvalue, full_handle;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002541 BOOL was_visible;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002542
Alexandre Julliardddc33172001-10-22 19:08:33 +00002543 if (!parent) parent = GetDesktopWindow();
2544 else parent = WIN_GetFullHandle( parent );
2545
2546 if (!IsWindow( parent ))
2547 {
2548 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2549 return 0;
2550 }
2551
2552 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
Michael Stefaniuc2247af32002-09-04 19:37:01 +00002553 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002554
2555 hwnd = full_handle;
2556
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002557 if (USER_Driver.pSetParent)
2558 return USER_Driver.pSetParent( hwnd, parent );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002559
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002560 /* Windows hides the window first, then shows it again
2561 * including the WM_SHOWWINDOW messages and all */
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002562 was_visible = ShowWindow( hwnd, SW_HIDE );
2563
2564 if (!IsWindow( parent )) return 0;
2565 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00002566
Alexandre Julliard556607a2001-10-10 20:28:17 +00002567 retvalue = wndPtr->parent; /* old parent */
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002568 if (parent != retvalue)
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002569 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002570 WIN_LinkWindow( hwnd, parent, HWND_TOP );
Ove Kaaven72d8dbe1999-02-13 09:02:17 +00002571
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002572 if (parent != GetDesktopWindow()) /* a child window */
2573 {
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002574 if (!(wndPtr->dwStyle & WS_CHILD))
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002575 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002576 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2577 if (menu) DestroyMenu( menu );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002578 }
2579 }
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002580 }
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002581 WIN_ReleasePtr( wndPtr );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002582
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002583 /* SetParent additionally needs to make hwnd the topmost window
2584 in the x-order and send the expected WM_WINDOWPOSCHANGING and
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002585 WM_WINDOWPOSCHANGED notification messages.
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002586 */
2587 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002588 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002589 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2590 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2591 return retvalue;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00002592}
2593
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002594
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002595/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002596 * IsChild (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00002597 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002598BOOL WINAPI IsChild( HWND parent, HWND child )
Alexandre Julliard0e607781993-11-03 19:23:37 +00002599{
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002600 HWND *list = WIN_ListParents( child );
2601 int i;
2602 BOOL ret;
2603
2604 if (!list) return FALSE;
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00002605 parent = WIN_GetFullHandle( parent );
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002606 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2607 ret = (list[i] != 0);
2608 HeapFree( GetProcessHeap(), 0, list );
2609 return ret;
Alexandre Julliard0e607781993-11-03 19:23:37 +00002610}
2611
2612
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002613/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002614 * IsWindowVisible (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00002615 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002616BOOL WINAPI IsWindowVisible( HWND hwnd )
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002617{
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002618 HWND *list;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002619 BOOL retval;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002620 int i;
2621
2622 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2623 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2624 for (i = 0; list[i]; i++)
2625 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2626 retval = !list[i];
2627 HeapFree( GetProcessHeap(), 0, list );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002628 return retval;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002629}
2630
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002631
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002632/***********************************************************************
2633 * WIN_IsWindowDrawable
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002634 *
2635 * hwnd is drawable when it is visible, all parents are not
2636 * minimized, and it is itself not minimized unless we are
Alexandre Julliard23946ad1997-06-16 17:43:53 +00002637 * trying to draw its default class icon.
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002638 */
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002639BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002640{
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002641 HWND *list;
2642 BOOL retval;
2643 int i;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002644 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002645
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002646 if (!(style & WS_VISIBLE)) return FALSE;
2647 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002648
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002649 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002650 for (i = 0; list[i]; i++)
2651 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2652 break;
2653 retval = !list[i];
2654 HeapFree( GetProcessHeap(), 0, list );
2655 return retval;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002656}
2657
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002658
Alexandre Julliard0e607781993-11-03 19:23:37 +00002659/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002660 * GetTopWindow (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00002661 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002662HWND WINAPI GetTopWindow( HWND hwnd )
Alexandre Julliard0e607781993-11-03 19:23:37 +00002663{
Alexandre Julliardfa42aa82001-08-21 17:13:55 +00002664 if (!hwnd) hwnd = GetDesktopWindow();
2665 return GetWindow( hwnd, GW_CHILD );
Alexandre Julliard0e607781993-11-03 19:23:37 +00002666}
2667
2668
2669/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002670 * GetWindow (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00002671 */
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002672HWND WINAPI GetWindow( HWND hwnd, UINT rel )
Alexandre Julliard0e607781993-11-03 19:23:37 +00002673{
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002674 HWND retval = 0;
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002675
Alexandre Julliardddc33172001-10-22 19:08:33 +00002676 if (rel == GW_OWNER) /* this one may be available locally */
Alexandre Julliard0e607781993-11-03 19:23:37 +00002677 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00002678 WND *wndPtr = WIN_GetPtr( hwnd );
2679 if (!wndPtr)
2680 {
2681 SetLastError( ERROR_INVALID_HANDLE );
2682 return 0;
2683 }
2684 if (wndPtr != WND_OTHER_PROCESS)
2685 {
2686 retval = wndPtr->owner;
2687 WIN_ReleasePtr( wndPtr );
2688 return retval;
2689 }
2690 /* else fall through to server call */
Alexandre Julliard0e607781993-11-03 19:23:37 +00002691 }
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002692
2693 SERVER_START_REQ( get_window_tree )
2694 {
2695 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002696 if (!wine_server_call_err( req ))
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002697 {
2698 switch(rel)
2699 {
2700 case GW_HWNDFIRST:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002701 retval = reply->first_sibling;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002702 break;
2703 case GW_HWNDLAST:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002704 retval = reply->last_sibling;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002705 break;
2706 case GW_HWNDNEXT:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002707 retval = reply->next_sibling;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002708 break;
2709 case GW_HWNDPREV:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002710 retval = reply->prev_sibling;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002711 break;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002712 case GW_OWNER:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002713 retval = reply->owner;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002714 break;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002715 case GW_CHILD:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002716 retval = reply->first_child;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002717 break;
2718 }
2719 }
2720 }
2721 SERVER_END_REQ;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002722 return retval;
Alexandre Julliard0e607781993-11-03 19:23:37 +00002723}
2724
2725
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002726/***********************************************************************
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002727 * WIN_InternalShowOwnedPopups
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002728 *
2729 * Internal version of ShowOwnedPopups; Wine functions should use this
2730 * to avoid interfering with application calls to ShowOwnedPopups
2731 * and to make sure the application can't prevent showing/hiding.
2732 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002733 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002734 *
2735 */
2736
2737BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2738{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002739 int count = 0;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002740 WND *pWnd;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002741 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002742
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002743 if (!win_array) return TRUE;
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002744
2745 /*
2746 * Show windows Lowest first, Highest last to preserve Z-Order
2747 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002748 while (win_array[count]) count++;
2749 while (--count >= 0)
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002750 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002751 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2752 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002753
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002754 if (pWnd->dwStyle & WS_POPUP)
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002755 {
2756 if (fShow)
2757 {
2758 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002759 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002760 {
2761 /*
2762 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2763 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002764 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2765 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002766 }
2767 }
2768 else
2769 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002770 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2771 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2772 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002773 {
2774 /*
2775 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2776 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002777 ShowWindow(pWnd->hwndSelf,SW_HIDE);
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002778 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002779 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002780 }
2781 }
2782 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002783 WIN_ReleaseWndPtr( pWnd );
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002784 }
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002785 HeapFree( GetProcessHeap(), 0, win_array );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002786
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002787 return TRUE;
2788}
2789
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002790/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002791 * ShowOwnedPopups (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002792 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002793BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002794{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002795 int count = 0;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002796 WND *pWnd;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002797 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
Noomen Hamzaa018d851999-09-28 16:26:09 +00002798
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002799 if (!win_array) return TRUE;
Noomen Hamzaa018d851999-09-28 16:26:09 +00002800
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002801 while (win_array[count]) count++;
2802 while (--count >= 0)
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002803 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002804 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2805 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002806
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002807 if (pWnd->dwStyle & WS_POPUP)
Noomen Hamzaff727762000-02-18 19:11:04 +00002808 {
2809 if (fShow)
2810 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002811 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
Noomen Hamzaff727762000-02-18 19:11:04 +00002812 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002813 /* In Windows, ShowOwnedPopups(TRUE) generates
2814 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002815 * regardless of the state of the owner
2816 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002817 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2818 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
Noomen Hamzaff727762000-02-18 19:11:04 +00002819 }
2820 }
2821 else
2822 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002823 if (IsWindowVisible(pWnd->hwndSelf))
Noomen Hamzaff727762000-02-18 19:11:04 +00002824 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002825 /* In Windows, ShowOwnedPopups(FALSE) generates
2826 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002827 * regardless of the state of the owner
2828 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002829 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2830 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
Noomen Hamzaff727762000-02-18 19:11:04 +00002831 }
2832 }
2833 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002834 WIN_ReleaseWndPtr( pWnd );
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002835 }
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002836 HeapFree( GetProcessHeap(), 0, win_array );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002837 return TRUE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002838}
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002839
2840
Alexandre Julliard3a405ba1994-10-30 16:25:19 +00002841/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002842 * GetLastActivePopup (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002843 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002844HWND WINAPI GetLastActivePopup( HWND hwnd )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +00002845{
Alexandre Julliard0b850f92002-10-12 01:23:05 +00002846 HWND retval = hwnd;
2847
2848 SERVER_START_REQ( get_window_info )
2849 {
2850 req->handle = hwnd;
2851 if (!wine_server_call_err( req )) retval = reply->last_active;
2852 }
2853 SERVER_END_REQ;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002854 return retval;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +00002855}
2856
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002857
2858/*******************************************************************
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002859 * WIN_ListParents
Alexandre Julliard3051b641996-07-05 17:14:13 +00002860 *
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002861 * Build an array of all parents of a given window, starting with
2862 * the immediate parent. The array must be freed with HeapFree.
2863 * Returns NULL if window is a top-level window.
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002864 */
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002865HWND *WIN_ListParents( HWND hwnd )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002866{
Alexandre Julliard55557312001-10-23 00:26:10 +00002867 WND *win;
2868 HWND current, *list;
Alexandre Julliard96ebfa92001-10-23 20:35:44 +00002869 int pos = 0, size = 16, count = 0;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002870
Alexandre Julliard55557312001-10-23 00:26:10 +00002871 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2872
2873 current = hwnd;
2874 for (;;)
2875 {
2876 if (!(win = WIN_GetPtr( current ))) goto empty;
2877 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2878 list[pos] = win->parent;
2879 WIN_ReleasePtr( win );
2880 if (!(current = list[pos]))
2881 {
2882 if (!pos) goto empty;
2883 return list;
2884 }
2885 if (++pos == size - 1)
2886 {
2887 /* need to grow the list */
2888 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2889 if (!new_list) goto empty;
2890 list = new_list;
2891 size += 16;
2892 }
2893 }
2894
2895 /* at least one parent belongs to another process, have to query the server */
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002896
2897 for (;;)
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002898 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002899 count = 0;
2900 SERVER_START_REQ( get_window_parents )
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002901 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002902 req->handle = hwnd;
2903 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2904 if (!wine_server_call( req )) count = reply->count;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002905 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002906 SERVER_END_REQ;
2907 if (!count) goto empty;
2908 if (size > count)
2909 {
2910 list[count] = 0;
2911 return list;
2912 }
2913 HeapFree( GetProcessHeap(), 0, list );
2914 size = count + 1;
2915 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002916 }
Alexandre Julliard55557312001-10-23 00:26:10 +00002917
2918 empty:
2919 HeapFree( GetProcessHeap(), 0, list );
2920 return NULL;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002921}
2922
2923
2924/*******************************************************************
2925 * WIN_ListChildren
2926 *
2927 * Build an array of the children of a given window. The array must be
2928 * freed with HeapFree. Returns NULL when no windows are found.
2929 */
2930HWND *WIN_ListChildren( HWND hwnd )
2931{
Alexandre Julliard844ceb92001-10-09 23:26:40 +00002932 return list_window_children( hwnd, 0, 0 );
Alexandre Julliard3051b641996-07-05 17:14:13 +00002933}
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002934
Alexandre Julliard3051b641996-07-05 17:14:13 +00002935
2936/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002937 * EnumWindows (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002938 */
Alexandre Julliardd6c0d862000-03-24 21:38:30 +00002939BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002940{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002941 HWND *list;
2942 BOOL ret = TRUE;
2943 int i, iWndsLocks;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002944
Alexandre Julliard594997c1995-04-30 10:05:20 +00002945 /* We have to build a list of all windows first, to avoid */
Andreas Mohr1c20b392000-02-20 19:17:35 +00002946 /* unpleasant side-effects, for instance if the callback */
2947 /* function changes the Z-order of the windows. */
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002948
Tommy Schultz Lassen440adc12002-01-22 00:50:07 +00002949 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00002950
Alexandre Julliard3051b641996-07-05 17:14:13 +00002951 /* Now call the callback function for every window */
Alexandre Julliard594997c1995-04-30 10:05:20 +00002952
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002953 iWndsLocks = WIN_SuspendWndsLock();
2954 for (i = 0; list[i]; i++)
Alexandre Julliard594997c1995-04-30 10:05:20 +00002955 {
Alexandre Julliard3051b641996-07-05 17:14:13 +00002956 /* Make sure that the window still exists */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002957 if (!IsWindow( list[i] )) continue;
2958 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
Alexandre Julliard594997c1995-04-30 10:05:20 +00002959 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002960 WIN_RestoreWndsLock(iWndsLocks);
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002961 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002962 return ret;
Alexandre Julliard594997c1995-04-30 10:05:20 +00002963}
2964
2965
Alexandre Julliard3051b641996-07-05 17:14:13 +00002966/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002967 * EnumThreadWindows (USER32.@)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002968 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002969BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002970{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002971 HWND *list;
2972 int i, iWndsLocks;
2973
Alexandre Julliard4f716152002-10-17 18:21:29 +00002974 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002975
2976 /* Now call the callback function for every window */
2977
2978 iWndsLocks = WIN_SuspendWndsLock();
2979 for (i = 0; list[i]; i++)
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002980 if (!func( list[i], lParam )) break;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002981 WIN_RestoreWndsLock(iWndsLocks);
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002982 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002983 return TRUE;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002984}
2985
Alexandre Julliard59730ae1996-03-24 16:20:51 +00002986
Alexandre Julliard3051b641996-07-05 17:14:13 +00002987/**********************************************************************
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00002988 * WIN_EnumChildWindows
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002989 *
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00002990 * Helper function for EnumChildWindows().
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002991 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002992static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002993{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002994 HWND *childList;
2995 BOOL ret = FALSE;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002996
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002997 for ( ; *list; list++)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002998 {
2999 /* Make sure that the window still exists */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003000 if (!IsWindow( *list )) continue;
3001 /* skip owned windows */
3002 if (GetWindow( *list, GW_OWNER )) continue;
Alexandre Julliard3051b641996-07-05 17:14:13 +00003003 /* Build children list first */
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003004 childList = WIN_ListChildren( *list );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003005
3006 ret = func( *list, lParam );
Francois Boisvertd96bc151999-04-02 10:34:43 +00003007
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00003008 if (childList)
3009 {
3010 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003011 HeapFree( GetProcessHeap(), 0, childList );
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00003012 }
Alexandre Julliard3051b641996-07-05 17:14:13 +00003013 if (!ret) return FALSE;
Alexandre Julliard3051b641996-07-05 17:14:13 +00003014 }
3015 return TRUE;
3016}
3017
3018
3019/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003020 * EnumChildWindows (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00003021 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003022BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliard3051b641996-07-05 17:14:13 +00003023{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003024 HWND *list;
3025 int iWndsLocks;
Alexandre Julliard3051b641996-07-05 17:14:13 +00003026
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003027 if (!(list = WIN_ListChildren( parent ))) return FALSE;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003028 iWndsLocks = WIN_SuspendWndsLock();
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00003029 WIN_EnumChildWindows( list, func, lParam );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003030 WIN_RestoreWndsLock(iWndsLocks);
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003031 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard3051b641996-07-05 17:14:13 +00003032 return TRUE;
3033}
3034
3035
Alexandre Julliard58199531994-04-21 01:20:00 +00003036/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003037 * AnyPopup (USER.52)
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003038 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003039BOOL16 WINAPI AnyPopup16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003040{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003041 return AnyPopup();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003042}
3043
3044
3045/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003046 * AnyPopup (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003047 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003048BOOL WINAPI AnyPopup(void)
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003049{
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00003050 int i;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003051 BOOL retvalue;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003052 HWND *list = WIN_ListChildren( GetDesktopWindow() );
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00003053
3054 if (!list) return FALSE;
3055 for (i = 0; list[i]; i++)
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003056 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00003057 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003058 }
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00003059 retvalue = (list[i] != 0);
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003060 HeapFree( GetProcessHeap(), 0, list );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003061 return retvalue;
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003062}
3063
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003064
Alexandre Julliard73450d61994-05-18 18:29:32 +00003065/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003066 * FlashWindow (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003067 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003068BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
Alexandre Julliard73450d61994-05-18 18:29:32 +00003069{
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003070 WND *wndPtr = WIN_FindWndPtr(hWnd);
3071
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00003072 TRACE("%04x\n", hWnd);
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003073
3074 if (!wndPtr) return FALSE;
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00003075 hWnd = wndPtr->hwndSelf; /* make it a full handle */
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003076
3077 if (wndPtr->dwStyle & WS_MINIMIZE)
3078 {
3079 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3080 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003081 HDC hDC = GetDC(hWnd);
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003082
Michael Stefaniuc61d92562002-10-19 00:52:55 +00003083 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003084 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003085
Alexandre Julliarda3960291999-02-26 11:11:13 +00003086 ReleaseDC( hWnd, hDC );
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003087 wndPtr->flags |= WIN_NCACTIVATED;
3088 }
3089 else
3090 {
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00003091 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003092 wndPtr->flags &= ~WIN_NCACTIVATED;
3093 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003094 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003095 return TRUE;
3096 }
3097 else
3098 {
Alexandre Julliard530ee841996-10-23 16:59:13 +00003099 WPARAM16 wparam;
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003100 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
Alexandre Julliard5030bda2002-10-11 23:41:06 +00003101 else wparam = (hWnd == GetForegroundWindow());
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003102
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003103 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00003104 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003105 return wparam;
3106 }
Alexandre Julliard73450d61994-05-18 18:29:32 +00003107}
3108
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003109
3110/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003111 * GetWindowContextHelpId (USER32.@)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003112 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003113DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003114{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003115 DWORD retval;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003116 WND *wnd = WIN_FindWndPtr( hwnd );
3117 if (!wnd) return 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003118 retval = wnd->helpContext;
3119 WIN_ReleaseWndPtr(wnd);
3120 return retval;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003121}
3122
3123
3124/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003125 * SetWindowContextHelpId (USER32.@)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003126 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003127BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003128{
3129 WND *wnd = WIN_FindWndPtr( hwnd );
3130 if (!wnd) return FALSE;
3131 wnd->helpContext = id;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003132 WIN_ReleaseWndPtr(wnd);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003133 return TRUE;
3134}
3135
3136
3137/*******************************************************************
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003138 * DRAG_QueryUpdate16
Alexandre Julliardade697e1995-11-26 13:59:11 +00003139 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003140 * recursively find a child that contains spDragInfo->pt point
Alexandre Julliardade697e1995-11-26 13:59:11 +00003141 * and send WM_QUERYDROPOBJECT
3142 */
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003143static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
Alexandre Julliardade697e1995-11-26 13:59:11 +00003144{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003145 BOOL16 wParam, bResult = 0;
Alexandre Julliard48f860c2002-10-28 19:04:39 +00003146 POINT pt, client_pt;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003147 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3148 RECT tempRect;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003149
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003150 if (!ptrDragInfo) return FALSE;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003151
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003152 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003153
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003154 GetWindowRect(hQueryWnd,&tempRect);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003155
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003156 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003157
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003158 if (!IsIconic( hQueryWnd ))
3159 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003160 GetClientRect( hQueryWnd, &tempRect );
3161 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003162
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003163 if (PtInRect( &tempRect, pt))
3164 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003165 int i;
3166 HWND *list = WIN_ListChildren( hQueryWnd );
3167
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003168 wParam = 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003169
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003170 if (list)
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003171 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003172 for (i = 0; list[i]; i++)
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003173 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003174 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3175 {
3176 GetWindowRect( list[i], &tempRect );
3177 if (PtInRect( &tempRect, pt )) break;
3178 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003179 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003180 if (list[i])
3181 {
3182 if (IsWindowEnabled( list[i] ))
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003183 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003184 }
3185 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003186 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003187 if(bResult) return bResult;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003188 }
3189 else wParam = 1;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003190 }
3191 else wParam = 1;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003192
Alexandre Julliard48f860c2002-10-28 19:04:39 +00003193 client_pt = pt;
3194 ScreenToClient( hQueryWnd, &client_pt );
3195 ptrDragInfo->pt.x = client_pt.x;
3196 ptrDragInfo->pt.y = client_pt.y;
Michael Stefaniuc2247af32002-09-04 19:37:01 +00003197 ptrDragInfo->hScope = HWND_16(hQueryWnd);
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003198
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003199 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003200
3201 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3202
3203 return bResult;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003204}
3205
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003206
Alexandre Julliardade697e1995-11-26 13:59:11 +00003207/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003208 * DragDetect (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003209 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003210BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
Alexandre Julliardade697e1995-11-26 13:59:11 +00003211{
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003212 MSG msg;
3213 RECT rect;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003214
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003215 rect.left = pt.x - wDragWidth;
3216 rect.right = pt.x + wDragWidth;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003217
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003218 rect.top = pt.y - wDragHeight;
3219 rect.bottom = pt.y + wDragHeight;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003220
Alexandre Julliarda3960291999-02-26 11:11:13 +00003221 SetCapture(hWnd);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003222
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003223 while(1)
3224 {
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003225 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003226 {
3227 if( msg.message == WM_LBUTTONUP )
3228 {
3229 ReleaseCapture();
3230 return 0;
3231 }
3232 if( msg.message == WM_MOUSEMOVE )
3233 {
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003234 POINT tmp;
3235 tmp.x = LOWORD(msg.lParam);
3236 tmp.y = HIWORD(msg.lParam);
3237 if( !PtInRect( &rect, tmp ))
Alexandre Julliardade697e1995-11-26 13:59:11 +00003238 {
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003239 ReleaseCapture();
3240 return 1;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003241 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003242 }
3243 }
3244 WaitMessage();
3245 }
3246 return 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003247}
3248
3249/******************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003250 * DragObject (USER.464)
Alexandre Julliardade697e1995-11-26 13:59:11 +00003251 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003252DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3253 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
Alexandre Julliardade697e1995-11-26 13:59:11 +00003254{
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003255 MSG msg;
Alexandre Julliard83f52d12000-09-26 22:20:14 +00003256 LPDRAGINFO16 lpDragInfo;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003257 SEGPTR spDragInfo;
Michael Stefaniucbc54d782002-10-10 21:22:09 +00003258 HCURSOR hOldCursor=0, hBummer=0;
Alexandre Julliard83f52d12000-09-26 22:20:14 +00003259 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
Michael Stefaniucbc54d782002-10-10 21:22:09 +00003260 HCURSOR hCurrentCursor = 0;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003261 HWND16 hCurrentWnd = 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003262
Alexandre Julliard83f52d12000-09-26 22:20:14 +00003263 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
Alexandre Julliard58017232000-12-22 01:09:26 +00003264 spDragInfo = K32WOWGlobalLock16(hDragInfo);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003265
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003266 if( !lpDragInfo || !spDragInfo ) return 0L;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003267
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003268 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003269 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003270 GlobalFree16(hDragInfo);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003271 return 0L;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003272 }
Alexandre Julliardade697e1995-11-26 13:59:11 +00003273
Michael Stefaniucbc54d782002-10-10 21:22:09 +00003274 if(hCursor) hOldCursor = SetCursor(HCURSOR_32(hCursor));
Alexandre Julliardade697e1995-11-26 13:59:11 +00003275
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003276 lpDragInfo->hWnd = hWnd;
3277 lpDragInfo->hScope = 0;
3278 lpDragInfo->wFlags = wObj;
3279 lpDragInfo->hList = szList; /* near pointer! */
3280 lpDragInfo->hOfStruct = hOfStruct;
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003281 lpDragInfo->l = 0L;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003282
Michael Stefaniuc2247af32002-09-04 19:37:01 +00003283 SetCapture(WIN_Handle32(hWnd));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003284 ShowCursor( TRUE );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003285
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003286 do
3287 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003288 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003289
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003290 *(lpDragInfo+1) = *lpDragInfo;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003291
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003292 lpDragInfo->pt.x = msg.pt.x;
3293 lpDragInfo->pt.y = msg.pt.y;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003294
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003295 /* update DRAGINFO struct */
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003296 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003297
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003298 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
Michael Stefaniucbc54d782002-10-10 21:22:09 +00003299 hCurrentCursor = HCURSOR_32(hCursor);
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003300 else
Alexandre Julliardade697e1995-11-26 13:59:11 +00003301 {
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003302 hCurrentCursor = hBummer;
3303 lpDragInfo->hScope = 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003304 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003305 if( hCurrentCursor )
Alexandre Julliarda3960291999-02-26 11:11:13 +00003306 SetCursor(hCurrentCursor);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003307
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003308 /* send WM_DRAGLOOP */
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003309 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003310 (LPARAM) spDragInfo );
3311 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3312 if( hCurrentWnd != lpDragInfo->hScope )
Alexandre Julliardade697e1995-11-26 13:59:11 +00003313 {
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003314 if( hCurrentWnd )
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003315 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
Alexandre Julliard83f52d12000-09-26 22:20:14 +00003316 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
Alexandre Julliardade697e1995-11-26 13:59:11 +00003317 HIWORD(spDragInfo)) );
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003318 hCurrentWnd = lpDragInfo->hScope;
3319 if( hCurrentWnd )
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003320 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003321 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003322 else
3323 if( hCurrentWnd )
3324 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3325
3326 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3327
3328 ReleaseCapture();
Alexandre Julliarda3960291999-02-26 11:11:13 +00003329 ShowCursor( FALSE );
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003330
Michael Stefaniucbc54d782002-10-10 21:22:09 +00003331 if( hCursor ) SetCursor(hOldCursor);
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003332
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003333 if( hCurrentCursor != hBummer )
3334 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003335 (WPARAM16)hWnd, (LPARAM)spDragInfo );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003336 else
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003337 msg.lParam = 0;
3338 GlobalFree16(hDragInfo);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003339
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003340 return (DWORD)(msg.lParam);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003341}
Eric Kohlca6c9a62001-03-20 01:53:51 +00003342
3343
3344/******************************************************************************
3345 * GetWindowModuleFileNameA (USER32.@)
3346 */
3347UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3348{
3349 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3350 hwnd, lpszFileName, cchFileNameMax);
3351 return 0;
3352}
3353
3354/******************************************************************************
3355 * GetWindowModuleFileNameW (USER32.@)
3356 */
3357UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3358{
3359 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3360 hwnd, lpszFileName, cchFileNameMax);
3361 return 0;
3362}
David Hammertonca30e482002-05-06 20:11:18 +00003363
3364/******************************************************************************
3365 * GetWindowInfo (USER32.@)
3366 * hwnd: in
3367 * pwi: out.
3368 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3369 * this may be because this structure changed over time. If this is the
3370 * the case, then please: FIXME.
3371 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3372 */
3373BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3374{
3375 WND *wndInfo = NULL;
3376 if (!pwi) return FALSE;
3377 if (pwi->cbSize != sizeof(WINDOWINFO))
3378 {
3379 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3380 return FALSE;
3381 }
3382 wndInfo = WIN_GetPtr(hwnd);
3383 if (!wndInfo) return FALSE;
3384 if (wndInfo == WND_OTHER_PROCESS)
3385 {
3386 FIXME("window belong to other process\n");
3387 return FALSE;
3388 }
3389
3390 pwi->rcWindow = wndInfo->rectWindow;
3391 pwi->rcClient = wndInfo->rectClient;
3392 pwi->dwStyle = wndInfo->dwStyle;
3393 pwi->dwExStyle = wndInfo->dwExStyle;
3394 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3395 /* if active WS_ACTIVECAPTION, else 0 */
3396
3397 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3398 GetSystemMetrics(SM_CXBORDER) : 0);
3399 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3400 GetSystemMetrics(SM_CYBORDER) : 0);
3401 /* above two: I'm presuming that borders widths are the same
3402 * for each window - so long as its actually using a border.. */
3403
3404 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3405 pwi->wCreatorVersion = GetVersion();
3406 /* Docs say this should be the version that
3407 * CREATED the window. But eh?.. Isn't that just the
3408 * version we are running.. Unless ofcourse its some wacky
3409 * RPC stuff or something */
3410
3411 WIN_ReleasePtr(wndInfo);
3412 return TRUE;
3413}