Add SHGetSpecialFolderPathW to spec file.
[wine.git] / windows / class.c
blob83998bcd9e428dc50edd0109fea5bf19d8fc39bf
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 "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 } CLASS;
53 static CLASS *firstClass;
56 /***********************************************************************
57 * CLASS_GetProc
59 * Get the class winproc for a given proc type
61 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
63 HWINDOWPROC proc = classPtr->winprocA;
65 if (classPtr->winprocW)
67 /* if we have a Unicode proc, use it if we have no ASCII proc
68 * or if we have both and Unicode was requested
70 if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
72 return WINPROC_GetProc( proc, type );
76 /***********************************************************************
77 * CLASS_SetProc
79 * Set the class winproc for a given proc type.
80 * Returns the previous window proc.
82 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
84 HWINDOWPROC *proc = &classPtr->winprocA;
85 WNDPROC16 ret;
87 if (classPtr->winprocW)
89 /* if we have a Unicode proc, use it if we have no ASCII proc
90 * or if we have both and Unicode was requested
92 if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
94 ret = WINPROC_GetProc( *proc, type );
95 WINPROC_SetProc( proc, (HWINDOWPROC)newproc, type, WIN_PROC_CLASS );
96 /* now free the one that we didn't set */
97 if (classPtr->winprocA && classPtr->winprocW)
99 if (proc == &classPtr->winprocA)
101 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
102 classPtr->winprocW = 0;
104 else
106 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
107 classPtr->winprocA = 0;
110 return ret;
114 /***********************************************************************
115 * CLASS_GetMenuNameA
117 * Get the menu name as a ASCII string.
119 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
121 if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
122 return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
126 /***********************************************************************
127 * CLASS_GetMenuNameW
129 * Get the menu name as a Unicode string.
131 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
133 return classPtr->menuName;
137 /***********************************************************************
138 * CLASS_SetMenuNameA
140 * Set the menu name in a class structure by copying the string.
142 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
144 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
145 if (HIWORD(name))
147 DWORD lenA = strlen(name) + 1;
148 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
149 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
150 MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
151 memcpy( classPtr->menuName + lenW, name, lenA );
153 else classPtr->menuName = (LPWSTR)name;
157 /***********************************************************************
158 * CLASS_SetMenuNameW
160 * Set the menu name in a class structure by copying the string.
162 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
164 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
165 if (HIWORD(name))
167 DWORD lenW = strlenW(name) + 1;
168 DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
169 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
170 memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
171 WideCharToMultiByte( CP_ACP, 0, name, lenW,
172 (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
174 else classPtr->menuName = (LPWSTR)name;
178 /***********************************************************************
179 * CLASS_FreeClass
181 * Free a class structure.
183 static BOOL CLASS_FreeClass( CLASS *classPtr )
185 TRACE("%p\n", classPtr);
187 /* Check if we can remove this class */
189 if (classPtr->cWindows > 0)
191 SetLastError( ERROR_CLASS_HAS_WINDOWS );
192 return FALSE;
195 /* Remove the class from the linked list */
197 if (classPtr->next) classPtr->next->prev = classPtr->prev;
198 if (classPtr->prev) classPtr->prev->next = classPtr->next;
199 else firstClass = classPtr->next;
201 /* Delete the class */
203 if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
204 if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
205 DeleteObject( classPtr->hbrBackground );
206 GlobalDeleteAtom( classPtr->atomName );
207 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
208 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
209 HeapFree( GetProcessHeap(), 0, classPtr->menuName );
210 HeapFree( GetProcessHeap(), 0, classPtr );
211 return TRUE;
215 /***********************************************************************
216 * CLASS_FreeModuleClasses
218 void CLASS_FreeModuleClasses( HMODULE16 hModule )
220 CLASS *ptr, *next;
222 TRACE("0x%08x\n", hModule);
224 for (ptr = firstClass; ptr; ptr = next)
226 next = ptr->next;
227 if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
232 /***********************************************************************
233 * CLASS_FindClassByAtom
235 * Return a pointer to the class.
236 * hinstance has been normalized by the caller.
238 * NOTES
239 * 980805 a local class will be found now if registred with hInst=0
240 * and looed up with a hInst!=0. msmoney does it (jsch)
242 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
244 CLASS * class, *tclass=0;
246 TRACE("0x%08x 0x%08x\n", atom, hinstance);
248 /* First search task-specific classes */
250 for (class = firstClass; (class); class = class->next)
252 if (class->style & CS_GLOBALCLASS) continue;
253 if (class->atomName == atom)
255 if (hinstance==class->hInstance || hinstance==0xffff )
257 TRACE("-- found local %p\n", class);
258 return class;
260 if (class->hInstance==0) tclass = class;
264 /* Then search global classes */
266 for (class = firstClass; (class); class = class->next)
268 if (!(class->style & CS_GLOBALCLASS)) continue;
269 if (class->atomName == atom)
271 TRACE("-- found global %p\n", class);
272 return class;
276 /* Then check if there was a local class with hInst=0*/
277 if ( tclass )
279 WARN("-- found local Class registred with hInst=0\n");
280 return tclass;
283 TRACE("-- not found\n");
284 return 0;
288 /***********************************************************************
289 * CLASS_RegisterClass
291 * The real RegisterClass() functionality.
293 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
294 DWORD style, INT classExtra, INT winExtra )
296 CLASS *classPtr;
298 TRACE("atom=0x%x hinst=0x%x style=0x%lx clExtr=0x%x winExtr=0x%x\n",
299 atom, hInstance, style, classExtra, winExtra );
301 /* Check if a class with this name already exists */
302 classPtr = CLASS_FindClassByAtom( atom, hInstance );
303 if (classPtr)
305 /* Class can be created only if it is local and */
306 /* if the class with the same name is global. */
308 if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
310 SetLastError( ERROR_CLASS_ALREADY_EXISTS );
311 return NULL;
315 /* Fix the extra bytes value */
317 if (classExtra < 0) classExtra = 0;
318 else if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
319 WARN("Class extra bytes %d is > 40\n", classExtra);
320 if (winExtra < 0) winExtra = 0;
321 else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
322 WARN("Win extra bytes %d is > 40\n", winExtra );
324 /* Create the class */
326 classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
327 if (!classPtr) return NULL;
328 classPtr->style = style;
329 classPtr->cbWndExtra = winExtra;
330 classPtr->cbClsExtra = classExtra;
331 classPtr->hInstance = hInstance;
332 classPtr->atomName = atom;
333 classPtr->dce = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
335 /* Other non-null values must be set by caller */
337 if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
338 firstClass = classPtr;
339 return classPtr;
343 /***********************************************************************
344 * CLASS_RegisterBuiltinClass
346 * Register a builtin control class.
347 * This allows having both ASCII and Unicode winprocs for the same class.
349 ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
351 ATOM atom;
352 CLASS *classPtr;
354 if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
356 if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
358 GlobalDeleteAtom( atom );
359 return 0;
362 classPtr->hCursor = LoadCursorA( 0, descr->cursor );
363 classPtr->hbrBackground = descr->brush;
365 if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)descr->procA,
366 WIN_PROC_32A, WIN_PROC_CLASS );
367 if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)descr->procW,
368 WIN_PROC_32W, WIN_PROC_CLASS );
369 return atom;
373 /***********************************************************************
374 * CLASS_AddWindow
376 * Add a new window using this class, and return the necessary
377 * information for creating the window.
379 CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
380 INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
382 CLASS *class;
383 if (type == WIN_PROC_16) inst = GetExePtr(inst);
385 if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
386 class->cWindows++;
388 if (type == WIN_PROC_32W)
390 if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
392 else
394 if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
396 *winExtra = class->cbWndExtra;
397 *style = class->style;
398 *dce = class->dce;
399 return class;
403 /***********************************************************************
404 * CLASS_RemoveWindow
406 * Remove a window from the class window count.
408 void CLASS_RemoveWindow( CLASS *cls )
410 if (cls && cls->cWindows) cls->cWindows--;
414 /***********************************************************************
415 * RegisterClass (USER.57)
417 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
419 ATOM atom;
420 CLASS *classPtr;
421 int iSmIconWidth, iSmIconHeight;
422 HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
424 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
425 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
426 wc->cbClsExtra, wc->cbWndExtra )))
428 GlobalDeleteAtom( atom );
429 return 0;
432 TRACE("atom=%04x wndproc=%08lx hinst=%04x "
433 "bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
434 atom, (DWORD)wc->lpfnWndProc, hInstance,
435 wc->hbrBackground, wc->style, wc->cbClsExtra,
436 wc->cbWndExtra, classPtr,
437 HIWORD(wc->lpszClassName) ?
438 (char *)MapSL(wc->lpszClassName) : "" );
440 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
441 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
443 classPtr->hIcon = wc->hIcon;
444 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
445 iSmIconWidth, iSmIconHeight,
446 LR_COPYFROMRESOURCE);
447 classPtr->hCursor = wc->hCursor;
448 classPtr->hbrBackground = wc->hbrBackground;
450 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
451 WIN_PROC_16, WIN_PROC_CLASS );
452 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
454 return atom;
458 /***********************************************************************
459 * RegisterClassA (USER32.@)
460 * RETURNS
461 * >0: Unique identifier
462 * 0: Failure
464 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
466 ATOM atom;
467 int iSmIconWidth, iSmIconHeight;
468 CLASS *classPtr;
470 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
472 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
473 wc->cbClsExtra, wc->cbWndExtra )))
475 GlobalDeleteAtom( atom );
476 return 0;
479 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
480 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
481 wc->hbrBackground, wc->style, wc->cbClsExtra,
482 wc->cbWndExtra, classPtr,
483 HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
485 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
486 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
488 classPtr->hIcon = wc->hIcon;
489 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
490 iSmIconWidth, iSmIconHeight,
491 LR_COPYFROMRESOURCE);
492 classPtr->hCursor = (HCURSOR16)wc->hCursor;
493 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
495 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
496 WIN_PROC_32A, WIN_PROC_CLASS );
497 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
498 return atom;
502 /***********************************************************************
503 * RegisterClassW (USER32.@)
505 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
507 ATOM atom;
508 int iSmIconWidth, iSmIconHeight;
509 CLASS *classPtr;
511 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
513 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
514 wc->cbClsExtra, wc->cbWndExtra )))
516 GlobalDeleteAtom( atom );
517 return 0;
520 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
521 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
522 wc->hbrBackground, wc->style, wc->cbClsExtra,
523 wc->cbWndExtra, classPtr );
525 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
526 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
528 classPtr->hIcon = wc->hIcon;
529 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
530 iSmIconWidth, iSmIconHeight,
531 LR_COPYFROMRESOURCE);
532 classPtr->hCursor = (HCURSOR16)wc->hCursor;
533 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
535 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
536 WIN_PROC_32W, WIN_PROC_CLASS );
537 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
538 return atom;
542 /***********************************************************************
543 * RegisterClassEx (USER.397)
545 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
547 ATOM atom;
548 CLASS *classPtr;
549 HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
551 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
552 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
553 wc->cbClsExtra, wc->cbWndExtra )))
555 GlobalDeleteAtom( atom );
556 return 0;
559 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
560 atom, (DWORD)wc->lpfnWndProc, hInstance,
561 wc->hbrBackground, wc->style, wc->cbClsExtra,
562 wc->cbWndExtra, classPtr );
564 classPtr->hIcon = wc->hIcon;
565 classPtr->hIconSm = wc->hIconSm;
566 classPtr->hCursor = wc->hCursor;
567 classPtr->hbrBackground = wc->hbrBackground;
569 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
570 WIN_PROC_16, WIN_PROC_CLASS );
571 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
572 return atom;
576 /***********************************************************************
577 * RegisterClassExA (USER32.@)
579 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
581 ATOM atom;
582 CLASS *classPtr;
584 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
586 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
587 wc->cbClsExtra, wc->cbWndExtra )))
589 GlobalDeleteAtom( atom );
590 return 0;
593 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
594 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
595 wc->hbrBackground, wc->style, wc->cbClsExtra,
596 wc->cbWndExtra, classPtr );
598 classPtr->hIcon = (HICON16)wc->hIcon;
599 classPtr->hIconSm = (HICON16)wc->hIconSm;
600 classPtr->hCursor = (HCURSOR16)wc->hCursor;
601 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
602 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
603 WIN_PROC_32A, WIN_PROC_CLASS );
604 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
605 return atom;
609 /***********************************************************************
610 * RegisterClassExW (USER32.@)
612 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
614 ATOM atom;
615 CLASS *classPtr;
617 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
619 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
620 wc->cbClsExtra, wc->cbWndExtra )))
622 GlobalDeleteAtom( atom );
623 return 0;
626 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
627 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
628 wc->hbrBackground, wc->style, wc->cbClsExtra,
629 wc->cbWndExtra, classPtr );
631 classPtr->hIcon = (HICON16)wc->hIcon;
632 classPtr->hIconSm = (HICON16)wc->hIconSm;
633 classPtr->hCursor = (HCURSOR16)wc->hCursor;
634 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
635 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
636 WIN_PROC_32W, WIN_PROC_CLASS );
637 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
638 return atom;
642 /***********************************************************************
643 * UnregisterClass (USER.403)
645 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
647 return UnregisterClassA( className, GetExePtr( hInstance ) );
651 /***********************************************************************
652 * UnregisterClassA (USER32.@)
655 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
657 CLASS *classPtr;
658 ATOM atom;
660 TRACE("%s %x\n",debugres_a(className), hInstance);
662 if (!(atom = GlobalFindAtomA( className )))
664 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
665 return FALSE;
667 if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
668 (classPtr->hInstance != hInstance))
670 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
671 return FALSE;
673 return CLASS_FreeClass( classPtr );
676 /***********************************************************************
677 * UnregisterClassW (USER32.@)
679 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
681 CLASS *classPtr;
682 ATOM atom;
684 TRACE("%s %x\n",debugres_w(className), hInstance);
686 if (!(atom = GlobalFindAtomW( className )))
688 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
689 return FALSE;
691 if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
692 (classPtr->hInstance != hInstance))
694 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
695 return FALSE;
697 return CLASS_FreeClass( classPtr );
700 /***********************************************************************
701 * GetClassWord (USER.129)
703 WORD WINAPI GetClassWord16( HWND16 hwnd, INT16 offset )
705 return GetClassWord( hwnd, offset );
709 /***********************************************************************
710 * GetClassWord (USER32.@)
712 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
714 WND * wndPtr;
715 WORD retvalue = 0;
717 TRACE("%x %x\n",hwnd, offset);
719 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
720 if (offset >= 0)
722 if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
724 retvalue = GET_WORD((char *)(wndPtr->class + 1) + offset);
725 goto END;
728 else switch(offset)
730 case GCW_ATOM:
731 retvalue = wndPtr->class->atomName;
732 goto END;
733 case GCL_HBRBACKGROUND:
734 case GCL_HCURSOR:
735 case GCL_HICON:
736 case GCL_HICONSM:
737 case GCL_STYLE:
738 case GCL_CBWNDEXTRA:
739 case GCL_CBCLSEXTRA:
740 case GCL_HMODULE:
741 retvalue = (WORD)GetClassLongA( hwnd, offset );
742 goto END;
745 WARN("Invalid offset %d\n", offset);
746 END:
747 WIN_ReleaseWndPtr(wndPtr);
748 return retvalue;
752 /***********************************************************************
753 * GetClassLong (USER.131)
755 LONG WINAPI GetClassLong16( HWND16 hwnd, INT16 offset )
757 WND *wndPtr;
758 LONG ret;
760 TRACE("%x %x\n",hwnd, offset);
762 switch( offset )
764 case GCL_WNDPROC:
765 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
766 ret = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_16 );
767 WIN_ReleaseWndPtr(wndPtr);
768 return ret;
769 case GCL_MENUNAME:
770 ret = GetClassLongA( hwnd, offset );
771 return (LONG)SEGPTR_GET( (void *)ret );
772 default:
773 return GetClassLongA( hwnd, offset );
778 /***********************************************************************
779 * GetClassLongA (USER32.@)
781 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
783 WND * wndPtr;
784 LONG retvalue;
786 TRACE("%x %x\n",hwnd, offset);
788 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
789 if (offset >= 0)
791 if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
793 retvalue = GET_DWORD((char *)(wndPtr->class + 1) + offset);
794 goto END;
798 switch(offset)
800 case GCL_HBRBACKGROUND:
801 retvalue = (LONG)wndPtr->class->hbrBackground;
802 goto END;
803 case GCL_HCURSOR:
804 retvalue = (LONG)wndPtr->class->hCursor;
805 goto END;
806 case GCL_HICON:
807 retvalue = (LONG)wndPtr->class->hIcon;
808 goto END;
809 case GCL_HICONSM:
810 retvalue = (LONG)wndPtr->class->hIconSm;
811 goto END;
812 case GCL_STYLE:
813 retvalue = (LONG)wndPtr->class->style;
814 goto END;
815 case GCL_CBWNDEXTRA:
816 retvalue = (LONG)wndPtr->class->cbWndExtra;
817 goto END;
818 case GCL_CBCLSEXTRA:
819 retvalue = (LONG)wndPtr->class->cbClsExtra;
820 goto END;
821 case GCL_HMODULE:
822 retvalue = (LONG)wndPtr->class->hInstance;
823 goto END;
824 case GCL_WNDPROC:
825 retvalue = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_32A );
826 goto END;
827 case GCL_MENUNAME:
828 retvalue = (LONG)CLASS_GetMenuNameA( wndPtr->class );
829 goto END;
830 case GCW_ATOM:
831 retvalue = GetClassWord( hwnd, offset );
832 goto END;
834 WARN("Invalid offset %d\n", offset);
835 retvalue = 0;
836 END:
837 WIN_ReleaseWndPtr(wndPtr);
838 return retvalue;
842 /***********************************************************************
843 * GetClassLongW (USER32.@)
845 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
847 WND * wndPtr;
848 LONG retvalue;
850 TRACE("%x %x\n",hwnd, offset);
852 switch(offset)
854 case GCL_WNDPROC:
855 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
856 retvalue = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_32W );
857 WIN_ReleaseWndPtr(wndPtr);
858 return retvalue;
859 case GCL_MENUNAME:
860 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
861 retvalue = (LONG)CLASS_GetMenuNameW( wndPtr->class );
862 WIN_ReleaseWndPtr(wndPtr);
863 return retvalue;
864 default:
865 return GetClassLongA( hwnd, offset );
870 /***********************************************************************
871 * SetClassWord (USER.130)
873 WORD WINAPI SetClassWord16( HWND16 hwnd, INT16 offset, WORD newval )
875 return SetClassWord( hwnd, offset, newval );
879 /***********************************************************************
880 * SetClassWord (USER32.@)
882 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
884 WND * wndPtr;
885 WORD retval = 0;
886 void *ptr;
888 TRACE("%x %x %x\n",hwnd, offset, newval);
890 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
891 if (offset >= 0)
893 if (offset + sizeof(WORD) <= wndPtr->class->cbClsExtra)
894 ptr = (char *)(wndPtr->class + 1) + offset;
895 else
897 WARN("Invalid offset %d\n", offset );
898 WIN_ReleaseWndPtr(wndPtr);
899 return 0;
902 else switch(offset)
904 case GCL_HBRBACKGROUND:
905 case GCL_HCURSOR:
906 case GCL_HICON:
907 case GCL_HICONSM:
908 case GCL_STYLE:
909 case GCL_CBWNDEXTRA:
910 case GCL_CBCLSEXTRA:
911 case GCL_HMODULE:
912 WIN_ReleaseWndPtr(wndPtr);
913 return (WORD)SetClassLongA( hwnd, offset, (LONG)newval );
914 case GCW_ATOM:
915 ptr = &wndPtr->class->atomName;
916 break;
917 default:
918 WARN("Invalid offset %d\n", offset);
919 WIN_ReleaseWndPtr(wndPtr);
920 return 0;
922 retval = GET_WORD(ptr);
923 PUT_WORD( ptr, newval );
924 WIN_ReleaseWndPtr(wndPtr);
925 return retval;
929 /***********************************************************************
930 * SetClassLong (USER.132)
932 LONG WINAPI SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
934 WND *wndPtr;
935 LONG retval;
937 TRACE("%x %x %lx\n",hwnd, offset, newval);
939 switch(offset)
941 case GCL_WNDPROC:
942 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
943 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_16 );
944 WIN_ReleaseWndPtr(wndPtr);
945 return retval;
946 case GCL_MENUNAME:
947 return SetClassLongA( hwnd, offset, (LONG)MapSL(newval) );
948 default:
949 return SetClassLongA( hwnd, offset, newval );
954 /***********************************************************************
955 * SetClassLongA (USER32.@)
957 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
959 WND * wndPtr;
960 LONG retval = 0;
961 void *ptr;
963 TRACE("%x %x %lx\n",hwnd, offset, newval);
965 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
966 if (offset >= 0)
968 if (offset + sizeof(LONG) <= wndPtr->class->cbClsExtra)
969 ptr = (char *)(wndPtr->class + 1) + offset;
970 else
972 WARN("Invalid offset %d\n", offset );
973 retval = 0;
974 goto END;
977 else switch(offset)
979 case GCL_MENUNAME:
980 CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
981 retval = 0; /* Old value is now meaningless anyway */
982 goto END;
983 case GCL_WNDPROC:
984 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_32A );
985 goto END;
986 case GCL_HBRBACKGROUND:
987 ptr = &wndPtr->class->hbrBackground;
988 break;
989 case GCL_HCURSOR:
990 ptr = &wndPtr->class->hCursor;
991 break;
992 case GCL_HICON:
993 ptr = &wndPtr->class->hIcon;
994 break;
995 case GCL_HICONSM:
996 ptr = &wndPtr->class->hIconSm;
997 break;
998 case GCL_STYLE:
999 ptr = &wndPtr->class->style;
1000 break;
1001 case GCL_CBWNDEXTRA:
1002 ptr = &wndPtr->class->cbWndExtra;
1003 break;
1004 case GCL_CBCLSEXTRA:
1005 ptr = &wndPtr->class->cbClsExtra;
1006 break;
1007 case GCL_HMODULE:
1008 ptr = &wndPtr->class->hInstance;
1009 break;
1010 case GCW_ATOM:
1011 WIN_ReleaseWndPtr(wndPtr);
1012 return SetClassWord( hwnd, offset, newval );
1013 default:
1014 WARN("Invalid offset %d\n", offset );
1015 retval = 0;
1016 goto END;
1018 retval = GET_DWORD(ptr);
1019 PUT_DWORD( ptr, newval );
1020 END:
1021 WIN_ReleaseWndPtr(wndPtr);
1022 return retval;
1026 /***********************************************************************
1027 * SetClassLongW (USER32.@)
1029 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1031 WND *wndPtr;
1032 LONG retval;
1034 TRACE("%x %x %lx\n",hwnd, offset, newval);
1036 switch(offset)
1038 case GCL_WNDPROC:
1039 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1040 retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_32W );
1041 WIN_ReleaseWndPtr(wndPtr);
1042 return retval;
1043 case GCL_MENUNAME:
1044 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1045 CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
1046 WIN_ReleaseWndPtr(wndPtr);
1047 return 0; /* Old value is now meaningless anyway */
1048 default:
1049 return SetClassLongA( hwnd, offset, newval );
1054 /***********************************************************************
1055 * GetClassName (USER.58)
1057 INT16 WINAPI GetClassName16( HWND16 hwnd, LPSTR buffer, INT16 count )
1059 return GetClassNameA( hwnd, buffer, count );
1063 /***********************************************************************
1064 * GetClassNameA (USER32.@)
1066 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1067 { INT ret;
1068 WND *wndPtr;
1070 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1071 ret = GlobalGetAtomNameA( wndPtr->class->atomName, buffer, count );
1073 WIN_ReleaseWndPtr(wndPtr);
1074 TRACE("%x %s %x\n",hwnd, buffer, count);
1075 return ret;
1079 /***********************************************************************
1080 * GetClassNameW (USER32.@)
1082 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1083 { INT ret;
1084 WND *wndPtr;
1086 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1087 ret = GlobalGetAtomNameW( wndPtr->class->atomName, buffer, count );
1088 WIN_ReleaseWndPtr(wndPtr);
1089 TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
1091 return ret;
1095 /***********************************************************************
1096 * GetClassInfo (USER.404)
1098 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASS16 *wc )
1100 ATOM atom;
1101 CLASS *classPtr;
1103 TRACE("%x %s %p\n",hInstance, debugres_a(MapSL(name)), wc);
1105 hInstance = GetExePtr( hInstance );
1106 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1107 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1108 return FALSE;
1109 if ((hInstance != classPtr->hInstance) &&
1110 !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
1111 return FALSE;
1112 wc->style = (UINT16)classPtr->style;
1113 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1114 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1115 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1116 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1117 wc->hIcon = classPtr->hIcon;
1118 wc->hCursor = classPtr->hCursor;
1119 wc->hbrBackground = classPtr->hbrBackground;
1120 wc->lpszClassName = name;
1121 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1122 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1123 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1124 return TRUE;
1128 /***********************************************************************
1129 * GetClassInfoA (USER32.@)
1131 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
1132 WNDCLASSA *wc )
1134 ATOM atom;
1135 CLASS *classPtr;
1137 TRACE("%x %p %p\n",hInstance, name, wc);
1139 /* workaround: if hInstance=NULL you expect to get the system classes
1140 but this classes (as example from comctl32.dll SysListView) won't be
1141 registered with hInstance=NULL in WINE because of the late loading
1142 of this dll. fixes file dialogs in WinWord95 (jsch)*/
1144 if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
1145 return FALSE;
1147 if (!(classPtr->style & CS_GLOBALCLASS) &&
1148 classPtr->hInstance &&
1149 (hInstance != classPtr->hInstance))
1151 if (hInstance) return FALSE;
1152 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
1155 wc->style = classPtr->style;
1156 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1157 wc->cbClsExtra = classPtr->cbClsExtra;
1158 wc->cbWndExtra = classPtr->cbWndExtra;
1159 wc->hInstance = hInstance;
1160 wc->hIcon = (HICON)classPtr->hIcon;
1161 wc->hCursor = (HCURSOR)classPtr->hCursor;
1162 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1163 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1164 wc->lpszClassName = name;
1165 return TRUE;
1169 /***********************************************************************
1170 * GetClassInfoW (USER32.@)
1172 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
1173 WNDCLASSW *wc )
1175 ATOM atom;
1176 CLASS *classPtr;
1178 TRACE("%x %p %p\n",hInstance, name, wc);
1180 if ( !(atom=GlobalFindAtomW(name)) ||
1181 !(classPtr=CLASS_FindClassByAtom(atom,hInstance))
1183 return FALSE;
1185 if (!(classPtr->style & CS_GLOBALCLASS) &&
1186 classPtr->hInstance &&
1187 (hInstance != classPtr->hInstance))
1189 if (hInstance) return FALSE;
1190 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",debugstr_w(name));
1192 wc->style = classPtr->style;
1193 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1194 wc->cbClsExtra = classPtr->cbClsExtra;
1195 wc->cbWndExtra = classPtr->cbWndExtra;
1196 wc->hInstance = hInstance;
1197 wc->hIcon = (HICON)classPtr->hIcon;
1198 wc->hCursor = (HCURSOR)classPtr->hCursor;
1199 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1200 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1201 wc->lpszClassName = name;
1202 return TRUE;
1206 /***********************************************************************
1207 * GetClassInfoEx (USER.398)
1209 * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1210 * same in Win16 as in Win32. --AJ
1212 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASSEX16 *wc )
1214 ATOM atom;
1215 CLASS *classPtr;
1217 TRACE("%x %s %p\n",hInstance,debugres_a( MapSL(name) ), wc);
1219 hInstance = GetExePtr( hInstance );
1220 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1221 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1222 (hInstance != classPtr->hInstance)) return FALSE;
1223 wc->style = classPtr->style;
1224 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1225 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1226 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1227 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1228 wc->hIcon = classPtr->hIcon;
1229 wc->hIconSm = classPtr->hIconSm;
1230 wc->hCursor = classPtr->hCursor;
1231 wc->hbrBackground = classPtr->hbrBackground;
1232 wc->lpszClassName = (SEGPTR)0;
1233 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1234 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1235 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1236 wc->lpszClassName = name;
1238 /* We must return the atom of the class here instead of just TRUE. */
1239 return atom;
1243 /***********************************************************************
1244 * GetClassInfoExA (USER32.@)
1246 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1247 WNDCLASSEXA *wc )
1249 ATOM atom;
1250 CLASS *classPtr;
1252 TRACE("%x %p %p\n",hInstance, name, wc);
1254 if (!(atom = GlobalFindAtomA( name )) ||
1255 !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))
1256 /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
1257 wc->style = classPtr->style;
1258 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1259 wc->cbClsExtra = classPtr->cbClsExtra;
1260 wc->cbWndExtra = classPtr->cbWndExtra;
1261 wc->hInstance = classPtr->hInstance;
1262 wc->hIcon = (HICON)classPtr->hIcon;
1263 wc->hIconSm = (HICON)classPtr->hIconSm;
1264 wc->hCursor = (HCURSOR)classPtr->hCursor;
1265 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1266 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1267 wc->lpszClassName = name;
1269 /* We must return the atom of the class here instead of just TRUE. */
1270 return atom;
1274 /***********************************************************************
1275 * GetClassInfoExW (USER32.@)
1277 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1278 WNDCLASSEXW *wc )
1280 ATOM atom;
1281 CLASS *classPtr;
1283 TRACE("%x %p %p\n",hInstance, name, wc);
1285 if (!(atom = GlobalFindAtomW( name )) ||
1286 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1287 (hInstance != classPtr->hInstance)) return FALSE;
1288 wc->style = classPtr->style;
1289 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1290 wc->cbClsExtra = classPtr->cbClsExtra;
1291 wc->cbWndExtra = classPtr->cbWndExtra;
1292 wc->hInstance = classPtr->hInstance;
1293 wc->hIcon = (HICON)classPtr->hIcon;
1294 wc->hIconSm = (HICON)classPtr->hIconSm;
1295 wc->hCursor = (HCURSOR)classPtr->hCursor;
1296 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1297 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1298 wc->lpszClassName = name;
1300 /* We must return the atom of the class here instead of just TRUE. */
1301 return atom;
1305 #if 0 /* toolhelp is in kernel, so this cannot work */
1307 /***********************************************************************
1308 * ClassFirst (TOOLHELP.69)
1310 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1312 TRACE("%p\n",pClassEntry);
1313 pClassEntry->wNext = 1;
1314 return ClassNext16( pClassEntry );
1318 /***********************************************************************
1319 * ClassNext (TOOLHELP.70)
1321 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1323 int i;
1324 CLASS *class = firstClass;
1326 TRACE("%p\n",pClassEntry);
1328 if (!pClassEntry->wNext) return FALSE;
1329 for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1330 if (!class)
1332 pClassEntry->wNext = 0;
1333 return FALSE;
1335 pClassEntry->hInst = class->hInstance;
1336 pClassEntry->wNext++;
1337 GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1338 sizeof(pClassEntry->szClassName) );
1339 return TRUE;
1341 #endif