~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/user32/win.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Window related functions
  3  *
  4  * Copyright 1993, 1994 Alexandre Julliard
  5  *
  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include "config.h"
 22 #include "wine/port.h"
 23 
 24 #include <assert.h>
 25 #include <stdarg.h>
 26 #include <stdlib.h>
 27 #include <string.h>
 28 #include "windef.h"
 29 #include "winbase.h"
 30 #include "wine/winbase16.h"
 31 #include "wine/winuser16.h"
 32 #include "wownt32.h"
 33 #include "wine/server.h"
 34 #include "wine/unicode.h"
 35 #include "win.h"
 36 #include "user_private.h"
 37 #include "controls.h"
 38 #include "winerror.h"
 39 #include "wine/debug.h"
 40 
 41 WINE_DEFAULT_DEBUG_CHANNEL(win);
 42 
 43 #define NB_USER_HANDLES  ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
 44 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
 45 
 46 /**********************************************************************/
 47 
 48 /* helper for Get/SetWindowLong */
 49 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
 50 {
 51     if (size == sizeof(WORD))
 52     {
 53         WORD ret;
 54         memcpy( &ret, ptr, sizeof(ret) );
 55         return ret;
 56     }
 57     else if (size == sizeof(DWORD))
 58     {
 59         DWORD ret;
 60         memcpy( &ret, ptr, sizeof(ret) );
 61         return ret;
 62     }
 63     else
 64     {
 65         LONG_PTR ret;
 66         memcpy( &ret, ptr, sizeof(ret) );
 67         return ret;
 68     }
 69 }
 70 
 71 /* helper for Get/SetWindowLong */
 72 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
 73 {
 74     if (size == sizeof(WORD))
 75     {
 76         WORD newval = val;
 77         memcpy( ptr, &newval, sizeof(newval) );
 78     }
 79     else if (size == sizeof(DWORD))
 80     {
 81         DWORD newval = val;
 82         memcpy( ptr, &newval, sizeof(newval) );
 83     }
 84     else
 85     {
 86         memcpy( ptr, &val, sizeof(val) );
 87     }
 88 }
 89 
 90 
 91 static void *user_handles[NB_USER_HANDLES];
 92 
 93 /***********************************************************************
 94  *           create_window_handle
 95  *
 96  * Create a window handle with the server.
 97  */
 98 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
 99                                   HINSTANCE instance, BOOL unicode )
