class.c 36.7 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 * Window classes functions
 *
4 5
 * Copyright 1993, 1996, 2003 Alexandre Julliard
 * Copyright 1998 Juergen Schmied (jsch)
Alexandre Julliard's avatar
Alexandre Julliard committed
6
 *
7 8 9 10 11 12 13 14 15 16 17 18
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
20
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
21

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

25
#include <assert.h>
26
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
27 28
#include <stdlib.h>
#include <string.h>
29

30 31
#include "winerror.h"
#include "windef.h"
32
#include "winbase.h"
33 34
#include "wingdi.h"
#include "wine/unicode.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
35
#include "win.h"
36
#include "user_private.h"
37
#include "controls.h"
38 39
#include "wine/server.h"
#include "wine/list.h"
40
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
41

42
WINE_DEFAULT_DEBUG_CHANNEL(class);
43

44 45
#define MAX_ATOM_LEN 255 /* from dlls/kernel32/atom.c */

46 47
typedef struct tagCLASS
{
48
    struct list      entry;         /* Entry in class list */
49
    UINT             style;         /* Class style */
50
    BOOL             local;         /* Local class? */
51
    WNDPROC          winproc;       /* Window procedure */
52 53 54
    INT              cbClsExtra;    /* Class extra bytes */
    INT              cbWndExtra;    /* Window extra bytes */
    LPWSTR           menuName;      /* Default menu name (Unicode followed by ASCII) */
55
    struct dce      *dce;           /* Opaque pointer to class DCE */
56 57 58 59 60 61
    HINSTANCE        hInstance;     /* Module that created the task */
    HICON            hIcon;         /* Default icon */
    HICON            hIconSm;       /* Default small icon */
    HCURSOR          hCursor;       /* Default cursor */
    HBRUSH           hbrBackground; /* Default background */
    ATOM             atomName;      /* Name of the class */
62
    WCHAR            name[MAX_ATOM_LEN + 1];
63 64
} CLASS;

65 66 67
static struct list class_list = LIST_INIT( class_list );

#define CLASS_OTHER_PROCESS ((CLASS *)1)
Alexandre Julliard's avatar
Alexandre Julliard committed
68

69 70 71
/***********************************************************************
 *           get_class_ptr
 */
72
static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
73
{
74
    WND *ptr = WIN_GetPtr( hwnd );
75

76
    if (ptr)
77
    {
78
        if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP) return ptr->class;
79
        if (!write_access) return CLASS_OTHER_PROCESS;
80

81 82
        /* modifying classes in other processes is not allowed */
        if (ptr == WND_DESKTOP || IsWindow( hwnd ))
83
        {
84 85
            SetLastError( ERROR_ACCESS_DENIED );
            return NULL;
86 87
        }
    }
88 89
    SetLastError( ERROR_INVALID_WINDOW_HANDLE );
    return NULL;
90 91 92 93 94 95
}


/***********************************************************************
 *           release_class_ptr
 */
96
static inline void release_class_ptr( CLASS *ptr )
97 98 99 100
{
    USER_Unlock();
}

Alexandre Julliard's avatar
Alexandre Julliard committed
101

102 103 104
/***********************************************************************
 *           get_int_atom_value
 */
105
ATOM get_int_atom_value( LPCWSTR name )
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
{
    UINT ret = 0;

    if (IS_INTRESOURCE(name)) return LOWORD(name);
    if (*name++ != '#') return 0;
    while (*name)
    {
        if (*name < '0' || *name > '9') return 0;
        ret = ret * 10 + *name++ - '0';
        if (ret > 0xffff) return 0;
    }
    return ret;
}


121 122 123 124 125
/***********************************************************************
 *           set_server_info
 *
 * Set class info with the wine server.
 */
