win.c 89.9 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 * Window related functions
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
4
 * Copyright 1993, 1994 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
19
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
20

21 22 23
#include "config.h"
#include "wine/port.h"

24
#include <assert.h>
25
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
26
#include <stdlib.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
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"
Alexandre Julliard's avatar
Alexandre Julliard committed
35
#include "win.h"
36
#include "user_private.h"
37
#include "controls.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
38
#include "winerror.h"
39
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
40

41
WINE_DEFAULT_DEBUG_CHANNEL(win);
42

43 44
#define NB_USER_HANDLES  ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
#define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
45

46 47
/**********************************************************************/

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/* helper for Get/SetWindowLong */
static inline LONG_PTR get_win_data( const void *ptr, UINT size )
{
    if (size == sizeof(WORD))
    {
        WORD ret;
        memcpy( &ret, ptr, sizeof(ret) );
        return ret;
    }
    else if (size == sizeof(DWORD))
    {
        DWORD ret;
        memcpy( &ret, ptr, sizeof(ret) );
        return ret;
    }
    else
    {
        LONG_PTR ret;
        memcpy( &ret, ptr, sizeof(ret) );
        return ret;
    }
}

/* helper for Get/SetWindowLong */
static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
{
    if (size == sizeof(WORD))
    {
        WORD newval = val;
        memcpy( ptr, &newval, sizeof(newval) );
    }
    else if (size == sizeof(DWORD))
    {
        DWORD newval = val;
        memcpy( ptr, &newval, sizeof(newval) );
    }
    else
    {
        memcpy( ptr, &val, sizeof(val) );
    }
}

Alexandre Julliard's avatar
Alexandre Julliard committed
90

91
static void *user_handles[NB_USER_HANDLES];
92 93 94 95 96 97

/***********************************************************************
 *           create_window_handle
 *
 * Create a window handle with the server.
 */
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 109 110
    /* if 16-bit instance, map to module handle */
    if (instance && !HIWORD(instance))
        instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
111

112
    SERVER_START_REQ( create_window )
113
    {
114 115 116
        req->parent   = parent;
        req->owner    = owner;
        req->instance = instance;
117 118
        if (!(req->atom = get_int_atom_value( name )) && name)
            wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
119 120 121
        if (!wine_server_call_err( req ))
        {
            handle = reply->handle;
122 123
            full_parent = reply->parent;
            full_owner  = reply->owner;
124 125 126
            extra_bytes = reply->extra;
            class = reply->class_ptr;
        }
127
    }
128
    SERVER_END_REQ;
129

130 131
    if (!handle)
    {
132
        WARN( "error %d creating window\n", GetLastError() );
133 134 135 136
        return NULL;
    }

    if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
137
    {
138 139 140 141 142 143 144
        SERVER_START_REQ( destroy_window )
        {
            req->handle = handle;
            wine_server_call( req );
        }
        SERVER_END_REQ;
        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
145 146
        return NULL;
    }
147

148 149 150 151
    if (!parent)  /* if parent is 0 we don't have a desktop window yet */
    {
        struct user_thread_info *thread_info = get_user_thread_info();

152 153
        if (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle;
        else assert( full_parent == thread_info->desktop );
154 155 156 157
        if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
            ERR( "failed to create desktop window\n" );
    }

158 159
    USER_Lock();

160
    index = USER_HANDLE_TO_INDEX(handle);
161 162
    assert( index < NB_USER_HANDLES );
    user_handles[index] = win;
163
    win->hwndSelf   = handle;
164 165
    win->parent     = full_parent;
    win->owner      = full_owner;
166
    win->dwMagic    = WND_MAGIC;
167
    win->flags      = 0;
168 169
    win->cbWndExtra = extra_bytes;
    memset( win->wExtra, 0, extra_bytes );
170
    CLASS_AddWindow( class, win, unicode );
171 172 173 174 175 176 177 178 179 180 181 182
    return win;
}


/***********************************************************************
 *           free_window_handle
 *
 * Free a window handle.
 */
static WND *free_window_handle( HWND hwnd )
{
    WND *ptr;
183
    WORD index = USER_HANDLE_TO_INDEX(hwnd);
184

185
    if (index >= NB_USER_HANDLES) return NULL;
186
    USER_Lock();
187
    if ((ptr = user_handles[index]))
188 189 190 191
    {
        SERVER_START_REQ( destroy_window )
        {
            req->handle = hwnd;
192
            if (!wine_server_call_err( req ))
193
            {
194
                user_handles[index] = NULL;
195 196
                ptr->dwMagic = 0;
            }
197 198 199 200 201 202
            else
                ptr = NULL;
        }
        SERVER_END_REQ;
    }
    USER_Unlock();
203
    HeapFree( GetProcessHeap(), 0, ptr );
204 205 206 207
    return ptr;
}


208 209 210 211 212 213
/*******************************************************************
 *           list_window_children
 *
 * Build an array of the children of a given window. The array must be
 * freed with HeapFree. Returns NULL when no windows are found.
 */
214
static HWND *list_window_children( HWND hwnd, LPCWSTR class, DWORD tid )
215
{
216 217
    HWND *list;
    int size = 32;
218

219
    for (;;)
220
    {
221 222 223 224 225
        int count = 0;

        if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;

        SERVER_START_REQ( get_window_children )
226
        {
227
            req->parent = hwnd;
228
            req->tid = tid;
229 230
            if (!(req->atom = get_int_atom_value( class )) && class)
                wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
231 232
            wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
            if (!wine_server_call( req )) count = reply->count;
233
        }
234 235 236 237 238 239 240 241 242
        SERVER_END_REQ;
        if (count && count < size)
        {
            list[count] = 0;
            return list;
        }
        HeapFree( GetProcessHeap(), 0, list );
        if (!count) break;
        size = count + 1;  /* restart with a large enough buffer */
243
    }
244
    return NULL;
245 246 247
}


248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
/*******************************************************************
 *           list_window_parents
 *
 * Build an array of all parents of a given window, starting with
 * the immediate parent. The array must be freed with HeapFree.
 */
static HWND *list_window_parents( HWND hwnd )
{
    WND *win;
    HWND current, *list;
    int pos = 0, size = 16, count = 0;

    if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;

    current = hwnd;
    for (;;)
    {
        if (!(win = WIN_GetPtr( current ))) goto empty;
        if (win == WND_OTHER_PROCESS) break;  /* need to do it the hard way */
267
        if (win == WND_DESKTOP)
268 269
        {
            if (!pos) goto empty;
270
            list[pos] = 0;
271 272
            return list;
        }
273 274
        list[pos] = current = win->parent;
        WIN_ReleasePtr( win );
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
        if (++pos == size - 1)
        {
            /* need to grow the list */
            HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
            if (!new_list) goto empty;
            list = new_list;
            size += 16;
        }
    }

    /* at least one parent belongs to another process, have to query the server */

    for (;;)
    {
        count = 0;
        SERVER_START_REQ( get_window_parents )
        {
            req->handle = hwnd;
            wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
            if (!wine_server_call( req )) count = reply->count;
        }
        SERVER_END_REQ;
        if (!count) goto empty;
        if (size > count)
        {
            list[count] = 0;
            return list;
        }
        HeapFree( GetProcessHeap(), 0, list );
        size = count + 1;
        if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
    }

 empty:
    HeapFree( GetProcessHeap(), 0, list );
    return NULL;
}


314 315 316 317 318
/*******************************************************************
 *           send_parent_notify
 */
