blob: 5a69a8c35545c0a963c0a280d567ae369cfe6cf3 [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 Julliard1a66d222001-08-28 18:44:52 +000030#include "wine/server.h"
Alexandre Julliardcb10fda2000-08-06 02:41:16 +000031#include "wine/unicode.h"
Alexandre Julliard401710d1993-09-04 10:09:32 +000032#include "win.h"
Alexandre Julliardf0b23541993-09-29 12:21:49 +000033#include "user.h"
Alexandre Julliard5f721f81994-01-04 20:14:34 +000034#include "dce.h"
Alexandre Julliard91222da2000-12-10 23:01:33 +000035#include "controls.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000036#include "cursoricon.h"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000037#include "hook.h"
Alexandre Julliardef702d81996-05-28 18:54:58 +000038#include "message.h"
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000039#include "queue.h"
Alexandre Julliard4ff32c82001-08-18 18:08:26 +000040#include "task.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000041#include "winpos.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000042#include "winerror.h"
Alexandre Julliard4220b291999-07-11 17:20:01 +000043#include "stackframe.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000044#include "wine/debug.h"
Alexandre Julliard401710d1993-09-04 10:09:32 +000045
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000046WINE_DEFAULT_DEBUG_CHANNEL(win);
47WINE_DECLARE_DEBUG_CHANNEL(msg);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000048
Alexandre Julliard7695d692001-09-24 01:19:59 +000049#define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
50
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +000051/**********************************************************************/
52
Alexandre Julliard59730ae1996-03-24 16:20:51 +000053/* Desktop window */
54static WND *pWndDesktop = NULL;
55
Alexandre Julliardd4719651995-12-12 18:49:11 +000056static WORD wDragWidth = 4;
57static WORD wDragHeight= 3;
Alexandre Julliardade697e1995-11-26 13:59:11 +000058
Alexandre Julliard7695d692001-09-24 01:19:59 +000059static void *user_handles[NB_USER_HANDLES];
Alexandre Julliard1a66d222001-08-28 18:44:52 +000060
Francois Boisvert93e3f901999-02-25 17:32:31 +000061/* thread safeness */
Alexandre Julliard6837b9c2001-08-16 18:14:22 +000062extern SYSLEVEL USER_SysLevel; /* FIXME */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000063
Francois Boisvert93e3f901999-02-25 17:32:31 +000064/***********************************************************************
65 * WIN_SuspendWndsLock
66 *
67 * Suspend the lock on WND structures.
68 * Returns the number of locks suspended
69 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000070int WIN_SuspendWndsLock( void )
Francois Boisvert93e3f901999-02-25 17:32:31 +000071{
Alexandre Julliard6837b9c2001-08-16 18:14:22 +000072 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000073 int count = isuspendedLocks;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +000074
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000075 while ( count-- > 0 )
Alexandre Julliard6837b9c2001-08-16 18:14:22 +000076 _LeaveSysLevel( &USER_SysLevel );
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +000077
Francois Boisvert93e3f901999-02-25 17:32:31 +000078 return isuspendedLocks;
Francois Boisvert93e3f901999-02-25 17:32:31 +000079}
80
81/***********************************************************************
82 * WIN_RestoreWndsLock
83 *
84 * Restore the suspended locks on WND structures
85 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000086void WIN_RestoreWndsLock( int ipreviousLocks )
Francois Boisvert93e3f901999-02-25 17:32:31 +000087{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000088 while ( ipreviousLocks-- > 0 )
Alexandre Julliard6837b9c2001-08-16 18:14:22 +000089 _EnterSysLevel( &USER_SysLevel );
Francois Boisvert93e3f901999-02-25 17:32:31 +000090}
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +000091
Alexandre Julliard401710d1993-09-04 10:09:32 +000092/***********************************************************************
Alexandre Julliard1a66d222001-08-28 18:44:52 +000093 * create_window_handle
94 *
95 * Create a window handle with the server.
96 */
Alexandre Julliard844ceb92001-10-09 23:26:40 +000097static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
Alexandre Julliard1a66d222001-08-28 18:44:52 +000098{
99 BOOL res;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000100 user_handle_t handle = 0;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000101 WORD index;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000102 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
103
104 if (!win) return NULL;
105
106 USER_Lock();
107
Alexandre Julliarda09da0c2001-09-21 21:08:40 +0000108 SERVER_START_REQ( create_window )
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000109 {
Alexandre Julliarda09da0c2001-09-21 21:08:40 +0000110 req->parent = parent;
111 req->owner = owner;
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000112 req->atom = atom;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000113 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000114 }
Alexandre Julliarda09da0c2001-09-21 21:08:40 +0000115 SERVER_END_REQ;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000116
117 if (!res)
118 {
119 USER_Unlock();
120 HeapFree( GetProcessHeap(), 0, win );
121 return NULL;
122 }
Alexandre Julliard7695d692001-09-24 01:19:59 +0000123 index = LOWORD(handle) - FIRST_USER_HANDLE;
124 assert( index < NB_USER_HANDLES );
125 user_handles[index] = win;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000126 win->hwndSelf = handle;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000127 win->dwMagic = WND_MAGIC;
128 win->irefCount = 1;
129 return win;
130}
131
132
133/***********************************************************************
134 * free_window_handle
135 *
136 * Free a window handle.
137 */
138static WND *free_window_handle( HWND hwnd )
139{
140 WND *ptr;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000141 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000142
Alexandre Julliard7695d692001-09-24 01:19:59 +0000143 if (index >= NB_USER_HANDLES) return NULL;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000144 USER_Lock();
Alexandre Julliard7695d692001-09-24 01:19:59 +0000145 if ((ptr = user_handles[index]))
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000146 {
147 SERVER_START_REQ( destroy_window )
148 {
149 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000150 if (!wine_server_call_err( req ))
Alexandre Julliard7695d692001-09-24 01:19:59 +0000151 user_handles[index] = NULL;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000152 else
153 ptr = NULL;
154 }
155 SERVER_END_REQ;
156 }
157 USER_Unlock();
158 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
159 return ptr;
160}
161
162
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000163/*******************************************************************
164 * list_window_children
165 *
166 * Build an array of the children of a given window. The array must be
167 * freed with HeapFree. Returns NULL when no windows are found.
168 */
169static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
170{
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000171 HWND *list;
172 int size = 32;
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000173
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000174 for (;;)
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000175 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000176 int count = 0;
177
178 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
179
180 SERVER_START_REQ( get_window_children )
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000181 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000182 req->parent = hwnd;
183 req->atom = atom;
Alexandre Julliard54f22872002-10-03 19:54:57 +0000184 req->tid = tid;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000185 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
186 if (!wine_server_call( req )) count = reply->count;
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000187 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000188 SERVER_END_REQ;
189 if (count && count < size)
190 {
191 list[count] = 0;
192 return list;
193 }
194 HeapFree( GetProcessHeap(), 0, list );
195 if (!count) break;
196 size = count + 1; /* restart with a large enough buffer */
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000197 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000198 return NULL;
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000199}
200
201
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000202/*******************************************************************
203 * send_parent_notify
204 */
205static void send_parent_notify( HWND hwnd, UINT msg )
206{
207 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
208 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
209 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
210 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
211}
212
213
Alexandre Julliard805bdc52001-11-13 22:23:48 +0000214/*******************************************************************
215 * get_server_window_text
216 *
217 * Retrieve the window text from the server.
218 */
219static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
220{
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000221 size_t len = 0;
222
223 SERVER_START_REQ( get_window_text )
Alexandre Julliard805bdc52001-11-13 22:23:48 +0000224 {
225 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000226 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
227 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
Alexandre Julliard805bdc52001-11-13 22:23:48 +0000228 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000229 SERVER_END_REQ;
Alexandre Julliard805bdc52001-11-13 22:23:48 +0000230 text[len / sizeof(WCHAR)] = 0;
231}
232
233
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000234/***********************************************************************
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000235 * WIN_GetPtr
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000236 *
Alexandre Julliard7695d692001-09-24 01:19:59 +0000237 * Return a pointer to the WND structure if local to the process,
Andreas Mohr7df2d9f2002-07-24 19:02:50 +0000238 * or WND_OTHER_PROCESS if handle may be valid in other process.
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000239 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000240 */
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000241WND *WIN_GetPtr( HWND hwnd )
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000242{
Alexandre Julliard37a46392001-09-12 17:19:13 +0000243 WND * ptr;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000244 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000245
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000246 if (index >= NB_USER_HANDLES) return NULL;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000247
248 USER_Lock();
Alexandre Julliard7695d692001-09-24 01:19:59 +0000249 if ((ptr = user_handles[index]))
Alexandre Julliard37a46392001-09-12 17:19:13 +0000250 {
251 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
252 return ptr;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000253 ptr = NULL;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000254 }
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000255 else ptr = WND_OTHER_PROCESS;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000256 USER_Unlock();
Alexandre Julliard7695d692001-09-24 01:19:59 +0000257 return ptr;
258}
259
260
261/***********************************************************************
262 * WIN_IsCurrentProcess
263 *
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000264 * Check whether a given window belongs to the current process (and return the full handle).
Alexandre Julliard7695d692001-09-24 01:19:59 +0000265 */
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000266HWND WIN_IsCurrentProcess( HWND hwnd )
Alexandre Julliard7695d692001-09-24 01:19:59 +0000267{
268 WND *ptr;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000269 HWND ret;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000270
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000271 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
272 ret = ptr->hwndSelf;
273 WIN_ReleasePtr( ptr );
274 return ret;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000275}
276
277
278/***********************************************************************
279 * WIN_IsCurrentThread
280 *
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000281 * Check whether a given window belongs to the current thread (and return the full handle).
Alexandre Julliard7695d692001-09-24 01:19:59 +0000282 */
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000283HWND WIN_IsCurrentThread( HWND hwnd )
Alexandre Julliard7695d692001-09-24 01:19:59 +0000284{
285 WND *ptr;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000286 HWND ret = 0;
Alexandre Julliard7695d692001-09-24 01:19:59 +0000287
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000288 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
Alexandre Julliard7695d692001-09-24 01:19:59 +0000289 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000290 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
291 WIN_ReleasePtr( ptr );
Alexandre Julliard7695d692001-09-24 01:19:59 +0000292 }
293 return ret;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000294}
295
296
297/***********************************************************************
298 * WIN_Handle32
299 *
300 * Convert a 16-bit window handle to a full 32-bit handle.
301 */
302HWND WIN_Handle32( HWND16 hwnd16 )
303{
304 WND *ptr;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000305 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000306
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000307 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
308 /* do sign extension for -2 and -3 */
309 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
Alexandre Julliard37a46392001-09-12 17:19:13 +0000310
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000311 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
312
313 if (ptr != WND_OTHER_PROCESS)
Alexandre Julliard37a46392001-09-12 17:19:13 +0000314 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000315 hwnd = ptr->hwndSelf;
316 WIN_ReleasePtr( ptr );
Alexandre Julliard37a46392001-09-12 17:19:13 +0000317 }
318 else /* may belong to another process */
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000319 {
320 SERVER_START_REQ( get_window_info )
321 {
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000322 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000323 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
Alexandre Julliard6bf2abf2001-08-29 00:16:00 +0000324 }
325 SERVER_END_REQ;
326 }
327 return hwnd;
328}
329
330
331/***********************************************************************
Alexandre Julliard401710d1993-09-04 10:09:32 +0000332 * WIN_FindWndPtr
333 *
334 * Return a pointer to the WND structure corresponding to a HWND.
Alexandre Julliard401710d1993-09-04 10:09:32 +0000335 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000336WND * WIN_FindWndPtr( HWND hwnd )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000337{
338 WND * ptr;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000339
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000340 if (!hwnd) return NULL;
341
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000342 if ((ptr = WIN_GetPtr( hwnd )))
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000343 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000344 if (ptr != WND_OTHER_PROCESS)
Alexandre Julliard7695d692001-09-24 01:19:59 +0000345 {
346 /* increment destruction monitoring */
347 ptr->irefCount++;
348 return ptr;
349 }
Alexandre Julliard8fd26b92001-10-15 17:56:45 +0000350 if (IsWindow( hwnd )) /* check other processes */
351 {
352 ERR( "window %04x belongs to other process\n", hwnd );
353 /* DbgBreakPoint(); */
354 }
Alexandre Julliard37a46392001-09-12 17:19:13 +0000355 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000356 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
Eric Pouechb9544f11999-02-14 14:09:42 +0000357 return NULL;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000358}
359
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000360
Francois Boisvert93e3f901999-02-25 17:32:31 +0000361/***********************************************************************
362 * WIN_ReleaseWndPtr
363 *
364 * Release the pointer to the WND structure.
365 */
366void WIN_ReleaseWndPtr(WND *wndPtr)
367{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000368 if(!wndPtr) return;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000369
Andreas Mohre15badb2001-10-21 15:18:15 +0000370 /* Decrement destruction monitoring value */
Francois Boisvert93e3f901999-02-25 17:32:31 +0000371 wndPtr->irefCount--;
Andreas Mohre15badb2001-10-21 15:18:15 +0000372 /* Check if it's time to release the memory */
Francois Boisvert86e2e111999-04-03 11:13:33 +0000373 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
Francois Boisvert93e3f901999-02-25 17:32:31 +0000374 {
Francois Boisvert86e2e111999-04-03 11:13:33 +0000375 /* Release memory */
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000376 free_window_handle( wndPtr->hwndSelf );
Francois Boisvert93e3f901999-02-25 17:32:31 +0000377 }
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000378 else if(wndPtr->irefCount < 0)
379 {
380 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000381 ERR("forgot a Lock on %p somewhere\n",wndPtr);
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000382 }
Andreas Mohre15badb2001-10-21 15:18:15 +0000383 /* unlock all WND structures for thread safeness */
Alexandre Julliard6837b9c2001-08-16 18:14:22 +0000384 USER_Unlock();
Francois Boisvert93e3f901999-02-25 17:32:31 +0000385}
386
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000387
388/***********************************************************************
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000389 * WIN_UnlinkWindow
390 *
391 * Remove a window from the siblings linked list.
392 */
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000393void WIN_UnlinkWindow( HWND hwnd )
394{
395 WIN_LinkWindow( hwnd, 0, 0 );
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000396}
397
398
399/***********************************************************************
400 * WIN_LinkWindow
401 *
402 * Insert a window into the siblings linked list.
403 * The window is inserted after the specified window, which can also
404 * be specified as HWND_TOP or HWND_BOTTOM.
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000405 * If parent is 0, window is unlinked from the tree.
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000406 */
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000407void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
408{
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000409 WND *wndPtr = WIN_GetPtr( hwnd );
410
411 if (!wndPtr) return;
412 if (wndPtr == WND_OTHER_PROCESS)
413 {
414 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
415 return;
416 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000417
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000418 SERVER_START_REQ( link_window )
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000419 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000420 req->handle = hwnd;
421 req->parent = parent;
422 req->previous = hwndInsertAfter;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000423 if (!wine_server_call( req ))
Alexandre Julliardddc33172001-10-22 19:08:33 +0000424 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000425 if (reply->full_parent) wndPtr->parent = reply->full_parent;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000426 }
427
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000428 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000429 SERVER_END_REQ;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000430 WIN_ReleasePtr( wndPtr );
431}
432
433
434/***********************************************************************
435 * WIN_SetOwner
436 *
437 * Change the owner of a window.
438 */
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000439HWND WIN_SetOwner( HWND hwnd, HWND owner )
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000440{
Alexandre Julliardddc33172001-10-22 19:08:33 +0000441 WND *win = WIN_GetPtr( hwnd );
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000442 HWND ret = 0;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000443
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000444 if (!win) return 0;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000445 if (win == WND_OTHER_PROCESS)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000446 {
Alexandre Julliardddc33172001-10-22 19:08:33 +0000447 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000448 return 0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000449 }
Alexandre Julliardddc33172001-10-22 19:08:33 +0000450 SERVER_START_REQ( set_window_owner )
451 {
452 req->handle = hwnd;
453 req->owner = owner;
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000454 if (!wine_server_call( req ))
455 {
456 win->owner = reply->full_owner;
457 ret = reply->prev_owner;
458 }
Alexandre Julliardddc33172001-10-22 19:08:33 +0000459 }
460 SERVER_END_REQ;
461 WIN_ReleasePtr( win );
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000462 return ret;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000463}
464
465
466/***********************************************************************
467 * WIN_SetStyle
468 *
469 * Change the style of a window.
470 */
471LONG WIN_SetStyle( HWND hwnd, LONG style )
472{
473 BOOL ok;
474 LONG ret = 0;
475 WND *win = WIN_GetPtr( hwnd );
476
477 if (!win) return 0;
478 if (win == WND_OTHER_PROCESS)
479 {
480 if (IsWindow(hwnd))
481 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
482 return 0;
483 }
484 if (style == win->dwStyle)
485 {
486 WIN_ReleasePtr( win );
487 return style;
488 }
489 SERVER_START_REQ( set_window_info )
490 {
491 req->handle = hwnd;
492 req->flags = SET_WIN_STYLE;
493 req->style = style;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000494 if ((ok = !wine_server_call( req )))
Alexandre Julliardddc33172001-10-22 19:08:33 +0000495 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000496 ret = reply->old_style;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000497 win->dwStyle = style;
498 }
499 }
500 SERVER_END_REQ;
501 WIN_ReleasePtr( win );
502 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
503 return ret;
504}
505
506
507/***********************************************************************
508 * WIN_SetExStyle
509 *
510 * Change the extended style of a window.
511 */
512LONG WIN_SetExStyle( HWND hwnd, LONG style )
513{
514 LONG ret = 0;
515 WND *win = WIN_GetPtr( hwnd );
516
517 if (!win) return 0;
518 if (win == WND_OTHER_PROCESS)
519 {
520 if (IsWindow(hwnd))
521 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
522 return 0;
523 }
524 if (style == win->dwExStyle)
525 {
526 WIN_ReleasePtr( win );
527 return style;
528 }
529 SERVER_START_REQ( set_window_info )
530 {
531 req->handle = hwnd;
532 req->flags = SET_WIN_EXSTYLE;
533 req->ex_style = style;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000534 if (!wine_server_call( req ))
Alexandre Julliardddc33172001-10-22 19:08:33 +0000535 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000536 ret = reply->old_ex_style;
Alexandre Julliardddc33172001-10-22 19:08:33 +0000537 win->dwExStyle = style;
538 }
539 }
540 SERVER_END_REQ;
541 WIN_ReleasePtr( win );
542 return ret;
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000543}
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000544
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000545
546/***********************************************************************
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000547 * WIN_SetRectangles
548 *
549 * Set the window and client rectangles.
550 */
551void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
552{
553 WND *win = WIN_GetPtr( hwnd );
554 BOOL ret;
555
556 if (!win) return;
557 if (win == WND_OTHER_PROCESS)
558 {
559 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
560 return;
561 }
562 SERVER_START_REQ( set_window_rectangles )
563 {
564 req->handle = hwnd;
565 req->window.left = rectWindow->left;
566 req->window.top = rectWindow->top;
567 req->window.right = rectWindow->right;
568 req->window.bottom = rectWindow->bottom;
569 req->client.left = rectClient->left;
570 req->client.top = rectClient->top;
571 req->client.right = rectClient->right;
572 req->client.bottom = rectClient->bottom;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000573 ret = !wine_server_call( req );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000574 }
575 SERVER_END_REQ;
576 if (ret)
577 {
578 win->rectWindow = *rectWindow;
579 win->rectClient = *rectClient;
580
581 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
582 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
583 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
584 }
585 WIN_ReleasePtr( win );
586}
587
588
589/***********************************************************************
Alexandre Julliard5797fbb2001-12-06 22:33:58 +0000590 * WIN_GetRectangles
591 *
592 * Get the window and client rectangles.
593 */
594BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
595{
596 WND *win = WIN_GetPtr( hwnd );
597 BOOL ret = TRUE;
598
599 if (!win) return FALSE;
600 if (win == WND_OTHER_PROCESS)
601 {
602 SERVER_START_REQ( get_window_rectangles )
603 {
604 req->handle = hwnd;
605 if ((ret = !wine_server_call( req )))
606 {
607 if (rectWindow)
608 {
609 rectWindow->left = reply->window.left;
610 rectWindow->top = reply->window.top;
611 rectWindow->right = reply->window.right;
612 rectWindow->bottom = reply->window.bottom;
613 }
614 if (rectClient)
615 {
616 rectClient->left = reply->client.left;
617 rectClient->top = reply->client.top;
618 rectClient->right = reply->client.right;
619 rectClient->bottom = reply->client.bottom;
620 }
621 }
622 }
623 SERVER_END_REQ;
624 }
625 else
626 {
627 if (rectWindow) *rectWindow = win->rectWindow;
628 if (rectClient) *rectClient = win->rectClient;
629 WIN_ReleasePtr( win );
630 }
631 return ret;
632}
633
634
635/***********************************************************************
Alexandre Julliardaca05781994-10-17 18:12:41 +0000636 * WIN_DestroyWindow
637 *
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000638 * Destroy storage associated to a window. "Internals" p.358
Alexandre Julliardaca05781994-10-17 18:12:41 +0000639 */
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000640LRESULT WIN_DestroyWindow( HWND hwnd )
Alexandre Julliardaca05781994-10-17 18:12:41 +0000641{
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000642 WND *wndPtr;
643 HWND *list;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000644
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000645 TRACE("%04x\n", hwnd );
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000646
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000647 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
648 {
649 ERR( "window doesn't belong to current thread\n" );
650 return 0;
651 }
652
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000653 /* free child windows */
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000654 if ((list = WIN_ListChildren( hwnd )))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000655 {
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000656 int i;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000657 for (i = 0; list[i]; i++)
658 {
659 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
660 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
661 }
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000662 HeapFree( GetProcessHeap(), 0, list );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000663 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000664
Francis Beaudet7c2f0fe1999-03-21 08:50:41 +0000665 /*
666 * Clear the update region to make sure no WM_PAINT messages will be
667 * generated for this window while processing the WM_NCDESTROY.
668 */
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000669 RedrawWindow( hwnd, NULL, 0,
Alexandre Julliard4b0343d2001-06-20 22:55:31 +0000670 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
Francis Beaudet7c2f0fe1999-03-21 08:50:41 +0000671
672 /*
673 * Send the WM_NCDESTROY to the window being destroyed.
674 */
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000675 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000676
677 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
678
Alexandre Julliardde424282001-08-10 22:51:42 +0000679 WINPOS_CheckInternalPos( hwnd );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000680 if( hwnd == GetCapture()) ReleaseCapture();
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000681
682 /* free resources associated with the window */
683
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000684 TIMER_RemoveWindowTimers( hwnd );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000685
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000686 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000687 wndPtr->hmemTaskQ = 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000688
689 if (!(wndPtr->dwStyle & WS_CHILD))
Alexandre Julliardddc33172001-10-22 19:08:33 +0000690 {
691 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
692 if (menu) DestroyMenu( menu );
693 }
Guy Albertelli38db0982000-05-11 00:06:38 +0000694 if (wndPtr->hSysMenu)
695 {
696 DestroyMenu( wndPtr->hSysMenu );
697 wndPtr->hSysMenu = 0;
698 }
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000699 USER_Driver.pDestroyWindow( hwnd );
700 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000701 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
Alexandre Julliard98779062000-12-07 23:39:16 +0000702 CLASS_RemoveWindow( wndPtr->class );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000703 wndPtr->class = NULL;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000704 wndPtr->dwMagic = 0; /* Mark it as invalid */
Alexandre Julliard80593bf2001-10-11 20:49:40 +0000705 WIN_ReleaseWndPtr( wndPtr );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000706 return 0;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000707}
708
Alexandre Julliardaca05781994-10-17 18:12:41 +0000709/***********************************************************************
Alexandre Julliard4b0343d2001-06-20 22:55:31 +0000710 * WIN_DestroyThreadWindows
Alexandre Julliard77b99181997-09-14 17:17:23 +0000711 *
Alexandre Julliard4b0343d2001-06-20 22:55:31 +0000712 * Destroy all children of 'wnd' owned by the current thread.
Alexandre Julliard77b99181997-09-14 17:17:23 +0000713 * Return TRUE if something was done.
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000714 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000715void WIN_DestroyThreadWindows( HWND hwnd )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000716{
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000717 HWND *list;
718 int i;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000719
Alexandre Julliard9d9dac02001-08-24 19:28:21 +0000720 if (!(list = WIN_ListChildren( hwnd ))) return;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000721 for (i = 0; list[i]; i++)
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000722 {
Alexandre Julliard7695d692001-09-24 01:19:59 +0000723 if (WIN_IsCurrentThread( list[i] ))
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000724 DestroyWindow( list[i] );
725 else
726 WIN_DestroyThreadWindows( list[i] );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000727 }
Alexandre Julliard9d9dac02001-08-24 19:28:21 +0000728 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000729}
730
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000731/***********************************************************************
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000732 * WIN_CreateDesktopWindow
733 *
734 * Create the desktop window.
735 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000736BOOL WIN_CreateDesktopWindow(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000737{
Alexandre Julliard98779062000-12-07 23:39:16 +0000738 struct tagCLASS *class;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000739 HWND hwndDesktop;
Alexandre Julliard98779062000-12-07 23:39:16 +0000740 INT wndExtra;
741 DWORD clsStyle;
742 WNDPROC winproc;
743 DCE *dce;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000744 CREATESTRUCTA cs;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000745 RECT rect;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000746
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000747 TRACE("Creating desktop window\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000748
Alexandre Julliard91222da2000-12-10 23:01:33 +0000749 if (!WINPOS_CreateInternalPosAtom() ||
750 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
Alexandre Julliard98779062000-12-07 23:39:16 +0000751 &wndExtra, &winproc, &clsStyle, &dce )))
752 return FALSE;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000753
Alexandre Julliard844ceb92001-10-09 23:26:40 +0000754 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
755 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000756 if (!pWndDesktop) return FALSE;
757 hwndDesktop = pWndDesktop->hwndSelf;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000758
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000759 pWndDesktop->tid = 0; /* nobody owns the desktop */
Alexandre Julliard556607a2001-10-10 20:28:17 +0000760 pWndDesktop->parent = 0;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +0000761 pWndDesktop->owner = 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000762 pWndDesktop->class = class;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000763 pWndDesktop->text = NULL;
Alexandre Julliard43230042001-05-16 19:52:29 +0000764 pWndDesktop->hmemTaskQ = 0;
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000765 pWndDesktop->hrgnUpdate = 0;
766 pWndDesktop->hwndLastActive = hwndDesktop;
Alexandre Julliard98779062000-12-07 23:39:16 +0000767 pWndDesktop->clsStyle = clsStyle;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000768 pWndDesktop->dce = NULL;
Alexandre Julliardca22b331996-07-12 19:02:39 +0000769 pWndDesktop->pVScroll = NULL;
770 pWndDesktop->pHScroll = NULL;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000771 pWndDesktop->helpContext = 0;
Alexandre Julliard26320d12001-03-23 23:45:45 +0000772 pWndDesktop->flags = 0;
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000773 pWndDesktop->hSysMenu = 0;
Alexandre Julliard98779062000-12-07 23:39:16 +0000774 pWndDesktop->winproc = winproc;
775 pWndDesktop->cbWndExtra = wndExtra;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000776
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000777 cs.lpCreateParams = NULL;
778 cs.hInstance = 0;
779 cs.hMenu = 0;
780 cs.hwndParent = 0;
781 cs.x = 0;
782 cs.y = 0;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000783 cs.cx = GetSystemMetrics( SM_CXSCREEN );
784 cs.cy = GetSystemMetrics( SM_CYSCREEN );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000785 cs.style = pWndDesktop->dwStyle;
786 cs.dwExStyle = pWndDesktop->dwExStyle;
787 cs.lpszName = NULL;
788 cs.lpszClass = DESKTOP_CLASS_ATOM;
Alexandre Julliard91222da2000-12-10 23:01:33 +0000789
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000790 SetRect( &rect, 0, 0, cs.cx, cs.cy );
791 WIN_SetRectangles( hwndDesktop, &rect, &rect );
Alexandre Julliard7dafa612002-09-25 00:21:56 +0000792
793 SERVER_START_REQ( set_window_info )
794 {
795 req->handle = hwndDesktop;
796 req->flags = 0; /* don't set anything, just retrieve */
797 wine_server_call( req );
798 pWndDesktop->dwStyle = reply->old_style;
799 pWndDesktop->dwExStyle = reply->old_ex_style;
800 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
801 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
802 pWndDesktop->wIDmenu = reply->old_id;
803 }
804 SERVER_END_REQ;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +0000805
Francois Gouget69e35002002-05-19 22:20:31 +0000806 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
807 {
808 WIN_ReleaseWndPtr( pWndDesktop );
809 return FALSE;
810 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000811
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000812 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
Alexandre Julliard1a66d222001-08-28 18:44:52 +0000813 WIN_ReleaseWndPtr( pWndDesktop );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000814 return TRUE;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000815}
816
817
818/***********************************************************************
Dmitry Timoshkov5956b982000-11-28 23:53:08 +0000819 * WIN_FixCoordinates
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000820 *
Gerard Patel78f52b52000-05-31 19:23:20 +0000821 * Fix the coordinates - Helper for WIN_CreateWindowEx.
822 * returns default show mode in sw.
823 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
824 */
825static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
826{
827 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
828 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
829 {
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000830 if (cs->style & (WS_CHILD | WS_POPUP))
Gerard Patel78f52b52000-05-31 19:23:20 +0000831 {
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000832 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
833 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
Gerard Patel78f52b52000-05-31 19:23:20 +0000834 }
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000835 else /* overlapped window */
Gerard Patel78f52b52000-05-31 19:23:20 +0000836 {
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000837 STARTUPINFOA info;
838
839 GetStartupInfoA( &info );
840
841 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
842 {
Alexandre Julliard0d92fe22001-09-10 23:26:42 +0000843 /* Never believe Microsoft's documentation... CreateWindowEx doc says
844 * that if an overlapped window is created with WS_VISIBLE style bit
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000845 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
846 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
847 * reveals that
848 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +0000849 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
850 * 2) it does not ignore the y parameter as the docs claim; instead, it
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000851 * uses it as second parameter to ShowWindow() unless y is either
852 * CW_USEDEFAULT or CW_USEDEFAULT16.
Alexandre Julliard0d92fe22001-09-10 23:26:42 +0000853 *
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000854 * The fact that we didn't do 2) caused bogus windows pop up when wine
Alexandre Julliard0d92fe22001-09-10 23:26:42 +0000855 * was running apps that were using this obscure feature. Example -
856 * calc.exe that comes with Win98 (only Win98, it's different from
Alexandre Julliard6aa28432000-06-08 01:01:09 +0000857 * the one that comes with Win95 and NT)
858 */
859 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
860 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
861 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
862 }
863
864 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
865 {
866 if (info.dwFlags & STARTF_USESIZE)
867 {
868 cs->cx = info.dwXSize;
869 cs->cy = info.dwYSize;
870 }
871 else /* if no other hint from the app, pick 3/4 of the screen real estate */
872 {
873 RECT r;
874 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
875 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
876 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
877 }
878 }
Gerard Patel78f52b52000-05-31 19:23:20 +0000879 }
880 }
Guy L. Albertellif1a624d2002-02-27 01:20:54 +0000881 else
882 {
883 /* neither x nor cx are default. Check the y values .
Vincent Béron9a624912002-05-31 23:06:46 +0000884 * In the trace we see Outlook and Outlook Express using
Guy L. Albertellif1a624d2002-02-27 01:20:54 +0000885 * cy set to CW_USEDEFAULT when opening the address book.
886 */
887 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
888 RECT r;
889 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
890 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
891 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
892 }
893 }
Gerard Patel78f52b52000-05-31 19:23:20 +0000894}
895
896/***********************************************************************
Dmitry Timoshkov5d3e1f72001-11-07 21:52:24 +0000897 * dump_window_styles
898 */
899static void dump_window_styles( DWORD style, DWORD exstyle )
900{
901 TRACE( "style:" );
902 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
903 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
904 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
905 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
906 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
907 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
908 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
909 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
910 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
911 else
912 {
913 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
914 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
915 }
916 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
917 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
918 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
919 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
920 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
921 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
922 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
923 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
924
925 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
926#define DUMPED_STYLES \
927 (WS_POPUP | \
928 WS_CHILD | \
929 WS_MINIMIZE | \
930 WS_VISIBLE | \
931 WS_DISABLED | \
932 WS_CLIPSIBLINGS | \
933 WS_CLIPCHILDREN | \
934 WS_MAXIMIZE | \
935 WS_BORDER | \
936 WS_DLGFRAME | \
937 WS_VSCROLL | \
938 WS_HSCROLL | \
939 WS_SYSMENU | \
940 WS_THICKFRAME | \
941 WS_GROUP | \
942 WS_TABSTOP | \
943 WS_MINIMIZEBOX | \
944 WS_MAXIMIZEBOX)
945
946 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
947 DPRINTF("\n");
948#undef DUMPED_STYLES
949
950 TRACE( "exstyle:" );
951 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
952 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
953 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
954 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
955 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
956 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
957 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
958 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
959 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
960 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
961 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
962 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
963 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
964 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
965 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
966 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
967 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
968 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
969
970#define DUMPED_EX_STYLES \
971 (WS_EX_DLGMODALFRAME | \
972 WS_EX_DRAGDETECT | \
973 WS_EX_NOPARENTNOTIFY | \
974 WS_EX_TOPMOST | \
975 WS_EX_ACCEPTFILES | \
976 WS_EX_TRANSPARENT | \
977 WS_EX_MDICHILD | \
978 WS_EX_TOOLWINDOW | \
979 WS_EX_WINDOWEDGE | \
980 WS_EX_CLIENTEDGE | \
981 WS_EX_CONTEXTHELP | \
982 WS_EX_RIGHT | \
983 WS_EX_RTLREADING | \
984 WS_EX_LEFTSCROLLBAR | \
985 WS_EX_CONTROLPARENT | \
986 WS_EX_STATICEDGE | \
987 WS_EX_APPWINDOW | \
988 WS_EX_LAYERED)
989
990 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
991 DPRINTF("\n");
992#undef DUMPED_EX_STYLES
993}
994
995
996/***********************************************************************
Gerard Patel78f52b52000-05-31 19:23:20 +0000997 * WIN_CreateWindowEx
998 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000999 * Implementation of CreateWindowEx().
Alexandre Julliard401710d1993-09-04 10:09:32 +00001000 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001001static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001002 WINDOWPROCTYPE type )
Alexandre Julliard401710d1993-09-04 10:09:32 +00001003{
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001004 INT sw = SW_SHOW;
Alexandre Julliard98779062000-12-07 23:39:16 +00001005 struct tagCLASS *classPtr;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +00001006 WND *wndPtr;
Rein Klazes0f2f2b32002-01-09 19:09:06 +00001007 HWND hwnd, parent, owner;
Alexandre Julliard98779062000-12-07 23:39:16 +00001008 INT wndExtra;
1009 DWORD clsStyle;
1010 WNDPROC winproc;
1011 DCE *dce;
Gerard Patelad363032001-06-06 21:26:50 +00001012 BOOL unicode = (type == WIN_PROC_32W);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001013
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00001014 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 +00001015 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1016 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001017 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1018 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
Alexandre Julliard401710d1993-09-04 10:09:32 +00001019
Dmitry Timoshkov5d3e1f72001-11-07 21:52:24 +00001020 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1021
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001022 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1023 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1024
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001025 /* Find the parent window */
Alexandre Julliard401710d1993-09-04 10:09:32 +00001026
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00001027 parent = GetDesktopWindow();
1028 owner = 0;
Juergen Schmiedeb2db1a2002-08-29 01:49:46 +00001029
1030 if (cs->hwndParent == HWND_MESSAGE)
1031 {
1032 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1033 * message window (style: WS_POPUP|WS_DISABLED)
1034 */
1035 FIXME("Parent is HWND_MESSAGE\n");
1036 }
1037 else if (cs->hwndParent)
Alexandre Julliard401710d1993-09-04 10:09:32 +00001038 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001039 /* Make sure parent is valid */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001040 if (!IsWindow( cs->hwndParent ))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001041 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001042 WARN("Bad parent %04x\n", cs->hwndParent );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001043 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001044 }
Alexandre Julliard7dafa612002-09-25 00:21:56 +00001045 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1046 parent = WIN_GetFullHandle(cs->hwndParent);
1047 else
1048 owner = GetAncestor( cs->hwndParent, GA_ROOT );
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00001049 }
Alexandre Julliard7dafa612002-09-25 00:21:56 +00001050 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00001051 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001052 WARN("No parent for child window\n" );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001053 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001054 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001055
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001056 /* Find the window class */
Alexandre Julliard98779062000-12-07 23:39:16 +00001057 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1058 &wndExtra, &winproc, &clsStyle, &dce )))
Alexandre Julliard808cb041995-08-17 17:11:36 +00001059 {
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001060 WARN("Bad class '%s'\n", cs->lpszClass );
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001061 return 0;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001062 }
Alexandre Julliardcdd09231994-01-12 11:12:51 +00001063
Gerard Patel78f52b52000-05-31 19:23:20 +00001064 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
Alexandre Julliardcdd09231994-01-12 11:12:51 +00001065
Bill Medland3f68bc92001-07-20 18:36:25 +00001066 /* Correct the window style - stage 1
1067 *
1068 * These are patches that appear to affect both the style loaded into the
1069 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1070 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001071 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
Bill Medland3f68bc92001-07-20 18:36:25 +00001072 * why does the user get to set it?
1073 */
1074
1075 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1076 * tested for WS_POPUP
1077 */
1078 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1079 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1080 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1081 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1082 else
1083 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1084
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001085 /* Create the window structure */
Alexandre Julliard401710d1993-09-04 10:09:32 +00001086
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001087 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
Alexandre Julliard1a66d222001-08-28 18:44:52 +00001088 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001089 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001090 TRACE("out of memory\n" );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001091 return 0;
1092 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00001093 hwnd = wndPtr->hwndSelf;
Alexandre Julliard401710d1993-09-04 10:09:32 +00001094
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001095 /* Fill the window structure */
Alexandre Julliard401710d1993-09-04 10:09:32 +00001096
Alexandre Julliard80593bf2001-10-11 20:49:40 +00001097 wndPtr->tid = GetCurrentThreadId();
1098 wndPtr->owner = owner;
Alexandre Julliard556607a2001-10-10 20:28:17 +00001099 wndPtr->parent = parent;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001100 wndPtr->class = classPtr;
Alexandre Julliard98779062000-12-07 23:39:16 +00001101 wndPtr->winproc = winproc;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001102 wndPtr->hInstance = cs->hInstance;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001103 wndPtr->text = NULL;
Alexandre Julliard8afe6622001-07-26 20:12:22 +00001104 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001105 wndPtr->hrgnUpdate = 0;
Huw D M Daviesa14ca862000-07-29 11:31:29 +00001106 wndPtr->hrgnWnd = 0;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001107 wndPtr->hwndLastActive = hwnd;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001108 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1109 wndPtr->dwExStyle = cs->dwExStyle;
Alexandre Julliard98779062000-12-07 23:39:16 +00001110 wndPtr->clsStyle = clsStyle;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001111 wndPtr->wIDmenu = 0;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001112 wndPtr->helpContext = 0;
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001113 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
Alexandre Julliardca22b331996-07-12 19:02:39 +00001114 wndPtr->pVScroll = NULL;
1115 wndPtr->pHScroll = NULL;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001116 wndPtr->userdata = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001117 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1118 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
Alexandre Julliard98779062000-12-07 23:39:16 +00001119 wndPtr->cbWndExtra = wndExtra;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001120
Alexandre Julliard98779062000-12-07 23:39:16 +00001121 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001122
Bill Medland3f68bc92001-07-20 18:36:25 +00001123 /* Correct the window style - stage 2 */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001124
Alex Korobka44a1b591999-04-01 12:03:52 +00001125 if (!(cs->style & WS_CHILD))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001126 {
Alex Korobka44a1b591999-04-01 12:03:52 +00001127 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1128 if (!(cs->style & WS_POPUP))
1129 {
1130 wndPtr->dwStyle |= WS_CAPTION;
1131 wndPtr->flags |= WIN_NEED_SIZE;
1132 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001133 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001134 SERVER_START_REQ( set_window_info )
1135 {
1136 req->handle = hwnd;
1137 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1138 req->style = wndPtr->dwStyle;
1139 req->ex_style = wndPtr->dwExStyle;
1140 req->instance = (void *)wndPtr->hInstance;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00001141 wine_server_call( req );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001142 }
1143 SERVER_END_REQ;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001144
1145 /* Get class or window DC if needed */
Alexandre Julliardaca05781994-10-17 18:12:41 +00001146
Alexandre Julliard98779062000-12-07 23:39:16 +00001147 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1148 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001149 else wndPtr->dce = NULL;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001150
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001151 /* Set the window menu */
1152
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001153 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001154 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001155 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001156 else
1157 {
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001158 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
Alexandre Julliard54c27111998-03-29 19:44:57 +00001159 if (menuName)
1160 {
Ulrich Weigand7df1fbb1998-11-01 18:01:53 +00001161 if (HIWORD(cs->hInstance))
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001162 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
Alexandre Julliard54c27111998-03-29 19:44:57 +00001163 else
Alexandre Julliard54c27111998-03-29 19:44:57 +00001164 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1165
Alexandre Julliarda3960291999-02-26 11:11:13 +00001166 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
Alexandre Julliard54c27111998-03-29 19:44:57 +00001167 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001168 }
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001169 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001170 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1171 WIN_ReleaseWndPtr( wndPtr );
Alexandre Julliard490a27e1994-06-08 13:57:50 +00001172
Alexandre Julliard80593bf2001-10-11 20:49:40 +00001173 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001174 {
Alexandre Julliard80593bf2001-10-11 20:49:40 +00001175 WIN_DestroyWindow( hwnd );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001176 return 0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001177 }
Alexandre Julliard401710d1993-09-04 10:09:32 +00001178
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001179 /* Notify the parent window only */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001180
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001181 send_parent_notify( hwnd, WM_CREATE );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001182 if (!IsWindow( hwnd )) return 0;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001183
1184 if (cs->style & WS_VISIBLE)
1185 {
1186 /* in case WS_VISIBLE got set in the meantime */
Alexandre Julliardddc33172001-10-22 19:08:33 +00001187 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1188 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1189 WIN_ReleasePtr( wndPtr );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001190 ShowWindow( hwnd, sw );
1191 }
1192
1193 /* Call WH_SHELL hook */
1194
Alexandre Julliardddc33172001-10-22 19:08:33 +00001195 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001196 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001197
1198 TRACE("created window %04x\n", hwnd);
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001199 return hwnd;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001200}
1201
1202
1203/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001204 * CreateWindow (USER.41)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001205 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001206HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1207 DWORD style, INT16 x, INT16 y, INT16 width,
1208 INT16 height, HWND16 parent, HMENU16 menu,
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001209 HINSTANCE16 instance, LPVOID data )
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001210{
1211 return CreateWindowEx16( 0, className, windowName, style,
1212 x, y, width, height, parent, menu, instance, data );
1213}
1214
1215
1216/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001217 * CreateWindowEx (USER.452)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001218 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001219HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1220 LPCSTR windowName, DWORD style, INT16 x,
1221 INT16 y, INT16 width, INT16 height,
1222 HWND16 parent, HMENU16 menu,
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001223 HINSTANCE16 instance, LPVOID data )
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001224{
1225 ATOM classAtom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001226 CREATESTRUCTA cs;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001227 char buffer[256];
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001228
1229 /* Find the class atom */
1230
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001231 if (HIWORD(className))
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001232 {
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001233 if (!(classAtom = GlobalFindAtomA( className )))
1234 {
Alexandre Julliard0aa28b52002-05-17 02:55:48 +00001235 ERR( "bad class name %s\n", debugstr_a(className) );
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001236 return 0;
1237 }
1238 }
1239 else
1240 {
1241 classAtom = LOWORD(className);
1242 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1243 {
1244 ERR( "bad atom %x\n", classAtom);
1245 return 0;
1246 }
1247 className = buffer;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001248 }
1249
1250 /* Fix the coordinates */
1251
Alexandre Julliarda3960291999-02-26 11:11:13 +00001252 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1253 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1254 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1255 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001256
1257 /* Create the window */
1258
1259 cs.lpCreateParams = data;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001260 cs.hInstance = (HINSTANCE)instance;
1261 cs.hMenu = (HMENU)menu;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001262 cs.hwndParent = WIN_Handle32( parent );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001263 cs.style = style;
1264 cs.lpszName = windowName;
1265 cs.lpszClass = className;
1266 cs.dwExStyle = exStyle;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001267
Michael Stefaniuc2247af32002-09-04 19:37:01 +00001268 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001269}
1270
1271
1272/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001273 * CreateWindowExA (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001274 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001275HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1276 LPCSTR windowName, DWORD style, INT x,
1277 INT y, INT width, INT height,
1278 HWND parent, HMENU menu,
1279 HINSTANCE instance, LPVOID data )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001280{
1281 ATOM classAtom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001282 CREATESTRUCTA cs;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001283 char buffer[256];
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001284
Rein Klazesd4a2cee1999-10-23 13:57:36 +00001285 if(!instance)
1286 instance=GetModuleHandleA(NULL);
1287
Rein Klazes5c6fc1b1998-11-01 14:50:06 +00001288 if(exStyle & WS_EX_MDICHILD)
Dmitry Timoshkov91adf0a2001-02-12 03:40:41 +00001289 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001290
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001291 /* Find the class atom */
1292
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001293 if (HIWORD(className))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001294 {
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001295 if (!(classAtom = GlobalFindAtomA( className )))
1296 {
Alexandre Julliard0aa28b52002-05-17 02:55:48 +00001297 ERR( "bad class name %s\n", debugstr_a(className) );
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001298 return 0;
1299 }
1300 }
1301 else
1302 {
1303 classAtom = LOWORD(className);
1304 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1305 {
1306 ERR( "bad atom %x\n", classAtom);
1307 return 0;
1308 }
1309 className = buffer;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001310 }
1311
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001312 /* Create the window */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001313
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001314 cs.lpCreateParams = data;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001315 cs.hInstance = instance;
1316 cs.hMenu = menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001317 cs.hwndParent = parent;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001318 cs.x = x;
1319 cs.y = y;
1320 cs.cx = width;
1321 cs.cy = height;
1322 cs.style = style;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001323 cs.lpszName = windowName;
1324 cs.lpszClass = className;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001325 cs.dwExStyle = exStyle;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001326
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001327 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001328}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001329
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001330
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001331/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001332 * CreateWindowExW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001333 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001334HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1335 LPCWSTR windowName, DWORD style, INT x,
1336 INT y, INT width, INT height,
1337 HWND parent, HMENU menu,
1338 HINSTANCE instance, LPVOID data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001339{
1340 ATOM classAtom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001341 CREATESTRUCTW cs;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001342 WCHAR buffer[256];
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001343
Rein Klazesd4a2cee1999-10-23 13:57:36 +00001344 if(!instance)
1345 instance=GetModuleHandleA(NULL);
1346
Rein Klazes5c6fc1b1998-11-01 14:50:06 +00001347 if(exStyle & WS_EX_MDICHILD)
Dmitry Timoshkov91adf0a2001-02-12 03:40:41 +00001348 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
Rein Klazes5c6fc1b1998-11-01 14:50:06 +00001349
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001350 /* Find the class atom */
1351
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001352 if (HIWORD(className))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001353 {
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001354 if (!(classAtom = GlobalFindAtomW( className )))
1355 {
Alexandre Julliard0aa28b52002-05-17 02:55:48 +00001356 ERR( "bad class name %s\n", debugstr_w(className) );
Gerard Patel6fdb5dd2000-02-16 21:23:24 +00001357 return 0;
1358 }
1359 }
1360 else
1361 {
1362 classAtom = LOWORD(className);
1363 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1364 {
1365 ERR( "bad atom %x\n", classAtom);
1366 return 0;
1367 }
1368 className = buffer;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001369 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001370
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001371 /* Create the window */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001372
1373 cs.lpCreateParams = data;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001374 cs.hInstance = instance;
1375 cs.hMenu = menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001376 cs.hwndParent = parent;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001377 cs.x = x;
1378 cs.y = y;
1379 cs.cx = width;
1380 cs.cy = height;
1381 cs.style = style;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001382 cs.lpszName = windowName;
1383 cs.lpszClass = className;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001384 cs.dwExStyle = exStyle;
Alexandre Julliardf1f68312000-01-01 22:22:21 +00001385
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001386 /* Note: we rely on the fact that CREATESTRUCTA and */
1387 /* CREATESTRUCTW have the same layout. */
Dmitry Timoshkov5956b982000-11-28 23:53:08 +00001388 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
Alexandre Julliard401710d1993-09-04 10:09:32 +00001389}
1390
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001391
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001392/***********************************************************************
1393 * WIN_SendDestroyMsg
1394 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001395static void WIN_SendDestroyMsg( HWND hwnd )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001396{
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001397 if( CARET_GetHwnd() == hwnd) DestroyCaret();
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00001398 if (USER_Driver.pResetSelectionOwner)
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001399 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001400
1401 /*
1402 * Send the WM_DESTROY to the window.
1403 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001404 SendMessageA( hwnd, WM_DESTROY, 0, 0);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001405
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001406 /*
1407 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1408 * make sure that the window still exists when we come back.
1409 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001410 if (IsWindow(hwnd))
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001411 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001412 HWND* pWndArray;
1413 int i;
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001414
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00001415 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001416
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001417 /* start from the end (FIXME: is this needed?) */
1418 for (i = 0; pWndArray[i]; i++) ;
Francis Beaudeteb6a9f01999-03-17 15:17:48 +00001419
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001420 while (--i >= 0)
1421 {
1422 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1423 }
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00001424 HeapFree( GetProcessHeap(), 0, pWndArray );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001425 }
1426 else
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001427 WARN("\tdestroyed itself while in WM_DESTROY!\n");
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001428}
1429
1430
1431/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001432 * DestroyWindow (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00001433 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001434BOOL WINAPI DestroyWindow( HWND hwnd )
Alexandre Julliard401710d1993-09-04 10:09:32 +00001435{
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001436 BOOL is_child;
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001437 HWND h;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +00001438
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001439 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1440 {
1441 SetLastError( ERROR_ACCESS_DENIED );
1442 return FALSE;
1443 }
1444
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001445 TRACE("(%04x)\n", hwnd);
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001446
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001447 /* Look whether the focus is within the tree of windows we will
1448 * be destroying.
1449 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001450 h = GetFocus();
1451 if (h == hwnd || IsChild( hwnd, h ))
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001452 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001453 HWND parent = GetAncestor( hwnd, GA_PARENT );
1454 if (parent == GetDesktopWindow()) parent = 0;
1455 SetFocus( parent );
Alexandre Julliard1f029ea2000-11-02 20:08:59 +00001456 }
1457
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001458 /* Call hooks */
1459
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001460 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001461
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001462 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1463
1464 if (is_child)
1465 {
1466 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1467 send_parent_notify( hwnd, WM_DESTROY );
1468 }
1469 else if (!GetWindow( hwnd, GW_OWNER ))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001470 {
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001471 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001472 /* FIXME: clean up palette - see "Internals" p.352 */
1473 }
1474
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001475 if (!IsWindow(hwnd)) return TRUE;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001476
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00001477 if (USER_Driver.pResetSelectionOwner)
1478 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001479
Alexandre Julliard58199531994-04-21 01:20:00 +00001480 /* Hide the window */
1481
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00001482 ShowWindow( hwnd, SW_HIDE );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001483 if (!IsWindow(hwnd)) return TRUE;
Alexandre Julliard0e607781993-11-03 19:23:37 +00001484
Alexandre Julliard22945d51995-03-02 17:44:29 +00001485 /* Recursively destroy owned windows */
1486
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001487 if (!is_child)
Alexandre Julliard22945d51995-03-02 17:44:29 +00001488 {
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00001489 HWND owner;
1490
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 Julliard2c69f6d1996-09-28 18:11:01 +00001512
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001513 WINPOS_ActivateOtherWindow( hwnd );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001514
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001515 if ((owner = GetWindow( hwnd, GW_OWNER )))
1516 {
1517 WND *ptr = WIN_FindWndPtr( owner );
1518 if (ptr)
1519 {
1520 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1521 WIN_ReleaseWndPtr( ptr );
1522 }
1523 }
Alexandre Julliard22945d51995-03-02 17:44:29 +00001524 }
1525
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001526 /* Send destroy messages */
Alexandre Julliard0e607781993-11-03 19:23:37 +00001527
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001528 WIN_SendDestroyMsg( hwnd );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001529 if (!IsWindow( hwnd )) return TRUE;
Alexandre Julliard401710d1993-09-04 10:09:32 +00001530
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001531 /* Unlink now so we won't bother with the children later on */
Alexandre Julliard401710d1993-09-04 10:09:32 +00001532
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001533 WIN_UnlinkWindow( hwnd );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001534
1535 /* Destroy the window storage */
1536
Alexandre Julliard80593bf2001-10-11 20:49:40 +00001537 WIN_DestroyWindow( hwnd );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001538 return TRUE;
Alexandre Julliard401710d1993-09-04 10:09:32 +00001539}
1540
1541
1542/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001543 * CloseWindow (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001544 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001545BOOL WINAPI CloseWindow( HWND hwnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001546{
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001547 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001548 ShowWindow( hwnd, SW_MINIMIZE );
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001549 return TRUE;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001550}
1551
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001552
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001553/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001554 * OpenIcon (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001555 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001556BOOL WINAPI OpenIcon( HWND hwnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001557{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001558 if (!IsIconic( hwnd )) return FALSE;
1559 ShowWindow( hwnd, SW_SHOWNORMAL );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001560 return TRUE;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001561}
1562
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001563
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001564/***********************************************************************
1565 * WIN_FindWindow
1566 *
1567 * Implementation of FindWindow() and FindWindowEx().
1568 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001569static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001570{
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001571 HWND *list = NULL;
1572 HWND retvalue = 0;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001573 int i = 0, len = 0;
1574 WCHAR *buffer = NULL;
1575
1576 if (!parent) parent = GetDesktopWindow();
1577 if (title)
1578 {
1579 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1580 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1581 }
1582
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001583 if (!(list = list_window_children( parent, className, 0 ))) goto done;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001584
1585 if (child)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001586 {
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00001587 child = WIN_GetFullHandle( child );
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001588 while (list[i] && list[i] != child) i++;
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001589 if (!list[i]) goto done;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001590 i++; /* start from next window */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001591 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001592
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001593 if (title)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001594 {
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001595 while (list[i])
1596 {
1597 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1598 i++;
1599 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001600 }
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001601 retvalue = list[i];
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00001602
Alexandre Julliard844ceb92001-10-09 23:26:40 +00001603 done:
1604 if (list) HeapFree( GetProcessHeap(), 0, list );
1605 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001606 return retvalue;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001607}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001608
1609
1610
1611/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001612 * FindWindowA (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001613 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001614HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001615{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001616 HWND ret = FindWindowExA( 0, 0, className, title );
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001617 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1618 return ret;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001619}
1620
1621
1622/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001623 * FindWindowExA (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001624 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001625HWND WINAPI FindWindowExA( HWND parent, HWND child,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001626 LPCSTR className, LPCSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001627{
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001628 ATOM atom = 0;
Dmitry Timoshkov04da8b82000-07-10 12:09:31 +00001629 LPWSTR buffer;
1630 HWND hwnd;
Alexandre Julliard193cf502002-01-01 00:24:30 +00001631 INT len;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001632
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001633 if (className)
1634 {
1635 /* If the atom doesn't exist, then no class */
1636 /* with this name exists either. */
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001637 if (!(atom = GlobalFindAtomA( className )))
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001638 {
1639 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1640 return 0;
1641 }
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001642 }
Alexandre Julliard193cf502002-01-01 00:24:30 +00001643 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
Dmitry Timoshkov04da8b82000-07-10 12:09:31 +00001644
Alexandre Julliard193cf502002-01-01 00:24:30 +00001645 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1646 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1647 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
Dmitry Timoshkov04da8b82000-07-10 12:09:31 +00001648 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1649 HeapFree( GetProcessHeap(), 0, buffer );
1650 return hwnd;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001651}
1652
1653
1654/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001655 * FindWindowExW (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001656 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001657HWND WINAPI FindWindowExW( HWND parent, HWND child,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001658 LPCWSTR className, LPCWSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001659{
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001660 ATOM atom = 0;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001661
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001662 if (className)
1663 {
1664 /* If the atom doesn't exist, then no class */
1665 /* with this name exists either. */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001666 if (!(atom = GlobalFindAtomW( className )))
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001667 {
1668 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1669 return 0;
1670 }
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001671 }
Dmitry Timoshkov04da8b82000-07-10 12:09:31 +00001672 return WIN_FindWindow( parent, child, atom, title );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001673}
1674
1675
1676/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001677 * FindWindowW (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001678 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001679HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001680{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001681 return FindWindowExW( 0, 0, className, title );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001682}
1683
1684
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001685/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001686 * GetDesktopWindow (USER32.@)
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001687 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001688HWND WINAPI GetDesktopWindow(void)
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001689{
Uwe Bonnes73619161999-10-24 20:42:39 +00001690 if (pWndDesktop) return pWndDesktop->hwndSelf;
Gerard Patele717b1b2001-11-19 02:07:11 +00001691 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 +00001692 ExitProcess(1);
Huw D M Davies238b6d71999-10-31 01:56:51 +00001693 return 0;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001694}
1695
1696
Alexandre Julliard01d63461997-01-20 19:43:45 +00001697/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001698 * EnableWindow (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00001699 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001700BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001701{
1702 WND *wndPtr;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001703 BOOL retvalue;
Alexandre Julliardddc33172001-10-22 19:08:33 +00001704 LONG style;
1705 HWND full_handle;
1706
1707 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1708 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1709
1710 hwnd = full_handle;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001711
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001712 TRACE("( %x, %d )\n", hwnd, enable);
1713
Alexandre Julliardddc33172001-10-22 19:08:33 +00001714 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1715 style = wndPtr->dwStyle;
1716 retvalue = ((style & WS_DISABLED) != 0);
1717 WIN_ReleasePtr( wndPtr );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001718
Alexandre Julliardddc33172001-10-22 19:08:33 +00001719 if (enable && retvalue)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001720 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00001721 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001722 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001723 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001724 else if (!enable && !retvalue)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001725 {
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00001726 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
Alex Korobka4f1ac051999-03-28 09:37:57 +00001727
Alexandre Julliardddc33172001-10-22 19:08:33 +00001728 WIN_SetStyle( hwnd, style | WS_DISABLED );
Alex Korobka4f1ac051999-03-28 09:37:57 +00001729
Alexandre Julliard481f8ff2002-04-08 23:57:08 +00001730 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001731 SetFocus( 0 ); /* A disabled window can't have the focus */
Alex Korobka4f1ac051999-03-28 09:37:57 +00001732
Alexandre Julliard481f8ff2002-04-08 23:57:08 +00001733 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001734 ReleaseCapture(); /* A disabled window can't capture the mouse */
1735
1736 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001737 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001738 return retvalue;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001739}
1740
1741
1742/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001743 * IsWindowEnabled (USER32.@)
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001744 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001745BOOL WINAPI IsWindowEnabled(HWND hWnd)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001746{
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001747 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001748}
1749
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001750
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001751/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001752 * IsWindowUnicode (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001753 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001754BOOL WINAPI IsWindowUnicode( HWND hwnd )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001755{
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001756 WND * wndPtr;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001757 BOOL retvalue;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001758
1759 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001760 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1761 WIN_ReleaseWndPtr(wndPtr);
1762 return retvalue;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001763}
1764
1765
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001766/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001767 * GetWindowWord (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00001768 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001769WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001770{
Alexandre Julliard3051b641996-07-05 17:14:13 +00001771 if (offset >= 0)
1772 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00001773 WORD retvalue = 0;
1774 WND *wndPtr = WIN_GetPtr( hwnd );
1775 if (!wndPtr)
1776 {
1777 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1778 return 0;
1779 }
1780 if (wndPtr == WND_OTHER_PROCESS)
1781 {
1782 if (IsWindow( hwnd ))
1783 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1784 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1785 return 0;
1786 }
1787 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
Alexandre Julliard3051b641996-07-05 17:14:13 +00001788 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001789 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001790 SetLastError( ERROR_INVALID_INDEX );
Alexandre Julliard3051b641996-07-05 17:14:13 +00001791 }
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001792 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
Alexandre Julliardddc33172001-10-22 19:08:33 +00001793 WIN_ReleasePtr( wndPtr );
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001794 return retvalue;
Alexandre Julliard3051b641996-07-05 17:14:13 +00001795 }
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001796
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001797 switch(offset)
1798 {
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001799 case GWL_HWNDPARENT:
1800 return GetWindowLongW( hwnd, offset );
1801 case GWL_ID:
1802 case GWL_HINSTANCE:
1803 {
1804 LONG ret = GetWindowLongW( hwnd, offset );
1805 if (HIWORD(ret))
1806 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1807 return LOWORD(ret);
1808 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001809 default:
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001810 WARN("Invalid offset %d\n", offset );
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001811 return 0;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001812 }
Alexandre Julliard21979011997-03-05 08:22:35 +00001813}
1814
1815
1816/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001817 * SetWindowWord (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00001818 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001819WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001820{
1821 WORD *ptr, retval;
Alexandre Julliardddc33172001-10-22 19:08:33 +00001822 WND * wndPtr;
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001823
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001824 switch(offset)
1825 {
1826 case GWL_ID:
1827 case GWL_HINSTANCE:
1828 case GWL_HWNDPARENT:
1829 return SetWindowLongW( hwnd, offset, (UINT)newval );
1830 default:
Alexandre Julliardddc33172001-10-22 19:08:33 +00001831 if (offset < 0)
1832 {
1833 WARN("Invalid offset %d\n", offset );
1834 SetLastError( ERROR_INVALID_INDEX );
1835 return 0;
1836 }
1837 }
1838
1839 wndPtr = WIN_GetPtr( hwnd );
1840 if (wndPtr == WND_OTHER_PROCESS)
1841 {
1842 if (IsWindow(hwnd))
1843 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1844 offset, newval, hwnd );
1845 wndPtr = NULL;
1846 }
1847 if (!wndPtr)
1848 {
1849 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1850 return 0;
1851 }
1852
1853 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1854 {
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001855 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001856 WIN_ReleasePtr(wndPtr);
1857 SetLastError( ERROR_INVALID_INDEX );
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001858 return 0;
1859 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001860 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1861 retval = *ptr;
1862 *ptr = newval;
1863 WIN_ReleasePtr(wndPtr);
1864 return retval;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001865}
1866
1867
1868/**********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +00001869 * WIN_GetWindowLong
1870 *
1871 * Helper function for GetWindowLong().
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001872 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001873static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001874{
Alexandre Julliardddc33172001-10-22 19:08:33 +00001875 LONG retvalue = 0;
1876 WND *wndPtr;
1877
Alexandre Julliard7dafa612002-09-25 00:21:56 +00001878 if (offset == GWL_HWNDPARENT)
1879 {
1880 HWND parent = GetAncestor( hwnd, GA_PARENT );
1881 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1882 return (LONG)parent;
1883 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001884
1885 if (!(wndPtr = WIN_GetPtr( hwnd )))
1886 {
1887 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1888 return 0;
1889 }
1890
1891 if (wndPtr == WND_OTHER_PROCESS)
1892 {
1893 if (offset >= 0)
1894 {
Alexandre Julliard96ebfa92001-10-23 20:35:44 +00001895 if (IsWindow(hwnd))
1896 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001897 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1898 return 0;
1899 }
1900 if (offset == GWL_WNDPROC)
1901 {
1902 SetLastError( ERROR_ACCESS_DENIED );
1903 return 0;
1904 }
1905 SERVER_START_REQ( set_window_info )
1906 {
1907 req->handle = hwnd;
1908 req->flags = 0; /* don't set anything, just retrieve */
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00001909 if (!wine_server_call_err( req ))
Alexandre Julliardddc33172001-10-22 19:08:33 +00001910 {
1911 switch(offset)
1912 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00001913 case GWL_STYLE: retvalue = reply->old_style; break;
1914 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1915 case GWL_ID: retvalue = reply->old_id; break;
1916 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1917 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
Alexandre Julliardddc33172001-10-22 19:08:33 +00001918 default:
1919 SetLastError( ERROR_INVALID_INDEX );
1920 break;
1921 }
1922 }
1923 }
1924 SERVER_END_REQ;
1925 return retvalue;
1926 }
1927
1928 /* now we have a valid wndPtr */
1929
Alexandre Julliard3051b641996-07-05 17:14:13 +00001930 if (offset >= 0)
1931 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00001932 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
Alexandre Julliard3051b641996-07-05 17:14:13 +00001933 {
Jukka Heinonen3fead8f2002-02-15 18:22:23 +00001934 /*
1935 * Some programs try to access last element from 16 bit
1936 * code using illegal offset value. Hopefully this is
1937 * what those programs really expect.
1938 */
Vincent Béron9a624912002-05-31 23:06:46 +00001939 if (type == WIN_PROC_16 &&
Jukka Heinonen3fead8f2002-02-15 18:22:23 +00001940 wndPtr->cbWndExtra >= 4 &&
1941 offset == wndPtr->cbWndExtra - sizeof(WORD))
1942 {
1943 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
Vincent Béron9a624912002-05-31 23:06:46 +00001944
Jukka Heinonen3fead8f2002-02-15 18:22:23 +00001945 ERR( "- replaced invalid offset %d with %d\n",
1946 offset, offset2 );
Vincent Béron9a624912002-05-31 23:06:46 +00001947
Jukka Heinonen3fead8f2002-02-15 18:22:23 +00001948 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1949 WIN_ReleasePtr( wndPtr );
1950 return retvalue;
1951 }
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001952 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001953 WIN_ReleasePtr( wndPtr );
1954 SetLastError( ERROR_INVALID_INDEX );
1955 return 0;
Alexandre Julliard3051b641996-07-05 17:14:13 +00001956 }
Gerard Patele717b1b2001-11-19 02:07:11 +00001957 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
Alexandre Julliard3051b641996-07-05 17:14:13 +00001958 /* Special case for dialog window procedure */
1959 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001960 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
Alexandre Julliardddc33172001-10-22 19:08:33 +00001961 WIN_ReleasePtr( wndPtr );
1962 return retvalue;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001963 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001964
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001965 switch(offset)
1966 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00001967 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1968 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1969 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1970 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1971 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1972 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1973 default:
1974 WARN("Unknown offset %d\n", offset );
1975 SetLastError( ERROR_INVALID_INDEX );
1976 break;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001977 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00001978 WIN_ReleasePtr(wndPtr);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001979 return retvalue;
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001980}
1981
1982
1983/**********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +00001984 * WIN_SetWindowLong
1985 *
1986 * Helper function for SetWindowLong().
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001987 *
1988 * 0 is the failure code. However, in the case of failure SetLastError
1989 * must be set to distinguish between a 0 return value and a failure.
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001990 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001991static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
Alexandre Julliard3051b641996-07-05 17:14:13 +00001992 WINDOWPROCTYPE type )
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001993{
Alexandre Julliardddc33172001-10-22 19:08:33 +00001994 LONG retval = 0;
1995 WND *wndPtr;
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00001996
Alexandre Julliardddc33172001-10-22 19:08:33 +00001997 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001998
Alexandre Julliard55557312001-10-23 00:26:10 +00001999 if (!WIN_IsCurrentProcess( hwnd ))
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002000 {
Alexandre Julliard55557312001-10-23 00:26:10 +00002001 if (offset == GWL_WNDPROC)
2002 {
2003 SetLastError( ERROR_ACCESS_DENIED );
2004 return 0;
2005 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002006 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002007 }
2008
Alexandre Julliardddc33172001-10-22 19:08:33 +00002009 wndPtr = WIN_GetPtr( hwnd );
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002010 if (wndPtr->hwndSelf == GetDesktopWindow())
2011 {
2012 /* can't change anything on the desktop window */
Alexandre Julliard02b8cb72002-09-25 03:25:43 +00002013 WIN_ReleasePtr( wndPtr );
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002014 SetLastError( ERROR_ACCESS_DENIED );
2015 return 0;
2016 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002017
Alexandre Julliard3051b641996-07-05 17:14:13 +00002018 if (offset >= 0)
2019 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00002020 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2021 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
Alexandre Julliard3051b641996-07-05 17:14:13 +00002022 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00002023 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002024 WIN_ReleasePtr( wndPtr );
2025 SetLastError( ERROR_INVALID_INDEX );
2026 return 0;
Alexandre Julliard3051b641996-07-05 17:14:13 +00002027 }
Alexandre Julliard3051b641996-07-05 17:14:13 +00002028 /* Special case for dialog window procedure */
2029 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2030 {
2031 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002032 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002033 type, WIN_PROC_WINDOW );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002034 WIN_ReleasePtr( wndPtr );
2035 return retval;
Alexandre Julliard3051b641996-07-05 17:14:13 +00002036 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002037 retval = *ptr;
2038 *ptr = newval;
2039 WIN_ReleasePtr( wndPtr );
Alexandre Julliard3051b641996-07-05 17:14:13 +00002040 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002041 else
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002042 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00002043 STYLESTRUCT style;
2044 BOOL ok;
2045
2046 /* first some special cases */
2047 switch( offset )
2048 {
2049 case GWL_STYLE:
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002050 case GWL_EXSTYLE:
Alexandre Julliardddc33172001-10-22 19:08:33 +00002051 style.styleOld = wndPtr->dwStyle;
2052 style.styleNew = newval;
2053 WIN_ReleasePtr( wndPtr );
2054 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2055 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2056 newval = style.styleNew;
2057 break;
2058 case GWL_HWNDPARENT:
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002059 if (wndPtr->parent == GetDesktopWindow())
2060 {
2061 WIN_ReleasePtr( wndPtr );
2062 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2063 }
2064 else
2065 {
2066 WIN_ReleasePtr( wndPtr );
2067 return (LONG)SetParent( hwnd, (HWND)newval );
2068 }
Alexandre Julliardddc33172001-10-22 19:08:33 +00002069 case GWL_WNDPROC:
2070 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2071 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2072 type, WIN_PROC_WINDOW );
2073 WIN_ReleasePtr( wndPtr );
2074 return retval;
2075 case GWL_ID:
2076 case GWL_HINSTANCE:
2077 case GWL_USERDATA:
2078 break;
2079 default:
2080 WIN_ReleasePtr( wndPtr );
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00002081 WARN("Invalid offset %d\n", offset );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002082 SetLastError( ERROR_INVALID_INDEX );
2083 return 0;
2084 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002085
Alexandre Julliardddc33172001-10-22 19:08:33 +00002086 SERVER_START_REQ( set_window_info )
2087 {
2088 req->handle = hwnd;
2089 switch(offset)
2090 {
2091 case GWL_STYLE:
2092 req->flags = SET_WIN_STYLE;
2093 req->style = newval;
2094 break;
2095 case GWL_EXSTYLE:
2096 req->flags = SET_WIN_EXSTYLE;
2097 req->ex_style = newval;
2098 break;
2099 case GWL_ID:
2100 req->flags = SET_WIN_ID;
2101 req->id = newval;
2102 break;
2103 case GWL_HINSTANCE:
2104 req->flags = SET_WIN_INSTANCE;
2105 req->instance = (void *)newval;
2106 break;
2107 case GWL_USERDATA:
2108 req->flags = SET_WIN_USERDATA;
2109 req->user_data = (void *)newval;
2110 break;
2111 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002112 if ((ok = !wine_server_call_err( req )))
Alexandre Julliardddc33172001-10-22 19:08:33 +00002113 {
2114 switch(offset)
2115 {
2116 case GWL_STYLE:
2117 wndPtr->dwStyle = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002118 retval = reply->old_style;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002119 break;
2120 case GWL_EXSTYLE:
2121 wndPtr->dwExStyle = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002122 retval = reply->old_ex_style;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002123 break;
2124 case GWL_ID:
2125 wndPtr->wIDmenu = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002126 retval = reply->old_id;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002127 break;
2128 case GWL_HINSTANCE:
2129 wndPtr->hInstance = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002130 retval = (HINSTANCE)reply->old_instance;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002131 break;
2132 case GWL_USERDATA:
2133 wndPtr->userdata = newval;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002134 retval = (ULONG_PTR)reply->old_user_data;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002135 break;
2136 }
2137 }
2138 }
2139 SERVER_END_REQ;
2140 WIN_ReleasePtr( wndPtr );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002141
Alexandre Julliardddc33172001-10-22 19:08:33 +00002142 if (!ok) return 0;
2143
2144 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2145 USER_Driver.pSetWindowStyle( hwnd, retval );
2146
2147 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2148 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2149
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002150 }
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002151 return retval;
2152}
2153
2154
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002155/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002156 * GetWindowLong (USER.135)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002157 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002158LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002159{
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00002160 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
Alexandre Julliard3051b641996-07-05 17:14:13 +00002161}
2162
2163
2164/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002165 * GetWindowLongA (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002166 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002167LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002168{
2169 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2170}
2171
2172
2173/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002174 * GetWindowLongW (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002175 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002176LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002177{
2178 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2179}
2180
2181
2182/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002183 * SetWindowLong (USER.136)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002184 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002185LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002186{
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00002187 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
Alexandre Julliard3051b641996-07-05 17:14:13 +00002188}
2189
2190
2191/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002192 * SetWindowLongA (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002193 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002194LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002195{
2196 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2197}
2198
2199
2200/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002201 * SetWindowLongW (USER32.@) Set window attribute
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002202 *
2203 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002204 * value in a window's extra memory.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002205 *
2206 * The _hwnd_ parameter specifies the window. is the handle to a
2207 * window that has extra memory. The _newval_ parameter contains the
2208 * new attribute or extra memory value. If positive, the _offset_
2209 * parameter is the byte-addressed location in the window's extra
2210 * memory to set. If negative, _offset_ specifies the window
2211 * attribute to set, and should be one of the following values:
2212 *
2213 * GWL_EXSTYLE The window's extended window style
2214 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002215 * GWL_STYLE The window's window style.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002216 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002217 * GWL_WNDPROC Pointer to the window's window procedure.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002218 *
2219 * GWL_HINSTANCE The window's pplication instance handle.
2220 *
2221 * GWL_ID The window's identifier.
2222 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002223 * GWL_USERDATA The window's user-specified data.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002224 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002225 * If the window is a dialog box, the _offset_ parameter can be one of
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002226 * the following values:
2227 *
2228 * DWL_DLGPROC The address of the window's dialog box procedure.
2229 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002230 * DWL_MSGRESULT The return value of a message
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002231 * that the dialog box procedure processed.
2232 *
2233 * DWL_USER Application specific information.
2234 *
2235 * RETURNS
2236 *
2237 * If successful, returns the previous value located at _offset_. Otherwise,
2238 * returns 0.
2239 *
2240 * NOTES
2241 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002242 * Extra memory for a window class is specified by a nonzero cbWndExtra
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002243 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2244 * time of class creation.
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002245 *
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002246 * Using GWL_WNDPROC to set a new window procedure effectively creates
2247 * a window subclass. Use CallWindowProc() in the new windows procedure
2248 * to pass messages to the superclass's window procedure.
2249 *
2250 * The user data is reserved for use by the application which created
2251 * the window.
2252 *
Gerard Patele717b1b2001-11-19 02:07:11 +00002253 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002254 * instead, call the EnableWindow() function to change the window's
2255 * disabled state.
2256 *
2257 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2258 * SetParent() instead.
2259 *
Alexandre Julliard638f1691999-01-17 16:32:32 +00002260 * Win95:
2261 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2262 * it sends WM_STYLECHANGING before changing the settings
2263 * and WM_STYLECHANGED afterwards.
2264 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002265 */
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002266LONG WINAPI SetWindowLongW(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00002267 HWND hwnd, /* [in] window to alter */
2268 INT offset, /* [in] offset, in bytes, of location to alter */
2269 LONG newval /* [in] new value of location */
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002270) {
Alexandre Julliard3051b641996-07-05 17:14:13 +00002271 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002272}
2273
2274
Alexandre Julliardf0b23541993-09-29 12:21:49 +00002275/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002276 * GetWindowTextA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002277 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002278INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002279{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002280 WCHAR *buffer;
2281
2282 if (WIN_IsCurrentProcess( hwnd ))
2283 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2284
2285 /* when window belongs to other process, don't send a message */
2286 if (nMaxCount <= 0) return 0;
2287 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2288 get_server_window_text( hwnd, buffer, nMaxCount );
2289 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2290 lpString[nMaxCount-1] = 0;
2291 HeapFree( GetProcessHeap(), 0, buffer );
2292 return strlen(lpString);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002293}
2294
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002295
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002296/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002297 * InternalGetWindowText (USER32.@)
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002298 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002299INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002300{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002301 WND *win;
2302
2303 if (nMaxCount <= 0) return 0;
2304 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2305 if (win != WND_OTHER_PROCESS)
2306 {
2307 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2308 else lpString[0] = 0;
2309 WIN_ReleasePtr( win );
2310 }
2311 else
2312 {
2313 get_server_window_text( hwnd, lpString, nMaxCount );
2314 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00002315 return strlenW(lpString);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002316}
2317
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002318
2319/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002320 * GetWindowTextW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002321 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002322INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002323{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002324 if (WIN_IsCurrentProcess( hwnd ))
2325 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2326
2327 /* when window belongs to other process, don't send a message */
2328 if (nMaxCount <= 0) return 0;
2329 get_server_window_text( hwnd, lpString, nMaxCount );
2330 return strlenW(lpString);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002331}
2332
2333
2334/*******************************************************************
Patrik Stridvall17fd4e32001-06-28 18:04:41 +00002335 * SetWindowText (USER32.@)
2336 * SetWindowTextA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002337 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002338BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002339{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002340 if (!WIN_IsCurrentProcess( hwnd ))
2341 {
2342 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2343 SetLastError( ERROR_ACCESS_DENIED );
2344 return FALSE;
2345 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002346 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002347}
2348
2349
2350/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002351 * SetWindowTextW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002352 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002353BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002354{
Alexandre Julliard805bdc52001-11-13 22:23:48 +00002355 if (!WIN_IsCurrentProcess( hwnd ))
2356 {
2357 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2358 SetLastError( ERROR_ACCESS_DENIED );
2359 return FALSE;
2360 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002361 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002362}
2363
2364
Alexandre Julliard0e607781993-11-03 19:23:37 +00002365/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002366 * GetWindowTextLengthA (USER32.@)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002367 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002368INT WINAPI GetWindowTextLengthA( HWND hwnd )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002369{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002370 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002371}
2372
2373/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002374 * GetWindowTextLengthW (USER32.@)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002375 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002376INT WINAPI GetWindowTextLengthW( HWND hwnd )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002377{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002378 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002379}
2380
Alexandre Julliard21979011997-03-05 08:22:35 +00002381
Alexandre Julliardb1bac321996-12-15 19:45:59 +00002382/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002383 * IsWindow (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00002384 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002385BOOL WINAPI IsWindow( HWND hwnd )
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002386{
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002387 WND *ptr;
Alexandre Julliard37a46392001-09-12 17:19:13 +00002388 BOOL ret;
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002389
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002390 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2391
2392 if (ptr != WND_OTHER_PROCESS)
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002393 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002394 WIN_ReleasePtr( ptr );
Alexandre Julliard7695d692001-09-24 01:19:59 +00002395 return TRUE;
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002396 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002397
Alexandre Julliard37a46392001-09-12 17:19:13 +00002398 /* check other processes */
2399 SERVER_START_REQ( get_window_info )
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002400 {
Alexandre Julliard37a46392001-09-12 17:19:13 +00002401 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002402 ret = !wine_server_call_err( req );
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002403 }
Alexandre Julliard37a46392001-09-12 17:19:13 +00002404 SERVER_END_REQ;
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002405 return ret;
2406}
2407
2408
2409/***********************************************************************
2410 * GetWindowThreadProcessId (USER32.@)
2411 */
2412DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2413{
2414 WND *ptr;
2415 DWORD tid = 0;
2416
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002417 if (!(ptr = WIN_GetPtr( hwnd )))
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002418 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002419 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2420 return 0;
2421 }
2422
2423 if (ptr != WND_OTHER_PROCESS)
2424 {
2425 /* got a valid window */
2426 tid = ptr->tid;
2427 if (process) *process = GetCurrentProcessId();
2428 WIN_ReleasePtr( ptr );
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002429 return tid;
2430 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002431
2432 /* check other processes */
2433 SERVER_START_REQ( get_window_info )
2434 {
2435 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002436 if (!wine_server_call_err( req ))
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002437 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002438 tid = (DWORD)reply->tid;
2439 if (process) *process = (DWORD)reply->pid;
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002440 }
2441 }
2442 SERVER_END_REQ;
2443 return tid;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002444}
2445
2446
2447/*****************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002448 * GetParent (USER32.@)
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +00002449 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002450HWND WINAPI GetParent( HWND hwnd )
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002451{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002452 WND *wndPtr;
Andreas Mohr1c20b392000-02-20 19:17:35 +00002453 HWND retvalue = 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002454
Alexandre Julliardddc33172001-10-22 19:08:33 +00002455 if (!(wndPtr = WIN_GetPtr( hwnd )))
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002456 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00002457 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2458 return 0;
2459 }
2460 if (wndPtr == WND_OTHER_PROCESS)
2461 {
2462 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2463 if (style & (WS_POPUP | WS_CHILD))
2464 {
2465 SERVER_START_REQ( get_window_tree )
2466 {
2467 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002468 if (!wine_server_call_err( req ))
Alexandre Julliardddc33172001-10-22 19:08:33 +00002469 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002470 if (style & WS_POPUP) retvalue = reply->owner;
2471 else if (style & WS_CHILD) retvalue = reply->parent;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002472 }
2473 }
2474 SERVER_END_REQ;
2475 }
2476 }
2477 else
2478 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002479 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2480 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002481 WIN_ReleasePtr( wndPtr );
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002482 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002483 return retvalue;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002484}
2485
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002486
2487/*****************************************************************
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002488 * GetAncestor (USER32.@)
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002489 */
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002490HWND WINAPI GetAncestor( HWND hwnd, UINT type )
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002491{
Alexandre Julliardddc33172001-10-22 19:08:33 +00002492 WND *win;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002493 HWND *list, ret = 0;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002494
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002495 switch(type)
Alexandre Julliardddc33172001-10-22 19:08:33 +00002496 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002497 case GA_PARENT:
Alexandre Julliardddc33172001-10-22 19:08:33 +00002498 if (!(win = WIN_GetPtr( hwnd )))
2499 {
2500 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2501 return 0;
2502 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002503 if (win != WND_OTHER_PROCESS)
Alexandre Julliardddc33172001-10-22 19:08:33 +00002504 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002505 ret = win->parent;
2506 WIN_ReleasePtr( win );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002507 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002508 else /* need to query the server */
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002509 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002510 SERVER_START_REQ( get_window_tree )
Alexandre Julliard556607a2001-10-10 20:28:17 +00002511 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002512 req->handle = hwnd;
2513 if (!wine_server_call_err( req )) ret = reply->parent;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002514 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002515 SERVER_END_REQ;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002516 }
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002517 break;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002518
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002519 case GA_ROOT:
2520 if (!(list = WIN_ListParents( hwnd ))) return 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002521
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002522 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2523 else
2524 {
2525 int count = 2;
2526 while (list[count]) count++;
2527 ret = list[count - 2]; /* get the one before the desktop */
2528 }
2529 HeapFree( GetProcessHeap(), 0, list );
2530 break;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002531
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002532 case GA_ROOTOWNER:
2533 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002534 for (;;)
2535 {
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002536 HWND parent = GetParent( ret );
2537 if (!parent) break;
2538 ret = parent;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002539 }
Alexandre Julliard7dafa612002-09-25 00:21:56 +00002540 break;
Alexandre Julliard556607a2001-10-10 20:28:17 +00002541 }
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002542 return ret;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002543}
2544
2545
Alexandre Julliard940d58c1994-09-16 09:24:37 +00002546/*****************************************************************
Alexandre Julliardddc33172001-10-22 19:08:33 +00002547 * SetParent (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002548 */
Alexandre Julliardddc33172001-10-22 19:08:33 +00002549HWND WINAPI SetParent( HWND hwnd, HWND parent )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002550{
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002551 WND *wndPtr;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002552 HWND retvalue, full_handle;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002553 BOOL was_visible;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002554
Alexandre Julliardddc33172001-10-22 19:08:33 +00002555 if (!parent) parent = GetDesktopWindow();
2556 else parent = WIN_GetFullHandle( parent );
2557
2558 if (!IsWindow( parent ))
2559 {
2560 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2561 return 0;
2562 }
2563
2564 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
Michael Stefaniuc2247af32002-09-04 19:37:01 +00002565 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
Alexandre Julliardddc33172001-10-22 19:08:33 +00002566
2567 hwnd = full_handle;
2568
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002569 if (USER_Driver.pSetParent)
2570 return USER_Driver.pSetParent( hwnd, parent );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002571
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002572 /* Windows hides the window first, then shows it again
2573 * including the WM_SHOWWINDOW messages and all */
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002574 was_visible = ShowWindow( hwnd, SW_HIDE );
2575
2576 if (!IsWindow( parent )) return 0;
2577 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00002578
Alexandre Julliard556607a2001-10-10 20:28:17 +00002579 retvalue = wndPtr->parent; /* old parent */
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002580 if (parent != retvalue)
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002581 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002582 WIN_LinkWindow( hwnd, parent, HWND_TOP );
Ove Kaaven72d8dbe1999-02-13 09:02:17 +00002583
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002584 if (parent != GetDesktopWindow()) /* a child window */
2585 {
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002586 if (!(wndPtr->dwStyle & WS_CHILD))
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002587 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00002588 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2589 if (menu) DestroyMenu( menu );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002590 }
2591 }
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002592 }
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002593 WIN_ReleasePtr( wndPtr );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002594
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002595 /* SetParent additionally needs to make hwnd the topmost window
2596 in the x-order and send the expected WM_WINDOWPOSCHANGING and
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002597 WM_WINDOWPOSCHANGED notification messages.
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002598 */
2599 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002600 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002601 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2602 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2603 return retvalue;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00002604}
2605
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002606
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002607/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002608 * IsChild (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00002609 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002610BOOL WINAPI IsChild( HWND parent, HWND child )
Alexandre Julliard0e607781993-11-03 19:23:37 +00002611{
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002612 HWND *list = WIN_ListParents( child );
2613 int i;
2614 BOOL ret;
2615
2616 if (!list) return FALSE;
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00002617 parent = WIN_GetFullHandle( parent );
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002618 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2619 ret = (list[i] != 0);
2620 HeapFree( GetProcessHeap(), 0, list );
2621 return ret;
Alexandre Julliard0e607781993-11-03 19:23:37 +00002622}
2623
2624
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002625/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002626 * IsWindowVisible (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00002627 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002628BOOL WINAPI IsWindowVisible( HWND hwnd )
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002629{
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002630 HWND *list;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002631 BOOL retval;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002632 int i;
2633
2634 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2635 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2636 for (i = 0; list[i]; i++)
2637 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2638 retval = !list[i];
2639 HeapFree( GetProcessHeap(), 0, list );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002640 return retval;
Alexandre Julliarde399fc31993-11-24 17:08:56 +00002641}
2642
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002643
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002644/***********************************************************************
2645 * WIN_IsWindowDrawable
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002646 *
2647 * hwnd is drawable when it is visible, all parents are not
2648 * minimized, and it is itself not minimized unless we are
Alexandre Julliard23946ad1997-06-16 17:43:53 +00002649 * trying to draw its default class icon.
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002650 */
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002651BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002652{
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002653 HWND *list;
2654 BOOL retval;
2655 int i;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002656 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002657
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002658 if (!(style & WS_VISIBLE)) return FALSE;
2659 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002660
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002661 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002662 for (i = 0; list[i]; i++)
2663 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2664 break;
2665 retval = !list[i];
2666 HeapFree( GetProcessHeap(), 0, list );
2667 return retval;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002668}
2669
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002670
Alexandre Julliard0e607781993-11-03 19:23:37 +00002671/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002672 * GetTopWindow (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00002673 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002674HWND WINAPI GetTopWindow( HWND hwnd )
Alexandre Julliard0e607781993-11-03 19:23:37 +00002675{
Alexandre Julliardfa42aa82001-08-21 17:13:55 +00002676 if (!hwnd) hwnd = GetDesktopWindow();
2677 return GetWindow( hwnd, GW_CHILD );
Alexandre Julliard0e607781993-11-03 19:23:37 +00002678}
2679
2680
2681/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002682 * GetWindow (USER32.@)
Alexandre Julliard01d63461997-01-20 19:43:45 +00002683 */
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002684HWND WINAPI GetWindow( HWND hwnd, UINT rel )
Alexandre Julliard0e607781993-11-03 19:23:37 +00002685{
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002686 HWND retval = 0;
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002687
Alexandre Julliardddc33172001-10-22 19:08:33 +00002688 if (rel == GW_OWNER) /* this one may be available locally */
Alexandre Julliard0e607781993-11-03 19:23:37 +00002689 {
Alexandre Julliardddc33172001-10-22 19:08:33 +00002690 WND *wndPtr = WIN_GetPtr( hwnd );
2691 if (!wndPtr)
2692 {
2693 SetLastError( ERROR_INVALID_HANDLE );
2694 return 0;
2695 }
2696 if (wndPtr != WND_OTHER_PROCESS)
2697 {
2698 retval = wndPtr->owner;
2699 WIN_ReleasePtr( wndPtr );
2700 return retval;
2701 }
2702 /* else fall through to server call */
Alexandre Julliard0e607781993-11-03 19:23:37 +00002703 }
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002704
2705 SERVER_START_REQ( get_window_tree )
2706 {
2707 req->handle = hwnd;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002708 if (!wine_server_call_err( req ))
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002709 {
2710 switch(rel)
2711 {
2712 case GW_HWNDFIRST:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002713 retval = reply->first_sibling;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002714 break;
2715 case GW_HWNDLAST:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002716 retval = reply->last_sibling;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002717 break;
2718 case GW_HWNDNEXT:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002719 retval = reply->next_sibling;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002720 break;
2721 case GW_HWNDPREV:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002722 retval = reply->prev_sibling;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002723 break;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002724 case GW_OWNER:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002725 retval = reply->owner;
Alexandre Julliardddc33172001-10-22 19:08:33 +00002726 break;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002727 case GW_CHILD:
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002728 retval = reply->first_child;
Alexandre Julliarda09da0c2001-09-21 21:08:40 +00002729 break;
2730 }
2731 }
2732 }
2733 SERVER_END_REQ;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002734 return retval;
Alexandre Julliard0e607781993-11-03 19:23:37 +00002735}
2736
2737
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002738/***********************************************************************
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002739 * WIN_InternalShowOwnedPopups
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002740 *
2741 * Internal version of ShowOwnedPopups; Wine functions should use this
2742 * to avoid interfering with application calls to ShowOwnedPopups
2743 * and to make sure the application can't prevent showing/hiding.
2744 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00002745 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002746 *
2747 */
2748
2749BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2750{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002751 int count = 0;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002752 WND *pWnd;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002753 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002754
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002755 if (!win_array) return TRUE;
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002756
2757 /*
2758 * Show windows Lowest first, Highest last to preserve Z-Order
2759 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002760 while (win_array[count]) count++;
2761 while (--count >= 0)
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002762 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002763 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2764 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002765
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002766 if (pWnd->dwStyle & WS_POPUP)
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002767 {
2768 if (fShow)
2769 {
2770 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002771 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002772 {
2773 /*
2774 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2775 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002776 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2777 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002778 }
2779 }
2780 else
2781 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002782 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2783 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2784 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002785 {
2786 /*
2787 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2788 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002789 ShowWindow(pWnd->hwndSelf,SW_HIDE);
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002790 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002791 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002792 }
2793 }
2794 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002795 WIN_ReleaseWndPtr( pWnd );
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002796 }
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002797 HeapFree( GetProcessHeap(), 0, win_array );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002798
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002799 return TRUE;
2800}
2801
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002802/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002803 * ShowOwnedPopups (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002804 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002805BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002806{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002807 int count = 0;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002808 WND *pWnd;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002809 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
Noomen Hamzaa018d851999-09-28 16:26:09 +00002810
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002811 if (!win_array) return TRUE;
Noomen Hamzaa018d851999-09-28 16:26:09 +00002812
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002813 while (win_array[count]) count++;
2814 while (--count >= 0)
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002815 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002816 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2817 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002818
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002819 if (pWnd->dwStyle & WS_POPUP)
Noomen Hamzaff727762000-02-18 19:11:04 +00002820 {
2821 if (fShow)
2822 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002823 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
Noomen Hamzaff727762000-02-18 19:11:04 +00002824 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002825 /* In Windows, ShowOwnedPopups(TRUE) generates
2826 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
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_SHOW, SW_PARENTOPENING);
2830 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
Noomen Hamzaff727762000-02-18 19:11:04 +00002831 }
2832 }
2833 else
2834 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002835 if (IsWindowVisible(pWnd->hwndSelf))
Noomen Hamzaff727762000-02-18 19:11:04 +00002836 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002837 /* In Windows, ShowOwnedPopups(FALSE) generates
2838 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
Louis Philippe Gagnon06057e72000-08-20 03:40:59 +00002839 * regardless of the state of the owner
2840 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002841 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2842 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
Noomen Hamzaff727762000-02-18 19:11:04 +00002843 }
2844 }
2845 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002846 WIN_ReleaseWndPtr( pWnd );
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002847 }
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002848 HeapFree( GetProcessHeap(), 0, win_array );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002849 return TRUE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00002850}
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002851
2852
Alexandre Julliard3a405ba1994-10-30 16:25:19 +00002853/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002854 * GetLastActivePopup (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00002855 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002856HWND WINAPI GetLastActivePopup( HWND hwnd )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +00002857{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002858 HWND retval;
Andreas Mohr1c20b392000-02-20 19:17:35 +00002859 WND *wndPtr =WIN_FindWndPtr(hwnd);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002860 if (!wndPtr) return hwnd;
2861 retval = wndPtr->hwndLastActive;
Alexandre Julliard37a46392001-09-12 17:19:13 +00002862 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002863 WIN_ReleaseWndPtr(wndPtr);
2864 return retval;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +00002865}
2866
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002867
2868/*******************************************************************
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002869 * WIN_ListParents
Alexandre Julliard3051b641996-07-05 17:14:13 +00002870 *
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002871 * Build an array of all parents of a given window, starting with
2872 * the immediate parent. The array must be freed with HeapFree.
2873 * Returns NULL if window is a top-level window.
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002874 */
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002875HWND *WIN_ListParents( HWND hwnd )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002876{
Alexandre Julliard55557312001-10-23 00:26:10 +00002877 WND *win;
2878 HWND current, *list;
Alexandre Julliard96ebfa92001-10-23 20:35:44 +00002879 int pos = 0, size = 16, count = 0;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002880
Alexandre Julliard55557312001-10-23 00:26:10 +00002881 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2882
2883 current = hwnd;
2884 for (;;)
2885 {
2886 if (!(win = WIN_GetPtr( current ))) goto empty;
2887 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2888 list[pos] = win->parent;
2889 WIN_ReleasePtr( win );
2890 if (!(current = list[pos]))
2891 {
2892 if (!pos) goto empty;
2893 return list;
2894 }
2895 if (++pos == size - 1)
2896 {
2897 /* need to grow the list */
2898 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2899 if (!new_list) goto empty;
2900 list = new_list;
2901 size += 16;
2902 }
2903 }
2904
2905 /* at least one parent belongs to another process, have to query the server */
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002906
2907 for (;;)
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002908 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002909 count = 0;
2910 SERVER_START_REQ( get_window_parents )
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002911 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002912 req->handle = hwnd;
2913 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2914 if (!wine_server_call( req )) count = reply->count;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002915 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00002916 SERVER_END_REQ;
2917 if (!count) goto empty;
2918 if (size > count)
2919 {
2920 list[count] = 0;
2921 return list;
2922 }
2923 HeapFree( GetProcessHeap(), 0, list );
2924 size = count + 1;
2925 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002926 }
Alexandre Julliard55557312001-10-23 00:26:10 +00002927
2928 empty:
2929 HeapFree( GetProcessHeap(), 0, list );
2930 return NULL;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002931}
2932
2933
2934/*******************************************************************
2935 * WIN_ListChildren
2936 *
2937 * Build an array of the children of a given window. The array must be
2938 * freed with HeapFree. Returns NULL when no windows are found.
2939 */
2940HWND *WIN_ListChildren( HWND hwnd )
2941{
Alexandre Julliard844ceb92001-10-09 23:26:40 +00002942 return list_window_children( hwnd, 0, 0 );
Alexandre Julliard3051b641996-07-05 17:14:13 +00002943}
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002944
Alexandre Julliard3051b641996-07-05 17:14:13 +00002945
2946/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002947 * EnumWindows (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00002948 */
Alexandre Julliardd6c0d862000-03-24 21:38:30 +00002949BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
Alexandre Julliard3051b641996-07-05 17:14:13 +00002950{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002951 HWND *list;
2952 BOOL ret = TRUE;
2953 int i, iWndsLocks;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002954
Alexandre Julliard594997c1995-04-30 10:05:20 +00002955 /* We have to build a list of all windows first, to avoid */
Andreas Mohr1c20b392000-02-20 19:17:35 +00002956 /* unpleasant side-effects, for instance if the callback */
2957 /* function changes the Z-order of the windows. */
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002958
Tommy Schultz Lassen440adc12002-01-22 00:50:07 +00002959 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00002960
Alexandre Julliard3051b641996-07-05 17:14:13 +00002961 /* Now call the callback function for every window */
Alexandre Julliard594997c1995-04-30 10:05:20 +00002962
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002963 iWndsLocks = WIN_SuspendWndsLock();
2964 for (i = 0; list[i]; i++)
Alexandre Julliard594997c1995-04-30 10:05:20 +00002965 {
Alexandre Julliard3051b641996-07-05 17:14:13 +00002966 /* Make sure that the window still exists */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002967 if (!IsWindow( list[i] )) continue;
2968 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
Alexandre Julliard594997c1995-04-30 10:05:20 +00002969 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002970 WIN_RestoreWndsLock(iWndsLocks);
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002971 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002972 return ret;
Alexandre Julliard594997c1995-04-30 10:05:20 +00002973}
2974
2975
Alexandre Julliard3051b641996-07-05 17:14:13 +00002976/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002977 * EnumThreadWindows (USER32.@)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002978 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002979BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002980{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002981 HWND *list;
2982 int i, iWndsLocks;
2983
Alexandre Julliard844ceb92001-10-09 23:26:40 +00002984 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
Tommy Schultz Lassen440adc12002-01-22 00:50:07 +00002985 return TRUE ;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002986
2987 /* Now call the callback function for every window */
2988
2989 iWndsLocks = WIN_SuspendWndsLock();
2990 for (i = 0; list[i]; i++)
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002991 if (!func( list[i], lParam )) break;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002992 WIN_RestoreWndsLock(iWndsLocks);
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00002993 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002994 return TRUE;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00002995}
2996
Alexandre Julliard59730ae1996-03-24 16:20:51 +00002997
Alexandre Julliard3051b641996-07-05 17:14:13 +00002998/**********************************************************************
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00002999 * WIN_EnumChildWindows
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003000 *
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00003001 * Helper function for EnumChildWindows().
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003002 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003003static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003004{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003005 HWND *childList;
3006 BOOL ret = FALSE;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003007
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003008 for ( ; *list; list++)
Alexandre Julliard3051b641996-07-05 17:14:13 +00003009 {
3010 /* Make sure that the window still exists */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003011 if (!IsWindow( *list )) continue;
3012 /* skip owned windows */
3013 if (GetWindow( *list, GW_OWNER )) continue;
Alexandre Julliard3051b641996-07-05 17:14:13 +00003014 /* Build children list first */
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003015 childList = WIN_ListChildren( *list );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003016
3017 ret = func( *list, lParam );
Francois Boisvertd96bc151999-04-02 10:34:43 +00003018
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00003019 if (childList)
3020 {
3021 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003022 HeapFree( GetProcessHeap(), 0, childList );
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00003023 }
Alexandre Julliard3051b641996-07-05 17:14:13 +00003024 if (!ret) return FALSE;
Alexandre Julliard3051b641996-07-05 17:14:13 +00003025 }
3026 return TRUE;
3027}
3028
3029
3030/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003031 * EnumChildWindows (USER32.@)
Alexandre Julliard3051b641996-07-05 17:14:13 +00003032 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003033BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliard3051b641996-07-05 17:14:13 +00003034{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003035 HWND *list;
3036 int iWndsLocks;
Alexandre Julliard3051b641996-07-05 17:14:13 +00003037
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003038 if (!(list = WIN_ListChildren( parent ))) return FALSE;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003039 iWndsLocks = WIN_SuspendWndsLock();
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00003040 WIN_EnumChildWindows( list, func, lParam );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003041 WIN_RestoreWndsLock(iWndsLocks);
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003042 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard3051b641996-07-05 17:14:13 +00003043 return TRUE;
3044}
3045
3046
Alexandre Julliard58199531994-04-21 01:20:00 +00003047/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003048 * AnyPopup (USER.52)
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003049 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003050BOOL16 WINAPI AnyPopup16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003051{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003052 return AnyPopup();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003053}
3054
3055
3056/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003057 * AnyPopup (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003058 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003059BOOL WINAPI AnyPopup(void)
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003060{
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00003061 int i;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003062 BOOL retvalue;
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003063 HWND *list = WIN_ListChildren( GetDesktopWindow() );
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00003064
3065 if (!list) return FALSE;
3066 for (i = 0; list[i]; i++)
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003067 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00003068 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003069 }
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00003070 retvalue = (list[i] != 0);
Alexandre Julliard9d9dac02001-08-24 19:28:21 +00003071 HeapFree( GetProcessHeap(), 0, list );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003072 return retvalue;
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003073}
3074
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003075
Alexandre Julliard73450d61994-05-18 18:29:32 +00003076/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003077 * FlashWindow (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003078 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003079BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
Alexandre Julliard73450d61994-05-18 18:29:32 +00003080{
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003081 WND *wndPtr = WIN_FindWndPtr(hWnd);
3082
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00003083 TRACE("%04x\n", hWnd);
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003084
3085 if (!wndPtr) return FALSE;
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00003086 hWnd = wndPtr->hwndSelf; /* make it a full handle */
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003087
3088 if (wndPtr->dwStyle & WS_MINIMIZE)
3089 {
3090 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3091 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003092 HDC hDC = GetDC(hWnd);
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003093
Alexandre Julliardcb25e252001-08-08 23:28:42 +00003094 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003095 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003096
Alexandre Julliarda3960291999-02-26 11:11:13 +00003097 ReleaseDC( hWnd, hDC );
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003098 wndPtr->flags |= WIN_NCACTIVATED;
3099 }
3100 else
3101 {
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00003102 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003103 wndPtr->flags &= ~WIN_NCACTIVATED;
3104 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003105 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003106 return TRUE;
3107 }
3108 else
3109 {
Alexandre Julliard530ee841996-10-23 16:59:13 +00003110 WPARAM16 wparam;
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003111 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003112 else wparam = (hWnd == GetActiveWindow());
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003113
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003114 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00003115 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00003116 return wparam;
3117 }
Alexandre Julliard73450d61994-05-18 18:29:32 +00003118}
3119
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003120
3121/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003122 * GetWindowContextHelpId (USER32.@)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003123 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003124DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003125{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003126 DWORD retval;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003127 WND *wnd = WIN_FindWndPtr( hwnd );
3128 if (!wnd) return 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003129 retval = wnd->helpContext;
3130 WIN_ReleaseWndPtr(wnd);
3131 return retval;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003132}
3133
3134
3135/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003136 * SetWindowContextHelpId (USER32.@)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003137 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003138BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003139{
3140 WND *wnd = WIN_FindWndPtr( hwnd );
3141 if (!wnd) return FALSE;
3142 wnd->helpContext = id;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003143 WIN_ReleaseWndPtr(wnd);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003144 return TRUE;
3145}
3146
3147
3148/*******************************************************************
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003149 * DRAG_QueryUpdate16
Alexandre Julliardade697e1995-11-26 13:59:11 +00003150 *
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003151 * recursively find a child that contains spDragInfo->pt point
Alexandre Julliardade697e1995-11-26 13:59:11 +00003152 * and send WM_QUERYDROPOBJECT
3153 */
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003154static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
Alexandre Julliardade697e1995-11-26 13:59:11 +00003155{
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003156 BOOL16 wParam, bResult = 0;
3157 POINT pt;
3158 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3159 RECT tempRect;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003160
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003161 if (!ptrDragInfo) return FALSE;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003162
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003163 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003164
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003165 GetWindowRect(hQueryWnd,&tempRect);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003166
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003167 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003168
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003169 if (!IsIconic( hQueryWnd ))
3170 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003171 GetClientRect( hQueryWnd, &tempRect );
3172 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003173
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003174 if (PtInRect( &tempRect, pt))
3175 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003176 int i;
3177 HWND *list = WIN_ListChildren( hQueryWnd );
3178
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003179 wParam = 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003180
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003181 if (list)
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003182 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003183 for (i = 0; list[i]; i++)
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003184 {
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003185 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3186 {
3187 GetWindowRect( list[i], &tempRect );
3188 if (PtInRect( &tempRect, pt )) break;
3189 }
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003190 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003191 if (list[i])
3192 {
3193 if (IsWindowEnabled( list[i] ))
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003194 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003195 }
3196 HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003197 }
Alexandre Julliard1a66d222001-08-28 18:44:52 +00003198 if(bResult) return bResult;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003199 }
3200 else wParam = 1;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003201 }
3202 else wParam = 1;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003203
Michael Stefaniuc2247af32002-09-04 19:37:01 +00003204 ScreenToClient16(HWND_16(hQueryWnd),&ptrDragInfo->pt);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003205
Michael Stefaniuc2247af32002-09-04 19:37:01 +00003206 ptrDragInfo->hScope = HWND_16(hQueryWnd);
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003207
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003208 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003209
3210 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3211
3212 return bResult;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003213}
3214
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003215
Alexandre Julliardade697e1995-11-26 13:59:11 +00003216/*******************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003217 * DragDetect (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00003218 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003219BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
Alexandre Julliardade697e1995-11-26 13:59:11 +00003220{
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003221 MSG msg;
3222 RECT rect;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003223
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003224 rect.left = pt.x - wDragWidth;
3225 rect.right = pt.x + wDragWidth;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003226
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003227 rect.top = pt.y - wDragHeight;
3228 rect.bottom = pt.y + wDragHeight;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003229
Alexandre Julliarda3960291999-02-26 11:11:13 +00003230 SetCapture(hWnd);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003231
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003232 while(1)
3233 {
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003234 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003235 {
3236 if( msg.message == WM_LBUTTONUP )
3237 {
3238 ReleaseCapture();
3239 return 0;
3240 }
3241 if( msg.message == WM_MOUSEMOVE )
3242 {
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003243 POINT tmp;
3244 tmp.x = LOWORD(msg.lParam);
3245 tmp.y = HIWORD(msg.lParam);
3246 if( !PtInRect( &rect, tmp ))
Alexandre Julliardade697e1995-11-26 13:59:11 +00003247 {
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003248 ReleaseCapture();
3249 return 1;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003250 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003251 }
3252 }
3253 WaitMessage();
3254 }
3255 return 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003256}
3257
3258/******************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00003259 * DragObject (USER.464)
Alexandre Julliardade697e1995-11-26 13:59:11 +00003260 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003261DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3262 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
Alexandre Julliardade697e1995-11-26 13:59:11 +00003263{
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003264 MSG msg;
Alexandre Julliard83f52d12000-09-26 22:20:14 +00003265 LPDRAGINFO16 lpDragInfo;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003266 SEGPTR spDragInfo;
Alexandre Julliard70e192b2002-06-02 21:29:23 +00003267 HCURSOR16 hOldCursor=0, hBummer=0;
Alexandre Julliard83f52d12000-09-26 22:20:14 +00003268 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003269 HCURSOR16 hCurrentCursor = 0;
3270 HWND16 hCurrentWnd = 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003271
Alexandre Julliard83f52d12000-09-26 22:20:14 +00003272 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
Alexandre Julliard58017232000-12-22 01:09:26 +00003273 spDragInfo = K32WOWGlobalLock16(hDragInfo);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003274
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003275 if( !lpDragInfo || !spDragInfo ) return 0L;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003276
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003277 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003278 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003279 GlobalFree16(hDragInfo);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003280 return 0L;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003281 }
Alexandre Julliardade697e1995-11-26 13:59:11 +00003282
Alexandre Julliard70e192b2002-06-02 21:29:23 +00003283 if(hCursor) hOldCursor = SetCursor(hCursor);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003284
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003285 lpDragInfo->hWnd = hWnd;
3286 lpDragInfo->hScope = 0;
3287 lpDragInfo->wFlags = wObj;
3288 lpDragInfo->hList = szList; /* near pointer! */
3289 lpDragInfo->hOfStruct = hOfStruct;
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003290 lpDragInfo->l = 0L;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003291
Michael Stefaniuc2247af32002-09-04 19:37:01 +00003292 SetCapture(WIN_Handle32(hWnd));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003293 ShowCursor( TRUE );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003294
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003295 do
3296 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00003297 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003298
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003299 *(lpDragInfo+1) = *lpDragInfo;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003300
Alexandre Julliard0ff083b2000-09-24 19:51:15 +00003301 lpDragInfo->pt.x = msg.pt.x;
3302 lpDragInfo->pt.y = msg.pt.y;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003303
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003304 /* update DRAGINFO struct */
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003305 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003306
Dimitrie O. Paun9dd12792002-09-23 20:56:37 +00003307 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003308 hCurrentCursor = hCursor;
3309 else
Alexandre Julliardade697e1995-11-26 13:59:11 +00003310 {
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003311 hCurrentCursor = hBummer;
3312 lpDragInfo->hScope = 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00003313 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003314 if( hCurrentCursor )
Alexandre Julliarda3960291999-02-26 11:11:13 +00003315 SetCursor(hCurrentCursor);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003316
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003317 /* send WM_DRAGLOOP */
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003318 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003319 (LPARAM) spDragInfo );
3320 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3321 if( hCurrentWnd != lpDragInfo->hScope )
Alexandre Julliardade697e1995-11-26 13:59:11 +00003322 {
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003323 if( hCurrentWnd )
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003324 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
Alexandre Julliard83f52d12000-09-26 22:20:14 +00003325 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
Alexandre Julliardade697e1995-11-26 13:59:11 +00003326 HIWORD(spDragInfo)) );
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003327 hCurrentWnd = lpDragInfo->hScope;
3328 if( hCurrentWnd )
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003329 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003330 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003331 else
3332 if( hCurrentWnd )
3333 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3334
3335 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3336
3337 ReleaseCapture();
Alexandre Julliarda3960291999-02-26 11:11:13 +00003338 ShowCursor( FALSE );
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003339
Alexandre Julliard70e192b2002-06-02 21:29:23 +00003340 if( hCursor ) SetCursor( hOldCursor );
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003341
Alexandre Julliard0d92fe22001-09-10 23:26:42 +00003342 if( hCurrentCursor != hBummer )
3343 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003344 (WPARAM16)hWnd, (LPARAM)spDragInfo );
Alexandre Julliardade697e1995-11-26 13:59:11 +00003345 else
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003346 msg.lParam = 0;
3347 GlobalFree16(hDragInfo);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003348
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003349 return (DWORD)(msg.lParam);
Alexandre Julliardade697e1995-11-26 13:59:11 +00003350}
Eric Kohlca6c9a62001-03-20 01:53:51 +00003351
3352
3353/******************************************************************************
3354 * GetWindowModuleFileNameA (USER32.@)
3355 */
3356UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3357{
3358 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3359 hwnd, lpszFileName, cchFileNameMax);
3360 return 0;
3361}
3362
3363/******************************************************************************
3364 * GetWindowModuleFileNameW (USER32.@)
3365 */
3366UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3367{
3368 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3369 hwnd, lpszFileName, cchFileNameMax);
3370 return 0;
3371}
David Hammertonca30e482002-05-06 20:11:18 +00003372
3373/******************************************************************************
3374 * GetWindowInfo (USER32.@)
3375 * hwnd: in
3376 * pwi: out.
3377 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3378 * this may be because this structure changed over time. If this is the
3379 * the case, then please: FIXME.
3380 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3381 */
3382BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3383{
3384 WND *wndInfo = NULL;
3385 if (!pwi) return FALSE;
3386 if (pwi->cbSize != sizeof(WINDOWINFO))
3387 {
3388 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3389 return FALSE;
3390 }
3391 wndInfo = WIN_GetPtr(hwnd);
3392 if (!wndInfo) return FALSE;
3393 if (wndInfo == WND_OTHER_PROCESS)
3394 {
3395 FIXME("window belong to other process\n");
3396 return FALSE;
3397 }
3398
3399 pwi->rcWindow = wndInfo->rectWindow;
3400 pwi->rcClient = wndInfo->rectClient;
3401 pwi->dwStyle = wndInfo->dwStyle;
3402 pwi->dwExStyle = wndInfo->dwExStyle;
3403 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3404 /* if active WS_ACTIVECAPTION, else 0 */
3405
3406 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3407 GetSystemMetrics(SM_CXBORDER) : 0);
3408 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3409 GetSystemMetrics(SM_CYBORDER) : 0);
3410 /* above two: I'm presuming that borders widths are the same
3411 * for each window - so long as its actually using a border.. */
3412
3413 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3414 pwi->wCreatorVersion = GetVersion();
3415 /* Docs say this should be the version that
3416 * CREATED the window. But eh?.. Isn't that just the
3417 * version we are running.. Unless ofcourse its some wacky
3418 * RPC stuff or something */
3419
3420 WIN_ReleasePtr(wndInfo);
3421 return TRUE;
3422}