126
static BOOL set_server_info( HWND hwnd, INT offset, LONG_PTR newval, UINT size )
127 128 129 130 131
{
    BOOL ret;

    SERVER_START_REQ( set_class_info )
    {
132
        req->window = wine_server_user_handle( hwnd );
133 134 135 136 137
        req->extra_offset = -1;
        switch(offset)
        {
        case GCW_ATOM:
            req->flags = SET_CLASS_ATOM;
138
            req->atom = LOWORD(newval);
139 140 141 142 143 144 145 146
        case GCL_STYLE:
            req->flags = SET_CLASS_STYLE;
            req->style = newval;
            break;
        case GCL_CBWNDEXTRA:
            req->flags = SET_CLASS_WINEXTRA;
            req->win_extra = newval;
            break;
147
        case GCLP_HMODULE:
148
            req->flags = SET_CLASS_INSTANCE;
149
            req->instance = wine_server_client_ptr( (void *)newval );
150 151 152 153 154
            break;
        default:
            assert( offset >= 0 );
            req->flags = SET_CLASS_EXTRA;
            req->extra_offset = offset;
155 156 157 158 159 160 161 162
            req->extra_size = size;
            if ( size == sizeof(LONG) )
            {
                LONG newlong = newval;
                memcpy( &req->extra_value, &newlong, sizeof(LONG) );
            }
            else
                memcpy( &req->extra_value, &newval, sizeof(LONG_PTR) );
163 164 165 166 167 168 169 170 171
            break;
        }
        ret = !wine_server_call_err( req );
    }
    SERVER_END_REQ;
    return ret;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
172 173 174 175 176
/***********************************************************************
 *           CLASS_GetMenuNameA
 *
 * Get the menu name as a ASCII string.
 */
177
static inline LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
Alexandre Julliard's avatar
Alexandre Julliard committed
178
{
179 180
    if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
    return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
Alexandre Julliard's avatar
Alexandre Julliard committed
181 182 183 184 185 186 187 188
}


/***********************************************************************
 *           CLASS_GetMenuNameW
 *
 * Get the menu name as a Unicode string.
 */
189
static inline LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
Alexandre Julliard's avatar
Alexandre Julliard committed
190
{
191
    return classPtr->menuName;
Alexandre Julliard's avatar
Alexandre Julliard committed
192 193 194 195 196 197 198 199 200 201
}


/***********************************************************************
 *           CLASS_SetMenuNameA
 *
 * Set the menu name in a class structure by copying the string.
 */
static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
{
202
    if (HIWORD(classPtr->menuName)) HeapFree( GetProcessHeap(), 0, classPtr->menuName );
203 204 205 206
    if (HIWORD(name))
    {
        DWORD lenA = strlen(name) + 1;
        DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
207
        classPtr->menuName = HeapAlloc( GetProcessHeap(), 0, lenA + lenW*sizeof(WCHAR) );
208 209 210 211
        MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
        memcpy( classPtr->menuName + lenW, name, lenA );
    }
    else classPtr->menuName = (LPWSTR)name;
Alexandre Julliard's avatar
Alexandre Julliard committed
212 213 214 215 216 217 218 219 220 221
}


/***********************************************************************
 *           CLASS_SetMenuNameW
 *
 * Set the menu name in a class structure by copying the string.
 */
static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
{
222
    if (HIWORD(classPtr->menuName)) HeapFree( GetProcessHeap(), 0, classPtr->menuName );
223
    if (HIWORD(name))
224
    {
225 226
        DWORD lenW = strlenW(name) + 1;
        DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
227
        classPtr->menuName = HeapAlloc( GetProcessHeap(), 0, lenA + lenW*sizeof(WCHAR) );
228 229 230
        memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
        WideCharToMultiByte( CP_ACP, 0, name, lenW,
                             (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
231
    }
232
    else classPtr->menuName = (LPWSTR)name;
233 234 235
}


Alexandre Julliard's avatar
Alexandre Julliard committed
236 237 238 239 240
/***********************************************************************
 *           CLASS_FreeClass
 *
 * Free a class structure.
 */
241
static void CLASS_FreeClass( CLASS *classPtr )
Alexandre Julliard's avatar
Alexandre Julliard committed
242
{
243
    TRACE("%p\n", classPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
244

245
    USER_Lock();
246

247
    if (classPtr->dce) free_dce( classPtr->dce, 0 );
248 249 250 251 252 253
    list_remove( &classPtr->entry );
    if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
        DeleteObject( classPtr->hbrBackground );
    HeapFree( GetProcessHeap(), 0, classPtr->menuName );
    HeapFree( GetProcessHeap(), 0, classPtr );
    USER_Unlock();
Alexandre Julliard's avatar
Alexandre Julliard committed
254 255 256
}


Alexandre Julliard's avatar
Alexandre Julliard committed
257
/***********************************************************************
258
 *           CLASS_FindClass
Alexandre Julliard's avatar
Alexandre Julliard committed
259
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
260
 * Return a pointer to the class.
Alexandre Julliard's avatar
Alexandre Julliard committed
261
 * hinstance has been normalized by the caller.
Alexandre Julliard's avatar
Alexandre Julliard committed
262
 */
263
static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance )
264
{
265
    struct list *ptr;
266
    ATOM atom = get_int_atom_value( name );
Alexandre Julliard's avatar
Alexandre Julliard committed
267

268 269
    USER_Lock();

270
    LIST_FOR_EACH( ptr, &class_list )
Alexandre Julliard's avatar
Alexandre Julliard committed
271
    {
272
        CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
273 274 275 276 277 278 279 280
        if (atom)
        {
            if (class->atomName != atom) continue;
        }
        else
        {
            if (!name || strcmpiW( class->name, name )) continue;
        }
281
        if (!hinstance || !class->local || class->hInstance == hinstance)
Alexandre Julliard's avatar
Alexandre Julliard committed
282
        {
283
            TRACE("%s %p -> %p\n", debugstr_w(name), hinstance, class);
Alexandre Julliard's avatar
Alexandre Julliard committed
284 285
            return class;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
286
    }
287
    USER_Unlock();
288
    TRACE("%s %p -> not found\n", debugstr_w(name), hinstance);
289
    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
290 291
}

Alexandre Julliard's avatar
Alexandre Julliard committed
292

Alexandre Julliard's avatar
Alexandre Julliard committed
293
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
294 295 296
 *           CLASS_RegisterClass
 *
 * The real RegisterClass() functionality.
Alexandre Julliard's avatar
Alexandre Julliard committed
297
 */
298
static CLASS *CLASS_RegisterClass( LPCWSTR name, HINSTANCE hInstance, BOOL local,
299
                                   DWORD style, INT classExtra, INT winExtra )
Alexandre Julliard's avatar
Alexandre Julliard committed
300
{
Alexandre Julliard's avatar
Alexandre Julliard committed
301
    CLASS *classPtr;
302
    BOOL ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
303

304 305
    TRACE("name=%s hinst=%p style=0x%x clExtr=0x%x winExtr=0x%x\n",
          debugstr_w(name), hInstance, style, classExtra, winExtra );
Alexandre Julliard's avatar
Alexandre Julliard committed
306 307 308

    /* Fix the extra bytes value */

309
    if (classExtra > 40)  /* Extra bytes are limited to 40 in Win32 */
310
        WARN("Class extra bytes %d is > 40\n", classExtra);
311
    if (winExtra > 40)    /* Extra bytes are limited to 40 in Win32 */
312
        WARN("Win extra bytes %d is > 40\n", winExtra );
Alexandre Julliard's avatar
Alexandre Julliard committed
313

314
    classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
315
    if (!classPtr) return NULL;
316

317 318 319 320
    classPtr->atomName = get_int_atom_value( name );
    if (!classPtr->atomName && name) strcpyW( classPtr->name, name );
    else GlobalGetAtomNameW( classPtr->atomName, classPtr->name, sizeof(classPtr->name)/sizeof(WCHAR) );

321 322
    SERVER_START_REQ( create_class )
    {
323 324
        req->local      = local;
        req->style      = style;
325
        req->instance   = wine_server_client_ptr( hInstance );
326 327
        req->extra      = classExtra;
        req->win_extra  = winExtra;
328
        req->client_ptr = wine_server_client_ptr( classPtr );
329 330
        req->atom       = classPtr->atomName;
        if (!req->atom && name) wine_server_add_data( req, name, strlenW(name) * sizeof(WCHAR) );
331
        ret = !wine_server_call_err( req );
332
        classPtr->atomName = reply->atom;
333 334 335 336 337 338 339 340
    }
    SERVER_END_REQ;
    if (!ret)
    {
        HeapFree( GetProcessHeap(), 0, classPtr );
        return NULL;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
341
    classPtr->style       = style;
342
    classPtr->local       = local;
Alexandre Julliard's avatar
Alexandre Julliard committed
343 344 345
    classPtr->cbWndExtra  = winExtra;
    classPtr->cbClsExtra  = classExtra;
    classPtr->hInstance   = hInstance;
Alexandre Julliard's avatar
Alexandre Julliard committed
346

347
    /* Other non-null values must be set by caller */
Alexandre Julliard's avatar
Alexandre Julliard committed
348

349
    USER_Lock();
350 351
    if (local) list_add_head( &class_list, &classPtr->entry );
    else list_add_tail( &class_list, &classPtr->entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
352 353 354 355
    return classPtr;
}


356
/***********************************************************************
357
 *           register_builtin
358 359 360 361
 *
 * Register a builtin control class.
 * This allows having both ASCII and Unicode winprocs for the same class.
 */
362
static void register_builtin( const struct builtin_class_descr *descr )
363 364 365
{
    CLASS *classPtr;

366
    if (!(classPtr = CLASS_RegisterClass( descr->name, user32_module, FALSE,
367
                                          descr->style, 0, descr->extra ))) return;
368

369
    classPtr->hCursor       = LoadCursorA( 0, (LPSTR)descr->cursor );
370
    classPtr->hbrBackground = descr->brush;
371
    classPtr->winproc       = BUILTIN_WINPROC( descr->proc );
372
    release_class_ptr( classPtr );
373 374 375
}


376 377 378
/***********************************************************************
 *           CLASS_RegisterBuiltinClasses
 */
379
void CLASS_RegisterBuiltinClasses(void)
380
{
381
    register_builtin( &DESKTOP_builtin_class );
382 383 384 385
    register_builtin( &BUTTON_builtin_class );
    register_builtin( &COMBO_builtin_class );
    register_builtin( &COMBOLBOX_builtin_class );
    register_builtin( &DIALOG_builtin_class );
386
    register_builtin( &EDIT_builtin_class );
387 388 389 390
    register_builtin( &ICONTITLE_builtin_class );
    register_builtin( &LISTBOX_builtin_class );
    register_builtin( &MDICLIENT_builtin_class );
    register_builtin( &MENU_builtin_class );
391
    register_builtin( &MESSAGE_builtin_class );
392 393 394 395 396
    register_builtin( &SCROLL_builtin_class );
    register_builtin( &STATIC_builtin_class );
}


397
/***********************************************************************
398
 *           get_class_winproc
399
 */
400
WNDPROC get_class_winproc( CLASS *class )
401
{
402
    return class->winproc;
403 404 405
}


406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
/***********************************************************************
 *           get_class_dce
 */
struct dce *get_class_dce( CLASS *class )
{
    return class->dce;
}


/***********************************************************************
 *           set_class_dce
 */
struct dce *set_class_dce( CLASS *class, struct dce *dce )
{
    if (class->dce) return class->dce;  /* already set, don't change it */
    class->dce = dce;
    return dce;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
426
/***********************************************************************
427
 *		RegisterClassA (USER32.@)
428 429 430
 *
 * Register a window class.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
431 432 433
 * RETURNS
 *	>0: Unique identifier
 *	0: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
434
 */
435
ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
436
{
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
    WNDCLASSEXA wcex;

    wcex.cbSize        = sizeof(wcex);
    wcex.style         = wc->style;
    wcex.lpfnWndProc   = wc->lpfnWndProc;
    wcex.cbClsExtra    = wc->cbClsExtra;
    wcex.cbWndExtra    = wc->cbWndExtra;
    wcex.hInstance     = wc->hInstance;
    wcex.hIcon         = wc->hIcon;
    wcex.hCursor       = wc->hCursor;
    wcex.hbrBackground = wc->hbrBackground;
    wcex.lpszMenuName  = wc->lpszMenuName;
    wcex.lpszClassName = wc->lpszClassName;
    wcex.hIconSm       = 0;
    return RegisterClassExA( &wcex );
Alexandre Julliard's avatar
Alexandre Julliard committed
452
}
Alexandre Julliard's avatar
Alexandre Julliard committed
453

Alexandre Julliard's avatar
Alexandre Julliard committed
454 455

/***********************************************************************
456
 *		RegisterClassW (USER32.@)
457 458
 *
 * See RegisterClassA.
Alexandre Julliard's avatar
Alexandre Julliard committed
459
 */
460
ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
Alexandre Julliard's avatar
Alexandre Julliard committed
461
{
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
    WNDCLASSEXW wcex;

    wcex.cbSize        = sizeof(wcex);
    wcex.style         = wc->style;
    wcex.lpfnWndProc   = wc->lpfnWndProc;
    wcex.cbClsExtra    = wc->cbClsExtra;
    wcex.cbWndExtra    = wc->cbWndExtra;
    wcex.hInstance     = wc->hInstance;
    wcex.hIcon         = wc->hIcon;
    wcex.hCursor       = wc->hCursor;
    wcex.hbrBackground = wc->hbrBackground;
    wcex.lpszMenuName  = wc->lpszMenuName;
    wcex.lpszClassName = wc->lpszClassName;
    wcex.hIconSm       = 0;
    return RegisterClassExW( &wcex );
Alexandre Julliard's avatar
Alexandre Julliard committed
477 478 479 480
}


/***********************************************************************
481
 *		RegisterClassExA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
482
 */
483
ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
Alexandre Julliard's avatar
Alexandre Julliard committed
484 485 486
{
    ATOM atom;
    CLASS *classPtr;
487 488
    HINSTANCE instance;

489 490
    if (wc->cbClsExtra < 0 || wc->cbWndExtra < 0 ||
        wc->hInstance == user32_module)  /* we can't register a class for user32 */
491
    {
492 493
         SetLastError( ERROR_INVALID_PARAMETER );
         return 0;
494 495
    }
    if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
Alexandre Julliard's avatar
Alexandre Julliard committed
496

497 498 499
    if (!IS_INTRESOURCE(wc->lpszClassName))
    {
        WCHAR name[MAX_ATOM_LEN + 1];
500

501 502 503 504 505 506 507 508 509 510 511 512
        if (!MultiByteToWideChar( CP_ACP, 0, wc->lpszClassName, -1, name, MAX_ATOM_LEN + 1 )) return 0;
        classPtr = CLASS_RegisterClass( name, instance, !(wc->style & CS_GLOBALCLASS),
                                        wc->style, wc->cbClsExtra, wc->cbWndExtra );
    }
    else
    {
        classPtr = CLASS_RegisterClass( (LPCWSTR)wc->lpszClassName, instance,
                                        !(wc->style & CS_GLOBALCLASS), wc->style,
                                        wc->cbClsExtra, wc->cbWndExtra );
    }
    if (!classPtr) return 0;
    atom = classPtr->atomName;
Alexandre Julliard's avatar
Alexandre Julliard committed
513

514 515
    TRACE("name=%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
          debugstr_a(wc->lpszClassName), atom, wc->lpfnWndProc, instance, wc->hbrBackground,
516
          wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
517

518 519 520 521
    classPtr->hIcon         = wc->hIcon;
    classPtr->hIconSm       = wc->hIconSm;
    classPtr->hCursor       = wc->hCursor;
    classPtr->hbrBackground = wc->hbrBackground;
522
    classPtr->winproc       = WINPROC_AllocProc( wc->lpfnWndProc, FALSE );
Alexandre Julliard's avatar
Alexandre Julliard committed
523
    CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
524
    release_class_ptr( classPtr );
Alexandre Julliard's avatar
Alexandre Julliard committed
525 526 527 528 529
    return atom;
}


/***********************************************************************
530
 *		RegisterClassExW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
531
 */
532
ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
Alexandre Julliard's avatar
Alexandre Julliard committed
533 534 535
{
    ATOM atom;
    CLASS *classPtr;
536 537
    HINSTANCE instance;

538 539
    if (wc->cbClsExtra < 0 || wc->cbWndExtra < 0 ||
        wc->hInstance == user32_module)  /* we can't register a class for user32 */
540
    {
541 542
         SetLastError( ERROR_INVALID_PARAMETER );
         return 0;
543 544
    }
    if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
Alexandre Julliard's avatar
Alexandre Julliard committed
545

546
    if (!(classPtr = CLASS_RegisterClass( wc->lpszClassName, instance, !(wc->style & CS_GLOBALCLASS),
547
                                          wc->style, wc->cbClsExtra, wc->cbWndExtra )))
Alexandre Julliard's avatar
Alexandre Julliard committed
548 549
        return 0;

550 551 552 553
    atom = classPtr->atomName;

    TRACE("name=%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
          debugstr_w(wc->lpszClassName), atom, wc->lpfnWndProc, instance, wc->hbrBackground,
554
          wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
555

556 557 558 559
    classPtr->hIcon         = wc->hIcon;
    classPtr->hIconSm       = wc->hIconSm;
    classPtr->hCursor       = wc->hCursor;
    classPtr->hbrBackground = wc->hbrBackground;
560
    classPtr->winproc       = WINPROC_AllocProc( wc->lpfnWndProc, TRUE );
Alexandre Julliard's avatar
Alexandre Julliard committed
561
    CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
562
    release_class_ptr( classPtr );
Alexandre Julliard's avatar
Alexandre Julliard committed
563
    return atom;
Alexandre Julliard's avatar
Alexandre Julliard committed
564 565 566
}


Alexandre Julliard's avatar
Alexandre Julliard committed
567
/***********************************************************************
568
 *		UnregisterClassA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
569
 */
570
BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
571
{
572 573 574 575 576 577 578 579 580
    if (!IS_INTRESOURCE(className))
    {
        WCHAR name[MAX_ATOM_LEN + 1];

        if (!MultiByteToWideChar( CP_ACP, 0, className, -1, name, MAX_ATOM_LEN + 1 ))
            return FALSE;
        return UnregisterClassW( name, hInstance );
    }
    return UnregisterClassW( (LPCWSTR)className, hInstance );
Alexandre Julliard's avatar
Alexandre Julliard committed
581
}
Alexandre Julliard's avatar
Alexandre Julliard committed
582 583

/***********************************************************************
584
 *		UnregisterClassW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
585
 */
586
BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
587
{
588
    CLASS *classPtr = NULL;
589

590
    SERVER_START_REQ( destroy_class )
591
    {
592
        req->instance = wine_server_client_ptr( hInstance );
593 594
        if (!(req->atom = get_int_atom_value(className)) && className)
            wine_server_add_data( req, className, strlenW(className) * sizeof(WCHAR) );
595
        if (!wine_server_call_err( req )) classPtr = wine_server_get_ptr( reply->client_ptr );
596
    }
597 598 599 600
    SERVER_END_REQ;

    if (classPtr) CLASS_FreeClass( classPtr );
    return (classPtr != NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
601 602
}

Alexandre Julliard's avatar
Alexandre Julliard committed
603 604

/***********************************************************************
605
 *		GetClassWord (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
606
 */
607
WORD WINAPI GetClassWord( HWND hwnd, INT offset )
Alexandre Julliard's avatar
Alexandre Julliard committed
608
{
609
    CLASS *class;
610
    WORD retvalue = 0;
611 612 613

    if (offset < 0) return GetClassLongA( hwnd, offset );

614
    if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
615

616 617 618 619
    if (class == CLASS_OTHER_PROCESS)
    {
        SERVER_START_REQ( set_class_info )
        {
620
            req->window = wine_server_user_handle( hwnd );
621 622 623 624 625 626 627 628 629 630
            req->flags = 0;
            req->extra_offset = offset;
            req->extra_size = sizeof(retvalue);
            if (!wine_server_call_err( req ))
                memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
        }
        SERVER_END_REQ;
        return retvalue;
    }

631
    if (offset <= class->cbClsExtra - sizeof(WORD))
632
        memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
633 634 635
    else
        SetLastError( ERROR_INVALID_INDEX );
    release_class_ptr( class );
636
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
637 638 639
}


Alexandre Julliard's avatar
Alexandre Julliard committed
640
/***********************************************************************
641 642 643
 *             CLASS_GetClassLong
 *
 * Implementation of GetClassLong(Ptr)A/W
Alexandre Julliard's avatar
Alexandre Julliard committed
644
 */
645 646
static ULONG_PTR CLASS_GetClassLong( HWND hwnd, INT offset, UINT size,
                                     BOOL unicode )
Alexandre Julliard's avatar
Alexandre Julliard committed
647
{
648
    CLASS *class;
649
    ULONG_PTR retvalue = 0;
650

651
    if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
652

653 654 655 656
    if (class == CLASS_OTHER_PROCESS)
    {
        SERVER_START_REQ( set_class_info )
        {
657
            req->window = wine_server_user_handle( hwnd );
658 659
            req->flags = 0;
            req->extra_offset = (offset >= 0) ? offset : -1;
660
            req->extra_size = (offset >= 0) ? size : 0;
661 662 663 664
            if (!wine_server_call_err( req ))
            {
                switch(offset)
                {
665 666 667 668 669 670
                case GCLP_HBRBACKGROUND:
                case GCLP_HCURSOR:
                case GCLP_HICON:
                case GCLP_HICONSM:
                case GCLP_WNDPROC:
                case GCLP_MENUNAME:
671 672
                    FIXME( "offset %d (%s) not supported on other process window %p\n",
			   offset, SPY_GetClassLongOffsetName(offset), hwnd );
673 674 675 676 677 678 679 680 681 682 683
                    SetLastError( ERROR_INVALID_HANDLE );
                    break;
                case GCL_STYLE:
                    retvalue = reply->old_style;
                    break;
                case GCL_CBWNDEXTRA:
                    retvalue = reply->old_win_extra;
                    break;
                case GCL_CBCLSEXTRA:
                    retvalue = reply->old_extra;
                    break;
684
                case GCLP_HMODULE:
685
                    retvalue = (ULONG_PTR)wine_server_get_ptr( reply->old_instance );
686 687 688 689 690
                    break;
                case GCW_ATOM:
                    retvalue = reply->old_atom;
                    break;
                default:
691 692 693 694 695 696 697 698 699 700 701 702
                    if (offset >= 0)
                    {
                        if (size == sizeof(DWORD))
                        {
                            DWORD retdword;
                            memcpy( &retdword, &reply->old_extra_value, sizeof(DWORD) );
                            retvalue = retdword;
                        }
                        else
                            memcpy( &retvalue, &reply->old_extra_value,
                                    sizeof(ULONG_PTR) );
                    }
703 704 705 706 707 708 709 710 711
                    else SetLastError( ERROR_INVALID_INDEX );
                    break;
                }
            }
        }
        SERVER_END_REQ;
        return retvalue;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
712 713
    if (offset >= 0)
    {
714 715 716 717 718 719 720 721 722 723 724
        if (offset <= class->cbClsExtra - size)
        {
            if (size == sizeof(DWORD))
            {
                DWORD retdword;
                memcpy( &retdword, (char *)(class + 1) + offset, sizeof(DWORD) );
                retvalue = retdword;
            }
            else
                memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(ULONG_PTR) );
        }
725 726 727 728
        else
            SetLastError( ERROR_INVALID_INDEX );
        release_class_ptr( class );
        return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
729
    }
730

Alexandre Julliard's avatar
Alexandre Julliard committed
731 732
    switch(offset)
    {
733
    case GCLP_HBRBACKGROUND:
734
        retvalue = (ULONG_PTR)class->hbrBackground;
735
        break;
736
    case GCLP_HCURSOR:
737
        retvalue = (ULONG_PTR)class->hCursor;
738
        break;
739
    case GCLP_HICON:
740
        retvalue = (ULONG_PTR)class->hIcon;
741
        break;
742
    case GCLP_HICONSM:
743
        retvalue = (ULONG_PTR)class->hIconSm;
744 745
        break;
    case GCL_STYLE:
746
        retvalue = class->style;
747 748
        break;
    case GCL_CBWNDEXTRA:
749
        retvalue = class->cbWndExtra;
750 751
        break;
    case GCL_CBCLSEXTRA:
752
        retvalue = class->cbClsExtra;
753
        break;
754
    case GCLP_HMODULE:
755
        retvalue = (ULONG_PTR)class->hInstance;
756
        break;
757
    case GCLP_WNDPROC:
758
        retvalue = (ULONG_PTR)WINPROC_GetProc( class->winproc, unicode );
759
        break;
760
    case GCLP_MENUNAME:
761 762 763 764 765
        retvalue = (ULONG_PTR)CLASS_GetMenuNameW( class );
        if (unicode)
            retvalue = (ULONG_PTR)CLASS_GetMenuNameW( class );
        else
            retvalue = (ULONG_PTR)CLASS_GetMenuNameA( class );
766 767
        break;
    case GCW_ATOM:
768
        retvalue = class->atomName;
769 770 771 772
        break;
    default:
        SetLastError( ERROR_INVALID_INDEX );
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
773
    }
774
    release_class_ptr( class );
775
    return retvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
776 777 778 779
}


/***********************************************************************
780
 *		GetClassLongW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
781
 */
782
DWORD WINAPI GetClassLongW( HWND hwnd, INT offset )
Alexandre Julliard's avatar
Alexandre Julliard committed
783
{
784 785
    return CLASS_GetClassLong( hwnd, offset, sizeof(DWORD), TRUE );
}
786

787

788

789 790 791 792 793 794
/***********************************************************************
 *		GetClassLongA (USER32.@)
 */
DWORD WINAPI GetClassLongA( HWND hwnd, INT offset )
{
    return CLASS_GetClassLong( hwnd, offset, sizeof(DWORD), FALSE );
Alexandre Julliard's avatar
Alexandre Julliard committed
795 796 797
}


Alexandre Julliard's avatar
Alexandre Julliard committed
798
/***********************************************************************
799
 *		SetClassWord (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
800
 */
801
WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
Alexandre Julliard's avatar
Alexandre Julliard committed
802
{
803
    CLASS *class;
Alexandre Julliard's avatar
Alexandre Julliard committed
804
    WORD retval = 0;
805 806 807

    if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );

808
    if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
809

810
    SERVER_START_REQ( set_class_info )
Alexandre Julliard's avatar
Alexandre Julliard committed
811
    {
812
        req->window = wine_server_user_handle( hwnd );
813 814 815 816 817 818 819 820 821 822
        req->flags = SET_CLASS_EXTRA;
        req->extra_offset = offset;
        req->extra_size = sizeof(newval);
        memcpy( &req->extra_value, &newval, sizeof(newval) );
        if (!wine_server_call_err( req ))
        {
            void *ptr = (char *)(class + 1) + offset;
            memcpy( &retval, ptr, sizeof(retval) );
            memcpy( ptr, &newval, sizeof(newval) );
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
823
    }
824
    SERVER_END_REQ;
825
    release_class_ptr( class );
Alexandre Julliard's avatar
Alexandre Julliard committed
826 827 828 829 830
    return retval;
}


/***********************************************************************
831 832 833
 *             CLASS_SetClassLong
 *
 * Implementation of SetClassLong(Ptr)A/W
Alexandre Julliard's avatar
Alexandre Julliard committed
834
 */
835 836
static ULONG_PTR CLASS_SetClassLong( HWND hwnd, INT offset, LONG_PTR newval,
                                     UINT size, BOOL unicode )
Alexandre Julliard's avatar
Alexandre Julliard committed
837
{
838
    CLASS *class;
839
    ULONG_PTR retval = 0;
840

841
    if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
842

Alexandre Julliard's avatar
Alexandre Julliard committed
843 844
    if (offset >= 0)
    {
845
        if (set_server_info( hwnd, offset, newval, size ))
Alexandre Julliard's avatar
Alexandre Julliard committed
846
        {
847
            void *ptr = (char *)(class + 1) + offset;
848 849 850 851 852 853 854 855 856 857 858 859 860
            if ( size == sizeof(LONG) )
            {
                DWORD retdword;
                LONG newlong = newval;
                memcpy( &retdword, ptr, sizeof(DWORD) );
                memcpy( ptr, &newlong, sizeof(LONG) );
                retval = retdword;
            }
            else
            {
                memcpy( &retval, ptr, sizeof(ULONG_PTR) );
                memcpy( ptr, &newval, sizeof(LONG_PTR) );
            }
Alexandre Julliard's avatar
Alexandre Julliard committed
861 862
        }
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
863 864
    else switch(offset)
    {
865
    case GCLP_MENUNAME:
866 867 868 869
        if ( unicode )
            CLASS_SetMenuNameW( class, (LPCWSTR)newval );
        else
            CLASS_SetMenuNameA( class, (LPCSTR)newval );
870 871
        retval = 0;  /* Old value is now meaningless anyway */
        break;
872
    case GCLP_WNDPROC:
873
        retval = (ULONG_PTR)WINPROC_GetProc( class->winproc, unicode );
874
        class->winproc = WINPROC_AllocProc( (WNDPROC)newval, unicode );
875
        break;
876
    case GCLP_HBRBACKGROUND:
877
        retval = (ULONG_PTR)class->hbrBackground;
878
        class->hbrBackground = (HBRUSH)newval;
879
        break;
880
    case GCLP_HCURSOR:
881
        retval = (ULONG_PTR)class->hCursor;
882
        class->hCursor = (HCURSOR)newval;
883
        break;
884
    case GCLP_HICON:
885
        retval = (ULONG_PTR)class->hIcon;
886
        class->hIcon = (HICON)newval;
887
        break;
888
    case GCLP_HICONSM:
889
        retval = (ULONG_PTR)class->hIconSm;
890
        class->hIconSm = (HICON)newval;
891 892
        break;
    case GCL_STYLE:
893 894
        if (!set_server_info( hwnd, offset, newval, size )) break;
        retval = class->style;
895 896 897
        class->style = newval;
        break;
    case GCL_CBWNDEXTRA:
898 899
        if (!set_server_info( hwnd, offset, newval, size )) break;
        retval = class->cbWndExtra;
900 901
        class->cbWndExtra = newval;
        break;
902
    case GCLP_HMODULE:
903 904
        if (!set_server_info( hwnd, offset, newval, size )) break;
        retval = (ULONG_PTR)class->hInstance;
905
        class->hInstance = (HINSTANCE)newval;
906 907
        break;
    case GCW_ATOM:
908 909
        if (!set_server_info( hwnd, offset, newval, size )) break;
        retval = class->atomName;
910
        class->atomName = newval;
911
        GlobalGetAtomNameW( newval, class->name, sizeof(class->name)/sizeof(WCHAR) );
912
        break;
913 914 915
    case GCL_CBCLSEXTRA:  /* cannot change this one */
        SetLastError( ERROR_INVALID_PARAMETER );
        break;
916 917 918
    default:
        SetLastError( ERROR_INVALID_INDEX );
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
919
    }
920
    release_class_ptr( class );
Alexandre Julliard's avatar
Alexandre Julliard committed
921 922
    return retval;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
923 924 925


/***********************************************************************
926
 *		SetClassLongW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
927
 */
928
DWORD WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
Alexandre Julliard's avatar
Alexandre Julliard committed
929
{
930 931
    return CLASS_SetClassLong( hwnd, offset, newval, sizeof(LONG), TRUE );
}
932 933


934 935 936 937 938 939
/***********************************************************************
 *		SetClassLongA (USER32.@)
 */
DWORD WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
{
    return CLASS_SetClassLong( hwnd, offset, newval, sizeof(LONG), FALSE );
Alexandre Julliard's avatar
Alexandre Julliard committed
940 941
}

Alexandre Julliard's avatar
Alexandre Julliard committed
942

Alexandre Julliard's avatar
Alexandre Julliard committed
943
/***********************************************************************
944
 *		GetClassNameA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
945
 */
946
INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
947
{
948 949
    WCHAR tmpbuf[MAX_ATOM_LEN + 1];
    DWORD len;
950 951

    if (count <= 0) return 0;
952 953 954 955
    if (!GetClassNameW( hwnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0;
    RtlUnicodeToMultiByteN( buffer, count - 1, &len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) );
    buffer[len] = 0;
    return len;
Alexandre Julliard's avatar
Alexandre Julliard committed
956 957 958 959
}


/***********************************************************************
960
 *		GetClassNameW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
961
 */
962
INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
963
{
964
    CLASS *class;
965
    INT ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
966

967 968 969 970
    TRACE("%p %p %d\n", hwnd, buffer, count);

    if (count <= 0) return 0;

971 972 973
    if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;

    if (class == CLASS_OTHER_PROCESS)
974
    {
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
        WCHAR tmpbuf[MAX_ATOM_LEN + 1];

        ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), tmpbuf, MAX_ATOM_LEN + 1 );
        if (ret)
        {
            ret = min(count - 1, ret);
            memcpy(buffer, tmpbuf, ret * sizeof(WCHAR));
            buffer[ret] = 0;
        }
    }
    else
    {
        lstrcpynW( buffer, class->name, count );
        release_class_ptr( class );
        ret = strlenW( buffer );
990
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
991
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
992 993 994
}


995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
/***********************************************************************
 *		RealGetWindowClassA (USER32.@)
 */
UINT WINAPI RealGetWindowClassA( HWND hwnd, LPSTR buffer, UINT count )
{
    return GetClassNameA( hwnd, buffer, count );
}


/***********************************************************************
 *		RealGetWindowClassW (USER32.@)
 */
UINT WINAPI RealGetWindowClassW( HWND hwnd, LPWSTR buffer, UINT count )
{
    return GetClassNameW( hwnd, buffer, count );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1013
/***********************************************************************
1014
 *		GetClassInfoA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1015
 */
1016
BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name, WNDCLASSA *wc )
Alexandre Julliard's avatar
Alexandre Julliard committed
1017
{
1018 1019
    WNDCLASSEXA wcex;
    UINT ret = GetClassInfoExA( hInstance, name, &wcex );
Alexandre Julliard's avatar
Alexandre Julliard committed
1020

1021
    if (ret)
Alexandre Julliard's avatar
Alexandre Julliard committed
1022
    {
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
        wc->style         = wcex.style;
        wc->lpfnWndProc   = wcex.lpfnWndProc;
        wc->cbClsExtra    = wcex.cbClsExtra;
        wc->cbWndExtra    = wcex.cbWndExtra;
        wc->hInstance     = wcex.hInstance;
        wc->hIcon         = wcex.hIcon;
        wc->hCursor       = wcex.hCursor;
        wc->hbrBackground = wcex.hbrBackground;
        wc->lpszMenuName  = wcex.lpszMenuName;
        wc->lpszClassName = wcex.lpszClassName;
Alexandre Julliard's avatar
Alexandre Julliard committed
1033
    }
1034
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
1035 1036 1037 1038
}


/***********************************************************************
1039
 *		GetClassInfoW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1040
 */
1041
BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc )
Alexandre Julliard's avatar
Alexandre Julliard committed
1042
{
1043 1044
    WNDCLASSEXW wcex;
    UINT ret = GetClassInfoExW( hInstance, name, &wcex );
Alexandre Julliard's avatar
Alexandre Julliard committed
1045

1046
    if (ret)
1047
    {
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
        wc->style         = wcex.style;
        wc->lpfnWndProc   = wcex.lpfnWndProc;
        wc->cbClsExtra    = wcex.cbClsExtra;
        wc->cbWndExtra    = wcex.cbWndExtra;
        wc->hInstance     = wcex.hInstance;
        wc->hIcon         = wcex.hIcon;
        wc->hCursor       = wcex.hCursor;
        wc->hbrBackground = wcex.hbrBackground;
        wc->lpszMenuName  = wcex.lpszMenuName;
        wc->lpszClassName = wcex.lpszClassName;
1058
    }
1059
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
1060 1061 1062 1063
}


/***********************************************************************
1064
 *		GetClassInfoExA (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1065
 */
1066
BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
Alexandre Julliard's avatar
Alexandre Julliard committed
1067
{
1068
    ATOM atom;
Alexandre Julliard's avatar
Alexandre Julliard committed
1069 1070
    CLASS *classPtr;

1071
    TRACE("%p %s %p\n", hInstance, debugstr_a(name), wc);
1072 1073

    if (!hInstance) hInstance = user32_module;
1074

1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
    if (!IS_INTRESOURCE(name))
    {
        WCHAR nameW[MAX_ATOM_LEN + 1];
        if (!MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, sizeof(nameW)/sizeof(WCHAR) ))
            return FALSE;
        classPtr = CLASS_FindClass( nameW, hInstance );
    }
    else classPtr = CLASS_FindClass( (LPCWSTR)name, hInstance );

    if (!classPtr)
1085 1086 1087 1088
    {
        SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
        return FALSE;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1089
    wc->style         = classPtr->style;
1090
    wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, FALSE );
Alexandre Julliard's avatar
Alexandre Julliard committed
1091 1092
    wc->cbClsExtra    = classPtr->cbClsExtra;
    wc->cbWndExtra    = classPtr->cbWndExtra;
1093
    wc->hInstance     = (hInstance == user32_module) ? 0 : hInstance;
1094 1095 1096 1097
    wc->hIcon         = classPtr->hIcon;
    wc->hIconSm       = classPtr->hIconSm;
    wc->hCursor       = classPtr->hCursor;
    wc->hbrBackground = classPtr->hbrBackground;
Alexandre Julliard's avatar
Alexandre Julliard committed
1098
    wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
1099
    wc->lpszClassName = name;
1100
    atom = classPtr->atomName;
1101
    release_class_ptr( classPtr );
1102

1103 1104
    /* We must return the atom of the class here instead of just TRUE. */
    return atom;
Alexandre Julliard's avatar
Alexandre Julliard committed
1105 1106 1107 1108
}


/***********************************************************************
1109
 *		GetClassInfoExW (USER32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1110
 */
1111
BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc )
Alexandre Julliard's avatar
Alexandre Julliard committed
1112
{
1113
    ATOM atom;
Alexandre Julliard's avatar
Alexandre Julliard committed
1114
    CLASS *classPtr;
Alexandre Julliard's avatar
Alexandre Julliard committed
1115

1116
    TRACE("%p %s %p\n", hInstance, debugstr_w(name), wc);
1117 1118

    if (!hInstance) hInstance = user32_module;
1119

1120
    if (!(classPtr = CLASS_FindClass( name, hInstance )))
1121 1122 1123 1124
    {
        SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
        return FALSE;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1125
    wc->style         = classPtr->style;
1126
    wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, TRUE );
Alexandre Julliard's avatar
Alexandre Julliard committed
1127 1128
    wc->cbClsExtra    = classPtr->cbClsExtra;
    wc->cbWndExtra    = classPtr->cbWndExtra;
1129
    wc->hInstance     = (hInstance == user32_module) ? 0 : hInstance;
1130 1131 1132 1133
    wc->hIcon         = classPtr->hIcon;
    wc->hIconSm       = classPtr->hIconSm;
    wc->hCursor       = classPtr->hCursor;
    wc->hbrBackground = classPtr->hbrBackground;
Alexandre Julliard's avatar
Alexandre Julliard committed
1134
    wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
1135
    wc->lpszClassName = name;
1136
    atom = classPtr->atomName;
1137
    release_class_ptr( classPtr );
1138

1139 1140
    /* We must return the atom of the class here instead of just TRUE. */
    return atom;
Alexandre Julliard's avatar
Alexandre Julliard committed
1141
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1142 1143


1144 1145
#if 0  /* toolhelp is in kernel, so this cannot work */

Alexandre Julliard's avatar
Alexandre Julliard committed
1146
/***********************************************************************
1147
 *		ClassFirst (TOOLHELP.69)
Alexandre Julliard's avatar
Alexandre Julliard committed
1148
 */
1149
BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
Alexandre Julliard's avatar
Alexandre Julliard committed
1150
{
1151
    TRACE("%p\n",pClassEntry);
Alexandre Julliard's avatar
Alexandre Julliard committed
1152
    pClassEntry->wNext = 1;
1153
    return ClassNext16( pClassEntry );
Alexandre Julliard's avatar
Alexandre Julliard committed
1154 1155 1156 1157
}


/***********************************************************************
1158
 *		ClassNext (TOOLHELP.70)
Alexandre Julliard's avatar
Alexandre Julliard committed
1159
 */
1160
BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
Alexandre Julliard's avatar
Alexandre Julliard committed
1161
{
Alexandre Julliard's avatar
Alexandre Julliard committed
1162 1163
    int i;
    CLASS *class = firstClass;
Alexandre Julliard's avatar
Alexandre Julliard committed
1164

1165
    TRACE("%p\n",pClassEntry);
1166

Alexandre Julliard's avatar
Alexandre Julliard committed
1167 1168 1169 1170 1171 1172 1173
    if (!pClassEntry->wNext) return FALSE;
    for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
    if (!class)
    {
        pClassEntry->wNext = 0;
        return FALSE;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1174
    pClassEntry->hInst = class->hInstance;
Alexandre Julliard's avatar
Alexandre Julliard committed
1175
    pClassEntry->wNext++;
1176
    GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
Alexandre Julliard's avatar
Alexandre Julliard committed
1177
                          sizeof(pClassEntry->szClassName) );
Alexandre Julliard's avatar
Alexandre Julliard committed
1178 1179
    return TRUE;
}
1180
#endif
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204

/* 64bit versions */

#ifdef GetClassLongPtrA
#undef GetClassLongPtrA
#endif

#ifdef GetClassLongPtrW
#undef GetClassLongPtrW
#endif

#ifdef SetClassLongPtrA
#undef SetClassLongPtrA
#endif

#ifdef SetClassLongPtrW
#undef SetClassLongPtrW
#endif

/***********************************************************************
 *		GetClassLongPtrA (USER32.@)
 */
ULONG_PTR WINAPI GetClassLongPtrA( HWND hwnd, INT offset )
{
1205
    return CLASS_GetClassLong( hwnd, offset, sizeof(ULONG_PTR), FALSE );
1206 1207 1208 1209 1210 1211 1212
}

/***********************************************************************
 *		GetClassLongPtrW (USER32.@)
 */
ULONG_PTR WINAPI GetClassLongPtrW( HWND hwnd, INT offset )
{
1213
    return CLASS_GetClassLong( hwnd, offset, sizeof(ULONG_PTR), TRUE );
1214 1215 1216 1217 1218 1219 1220
}

/***********************************************************************
 *		SetClassLongPtrW (USER32.@)
 */
ULONG_PTR WINAPI SetClassLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
{
1221
    return CLASS_SetClassLong( hwnd, offset, newval, sizeof(LONG_PTR), TRUE );
1222 1223 1224 1225 1226 1227 1228
}

/***********************************************************************
 *		SetClassLongPtrA (USER32.@)
 */
ULONG_PTR WINAPI SetClassLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
{
1229
    return CLASS_SetClassLong( hwnd, offset, newval, sizeof(LONG_PTR), FALSE );
1230
}