Use poll() on the client-side during server waits to implement
[wine.git] / windows / class.c
blobcf335a268c29192669a8dabd81c06d13c8a3e330
1 /*
2 * Window classes functions
4 * Copyright 1993, 1996 Alexandre Julliard
5 * 1998 Juergen Schmied (jsch)
7 * FIXME: In win32 all classes are local. They are registered at
8 * program start. Processes CANNOT share classes. (Source: some
9 * win31->NT migration book)
11 * FIXME: There seems to be a general problem with hInstance in WINE
12 * classes are getting registered with wrong hInstance.
15 #include <stdlib.h>
16 #include <string.h>
17 #include "wine/winbase16.h"
18 #include "winerror.h"
19 #include "windef.h"
20 #include "wingdi.h"
21 #include "wine/winuser16.h"
22 #include "wine/unicode.h"
23 #include "wine/port.h"
24 #include "heap.h"
25 #include "win.h"
26 #include "controls.h"
27 #include "dce.h"
28 #include "toolhelp.h"
29 #include "winproc.h"
30 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(class);
34 typedef struct tagCLASS
36 struct tagCLASS *next; /* Next class */
37 struct tagCLASS *prev; /* Prev class */
38 UINT cWindows; /* Count of existing windows */
39 UINT style; /* Class style */
40 HWINDOWPROC winprocA; /* Window procedure (ASCII) */
41 HWINDOWPROC winprocW; /* Window procedure (Unicode) */
42 INT cbClsExtra; /* Class extra bytes */
43 INT cbWndExtra; /* Window extra bytes */
44 LPWSTR menuName; /* Default menu name (Unicode followed by ASCII) */
45 struct tagDCE *dce; /* Class DCE (if CS_CLASSDC) */
46 HINSTANCE hInstance; /* Module that created the task */
47 HICON hIcon; /* Default icon */
48 HICON hIconSm; /* Default small icon */
49 HCURSOR hCursor; /* Default cursor */
50 HBRUSH hbrBackground; /* Default background */
51 ATOM atomName; /* Name of the class */
52 LONG wExtra[1]; /* Class extra bytes */
53 } CLASS;
55 static CLASS *firstClass;
58 /***********************************************************************
59 * CLASS_GetProc
61 * Get the class winproc for a given proc type
63 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
65 HWINDOWPROC proc = classPtr->winprocA;
67 if (classPtr->winprocW)
69 /* if we have a Unicode proc, use it if we have no ASCII proc
70 * or if we have both and Unicode was requested
72 if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
74 return WINPROC_GetProc( proc, type );
78 /***********************************************************************
79 * CLASS_SetProc
81 * Set the class winproc for a given proc type.
82 * Returns the previous window proc.
84 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
86 HWINDOWPROC *proc = &classPtr->winprocA;
87 WNDPROC16 ret;
89 if (classPtr->winprocW)
91 /* if we have a Unicode proc, use it if we have no ASCII proc
92 * or if we have both and Unicode was requested
94 if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
96 ret = WINPROC_GetProc( *proc, type );
97 WINPROC_SetProc( proc, (HWINDOWPROC)newproc, type, WIN_PROC_CLASS );
98 /* now free the one that we didn't set */
99 if (classPtr->winprocA && classPtr->winprocW)
101 if (proc == &classPtr->winprocA)
103 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
104 classPtr->winprocW = 0;
106 else
108 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
109 classPtr->winprocA = 0;
112 return ret;
116 /***********************************************************************
117 * CLASS_GetMenuNameA
119 * Get the menu name as a ASCII string.
121 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
123 if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
124 return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
128 /***********************************************************************
129 * CLASS_GetMenuNameW
131 * Get the menu name as a Unicode string.
133 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
135 return classPtr->menuName;
139 /***********************************************************************
140 * CLASS_SetMenuNameA
142 * Set the menu name in a class structure by copying the string.
144 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
146 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
147 if (HIWORD(name))
149 DWORD lenA = strlen(name) + 1;
150 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
151 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
152 MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
153 memcpy( classPtr->menuName + lenW, name, lenA );
155 else classPtr->menuName = (LPWSTR)name;
159 /***********************************************************************
160 * CLASS_SetMenuNameW
162 * Set the menu name in a class structure by copying the string.
164 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
166 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
167 if (HIWORD(name))
169 DWORD lenW = strlenW(name) + 1;
170 DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
171 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
172 memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
173 WideCharToMultiByte( CP_ACP, 0, name, lenW,
174 (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
176 else classPtr->menuName = (LPWSTR)name;
180 /***********************************************************************
181 * CLASS_FreeClass
183 * Free a class structure.
185 static BOOL CLASS_FreeClass( CLASS *classPtr )
187 TRACE("%p\n", classPtr);
189 /* Check if we can remove this class */
191 if (classPtr->cWindows > 0)
193 SetLastError( ERROR_CLASS_HAS_WINDOWS );
194 return FALSE;
197 /* Remove the class from the linked list */
199 if (classPtr->next) classPtr->next->prev = classPtr->prev;
200 if (classPtr->prev) classPtr->prev->next = classPtr->next;
201 else firstClass = classPtr->next;
203 /* Delete the class */
205 if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
206 if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
207 DeleteObject( classPtr->hbrBackground );
208 GlobalDeleteAtom( classPtr->atomName );
209 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
210 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
211 HeapFree( GetProcessHeap(), 0, classPtr->menuName );
212 HeapFree( GetProcessHeap(), 0, classPtr );
213 return TRUE;
217 /***********************************************************************
218 * CLASS_FreeModuleClasses
220 void CLASS_FreeModuleClasses( HMODULE16 hModule )
222 CLASS *ptr, *next;
224 TRACE("0x%08x\n", hModule);
226 for (ptr = firstClass; ptr; ptr = next)
228 next = ptr->next;
229 if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
234 /***********************************************************************
235 * CLASS_FindClassByAtom
237 * Return a pointer to the class.
238 * hinstance has been normalized by the caller.
240 * NOTES
241 * 980805 a local class will be found now if registred with hInst=0
242 * and looed up with a hInst!=0. msmoney does it (jsch)
244 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
246 CLASS * class, *tclass=0;
248 TRACE("0x%08x 0x%08x\n", atom, hinstance);
250 /* First search task-specific classes */
252 for (class = firstClass; (class); class = class->next)
254 if (class->style & CS_GLOBALCLASS) continue;
255 if (class->atomName == atom)
257 if (hinstance==class->hInstance || hinstance==0xffff )
259 TRACE("-- found local %p\n", class);
260 return class;
262 if (class->hInstance==0) tclass = class;
266 /* Then search global classes */
268 for (class = firstClass; (class); class = class->next)
270 if (!(class->style & CS_GLOBALCLASS)) continue;
271 if (class->atomName == atom)
273 TRACE("-- found global %p\n", class);
274 return class;
278 /* Then check if there was a local class with hInst=0*/
279 if ( tclass )
281 WARN("-- found local Class registred with hInst=0\n");
282 return tclass;
285 TRACE("-- not found\n");
286 return 0;
290 /***********************************************************************
291 * CLASS_RegisterClass
293 * The real RegisterClass() functionality.
295 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
296 DWORD style, INT classExtra, INT winExtra )
298 CLASS *classPtr;
300 TRACE("atom=0x%x hinst=0x%x style=0x%lx clExtr=0x%x winExtr=0x%x\n",
301 atom, hInstance, style, classExtra, winExtra );
303 /* Check if a class with this name already exists */
304 classPtr = CLASS_FindClassByAtom( atom, hInstance );
305 if (classPtr)
307 /* Class can be created only if it is local and */
308 /* if the class with the same name is global. */
310 if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
312 SetLastError( ERROR_CLASS_ALREADY_EXISTS );
313 return NULL;
317 /* Fix the extra bytes value */
319 if (classExtra < 0) classExtra = 0;
320 else if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
321 WARN("Class extra bytes %d is > 40\n", classExtra);
322 if (winExtra < 0) winExtra = 0;
323 else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
324 WARN("Win extra bytes %d is > 40\n", winExtra );
326 /* Create the class */
328 classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
329 sizeof(CLASS) + classExtra - sizeof(classPtr->wExtra) );
330 if (!classPtr) return NULL;
331 classPtr->style = style;
332 classPtr->cbWndExtra = winExtra;
333 classPtr->cbClsExtra = classExtra;
334 classPtr->hInstance = hInstance;
335 classPtr->atomName = atom;
336 classPtr->dce = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
338 /* Other non-null values must be set by caller */
340 if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
341 firstClass = classPtr;
342 return classPtr;
346 /***********************************************************************
347 * CLASS_RegisterBuiltinClass
349 * Register a builtin control class.
350 * This allows having both ASCII and Unicode winprocs for the same class.
352 ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
354 ATOM atom;
355 CLASS *classPtr;
357 if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
359 if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
361 GlobalDeleteAtom( atom );
362 return 0;
365 classPtr->hCursor = LoadCursorA( 0, descr->cursor );
366 classPtr->hbrBackground = descr->brush;
368 if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)descr->procA,
369 WIN_PROC_32A, WIN_PROC_CLASS );
370 if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)descr->procW,
371 WIN_PROC_32W, WIN_PROC_CLASS );
372 return atom;
376 /***********************************************************************
377 * CLASS_AddWindow
379 * Add a new window using this class, and return the necessary
380 * information for creating the window.
382 CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
383 INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
385 CLASS *class;
386 if (type == WIN_PROC_16) inst = GetExePtr(inst);
388 if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
389 class->cWindows++;
391 if (type == WIN_PROC_32W)
393 if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
395 else
397 if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
399 *winExtra = class->cbWndExtra;
400 *style = class->style;
401 *dce = class->dce;
402 return class;
406 /***********************************************************************
407 * CLASS_RemoveWindow
409 * Remove a window from the class window count.
411 void CLASS_RemoveWindow( CLASS *cls )
413 if (cls && cls->cWindows) cls->cWindows--;
417 /***********************************************************************
418 * RegisterClass (USER.57)
420 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
422 ATOM atom;
423 CLASS *classPtr;
424 int iSmIconWidth, iSmIconHeight;
425 HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
427 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
428 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
429 wc->cbClsExtra, wc->cbWndExtra )))
431 GlobalDeleteAtom( atom );
432 return 0;
435 TRACE("atom=%04x wndproc=%08lx hinst=%04x "
436 "bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
437 atom, (DWORD)wc->lpfnWndProc, hInstance,
438 wc->hbrBackground, wc->style, wc->cbClsExtra,
439 wc->cbWndExtra, classPtr,
440 HIWORD(wc->lpszClassName) ?
441 (char *)MapSL(wc->lpszClassName) : "" );
443 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
444 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
446 classPtr->hIcon = wc->hIcon;
447 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
448 iSmIconWidth, iSmIconHeight,
449 LR_COPYFROMRESOURCE);
450 classPtr->hCursor = wc->hCursor;
451 classPtr->hbrBackground = wc->hbrBackground;
453 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
454 WIN_PROC_16, WIN_PROC_CLASS );
455 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
457 return atom;
461 /***********************************************************************
462 * RegisterClassA (USER32.@)
463 * RETURNS
464 * >0: Unique identifier
465 * 0: Failure
467 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
469 ATOM atom;
470 int iSmIconWidth, iSmIconHeight;
471 CLASS *classPtr;
473 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
475 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
476 wc->cbClsExtra, wc->cbWndExtra )))
478 GlobalDeleteAtom( atom );
479 return 0;
482 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
483 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
484 wc->hbrBackground, wc->style, wc->cbClsExtra,
485 wc->cbWndExtra, classPtr,
486 HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
488 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
489 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
491 classPtr->hIcon = wc->hIcon;
492 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
493 iSmIconWidth, iSmIconHeight,
494 LR_COPYFROMRESOURCE);
495 classPtr->hCursor = (HCURSOR16)wc->hCursor;
496 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
498 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
499 WIN_PROC_32A, WIN_PROC_CLASS );
500 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
501 return atom;
505 /***********************************************************************
506 * RegisterClassW (USER32.@)
508 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
510 ATOM atom;
511 int iSmIconWidth, iSmIconHeight;
512 CLASS *classPtr;
514 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
516 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
517 wc->cbClsExtra, wc->cbWndExtra )))
519 GlobalDeleteAtom( atom );
520 return 0;
523 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
524 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
525 wc->hbrBackground, wc->style, wc->cbClsExtra,
526 wc->cbWndExtra, classPtr );
528 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
529 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
531 classPtr->hIcon = wc->hIcon;
532 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
533 iSmIconWidth, iSmIconHeight,
534 LR_COPYFROMRESOURCE);
535 classPtr->hCursor = (HCURSOR16)wc->hCursor;
536 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
538 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
539 WIN_PROC_32W, WIN_PROC_CLASS );
540 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
541 return atom;
545 /***********************************************************************
546 * RegisterClassEx (USER.397)
548 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
550 ATOM atom;
551 CLASS *classPtr;
552 HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
554 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
555 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
556 wc->cbClsExtra, wc->cbWndExtra )))
558 GlobalDeleteAtom( atom );
559 return 0;
562 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
563 atom, (DWORD)wc->lpfnWndProc, hInstance,
564 wc->hbrBackground, wc->style, wc->cbClsExtra,
565 wc->cbWndExtra, classPtr );
567 classPtr->hIcon = wc->hIcon;
568 classPtr->hIconSm = wc->hIconSm;
569 classPtr->hCursor = wc->hCursor;
570 classPtr->hbrBackground = wc->hbrBackground;
572 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
573 WIN_PROC_16, WIN_PROC_CLASS );
574 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
575 return atom;
579 /***********************************************************************
580 * RegisterClassExA (USER32.@)
582 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
584 ATOM atom;
585 CLASS *classPtr;
587 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
589 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
590 wc->cbClsExtra, wc->cbWndExtra )))
592 GlobalDeleteAtom( atom );
593 return 0;
596 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
597 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
598 wc->hbrBackground, wc->style, wc->cbClsExtra,
599 wc->cbWndExtra, classPtr );
601 classPtr->hIcon = (HICON16)wc->hIcon;
602 classPtr->hIconSm = (HICON16)wc->hIconSm;
603 classPtr->hCursor = (HCURSOR16)wc->hCursor;
604 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
605 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
606 WIN_PROC_32A, WIN_PROC_CLASS );
607 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
608 return atom;
612 /***********************************************************************
613 * RegisterClassExW (USER32.@)
615 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
617 ATOM atom;
618 CLASS *classPtr;
620 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
622 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
623 wc->cbClsExtra, wc->cbWndExtra )))
625 GlobalDeleteAtom( atom );
626 return 0;
629 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
630 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
631 wc->hbrBackground, wc->style, wc->cbClsExtra,
632 wc->cbWndExtra, classPtr );
634 classPtr->hIcon = (HICON16)wc->hIcon;
635 classPtr->hIconSm = (HICON16)wc->hIconSm;
636 classPtr->hCursor = (HCURSOR16)wc->hCursor;
637 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
638 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
639 WIN_PROC_32W, WIN_PROC_CLASS );
640 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
641 return atom;
645 /***********************************************************************
646 * UnregisterClass (USER.403)
648 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
650 return UnregisterClassA( className, GetExePtr( hInstance ) );
654 /***********************************************************************
655 * UnregisterClassA (USER32.@)
658 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
660 CLASS *classPtr;
661 ATOM atom;
663 TRACE("%s %x\n",debugres_a(className), hInstance);
665 if (!(atom = GlobalFindAtomA( className )))
667 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
668 return FALSE;
670 if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
671 (classPtr->hInstance != hInstance))
673 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
674 return FALSE;
676 return CLASS_FreeClass( classPtr );
679 /***********************************************************************
680 * UnregisterClassW (USER32.@)
682 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
684 CLASS *classPtr;
685 ATOM atom;
687 TRACE("%s %x\n",debugres_w(className), hInstance);
689 if (!(atom = GlobalFindAtomW( className )))
691 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
692 return FALSE;
694 if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
695 (classPtr->hInstance != hInstance))
697 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
698 return FALSE;
700 return CLASS_FreeClass( classPtr );
703 /***********************************************************************
704 * GetClassWord (USER.129)
706 WORD WINAPI GetClassWord16( HWND16 hwnd, INT16 offset )
708 return GetClassWord( hwnd, offset );
712 /***********************************************************************
713 * GetClassWord (USER32.@)
715 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
717 WND * wndPtr;
718 WORD retvalue = 0;
720 TRACE("%x %x\n",hwnd, offset);
722 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
723 if (offset >= 0)
725 if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
727 retvalue = GET_WORD(((char *)wndPtr->class->wExtra) + offset);
728 goto END;
731 else switch(offset)
733 case GCW_HBRBACKGROUND: retvalue = wndPtr->class->hbrBackground;
734 goto END;
735 case GCW_HCURSOR: retvalue = wndPtr->class->hCursor;
736 goto END;
737 case GCW_HICON: retvalue = wndPtr->class->hIcon;
738 goto END;
739 case GCW_HICONSM: retvalue = wndPtr->class->hIconSm;
740 goto END;
741 case GCW_ATOM: retvalue = wndPtr->class->atomName;
742 goto END;
743 case GCW_STYLE:
744 case GCW_CBWNDEXTRA:
745 case GCW_CBCLSEXTRA:
746 case GCW_HMODULE:
747 retvalue = (WORD)GetClassLongA( hwnd, offset );
748 goto END;
751 WARN("Invalid offset %d\n", offset);
752 END:
753 WIN_ReleaseWndPtr(wndPtr);
754 return retvalue;
758 /***********************************************************************
759 * GetClassLong (USER.131)
761 LONG WINAPI GetClassLong16( HWND16 hwnd, INT16 offset )
763 WND *wndPtr;
764 LONG ret;
766 TRACE("%x %x\n",hwnd, offset);
768 switch( offset )
770 case GCL_WNDPROC:
771 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
772 ret = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_16 );
773 WIN_ReleaseWndPtr(wndPtr);
774 return ret;
775 case GCL_MENUNAME:
776 ret = GetClassLongA( hwnd, offset );
777 return (LONG)SEGPTR_GET( (void *)ret );
778 default:
779 return GetClassLongA( hwnd, offset );
784 /***********************************************************************
785 * GetClassLongA (USER32.@)
787 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
789 WND * wndPtr;
790 LONG retvalue;
792 TRACE("%x %x\n",hwnd, offset);
794 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
795 if (offset >= 0)
797 if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
799 retvalue = GET_DWORD(((char *)wndPtr->class->wExtra) + offset);
800 goto END;
804 switch(offset)
806 case GCL_STYLE: retvalue = (LONG)wndPtr->class->style;
807 goto END;
808 case GCL_CBWNDEXTRA: retvalue = (LONG)wndPtr->class->cbWndExtra;
809 goto END;
810 case GCL_CBCLSEXTRA: retvalue = (LONG)wndPtr->class->cbClsExtra;
811 goto END;
812 case GCL_HMODULE: retvalue = (LONG)wndPtr->class->hInstance;
813 goto END;
814 case GCL_WNDPROC:
815 retvalue = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_32A );
816 goto END;
817 case GCL_MENUNAME:
818 retvalue = (LONG)CLASS_GetMenuNameA( wndPtr->class );
819 goto END;
820 case GCW_ATOM:
821 case GCL_HBRBACKGROUND:
822 case GCL_HCURSOR:
823 case GCL_HICON:
824 case GCL_HICONSM:
825 retvalue = GetClassWord( hwnd, offset );
826 goto END;
828 WARN("Invalid offset %d\n", offset);
829 retvalue = 0;
830 END:
831 WIN_ReleaseWndPtr(wndPtr);
832 return retvalue;
836 /***********************************************************************
837 * GetClassLongW (USER32.@)
839 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
841 WND * wndPtr;
842 LONG retvalue;
844 TRACE("%x %x\n",hwnd, offset);
846 switch(offset)
848 case GCL_WNDPROC:
849 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
850 retvalue = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_32W );
851 WIN_ReleaseWndPtr(wndPtr);
852 return retvalue;
853 case GCL_MENUNAME:
854 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
855 retvalue = (LONG)CLASS_GetMenuNameW( wndPtr->class );
856 WIN_ReleaseWndPtr(wndPtr);
857 return retvalue;
858 default:
859 return GetClassLongA( hwnd, offset );
864 /***********************************************************************
865 * SetClassWord (USER.130)
867 WORD WINAPI SetClassWord16( HWND16 hwnd, INT16 offset, WORD newval )
869 return SetClassWord( hwnd, offset, newval );
873 /***********************************************************************
874 * SetClassWord (USER32.@)
876 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
878 WND * wndPtr;
879 WORD retval = 0;
880 void *ptr;
882 TRACE("%x %x %x\n",hwnd, offset, newval);
884 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
885 if (offset >= 0)
887 if (offset + sizeof(WORD) <= wndPtr->class->cbClsExtra)
888 ptr = ((char *)wndPtr->class->wExtra) + offset;
889 else
891 WARN("Invalid offset %d\n", offset );
892 WIN_ReleaseWndPtr(wndPtr);
893 return 0;
896 else switch(offset)
898 case GCW_STYLE:
899 case GCW_CBWNDEXTRA:
900 case GCW_CBCLSEXTRA:
901 case GCW_HMODULE:
902 WIN_ReleaseWndPtr(wndPtr);
903 return (WORD)SetClassLongA( hwnd, offset, (LONG)newval );
904 case GCW_HBRBACKGROUND: ptr = &wndPtr->class->hbrBackground; break;
905 case GCW_HCURSOR: ptr = &wndPtr->class->hCursor; break;
906 case GCW_HICON: ptr = &wndPtr->class->hIcon; break;
907 case GCW_HICONSM: ptr = &wndPtr->class->hIconSm; break;
908 case GCW_ATOM: ptr = &wndPtr->class->atomName; break;
909 default:
910 WARN("Invalid offset %d\n", offset);
911 WIN_ReleaseWndPtr(wndPtr);
912 return 0;
914 retval = GET_WORD(ptr);
915 PUT_WORD( ptr, newval );
916 WIN_ReleaseWndPtr(wndPtr);
917 return retval;
921 /***********************************************************************
922 * SetClassLong (USER.132)
924 LONG WINAPI SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
926 WND *wndPtr;
927 LONG retval;
929 TRACE("%x %x %lx\n",hwnd, offset, newval);
931 switch(offset)
933 case GCL_WNDPROC:
934 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
935 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_16 );
936 WIN_ReleaseWndPtr(wndPtr);
937 return retval;
938 case GCL_MENUNAME:
939 return SetClassLongA( hwnd, offset, (LONG)MapSL(newval) );
940 default:
941 return SetClassLongA( hwnd, offset, newval );
946 /***********************************************************************
947 * SetClassLongA (USER32.@)
949 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
951 WND * wndPtr;
952 LONG retval = 0;
953 void *ptr;
955 TRACE("%x %x %lx\n",hwnd, offset, newval);
957 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
958 if (offset >= 0)
960 if (offset + sizeof(LONG) <= wndPtr->class->cbClsExtra)
961 ptr = ((char *)wndPtr->class->wExtra) + offset;
962 else
964 WARN("Invalid offset %d\n", offset );
965 retval = 0;
966 goto END;
969 else switch(offset)
971 case GCL_MENUNAME:
972 CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
973 retval = 0; /* Old value is now meaningless anyway */
974 goto END;
975 case GCL_WNDPROC:
976 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_32A );
977 goto END;
978 case GCL_HBRBACKGROUND:
979 case GCL_HCURSOR:
980 case GCL_HICON:
981 case GCL_HICONSM:
982 retval = SetClassWord( hwnd, offset, (WORD)newval );
983 goto END;
984 case GCL_STYLE: ptr = &wndPtr->class->style; break;
985 case GCL_CBWNDEXTRA: ptr = &wndPtr->class->cbWndExtra; break;
986 case GCL_CBCLSEXTRA: ptr = &wndPtr->class->cbClsExtra; break;
987 case GCL_HMODULE: ptr = &wndPtr->class->hInstance; break;
988 default:
989 WARN("Invalid offset %d\n", offset );
990 retval = 0;
991 goto END;
993 retval = GET_DWORD(ptr);
994 PUT_DWORD( ptr, newval );
995 END:
996 WIN_ReleaseWndPtr(wndPtr);
997 return retval;
1001 /***********************************************************************
1002 * SetClassLongW (USER32.@)
1004 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1006 WND *wndPtr;
1007 LONG retval;
1009 TRACE("%x %x %lx\n",hwnd, offset, newval);
1011 switch(offset)
1013 case GCL_WNDPROC:
1014 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1015 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_32W );
1016 WIN_ReleaseWndPtr(wndPtr);
1017 return retval;
1018 case GCL_MENUNAME:
1019 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1020 CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
1021 WIN_ReleaseWndPtr(wndPtr);
1022 return 0; /* Old value is now meaningless anyway */
1023 default:
1024 return SetClassLongA( hwnd, offset, newval );
1029 /***********************************************************************
1030 * GetClassName (USER.58)
1032 INT16 WINAPI GetClassName16( HWND16 hwnd, LPSTR buffer, INT16 count )
1034 return GetClassNameA( hwnd, buffer, count );
1038 /***********************************************************************
1039 * GetClassNameA (USER32.@)
1041 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1042 { INT ret;
1043 WND *wndPtr;
1045 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1046 ret = GlobalGetAtomNameA( wndPtr->class->atomName, buffer, count );
1048 WIN_ReleaseWndPtr(wndPtr);
1049 TRACE("%x %s %x\n",hwnd, buffer, count);
1050 return ret;
1054 /***********************************************************************
1055 * GetClassNameW (USER32.@)
1057 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1058 { INT ret;
1059 WND *wndPtr;
1061 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1062 ret = GlobalGetAtomNameW( wndPtr->class->atomName, buffer, count );
1063 WIN_ReleaseWndPtr(wndPtr);
1064 TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
1066 return ret;
1070 /***********************************************************************
1071 * GetClassInfo (USER.404)
1073 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASS16 *wc )
1075 ATOM atom;
1076 CLASS *classPtr;
1078 TRACE("%x %s %p\n",hInstance, debugres_a(MapSL(name)), wc);
1080 hInstance = GetExePtr( hInstance );
1081 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1082 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1083 return FALSE;
1084 if ((hInstance != classPtr->hInstance) &&
1085 !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
1086 return FALSE;
1087 wc->style = (UINT16)classPtr->style;
1088 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1089 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1090 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1091 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1092 wc->hIcon = classPtr->hIcon;
1093 wc->hCursor = classPtr->hCursor;
1094 wc->hbrBackground = classPtr->hbrBackground;
1095 wc->lpszClassName = name;
1096 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1097 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1098 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1099 return TRUE;
1103 /***********************************************************************
1104 * GetClassInfoA (USER32.@)
1106 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
1107 WNDCLASSA *wc )
1109 ATOM atom;
1110 CLASS *classPtr;
1112 TRACE("%x %p %p\n",hInstance, name, wc);
1114 /* workaround: if hInstance=NULL you expect to get the system classes
1115 but this classes (as example from comctl32.dll SysListView) won't be
1116 registered with hInstance=NULL in WINE because of the late loading
1117 of this dll. fixes file dialogs in WinWord95 (jsch)*/
1119 if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
1120 return FALSE;
1122 if (!(classPtr->style & CS_GLOBALCLASS) &&
1123 classPtr->hInstance &&
1124 (hInstance != classPtr->hInstance))
1126 if (hInstance) return FALSE;
1127 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
1130 wc->style = classPtr->style;
1131 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1132 wc->cbClsExtra = classPtr->cbClsExtra;
1133 wc->cbWndExtra = classPtr->cbWndExtra;
1134 wc->hInstance = hInstance;
1135 wc->hIcon = (HICON)classPtr->hIcon;
1136 wc->hCursor = (HCURSOR)classPtr->hCursor;
1137 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1138 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1139 wc->lpszClassName = name;
1140 return TRUE;
1144 /***********************************************************************
1145 * GetClassInfoW (USER32.@)
1147 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
1148 WNDCLASSW *wc )
1150 ATOM atom;
1151 CLASS *classPtr;
1153 TRACE("%x %p %p\n",hInstance, name, wc);
1155 if ( !(atom=GlobalFindAtomW(name)) ||
1156 !(classPtr=CLASS_FindClassByAtom(atom,hInstance))
1158 return FALSE;
1160 if (!(classPtr->style & CS_GLOBALCLASS) &&
1161 classPtr->hInstance &&
1162 (hInstance != classPtr->hInstance))
1164 if (hInstance) return FALSE;
1165 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",debugstr_w(name));
1167 wc->style = classPtr->style;
1168 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1169 wc->cbClsExtra = classPtr->cbClsExtra;
1170 wc->cbWndExtra = classPtr->cbWndExtra;
1171 wc->hInstance = hInstance;
1172 wc->hIcon = (HICON)classPtr->hIcon;
1173 wc->hCursor = (HCURSOR)classPtr->hCursor;
1174 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1175 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1176 wc->lpszClassName = name;
1177 return TRUE;
1181 /***********************************************************************
1182 * GetClassInfoEx (USER.398)
1184 * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1185 * same in Win16 as in Win32. --AJ
1187 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASSEX16 *wc )
1189 ATOM atom;
1190 CLASS *classPtr;
1192 TRACE("%x %s %p\n",hInstance,debugres_a( MapSL(name) ), wc);
1194 hInstance = GetExePtr( hInstance );
1195 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1196 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1197 (hInstance != classPtr->hInstance)) return FALSE;
1198 wc->style = classPtr->style;
1199 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1200 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1201 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1202 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1203 wc->hIcon = classPtr->hIcon;
1204 wc->hIconSm = classPtr->hIconSm;
1205 wc->hCursor = classPtr->hCursor;
1206 wc->hbrBackground = classPtr->hbrBackground;
1207 wc->lpszClassName = (SEGPTR)0;
1208 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1209 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1210 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1211 wc->lpszClassName = name;
1213 /* We must return the atom of the class here instead of just TRUE. */
1214 return atom;
1218 /***********************************************************************
1219 * GetClassInfoExA (USER32.@)
1221 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1222 WNDCLASSEXA *wc )
1224 ATOM atom;
1225 CLASS *classPtr;
1227 TRACE("%x %p %p\n",hInstance, name, wc);
1229 if (!(atom = GlobalFindAtomA( name )) ||
1230 !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))
1231 /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
1232 wc->style = classPtr->style;
1233 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1234 wc->cbClsExtra = classPtr->cbClsExtra;
1235 wc->cbWndExtra = classPtr->cbWndExtra;
1236 wc->hInstance = classPtr->hInstance;
1237 wc->hIcon = (HICON)classPtr->hIcon;
1238 wc->hIconSm = (HICON)classPtr->hIconSm;
1239 wc->hCursor = (HCURSOR)classPtr->hCursor;
1240 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1241 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1242 wc->lpszClassName = name;
1244 /* We must return the atom of the class here instead of just TRUE. */
1245 return atom;
1249 /***********************************************************************
1250 * GetClassInfoExW (USER32.@)
1252 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1253 WNDCLASSEXW *wc )
1255 ATOM atom;
1256 CLASS *classPtr;
1258 TRACE("%x %p %p\n",hInstance, name, wc);
1260 if (!(atom = GlobalFindAtomW( name )) ||
1261 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1262 (hInstance != classPtr->hInstance)) return FALSE;
1263 wc->style = classPtr->style;
1264 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1265 wc->cbClsExtra = classPtr->cbClsExtra;
1266 wc->cbWndExtra = classPtr->cbWndExtra;
1267 wc->hInstance = classPtr->hInstance;
1268 wc->hIcon = (HICON)classPtr->hIcon;
1269 wc->hIconSm = (HICON)classPtr->hIconSm;
1270 wc->hCursor = (HCURSOR)classPtr->hCursor;
1271 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1272 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1273 wc->lpszClassName = name;
1275 /* We must return the atom of the class here instead of just TRUE. */
1276 return atom;
1280 /***********************************************************************
1281 * ClassFirst (TOOLHELP.69)
1283 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1285 TRACE("%p\n",pClassEntry);
1286 pClassEntry->wNext = 1;
1287 return ClassNext16( pClassEntry );
1291 /***********************************************************************
1292 * ClassNext (TOOLHELP.70)
1294 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1296 int i;
1297 CLASS *class = firstClass;
1299 TRACE("%p\n",pClassEntry);
1301 if (!pClassEntry->wNext) return FALSE;
1302 for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1303 if (!class)
1305 pClassEntry->wNext = 0;
1306 return FALSE;
1308 pClassEntry->hInst = class->hInstance;
1309 pClassEntry->wNext++;
1310 GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1311 sizeof(pClassEntry->szClassName) );
1312 return TRUE;