Misc fixes for QueryPathOfRegTypeLib, TLB_ReadTypeLib,
[wine.git] / windows / class.c
blobda44e66abbe09f13e2b6514104caf3256f8e31de
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 "heap.h"
24 #include "win.h"
25 #include "controls.h"
26 #include "dce.h"
27 #include "toolhelp.h"
28 #include "winproc.h"
29 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(class);
33 typedef struct tagCLASS
35 struct tagCLASS *next; /* Next class */
36 struct tagCLASS *prev; /* Prev class */
37 UINT cWindows; /* Count of existing windows */
38 UINT style; /* Class style */
39 HWINDOWPROC winprocA; /* Window procedure (ASCII) */
40 HWINDOWPROC winprocW; /* Window procedure (Unicode) */
41 INT cbClsExtra; /* Class extra bytes */
42 INT cbWndExtra; /* Window extra bytes */
43 LPWSTR menuName; /* Default menu name (Unicode followed by ASCII) */
44 struct tagDCE *dce; /* Class DCE (if CS_CLASSDC) */
45 HINSTANCE hInstance; /* Module that created the task */
46 HICON hIcon; /* Default icon */
47 HICON hIconSm; /* Default small icon */
48 HCURSOR hCursor; /* Default cursor */
49 HBRUSH hbrBackground; /* Default background */
50 ATOM atomName; /* Name of the class */
51 LONG wExtra[1]; /* Class extra bytes */
52 } CLASS;
54 static CLASS *firstClass;
57 /***********************************************************************
58 * CLASS_GetProc
60 * Get the class winproc for a given proc type
62 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
64 HWINDOWPROC proc = classPtr->winprocA;
66 if (classPtr->winprocW)
68 /* if we have a Unicode proc, use it if we have no ASCII proc
69 * or if we have both and Unicode was requested
71 if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
73 return WINPROC_GetProc( proc, type );
77 /***********************************************************************
78 * CLASS_SetProc
80 * Set the class winproc for a given proc type.
81 * Returns the previous window proc.
83 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
85 HWINDOWPROC *proc = &classPtr->winprocA;
86 WNDPROC16 ret;
88 if (classPtr->winprocW)
90 /* if we have a Unicode proc, use it if we have no ASCII proc
91 * or if we have both and Unicode was requested
93 if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
95 ret = WINPROC_GetProc( *proc, type );
96 WINPROC_SetProc( proc, (HWINDOWPROC)newproc, type, WIN_PROC_CLASS );
97 /* now free the one that we didn't set */
98 if (classPtr->winprocA && classPtr->winprocW)
100 if (proc == &classPtr->winprocA)
102 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
103 classPtr->winprocW = 0;
105 else
107 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
108 classPtr->winprocA = 0;
111 return ret;
115 /***********************************************************************
116 * CLASS_GetMenuNameA
118 * Get the menu name as a ASCII string.
120 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
122 if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
123 return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
127 /***********************************************************************
128 * CLASS_GetMenuNameW
130 * Get the menu name as a Unicode string.
132 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
134 return classPtr->menuName;
138 /***********************************************************************
139 * CLASS_SetMenuNameA
141 * Set the menu name in a class structure by copying the string.
143 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
145 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
146 if (HIWORD(name))
148 DWORD lenA = strlen(name) + 1;
149 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
150 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
151 MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
152 memcpy( classPtr->menuName + lenW, name, lenA );
154 else classPtr->menuName = (LPWSTR)name;
158 /***********************************************************************
159 * CLASS_SetMenuNameW
161 * Set the menu name in a class structure by copying the string.
163 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
165 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
166 if (HIWORD(name))
168 DWORD lenW = strlenW(name) + 1;
169 DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
170 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
171 memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
172 WideCharToMultiByte( CP_ACP, 0, name, lenW,
173 (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
175 else classPtr->menuName = (LPWSTR)name;
179 /***********************************************************************
180 * CLASS_FreeClass
182 * Free a class structure.
184 static BOOL CLASS_FreeClass( CLASS *classPtr )
186 TRACE("%p\n", classPtr);
188 /* Check if we can remove this class */
190 if (classPtr->cWindows > 0)
192 SetLastError( ERROR_CLASS_HAS_WINDOWS );
193 return FALSE;
196 /* Remove the class from the linked list */
198 if (classPtr->next) classPtr->next->prev = classPtr->prev;
199 if (classPtr->prev) classPtr->prev->next = classPtr->next;
200 else firstClass = classPtr->next;
202 /* Delete the class */
204 if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
205 if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
206 DeleteObject( classPtr->hbrBackground );
207 GlobalDeleteAtom( classPtr->atomName );
208 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
209 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
210 HeapFree( GetProcessHeap(), 0, classPtr->menuName );
211 HeapFree( GetProcessHeap(), 0, classPtr );
212 return TRUE;
216 /***********************************************************************
217 * CLASS_FreeModuleClasses
219 void CLASS_FreeModuleClasses( HMODULE16 hModule )
221 CLASS *ptr, *next;
223 TRACE("0x%08x\n", hModule);
225 for (ptr = firstClass; ptr; ptr = next)
227 next = ptr->next;
228 if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
233 /***********************************************************************
234 * CLASS_FindClassByAtom
236 * Return a pointer to the class.
237 * hinstance has been normalized by the caller.
239 * NOTES
240 * 980805 a local class will be found now if registred with hInst=0
241 * and looed up with a hInst!=0. msmoney does it (jsch)
243 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
245 CLASS * class, *tclass=0;
247 TRACE("0x%08x 0x%08x\n", atom, hinstance);
249 /* First search task-specific classes */
251 for (class = firstClass; (class); class = class->next)
253 if (class->style & CS_GLOBALCLASS) continue;
254 if (class->atomName == atom)
256 if (hinstance==class->hInstance || hinstance==0xffff )
258 TRACE("-- found local %p\n", class);
259 return class;
261 if (class->hInstance==0) tclass = class;
265 /* Then search global classes */
267 for (class = firstClass; (class); class = class->next)
269 if (!(class->style & CS_GLOBALCLASS)) continue;
270 if (class->atomName == atom)
272 TRACE("-- found global %p\n", class);
273 return class;
277 /* Then check if there was a local class with hInst=0*/
278 if ( tclass )
280 WARN("-- found local Class registred with hInst=0\n");
281 return tclass;
284 TRACE("-- not found\n");
285 return 0;
289 /***********************************************************************
290 * CLASS_RegisterClass
292 * The real RegisterClass() functionality.
294 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
295 DWORD style, INT classExtra, INT winExtra )
297 CLASS *classPtr;
299 TRACE("atom=0x%x hinst=0x%x style=0x%lx clExtr=0x%x winExtr=0x%x\n",
300 atom, hInstance, style, classExtra, winExtra );
302 /* Check if a class with this name already exists */
303 classPtr = CLASS_FindClassByAtom( atom, hInstance );
304 if (classPtr)
306 /* Class can be created only if it is local and */
307 /* if the class with the same name is global. */
309 if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
311 SetLastError( ERROR_CLASS_ALREADY_EXISTS );
312 return NULL;
316 /* Fix the extra bytes value */
318 if (classExtra < 0) classExtra = 0;
319 else if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
320 WARN("Class extra bytes %d is > 40\n", classExtra);
321 if (winExtra < 0) winExtra = 0;
322 else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
323 WARN("Win extra bytes %d is > 40\n", winExtra );
325 /* Create the class */
327 classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
328 sizeof(CLASS) + classExtra - sizeof(classPtr->wExtra) );
329 if (!classPtr) return NULL;
330 classPtr->style = style;
331 classPtr->cbWndExtra = winExtra;
332 classPtr->cbClsExtra = classExtra;
333 classPtr->hInstance = hInstance;
334 classPtr->atomName = atom;
335 classPtr->dce = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
337 /* Other non-null values must be set by caller */
339 if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
340 firstClass = classPtr;
341 return classPtr;
345 /***********************************************************************
346 * CLASS_RegisterBuiltinClass
348 * Register a builtin control class.
349 * This allows having both ASCII and Unicode winprocs for the same class.
351 ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
353 ATOM atom;
354 CLASS *classPtr;
356 if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
358 if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
360 GlobalDeleteAtom( atom );
361 return 0;
364 classPtr->hCursor = LoadCursorA( 0, descr->cursor );
365 classPtr->hbrBackground = descr->brush;
367 if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)descr->procA,
368 WIN_PROC_32A, WIN_PROC_CLASS );
369 if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)descr->procW,
370 WIN_PROC_32W, WIN_PROC_CLASS );
371 return atom;
375 /***********************************************************************
376 * CLASS_AddWindow
378 * Add a new window using this class, and return the necessary
379 * information for creating the window.
381 CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
382 INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
384 CLASS *class;
385 if (type == WIN_PROC_16) inst = GetExePtr(inst);
387 if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
388 class->cWindows++;
390 if (type == WIN_PROC_32W)
392 if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
394 else
396 if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
398 *winExtra = class->cbWndExtra;
399 *style = class->style;
400 *dce = class->dce;
401 return class;
405 /***********************************************************************
406 * CLASS_RemoveWindow
408 * Remove a window from the class window count.
410 void CLASS_RemoveWindow( CLASS *cls )
412 if (cls && cls->cWindows) cls->cWindows--;
416 /***********************************************************************
417 * RegisterClass16 (USER.57)
419 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
421 ATOM atom;
422 CLASS *classPtr;
423 int iSmIconWidth, iSmIconHeight;
424 HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
426 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
427 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
428 wc->cbClsExtra, wc->cbWndExtra )))
430 GlobalDeleteAtom( atom );
431 return 0;
434 TRACE("atom=%04x wndproc=%08lx hinst=%04x "
435 "bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
436 atom, (DWORD)wc->lpfnWndProc, hInstance,
437 wc->hbrBackground, wc->style, wc->cbClsExtra,
438 wc->cbWndExtra, classPtr,
439 HIWORD(wc->lpszClassName) ?
440 (char *)MapSL(wc->lpszClassName) : "" );
442 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
443 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
445 classPtr->hIcon = wc->hIcon;
446 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
447 iSmIconWidth, iSmIconHeight,
448 LR_COPYFROMRESOURCE);
449 classPtr->hCursor = wc->hCursor;
450 classPtr->hbrBackground = wc->hbrBackground;
452 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
453 WIN_PROC_16, WIN_PROC_CLASS );
454 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
456 return atom;
460 /***********************************************************************
461 * RegisterClassA (USER32.427)
462 * RETURNS
463 * >0: Unique identifier
464 * 0: Failure
466 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
468 ATOM atom;
469 int iSmIconWidth, iSmIconHeight;
470 CLASS *classPtr;
472 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
474 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
475 wc->cbClsExtra, wc->cbWndExtra )))
477 GlobalDeleteAtom( atom );
478 return 0;
481 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
482 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
483 wc->hbrBackground, wc->style, wc->cbClsExtra,
484 wc->cbWndExtra, classPtr,
485 HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
487 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
488 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
490 classPtr->hIcon = wc->hIcon;
491 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
492 iSmIconWidth, iSmIconHeight,
493 LR_COPYFROMRESOURCE);
494 classPtr->hCursor = (HCURSOR16)wc->hCursor;
495 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
497 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
498 WIN_PROC_32A, WIN_PROC_CLASS );
499 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
500 return atom;
504 /***********************************************************************
505 * RegisterClassW (USER32.430)
507 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
509 ATOM atom;
510 int iSmIconWidth, iSmIconHeight;
511 CLASS *classPtr;
513 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
515 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
516 wc->cbClsExtra, wc->cbWndExtra )))
518 GlobalDeleteAtom( atom );
519 return 0;
522 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
523 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
524 wc->hbrBackground, wc->style, wc->cbClsExtra,
525 wc->cbWndExtra, classPtr );
527 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
528 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
530 classPtr->hIcon = wc->hIcon;
531 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
532 iSmIconWidth, iSmIconHeight,
533 LR_COPYFROMRESOURCE);
534 classPtr->hCursor = (HCURSOR16)wc->hCursor;
535 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
537 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
538 WIN_PROC_32W, WIN_PROC_CLASS );
539 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
540 return atom;
544 /***********************************************************************
545 * RegisterClassEx16 (USER.397)
547 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
549 ATOM atom;
550 CLASS *classPtr;
551 HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
553 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
554 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
555 wc->cbClsExtra, wc->cbWndExtra )))
557 GlobalDeleteAtom( atom );
558 return 0;
561 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
562 atom, (DWORD)wc->lpfnWndProc, hInstance,
563 wc->hbrBackground, wc->style, wc->cbClsExtra,
564 wc->cbWndExtra, classPtr );
566 classPtr->hIcon = wc->hIcon;
567 classPtr->hIconSm = wc->hIconSm;
568 classPtr->hCursor = wc->hCursor;
569 classPtr->hbrBackground = wc->hbrBackground;
571 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
572 WIN_PROC_16, WIN_PROC_CLASS );
573 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
574 return atom;
578 /***********************************************************************
579 * RegisterClassExA (USER32.428)
581 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
583 ATOM atom;
584 CLASS *classPtr;
586 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
588 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
589 wc->cbClsExtra, wc->cbWndExtra )))
591 GlobalDeleteAtom( atom );
592 return 0;
595 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
596 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
597 wc->hbrBackground, wc->style, wc->cbClsExtra,
598 wc->cbWndExtra, classPtr );
600 classPtr->hIcon = (HICON16)wc->hIcon;
601 classPtr->hIconSm = (HICON16)wc->hIconSm;
602 classPtr->hCursor = (HCURSOR16)wc->hCursor;
603 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
604 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
605 WIN_PROC_32A, WIN_PROC_CLASS );
606 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
607 return atom;
611 /***********************************************************************
612 * RegisterClassExW (USER32.429)
614 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
616 ATOM atom;
617 CLASS *classPtr;
619 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
621 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
622 wc->cbClsExtra, wc->cbWndExtra )))
624 GlobalDeleteAtom( atom );
625 return 0;
628 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
629 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
630 wc->hbrBackground, wc->style, wc->cbClsExtra,
631 wc->cbWndExtra, classPtr );
633 classPtr->hIcon = (HICON16)wc->hIcon;
634 classPtr->hIconSm = (HICON16)wc->hIconSm;
635 classPtr->hCursor = (HCURSOR16)wc->hCursor;
636 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
637 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
638 WIN_PROC_32W, WIN_PROC_CLASS );
639 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
640 return atom;
644 /***********************************************************************
645 * UnregisterClass16 (USER.403)
647 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
649 return UnregisterClassA( className, GetExePtr( hInstance ) );
653 /***********************************************************************
654 * UnregisterClassA (USER32.563)
657 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
659 CLASS *classPtr;
660 ATOM atom;
662 TRACE("%s %x\n",debugres_a(className), hInstance);
664 if (!(atom = GlobalFindAtomA( className )))
666 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
667 return FALSE;
669 if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
670 (classPtr->hInstance != hInstance))
672 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
673 return FALSE;
675 return CLASS_FreeClass( classPtr );
678 /***********************************************************************
679 * UnregisterClassW (USER32.564)
681 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
683 CLASS *classPtr;
684 ATOM atom;
686 TRACE("%s %x\n",debugres_w(className), hInstance);
688 if (!(atom = GlobalFindAtomW( className )))
690 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
691 return FALSE;
693 if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
694 (classPtr->hInstance != hInstance))
696 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
697 return FALSE;
699 return CLASS_FreeClass( classPtr );
702 /***********************************************************************
703 * GetClassWord16 (USER.129)
705 WORD WINAPI GetClassWord16( HWND16 hwnd, INT16 offset )
707 return GetClassWord( hwnd, offset );
711 /***********************************************************************
712 * GetClassWord (USER32.219)
714 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
716 WND * wndPtr;
717 WORD retvalue = 0;
719 TRACE("%x %x\n",hwnd, offset);
721 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
722 if (offset >= 0)
724 if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
726 retvalue = GET_WORD(((char *)wndPtr->class->wExtra) + offset);
727 goto END;
730 else switch(offset)
732 case GCW_HBRBACKGROUND: retvalue = wndPtr->class->hbrBackground;
733 goto END;
734 case GCW_HCURSOR: retvalue = wndPtr->class->hCursor;
735 goto END;
736 case GCW_HICON: retvalue = wndPtr->class->hIcon;
737 goto END;
738 case GCW_HICONSM: retvalue = wndPtr->class->hIconSm;
739 goto END;
740 case GCW_ATOM: retvalue = wndPtr->class->atomName;
741 goto END;
742 case GCW_STYLE:
743 case GCW_CBWNDEXTRA:
744 case GCW_CBCLSEXTRA:
745 case GCW_HMODULE:
746 retvalue = (WORD)GetClassLongA( hwnd, offset );
747 goto END;
750 WARN("Invalid offset %d\n", offset);
751 END:
752 WIN_ReleaseWndPtr(wndPtr);
753 return retvalue;
757 /***********************************************************************
758 * GetClassLong16 (USER.131)
760 LONG WINAPI GetClassLong16( HWND16 hwnd, INT16 offset )
762 WND *wndPtr;
763 LONG ret;
765 TRACE("%x %x\n",hwnd, offset);
767 switch( offset )
769 case GCL_WNDPROC:
770 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
771 ret = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_16 );
772 WIN_ReleaseWndPtr(wndPtr);
773 return ret;
774 case GCL_MENUNAME:
775 ret = GetClassLongA( hwnd, offset );
776 return (LONG)SEGPTR_GET( (void *)ret );
777 default:
778 return GetClassLongA( hwnd, offset );
783 /***********************************************************************
784 * GetClassLongA (USER32.215)
786 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
788 WND * wndPtr;
789 LONG retvalue;
791 TRACE("%x %x\n",hwnd, offset);
793 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
794 if (offset >= 0)
796 if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
798 retvalue = GET_DWORD(((char *)wndPtr->class->wExtra) + offset);
799 goto END;
803 switch(offset)
805 case GCL_STYLE: retvalue = (LONG)wndPtr->class->style;
806 goto END;
807 case GCL_CBWNDEXTRA: retvalue = (LONG)wndPtr->class->cbWndExtra;
808 goto END;
809 case GCL_CBCLSEXTRA: retvalue = (LONG)wndPtr->class->cbClsExtra;
810 goto END;
811 case GCL_HMODULE: retvalue = (LONG)wndPtr->class->hInstance;
812 goto END;
813 case GCL_WNDPROC:
814 retvalue = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_32A );
815 goto END;
816 case GCL_MENUNAME:
817 retvalue = (LONG)CLASS_GetMenuNameA( wndPtr->class );
818 goto END;
819 case GCW_ATOM:
820 case GCL_HBRBACKGROUND:
821 case GCL_HCURSOR:
822 case GCL_HICON:
823 case GCL_HICONSM:
824 retvalue = GetClassWord( hwnd, offset );
825 goto END;
827 WARN("Invalid offset %d\n", offset);
828 retvalue = 0;
829 END:
830 WIN_ReleaseWndPtr(wndPtr);
831 return retvalue;
835 /***********************************************************************
836 * GetClassLongW (USER32.216)
838 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
840 WND * wndPtr;
841 LONG retvalue;
843 TRACE("%x %x\n",hwnd, offset);
845 switch(offset)
847 case GCL_WNDPROC:
848 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
849 retvalue = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_32W );
850 WIN_ReleaseWndPtr(wndPtr);
851 return retvalue;
852 case GCL_MENUNAME:
853 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
854 retvalue = (LONG)CLASS_GetMenuNameW( wndPtr->class );
855 WIN_ReleaseWndPtr(wndPtr);
856 return retvalue;
857 default:
858 return GetClassLongA( hwnd, offset );
863 /***********************************************************************
864 * SetClassWord16 (USER.130)
866 WORD WINAPI SetClassWord16( HWND16 hwnd, INT16 offset, WORD newval )
868 return SetClassWord( hwnd, offset, newval );
872 /***********************************************************************
873 * SetClassWord (USER32.469)
875 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
877 WND * wndPtr;
878 WORD retval = 0;
879 void *ptr;
881 TRACE("%x %x %x\n",hwnd, offset, newval);
883 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
884 if (offset >= 0)
886 if (offset + sizeof(WORD) <= wndPtr->class->cbClsExtra)
887 ptr = ((char *)wndPtr->class->wExtra) + offset;
888 else
890 WARN("Invalid offset %d\n", offset );
891 WIN_ReleaseWndPtr(wndPtr);
892 return 0;
895 else switch(offset)
897 case GCW_STYLE:
898 case GCW_CBWNDEXTRA:
899 case GCW_CBCLSEXTRA:
900 case GCW_HMODULE:
901 WIN_ReleaseWndPtr(wndPtr);
902 return (WORD)SetClassLongA( hwnd, offset, (LONG)newval );
903 case GCW_HBRBACKGROUND: ptr = &wndPtr->class->hbrBackground; break;
904 case GCW_HCURSOR: ptr = &wndPtr->class->hCursor; break;
905 case GCW_HICON: ptr = &wndPtr->class->hIcon; break;
906 case GCW_HICONSM: ptr = &wndPtr->class->hIconSm; break;
907 case GCW_ATOM: ptr = &wndPtr->class->atomName; break;
908 default:
909 WARN("Invalid offset %d\n", offset);
910 WIN_ReleaseWndPtr(wndPtr);
911 return 0;
913 retval = GET_WORD(ptr);
914 PUT_WORD( ptr, newval );
915 WIN_ReleaseWndPtr(wndPtr);
916 return retval;
920 /***********************************************************************
921 * SetClassLong16 (USER.132)
923 LONG WINAPI SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
925 WND *wndPtr;
926 LONG retval;
928 TRACE("%x %x %lx\n",hwnd, offset, newval);
930 switch(offset)
932 case GCL_WNDPROC:
933 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
934 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_16 );
935 WIN_ReleaseWndPtr(wndPtr);
936 return retval;
937 case GCL_MENUNAME:
938 return SetClassLongA( hwnd, offset, (LONG)MapSL(newval) );
939 default:
940 return SetClassLongA( hwnd, offset, newval );
945 /***********************************************************************
946 * SetClassLongA (USER32.467)
948 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
950 WND * wndPtr;
951 LONG retval = 0;
952 void *ptr;
954 TRACE("%x %x %lx\n",hwnd, offset, newval);
956 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
957 if (offset >= 0)
959 if (offset + sizeof(LONG) <= wndPtr->class->cbClsExtra)
960 ptr = ((char *)wndPtr->class->wExtra) + offset;
961 else
963 WARN("Invalid offset %d\n", offset );
964 retval = 0;
965 goto END;
968 else switch(offset)
970 case GCL_MENUNAME:
971 CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
972 retval = 0; /* Old value is now meaningless anyway */
973 goto END;
974 case GCL_WNDPROC:
975 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_32A );
976 goto END;
977 case GCL_HBRBACKGROUND:
978 case GCL_HCURSOR:
979 case GCL_HICON:
980 case GCL_HICONSM:
981 retval = SetClassWord( hwnd, offset, (WORD)newval );
982 goto END;
983 case GCL_STYLE: ptr = &wndPtr->class->style; break;
984 case GCL_CBWNDEXTRA: ptr = &wndPtr->class->cbWndExtra; break;
985 case GCL_CBCLSEXTRA: ptr = &wndPtr->class->cbClsExtra; break;
986 case GCL_HMODULE: ptr = &wndPtr->class->hInstance; break;
987 default:
988 WARN("Invalid offset %d\n", offset );
989 retval = 0;
990 goto END;
992 retval = GET_DWORD(ptr);
993 PUT_DWORD( ptr, newval );
994 END:
995 WIN_ReleaseWndPtr(wndPtr);
996 return retval;
1000 /***********************************************************************
1001 * SetClassLongW (USER32.468)
1003 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1005 WND *wndPtr;
1006 LONG retval;
1008 TRACE("%x %x %lx\n",hwnd, offset, newval);
1010 switch(offset)
1012 case GCL_WNDPROC:
1013 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1014 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_32W );
1015 WIN_ReleaseWndPtr(wndPtr);
1016 return retval;
1017 case GCL_MENUNAME:
1018 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1019 CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
1020 WIN_ReleaseWndPtr(wndPtr);
1021 return 0; /* Old value is now meaningless anyway */
1022 default:
1023 return SetClassLongA( hwnd, offset, newval );
1028 /***********************************************************************
1029 * GetClassName16 (USER.58)
1031 INT16 WINAPI GetClassName16( HWND16 hwnd, LPSTR buffer, INT16 count )
1033 return GetClassNameA( hwnd, buffer, count );
1037 /***********************************************************************
1038 * GetClassNameA (USER32.217)
1040 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1041 { INT ret;
1042 WND *wndPtr;
1044 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1045 ret = GlobalGetAtomNameA( wndPtr->class->atomName, buffer, count );
1047 WIN_ReleaseWndPtr(wndPtr);
1048 TRACE("%x %s %x\n",hwnd, buffer, count);
1049 return ret;
1053 /***********************************************************************
1054 * GetClassNameW (USER32.218)
1056 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1057 { INT ret;
1058 WND *wndPtr;
1060 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1061 ret = GlobalGetAtomNameW( wndPtr->class->atomName, buffer, count );
1062 WIN_ReleaseWndPtr(wndPtr);
1063 TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
1065 return ret;
1069 /***********************************************************************
1070 * GetClassInfo16 (USER.404)
1072 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASS16 *wc )
1074 ATOM atom;
1075 CLASS *classPtr;
1077 TRACE("%x %s %p\n",hInstance, debugres_a(MapSL(name)), wc);
1079 hInstance = GetExePtr( hInstance );
1080 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1081 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1082 return FALSE;
1083 if ((hInstance != classPtr->hInstance) &&
1084 !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
1085 return FALSE;
1086 wc->style = (UINT16)classPtr->style;
1087 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1088 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1089 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1090 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1091 wc->hIcon = classPtr->hIcon;
1092 wc->hCursor = classPtr->hCursor;
1093 wc->hbrBackground = classPtr->hbrBackground;
1094 wc->lpszClassName = name;
1095 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1096 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1097 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1098 return TRUE;
1102 /***********************************************************************
1103 * GetClassInfoA (USER32.211)
1105 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
1106 WNDCLASSA *wc )
1108 ATOM atom;
1109 CLASS *classPtr;
1111 TRACE("%x %p %p\n",hInstance, name, wc);
1113 /* workaround: if hInstance=NULL you expect to get the system classes
1114 but this classes (as example from comctl32.dll SysListView) won't be
1115 registered with hInstance=NULL in WINE because of the late loading
1116 of this dll. fixes file dialogs in WinWord95 (jsch)*/
1118 if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
1119 return FALSE;
1121 if (!(classPtr->style & CS_GLOBALCLASS) &&
1122 classPtr->hInstance &&
1123 (hInstance != classPtr->hInstance))
1125 if (hInstance) return FALSE;
1126 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
1129 wc->style = classPtr->style;
1130 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1131 wc->cbClsExtra = classPtr->cbClsExtra;
1132 wc->cbWndExtra = classPtr->cbWndExtra;
1133 wc->hInstance = hInstance;
1134 wc->hIcon = (HICON)classPtr->hIcon;
1135 wc->hCursor = (HCURSOR)classPtr->hCursor;
1136 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1137 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1138 wc->lpszClassName = name;
1139 return TRUE;
1143 /***********************************************************************
1144 * GetClassInfoW (USER32.214)
1146 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
1147 WNDCLASSW *wc )
1149 ATOM atom;
1150 CLASS *classPtr;
1152 TRACE("%x %p %p\n",hInstance, name, wc);
1154 if ( !(atom=GlobalFindAtomW(name)) ||
1155 !(classPtr=CLASS_FindClassByAtom(atom,hInstance))
1157 return FALSE;
1159 if (!(classPtr->style & CS_GLOBALCLASS) &&
1160 classPtr->hInstance &&
1161 (hInstance != classPtr->hInstance))
1163 if (hInstance) return FALSE;
1164 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",debugstr_w(name));
1166 wc->style = classPtr->style;
1167 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1168 wc->cbClsExtra = classPtr->cbClsExtra;
1169 wc->cbWndExtra = classPtr->cbWndExtra;
1170 wc->hInstance = hInstance;
1171 wc->hIcon = (HICON)classPtr->hIcon;
1172 wc->hCursor = (HCURSOR)classPtr->hCursor;
1173 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1174 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1175 wc->lpszClassName = name;
1176 return TRUE;
1180 /***********************************************************************
1181 * GetClassInfoEx16 (USER.398)
1183 * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1184 * same in Win16 as in Win32. --AJ
1186 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASSEX16 *wc )
1188 ATOM atom;
1189 CLASS *classPtr;
1191 TRACE("%x %s %p\n",hInstance,debugres_a( MapSL(name) ), wc);
1193 hInstance = GetExePtr( hInstance );
1194 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1195 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1196 (hInstance != classPtr->hInstance)) return FALSE;
1197 wc->style = classPtr->style;
1198 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1199 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1200 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1201 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1202 wc->hIcon = classPtr->hIcon;
1203 wc->hIconSm = classPtr->hIconSm;
1204 wc->hCursor = classPtr->hCursor;
1205 wc->hbrBackground = classPtr->hbrBackground;
1206 wc->lpszClassName = (SEGPTR)0;
1207 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1208 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1209 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1210 wc->lpszClassName = name;
1212 /* We must return the atom of the class here instead of just TRUE. */
1213 return atom;
1217 /***********************************************************************
1218 * GetClassInfoExA (USER32.212)
1220 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1221 WNDCLASSEXA *wc )
1223 ATOM atom;
1224 CLASS *classPtr;
1226 TRACE("%x %p %p\n",hInstance, name, wc);
1228 if (!(atom = GlobalFindAtomA( name )) ||
1229 !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))
1230 /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
1231 wc->style = classPtr->style;
1232 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1233 wc->cbClsExtra = classPtr->cbClsExtra;
1234 wc->cbWndExtra = classPtr->cbWndExtra;
1235 wc->hInstance = classPtr->hInstance;
1236 wc->hIcon = (HICON)classPtr->hIcon;
1237 wc->hIconSm = (HICON)classPtr->hIconSm;
1238 wc->hCursor = (HCURSOR)classPtr->hCursor;
1239 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1240 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1241 wc->lpszClassName = name;
1243 /* We must return the atom of the class here instead of just TRUE. */
1244 return atom;
1248 /***********************************************************************
1249 * GetClassInfoExW (USER32.213)
1251 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1252 WNDCLASSEXW *wc )
1254 ATOM atom;
1255 CLASS *classPtr;
1257 TRACE("%x %p %p\n",hInstance, name, wc);
1259 if (!(atom = GlobalFindAtomW( name )) ||
1260 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1261 (hInstance != classPtr->hInstance)) return FALSE;
1262 wc->style = classPtr->style;
1263 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1264 wc->cbClsExtra = classPtr->cbClsExtra;
1265 wc->cbWndExtra = classPtr->cbWndExtra;
1266 wc->hInstance = classPtr->hInstance;
1267 wc->hIcon = (HICON)classPtr->hIcon;
1268 wc->hIconSm = (HICON)classPtr->hIconSm;
1269 wc->hCursor = (HCURSOR)classPtr->hCursor;
1270 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1271 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1272 wc->lpszClassName = name;
1274 /* We must return the atom of the class here instead of just TRUE. */
1275 return atom;
1279 /***********************************************************************
1280 * ClassFirst (TOOLHELP.69)
1282 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1284 TRACE("%p\n",pClassEntry);
1285 pClassEntry->wNext = 1;
1286 return ClassNext16( pClassEntry );
1290 /***********************************************************************
1291 * ClassNext (TOOLHELP.70)
1293 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1295 int i;
1296 CLASS *class = firstClass;
1298 TRACE("%p\n",pClassEntry);
1300 if (!pClassEntry->wNext) return FALSE;
1301 for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1302 if (!class)
1304 pClassEntry->wNext = 0;
1305 return FALSE;
1307 pClassEntry->hInst = class->hInstance;
1308 pClassEntry->wNext++;
1309 GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1310 sizeof(pClassEntry->szClassName) );
1311 return TRUE;