100 {
101     WORD index;
102     WND *win;
103     HWND full_parent = 0, full_owner = 0;
104     struct tagCLASS *class = NULL;
105     user_handle_t handle = 0;
106     int extra_bytes = 0;
107 
108     /* if 16-bit instance, map to module handle */
109     if (instance && !HIWORD(instance))
110         instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
111 
112     SERVER_START_REQ( create_window )
113     {
114         req->parent   = parent;
115         req->owner    = owner;
116         req->instance = instance;
117         if (!(req->atom = get_int_atom_value( name )) && name)
118             wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
119         if (!wine_server_call_err( req ))
120         {
121             handle = reply->handle;
122             full_parent = reply->parent;
123             full_owner  = reply->owner;
124             extra_bytes = reply->extra;
125             class = reply->class_ptr;
126         }
127     }
128     SERVER_END_REQ;
129 
130     if (!handle)
131     {
132         WARN( "error %d creating window\n", GetLastError() );
133         return NULL;
134     }
135 
136     if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
137                            sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
138     {
139         SERVER_START_REQ( destroy_window )
140         {
141             req->handle = handle;
142             wine_server_call( req );
143         }
144         SERVER_END_REQ;
145         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
146         return NULL;
147     }
148 
149     if (!parent)  /* if parent is 0 we don't have a desktop window yet */
150     {
151         struct user_thread_info *thread_info = get_user_thread_info();
152 
153         if (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle;
154         else assert( full_parent == thread_info->desktop );
155         if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
156             ERR( "failed to create desktop window\n" );
157     }
158 
159     USER_Lock();
160 
161     index = USER_HANDLE_TO_INDEX(handle);
162     assert( index < NB_USER_HANDLES );
163     user_handles[index] = win;
164     win->hwndSelf   = handle;
165     win->parent     = full_parent;
166     win->owner      = full_owner;
167     win->class      = class;
168     win->winproc    = get_class_winproc( class );
169     win->dwMagic    = WND_MAGIC;
170     win->cbWndExtra = extra_bytes;
171     if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
172     return win;
173 }
174 
175 
176 /***********************************************************************
177  *           free_window_handle
178  *
179  * Free a window handle.
180  */
181 static WND *free_window_handle( HWND hwnd )
182 {
183     WND *ptr;
184     WORD index = USER_HANDLE_TO_INDEX(hwnd);
185 
186     if (index >= NB_USER_HANDLES) return NULL;
187     USER_Lock();
188     if ((ptr = user_handles[index]))
189     {
190         SERVER_START_REQ( destroy_window )
191         {
192             req->handle = hwnd;
193             if (!wine_server_call_err( req ))
194             {
195                 user_handles[index] = NULL;
196                 ptr->dwMagic = 0;
197             }
198             else
199                 ptr = NULL;
200         }
201         SERVER_END_REQ;
202     }
203     USER_Unlock();
204     HeapFree( GetProcessHeap(), 0, ptr );
205     return ptr;
206 }
207 
208 
209 /*******************************************************************
210  *           list_window_children
211  *
212  * Build an array of the children of a given window. The array must be
213  * freed with HeapFree. Returns NULL when no windows are found.
214  */
215 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
216 {
217     HWND *list;
218     int size = 128;
219 
220     for (;;)
221     {
222         int count = 0;
223 
224         if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
225 
226         SERVER_START_REQ( get_window_children )
227         {
228             req->desktop = desktop;
229             req->parent = hwnd;
230             req->tid = tid;
231             if (!(req->atom = get_int_atom_value( class )) && class)
232                 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
233             wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
234             if (!wine_server_call( req )) count = reply->count;
235         }
236         SERVER_END_REQ;
237         if (count && count < size)
238         {
239             list[count] = 0;
240             return list;
241         }
242         HeapFree( GetProcessHeap(), 0, list );
243         if (!count) break;
244         size = count + 1;  /* restart with a large enough buffer */
245     }
246     return NULL;
247 }
248 
249 
250 /*******************************************************************
251  *           list_window_parents
252  *
253  * Build an array of all parents of a given window, starting with
254  * the immediate parent. The array must be freed with HeapFree.
255  */
256 static HWND *list_window_parents( HWND hwnd )
257 {
258     WND *win;
259     HWND current, *list;
260     int pos = 0, size = 16, count = 0;
261 
262     if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
263 
264     current = hwnd;
265     for (;;)
266     {
267         if (!(win = WIN_GetPtr( current ))) goto empty;
268         if (win == WND_OTHER_PROCESS) break;  /* need to do it the hard way */
269         if (win == WND_DESKTOP)
270         {
271             if (!pos) goto empty;
272             list[pos] = 0;
273             return list;
274         }
275         list[pos] = current = win->parent;
276         WIN_ReleasePtr( win );
277         if (!current) return list;
278         if (++pos == size - 1)
279         {
280             /* need to grow the list */
281             HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
282             if (!new_list) goto empty;
283             list = new_list;
284             size += 16;
285         }
286     }
287 
288     /* at least one parent belongs to another process, have to query the server */
289 
290     for (;;)
291     {
292         count = 0;
293         SERVER_START_REQ( get_window_parents )
294         {
295             req->handle = hwnd;
296             wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
297             if (!wine_server_call( req )) count = reply->count;
298         }
299         SERVER_END_REQ;
300         if (!count) goto empty;
301         if (size > count)
302         {
303             list[count] = 0;
304             return list;
305         }
306         HeapFree( GetProcessHeap(), 0, list );
307         size = count + 1;
308         if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
309     }
310 
311  empty:
312     HeapFree( GetProcessHeap(), 0, list );
313     return NULL;
314 }
315 
316 
317 /*******************************************************************
318  *           send_parent_notify
319  */
320 static void send_parent_notify( HWND hwnd, UINT msg )
321 {
322     if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
323         !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
324     {
325         HWND parent = GetParent(hwnd);
326         if (parent && parent != GetDesktopWindow())
327             SendMessageW( parent, WM_PARENTNOTIFY,
328                           MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
329     }
330 }
331 
332 
333 /*******************************************************************
334  *              get_server_window_text
335  *
336  * Retrieve the window text from the server.
337  */
338 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
339 {
340     size_t len = 0;
341 
342     SERVER_START_REQ( get_window_text )
343     {
344         req->handle = hwnd;
345         wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
346         if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
347     }
348     SERVER_END_REQ;
349     text[len / sizeof(WCHAR)] = 0;
350 }
351 
352 
353 /***********************************************************************
354  *           WIN_GetPtr
355  *
356  * Return a pointer to the WND structure if local to the process,
357  * or WND_OTHER_PROCESS if handle may be valid in other process.
358  * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
359  */
360 WND *WIN_GetPtr( HWND hwnd )
361 {
362     WND * ptr;
363     WORD index = USER_HANDLE_TO_INDEX(hwnd);
364 
365     if (index >= NB_USER_HANDLES) return NULL;
366 
367     USER_Lock();
368     if ((ptr = user_handles[index]))
369     {
370         if (ptr->dwMagic == WND_MAGIC &&
371             (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
372             return ptr;
373         ptr = NULL;
374     }
375     else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
376     {
377         if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
378         else ptr = NULL;
379     }
380     else ptr = WND_OTHER_PROCESS;
381     USER_Unlock();
382     return ptr;
383 }
384 
385 
386 /***********************************************************************
387  *           WIN_IsCurrentProcess
388  *
389  * Check whether a given window belongs to the current process (and return the full handle).
390  */
391 HWND WIN_IsCurrentProcess( HWND hwnd )
392 {
393     WND *ptr;
394     HWND ret;
395 
396     if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
397     ret = ptr->hwndSelf;
398     WIN_ReleasePtr( ptr );
399     return ret;
400 }
401 
402 
403 /***********************************************************************
404  *           WIN_IsCurrentThread
405  *
406  * Check whether a given window belongs to the current thread (and return the full handle).
407  */
408 HWND WIN_IsCurrentThread( HWND hwnd )
409 {
410     WND *ptr;
411     HWND ret = 0;
412 
413     if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
414     if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
415     WIN_ReleasePtr( ptr );
416     return ret;
417 }
418 
419 
420 /***********************************************************************
421  *           WIN_Handle32
422  *
423  * Convert a 16-bit window handle to a full 32-bit handle.
424  */
425 HWND WIN_Handle32( HWND16 hwnd16 )
426 {
427     WND *ptr;
428     HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
429 
430     if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
431     /* do sign extension for -2 and -3 */
432     if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
433 
434     if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
435 
436     if (ptr == WND_DESKTOP) return GetDesktopWindow();
437 
438     if (ptr != WND_OTHER_PROCESS)
439     {
440         hwnd = ptr->hwndSelf;
441         WIN_ReleasePtr( ptr );
442     }
443     else  /* may belong to another process */
444     {
445         SERVER_START_REQ( get_window_info )
446         {
447             req->handle = hwnd;
448             if (!wine_server_call_err( req )) hwnd = reply->full_handle;
449         }
450         SERVER_END_REQ;
451     }
452     return hwnd;
453 }
454 
455 
456 /***********************************************************************
457  *           WIN_SetOwner
458  *
459  * Change the owner of a window.
460  */
461 HWND WIN_SetOwner( HWND hwnd, HWND owner )
462 {
463     WND *win = WIN_GetPtr( hwnd );
464     HWND ret = 0;
465 
466     if (!win || win == WND_DESKTOP) return 0;
467     if (win == WND_OTHER_PROCESS)
468     {
469         if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
470         return 0;
471     }
472     SERVER_START_REQ( set_window_owner )
473     {
474         req->handle = hwnd;
475         req->owner  = owner;
476         if (!wine_server_call( req ))
477         {
478             win->owner = reply->full_owner;
479             ret = reply->prev_owner;
480         }
481     }
482     SERVER_END_REQ;
483     WIN_ReleasePtr( win );
484     return ret;
485 }
486 
487 
488 /***********************************************************************
489  *           WIN_SetStyle
490  *
491  * Change the style of a window.
492  */
493 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
494 {
495     BOOL ok;
496     ULONG new_style, old_style = 0;
497     WND *win = WIN_GetPtr( hwnd );
498 
499     if (!win || win == WND_DESKTOP) return 0;
500     if (win == WND_OTHER_PROCESS)
501     {
502         if (IsWindow(hwnd))
503             ERR( "cannot set style %x/%x on other process window %p\n",
504                  set_bits, clear_bits, hwnd );
505         return 0;
506     }
507     new_style = (win->dwStyle | set_bits) & ~clear_bits;
508     if (new_style == win->dwStyle)
509     {
510         WIN_ReleasePtr( win );
511         return new_style;
512     }
513     SERVER_START_REQ( set_window_info )
514     {
515         req->handle = hwnd;
516         req->flags  = SET_WIN_STYLE;
517         req->style  = new_style;
518         req->extra_offset = -1;
519         if ((ok = !wine_server_call( req )))
520         {
521             old_style = reply->old_style;
522             win->dwStyle = new_style;
523         }
524     }
525     SERVER_END_REQ;
526     WIN_ReleasePtr( win );
527     if (ok)
528     {
529         USER_Driver->pSetWindowStyle( hwnd, old_style );
530         if ((old_style ^ new_style) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
531     }
532     return old_style;
533 }
534 
535 
536 /***********************************************************************
537  *           WIN_GetRectangles
538  *
539  * Get the window and client rectangles.
540  */
541 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
542 {
543     WND *win = WIN_GetPtr( hwnd );
544     BOOL ret = TRUE;
545 
546     if (!win) return FALSE;
547     if (win == WND_DESKTOP)
548     {
549         RECT rect;
550         rect.left = rect.top = 0;
551         rect.right  = GetSystemMetrics(SM_CXSCREEN);
552         rect.bottom = GetSystemMetrics(SM_CYSCREEN);
553         if (rectWindow) *rectWindow = rect;
554         if (rectClient) *rectClient = rect;
555     }
556     else if (win == WND_OTHER_PROCESS)
557     {
558         SERVER_START_REQ( get_window_rectangles )
559         {
560             req->handle = hwnd;
561             if ((ret = !wine_server_call( req )))
562             {
563                 if (rectWindow)
564                 {
565                     rectWindow->left   = reply->window.left;
566                     rectWindow->top    = reply->window.top;
567                     rectWindow->right  = reply->window.right;
568                     rectWindow->bottom = reply->window.bottom;
569                 }
570                 if (rectClient)
571                 {
572                     rectClient->left   = reply->client.left;
573                     rectClient->top    = reply->client.top;
574                     rectClient->right  = reply->client.right;
575                     rectClient->bottom = reply->client.bottom;
576                 }
577             }
578         }
579         SERVER_END_REQ;
580     }
581     else
582     {
583         if (rectWindow) *rectWindow = win->rectWindow;
584         if (rectClient) *rectClient = win->rectClient;
585         WIN_ReleasePtr( win );
586     }
587     return ret;
588 }
589 
590 
591 /***********************************************************************
592  *           WIN_DestroyWindow
593  *
594  * Destroy storage associated to a window. "Internals" p.358
595  */
596 LRESULT WIN_DestroyWindow( HWND hwnd )
597 {
598     WND *wndPtr;
599     HWND *list;
600     HMENU menu = 0, sys_menu;
601     HWND icon_title;
602 
603     TRACE("%p\n", hwnd );
604 
605     /* free child windows */
606     if ((list = WIN_ListChildren( hwnd )))
607     {
608         int i;
609         for (i = 0; list[i]; i++)
610         {
611             if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
612             else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
613         }
614         HeapFree( GetProcessHeap(), 0, list );
615     }
616 
617     /* Unlink now so we won't bother with the children later on */
618     SERVER_START_REQ( set_parent )
619     {
620         req->handle = hwnd;
621         req->parent = 0;
622         wine_server_call( req );
623     }
624     SERVER_END_REQ;
625 
626     /*
627      * Send the WM_NCDESTROY to the window being destroyed.
628      */
629     SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
630 
631     /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
632 
633     /* free resources associated with the window */
634 
635     if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
636     if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
637         menu = (HMENU)wndPtr->wIDmenu;
638     sys_menu = wndPtr->hSysMenu;
639     free_dce( wndPtr->dce, hwnd );
640     wndPtr->dce = NULL;
641     icon_title = wndPtr->icon_title;
642     WIN_ReleasePtr( wndPtr );
643 
644     if (icon_title) DestroyWindow( icon_title );
645     if (menu) DestroyMenu( menu );
646     if (sys_menu) DestroyMenu( sys_menu );
647 
648     USER_Driver->pDestroyWindow( hwnd );
649 
650     free_window_handle( hwnd );
651     return 0;
652 }
653 
654 /***********************************************************************
655  *           WIN_DestroyThreadWindows
656  *
657  * Destroy all children of 'wnd' owned by the current thread.
658  */
659 void WIN_DestroyThreadWindows( HWND hwnd )
660 {
661     HWND *list;
662     int i;
663 
664     if (!(list = WIN_ListChildren( hwnd ))) return;
665     for (i = 0; list[i]; i++)
666     {
667         if (WIN_IsCurrentThread( list[i] ))
668             DestroyWindow( list[i] );
669         else
670             WIN_DestroyThreadWindows( list[i] );
671     }
672     HeapFree( GetProcessHeap(), 0, list );
673 }
674 
675 
676 /***********************************************************************
677  *           WIN_FixCoordinates
678  *
679  * Fix the coordinates - Helper for WIN_CreateWindowEx.
680  * returns default show mode in sw.
681  */
682 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
683 {
684 #define IS_DEFAULT(x)  ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
685     POINT pos[2];
686 
687     if (cs->dwExStyle & WS_EX_MDICHILD)
688     {
689         UINT id = 0;
690 
691         MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
692         if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
693 
694         TRACE("MDI child id %04x\n", id);
695     }
696 
697     if (cs->style & (WS_CHILD | WS_POPUP))
698     {
699         if (cs->dwExStyle & WS_EX_MDICHILD)
700         {
701             if (IS_DEFAULT(cs->x))
702             {
703                 cs->x = pos[0].x;
704                 cs->y = pos[0].y;
705             }
706             if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
707             if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
708         }
709         else
710         {
711             if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
712             if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
713         }
714     }
715     else  /* overlapped window */
716     {
717         HMONITOR monitor;
718         MONITORINFO mon_info;
719         STARTUPINFOW info;
720 
721         if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
722 
723         monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
724         mon_info.cbSize = sizeof(mon_info);
725         GetMonitorInfoW( monitor, &mon_info );
726         GetStartupInfoW( &info );
727 
728         if (IS_DEFAULT(cs->x))
729         {
730             if (!IS_DEFAULT(cs->y)) *sw = cs->y;
731             cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
732             cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
733         }
734 
735         if (IS_DEFAULT(cs->cx))
736         {
737             if (info.dwFlags & STARTF_USESIZE)
738             {
739                 cs->cx = info.dwXSize;
740                 cs->cy = info.dwYSize;
741             }
742             else
743             {
744                 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
745                 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
746             }
747         }
748         /* neither x nor cx are default. Check the y values .
749          * In the trace we see Outlook and Outlook Express using
750          * cy set to CW_USEDEFAULT when opening the address book.
751          */
752         else if (IS_DEFAULT(cs->cy))
753         {
754             FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
755             cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
756         }
757     }
758 #undef IS_DEFAULT
759 }
760 
761 /***********************************************************************
762  *           dump_window_styles
763  */
764 static void dump_window_styles( DWORD style, DWORD exstyle )
765 {
766     TRACE( "style:" );
767     if(style & WS_POPUP) TRACE(" WS_POPUP");
768     if(style & WS_CHILD) TRACE(" WS_CHILD");
769     if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
770     if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
771     if(style & WS_DISABLED) TRACE(" WS_DISABLED");
772     if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
773     if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
774     if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
775     if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
776     else
777     {
778         if(style & WS_BORDER) TRACE(" WS_BORDER");
779         if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
780     }
781     if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
782     if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
783     if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
784     if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
785     if (style & WS_CHILD)
786     {
787         if(style & WS_GROUP) TRACE(" WS_GROUP");
788         if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
789     }
790     else
791     {
792         if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
793         if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
794     }
795 
796     /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
797 #define DUMPED_STYLES \
798     (WS_POPUP | \
799      WS_CHILD | \
800      WS_MINIMIZE | \
801      WS_VISIBLE | \
802      WS_DISABLED | \
803      WS_CLIPSIBLINGS | \
804      WS_CLIPCHILDREN | \
805      WS_MAXIMIZE | \
806      WS_BORDER | \
807      WS_DLGFRAME | \
808      WS_VSCROLL | \
809      WS_HSCROLL | \
810      WS_SYSMENU | \
811      WS_THICKFRAME | \
812      WS_GROUP | \
813      WS_TABSTOP | \
814      WS_MINIMIZEBOX | \
815      WS_MAXIMIZEBOX)
816 
817     if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
818     TRACE("\n");
819 #undef DUMPED_STYLES
820 
821     TRACE( "exstyle:" );
822     if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
823     if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
824     if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
825     if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
826     if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
827     if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
828     if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
829     if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
830     if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
831     if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
832     if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
833     if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
834     if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
835     if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
836     if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
837     if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
838     if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
839     if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
840 
841 #define DUMPED_EX_STYLES \
842     (WS_EX_DLGMODALFRAME | \
843      WS_EX_DRAGDETECT | \
844      WS_EX_NOPARENTNOTIFY | \
845      WS_EX_TOPMOST | \
846      WS_EX_ACCEPTFILES | \
847      WS_EX_TRANSPARENT | \
848      WS_EX_MDICHILD | \
849      WS_EX_TOOLWINDOW | \
850      WS_EX_WINDOWEDGE | \
851      WS_EX_CLIENTEDGE | \
852      WS_EX_CONTEXTHELP | \
853      WS_EX_RIGHT | \
854      WS_EX_RTLREADING | \
855      WS_EX_LEFTSCROLLBAR | \
856      WS_EX_CONTROLPARENT | \
857      WS_EX_STATICEDGE | \
858      WS_EX_APPWINDOW | \
859      WS_EX_LAYERED)
860 
861     if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
862     TRACE("\n");
863 #undef DUMPED_EX_STYLES
864 }
865 
866 
867 /***********************************************************************
868  *           WIN_CreateWindowEx
869  *
870  * Implementation of CreateWindowEx().
871  */
872 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
873 {
874     INT cx, cy, style, sw = SW_SHOW;
875     LRESULT result;
876     RECT rect;
877     WND *wndPtr;
878     HWND hwnd, parent, owner, top_child = 0;
879     BOOL unicode = (flags & WIN_ISUNICODE) != 0;
880     MDICREATESTRUCTA mdi_cs;
881     CBT_CREATEWNDA cbtc;
882     CREATESTRUCTA cbcs;
883 
884     TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
885           unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
886           debugstr_w(className),
887           cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
888           cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
889     if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
890 
891     /* Fix the styles for MDI children */
892     if (cs->dwExStyle & WS_EX_MDICHILD)
893     {
894         UINT flags = 0;
895 
896         wndPtr = WIN_GetPtr(cs->hwndParent);
897         if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
898         {
899             flags = wndPtr->flags;
900             WIN_ReleasePtr(wndPtr);
901         }
902 
903         if (!(flags & WIN_ISMDICLIENT))
904         {
905             WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
906             return 0;
907         }
908 
909         /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
910          * MDICREATESTRUCT members have the originally passed values.
911          *
912          * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
913          * have the same layout.
914          */
915         mdi_cs.szClass = cs->lpszClass;
916         mdi_cs.szTitle = cs->lpszName;
917         mdi_cs.hOwner = cs->hInstance;
918         mdi_cs.x = cs->x;
919         mdi_cs.y = cs->y;
920         mdi_cs.cx = cs->cx;
921         mdi_cs.cy = cs->cy;
922         mdi_cs.style = cs->style;
923         mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
924 
925         cs->lpCreateParams = (LPVOID)&mdi_cs;
926 
927         if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
928         {
929             if (cs->style & WS_POPUP)
930             {
931                 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
932                 return 0;
933             }
934             cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
935         }
936         else
937         {
938             cs->style &= ~WS_POPUP;
939             cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
940                 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
941         }
942 
943         top_child = GetWindow(cs->hwndParent, GW_CHILD);
944 
945         if (top_child)
946         {
947             /* Restore current maximized child */
948             if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
949             {
950                 TRACE("Restoring current maximized child %p\n", top_child);
951                 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
952                 ShowWindow( top_child, SW_SHOWNORMAL );
953                 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
954             }
955         }
956     }
957 
958     /* Find the parent window */
959 
960     parent = cs->hwndParent;
961     owner = 0;
962 
963     if (cs->hwndParent == HWND_MESSAGE)
964     {
965       /* native ole32.OleInitialize uses HWND_MESSAGE to create the
966        * message window (style: WS_POPUP|WS_DISABLED)
967        */
968       FIXME("Parent is HWND_MESSAGE\n");
969       parent = GetDesktopWindow();
970     }
971     else if (cs->hwndParent)
972     {
973         if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
974         {
975             parent = GetDesktopWindow();
976             owner = cs->hwndParent;
977         }
978     }
979     else
980     {
981         if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
982         {
983             WARN("No parent for child window\n" );
984             SetLastError(ERROR_TLW_WITH_WSCHILD);
985             return 0;  /* WS_CHILD needs a parent, but WS_POPUP doesn't */
986         }
987         if (className != (LPCWSTR)DESKTOP_CLASS_ATOM)  /* are we creating the desktop itself? */
988             parent = GetDesktopWindow();
989     }
990 
991     WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
992 
993     if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
994         ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
995           (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
996         cs->dwExStyle |= WS_EX_WINDOWEDGE;
997     else
998         cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
999 
1000     /* Create the window structure */
1001 
1002     if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1003         return 0;
1004     hwnd = wndPtr->hwndSelf;
1005 
1006     /* Fill the window structure */
1007 
1008     wndPtr->tid            = GetCurrentThreadId();
1009     wndPtr->hInstance      = cs->hInstance;
1010     wndPtr->text           = NULL;
1011     wndPtr->dwStyle        = cs->style & ~WS_VISIBLE;
1012     wndPtr->dwExStyle      = cs->dwExStyle;
1013     wndPtr->wIDmenu        = 0;
1014     wndPtr->helpContext    = 0;
1015     wndPtr->pVScroll       = NULL;
1016     wndPtr->pHScroll       = NULL;
1017     wndPtr->userdata       = 0;
1018     wndPtr->hIcon          = 0;
1019     wndPtr->hIconSmall     = 0;
1020     wndPtr->hSysMenu       = 0;
1021     wndPtr->flags         |= (flags & WIN_ISWIN32);
1022 
1023     if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1024 
1025     /*
1026      * Correct the window styles.
1027      *
1028      * It affects only the style loaded into the WIN structure.
1029      */
1030 
1031     if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1032     {
1033         wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1034         if (!(wndPtr->dwStyle & WS_POPUP))
1035             wndPtr->dwStyle |= WS_CAPTION;
1036     }
1037 
1038     /*
1039      * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1040      * why does the user get to set it?
1041      */
1042 
1043     if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1044           (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1045         wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1046     else
1047         wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1048 
1049     if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1050         wndPtr->flags |= WIN_NEED_SIZE;
1051 
1052     SERVER_START_REQ( set_window_info )
1053     {
1054         req->handle    = hwnd;
1055         req->flags     = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1056         req->style     = wndPtr->dwStyle;
1057         req->ex_style  = wndPtr->dwExStyle;
1058         req->instance  = (void *)wndPtr->hInstance;
1059         req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1060         req->extra_offset = -1;
1061         wine_server_call( req );
1062     }
1063     SERVER_END_REQ;
1064 
1065     /* Set the window menu */
1066 
1067     if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1068     {
1069         if (cs->hMenu)
1070         {
1071             if (!MENU_SetMenu(hwnd, cs->hMenu))
1072             {
1073                 WIN_ReleasePtr( wndPtr );
1074                 free_window_handle( hwnd );
1075                 return 0;
1076             }
1077         }
1078         else
1079         {
1080             LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1081             if (menuName)
1082             {
1083                 if (!cs->hInstance || HIWORD(cs->hInstance))
1084                     cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1085                 else
1086                     cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1087 
1088                 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1089             }
1090         }
1091     }
1092     else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1093 
1094     /* call the WH_CBT hook */
1095 
1096     /* the window style passed to the hook must be the real window style,
1097      * rather than just the window style that the caller to CreateWindowEx
1098      * passed in, so we have to copy the original CREATESTRUCT and get the
1099      * the real style. */
1100     cbcs = *cs;
1101     cbcs.style = wndPtr->dwStyle;
1102     cbtc.lpcs = &cbcs;
1103     cbtc.hwndInsertAfter = HWND_TOP;
1104     WIN_ReleasePtr( wndPtr );
1105     if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1106 
1107     /* send the WM_GETMINMAXINFO message and fix the size if needed */
1108 
1109     cx = cs->cx;
1110     cy = cs->cy;
1111     if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1112     {
1113         POINT maxSize, maxPos, minTrack, maxTrack;
1114         WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1115         if (maxTrack.x < cx) cx = maxTrack.x;
1116         if (maxTrack.y < cy) cy = maxTrack.y;
1117         if (minTrack.x > cx) cx = minTrack.x;
1118         if (minTrack.y > cy) cy = minTrack.y;
1119     }
1120 
1121     if (cx < 0) cx = 0;
1122     if (cy < 0) cy = 0;
1123     SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1124     /* check for wraparound */
1125     if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1126     if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1127     if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1128 
1129     /* send WM_NCCREATE */
1130 
1131     TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1132     if (unicode)
1133         result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1134     else
1135         result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1136     if (!result)
1137     {
1138         WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1139         goto failed;
1140     }
1141 
1142     /* send WM_NCCALCSIZE */
1143 
1144     if ((wndPtr = WIN_GetPtr(hwnd)))
1145     {
1146         /* yes, even if the CBT hook was called with HWND_TOP */
1147         POINT pt;
1148         HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1149         RECT window_rect = wndPtr->rectWindow;
1150         RECT client_rect = window_rect;
1151         WIN_ReleasePtr( wndPtr );
1152 
1153         /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1154         pt.x = pt.y = 0;
1155         MapWindowPoints( parent, 0, &pt, 1 );
1156         OffsetRect( &client_rect, pt.x, pt.y );
1157         SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1158         OffsetRect( &client_rect, -pt.x, -pt.y );
1159         set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1160     }
1161     else return 0;
1162 
1163     /* send WM_CREATE */
1164 
1165     if (unicode)
1166         result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1167     else
1168         result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1169     if (result == -1) goto failed;
1170 
1171     /* call the driver */
1172 
1173     if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1174 
1175     NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1176 
1177     /* send the size messages */
1178 
1179     if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1180     if (!(wndPtr->flags & WIN_NEED_SIZE))
1181     {
1182         rect = wndPtr->rectClient;
1183         WIN_ReleasePtr( wndPtr );
1184         SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1185                       MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1186         SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1187     }
1188     else WIN_ReleasePtr( wndPtr );
1189 
1190     /* Show the window, maximizing or minimizing if needed */
1191 
1192     style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1193     if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1194     {
1195         RECT newPos;
1196         UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1197 
1198         swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1199         swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1200         if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1201         SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1202     }
1203 
1204     /* Notify the parent window only */
1205 
1206     send_parent_notify( hwnd, WM_CREATE );
1207     if (!IsWindow( hwnd )) return 0;
1208 
1209     if (cs->style & WS_VISIBLE)
1210     {
1211         if (cs->style & WS_MAXIMIZE)
1212             sw = SW_SHOW;
1213         else if (cs->style & WS_MINIMIZE)
1214             sw = SW_SHOWMINIMIZED;
1215 
1216         ShowWindow( hwnd, sw );
1217         if (cs->dwExStyle & WS_EX_MDICHILD)
1218         {
1219             SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1220             /* ShowWindow won't activate child windows */
1221             SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1222         }
1223     }
1224 
1225     /* Call WH_SHELL hook */
1226 
1227     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1228         HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1229 
1230     TRACE("created window %p\n", hwnd);
1231     return hwnd;
1232 
1233 failed:
1234     WIN_DestroyWindow( hwnd );
1235     return 0;
1236 }
1237 
1238 
1239 /***********************************************************************
1240  *              CreateWindow (USER.41)
1241  */
1242 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1243                               DWORD style, INT16 x, INT16 y, INT16 width,
1244                               INT16 height, HWND16 parent, HMENU16 menu,
1245                               HINSTANCE16 instance, LPVOID data )
1246 {
1247     return CreateWindowEx16( 0, className, windowName, style,
1248                              x, y, width, height, parent, menu, instance, data );
1249 }
1250 
1251 
1252 /***********************************************************************
1253  *              CreateWindowEx (USER.452)
1254  */
1255 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1256                                 LPCSTR windowName, DWORD style, INT16 x,
1257                                 INT16 y, INT16 width, INT16 height,
1258                                 HWND16 parent, HMENU16 menu,
1259                                 HINSTANCE16 instance, LPVOID data )
1260 {
1261     CREATESTRUCTA cs;
1262     char buffer[256];
1263 
1264     /* Fix the coordinates */
1265 
1266     cs.x  = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1267     cs.y  = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1268     cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1269     cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1270 
1271     /* Create the window */
1272 
1273     cs.lpCreateParams = data;
1274     cs.hInstance      = HINSTANCE_32(instance);
1275     cs.hMenu          = HMENU_32(menu);
1276     cs.hwndParent     = WIN_Handle32( parent );
1277     cs.style          = style;
1278     cs.lpszName       = windowName;
1279     cs.lpszClass      = className;
1280     cs.dwExStyle      = exStyle;
1281 
1282     if (!IS_INTRESOURCE(className))
1283     {
1284         WCHAR bufferW[256];
1285 
1286         if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1287             return 0;
1288         return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1289     }
1290     else
1291     {
1292         if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1293         {
1294             ERR( "bad atom %x\n", LOWORD(className));
1295             return 0;
1296         }
1297         cs.lpszClass = buffer;
1298         return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1299     }
1300 }
1301 
1302 
1303 /***********************************************************************
1304  *              CreateWindowExA (USER32.@)
1305  */
1306 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1307                                  LPCSTR windowName, DWORD style, INT x,
1308                                  INT y, INT width, INT height,
1309                                  HWND parent, HMENU menu,
1310                                  HINSTANCE instance, LPVOID data )
1311 {
1312     CREATESTRUCTA cs;
1313 
1314     cs.lpCreateParams = data;
1315     cs.hInstance      = instance;
1316     cs.hMenu          = menu;
1317     cs.hwndParent     = parent;
1318     cs.x              = x;
1319     cs.y              = y;
1320     cs.cx             = width;
1321     cs.cy             = height;
1322     cs.style          = style;
1323     cs.lpszName       = windowName;
1324     cs.lpszClass      = className;
1325     cs.dwExStyle      = exStyle;
1326 
1327     if (!IS_INTRESOURCE(className))
1328     {
1329         WCHAR bufferW[256];
1330         if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1331             return 0;
1332         return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1333     }
1334     return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1335 }
1336 
1337 
1338 /***********************************************************************
1339  *              CreateWindowExW (USER32.@)
1340  */
1341 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1342                                  LPCWSTR windowName, DWORD style, INT x,
1343                                  INT y, INT width, INT height,
1344                                  HWND parent, HMENU menu,
1345                                  HINSTANCE instance, LPVOID data )
1346 {
1347     CREATESTRUCTW cs;
1348 
1349     cs.lpCreateParams = data;
1350     cs.hInstance      = instance;
1351     cs.hMenu          = menu;
1352     cs.hwndParent     = parent;
1353     cs.x              = x;
1354     cs.y              = y;
1355     cs.cx             = width;
1356     cs.cy             = height;
1357     cs.style          = style;
1358     cs.lpszName       = windowName;
1359     cs.lpszClass      = className;
1360     cs.dwExStyle      = exStyle;
1361 
1362     /* Note: we rely on the fact that CREATESTRUCTA and */
1363     /* CREATESTRUCTW have the same layout. */
1364     return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1365 }
1366 
1367 
1368 /***********************************************************************
1369  *           WIN_SendDestroyMsg
1370  */
1371 static void WIN_SendDestroyMsg( HWND hwnd )
1372 {
1373     GUITHREADINFO info;
1374 
1375     if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1376     {
1377         if (hwnd == info.hwndCaret) DestroyCaret();
1378         if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1379     }
1380 
1381     /*
1382      * Send the WM_DESTROY to the window.
1383      */
1384     SendMessageW( hwnd, WM_DESTROY, 0, 0);
1385 
1386     /*
1387      * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1388      * make sure that the window still exists when we come back.
1389      */
1390     if (IsWindow(hwnd))
1391     {
1392         HWND* pWndArray;
1393         int i;
1394 
1395         if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1396 
1397         for (i = 0; pWndArray[i]; i++)
1398         {
1399             if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1400         }
1401         HeapFree( GetProcessHeap(), 0, pWndArray );
1402     }
1403     else
1404       WARN("\tdestroyed itself while in WM_DESTROY!\n");
1405 }
1406 
1407 
1408 /***********************************************************************
1409  *              DestroyWindow (USER32.@)
1410  */
1411 BOOL WINAPI DestroyWindow( HWND hwnd )
1412 {
1413     BOOL is_child;
1414 
1415     if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1416     {
1417         SetLastError( ERROR_ACCESS_DENIED );
1418         return FALSE;
1419     }
1420 
1421     TRACE("(%p)\n", hwnd);
1422 
1423       /* Call hooks */
1424 
1425     if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1426 
1427     if (MENU_IsMenuActive() == hwnd)
1428         EndMenu();
1429 
1430     is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1431 
1432     if (is_child)
1433     {
1434         if (!USER_IsExitingThread( GetCurrentThreadId() ))
1435             send_parent_notify( hwnd, WM_DESTROY );
1436     }
1437     else if (!GetWindow( hwnd, GW_OWNER ))
1438     {
1439         HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1440         /* FIXME: clean up palette - see "Internals" p.352 */
1441     }
1442 
1443     if (!IsWindow(hwnd)) return TRUE;
1444 
1445       /* Hide the window */
1446     if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1447     {
1448         /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1449         if (is_child)
1450             ShowWindow( hwnd, SW_HIDE );
1451         else
1452             SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1453                           SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1454     }
1455 
1456     if (!IsWindow(hwnd)) return TRUE;
1457 
1458       /* Recursively destroy owned windows */
1459 
1460     if (!is_child)
1461     {
1462         for (;;)
1463         {
1464             int i, got_one = 0;
1465             HWND *list = WIN_ListChildren( GetDesktopWindow() );
1466             if (list)
1467             {
1468                 for (i = 0; list[i]; i++)
1469                 {
1470                     if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1471                     if (WIN_IsCurrentThread( list[i] ))
1472                     {
1473                         DestroyWindow( list[i] );
1474                         got_one = 1;
1475                         continue;
1476                     }
1477                     WIN_SetOwner( list[i], 0 );
1478                 }
1479                 HeapFree( GetProcessHeap(), 0, list );
1480             }
1481             if (!got_one) break;
1482         }
1483     }
1484 
1485       /* Send destroy messages */
1486 
1487     WIN_SendDestroyMsg( hwnd );
1488     if (!IsWindow( hwnd )) return TRUE;
1489 
1490     if (GetClipboardOwner() == hwnd)
1491         CLIPBOARD_ReleaseOwner();
1492 
1493       /* Destroy the window storage */
1494 
1495     WIN_DestroyWindow( hwnd );
1496     return TRUE;
1497 }
1498 
1499 
1500 /***********************************************************************
1501  *              CloseWindow (USER32.@)
1502  */
1503 BOOL WINAPI CloseWindow( HWND hwnd )
1504 {
1505     if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1506     ShowWindow( hwnd, SW_MINIMIZE );
1507     return TRUE;
1508 }
1509 
1510 
1511 /***********************************************************************
1512  *              OpenIcon (USER32.@)
1513  */
1514 BOOL WINAPI OpenIcon( HWND hwnd )
1515 {
1516     if (!IsIconic( hwnd )) return FALSE;
1517     ShowWindow( hwnd, SW_SHOWNORMAL );
1518     return TRUE;
1519 }
1520 
1521 
1522 /***********************************************************************
1523  *              FindWindowExW (USER32.@)
1524  */
1525 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1526 {
1527     HWND *list = NULL;
1528     HWND retvalue = 0;
1529     int i = 0, len = 0;
1530     WCHAR *buffer = NULL;
1531 
1532     if (!parent) parent = GetDesktopWindow();
1533     if (title)
1534     {
1535         len = strlenW(title) + 1;  /* one extra char to check for chars beyond the end */
1536         if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1537     }
1538 
1539     if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1540 
1541     if (child)
1542     {
1543         child = WIN_GetFullHandle( child );
1544         while (list[i] && list[i] != child) i++;
1545         if (!list[i]) goto done;
1546         i++;  /* start from next window */
1547     }
1548 
1549     if (title)
1550     {
1551         while (list[i])
1552         {
1553             if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1554             i++;
1555         }
1556     }
1557     retvalue = list[i];
1558 
1559  done:
1560     HeapFree( GetProcessHeap(), 0, list );
1561     HeapFree( GetProcessHeap(), 0, buffer );
1562     return retvalue;
1563 }
1564 
1565 
1566 
1567 /***********************************************************************
1568  *              FindWindowA (USER32.@)
1569  */
1570 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1571 {
1572     HWND ret = FindWindowExA( 0, 0, className, title );
1573     if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1574     return ret;
1575 }
1576 
1577 
1578 /***********************************************************************
1579  *              FindWindowExA (USER32.@)
1580  */
1581 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1582 {
1583     LPWSTR titleW = NULL;
1584     HWND hwnd = 0;
1585 
1586     if (title)
1587     {
1588         DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1589         if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1590         MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1591     }
1592 
1593     if (!IS_INTRESOURCE(className))
1594     {
1595         WCHAR classW[256];
1596         if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1597             hwnd = FindWindowExW( parent, child, classW, titleW );
1598     }
1599     else
1600     {
1601         hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1602     }
1603 
1604     HeapFree( GetProcessHeap(), 0, titleW );
1605     return hwnd;
1606 }
1607 
1608 
1609 /***********************************************************************
1610  *              FindWindowW (USER32.@)
1611  */
1612 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1613 {
1614     return FindWindowExW( 0, 0, className, title );
1615 }
1616 
1617 
1618 /**********************************************************************
1619  *              GetDesktopWindow (USER32.@)
1620  */
1621 HWND WINAPI GetDesktopWindow(void)
1622 {
1623     struct user_thread_info *thread_info = get_user_thread_info();
1624 
1625     if (thread_info->desktop) return thread_info->desktop;
1626 
1627     SERVER_START_REQ( get_desktop_window )
1628     {
1629         req->force = 0;
1630         if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1631     }
1632     SERVER_END_REQ;
1633 
1634     if (!thread_info->desktop)
1635     {
1636         USEROBJECTFLAGS flags;
1637         if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1638                                         sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1639         {
1640             static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1641             STARTUPINFOW si;
1642             PROCESS_INFORMATION pi;
1643             WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1644 
1645             memset( &si, 0, sizeof(si) );
1646             si.cb = sizeof(si);
1647             si.dwFlags = STARTF_USESTDHANDLES;
1648             si.hStdInput  = 0;
1649             si.hStdOutput = 0;
1650             si.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
1651 
1652             GetSystemDirectoryW( cmdline, MAX_PATH );
1653             lstrcatW( cmdline, command_line );
1654             if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1655                                 NULL, NULL, &si, &pi ))
1656             {
1657                 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1658                 WaitForInputIdle( pi.hProcess, 10000 );
1659                 CloseHandle( pi.hThread );
1660                 CloseHandle( pi.hProcess );
1661             }
1662             else WARN( "failed to start explorer, err %d\n", GetLastError() );
1663         }
1664         else TRACE( "not starting explorer since winstation is not visible\n" );
1665 
1666         SERVER_START_REQ( get_desktop_window )
1667         {
1668             req->force = 1;
1669             if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1670         }
1671         SERVER_END_REQ;
1672     }
1673 
1674     if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1675         ERR( "failed to create desktop window\n" );
1676 
1677     return thread_info->desktop;
1678 }
1679 
1680 
1681 /*******************************************************************
1682  *              EnableWindow (USER32.@)
1683  */
1684 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1685 {
1686     BOOL retvalue;
1687     HWND full_handle;
1688 
1689     if (is_broadcast(hwnd))
1690     {
1691         SetLastError( ERROR_INVALID_PARAMETER );
1692         return FALSE;
1693     }
1694 
1695     if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1696         return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1697 
1698     hwnd = full_handle;
1699 
1700     TRACE("( %p, %d )\n", hwnd, enable);
1701 
1702     retvalue = !IsWindowEnabled( hwnd );
1703 
1704     if (enable && retvalue)
1705     {
1706         WIN_SetStyle( hwnd, 0, WS_DISABLED );
1707         SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1708     }
1709     else if (!enable && !retvalue)
1710     {
1711         HWND capture_wnd;
1712 
1713         SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1714 
1715         WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1716 
1717         if (hwnd == GetFocus())
1718             SetFocus( 0 );  /* A disabled window can't have the focus */
1719 
1720         capture_wnd = GetCapture();
1721         if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1722             ReleaseCapture();  /* A disabled window can't capture the mouse */
1723 
1724         SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1725     }
1726     return retvalue;
1727 }
1728 
1729 
1730 /***********************************************************************
1731  *              IsWindowEnabled (USER32.@)
1732  */
1733 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1734 {
1735     return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1736 }
1737 
1738 
1739 /***********************************************************************
1740  *              IsWindowUnicode (USER32.@)
1741  */
1742 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1743 {
1744     WND * wndPtr;
1745     BOOL retvalue = FALSE;
1746 
1747     if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1748 
1749     if (wndPtr == WND_DESKTOP) return TRUE;
1750 
1751     if (wndPtr != WND_OTHER_PROCESS)
1752     {
1753         retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1754         WIN_ReleasePtr( wndPtr );
1755     }
1756     else
1757     {
1758         SERVER_START_REQ( get_window_info )
1759         {
1760             req->handle = hwnd;
1761             if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1762         }
1763         SERVER_END_REQ;
1764     }
1765     return retvalue;
1766 }
1767 
1768 
1769 /**********************************************************************
1770  *           WIN_GetWindowLong
1771  *
1772  * Helper function for GetWindowLong().
1773  */
1774 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1775 {
1776     LONG_PTR retvalue = 0;
1777     WND *wndPtr;
1778 
1779     if (offset == GWLP_HWNDPARENT)
1780     {
1781         HWND parent = GetAncestor( hwnd, GA_PARENT );
1782         if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1783         return (ULONG_PTR)parent;
1784     }
1785 
1786     if (!(wndPtr = WIN_GetPtr( hwnd )))
1787     {
1788         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1789         return 0;
1790     }
1791 
1792     if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1793     {
1794         if (offset == GWLP_WNDPROC)
1795         {
1796             SetLastError( ERROR_ACCESS_DENIED );
1797             return 0;
1798         }
1799         SERVER_START_REQ( set_window_info )
1800         {
1801             req->handle = hwnd;
1802             req->flags  = 0;  /* don't set anything, just retrieve */
1803             req->extra_offset = (offset >= 0) ? offset : -1;
1804             req->extra_size = (offset >= 0) ? size : 0;
1805             if (!wine_server_call_err( req ))
1806             {
1807                 switch(offset)
1808                 {
1809                 case GWL_STYLE:      retvalue = reply->old_style; break;
1810                 case GWL_EXSTYLE:    retvalue = reply->old_ex_style; break;
1811                 case GWLP_ID:        retvalue = reply->old_id; break;
1812                 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1813                 case GWLP_USERDATA:  retvalue = reply->old_user_data; break;
1814                 default:
1815                     if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1816                     else SetLastError( ERROR_INVALID_INDEX );
1817                     break;
1818                 }
1819             }
1820         }
1821         SERVER_END_REQ;
1822         return retvalue;
1823     }
1824 
1825     /* now we have a valid wndPtr */
1826 
1827     if (offset >= 0)
1828     {
1829         if (offset > (int)(wndPtr->cbWndExtra - size))
1830         {
1831             WARN("Invalid offset %d\n", offset );
1832             WIN_ReleasePtr( wndPtr );
1833             SetLastError( ERROR_INVALID_INDEX );
1834             return 0;
1835         }
1836         retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1837 
1838         /* Special case for dialog window procedure */
1839         if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1840             retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1841         WIN_ReleasePtr( wndPtr );
1842         return retvalue;
1843     }
1844 
1845     switch(offset)
1846     {
1847     case GWLP_USERDATA:  retvalue = wndPtr->userdata; break;
1848     case GWL_STYLE:      retvalue = wndPtr->dwStyle; break;
1849     case GWL_EXSTYLE:    retvalue = wndPtr->dwExStyle; break;
1850     case GWLP_ID:        retvalue = wndPtr->wIDmenu; break;
1851     case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1852     case GWLP_WNDPROC:
1853         /* This looks like a hack only for the edit control (see tests). This makes these controls
1854          * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1855          * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1856          */
1857         if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1858             retvalue = (ULONG_PTR)wndPtr->winproc;
1859         else
1860             retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1861         break;
1862     default:
1863         WARN("Unknown offset %d\n", offset );
1864         SetLastError( ERROR_INVALID_INDEX );
1865         break;
1866     }
1867     WIN_ReleasePtr(wndPtr);
1868     return retvalue;
1869 }
1870 
1871 
1872 /**********************************************************************
1873  *           WIN_SetWindowLong
1874  *
1875  * Helper function for SetWindowLong().
1876  *
1877  * 0 is the failure code. However, in the case of failure SetLastError
1878  * must be set to distinguish between a 0 return value and a failure.
1879  */
1880 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1881 {
1882     STYLESTRUCT style;
1883     BOOL ok;
1884     LONG_PTR retval = 0;
1885     WND *wndPtr;
1886 
1887     TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1888 
1889     if (is_broadcast(hwnd))
1890     {
1891         SetLastError( ERROR_INVALID_PARAMETER );
1892         return FALSE;
1893     }
1894 
1895     if (!(wndPtr = WIN_GetPtr( hwnd )))
1896     {
1897         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1898         return 0;
1899     }
1900     if (wndPtr == WND_DESKTOP)
1901     {
1902         /* can't change anything on the desktop window */
1903         SetLastError( ERROR_ACCESS_DENIED );
1904         return 0;
1905     }
1906     if (wndPtr == WND_OTHER_PROCESS)
1907     {
1908         if (offset == GWLP_WNDPROC)
1909         {
1910             SetLastError( ERROR_ACCESS_DENIED );
1911             return 0;
1912         }
1913         if (offset > 32767 || offset < -32767)
1914         {
1915             SetLastError( ERROR_INVALID_INDEX );
1916             return 0;
1917         }
1918         return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1919     }
1920 
1921     /* first some special cases */
1922     switch( offset )
1923     {
1924     case GWL_STYLE:
1925     case GWL_EXSTYLE:
1926         style.styleOld =
1927             offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1928         style.styleNew = newval;
1929         WIN_ReleasePtr( wndPtr );
1930         SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1931         if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1932         newval = style.styleNew;
1933         break;
1934     case GWLP_HWNDPARENT:
1935         if (wndPtr->parent == GetDesktopWindow())
1936         {
1937             WIN_ReleasePtr( wndPtr );
1938             return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1939         }
1940         else
1941         {
1942             WIN_ReleasePtr( wndPtr );
1943             return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1944         }
1945     case GWLP_WNDPROC:
1946     {
1947         WNDPROC proc;
1948         UINT old_flags = wndPtr->flags;
1949         retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1950         if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1951         else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1952         if (proc) wndPtr->winproc = proc;
1953         if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1954         else wndPtr->flags &= ~WIN_ISUNICODE;
1955         if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1956         {
1957             WIN_ReleasePtr( wndPtr );
1958             return retval;
1959         }
1960         /* update is_unicode flag on the server side */
1961         break;
1962     }
1963     case GWLP_ID:
1964     case GWLP_HINSTANCE:
1965     case GWLP_USERDATA:
1966         break;
1967     case DWLP_DLGPROC:
1968         if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1969             (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1970         {
1971             WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1972             retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1973             if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1974             else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1975             WIN_ReleasePtr( wndPtr );
1976             return retval;
1977         }
1978         /* fall through */
1979     default:
1980         if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1981         {
1982             WARN("Invalid offset %d\n", offset );
1983             WIN_ReleasePtr( wndPtr );
1984             SetLastError( ERROR_INVALID_INDEX );
1985             return 0;
1986         }
1987         else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1988         {
1989             /* already set to the same value */
1990             WIN_ReleasePtr( wndPtr );
1991             return newval;
1992         }
1993         break;
1994     }
1995 
1996     SERVER_START_REQ( set_window_info )
1997     {
1998         req->handle = hwnd;
1999         req->extra_offset = -1;
2000         switch(offset)
2001         {
2002         case GWL_STYLE:
2003             req->flags = SET_WIN_STYLE;
2004             req->style = newval;
2005             break;
2006         case GWL_EXSTYLE:
2007             req->flags = SET_WIN_EXSTYLE;
2008             /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2009             newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2010             req->ex_style = newval;
2011             break;
2012         case GWLP_ID:
2013             req->flags = SET_WIN_ID;
2014             req->id = newval;
2015             break;
2016         case GWLP_HINSTANCE:
2017             req->flags = SET_WIN_INSTANCE;
2018             req->instance = (void *)newval;
2019             break;
2020         case GWLP_WNDPROC:
2021             req->flags = SET_WIN_UNICODE;
2022             req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2023             break;
2024         case GWLP_USERDATA:
2025             req->flags = SET_WIN_USERDATA;
2026             req->user_data = newval;
2027             break;
2028         default:
2029             req->flags = SET_WIN_EXTRA;
2030             req->extra_offset = offset;
2031             req->extra_size = size;
2032             set_win_data( &req->extra_value, newval, size );
2033         }
2034         if ((ok = !wine_server_call_err( req )))
2035         {
2036             switch(offset)
2037             {
2038             case GWL_STYLE:
2039                 wndPtr->dwStyle = newval;
2040                 retval = reply->old_style;
2041                 break;
2042             case GWL_EXSTYLE:
2043                 wndPtr->dwExStyle = newval;
2044                 retval = reply->old_ex_style;
2045                 break;
2046             case GWLP_ID:
2047                 wndPtr->wIDmenu = newval;
2048                 retval = reply->old_id;
2049                 break;
2050             case GWLP_HINSTANCE:
2051                 wndPtr->hInstance = (HINSTANCE)newval;
2052                 retval = (ULONG_PTR)reply->old_instance;
2053                 break;
2054             case GWLP_WNDPROC:
2055                 break;
2056             case GWLP_USERDATA:
2057                 wndPtr->userdata = newval;
2058                 retval = reply->old_user_data;
2059                 break;
2060             default:
2061                 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2062                 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2063                 break;
2064             }
2065         }
2066     }
2067     SERVER_END_REQ;
2068     WIN_ReleasePtr( wndPtr );
2069 
2070     if (!ok) return 0;
2071 
2072     if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2073 
2074     if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2075         SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2076 
2077     return retval;
2078 }
2079 
2080 
2081 /**********************************************************************
2082  *              GetWindowLong (USER.135)
2083  */
2084 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2085 {
2086     WND *wndPtr;
2087     LONG_PTR retvalue;
2088     BOOL is_winproc = (offset == GWLP_WNDPROC);
2089 
2090     if (offset >= 0)
2091     {
2092         if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2093         {
2094             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2095             return 0;
2096         }
2097         if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2098         {
2099             if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2100             {
2101                 /*
2102                  * Some programs try to access last element from 16 bit
2103                  * code using illegal offset value. Hopefully this is
2104                  * what those programs really expect.
2105                  */
2106                 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2107                 {
2108                     INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2109                     ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2110                     offset = offset2;
2111                 }
2112                 else
2113                 {
2114                     WARN("Invalid offset %d\n", offset );
2115                     WIN_ReleasePtr( wndPtr );
2116                     SetLastError( ERROR_INVALID_INDEX );
2117                     return 0;
2118                 }
2119             }
2120             is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2121             WIN_ReleasePtr( wndPtr );
2122         }
2123     }
2124     retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2125     if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2126     return retvalue;
2127 }
2128 
2129 
2130 /**********************************************************************
2131  *              GetWindowWord (USER32.@)
2132  */
2133 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2134 {
2135     switch(offset)
2136     {
2137     case GWLP_ID:
2138     case GWLP_HINSTANCE:
2139     case GWLP_HWNDPARENT:
2140         break;
2141     default:
2142         if (offset < 0)
2143         {
2144             WARN("Invalid offset %d\n", offset );
2145             SetLastError( ERROR_INVALID_INDEX );
2146             return 0;
2147         }
2148         break;
2149     }
2150     return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2151 }
2152 
2153 
2154 /**********************************************************************
2155  *              GetWindowLongA (USER32.@)
2156  */
2157 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2158 {
2159     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2160 }
2161 
2162 
2163 /**********************************************************************
2164  *              GetWindowLongW (USER32.@)
2165  */
2166 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2167 {
2168     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2169 }
2170 
2171 
2172 /**********************************************************************
2173  *              SetWindowLong (USER.136)
2174  */
2175 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2176 {
2177     WND *wndPtr;
2178     BOOL is_winproc = (offset == GWLP_WNDPROC);
2179 
2180     if (offset == DWLP_DLGPROC)
2181     {
2182         if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2183         {
2184             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2185             return 0;
2186         }
2187         if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2188         {
2189             is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2190                           (wndPtr->flags & WIN_ISDIALOG));
2191             WIN_ReleasePtr( wndPtr );
2192         }
2193     }
2194 
2195     if (is_winproc)
2196     {
2197         WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2198         WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2199         return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2200     }
2201     else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2202 }
2203 
2204 
2205 /**********************************************************************
2206  *              SetWindowWord (USER32.@)
2207  */
2208 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2209 {
2210     switch(offset)
2211     {
2212     case GWLP_ID:
2213     case GWLP_HINSTANCE:
2214     case GWLP_HWNDPARENT:
2215         break;
2216     default:
2217         if (offset < 0)
2218         {
2219             WARN("Invalid offset %d\n", offset );
2220             SetLastError( ERROR_INVALID_INDEX );
2221             return 0;
2222         }
2223         break;
2224     }
2225     return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2226 }
2227 
2228 
2229 /**********************************************************************
2230  *              SetWindowLongA (USER32.@)
2231  *
2232  * See SetWindowLongW.
2233  */
2234 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2235 {
2236     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2237 }
2238 
2239 
2240 /**********************************************************************
2241  *              SetWindowLongW (USER32.@) Set window attribute
2242  *
2243  * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2244  * value in a window's extra memory.
2245  *
2246  * The _hwnd_ parameter specifies the window.  is the handle to a
2247  * window that has extra memory. The _newval_ parameter contains the
2248  * new attribute or extra memory value.  If positive, the _offset_
2249  * parameter is the byte-addressed location in the window's extra
2250  * memory to set.  If negative, _offset_ specifies the window
2251  * attribute to set, and should be one of the following values:
2252  *
2253  * GWL_EXSTYLE      The window's extended window style
2254  *
2255  * GWL_STYLE        The window's window style.
2256  *
2257  * GWLP_WNDPROC     Pointer to the window's window procedure.
2258  *
2259  * GWLP_HINSTANCE   The window's pplication instance handle.
2260  *
2261  * GWLP_ID          The window's identifier.
2262  *
2263  * GWLP_USERDATA    The window's user-specified data.
2264  *
2265  * If the window is a dialog box, the _offset_ parameter can be one of
2266  * the following values:
2267  *
2268  * DWLP_DLGPROC     The address of the window's dialog box procedure.
2269  *
2270  * DWLP_MSGRESULT   The return value of a message
2271  *                  that the dialog box procedure processed.
2272  *
2273  * DWLP_USER        Application specific information.
2274  *
2275  * RETURNS
2276  *
2277  * If successful, returns the previous value located at _offset_. Otherwise,
2278  * returns 0.
2279  *
2280  * NOTES
2281  *
2282  * Extra memory for a window class is specified by a nonzero cbWndExtra
2283  * parameter of the WNDCLASS structure passed to RegisterClass() at the
2284  * time of class creation.
2285  *
2286  * Using GWL_WNDPROC to set a new window procedure effectively creates
2287  * a window subclass. Use CallWindowProc() in the new windows procedure
2288  * to pass messages to the superclass's window procedure.
2289  *
2290  * The user data is reserved for use by the application which created
2291  * the window.
2292  *
2293  * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2294  * instead, call the EnableWindow() function to change the window's
2295  * disabled state.
2296  *
2297  * Do not use GWL_HWNDPARENT to reset the window's parent, use
2298  * SetParent() instead.
2299  *
2300  * Win95:
2301  * When offset is GWL_STYLE and the calling app's ver is 4.0,
2302  * it sends WM_STYLECHANGING before changing the settings
2303  * and WM_STYLECHANGED afterwards.
2304  * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2305  */
2306 LONG WINAPI SetWindowLongW(
2307     HWND hwnd,  /* [in] window to alter */
2308     INT offset, /* [in] offset, in bytes, of location to alter */
2309     LONG newval /* [in] new value of location */
2310 ) {
2311     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2312 }
2313 
2314 
2315 /*******************************************************************
2316  *              GetWindowTextA (USER32.@)
2317  */
2318 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2319 {
2320     WCHAR *buffer;
2321 
2322     if (!lpString) return 0;
2323 
2324     if (WIN_IsCurrentProcess( hwnd ))
2325         return (INT)SendMessageA( 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     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2330     get_server_window_text( hwnd, buffer, nMaxCount );
2331     if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2332         lpString[nMaxCount-1] = 0;
2333     HeapFree( GetProcessHeap(), 0, buffer );
2334     return strlen(lpString);
2335 }
2336 
2337 
2338 /*******************************************************************
2339  *              InternalGetWindowText (USER32.@)
2340  */
2341 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2342 {
2343     WND *win;
2344 
2345     if (nMaxCount <= 0) return 0;
2346     if (!(win = WIN_GetPtr( hwnd ))) return 0;
2347     if (win == WND_DESKTOP) lpString[0] = 0;
2348     else if (win != WND_OTHER_PROCESS)
2349     {
2350         if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2351         else lpString[0] = 0;
2352         WIN_ReleasePtr( win );
2353     }
2354     else
2355     {
2356         get_server_window_text( hwnd, lpString, nMaxCount );
2357     }
2358     return strlenW(lpString);
2359 }
2360 
2361 
2362 /*******************************************************************
2363  *              GetWindowTextW (USER32.@)
2364  */
2365 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2366 {
2367     if (!lpString) return 0;
2368 
2369     if (WIN_IsCurrentProcess( hwnd ))
2370         return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2371 
2372     /* when window belongs to other process, don't send a message */
2373     if (nMaxCount <= 0) return 0;
2374     get_server_window_text( hwnd, lpString, nMaxCount );
2375     return strlenW(lpString);
2376 }
2377 
2378 
2379 /*******************************************************************
2380  *              SetWindowTextA (USER32.@)
2381  *              SetWindowText  (USER32.@)
2382  */
2383 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2384 {
2385     if (is_broadcast(hwnd))
2386     {
2387         SetLastError( ERROR_INVALID_PARAMETER );
2388         return FALSE;
2389     }
2390     if (!WIN_IsCurrentProcess( hwnd ))
2391         WARN( "setting text %s of other process window %p should not use SendMessage\n",
2392                debugstr_a(lpString), hwnd );
2393     return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2394 }
2395 
2396 
2397 /*******************************************************************
2398  *              SetWindowTextW (USER32.@)
2399  */
2400 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2401 {
2402     if (is_broadcast(hwnd))
2403     {
2404         SetLastError( ERROR_INVALID_PARAMETER );
2405         return FALSE;
2406     }
2407     if (!WIN_IsCurrentProcess( hwnd ))
2408         WARN( "setting text %s of other process window %p should not use SendMessage\n",
2409                debugstr_w(lpString), hwnd );
2410     return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2411 }
2412 
2413 
2414 /*******************************************************************
2415  *              GetWindowTextLengthA (USER32.@)
2416  */
2417 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2418 {
2419     return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2420 }
2421 
2422 /*******************************************************************
2423  *              GetWindowTextLengthW (USER32.@)
2424  */
2425 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2426 {
2427     return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2428 }
2429 
2430 
2431 /*******************************************************************
2432  *              IsWindow (USER32.@)
2433  */
2434 BOOL WINAPI IsWindow( HWND hwnd )
2435 {
2436     WND *ptr;
2437     BOOL ret;
2438 
2439     if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2440     if (ptr == WND_DESKTOP) return TRUE;
2441 
2442     if (ptr != WND_OTHER_PROCESS)
2443     {
2444         WIN_ReleasePtr( ptr );
2445         return TRUE;
2446     }
2447 
2448     /* check other processes */
2449     SERVER_START_REQ( get_window_info )
2450     {
2451         req->handle = hwnd;
2452         ret = !wine_server_call_err( req );
2453     }
2454     SERVER_END_REQ;
2455     return ret;
2456 }
2457 
2458 
2459 /***********************************************************************
2460  *              GetWindowThreadProcessId (USER32.@)
2461  */
2462 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2463 {
2464     WND *ptr;
2465     DWORD tid = 0;
2466 
2467     if (!(ptr = WIN_GetPtr( hwnd )))
2468     {
2469         SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2470         return 0;
2471     }
2472 
2473     if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2474     {
2475         /* got a valid window */
2476         tid = ptr->tid;
2477         if (process) *process = GetCurrentProcessId();
2478         WIN_ReleasePtr( ptr );
2479         return tid;
2480     }
2481 
2482     /* check other processes */
2483     SERVER_START_REQ( get_window_info )
2484     {
2485         req->handle = hwnd;
2486         if (!wine_server_call_err( req ))
2487         {
2488             tid = (DWORD)reply->tid;
2489             if (process) *process = (DWORD)reply->pid;
2490         }
2491     }
2492     SERVER_END_REQ;
2493     return tid;
2494 }
2495 
2496 
2497 /*****************************************************************
2498  *              GetParent (USER32.@)
2499  */
2500 HWND WINAPI GetParent( HWND hwnd )
2501 {
2502     WND *wndPtr;
2503     HWND retvalue = 0;
2504 
2505     if (!(wndPtr = WIN_GetPtr( hwnd )))
2506     {
2507         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2508         return 0;
2509     }
2510     if (wndPtr == WND_DESKTOP) return 0;
2511     if (wndPtr == WND_OTHER_PROCESS)
2512     {
2513         LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2514         if (style & (WS_POPUP | WS_CHILD))
2515         {
2516             SERVER_START_REQ( get_window_tree )
2517             {
2518                 req->handle = hwnd;
2519                 if (!wine_server_call_err( req ))
2520                 {
2521                     if (style & WS_POPUP) retvalue = reply->owner;
2522                     else if (style & WS_CHILD) retvalue = reply->parent;
2523                 }
2524             }
2525             SERVER_END_REQ;
2526         }
2527     }
2528     else
2529     {
2530         if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2531         else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2532         WIN_ReleasePtr( wndPtr );
2533     }
2534     return retvalue;
2535 }
2536 
2537 
2538 /*****************************************************************
2539  *              GetAncestor (USER32.@)
2540  */
2541 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2542 {
2543     WND *win;
2544     HWND *list, ret = 0;
2545 
2546     switch(type)
2547     {
2548     case GA_PARENT:
2549         if (!(win = WIN_GetPtr( hwnd )))
2550         {
2551             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2552             return 0;
2553         }
2554         if (win == WND_DESKTOP) return 0;
2555         if (win != WND_OTHER_PROCESS)
2556         {
2557             ret = win->parent;
2558             WIN_ReleasePtr( win );
2559         }
2560         else /* need to query the server */
2561         {
2562             SERVER_START_REQ( get_window_tree )
2563             {
2564                 req->handle = hwnd;
2565                 if (!wine_server_call_err( req )) ret = reply->parent;
2566             }
2567             SERVER_END_REQ;
2568         }
2569         break;
2570 
2571     case GA_ROOT:
2572         if (!(list = list_window_parents( hwnd ))) return 0;
2573 
2574         if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd );  /* top-level window */
2575         else
2576         {
2577             int count = 2;
2578             while (list[count]) count++;
2579             ret = list[count - 2];  /* get the one before the desktop */
2580         }
2581         HeapFree( GetProcessHeap(), 0, list );
2582         break;
2583 
2584     case GA_ROOTOWNER:
2585         if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2586         for (;;)
2587         {
2588             HWND parent = GetParent( ret );
2589             if (!parent) break;
2590             ret = parent;
2591         }
2592         break;
2593     }
2594     return ret;
2595 }
2596 
2597 
2598 /*****************************************************************
2599  *              SetParent (USER32.@)
2600  */
2601 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2602 {
2603     HWND full_handle;
2604     HWND old_parent = 0;
2605     BOOL was_visible;
2606     WND *wndPtr;
2607     BOOL ret;
2608 
2609     if (is_broadcast(hwnd) || is_broadcast(parent))
2610     {
2611         SetLastError(ERROR_INVALID_PARAMETER);
2612         return 0;
2613     }
2614 
2615     if (!parent) parent = GetDesktopWindow();
2616     else parent = WIN_GetFullHandle( parent );
2617 
2618     if (!IsWindow( parent ))
2619     {
2620         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2621         return 0;
2622     }
2623 
2624     /* Some applications try to set a child as a parent */
2625     if (IsChild(hwnd, parent))
2626     {
2627         SetLastError( ERROR_INVALID_PARAMETER );
2628         return 0;
2629     }
2630 
2631     if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2632         return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2633 
2634     /* Windows hides the window first, then shows it again
2635      * including the WM_SHOWWINDOW messages and all */
2636     was_visible = ShowWindow( hwnd, SW_HIDE );
2637 
2638     wndPtr = WIN_GetPtr( hwnd );
2639     if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2640 
2641     SERVER_START_REQ( set_parent )
2642     {
2643         req->handle = hwnd;
2644         req->parent = parent;
2645         if ((ret = !wine_server_call( req )))
2646         {
2647             old_parent = reply->old_parent;
2648             wndPtr->parent = parent = reply->full_parent;
2649         }
2650 
2651     }
2652     SERVER_END_REQ;
2653     WIN_ReleasePtr( wndPtr );
2654     if (!ret) return 0;
2655 
2656     USER_Driver->pSetParent( full_handle, parent, old_parent );
2657 
2658     /* SetParent additionally needs to make hwnd the topmost window
2659        in the x-order and send the expected WM_WINDOWPOSCHANGING and
2660        WM_WINDOWPOSCHANGED notification messages.
2661     */
2662     SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2663                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2664     /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2665      * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2666 
2667     return old_parent;
2668 }
2669 
2670 
2671 /*******************************************************************
2672  *              IsChild (USER32.@)
2673  */
2674 BOOL WINAPI IsChild( HWND parent, HWND child )
2675 {
2676     HWND *list = list_window_parents( child );
2677     int i;
2678     BOOL ret;
2679 
2680     if (!list) return FALSE;
2681     parent = WIN_GetFullHandle( parent );
2682     for (i = 0; list[i]; i++) if (list[i] == parent) break;
2683     ret = list[i] && list[i+1];
2684     HeapFree( GetProcessHeap(), 0, list );
2685     return ret;
2686 }
2687 
2688 
2689 /***********************************************************************
2690  *              IsWindowVisible (USER32.@)
2691  */
2692 BOOL WINAPI IsWindowVisible( HWND hwnd )
2693 {
2694     HWND *list;
2695     BOOL retval = TRUE;
2696     int i;
2697 
2698     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2699     if (!(list = list_window_parents( hwnd ))) return TRUE;
2700     if (list[0] && list[1])  /* desktop window is considered always visible so we don't check it */
2701     {
2702         for (i = 0; list[i+1]; i++)
2703             if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2704         retval = !list[i+1];
2705     }
2706     HeapFree( GetProcessHeap(), 0, list );
2707     return retval;
2708 }
2709 
2710 
2711 /***********************************************************************
2712  *           WIN_IsWindowDrawable
2713  *
2714  * hwnd is drawable when it is visible, all parents are not
2715  * minimized, and it is itself not minimized unless we are
2716  * trying to draw its default class icon.
2717  */
2718 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2719 {
2720     HWND *list;
2721     BOOL retval = TRUE;
2722     int i;
2723     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2724 
2725     if (!(style & WS_VISIBLE)) return FALSE;
2726     if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON ))  return FALSE;
2727 
2728     if (!(list = list_window_parents( hwnd ))) return TRUE;
2729     if (list[0] && list[1])  /* desktop window is considered always visible so we don't check it */
2730     {
2731         for (i = 0; list[i+1]; i++)
2732             if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2733                 break;
2734         retval = !list[i+1];
2735     }
2736     HeapFree( GetProcessHeap(), 0, list );
2737     return retval;
2738 }
2739 
2740 
2741 /*******************************************************************
2742  *              GetTopWindow (USER32.@)
2743  */
2744 HWND WINAPI GetTopWindow( HWND hwnd )
2745 {
2746     if (!hwnd) hwnd = GetDesktopWindow();
2747     return GetWindow( hwnd, GW_CHILD );
2748 }
2749 
2750 
2751 /*******************************************************************
2752  *              GetWindow (USER32.@)
2753  */
2754 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2755 {
2756     HWND retval = 0;
2757 
2758     if (rel == GW_OWNER)  /* this one may be available locally */
2759     {
2760         WND *wndPtr = WIN_GetPtr( hwnd );
2761         if (!wndPtr)
2762         {
2763             SetLastError( ERROR_INVALID_HANDLE );
2764             return 0;
2765         }
2766         if (wndPtr == WND_DESKTOP) return 0;
2767         if (wndPtr != WND_OTHER_PROCESS)
2768         {
2769             retval = wndPtr->owner;
2770             WIN_ReleasePtr( wndPtr );
2771             return retval;
2772         }
2773         /* else fall through to server call */
2774     }
2775 
2776     SERVER_START_REQ( get_window_tree )
2777     {
2778         req->handle = hwnd;
2779         if (!wine_server_call_err( req ))
2780         {
2781             switch(rel)
2782             {
2783             case GW_HWNDFIRST:
2784                 retval = reply->first_sibling;
2785                 break;
2786             case GW_HWNDLAST:
2787                 retval = reply->last_sibling;
2788                 break;
2789             case GW_HWNDNEXT:
2790                 retval = reply->next_sibling;
2791                 break;
2792             case GW_HWNDPREV:
2793                 retval = reply->prev_sibling;
2794                 break;
2795             case GW_OWNER:
2796                 retval = reply->owner;
2797                 break;
2798             case GW_CHILD:
2799                 retval = reply->first_child;
2800                 break;
2801             }
2802         }
2803     }
2804     SERVER_END_REQ;
2805     return retval;
2806 }
2807 
2808 
2809 /*******************************************************************
2810  *              ShowOwnedPopups (USER32.@)
2811  */
2812 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2813 {
2814     int count = 0;
2815     WND *pWnd;
2816     HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2817 
2818     if (!win_array) return TRUE;
2819 
2820     while (win_array[count]) count++;
2821     while (--count >= 0)
2822     {
2823         if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2824         if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2825         if (pWnd == WND_OTHER_PROCESS) continue;
2826         if (fShow)
2827         {
2828             if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2829             {
2830                 WIN_ReleasePtr( pWnd );
2831                 /* In Windows, ShowOwnedPopups(TRUE) generates
2832                  * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2833                  * regardless of the state of the owner
2834                  */
2835                 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2836                 continue;
2837             }
2838         }
2839         else
2840         {
2841             if (pWnd->dwStyle & WS_VISIBLE)
2842             {
2843                 WIN_ReleasePtr( pWnd );
2844                 /* In Windows, ShowOwnedPopups(FALSE) generates
2845                  * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2846                  * regardless of the state of the owner
2847                  */
2848                 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2849                 continue;
2850             }
2851         }
2852         WIN_ReleasePtr( pWnd );
2853     }
2854     HeapFree( GetProcessHeap(), 0, win_array );
2855     return TRUE;
2856 }
2857 
2858 
2859 /*******************************************************************
2860  *              GetLastActivePopup (USER32.@)
2861  */
2862 HWND WINAPI GetLastActivePopup( HWND hwnd )
2863 {
2864     HWND retval = hwnd;
2865 
2866     SERVER_START_REQ( get_window_info )
2867     {
2868         req->handle = hwnd;
2869         if (!wine_server_call_err( req )) retval = reply->last_active;
2870     }
2871     SERVER_END_REQ;
2872     return retval;
2873 }
2874 
2875 
2876 /*******************************************************************
2877  *           WIN_ListChildren
2878  *
2879  * Build an array of the children of a given window. The array must be
2880  * freed with HeapFree. Returns NULL when no windows are found.
2881  */
2882 HWND *WIN_ListChildren( HWND hwnd )
2883 {
2884     return list_window_children( 0, hwnd, NULL, 0 );
2885 }
2886 
2887 
2888 /*******************************************************************
2889  *              EnumWindows (USER32.@)
2890  */
2891 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2892 {
2893     HWND *list;
2894     BOOL ret = TRUE;
2895     int i;
2896 
2897     USER_CheckNotLock();
2898 
2899     /* We have to build a list of all windows first, to avoid */
2900     /* unpleasant side-effects, for instance if the callback */
2901     /* function changes the Z-order of the windows.          */
2902 
2903     if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2904 
2905     /* Now call the callback function for every window */
2906 
2907     for (i = 0; list[i]; i++)
2908     {
2909         /* Make sure that the window still exists */
2910         if (!IsWindow( list[i] )) continue;
2911         if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2912     }
2913     HeapFree( GetProcessHeap(), 0, list );
2914     return ret;
2915 }
2916 
2917 
2918 /**********************************************************************
2919  *              EnumThreadWindows (USER32.@)
2920  */
2921 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2922 {
2923     HWND *list;
2924     int i;
2925 
2926     USER_CheckNotLock();
2927 
2928     if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
2929 
2930     /* Now call the callback function for every window */
2931 
2932     for (i = 0; list[i]; i++)
2933         if (!func( list[i], lParam )) break;
2934     HeapFree( GetProcessHeap(), 0, list );
2935     return TRUE;
2936 }
2937 
2938 
2939 /***********************************************************************
2940  *              EnumDesktopWindows   (USER32.@)
2941  */
2942 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
2943 {
2944     HWND *list;
2945     int i;
2946 
2947     USER_CheckNotLock();
2948 
2949     if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
2950 
2951     for (i = 0; list[i]; i++)
2952         if (!func( list[i], lparam )) break;
2953     HeapFree( GetProcessHeap(), 0, list );
2954     return TRUE;
2955 }
2956 
2957 
2958 /**********************************************************************
2959  *           WIN_EnumChildWindows
2960  *
2961  * Helper function for EnumChildWindows().
2962  */
2963 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2964 {
2965     HWND *childList;
2966     BOOL ret = FALSE;
2967 
2968     for ( ; *list; list++)
2969     {
2970         /* Make sure that the window still exists */
2971         if (!IsWindow( *list )) continue;
2972         /* Build children list first */
2973         childList = WIN_ListChildren( *list );
2974 
2975         ret = func( *list, lParam );
2976 
2977         if (childList)
2978         {
2979             if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2980             HeapFree( GetProcessHeap(), 0, childList );
2981         }
2982         if (!ret) return FALSE;
2983     }
2984     return TRUE;
2985 }
2986 
2987 
2988 /**********************************************************************
2989  *              EnumChildWindows (USER32.@)
2990  */
2991 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2992 {
2993     HWND *list;
2994     BOOL ret;
2995 
2996     USER_CheckNotLock();
2997 
2998     if (!(list = WIN_ListChildren( parent ))) return FALSE;
2999     ret = WIN_EnumChildWindows( list, func, lParam );
3000     HeapFree( GetProcessHeap(), 0, list );
3001     return ret;
3002 }
3003 
3004 
3005 /*******************************************************************
3006  *              AnyPopup (USER.52)
3007  */
3008 BOOL16 WINAPI AnyPopup16(void)
3009 {
3010     return AnyPopup();
3011 }
3012 
3013 
3014 /*******************************************************************
3015  *              AnyPopup (USER32.@)
3016  */
3017 BOOL WINAPI AnyPopup(void)
3018 {
3019     int i;
3020     BOOL retvalue;
3021     HWND *list = WIN_ListChildren( GetDesktopWindow() );
3022 
3023     if (!list) return FALSE;
3024     for (i = 0; list[i]; i++)
3025     {
3026         if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3027     }
3028     retvalue = (list[i] != 0);
3029     HeapFree( GetProcessHeap(), 0, list );
3030     return retvalue;
3031 }
3032 
3033 
3034 /*******************************************************************
3035  *              FlashWindow (USER32.@)
3036  */
3037 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3038 {
3039     WND *wndPtr;
3040 
3041     TRACE("%p\n", hWnd);
3042 
3043     if (IsIconic( hWnd ))
3044     {
3045         RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3046 
3047         wndPtr = WIN_GetPtr(hWnd);
3048         if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3049         if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3050         {
3051             wndPtr->flags |= WIN_NCACTIVATED;
3052         }
3053         else
3054         {
3055             wndPtr->flags &= ~WIN_NCACTIVATED;
3056         }
3057         WIN_ReleasePtr( wndPtr );
3058         return TRUE;
3059     }
3060     else
3061     {
3062         WPARAM wparam;
3063 
3064         wndPtr = WIN_GetPtr(hWnd);
3065         if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3066         hWnd = wndPtr->hwndSelf;  /* make it a full handle */
3067 
3068         if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3069         else wparam = (hWnd == GetForegroundWindow());
3070 
3071         WIN_ReleasePtr( wndPtr );
3072         SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3073         return wparam;
3074     }
3075 }
3076 
3077 /*******************************************************************
3078  *              FlashWindowEx (USER32.@)
3079  */
3080 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3081 {
3082     FIXME("%p\n", pfwi);
3083     return TRUE;
3084 }
3085 
3086 /*******************************************************************
3087  *              GetWindowContextHelpId (USER32.@)
3088  */
3089 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3090 {
3091     DWORD retval;
3092     WND *wnd = WIN_GetPtr( hwnd );
3093     if (!wnd || wnd == WND_DESKTOP) return 0;
3094     if (wnd == WND_OTHER_PROCESS)
3095     {
3096         if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3097         return 0;
3098     }
3099     retval = wnd->helpContext;
3100     WIN_ReleasePtr( wnd );
3101     return retval;
3102 }
3103 
3104 
3105 /*******************************************************************
3106  *              SetWindowContextHelpId (USER32.@)
3107  */
3108 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3109 {
3110     WND *wnd = WIN_GetPtr( hwnd );
3111     if (!wnd || wnd == WND_DESKTOP) return FALSE;
3112     if (wnd == WND_OTHER_PROCESS)
3113     {
3114         if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3115         return 0;
3116     }
3117     wnd->helpContext = id;
3118     WIN_ReleasePtr( wnd );
3119     return TRUE;
3120 }
3121 
3122 
3123 /*******************************************************************
3124  *              DragDetect (USER32.@)
3125  */
3126 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3127 {
3128     MSG msg;
3129     RECT rect;
3130     WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3131     WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3132 
3133     rect.left = pt.x - wDragWidth;
3134     rect.right = pt.x + wDragWidth;
3135 
3136     rect.top = pt.y - wDragHeight;
3137     rect.bottom = pt.y + wDragHeight;
3138 
3139     SetCapture(hWnd);
3140 
3141     while(1)
3142     {
3143         while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3144         {
3145             if( msg.message == WM_LBUTTONUP )
3146             {
3147                 ReleaseCapture();
3148                 return 0;
3149             }
3150             if( msg.message == WM_MOUSEMOVE )
3151             {
3152                 POINT tmp;
3153                 tmp.x = (short)LOWORD(msg.lParam);
3154                 tmp.y = (short)HIWORD(msg.lParam);
3155                 if( !PtInRect( &rect, tmp ))
3156                 {
3157                     ReleaseCapture();
3158                     return 1;
3159                 }
3160             }
3161         }
3162         WaitMessage();
3163     }
3164     return 0;
3165 }
3166 
3167 /******************************************************************************
3168  *              GetWindowModuleFileNameA (USER32.@)
3169  */
3170 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3171 {
3172     WND *win;
3173     HINSTANCE hinst;
3174 
3175     TRACE( "%p, %p, %u\n", hwnd, module, size );
3176 
3177     win = WIN_GetPtr( hwnd );
3178     if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3179     {
3180         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3181         return 0;
3182     }
3183     hinst = win->hInstance;
3184     WIN_ReleasePtr( win );
3185 
3186     return GetModuleFileNameA( hinst, module, size );
3187 }
3188 
3189 /******************************************************************************
3190  *              GetWindowModuleFileNameW (USER32.@)
3191  */
3192 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3193 {
3194     WND *win;
3195     HINSTANCE hinst;
3196 
3197     TRACE( "%p, %p, %u\n", hwnd, module, size );
3198 
3199     win = WIN_GetPtr( hwnd );
3200     if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3201     {
3202         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3203         return 0;
3204     }
3205     hinst = win->hInstance;
3206     WIN_ReleasePtr( win );
3207 
3208     return GetModuleFileNameW( hinst, module, size );
3209 }
3210 
3211 /******************************************************************************
3212  *              GetWindowInfo (USER32.@)
3213  *
3214  * Note: tests show that Windows doesn't check cbSize of the structure.
3215  */
3216 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3217 {
3218     if (!pwi) return FALSE;
3219     if (!IsWindow(hwnd)) return FALSE;
3220 
3221     GetWindowRect(hwnd, &pwi->rcWindow);
3222     GetClientRect(hwnd, &pwi->rcClient);
3223     /* translate to screen coordinates */
3224     MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3225 
3226     pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3227     pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3228     pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3229 
3230     pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3231     pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3232 
3233     pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3234     pwi->wCreatorVersion = 0x0400;
3235 
3236     return TRUE;
3237 }
3238 
3239 /******************************************************************************
3240  *              SwitchDesktop (USER32.@)
3241  *
3242  * NOTES: Sets the current input or interactive desktop.
3243  */
3244 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3245 {
3246     FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3247     return TRUE;
3248 }
3249 
3250 /*****************************************************************************
3251  *              SetLayeredWindowAttributes (USER32.@)
3252  */
3253 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey, 
3254                                         BYTE bAlpha, DWORD dwFlags )
3255 {
3256     FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3257     return TRUE;
3258 }
3259 
3260 /*****************************************************************************
3261  *              GetLayeredWindowAttributes (USER32.@)
3262  */
3263 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3264                                         BYTE *pbAlpha, DWORD *pdwFlags )
3265 {
3266     FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3267     return FALSE;
3268 }
3269 
3270 /*****************************************************************************
3271  *              UpdateLayeredWindow (USER32.@)
3272  */
3273 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3274                                  HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3275                                  DWORD dwFlags)
3276 {
3277     static int once;
3278     if (!once)
3279     {
3280         once = 1;
3281         FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3282               hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3283     }
3284     return 0;
3285 }
3286 
3287 /* 64bit versions */
3288 
3289 #ifdef GetWindowLongPtrW
3290 #undef GetWindowLongPtrW
3291 #endif
3292 
3293 #ifdef GetWindowLongPtrA
3294 #undef GetWindowLongPtrA
3295 #endif
3296 
3297 #ifdef SetWindowLongPtrW
3298 #undef SetWindowLongPtrW
3299 #endif
3300 
3301 #ifdef SetWindowLongPtrA
3302 #undef SetWindowLongPtrA
3303 #endif
3304 
3305 /*****************************************************************************
3306  *              GetWindowLongPtrW (USER32.@)
3307  */
3308 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3309 {
3310     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3311 }
3312 
3313 /*****************************************************************************
3314  *              GetWindowLongPtrA (USER32.@)
3315  */
3316 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3317 {
3318     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3319 }
3320 
3321 /*****************************************************************************
3322  *              SetWindowLongPtrW (USER32.@)
3323  */
3324 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3325 {
3326     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3327 }
3328 
3329 /*****************************************************************************
3330  *              SetWindowLongPtrA (USER32.@)
3331  */
3332 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3333 {
3334     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );
3335 }
3336 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.