static void send_parent_notify( HWND hwnd, UINT msg )
{
319 320
    if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
        !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
321 322 323 324 325 326
    {
        HWND parent = GetParent(hwnd);
        if (parent && parent != GetDesktopWindow())
            SendMessageW( parent, WM_PARENTNOTIFY,
                          MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
    }
327 328 329
}


330 331 332 333 334 335 336
/*******************************************************************
 *		get_server_window_text
 *
 * Retrieve the window text from the server.
 */
static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
{
337 338 339
    size_t len = 0;

    SERVER_START_REQ( get_window_text )
340 341
    {
        req->handle = hwnd;
342 343
        wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
        if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
344
    }
345
    SERVER_END_REQ;
346 347 348 349
    text[len / sizeof(WCHAR)] = 0;
}


350
/***********************************************************************
351
 *           WIN_GetPtr
352
 *
353
 * Return a pointer to the WND structure if local to the process,
Andreas Mohr's avatar
Andreas Mohr committed
354
 * or WND_OTHER_PROCESS if handle may be valid in other process.
355
 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
356
 */
357
WND *WIN_GetPtr( HWND hwnd )
358
{
359
    WND * ptr;
360
    WORD index = USER_HANDLE_TO_INDEX(hwnd);
361

362
    if (index >= NB_USER_HANDLES) return NULL;
363 364

    USER_Lock();
365
    if ((ptr = user_handles[index]))
366
    {
367 368
        if (ptr->dwMagic == WND_MAGIC &&
            (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
369
            return ptr;
370
        ptr = NULL;
371
    }
372
    else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
373
    {
374
        if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
375 376
        else ptr = NULL;
    }
377
    else ptr = WND_OTHER_PROCESS;
378
    USER_Unlock();
379 380 381 382 383 384 385
    return ptr;
}


/***********************************************************************
 *           WIN_IsCurrentProcess
 *
386
 * Check whether a given window belongs to the current process (and return the full handle).
387
 */
388
HWND WIN_IsCurrentProcess( HWND hwnd )
389 390
{
    WND *ptr;
391
    HWND ret;
392

393
    if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
394 395 396
    ret = ptr->hwndSelf;
    WIN_ReleasePtr( ptr );
    return ret;
397 398 399 400 401 402
}


/***********************************************************************
 *           WIN_IsCurrentThread
 *
403
 * Check whether a given window belongs to the current thread (and return the full handle).
404
 */
405
HWND WIN_IsCurrentThread( HWND hwnd )
406 407
{
    WND *ptr;
408
    HWND ret = 0;
409

410 411 412
    if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
    if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
    WIN_ReleasePtr( ptr );
413
    return ret;
414 415 416 417 418 419 420 421 422 423 424
}


/***********************************************************************
 *           WIN_Handle32
 *
 * Convert a 16-bit window handle to a full 32-bit handle.
 */
HWND WIN_Handle32( HWND16 hwnd16 )
{
    WND *ptr;
425
    HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
426

427 428 429
    if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
    /* do sign extension for -2 and -3 */
    if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
430

431 432
    if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;

433 434
    if (ptr == WND_DESKTOP) return GetDesktopWindow();

435
    if (ptr != WND_OTHER_PROCESS)
436
    {
437 438
        hwnd = ptr->hwndSelf;
        WIN_ReleasePtr( ptr );
439 440
    }
    else  /* may belong to another process */
441 442 443
    {
        SERVER_START_REQ( get_window_info )
        {
444
            req->handle = hwnd;
445
            if (!wine_server_call_err( req )) hwnd = reply->full_handle;
446 447 448 449 450 451 452
        }
        SERVER_END_REQ;
    }
    return hwnd;
}


453 454 455 456 457
/***********************************************************************
 *           WIN_SetOwner
 *
 * Change the owner of a window.
 */
458
HWND WIN_SetOwner( HWND hwnd, HWND owner )
459
{
460
    WND *win = WIN_GetPtr( hwnd );
461
    HWND ret = 0;
462

463
    if (!win || win == WND_DESKTOP) return 0;
464
    if (win == WND_OTHER_PROCESS)
Alexandre Julliard's avatar
Alexandre Julliard committed
465
    {
466
        if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
467
        return 0;
468
    }
469 470 471 472
    SERVER_START_REQ( set_window_owner )
    {
        req->handle = hwnd;
        req->owner  = owner;
473 474 475 476 477
        if (!wine_server_call( req ))
        {
            win->owner = reply->full_owner;
            ret = reply->prev_owner;
        }
478 479 480
    }
    SERVER_END_REQ;
    WIN_ReleasePtr( win );
481
    return ret;
482 483 484 485 486 487 488 489
}


/***********************************************************************
 *           WIN_SetStyle
 *
 * Change the style of a window.
 */
490
ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
491 492
{
    BOOL ok;
493
    ULONG new_style, old_style = 0;
494 495
    WND *win = WIN_GetPtr( hwnd );

496
    if (!win || win == WND_DESKTOP) return 0;
497 498 499
    if (win == WND_OTHER_PROCESS)
    {
        if (IsWindow(hwnd))
500
            ERR( "cannot set style %x/%x on other process window %p\n",
501
                 set_bits, clear_bits, hwnd );
502 503
        return 0;
    }
504 505
    new_style = (win->dwStyle | set_bits) & ~clear_bits;
    if (new_style == win->dwStyle)
506 507
    {
        WIN_ReleasePtr( win );
508
        return new_style;
509 510 511 512 513
    }
    SERVER_START_REQ( set_window_info )
    {
        req->handle = hwnd;
        req->flags  = SET_WIN_STYLE;
514
        req->style  = new_style;
515
        req->extra_offset = -1;
516
        if ((ok = !wine_server_call( req )))
517
        {
518 519
            old_style = reply->old_style;
            win->dwStyle = new_style;
520 521 522 523
        }
    }
    SERVER_END_REQ;
    WIN_ReleasePtr( win );
524
    if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
525
    return old_style;
526 527 528
}


529 530 531 532 533 534 535 536 537 538 539
/***********************************************************************
 *           WIN_GetRectangles
 *
 * Get the window and client rectangles.
 */
BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
{
    WND *win = WIN_GetPtr( hwnd );
    BOOL ret = TRUE;

    if (!win) return FALSE;
540 541 542 543 544 545 546 547 548 549
    if (win == WND_DESKTOP)
    {
        RECT rect;
        rect.left = rect.top = 0;
        rect.right  = GetSystemMetrics(SM_CXSCREEN);
        rect.bottom = GetSystemMetrics(SM_CYSCREEN);
        if (rectWindow) *rectWindow = rect;
        if (rectClient) *rectClient = rect;
    }
    else if (win == WND_OTHER_PROCESS)
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
    {
        SERVER_START_REQ( get_window_rectangles )
        {
            req->handle = hwnd;
            if ((ret = !wine_server_call( req )))
            {
                if (rectWindow)
                {
                    rectWindow->left   = reply->window.left;
                    rectWindow->top    = reply->window.top;
                    rectWindow->right  = reply->window.right;
                    rectWindow->bottom = reply->window.bottom;
                }
                if (rectClient)
                {
                    rectClient->left   = reply->client.left;
                    rectClient->top    = reply->client.top;
                    rectClient->right  = reply->client.right;
                    rectClient->bottom = reply->client.bottom;
                }
            }
        }
        SERVER_END_REQ;
    }
    else
    {
        if (rectWindow) *rectWindow = win->rectWindow;
        if (rectClient) *rectClient = win->rectClient;
        WIN_ReleasePtr( win );
    }
    return ret;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
584 585 586
/***********************************************************************
 *           WIN_DestroyWindow
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
587
 * Destroy storage associated to a window. "Internals" p.358
Alexandre Julliard's avatar
Alexandre Julliard committed
588
 */
589
LRESULT WIN_DestroyWindow( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
590
{
591 592
    WND *wndPtr;
    HWND *list;
593
    HMENU menu = 0, sys_menu;
Alexandre Julliard's avatar
Alexandre Julliard committed
594

595
    TRACE("%p\n", hwnd );
Alexandre Julliard's avatar
Alexandre Julliard committed
596

Alexandre Julliard's avatar
Alexandre Julliard committed
597
    /* free child windows */
598
    if ((list = WIN_ListChildren( hwnd )))
599
    {
600
        int i;
601 602 603 604 605
        for (i = 0; list[i]; i++)
        {
            if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
            else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
        }
606
        HeapFree( GetProcessHeap(), 0, list );
607
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
608

609
    /* Unlink now so we won't bother with the children later on */
610 611 612 613 614 615 616
    SERVER_START_REQ( set_parent )
    {
        req->handle = hwnd;
        req->parent = 0;
        wine_server_call( req );
    }
    SERVER_END_REQ;
617

618 619 620
    /*
     * Send the WM_NCDESTROY to the window being destroyed.
     */
621
    SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
622 623 624

    /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */

625
    WINPOS_CheckInternalPos( hwnd );
Alexandre Julliard's avatar
Alexandre Julliard committed
626 627 628

    /* free resources associated with the window */

629
    if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
630 631
    if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
        menu = (HMENU)wndPtr->wIDmenu;
632 633 634 635 636
    sys_menu = wndPtr->hSysMenu;
    WIN_ReleasePtr( wndPtr );

    if (menu) DestroyMenu( menu );
    if (sys_menu) DestroyMenu( sys_menu );
Alexandre Julliard's avatar
Alexandre Julliard committed
637

638
    USER_Driver->pDestroyWindow( hwnd );
639 640

    free_window_handle( hwnd );
641
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
642 643
}

Alexandre Julliard's avatar
Alexandre Julliard committed
644
/***********************************************************************
645
 *           WIN_DestroyThreadWindows
Alexandre Julliard's avatar
Alexandre Julliard committed
646
 *
647
 * Destroy all children of 'wnd' owned by the current thread.
Alexandre Julliard's avatar
Alexandre Julliard committed
648
 */
649
void WIN_DestroyThreadWindows( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
650
{
651 652
    HWND *list;
    int i;
Alexandre Julliard's avatar
Alexandre Julliard committed
653

654
    if (!(list = WIN_ListChildren( hwnd ))) return;
655
    for (i = 0; list[i]; i++)
Alexandre Julliard's avatar
Alexandre Julliard committed
656
    {
657
        if (WIN_IsCurrentThread( list[i] ))
658 659 660
            DestroyWindow( list[i] );
        else
            WIN_DestroyThreadWindows( list[i] );
Alexandre Julliard's avatar
Alexandre Julliard committed
661
    }
662
    HeapFree( GetProcessHeap(), 0, list );
Alexandre Julliard's avatar
Alexandre Julliard committed
663 664
}

Alexandre Julliard's avatar
Alexandre Julliard committed
665

666
/***********************************************************************
667
 *           WIN_FixCoordinates
668 669 670 671 672 673
 *
 * Fix the coordinates - Helper for WIN_CreateWindowEx.
 * returns default show mode in sw.
 */
static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
{
674
#define IS_DEFAULT(x)  ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
675 676 677 678 679 680 681
    POINT pos[2];

    if (cs->dwExStyle & WS_EX_MDICHILD)
    {
        UINT id = 0;

        MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
682
        if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
683 684 685 686

        TRACE("MDI child id %04x\n", id);
    }

687
    if (cs->style & (WS_CHILD | WS_POPUP))
688
    {
689
        if (cs->dwExStyle & WS_EX_MDICHILD)
690
        {
691
            if (IS_DEFAULT(cs->x))
692
            {
693 694
                cs->x = pos[0].x;
                cs->y = pos[0].y;
695
            }
696 697
            if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
            if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
698
        }
699
        else
700
        {
701 702 703 704 705 706 707 708 709
            if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
            if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
        }
    }
    else  /* overlapped window */
    {
        HMONITOR monitor;
        MONITORINFO mon_info;
        STARTUPINFOW info;
710

711
        if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
712

713
        monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
714 715 716 717 718 719 720 721 722 723
        mon_info.cbSize = sizeof(mon_info);
        GetMonitorInfoW( monitor, &mon_info );
        GetStartupInfoW( &info );

        if (IS_DEFAULT(cs->x))
        {
            if (!IS_DEFAULT(cs->y)) *sw = cs->y;
            cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
            cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
        }
724

725 726 727
        if (IS_DEFAULT(cs->cx))
        {
            if (info.dwFlags & STARTF_USESIZE)
728
            {
729 730
                cs->cx = info.dwXSize;
                cs->cy = info.dwYSize;
731
            }
732
            else
733
            {
734 735
                cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
                cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
736
            }
737
        }
738 739 740 741
        /* neither x nor cx are default. Check the y values .
         * In the trace we see Outlook and Outlook Express using
         * cy set to CW_USEDEFAULT when opening the address book.
         */
742 743
        else if (IS_DEFAULT(cs->cy))
        {
744
            FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
745
            cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
746
        }
747
    }
748
#undef IS_DEFAULT
749 750
}

751 752 753 754 755 756
/***********************************************************************
 *           dump_window_styles
 */
static void dump_window_styles( DWORD style, DWORD exstyle )
{
    TRACE( "style:" );
757 758 759 760 761 762 763 764 765
    if(style & WS_POPUP) TRACE(" WS_POPUP");
    if(style & WS_CHILD) TRACE(" WS_CHILD");
    if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
    if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
    if(style & WS_DISABLED) TRACE(" WS_DISABLED");
    if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
    if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
    if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
    if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
766 767
    else
    {
768 769
        if(style & WS_BORDER) TRACE(" WS_BORDER");
        if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
770
    }
771 772 773 774
    if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
    if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
    if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
    if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
775 776 777 778 779 780 781 782 783 784
    if (style & WS_CHILD)
    {
        if(style & WS_GROUP) TRACE(" WS_GROUP");
        if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
    }
    else
    {
        if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
        if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
    }
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806

    /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
#define DUMPED_STYLES \
    (WS_POPUP | \
     WS_CHILD | \
     WS_MINIMIZE | \
     WS_VISIBLE | \
     WS_DISABLED | \
     WS_CLIPSIBLINGS | \
     WS_CLIPCHILDREN | \
     WS_MAXIMIZE | \
     WS_BORDER | \
     WS_DLGFRAME | \
     WS_VSCROLL | \
     WS_HSCROLL | \
     WS_SYSMENU | \
     WS_THICKFRAME | \
     WS_GROUP | \
     WS_TABSTOP | \
     WS_MINIMIZEBOX | \
     WS_MAXIMIZEBOX)

807 808
    if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
    TRACE("\n");
809 810 811
#undef DUMPED_STYLES

    TRACE( "exstyle:" );
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
    if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
    if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
    if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
    if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
    if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
    if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
    if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
    if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
    if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
    if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
    if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
    if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
    if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
    if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
    if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
    if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
    if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
    if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850

#define DUMPED_EX_STYLES \
    (WS_EX_DLGMODALFRAME | \
     WS_EX_DRAGDETECT | \
     WS_EX_NOPARENTNOTIFY | \
     WS_EX_TOPMOST | \
     WS_EX_ACCEPTFILES | \
     WS_EX_TRANSPARENT | \
     WS_EX_MDICHILD | \
     WS_EX_TOOLWINDOW | \
     WS_EX_WINDOWEDGE | \
     WS_EX_CLIENTEDGE | \
     WS_EX_CONTEXTHELP | \
     WS_EX_RIGHT | \
     WS_EX_RTLREADING | \
     WS_EX_LEFTSCROLLBAR | \
     WS_EX_CONTROLPARENT | \
     WS_EX_STATICEDGE | \
     WS_EX_APPWINDOW | \
     WS_EX_LAYERED)

851 852
    if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
    TRACE("\n");
853 854 855 856
#undef DUMPED_EX_STYLES
}


Alexandre Julliard's avatar
Alexandre Julliard committed
857
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
858 859 860
 *           WIN_CreateWindowEx
 *
 * Implementation of CreateWindowEx().
Alexandre Julliard's avatar
Alexandre Julliard committed
861
 */
862
static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
Alexandre Julliard's avatar
Alexandre Julliard committed
863
{
864
    INT sw = SW_SHOW;
Alexandre Julliard's avatar
Alexandre Julliard committed
865
    WND *wndPtr;
866
    HWND hwnd, parent, owner, top_child = 0;
867
    BOOL unicode = (flags & WIN_ISUNICODE) != 0;
868
    MDICREATESTRUCTA mdi_cs;
Alexandre Julliard's avatar
Alexandre Julliard committed
869

870
    TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
871
          unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
872
          debugstr_w(className),
Alexandre Julliard's avatar
Alexandre Julliard committed
873 874
          cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
          cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
875 876
    if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );

877 878 879 880 881 882
    /* Fix the styles for MDI children */
    if (cs->dwExStyle & WS_EX_MDICHILD)
    {
        UINT flags = 0;

        wndPtr = WIN_GetPtr(cs->hwndParent);
883
        if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
        {
            flags = wndPtr->flags;
            WIN_ReleasePtr(wndPtr);
        }

        if (!(flags & WIN_ISMDICLIENT))
        {
            WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
            return 0;
        }

        /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
         * MDICREATESTRUCT members have the originally passed values.
         *
         * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
         * have the same layout.
         */
        mdi_cs.szClass = cs->lpszClass;
        mdi_cs.szTitle = cs->lpszName;
        mdi_cs.hOwner = cs->hInstance;
        mdi_cs.x = cs->x;
        mdi_cs.y = cs->y;
        mdi_cs.cx = cs->cx;
        mdi_cs.cy = cs->cy;
        mdi_cs.style = cs->style;
        mdi_cs.lParam = (LPARAM)cs->lpCreateParams;

        cs->lpCreateParams = (LPVOID)&mdi_cs;

        if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
        {
            if (cs->style & WS_POPUP)
            {
                TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
                return 0;
            }
            cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
        }
        else
        {
            cs->style &= ~WS_POPUP;
            cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
                WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
        }

        top_child = GetWindow(cs->hwndParent, GW_CHILD);
930 931 932 933 934 935 936 937

        if (top_child)
        {
            /* Restore current maximized child */
            if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
            {
                TRACE("Restoring current maximized child %p\n", top_child);
                SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
938
                ShowWindow( top_child, SW_SHOWNORMAL );
939 940 941
                SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
            }
        }
942 943
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
944
    /* Find the parent window */
Alexandre Julliard's avatar
Alexandre Julliard committed
945

946
    parent = cs->hwndParent;
947
    owner = 0;
948 949 950 951 952 953 954

    if (cs->hwndParent == HWND_MESSAGE)
    {
      /* native ole32.OleInitialize uses HWND_MESSAGE to create the
       * message window (style: WS_POPUP|WS_DISABLED)
       */
      FIXME("Parent is HWND_MESSAGE\n");
955
      parent = GetDesktopWindow();
956 957
    }
    else if (cs->hwndParent)
Alexandre Julliard's avatar
Alexandre Julliard committed
958
    {
959
        if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
Alexandre Julliard's avatar
Alexandre Julliard committed
960
        {
961 962 963
            parent = GetDesktopWindow();
            owner = cs->hwndParent;
        }
964
    }
965
    else
966
    {
967 968 969
        if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
        {
            WARN("No parent for child window\n" );
970
            SetLastError(ERROR_TLW_WITH_WSCHILD);
971 972
            return 0;  /* WS_CHILD needs a parent, but WS_POPUP doesn't */
        }
973
        if (className != (LPCWSTR)DESKTOP_CLASS_ATOM)  /* are we creating the desktop itself? */
974
            parent = GetDesktopWindow();
Alexandre Julliard's avatar
Alexandre Julliard committed
975
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
976

977
    WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
Alexandre Julliard's avatar
Alexandre Julliard committed
978

979 980 981 982 983 984 985
    if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
        ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
          (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
        cs->dwExStyle |= WS_EX_WINDOWEDGE;
    else
        cs->dwExStyle &= ~WS_EX_WINDOWEDGE;

Alexandre Julliard's avatar
Alexandre Julliard committed
986
    /* Create the window structure */
Alexandre Julliard's avatar
Alexandre Julliard committed
987

988
    if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
989
        return 0;
990
    hwnd = wndPtr->hwndSelf;
Alexandre Julliard's avatar
Alexandre Julliard committed
991

Alexandre Julliard's avatar
Alexandre Julliard committed
992
    /* Fill the window structure */
Alexandre Julliard's avatar
Alexandre Julliard committed
993

994
    wndPtr->tid            = GetCurrentThreadId();
Alexandre Julliard's avatar
Alexandre Julliard committed
995
    wndPtr->hInstance      = cs->hInstance;
Alexandre Julliard's avatar
Alexandre Julliard committed
996
    wndPtr->text           = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
997 998
    wndPtr->dwStyle        = cs->style & ~WS_VISIBLE;
    wndPtr->dwExStyle      = cs->dwExStyle;
Alexandre Julliard's avatar
Alexandre Julliard committed
999
    wndPtr->wIDmenu        = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1000
    wndPtr->helpContext    = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1001 1002
    wndPtr->pVScroll       = NULL;
    wndPtr->pHScroll       = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
1003
    wndPtr->userdata       = 0;
1004 1005
    wndPtr->hIcon          = 0;
    wndPtr->hIconSmall     = 0;
1006
    wndPtr->hSysMenu       = 0;
1007
    wndPtr->flags         |= (flags & WIN_ISWIN32);
1008 1009

    if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
1010

1011 1012 1013 1014 1015 1016
    /*
     * Correct the window styles.
     *
     * It affects only the style loaded into the WIN structure.
     */

1017
    if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
    {
        wndPtr->dwStyle |= WS_CLIPSIBLINGS;
        if (!(wndPtr->dwStyle & WS_POPUP))
            wndPtr->dwStyle |= WS_CAPTION;
    }

    /*
     * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
     * why does the user get to set it?
     */

    if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
          (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
        wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
    else
        wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;

    if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1036
        wndPtr->flags |= WIN_NEED_SIZE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1037

1038 1039 1040
    SERVER_START_REQ( set_window_info )
    {
        req->handle    = hwnd;
1041
        req->flags     = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1042 1043 1044
        req->style     = wndPtr->dwStyle;
        req->ex_style  = wndPtr->dwExStyle;
        req->instance  = (void *)wndPtr->hInstance;
1045
        req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1046
        req->extra_offset = -1;
1047
        wine_server_call( req );
1048 1049
    }
    SERVER_END_REQ;
Alexandre Julliard's avatar
Alexandre Julliard committed
1050

Alexandre Julliard's avatar
Alexandre Julliard committed
1051 1052
    /* Set the window menu */

1053
    if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
Alexandre Julliard's avatar
Alexandre Julliard committed
1054
    {
1055 1056 1057 1058 1059 1060 1061 1062 1063
        if (cs->hMenu)
        {
            if (!MENU_SetMenu(hwnd, cs->hMenu))
            {
                WIN_ReleasePtr( wndPtr );
                free_window_handle( hwnd );
                return 0;
            }
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
1064 1065
        else
        {
1066
            LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
Alexandre Julliard's avatar
Alexandre Julliard committed
1067 1068
            if (menuName)
            {
1069
                if (!cs->hInstance || HIWORD(cs->hInstance))
1070
                    cs->hMenu = LoadMenuA(cs->hInstance,menuName);
Alexandre Julliard's avatar
Alexandre Julliard committed
1071
                else
1072
                    cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
Alexandre Julliard's avatar
Alexandre Julliard committed
1073

1074
                if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
Alexandre Julliard's avatar
Alexandre Julliard committed
1075
            }
Alexandre Julliard's avatar
Alexandre Julliard committed
1076
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
1077
    }
1078
    else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1079
    WIN_ReleasePtr( wndPtr );
Alexandre Julliard's avatar
Alexandre Julliard committed
1080

1081
    if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
Alexandre Julliard's avatar
Alexandre Julliard committed
1082
    {
1083
        WIN_DestroyWindow( hwnd );
1084 1085
        return 0;
    }
1086

1087
    /* Notify the parent window only */
1088

1089
    send_parent_notify( hwnd, WM_CREATE );
1090
    if (!IsWindow( hwnd )) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1091

1092
    if (cs->style & WS_VISIBLE)
1093
    {
1094
        if (cs->style & WS_MAXIMIZE)
1095
            sw = SW_SHOW;
1096 1097 1098 1099 1100
        else if (cs->style & WS_MINIMIZE)
            sw = SW_SHOWMINIMIZED;

        ShowWindow( hwnd, sw );
        if (cs->dwExStyle & WS_EX_MDICHILD)
1101
        {
1102 1103 1104
            SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
            /* ShowWindow won't activate child windows */
            SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1105 1106 1107
        }
    }

1108
    /* Call WH_SHELL hook */
1109

1110
    if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1111
        HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1112

1113
    TRACE("created window %p\n", hwnd);
1114
    return hwnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
1115 1116 1117
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1118
/***********************************************************************
1119
 *		CreateWindow (USER.41)
Alexandre Julliard's avatar
Alexandre Julliard committed
1120
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
1121 1122 1123
HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
                              DWORD style, INT16 x, INT16 y, INT16 width,
                              INT16 height, HWND16 parent, HMENU16 menu,
1124
                              HINSTANCE16 instance, LPVOID data )
Alexandre Julliard's avatar
Alexandre Julliard committed
1125 1126
{
    return CreateWindowEx16( 0, className, windowName, style,
1127
                             x, y, width, height, parent, menu, instance, data );
Alexandre Julliard's avatar
Alexandre Julliard committed
1128 1129 1130 1131
}


/***********************************************************************
1132
 *		CreateWindowEx (USER.452)
Alexandre Julliard's avatar
Alexandre Julliard committed
1133
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
1134 1135 1136 1137
HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
                                LPCSTR windowName, DWORD style, INT16 x,
                                INT16 y, INT16 width, INT16 height,
                                HWND16 parent, HMENU16 menu,
1138
                                HINSTANCE16 instance, LPVOID data )
Alexandre Julliard's avatar
Alexandre Julliard committed
1139
{
1140
    CREATESTRUCTA cs;
1141
    char buffer[256];
Alexandre Julliard's avatar
Alexandre Julliard committed
1142

Alexandre Julliard's avatar
Alexandre Julliard committed
1143
    /* Fix the coordinates */
Alexandre Julliard's avatar
Alexandre Julliard committed
1144

1145 1146 1147 1148
    cs.x  = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
    cs.y  = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
    cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
    cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
Alexandre Julliard's avatar
Alexandre Julliard committed
1149

Alexandre Julliard's avatar
Alexandre Julliard committed
1150
    /* Create the window */
Alexandre Julliard's avatar
Alexandre Julliard committed
1151

Alexandre Julliard's avatar
Alexandre Julliard committed
1152
    cs.lpCreateParams = data;
1153
    cs.hInstance      = HINSTANCE_32(instance);
1154
    cs.hMenu          = HMENU_32(menu);
1155
    cs.hwndParent     = WIN_Handle32( parent );
Alexandre Julliard's avatar
Alexandre Julliard committed
1156 1157 1158 1159
    cs.style          = style;
    cs.lpszName       = windowName;
    cs.lpszClass      = className;
    cs.dwExStyle      = exStyle;
1160

1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
    if (!IS_INTRESOURCE(className))
    {
        WCHAR bufferW[256];

        if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
            return 0;
        return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
    }
    else
    {
        if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
        {
            ERR( "bad atom %x\n", LOWORD(className));
            return 0;
        }
        cs.lpszClass = buffer;
        return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1179 1180 1181 1182
}


/***********************************************************************
1183
 *		CreateWindowExA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1184
 */
1185 1186 1187 1188 1189
HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
                                 LPCSTR windowName, DWORD style, INT x,
                                 INT y, INT width, INT height,
                                 HWND parent, HMENU menu,
                                 HINSTANCE instance, LPVOID data )
Alexandre Julliard's avatar
Alexandre Julliard committed
1190
{
1191
    CREATESTRUCTA cs;
Alexandre Julliard's avatar
Alexandre Julliard committed
1192 1193

    cs.lpCreateParams = data;
Alexandre Julliard's avatar
Alexandre Julliard committed
1194 1195
    cs.hInstance      = instance;
    cs.hMenu          = menu;
Alexandre Julliard's avatar
Alexandre Julliard committed
1196
    cs.hwndParent     = parent;
Alexandre Julliard's avatar
Alexandre Julliard committed
1197 1198 1199 1200 1201
    cs.x              = x;
    cs.y              = y;
    cs.cx             = width;
    cs.cy             = height;
    cs.style          = style;
Alexandre Julliard's avatar
Alexandre Julliard committed
1202 1203
    cs.lpszName       = windowName;
    cs.lpszClass      = className;
Alexandre Julliard's avatar
Alexandre Julliard committed
1204
    cs.dwExStyle      = exStyle;
1205

1206 1207 1208 1209 1210 1211 1212 1213
    if (!IS_INTRESOURCE(className))
    {
        WCHAR bufferW[256];
        if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
            return 0;
        return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
    }
    return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
Alexandre Julliard's avatar
Alexandre Julliard committed
1214
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1215 1216


Alexandre Julliard's avatar
Alexandre Julliard committed
1217
/***********************************************************************
1218
 *		CreateWindowExW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1219
 */
1220 1221 1222 1223 1224
HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
                                 LPCWSTR windowName, DWORD style, INT x,
                                 INT y, INT width, INT height,
                                 HWND parent, HMENU menu,
                                 HINSTANCE instance, LPVOID data )
Alexandre Julliard's avatar
Alexandre Julliard committed
1225
{
1226
    CREATESTRUCTW cs;
Alexandre Julliard's avatar
Alexandre Julliard committed
1227 1228

    cs.lpCreateParams = data;
Alexandre Julliard's avatar
Alexandre Julliard committed
1229 1230
    cs.hInstance      = instance;
    cs.hMenu          = menu;
Alexandre Julliard's avatar
Alexandre Julliard committed
1231
    cs.hwndParent     = parent;
Alexandre Julliard's avatar
Alexandre Julliard committed
1232 1233 1234 1235 1236
    cs.x              = x;
    cs.y              = y;
    cs.cx             = width;
    cs.cy             = height;
    cs.style          = style;
Alexandre Julliard's avatar
Alexandre Julliard committed
1237 1238
    cs.lpszName       = windowName;
    cs.lpszClass      = className;
Alexandre Julliard's avatar
Alexandre Julliard committed
1239
    cs.dwExStyle      = exStyle;
1240

1241 1242
    /* Note: we rely on the fact that CREATESTRUCTA and */
    /* CREATESTRUCTW have the same layout. */
1243
    return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
Alexandre Julliard's avatar
Alexandre Julliard committed
1244 1245
}

1246

Alexandre Julliard's avatar
Alexandre Julliard committed
1247 1248 1249
/***********************************************************************
 *           WIN_SendDestroyMsg
 */
1250
static void WIN_SendDestroyMsg( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
1251
{
1252 1253 1254 1255 1256
    GUITHREADINFO info;

    if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
    {
        if (hwnd == info.hwndCaret) DestroyCaret();
1257
        if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1258
    }
1259 1260 1261 1262

    /*
     * Send the WM_DESTROY to the window.
     */
1263
    SendMessageW( hwnd, WM_DESTROY, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
1264

1265 1266 1267 1268
    /*
     * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
     * make sure that the window still exists when we come back.
     */
1269 1270 1271 1272
    if (IsWindow(hwnd))
    {
        HWND* pWndArray;
        int i;
1273

1274
        if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1275

1276
        for (i = 0; pWndArray[i]; i++)
1277 1278 1279
        {
            if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
        }
1280
        HeapFree( GetProcessHeap(), 0, pWndArray );
Alexandre Julliard's avatar
Alexandre Julliard committed
1281 1282
    }
    else
1283
      WARN("\tdestroyed itself while in WM_DESTROY!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1284 1285 1286
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1287
/***********************************************************************
1288
 *		DestroyWindow (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1289
 */
1290
BOOL WINAPI DestroyWindow( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
1291
{
1292
    BOOL is_child;
Alexandre Julliard's avatar
Alexandre Julliard committed
1293

1294 1295 1296 1297 1298
    if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
    {
        SetLastError( ERROR_ACCESS_DENIED );
        return FALSE;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1299

1300
    TRACE("(%p)\n", hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1301

Alexandre Julliard's avatar
Alexandre Julliard committed
1302 1303
      /* Call hooks */

1304
    if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1305

1306 1307 1308
    if (MENU_IsMenuActive() == hwnd)
        EndMenu();

1309 1310 1311 1312 1313 1314 1315 1316
    is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;

    if (is_child)
    {
        if (!USER_IsExitingThread( GetCurrentThreadId() ))
            send_parent_notify( hwnd, WM_DESTROY );
    }
    else if (!GetWindow( hwnd, GW_OWNER ))
Alexandre Julliard's avatar
Alexandre Julliard committed
1317
    {
1318
        HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
Alexandre Julliard's avatar
Alexandre Julliard committed
1319 1320 1321
        /* FIXME: clean up palette - see "Internals" p.352 */
    }

1322
    if (!IsWindow(hwnd)) return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1323

Alexandre Julliard's avatar
Alexandre Julliard committed
1324
      /* Hide the window */
1325 1326 1327 1328 1329 1330 1331 1332 1333
    if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
    {
        /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
        if (is_child)
            ShowWindow( hwnd, SW_HIDE );
        else
            SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
                          SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
    }
1334

1335
    if (!IsWindow(hwnd)) return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1336

Alexandre Julliard's avatar
Alexandre Julliard committed
1337 1338
      /* Recursively destroy owned windows */

1339
    if (!is_child)
Alexandre Julliard's avatar
Alexandre Julliard committed
1340
    {
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361
        for (;;)
        {
            int i, got_one = 0;
            HWND *list = WIN_ListChildren( GetDesktopWindow() );
            if (list)
            {
                for (i = 0; list[i]; i++)
                {
                    if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
                    if (WIN_IsCurrentThread( list[i] ))
                    {
                        DestroyWindow( list[i] );
                        got_one = 1;
                        continue;
                    }
                    WIN_SetOwner( list[i], 0 );
                }
                HeapFree( GetProcessHeap(), 0, list );
            }
            if (!got_one) break;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
1362 1363
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
1364
      /* Send destroy messages */
Alexandre Julliard's avatar
Alexandre Julliard committed
1365

1366
    WIN_SendDestroyMsg( hwnd );
1367
    if (!IsWindow( hwnd )) return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1368

1369 1370 1371
    if (GetClipboardOwner() == hwnd)
        CLIPBOARD_ReleaseOwner();

Alexandre Julliard's avatar
Alexandre Julliard committed
1372 1373
      /* Destroy the window storage */

1374
    WIN_DestroyWindow( hwnd );
1375
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1376 1377 1378
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1379
/***********************************************************************
1380
 *		CloseWindow (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1381
 */
1382
BOOL WINAPI CloseWindow( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
1383
{
1384
    if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1385
    ShowWindow( hwnd, SW_MINIMIZE );
1386
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1387 1388
}

1389

Alexandre Julliard's avatar
Alexandre Julliard committed
1390
/***********************************************************************
1391
 *		OpenIcon (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1392
 */
1393
BOOL WINAPI OpenIcon( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
1394
{
1395 1396
    if (!IsIconic( hwnd )) return FALSE;
    ShowWindow( hwnd, SW_SHOWNORMAL );
Alexandre Julliard's avatar
Alexandre Julliard committed
1397
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1398 1399
}

Alexandre Julliard's avatar
Alexandre Julliard committed
1400

Alexandre Julliard's avatar
Alexandre Julliard committed
1401
/***********************************************************************
1402
 *		FindWindowExW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1403
 */
1404
HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
Alexandre Julliard's avatar
Alexandre Julliard committed
1405
{
1406 1407
    HWND *list = NULL;
    HWND retvalue = 0;
1408 1409
    int i = 0, len = 0;
    WCHAR *buffer = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
1410

1411 1412
    if (!parent) parent = GetDesktopWindow();
    if (title)
Alexandre Julliard's avatar
Alexandre Julliard committed
1413
    {
1414 1415
        len = strlenW(title) + 1;  /* one extra char to check for chars beyond the end */
        if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1416
    }
1417

1418
    if (!(list = list_window_children( parent, className, 0 ))) goto done;
1419 1420

    if (child)
1421
    {
1422
        child = WIN_GetFullHandle( child );
1423
        while (list[i] && list[i] != child) i++;
1424
        if (!list[i]) goto done;
1425
        i++;  /* start from next window */
Alexandre Julliard's avatar
Alexandre Julliard committed
1426 1427
    }

1428
    if (title)
Alexandre Julliard's avatar
Alexandre Julliard committed
1429
    {
1430 1431
        while (list[i])
        {
1432
            if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1433 1434
            i++;
        }
1435
    }
1436 1437
    retvalue = list[i];

1438
 done:
1439 1440
    HeapFree( GetProcessHeap(), 0, list );
    HeapFree( GetProcessHeap(), 0, buffer );
1441
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
1442
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1443 1444 1445 1446



/***********************************************************************
1447
 *		FindWindowA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1448
 */
1449
HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
Alexandre Julliard's avatar
Alexandre Julliard committed
1450
{
1451
    HWND ret = FindWindowExA( 0, 0, className, title );
Alexandre Julliard's avatar
Alexandre Julliard committed
1452 1453
    if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
1454 1455 1456 1457
}


/***********************************************************************
1458
 *		FindWindowExA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1459
 */
1460
HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
Alexandre Julliard's avatar
Alexandre Julliard committed
1461
{
1462 1463
    LPWSTR titleW = NULL;
    HWND hwnd = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1464

1465
    if (title)
Alexandre Julliard's avatar
Alexandre Julliard committed
1466
    {
1467 1468 1469
        DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
        if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
        MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
Alexandre Julliard's avatar
Alexandre Julliard committed
1470
    }
1471

1472
    if (!IS_INTRESOURCE(className))
Alexandre Julliard's avatar
Alexandre Julliard committed
1473
    {
1474 1475 1476 1477 1478 1479 1480
        WCHAR classW[256];
        if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
            hwnd = FindWindowExW( parent, child, classW, titleW );
    }
    else
    {
        hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
Alexandre Julliard's avatar
Alexandre Julliard committed
1481
    }
1482 1483 1484

    HeapFree( GetProcessHeap(), 0, titleW );
    return hwnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
1485 1486 1487 1488
}


/***********************************************************************
1489
 *		FindWindowW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1490
 */
1491
HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
Alexandre Julliard's avatar
Alexandre Julliard committed
1492
{
1493
    return FindWindowExW( 0, 0, className, title );
Alexandre Julliard's avatar
Alexandre Julliard committed
1494 1495 1496
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1497
/**********************************************************************
1498
 *		GetDesktopWindow (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1499
 */
1500
HWND WINAPI GetDesktopWindow(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
1501
{
1502 1503
    struct user_thread_info *thread_info = get_user_thread_info();

1504 1505 1506 1507 1508 1509 1510 1511 1512
    if (thread_info->desktop) return thread_info->desktop;

    SERVER_START_REQ( get_desktop_window )
    {
        req->force = 0;
        if (!wine_server_call( req )) thread_info->desktop = reply->handle;
    }
    SERVER_END_REQ;

1513 1514
    if (!thread_info->desktop)
    {
1515
        static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1516 1517
        STARTUPINFOW si;
        PROCESS_INFORMATION pi;
1518
        WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1519 1520 1521

        memset( &si, 0, sizeof(si) );
        si.cb = sizeof(si);
1522 1523 1524
        GetSystemDirectoryW( cmdline, MAX_PATH );
        lstrcatW( cmdline, command_line );
        if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1525 1526
                            NULL, NULL, &si, &pi ))
        {
1527
            TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1528 1529 1530 1531 1532
            WaitForInputIdle( pi.hProcess, 10000 );
            CloseHandle( pi.hThread );
            CloseHandle( pi.hProcess );

        }
1533
        else WARN( "failed to start explorer, err %d\n", GetLastError() );
1534

1535 1536
        SERVER_START_REQ( get_desktop_window )
        {
1537
            req->force = 1;
1538 1539 1540 1541
            if (!wine_server_call( req )) thread_info->desktop = reply->handle;
        }
        SERVER_END_REQ;
    }
1542 1543 1544 1545

    if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
        ERR( "failed to create desktop window\n" );

1546
    return thread_info->desktop;
Alexandre Julliard's avatar
Alexandre Julliard committed
1547 1548 1549
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1550
/*******************************************************************
1551
 *		EnableWindow (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1552
 */
1553
BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
Alexandre Julliard's avatar
Alexandre Julliard committed
1554
{
1555
    BOOL retvalue;
1556
    HWND full_handle;
Alexandre Julliard's avatar
Alexandre Julliard committed
1557

1558 1559 1560 1561 1562 1563
    if (is_broadcast(hwnd))
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }

1564 1565
    if (!(full_handle = WIN_IsCurrentThread( hwnd )))
        return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1566

1567
    hwnd = full_handle;
1568

1569
    TRACE("( %p, %d )\n", hwnd, enable);
1570

1571
    retvalue = !IsWindowEnabled( hwnd );
1572

1573
    if (enable && retvalue)
1574
    {
1575
        WIN_SetStyle( hwnd, 0, WS_DISABLED );
1576
        SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
1577
    }
1578
    else if (!enable && !retvalue)
Alexandre Julliard's avatar
Alexandre Julliard committed
1579
    {
1580
        HWND capture_wnd;
1581

1582
        SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1583

1584
        WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1585

1586
        if (hwnd == GetFocus())
1587
            SetFocus( 0 );  /* A disabled window can't have the focus */
1588

1589 1590
        capture_wnd = GetCapture();
        if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1591 1592
            ReleaseCapture();  /* A disabled window can't capture the mouse */

1593
        SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
1594
    }
1595
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
1596 1597 1598
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1599
/***********************************************************************
1600
 *		IsWindowEnabled (USER32.@)
1601
 */
1602
BOOL WINAPI IsWindowEnabled(HWND hWnd)
Alexandre Julliard's avatar
Alexandre Julliard committed
1603
{
1604
    return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
Alexandre Julliard's avatar
Alexandre Julliard committed
1605 1606
}

Alexandre Julliard's avatar
Alexandre Julliard committed
1607

Alexandre Julliard's avatar
Alexandre Julliard committed
1608
/***********************************************************************
1609
 *		IsWindowUnicode (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1610
 */
1611
BOOL WINAPI IsWindowUnicode( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
1612
{
1613
    WND * wndPtr;
1614 1615 1616
    BOOL retvalue = FALSE;

    if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1617

1618
    if (wndPtr == WND_DESKTOP) return TRUE;
1619 1620 1621

    if (wndPtr != WND_OTHER_PROCESS)
    {
1622
        retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633
        WIN_ReleasePtr( wndPtr );
    }
    else
    {
        SERVER_START_REQ( get_window_info )
        {
            req->handle = hwnd;
            if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
        }
        SERVER_END_REQ;
    }
1634
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
1635 1636 1637
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1638
/**********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1639 1640 1641
 *	     WIN_GetWindowLong
 *
 * Helper function for GetWindowLong().
Alexandre Julliard's avatar
Alexandre Julliard committed
1642
 */
1643
static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
Alexandre Julliard's avatar
Alexandre Julliard committed
1644
{
1645
    LONG_PTR retvalue = 0;
1646 1647
    WND *wndPtr;

1648
    if (offset == GWLP_HWNDPARENT)
1649 1650 1651
    {
        HWND parent = GetAncestor( hwnd, GA_PARENT );
        if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1652
        return (ULONG_PTR)parent;
1653
    }
1654 1655 1656 1657 1658 1659 1660

    if (!(wndPtr = WIN_GetPtr( hwnd )))
    {
        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
        return 0;
    }

1661
    if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1662
    {
1663
        if (offset == GWLP_WNDPROC)
1664 1665 1666 1667 1668 1669 1670 1671
        {
            SetLastError( ERROR_ACCESS_DENIED );
            return 0;
        }
        SERVER_START_REQ( set_window_info )
        {
            req->handle = hwnd;
            req->flags  = 0;  /* don't set anything, just retrieve */
1672
            req->extra_offset = (offset >= 0) ? offset : -1;
1673
            req->extra_size = (offset >= 0) ? size : 0;
1674
            if (!wine_server_call_err( req ))
1675 1676 1677
            {
                switch(offset)
                {
1678 1679 1680 1681
                case GWL_STYLE:      retvalue = reply->old_style; break;
                case GWL_EXSTYLE:    retvalue = reply->old_ex_style; break;
                case GWLP_ID:        retvalue = reply->old_id; break;
                case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1682
                case GWLP_USERDATA:  retvalue = reply->old_user_data; break;
1683
                default:
1684
                    if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1685
                    else SetLastError( ERROR_INVALID_INDEX );
1686 1687 1688 1689 1690 1691 1692 1693 1694 1695
                    break;
                }
            }
        }
        SERVER_END_REQ;
        return retvalue;
    }

    /* now we have a valid wndPtr */

Alexandre Julliard's avatar
Alexandre Julliard committed
1696 1697
    if (offset >= 0)
    {
1698
        if (offset > (int)(wndPtr->cbWndExtra - size))
Alexandre Julliard's avatar
Alexandre Julliard committed
1699
        {
1700
            WARN("Invalid offset %d\n", offset );
1701 1702 1703
            WIN_ReleasePtr( wndPtr );
            SetLastError( ERROR_INVALID_INDEX );
            return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1704
        }
1705 1706
        retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );

Alexandre Julliard's avatar
Alexandre Julliard committed
1707
        /* Special case for dialog window procedure */
1708
        if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1709
            retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1710 1711
        WIN_ReleasePtr( wndPtr );
        return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
1712
    }
1713

Alexandre Julliard's avatar
Alexandre Julliard committed
1714 1715
    switch(offset)
    {
1716
    case GWLP_USERDATA:  retvalue = wndPtr->userdata; break;
1717 1718
    case GWL_STYLE:      retvalue = wndPtr->dwStyle; break;
    case GWL_EXSTYLE:    retvalue = wndPtr->dwExStyle; break;
1719 1720
    case GWLP_ID:        retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
    case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730
    case GWLP_WNDPROC:
        /* This looks like a hack only for the edit control (see tests). This makes these controls
         * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
         * that the hack is in GetWindowLongPtr[AW], not in winprocs.
         */
        if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
            retvalue = (ULONG_PTR)wndPtr->winproc;
        else
            retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
        break;
1731 1732 1733 1734
    default:
        WARN("Unknown offset %d\n", offset );
        SetLastError( ERROR_INVALID_INDEX );
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1735
    }
1736
    WIN_ReleasePtr(wndPtr);
1737
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
1738 1739 1740
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1741
/**********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1742 1743 1744
 *	     WIN_SetWindowLong
 *
 * Helper function for SetWindowLong().
Alexandre Julliard's avatar
Alexandre Julliard committed
1745 1746 1747
 *
 * 0 is the failure code. However, in the case of failure SetLastError
 * must be set to distinguish between a 0 return value and a failure.
Alexandre Julliard's avatar
Alexandre Julliard committed
1748
 */
1749
LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
Alexandre Julliard's avatar
Alexandre Julliard committed
1750
{
1751 1752
    STYLESTRUCT style;
    BOOL ok;
1753
    LONG_PTR retval = 0;
1754
    WND *wndPtr;
1755

1756
    TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
Alexandre Julliard's avatar
Alexandre Julliard committed
1757

1758 1759 1760 1761 1762
    if (is_broadcast(hwnd))
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775

    if (!(wndPtr = WIN_GetPtr( hwnd )))
    {
        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
        return 0;
    }
    if (wndPtr == WND_DESKTOP)
    {
        /* can't change anything on the desktop window */
        SetLastError( ERROR_ACCESS_DENIED );
        return 0;
    }
    if (wndPtr == WND_OTHER_PROCESS)
Alexandre Julliard's avatar
Alexandre Julliard committed
1776
    {
1777
        if (offset == GWLP_WNDPROC)
1778 1779 1780 1781
        {
            SetLastError( ERROR_ACCESS_DENIED );
            return 0;
        }
1782 1783 1784 1785 1786 1787
        if (offset > 32767 || offset < -32767)
        {
            SetLastError( ERROR_INVALID_INDEX );
            return 0;
        }
        return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
Alexandre Julliard's avatar
Alexandre Julliard committed
1788 1789
    }

1790 1791
    /* first some special cases */
    switch( offset )
Alexandre Julliard's avatar
Alexandre Julliard committed
1792
    {
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802
    case GWL_STYLE:
    case GWL_EXSTYLE:
        style.styleOld =
            offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
        style.styleNew = newval;
        WIN_ReleasePtr( wndPtr );
        SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
        if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
        newval = style.styleNew;
        break;
1803
    case GWLP_HWNDPARENT:
1804 1805 1806
        if (wndPtr->parent == GetDesktopWindow())
        {
            WIN_ReleasePtr( wndPtr );
1807
            return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1808 1809 1810 1811
        }
        else
        {
            WIN_ReleasePtr( wndPtr );
1812
            return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1813
        }
1814
    case GWLP_WNDPROC:
1815
    {
1816
        WNDPROC proc;
1817
        UINT old_flags = wndPtr->flags;
1818
        retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1819 1820 1821 1822
        if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
        else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
        if (proc) wndPtr->winproc = proc;
        if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1823 1824
        else wndPtr->flags &= ~WIN_ISUNICODE;
        if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1825 1826 1827 1828 1829 1830 1831
        {
            WIN_ReleasePtr( wndPtr );
            return retval;
        }
        /* update is_unicode flag on the server side */
        break;
    }
1832 1833 1834
    case GWLP_ID:
    case GWLP_HINSTANCE:
    case GWLP_USERDATA:
1835
        break;
1836
    case DWLP_DLGPROC:
1837 1838
        if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
            (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1839
        {
1840
            WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1841
            retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1842 1843
            if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
            else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1844 1845 1846 1847 1848
            WIN_ReleasePtr( wndPtr );
            return retval;
        }
        /* fall through */
    default:
1849
        if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
Alexandre Julliard's avatar
Alexandre Julliard committed
1850
        {
1851
            WARN("Invalid offset %d\n", offset );
1852 1853 1854
            WIN_ReleasePtr( wndPtr );
            SetLastError( ERROR_INVALID_INDEX );
            return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1855
        }
1856
        else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
Alexandre Julliard's avatar
Alexandre Julliard committed
1857
        {
1858 1859 1860
            /* already set to the same value */
            WIN_ReleasePtr( wndPtr );
            return newval;
Alexandre Julliard's avatar
Alexandre Julliard committed
1861
        }
1862
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1863
    }
1864

1865 1866 1867 1868 1869
    SERVER_START_REQ( set_window_info )
    {
        req->handle = hwnd;
        req->extra_offset = -1;
        switch(offset)
1870 1871
        {
        case GWL_STYLE:
1872 1873 1874
            req->flags = SET_WIN_STYLE;
            req->style = newval;
            break;
1875
        case GWL_EXSTYLE:
1876
            req->flags = SET_WIN_EXSTYLE;
1877 1878
            /* WS_EX_TOPMOST can only be changed through SetWindowPos */
            newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1879
            req->ex_style = newval;
1880
            break;
1881
        case GWLP_ID:
1882 1883 1884
            req->flags = SET_WIN_ID;
            req->id = newval;
            break;
1885
        case GWLP_HINSTANCE:
1886 1887 1888
            req->flags = SET_WIN_INSTANCE;
            req->instance = (void *)newval;
            break;
1889 1890
        case GWLP_WNDPROC:
            req->flags = SET_WIN_UNICODE;
1891
            req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1892
            break;
1893
        case GWLP_USERDATA:
1894
            req->flags = SET_WIN_USERDATA;
1895
            req->user_data = newval;
1896 1897
            break;
        default:
1898
            req->flags = SET_WIN_EXTRA;
1899
            req->extra_offset = offset;
1900 1901
            req->extra_size = size;
            set_win_data( &req->extra_value, newval, size );
1902
        }
1903
        if ((ok = !wine_server_call_err( req )))
1904 1905 1906 1907
        {
            switch(offset)
            {
            case GWL_STYLE:
1908 1909
                wndPtr->dwStyle = newval;
                retval = reply->old_style;
1910 1911
                break;
            case GWL_EXSTYLE:
1912 1913
                wndPtr->dwExStyle = newval;
                retval = reply->old_ex_style;
1914
                break;
1915
            case GWLP_ID:
1916 1917
                wndPtr->wIDmenu = newval;
                retval = reply->old_id;
1918
                break;
1919
            case GWLP_HINSTANCE:
1920 1921
                wndPtr->hInstance = (HINSTANCE)newval;
                retval = (ULONG_PTR)reply->old_instance;
1922
                break;
1923 1924
            case GWLP_WNDPROC:
                break;
1925
            case GWLP_USERDATA:
1926
                wndPtr->userdata = newval;
1927
                retval = reply->old_user_data;
1928
                break;
1929
            default:
1930 1931
                retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
                set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
1932
                break;
1933 1934
            }
        }
1935 1936 1937
    }
    SERVER_END_REQ;
    WIN_ReleasePtr( wndPtr );
1938

1939
    if (!ok) return 0;
1940

1941
    if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
1942

1943 1944
    if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
        SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
Alexandre Julliard's avatar
Alexandre Julliard committed
1945

Alexandre Julliard's avatar
Alexandre Julliard committed
1946 1947 1948 1949
    return retval;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1950
/**********************************************************************
1951
 *		GetWindowLong (USER.135)
Alexandre Julliard's avatar
Alexandre Julliard committed
1952
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
1953
LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
Alexandre Julliard's avatar
Alexandre Julliard committed
1954
{
1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993
    WND *wndPtr;
    LONG_PTR retvalue;
    BOOL is_winproc = (offset == GWLP_WNDPROC);

    if (offset >= 0)
    {
        if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
        {
            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
            return 0;
        }
        if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
        {
            if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
            {
                /*
                 * Some programs try to access last element from 16 bit
                 * code using illegal offset value. Hopefully this is
                 * what those programs really expect.
                 */
                if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
                {
                    INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
                    ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
                    offset = offset2;
                }
                else
                {
                    WARN("Invalid offset %d\n", offset );
                    WIN_ReleasePtr( wndPtr );
                    SetLastError( ERROR_INVALID_INDEX );
                    return 0;
                }
            }
            is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
            WIN_ReleasePtr( wndPtr );
        }
    }
    retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
1994
    if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
1995
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
1996 1997 1998
}


1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
/**********************************************************************
 *		GetWindowWord (USER32.@)
 */
WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
{
    switch(offset)
    {
    case GWLP_ID:
    case GWLP_HINSTANCE:
    case GWLP_HWNDPARENT:
        break;
    default:
        if (offset < 0)
        {
            WARN("Invalid offset %d\n", offset );
            SetLastError( ERROR_INVALID_INDEX );
            return 0;
        }
        break;
    }
    return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2023
/**********************************************************************
2024
 *		GetWindowLongA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2025
 */
2026
LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
Alexandre Julliard's avatar
Alexandre Julliard committed
2027
{
2028
    return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
Alexandre Julliard's avatar
Alexandre Julliard committed
2029 2030 2031 2032
}


/**********************************************************************
2033
 *		GetWindowLongW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2034
 */
2035
LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
Alexandre Julliard's avatar
Alexandre Julliard committed
2036
{
2037
    return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
Alexandre Julliard's avatar
Alexandre Julliard committed
2038 2039 2040 2041
}


/**********************************************************************
2042
 *		SetWindowLong (USER.136)
Alexandre Julliard's avatar
Alexandre Julliard committed
2043
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
2044
LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
Alexandre Julliard's avatar
Alexandre Julliard committed
2045
{
2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065
    WND *wndPtr;
    BOOL is_winproc = (offset == GWLP_WNDPROC);

    if (offset == DWLP_DLGPROC)
    {
        if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
        {
            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
            return 0;
        }
        if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
        {
            is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
                          (wndPtr->flags & WIN_ISDIALOG));
            WIN_ReleasePtr( wndPtr );
        }
    }

    if (is_winproc)
    {
2066
        WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2067
        WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2068
        return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2069 2070
    }
    else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
Alexandre Julliard's avatar
Alexandre Julliard committed
2071 2072 2073
}


2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097
/**********************************************************************
 *		SetWindowWord (USER32.@)
 */
WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
{
    switch(offset)
    {
    case GWLP_ID:
    case GWLP_HINSTANCE:
    case GWLP_HWNDPARENT:
        break;
    default:
        if (offset < 0)
        {
            WARN("Invalid offset %d\n", offset );
            SetLastError( ERROR_INVALID_INDEX );
            return 0;
        }
        break;
    }
    return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2098
/**********************************************************************
2099
 *		SetWindowLongA (USER32.@)
2100 2101
 *
 * See SetWindowLongW.
Alexandre Julliard's avatar
Alexandre Julliard committed
2102
 */
2103
LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
Alexandre Julliard's avatar
Alexandre Julliard committed
2104
{
2105
    return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
Alexandre Julliard's avatar
Alexandre Julliard committed
2106 2107 2108
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2109
/**********************************************************************
2110
 *		SetWindowLongW (USER32.@) Set window attribute
Alexandre Julliard's avatar
Alexandre Julliard committed
2111 2112
 *
 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2113
 * value in a window's extra memory.
Alexandre Julliard's avatar
Alexandre Julliard committed
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123
 *
 * The _hwnd_ parameter specifies the window.  is the handle to a
 * window that has extra memory. The _newval_ parameter contains the
 * new attribute or extra memory value.  If positive, the _offset_
 * parameter is the byte-addressed location in the window's extra
 * memory to set.  If negative, _offset_ specifies the window
 * attribute to set, and should be one of the following values:
 *
 * GWL_EXSTYLE      The window's extended window style
 *
2124
 * GWL_STYLE        The window's window style.
Alexandre Julliard's avatar
Alexandre Julliard committed
2125
 *
2126
 * GWLP_WNDPROC     Pointer to the window's window procedure.
Alexandre Julliard's avatar
Alexandre Julliard committed
2127
 *
2128
 * GWLP_HINSTANCE   The window's pplication instance handle.
Alexandre Julliard's avatar
Alexandre Julliard committed
2129
 *
2130
 * GWLP_ID          The window's identifier.
Alexandre Julliard's avatar
Alexandre Julliard committed
2131
 *
2132
 * GWLP_USERDATA    The window's user-specified data.
Alexandre Julliard's avatar
Alexandre Julliard committed
2133
 *
2134
 * If the window is a dialog box, the _offset_ parameter can be one of
Alexandre Julliard's avatar
Alexandre Julliard committed
2135 2136
 * the following values:
 *
2137
 * DWLP_DLGPROC     The address of the window's dialog box procedure.
Alexandre Julliard's avatar
Alexandre Julliard committed
2138
 *
2139
 * DWLP_MSGRESULT   The return value of a message
Alexandre Julliard's avatar
Alexandre Julliard committed
2140 2141
 *                  that the dialog box procedure processed.
 *
2142
 * DWLP_USER        Application specific information.
Alexandre Julliard's avatar
Alexandre Julliard committed
2143 2144 2145 2146 2147 2148 2149 2150
 *
 * RETURNS
 *
 * If successful, returns the previous value located at _offset_. Otherwise,
 * returns 0.
 *
 * NOTES
 *
2151
 * Extra memory for a window class is specified by a nonzero cbWndExtra
Alexandre Julliard's avatar
Alexandre Julliard committed
2152 2153
 * parameter of the WNDCLASS structure passed to RegisterClass() at the
 * time of class creation.
2154
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
2155 2156 2157 2158 2159 2160 2161
 * Using GWL_WNDPROC to set a new window procedure effectively creates
 * a window subclass. Use CallWindowProc() in the new windows procedure
 * to pass messages to the superclass's window procedure.
 *
 * The user data is reserved for use by the application which created
 * the window.
 *
2162
 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
Alexandre Julliard's avatar
Alexandre Julliard committed
2163 2164 2165 2166 2167 2168
 * instead, call the EnableWindow() function to change the window's
 * disabled state.
 *
 * Do not use GWL_HWNDPARENT to reset the window's parent, use
 * SetParent() instead.
 *
2169 2170 2171 2172 2173
 * Win95:
 * When offset is GWL_STYLE and the calling app's ver is 4.0,
 * it sends WM_STYLECHANGING before changing the settings
 * and WM_STYLECHANGED afterwards.
 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
Alexandre Julliard's avatar
Alexandre Julliard committed
2174
 */
2175
LONG WINAPI SetWindowLongW(
2176 2177 2178
    HWND hwnd,  /* [in] window to alter */
    INT offset, /* [in] offset, in bytes, of location to alter */
    LONG newval /* [in] new value of location */
Alexandre Julliard's avatar
Alexandre Julliard committed
2179
) {
2180
    return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
Alexandre Julliard's avatar
Alexandre Julliard committed
2181 2182 2183 2184
}


/*******************************************************************
2185
 *		GetWindowTextA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2186
 */
2187
INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
Alexandre Julliard's avatar
Alexandre Julliard committed
2188
{
2189 2190
    WCHAR *buffer;

2191 2192
    if (!lpString) return 0;

2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203
    if (WIN_IsCurrentProcess( hwnd ))
        return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );

    /* when window belongs to other process, don't send a message */
    if (nMaxCount <= 0) return 0;
    if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
    get_server_window_text( hwnd, buffer, nMaxCount );
    if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
        lpString[nMaxCount-1] = 0;
    HeapFree( GetProcessHeap(), 0, buffer );
    return strlen(lpString);
Alexandre Julliard's avatar
Alexandre Julliard committed
2204
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2205

2206

Alexandre Julliard's avatar
Alexandre Julliard committed
2207
/*******************************************************************
2208
 *		InternalGetWindowText (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2209
 */
2210
INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
Alexandre Julliard's avatar
Alexandre Julliard committed
2211
{
2212 2213 2214 2215
    WND *win;

    if (nMaxCount <= 0) return 0;
    if (!(win = WIN_GetPtr( hwnd ))) return 0;
2216 2217
    if (win == WND_DESKTOP) lpString[0] = 0;
    else if (win != WND_OTHER_PROCESS)
2218 2219 2220 2221 2222 2223 2224 2225 2226
    {
        if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
        else lpString[0] = 0;
        WIN_ReleasePtr( win );
    }
    else
    {
        get_server_window_text( hwnd, lpString, nMaxCount );
    }
2227
    return strlenW(lpString);
Alexandre Julliard's avatar
Alexandre Julliard committed
2228 2229
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2230 2231

/*******************************************************************
2232
 *		GetWindowTextW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2233
 */
2234
INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
Alexandre Julliard's avatar
Alexandre Julliard committed
2235
{
2236 2237
    if (!lpString) return 0;

2238 2239 2240 2241 2242 2243 2244
    if (WIN_IsCurrentProcess( hwnd ))
        return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );

    /* when window belongs to other process, don't send a message */
    if (nMaxCount <= 0) return 0;
    get_server_window_text( hwnd, lpString, nMaxCount );
    return strlenW(lpString);
Alexandre Julliard's avatar
Alexandre Julliard committed
2245 2246 2247
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2248
/*******************************************************************
2249
 *		SetWindowTextA (USER32.@)
2250
 *		SetWindowText  (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2251
 */
2252
BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
Alexandre Julliard's avatar
Alexandre Julliard committed
2253
{
2254 2255 2256 2257 2258
    if (is_broadcast(hwnd))
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
2259
    if (!WIN_IsCurrentProcess( hwnd ))
2260
        WARN( "setting text %s of other process window %p should not use SendMessage\n",
2261
               debugstr_a(lpString), hwnd );
2262
    return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
Alexandre Julliard's avatar
Alexandre Julliard committed
2263 2264
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2265

Alexandre Julliard's avatar
Alexandre Julliard committed
2266
/*******************************************************************
2267
 *		SetWindowTextW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2268
 */
2269
BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
Alexandre Julliard's avatar
Alexandre Julliard committed
2270
{
2271 2272 2273 2274 2275
    if (is_broadcast(hwnd))
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
2276
    if (!WIN_IsCurrentProcess( hwnd ))
2277
        WARN( "setting text %s of other process window %p should not use SendMessage\n",
2278
               debugstr_w(lpString), hwnd );
2279
    return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
Alexandre Julliard's avatar
Alexandre Julliard committed
2280 2281 2282
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2283
/*******************************************************************
2284
 *		GetWindowTextLengthA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2285
 */
2286
INT WINAPI GetWindowTextLengthA( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2287
{
2288
    return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
2289 2290 2291
}

/*******************************************************************
2292
 *		GetWindowTextLengthW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2293
 */
2294
INT WINAPI GetWindowTextLengthW( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2295
{
2296
    return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
2297 2298
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2299

Alexandre Julliard's avatar
Alexandre Julliard committed
2300
/*******************************************************************
2301
 *		IsWindow (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2302
 */
2303
BOOL WINAPI IsWindow( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2304
{
2305
    WND *ptr;
2306
    BOOL ret;
2307

2308
    if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2309
    if (ptr == WND_DESKTOP) return TRUE;
2310 2311

    if (ptr != WND_OTHER_PROCESS)
2312
    {
2313
        WIN_ReleasePtr( ptr );
2314
        return TRUE;
2315 2316
    }

2317 2318
    /* check other processes */
    SERVER_START_REQ( get_window_info )
2319
    {
2320
        req->handle = hwnd;
2321
        ret = !wine_server_call_err( req );
2322
    }
2323
    SERVER_END_REQ;
2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335
    return ret;
}


/***********************************************************************
 *		GetWindowThreadProcessId (USER32.@)
 */
DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
{
    WND *ptr;
    DWORD tid = 0;

2336
    if (!(ptr = WIN_GetPtr( hwnd )))
2337
    {
2338 2339 2340 2341
        SetLastError( ERROR_INVALID_WINDOW_HANDLE);
        return 0;
    }

2342
    if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2343 2344 2345 2346 2347
    {
        /* got a valid window */
        tid = ptr->tid;
        if (process) *process = GetCurrentProcessId();
        WIN_ReleasePtr( ptr );
2348 2349 2350 2351 2352 2353 2354
        return tid;
    }

    /* check other processes */
    SERVER_START_REQ( get_window_info )
    {
        req->handle = hwnd;
2355
        if (!wine_server_call_err( req ))
2356
        {
2357 2358
            tid = (DWORD)reply->tid;
            if (process) *process = (DWORD)reply->pid;
2359 2360 2361 2362
        }
    }
    SERVER_END_REQ;
    return tid;
Alexandre Julliard's avatar
Alexandre Julliard committed
2363 2364 2365
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2366
/*****************************************************************
2367
 *		GetParent (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2368
 */
2369
HWND WINAPI GetParent( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2370
{
2371
    WND *wndPtr;
2372 2373
    HWND retvalue = 0;

2374 2375 2376 2377 2378
    if (!(wndPtr = WIN_GetPtr( hwnd )))
    {
        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
        return 0;
    }
2379
    if (wndPtr == WND_DESKTOP) return 0;
2380 2381 2382 2383 2384 2385 2386 2387
    if (wndPtr == WND_OTHER_PROCESS)
    {
        LONG style = GetWindowLongW( hwnd, GWL_STYLE );
        if (style & (WS_POPUP | WS_CHILD))
        {
            SERVER_START_REQ( get_window_tree )
            {
                req->handle = hwnd;
2388
                if (!wine_server_call_err( req ))
2389
                {
2390 2391
                    if (style & WS_POPUP) retvalue = reply->owner;
                    else if (style & WS_CHILD) retvalue = reply->parent;
2392 2393 2394 2395 2396 2397
                }
            }
            SERVER_END_REQ;
        }
    }
    else
2398
    {
2399 2400
        if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
        else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2401
        WIN_ReleasePtr( wndPtr );
2402
    }
2403
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
2404 2405 2406 2407
}


/*****************************************************************
2408
 *		GetAncestor (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2409
 */
2410
HWND WINAPI GetAncestor( HWND hwnd, UINT type )
Alexandre Julliard's avatar
Alexandre Julliard committed
2411
{
2412
    WND *win;
2413
    HWND *list, ret = 0;
2414

2415
    switch(type)
2416
    {
2417
    case GA_PARENT:
2418 2419 2420 2421 2422
        if (!(win = WIN_GetPtr( hwnd )))
        {
            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
            return 0;
        }
2423
        if (win == WND_DESKTOP) return 0;
2424
        if (win != WND_OTHER_PROCESS)
2425
        {
2426 2427
            ret = win->parent;
            WIN_ReleasePtr( win );
2428
        }
2429
        else /* need to query the server */
2430
        {
2431
            SERVER_START_REQ( get_window_tree )
2432
            {
2433 2434
                req->handle = hwnd;
                if (!wine_server_call_err( req )) ret = reply->parent;
2435
            }
2436
            SERVER_END_REQ;
2437
        }
2438
        break;
2439

2440
    case GA_ROOT:
2441
        if (!(list = list_window_parents( hwnd ))) return 0;
2442

2443 2444 2445 2446 2447 2448 2449 2450 2451
        if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd );  /* top-level window */
        else
        {
            int count = 2;
            while (list[count]) count++;
            ret = list[count - 2];  /* get the one before the desktop */
        }
        HeapFree( GetProcessHeap(), 0, list );
        break;
2452

2453 2454
    case GA_ROOTOWNER:
        if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2455 2456
        for (;;)
        {
2457 2458 2459
            HWND parent = GetParent( ret );
            if (!parent) break;
            ret = parent;
2460
        }
2461
        break;
2462 2463
    }
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
2464 2465
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2466

Alexandre Julliard's avatar
Alexandre Julliard committed
2467
/*****************************************************************
2468
 *		SetParent (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2469
 */
2470
HWND WINAPI SetParent( HWND hwnd, HWND parent )
Alexandre Julliard's avatar
Alexandre Julliard committed
2471
{
2472
    HWND full_handle;
2473 2474 2475 2476
    HWND old_parent = 0;
    BOOL was_visible;
    WND *wndPtr;
    BOOL ret;
2477

2478 2479 2480 2481 2482 2483
    if (is_broadcast(hwnd) || is_broadcast(parent))
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

2484 2485 2486 2487 2488 2489 2490 2491 2492
    if (!parent) parent = GetDesktopWindow();
    else parent = WIN_GetFullHandle( parent );

    if (!IsWindow( parent ))
    {
        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
        return 0;
    }

2493 2494 2495 2496 2497 2498 2499
    /* Some applications try to set a child as a parent */
    if (IsChild(hwnd, parent))
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return 0;
    }

2500
    if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2501
        return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2502

2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530
    /* Windows hides the window first, then shows it again
     * including the WM_SHOWWINDOW messages and all */
    was_visible = ShowWindow( hwnd, SW_HIDE );

    wndPtr = WIN_GetPtr( hwnd );
    if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;

    SERVER_START_REQ( set_parent )
    {
        req->handle = hwnd;
        req->parent = parent;
        if ((ret = !wine_server_call( req )))
        {
            old_parent = reply->old_parent;
            wndPtr->parent = parent = reply->full_parent;
        }

    }
    SERVER_END_REQ;
    WIN_ReleasePtr( wndPtr );
    if (!ret) return 0;

    USER_Driver->pSetParent( full_handle, parent, old_parent );

    /* SetParent additionally needs to make hwnd the topmost window
       in the x-order and send the expected WM_WINDOWPOSCHANGING and
       WM_WINDOWPOSCHANGED notification messages.
    */
2531
    SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2532 2533 2534 2535 2536
                  SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
    /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
     * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */

    return old_parent;
Alexandre Julliard's avatar
Alexandre Julliard committed
2537 2538
}

2539

Alexandre Julliard's avatar
Alexandre Julliard committed
2540
/*******************************************************************
2541
 *		IsChild (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2542
 */
2543
BOOL WINAPI IsChild( HWND parent, HWND child )
Alexandre Julliard's avatar
Alexandre Julliard committed
2544
{
2545
    HWND *list = list_window_parents( child );
2546 2547 2548 2549
    int i;
    BOOL ret;

    if (!list) return FALSE;
2550
    parent = WIN_GetFullHandle( parent );
2551
    for (i = 0; list[i]; i++) if (list[i] == parent) break;
2552
    ret = list[i] && list[i+1];
2553 2554
    HeapFree( GetProcessHeap(), 0, list );
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
2555 2556 2557
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2558
/***********************************************************************
2559
 *		IsWindowVisible (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2560
 */
2561
BOOL WINAPI IsWindowVisible( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2562
{
2563
    HWND *list;
2564
    BOOL retval = TRUE;
2565 2566 2567
    int i;

    if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2568
    if (!(list = list_window_parents( hwnd ))) return TRUE;
2569 2570 2571 2572 2573 2574
    if (list[0] && list[1])  /* desktop window is considered always visible so we don't check it */
    {
        for (i = 0; list[i+1]; i++)
            if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
        retval = !list[i+1];
    }
2575
    HeapFree( GetProcessHeap(), 0, list );
2576
    return retval;
Alexandre Julliard's avatar
Alexandre Julliard committed
2577 2578
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2579

Alexandre Julliard's avatar
Alexandre Julliard committed
2580 2581
/***********************************************************************
 *           WIN_IsWindowDrawable
Alexandre Julliard's avatar
Alexandre Julliard committed
2582 2583 2584
 *
 * hwnd is drawable when it is visible, all parents are not
 * minimized, and it is itself not minimized unless we are
Alexandre Julliard's avatar
Alexandre Julliard committed
2585
 * trying to draw its default class icon.
Alexandre Julliard's avatar
Alexandre Julliard committed
2586
 */
2587
BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
Alexandre Julliard's avatar
Alexandre Julliard committed
2588
{
2589
    HWND *list;
2590
    BOOL retval = TRUE;
2591
    int i;
2592
    LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2593

2594
    if (!(style & WS_VISIBLE)) return FALSE;
2595
    if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON ))  return FALSE;
2596

2597
    if (!(list = list_window_parents( hwnd ))) return TRUE;
2598 2599 2600 2601 2602 2603 2604
    if (list[0] && list[1])  /* desktop window is considered always visible so we don't check it */
    {
        for (i = 0; list[i+1]; i++)
            if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
                break;
        retval = !list[i+1];
    }
2605 2606
    HeapFree( GetProcessHeap(), 0, list );
    return retval;
Alexandre Julliard's avatar
Alexandre Julliard committed
2607 2608
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2609

Alexandre Julliard's avatar
Alexandre Julliard committed
2610
/*******************************************************************
2611
 *		GetTopWindow (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2612
 */
2613
HWND WINAPI GetTopWindow( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2614
{
2615 2616
    if (!hwnd) hwnd = GetDesktopWindow();
    return GetWindow( hwnd, GW_CHILD );
Alexandre Julliard's avatar
Alexandre Julliard committed
2617 2618 2619
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2620
/*******************************************************************
2621
 *		GetWindow (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2622
 */
2623
HWND WINAPI GetWindow( HWND hwnd, UINT rel )
Alexandre Julliard's avatar
Alexandre Julliard committed
2624
{
2625
    HWND retval = 0;
2626

2627
    if (rel == GW_OWNER)  /* this one may be available locally */
Alexandre Julliard's avatar
Alexandre Julliard committed
2628
    {
2629 2630 2631 2632 2633 2634
        WND *wndPtr = WIN_GetPtr( hwnd );
        if (!wndPtr)
        {
            SetLastError( ERROR_INVALID_HANDLE );
            return 0;
        }
2635
        if (wndPtr == WND_DESKTOP) return 0;
2636 2637 2638 2639 2640 2641 2642
        if (wndPtr != WND_OTHER_PROCESS)
        {
            retval = wndPtr->owner;
            WIN_ReleasePtr( wndPtr );
            return retval;
        }
        /* else fall through to server call */
2643
    }
2644

2645 2646 2647
    SERVER_START_REQ( get_window_tree )
    {
        req->handle = hwnd;
2648
        if (!wine_server_call_err( req ))
Alexandre Julliard's avatar
Alexandre Julliard committed
2649
        {
2650
            switch(rel)
2651
            {
2652
            case GW_HWNDFIRST:
2653
                retval = reply->first_sibling;
2654 2655
                break;
            case GW_HWNDLAST:
2656
                retval = reply->last_sibling;
2657 2658
                break;
            case GW_HWNDNEXT:
2659
                retval = reply->next_sibling;
2660 2661
                break;
            case GW_HWNDPREV:
2662
                retval = reply->prev_sibling;
2663
                break;
2664
            case GW_OWNER:
2665
                retval = reply->owner;
2666
                break;
2667
            case GW_CHILD:
2668
                retval = reply->first_child;
2669
                break;
2670
            }
2671
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
2672
    }
2673
    SERVER_END_REQ;
2674
    return retval;
Alexandre Julliard's avatar
Alexandre Julliard committed
2675 2676 2677
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2678
/*******************************************************************
2679
 *		ShowOwnedPopups (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2680
 */
2681
BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
Alexandre Julliard's avatar
Alexandre Julliard committed
2682
{
2683
    int count = 0;
2684
    WND *pWnd;
2685
    HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2686

2687
    if (!win_array) return TRUE;
2688

2689 2690
    while (win_array[count]) count++;
    while (--count >= 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
2691
    {
2692
        if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2693 2694
        if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
        if (pWnd == WND_OTHER_PROCESS) continue;
2695
        if (fShow)
2696
        {
2697
            if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2698
            {
2699 2700 2701 2702 2703 2704 2705
                WIN_ReleasePtr( pWnd );
                /* In Windows, ShowOwnedPopups(TRUE) generates
                 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
                 * regardless of the state of the owner
                 */
                SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
                continue;
2706
            }
2707 2708 2709 2710
        }
        else
        {
            if (pWnd->dwStyle & WS_VISIBLE)
2711
            {
2712 2713 2714 2715 2716 2717 2718
                WIN_ReleasePtr( pWnd );
                /* In Windows, ShowOwnedPopups(FALSE) generates
                 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
                 * regardless of the state of the owner
                 */
                SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
                continue;
2719 2720
            }
        }
2721
        WIN_ReleasePtr( pWnd );
Alexandre Julliard's avatar
Alexandre Julliard committed
2722
    }
2723
    HeapFree( GetProcessHeap(), 0, win_array );
Alexandre Julliard's avatar
Alexandre Julliard committed
2724
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2725
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2726 2727


Alexandre Julliard's avatar
Alexandre Julliard committed
2728
/*******************************************************************
2729
 *		GetLastActivePopup (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2730
 */
2731
HWND WINAPI GetLastActivePopup( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2732
{
2733 2734 2735 2736 2737 2738 2739 2740
    HWND retval = hwnd;

    SERVER_START_REQ( get_window_info )
    {
        req->handle = hwnd;
        if (!wine_server_call_err( req )) retval = reply->last_active;
    }
    SERVER_END_REQ;
2741
    return retval;
Alexandre Julliard's avatar
Alexandre Julliard committed
2742 2743
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2744

2745 2746 2747 2748 2749 2750 2751
/*******************************************************************
 *           WIN_ListChildren
 *
 * Build an array of the children of a given window. The array must be
 * freed with HeapFree. Returns NULL when no windows are found.
 */
HWND *WIN_ListChildren( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2752
{
2753
    return list_window_children( hwnd, NULL, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
2754
}
2755

Alexandre Julliard's avatar
Alexandre Julliard committed
2756 2757

/*******************************************************************
2758
 *		EnumWindows (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2759
 */
2760
BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
Alexandre Julliard's avatar
Alexandre Julliard committed
2761
{
2762 2763
    HWND *list;
    BOOL ret = TRUE;
2764 2765 2766
    int i;

    USER_CheckNotLock();
Alexandre Julliard's avatar
Alexandre Julliard committed
2767

Alexandre Julliard's avatar
Alexandre Julliard committed
2768
    /* We have to build a list of all windows first, to avoid */
2769 2770
    /* unpleasant side-effects, for instance if the callback */
    /* function changes the Z-order of the windows.          */
Alexandre Julliard's avatar
Alexandre Julliard committed
2771

2772
    if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2773

Alexandre Julliard's avatar
Alexandre Julliard committed
2774
    /* Now call the callback function for every window */
Alexandre Julliard's avatar
Alexandre Julliard committed
2775

2776
    for (i = 0; list[i]; i++)
Alexandre Julliard's avatar
Alexandre Julliard committed
2777 2778
    {
        /* Make sure that the window still exists */
2779 2780
        if (!IsWindow( list[i] )) continue;
        if (!(ret = lpEnumFunc( list[i], lParam ))) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
2781
    }
2782
    HeapFree( GetProcessHeap(), 0, list );
2783
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
2784
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2785 2786


Alexandre Julliard's avatar
Alexandre Julliard committed
2787
/**********************************************************************
2788
 *		EnumThreadWindows (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2789
 */
2790
BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliard's avatar
Alexandre Julliard committed
2791
{
2792
    HWND *list;
2793 2794 2795
    int i;

    USER_CheckNotLock();
2796

2797
    if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2798 2799 2800 2801 2802

    /* Now call the callback function for every window */

    for (i = 0; list[i]; i++)
        if (!func( list[i], lParam )) break;
2803
    HeapFree( GetProcessHeap(), 0, list );
2804
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2805 2806 2807
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2808
/**********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
2809
 *           WIN_EnumChildWindows
Alexandre Julliard's avatar
Alexandre Julliard committed
2810
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
2811
 * Helper function for EnumChildWindows().
Alexandre Julliard's avatar
Alexandre Julliard committed
2812
 */
2813
static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliard's avatar
Alexandre Julliard committed
2814
{
2815 2816
    HWND *childList;
    BOOL ret = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2817

2818
    for ( ; *list; list++)
Alexandre Julliard's avatar
Alexandre Julliard committed
2819
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
2820
        /* Make sure that the window still exists */
2821
        if (!IsWindow( *list )) continue;
Alexandre Julliard's avatar
Alexandre Julliard committed
2822
        /* Build children list first */
2823
        childList = WIN_ListChildren( *list );
2824 2825

        ret = func( *list, lParam );
2826

Alexandre Julliard's avatar
Alexandre Julliard committed
2827 2828 2829
        if (childList)
        {
            if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2830
            HeapFree( GetProcessHeap(), 0, childList );
Alexandre Julliard's avatar
Alexandre Julliard committed
2831
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
2832 2833 2834 2835 2836 2837 2838
        if (!ret) return FALSE;
    }
    return TRUE;
}


/**********************************************************************
2839
 *		EnumChildWindows (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2840
 */
2841
BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
Alexandre Julliard's avatar
Alexandre Julliard committed
2842
{
2843
    HWND *list;
2844
    BOOL ret;
2845 2846

    USER_CheckNotLock();
Alexandre Julliard's avatar
Alexandre Julliard committed
2847

2848
    if (!(list = WIN_ListChildren( parent ))) return FALSE;
2849
    ret = WIN_EnumChildWindows( list, func, lParam );
2850
    HeapFree( GetProcessHeap(), 0, list );
2851
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
2852
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2853 2854


Alexandre Julliard's avatar
Alexandre Julliard committed
2855
/*******************************************************************
2856
 *		AnyPopup (USER.52)
Alexandre Julliard's avatar
Alexandre Julliard committed
2857
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
2858
BOOL16 WINAPI AnyPopup16(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
2859
{
2860
    return AnyPopup();
Alexandre Julliard's avatar
Alexandre Julliard committed
2861 2862 2863 2864
}


/*******************************************************************
2865
 *		AnyPopup (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2866
 */
2867
BOOL WINAPI AnyPopup(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
2868
{
2869
    int i;
2870
    BOOL retvalue;
2871
    HWND *list = WIN_ListChildren( GetDesktopWindow() );
2872 2873 2874

    if (!list) return FALSE;
    for (i = 0; list[i]; i++)
2875
    {
2876
        if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2877
    }
2878
    retvalue = (list[i] != 0);
2879
    HeapFree( GetProcessHeap(), 0, list );
2880
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
2881 2882
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2883 2884

/*******************************************************************
2885
 *		FlashWindow (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2886
 */
2887
BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
Alexandre Julliard's avatar
Alexandre Julliard committed
2888
{
2889
    WND *wndPtr;
Alexandre Julliard's avatar
Alexandre Julliard committed
2890

2891
    TRACE("%p\n", hWnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2892

2893
    if (IsIconic( hWnd ))
Alexandre Julliard's avatar
Alexandre Julliard committed
2894
    {
2895
        RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2896 2897

        wndPtr = WIN_GetPtr(hWnd);
2898
        if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2899 2900 2901 2902 2903 2904 2905 2906
        if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
        {
            wndPtr->flags |= WIN_NCACTIVATED;
        }
        else
        {
            wndPtr->flags &= ~WIN_NCACTIVATED;
        }
2907
        WIN_ReleasePtr( wndPtr );
Alexandre Julliard's avatar
Alexandre Julliard committed
2908 2909 2910 2911
        return TRUE;
    }
    else
    {
2912 2913 2914
        WPARAM wparam;

        wndPtr = WIN_GetPtr(hWnd);
2915
        if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2916 2917
        hWnd = wndPtr->hwndSelf;  /* make it a full handle */

Alexandre Julliard's avatar
Alexandre Julliard committed
2918
        if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2919
        else wparam = (hWnd == GetForegroundWindow());
Alexandre Julliard's avatar
Alexandre Julliard committed
2920

2921
        WIN_ReleasePtr( wndPtr );
2922
        SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
2923 2924
        return wparam;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2925 2926
}

2927 2928 2929 2930 2931 2932 2933 2934
/*******************************************************************
 *		FlashWindowEx (USER32.@)
 */
BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
{
    FIXME("%p\n", pfwi);
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2935

Alexandre Julliard's avatar
Alexandre Julliard committed
2936
/*******************************************************************
2937
 *		GetWindowContextHelpId (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2938
 */
2939
DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
Alexandre Julliard's avatar
Alexandre Julliard committed
2940
{
2941
    DWORD retval;
2942
    WND *wnd = WIN_GetPtr( hwnd );
2943
    if (!wnd || wnd == WND_DESKTOP) return 0;
2944 2945 2946 2947 2948
    if (wnd == WND_OTHER_PROCESS)
    {
        if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
        return 0;
    }
2949
    retval = wnd->helpContext;
2950
    WIN_ReleasePtr( wnd );
2951
    return retval;
Alexandre Julliard's avatar
Alexandre Julliard committed
2952 2953 2954 2955
}


/*******************************************************************
2956
 *		SetWindowContextHelpId (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2957
 */
2958
BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
Alexandre Julliard's avatar
Alexandre Julliard committed
2959
{
2960
    WND *wnd = WIN_GetPtr( hwnd );
2961
    if (!wnd || wnd == WND_DESKTOP) return FALSE;
2962 2963 2964 2965 2966
    if (wnd == WND_OTHER_PROCESS)
    {
        if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
        return 0;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2967
    wnd->helpContext = id;
2968
    WIN_ReleasePtr( wnd );
Alexandre Julliard's avatar
Alexandre Julliard committed
2969 2970 2971 2972
    return TRUE;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2973
/*******************************************************************
2974
 *		DragDetect (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
2975
 */
2976
BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
Alexandre Julliard's avatar
Alexandre Julliard committed
2977
{
2978 2979
    MSG msg;
    RECT rect;
2980 2981
    WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
    WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
Alexandre Julliard's avatar
Alexandre Julliard committed
2982

Alexandre Julliard's avatar
Alexandre Julliard committed
2983 2984
    rect.left = pt.x - wDragWidth;
    rect.right = pt.x + wDragWidth;
Alexandre Julliard's avatar
Alexandre Julliard committed
2985

Alexandre Julliard's avatar
Alexandre Julliard committed
2986 2987
    rect.top = pt.y - wDragHeight;
    rect.bottom = pt.y + wDragHeight;
Alexandre Julliard's avatar
Alexandre Julliard committed
2988

2989
    SetCapture(hWnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2990

Alexandre Julliard's avatar
Alexandre Julliard committed
2991 2992
    while(1)
    {
2993
        while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
Alexandre Julliard's avatar
Alexandre Julliard committed
2994 2995
        {
            if( msg.message == WM_LBUTTONUP )
2996 2997 2998
            {
                ReleaseCapture();
                return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2999 3000
            }
            if( msg.message == WM_MOUSEMOVE )
3001
            {
3002
                POINT tmp;
3003 3004
                tmp.x = (short)LOWORD(msg.lParam);
                tmp.y = (short)HIWORD(msg.lParam);
3005
                if( !PtInRect( &rect, tmp ))
Alexandre Julliard's avatar
Alexandre Julliard committed
3006
                {
3007 3008
                    ReleaseCapture();
                    return 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
3009
                }
3010
            }
Alexandre Julliard's avatar
Alexandre Julliard committed
3011
        }
3012
        WaitMessage();
Alexandre Julliard's avatar
Alexandre Julliard committed
3013 3014
    }
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
3015 3016
}

3017 3018 3019 3020 3021
/******************************************************************************
 *		GetWindowModuleFileNameA (USER32.@)
 */
UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
{
3022
    FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3023 3024 3025 3026 3027 3028 3029
          hwnd, lpszFileName, cchFileNameMax);
    return 0;
}

/******************************************************************************
 *		GetWindowModuleFileNameW (USER32.@)
 */
3030
UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3031
{
3032
    FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3033 3034 3035
          hwnd, lpszFileName, cchFileNameMax);
    return 0;
}
3036 3037 3038

/******************************************************************************
 *              GetWindowInfo (USER32.@)
3039 3040
 *
 * Note: tests show that Windows doesn't check cbSize of the structure.
3041 3042 3043 3044
 */
BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
{
    if (!pwi) return FALSE;
3045 3046 3047 3048 3049 3050
    if (!IsWindow(hwnd)) return FALSE;

    GetWindowRect(hwnd, &pwi->rcWindow);
    GetClientRect(hwnd, &pwi->rcClient);
    /* translate to screen coordinates */
    MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3051

3052 3053
    pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
    pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3054
    pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3055 3056 3057 3058 3059 3060 3061

    pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
    pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;

    pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
    pwi->wCreatorVersion = 0x0400;

3062 3063
    return TRUE;
}
3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074

/******************************************************************************
 *              SwitchDesktop (USER32.@)
 *
 * NOTES: Sets the current input or interactive desktop.
 */
BOOL WINAPI SwitchDesktop( HDESK hDesktop)
{
    FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
    return TRUE;
}
3075 3076 3077 3078 3079 3080 3081

/*****************************************************************************
 *              SetLayeredWindowAttributes (USER32.@)
 */
BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey, 
                                        BYTE bAlpha, DWORD dwFlags )
{
3082
    FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3083 3084
    return TRUE;
}
3085 3086 3087 3088 3089 3090 3091 3092

/*****************************************************************************
 *              UpdateLayeredWindow (USER32.@)
 */
BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
                                 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
                                 DWORD dwFlags)
{
3093 3094 3095 3096 3097 3098 3099
    static int once;
    if (!once)
    {
        once = 1;
        FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
              hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
    }
3100 3101
    return 0;
}
3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125

/* 64bit versions */

#ifdef GetWindowLongPtrW
#undef GetWindowLongPtrW
#endif

#ifdef GetWindowLongPtrA
#undef GetWindowLongPtrA
#endif

#ifdef SetWindowLongPtrW
#undef SetWindowLongPtrW
#endif

#ifdef SetWindowLongPtrA
#undef SetWindowLongPtrA
#endif

/*****************************************************************************
 *              GetWindowLongPtrW (USER32.@)
 */
LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
{
3126
    return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3127 3128 3129 3130 3131 3132 3133
}

/*****************************************************************************
 *              GetWindowLongPtrA (USER32.@)
 */
LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
{
3134
    return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3135 3136 3137 3138 3139 3140 3141
}

/*****************************************************************************
 *              SetWindowLongPtrW (USER32.@)
 */
LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
{
3142
    return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3143 3144 3145 3146 3147 3148 3149
}

/*****************************************************************************
 *              SetWindowLongPtrA (USER32.@)
 */
LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
{
3150
    return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );
3151
}