Return success in CreateProcess when we started a non-Winelib Unix
[wine/multimedia.git] / windows / class.c
blob80c03dbf023853d7765a81d5dcd32f585b9b92e6
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 "config.h"
16 #include "wine/port.h"
18 #include <stdlib.h>
19 #include <string.h>
21 #include "wine/winbase16.h"
22 #include "winerror.h"
23 #include "windef.h"
24 #include "wingdi.h"
25 #include "wine/winuser16.h"
26 #include "wine/unicode.h"
27 #include "heap.h"
28 #include "win.h"
29 #include "user.h"
30 #include "controls.h"
31 #include "dce.h"
32 #include "winproc.h"
33 #include "debugtools.h"
35 DEFAULT_DEBUG_CHANNEL(class);
37 typedef struct tagCLASS
39 struct tagCLASS *next; /* Next class */
40 struct tagCLASS *prev; /* Prev class */
41 UINT cWindows; /* Count of existing windows */
42 UINT style; /* Class style */
43 HWINDOWPROC winprocA; /* Window procedure (ASCII) */
44 HWINDOWPROC winprocW; /* Window procedure (Unicode) */
45 INT cbClsExtra; /* Class extra bytes */
46 INT cbWndExtra; /* Window extra bytes */
47 LPWSTR menuName; /* Default menu name (Unicode followed by ASCII) */
48 struct tagDCE *dce; /* Class DCE (if CS_CLASSDC) */
49 HINSTANCE hInstance; /* Module that created the task */
50 HICON hIcon; /* Default icon */
51 HICON hIconSm; /* Default small icon */
52 HCURSOR hCursor; /* Default cursor */
53 HBRUSH hbrBackground; /* Default background */
54 ATOM atomName; /* Name of the class */
55 } CLASS;
57 static CLASS *firstClass;
59 /***********************************************************************
60 * get_class_ptr
62 static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
64 WND *ptr = WIN_GetPtr( hwnd );
66 if (ptr)
68 if (ptr != WND_OTHER_PROCESS) return ptr->class;
69 if (IsWindow( hwnd )) /* check other processes */
71 if (write_access)
73 /* modifying classes in other processes is not allowed */
74 SetLastError( ERROR_ACCESS_DENIED );
75 return NULL;
77 FIXME( "reading from class of other process window %04x\n", hwnd );
78 /* DbgBreakPoint(); */
81 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
82 return NULL;
86 /***********************************************************************
87 * release_class_ptr
89 inline static void release_class_ptr( CLASS *ptr )
91 USER_Unlock();
95 /***********************************************************************
96 * CLASS_GetProc
98 * Get the class winproc for a given proc type
100 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
102 HWINDOWPROC proc = classPtr->winprocA;
104 if (classPtr->winprocW)
106 /* if we have a Unicode proc, use it if we have no ASCII proc
107 * or if we have both and Unicode was requested
109 if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
111 return WINPROC_GetProc( proc, type );
115 /***********************************************************************
116 * CLASS_SetProc
118 * Set the class winproc for a given proc type.
119 * Returns the previous window proc.
121 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
123 HWINDOWPROC *proc = &classPtr->winprocA;
124 WNDPROC16 ret;
126 if (classPtr->winprocW)
128 /* if we have a Unicode proc, use it if we have no ASCII proc
129 * or if we have both and Unicode was requested
131 if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
133 ret = WINPROC_GetProc( *proc, type );
134 WINPROC_SetProc( proc, (HWINDOWPROC)newproc, type, WIN_PROC_CLASS );
135 /* now free the one that we didn't set */
136 if (classPtr->winprocA && classPtr->winprocW)
138 if (proc == &classPtr->winprocA)
140 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
141 classPtr->winprocW = 0;
143 else
145 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
146 classPtr->winprocA = 0;
149 return ret;
153 /***********************************************************************
154 * CLASS_GetMenuNameA
156 * Get the menu name as a ASCII string.
158 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
160 if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
161 return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
165 /***********************************************************************
166 * CLASS_GetMenuNameW
168 * Get the menu name as a Unicode string.
170 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
172 return classPtr->menuName;
176 /***********************************************************************
177 * CLASS_SetMenuNameA
179 * Set the menu name in a class structure by copying the string.
181 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
183 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
184 if (HIWORD(name))
186 DWORD lenA = strlen(name) + 1;
187 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
188 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
189 MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
190 memcpy( classPtr->menuName + lenW, name, lenA );
192 else classPtr->menuName = (LPWSTR)name;
196 /***********************************************************************
197 * CLASS_SetMenuNameW
199 * Set the menu name in a class structure by copying the string.
201 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
203 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
204 if (HIWORD(name))
206 DWORD lenW = strlenW(name) + 1;
207 DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
208 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
209 memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
210 WideCharToMultiByte( CP_ACP, 0, name, lenW,
211 (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
213 else classPtr->menuName = (LPWSTR)name;
217 /***********************************************************************
218 * CLASS_FreeClass
220 * Free a class structure.
222 static BOOL CLASS_FreeClass( CLASS *classPtr )
224 TRACE("%p\n", classPtr);
226 /* Check if we can remove this class */
228 if (classPtr->cWindows > 0)
230 SetLastError( ERROR_CLASS_HAS_WINDOWS );
231 return FALSE;
234 /* Remove the class from the linked list */
236 if (classPtr->next) classPtr->next->prev = classPtr->prev;
237 if (classPtr->prev) classPtr->prev->next = classPtr->next;
238 else firstClass = classPtr->next;
240 /* Delete the class */
242 if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
243 if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
244 DeleteObject( classPtr->hbrBackground );
245 GlobalDeleteAtom( classPtr->atomName );
246 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
247 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
248 HeapFree( GetProcessHeap(), 0, classPtr->menuName );
249 HeapFree( GetProcessHeap(), 0, classPtr );
250 return TRUE;
254 /***********************************************************************
255 * CLASS_FreeModuleClasses
257 void CLASS_FreeModuleClasses( HMODULE16 hModule )
259 CLASS *ptr, *next;
261 TRACE("0x%08x\n", hModule);
263 USER_Lock();
264 for (ptr = firstClass; ptr; ptr = next)
266 next = ptr->next;
267 if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
269 USER_Unlock();
273 /***********************************************************************
274 * CLASS_FindClassByAtom
276 * Return a pointer to the class.
277 * hinstance has been normalized by the caller.
279 * NOTES
280 * 980805 a local class will be found now if registred with hInst=0
281 * and looed up with a hInst!=0. msmoney does it (jsch)
283 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
285 CLASS * class, *tclass=0;
287 TRACE("0x%08x 0x%08x\n", atom, hinstance);
289 /* First search task-specific classes */
291 for (class = firstClass; (class); class = class->next)
293 if (class->style & CS_GLOBALCLASS) continue;
294 if (class->atomName == atom)
296 if (hinstance==class->hInstance || hinstance==0xffff )
298 TRACE("-- found local %p\n", class);
299 return class;
301 if (class->hInstance==0) tclass = class;
305 /* Then search global classes */
307 for (class = firstClass; (class); class = class->next)
309 if (!(class->style & CS_GLOBALCLASS)) continue;
310 if (class->atomName == atom)
312 TRACE("-- found global %p\n", class);
313 return class;
317 /* Then check if there was a local class with hInst=0*/
318 if ( tclass )
320 WARN("-- found local Class registred with hInst=0\n");
321 return tclass;
324 TRACE("-- not found\n");
325 return 0;
329 /***********************************************************************
330 * CLASS_RegisterClass
332 * The real RegisterClass() functionality.
334 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
335 DWORD style, INT classExtra, INT winExtra )
337 CLASS *classPtr;
339 TRACE("atom=0x%x hinst=0x%x style=0x%lx clExtr=0x%x winExtr=0x%x\n",
340 atom, hInstance, style, classExtra, winExtra );
342 /* Check if a class with this name already exists */
343 classPtr = CLASS_FindClassByAtom( atom, hInstance );
344 if (classPtr)
346 /* Class can be created only if it is local and */
347 /* if the class with the same name is global. */
349 if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
351 SetLastError( ERROR_CLASS_ALREADY_EXISTS );
352 return NULL;
356 /* Fix the extra bytes value */
358 if (classExtra < 0) classExtra = 0;
359 else if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
360 WARN("Class extra bytes %d is > 40\n", classExtra);
361 if (winExtra < 0) winExtra = 0;
362 else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
363 WARN("Win extra bytes %d is > 40\n", winExtra );
365 /* Create the class */
367 classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
368 if (!classPtr) return NULL;
369 classPtr->style = style;
370 classPtr->cbWndExtra = winExtra;
371 classPtr->cbClsExtra = classExtra;
372 classPtr->hInstance = hInstance;
373 classPtr->atomName = atom;
374 classPtr->dce = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
376 /* Other non-null values must be set by caller */
378 if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
379 firstClass = classPtr;
380 return classPtr;
384 /***********************************************************************
385 * CLASS_UnregisterClass
387 * The real UnregisterClass() functionality.
389 static BOOL CLASS_UnregisterClass( ATOM atom, HINSTANCE hInstance )
391 CLASS *classPtr;
392 BOOL ret = FALSE;
394 USER_Lock();
395 if (atom &&
396 (classPtr = CLASS_FindClassByAtom( atom, hInstance )) &&
397 (classPtr->hInstance == hInstance))
399 ret = CLASS_FreeClass( classPtr );
401 else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
403 USER_Unlock();
404 return ret;
408 /***********************************************************************
409 * CLASS_RegisterBuiltinClass
411 * Register a builtin control class.
412 * This allows having both ASCII and Unicode winprocs for the same class.
414 ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
416 ATOM atom;
417 CLASS *classPtr;
419 if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
421 if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
423 GlobalDeleteAtom( atom );
424 return 0;
427 classPtr->hCursor = LoadCursorA( 0, descr->cursor );
428 classPtr->hbrBackground = descr->brush;
430 if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)descr->procA,
431 WIN_PROC_32A, WIN_PROC_CLASS );
432 if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)descr->procW,
433 WIN_PROC_32W, WIN_PROC_CLASS );
434 return atom;
438 /***********************************************************************
439 * CLASS_AddWindow
441 * Add a new window using this class, and return the necessary
442 * information for creating the window.
444 CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
445 INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
447 CLASS *class;
448 if (type == WIN_PROC_16) inst = GetExePtr(inst);
450 if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
451 class->cWindows++;
453 if (type == WIN_PROC_32W)
455 if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
457 else
459 if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
461 *winExtra = class->cbWndExtra;
462 *style = class->style;
463 *dce = class->dce;
464 return class;
468 /***********************************************************************
469 * CLASS_RemoveWindow
471 * Remove a window from the class window count.
473 void CLASS_RemoveWindow( CLASS *cls )
475 if (cls && cls->cWindows) cls->cWindows--;
479 /***********************************************************************
480 * RegisterClass (USER.57)
482 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
484 ATOM atom;
485 CLASS *classPtr;
486 int iSmIconWidth, iSmIconHeight;
487 HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
489 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
490 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
491 wc->cbClsExtra, wc->cbWndExtra )))
493 GlobalDeleteAtom( atom );
494 return 0;
497 TRACE("atom=%04x wndproc=%08lx hinst=%04x "
498 "bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
499 atom, (DWORD)wc->lpfnWndProc, hInstance,
500 wc->hbrBackground, wc->style, wc->cbClsExtra,
501 wc->cbWndExtra, classPtr,
502 HIWORD(wc->lpszClassName) ?
503 (char *)MapSL(wc->lpszClassName) : "" );
505 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
506 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
508 classPtr->hIcon = wc->hIcon;
509 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
510 iSmIconWidth, iSmIconHeight,
511 LR_COPYFROMRESOURCE);
512 classPtr->hCursor = wc->hCursor;
513 classPtr->hbrBackground = wc->hbrBackground;
515 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
516 WIN_PROC_16, WIN_PROC_CLASS );
517 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
519 return atom;
523 /***********************************************************************
524 * RegisterClassA (USER32.@)
525 * RETURNS
526 * >0: Unique identifier
527 * 0: Failure
529 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
531 ATOM atom;
532 int iSmIconWidth, iSmIconHeight;
533 CLASS *classPtr;
535 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
537 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
538 wc->cbClsExtra, wc->cbWndExtra )))
540 GlobalDeleteAtom( atom );
541 return 0;
544 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
545 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
546 wc->hbrBackground, wc->style, wc->cbClsExtra,
547 wc->cbWndExtra, classPtr,
548 HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
550 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
551 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
553 classPtr->hIcon = wc->hIcon;
554 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
555 iSmIconWidth, iSmIconHeight,
556 LR_COPYFROMRESOURCE);
557 classPtr->hCursor = (HCURSOR16)wc->hCursor;
558 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
560 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
561 WIN_PROC_32A, WIN_PROC_CLASS );
562 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
563 return atom;
567 /***********************************************************************
568 * RegisterClassW (USER32.@)
570 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
572 ATOM atom;
573 int iSmIconWidth, iSmIconHeight;
574 CLASS *classPtr;
576 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
578 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
579 wc->cbClsExtra, wc->cbWndExtra )))
581 GlobalDeleteAtom( atom );
582 return 0;
585 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
586 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
587 wc->hbrBackground, wc->style, wc->cbClsExtra,
588 wc->cbWndExtra, classPtr );
590 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
591 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
593 classPtr->hIcon = wc->hIcon;
594 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
595 iSmIconWidth, iSmIconHeight,
596 LR_COPYFROMRESOURCE);
597 classPtr->hCursor = (HCURSOR16)wc->hCursor;
598 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
600 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
601 WIN_PROC_32W, WIN_PROC_CLASS );
602 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
603 return atom;
607 /***********************************************************************
608 * RegisterClassEx (USER.397)
610 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
612 ATOM atom;
613 CLASS *classPtr;
614 HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
616 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
617 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
618 wc->cbClsExtra, wc->cbWndExtra )))
620 GlobalDeleteAtom( atom );
621 return 0;
624 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
625 atom, (DWORD)wc->lpfnWndProc, hInstance,
626 wc->hbrBackground, wc->style, wc->cbClsExtra,
627 wc->cbWndExtra, classPtr );
629 classPtr->hIcon = wc->hIcon;
630 classPtr->hIconSm = wc->hIconSm;
631 classPtr->hCursor = wc->hCursor;
632 classPtr->hbrBackground = wc->hbrBackground;
634 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
635 WIN_PROC_16, WIN_PROC_CLASS );
636 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
637 return atom;
641 /***********************************************************************
642 * RegisterClassExA (USER32.@)
644 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
646 ATOM atom;
647 CLASS *classPtr;
649 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
651 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
652 wc->cbClsExtra, wc->cbWndExtra )))
654 GlobalDeleteAtom( atom );
655 return 0;
658 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
659 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
660 wc->hbrBackground, wc->style, wc->cbClsExtra,
661 wc->cbWndExtra, classPtr );
663 classPtr->hIcon = (HICON16)wc->hIcon;
664 classPtr->hIconSm = (HICON16)wc->hIconSm;
665 classPtr->hCursor = (HCURSOR16)wc->hCursor;
666 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
667 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
668 WIN_PROC_32A, WIN_PROC_CLASS );
669 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
670 return atom;
674 /***********************************************************************
675 * RegisterClassExW (USER32.@)
677 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
679 ATOM atom;
680 CLASS *classPtr;
682 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
684 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
685 wc->cbClsExtra, wc->cbWndExtra )))
687 GlobalDeleteAtom( atom );
688 return 0;
691 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
692 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
693 wc->hbrBackground, wc->style, wc->cbClsExtra,
694 wc->cbWndExtra, classPtr );
696 classPtr->hIcon = (HICON16)wc->hIcon;
697 classPtr->hIconSm = (HICON16)wc->hIconSm;
698 classPtr->hCursor = (HCURSOR16)wc->hCursor;
699 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
700 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
701 WIN_PROC_32W, WIN_PROC_CLASS );
702 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
703 return atom;
707 /***********************************************************************
708 * UnregisterClass (USER.403)
710 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
712 return UnregisterClassA( className, GetExePtr( hInstance ) );
715 /***********************************************************************
716 * UnregisterClassA (USER32.@)
719 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
721 TRACE("%s %x\n",debugres_a(className), hInstance);
722 return CLASS_UnregisterClass( GlobalFindAtomA( className ), hInstance );
725 /***********************************************************************
726 * UnregisterClassW (USER32.@)
728 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
730 TRACE("%s %x\n",debugres_w(className), hInstance);
731 return CLASS_UnregisterClass( GlobalFindAtomW( className ), hInstance );
735 /***********************************************************************
736 * GetClassWord (USER32.@)
738 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
740 CLASS *class;
741 WORD retvalue = 0;
743 if (offset < 0) return GetClassLongA( hwnd, offset );
745 TRACE("%x %x\n",hwnd, offset);
747 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
749 if (offset <= class->cbClsExtra - sizeof(WORD))
750 retvalue = GET_WORD((char *)(class + 1) + offset);
751 else
752 SetLastError( ERROR_INVALID_INDEX );
753 release_class_ptr( class );
754 return retvalue;
758 /***********************************************************************
759 * GetClassLong (USER.131)
761 LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
763 CLASS *class;
764 LONG ret;
765 HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
767 TRACE("%x %d\n",hwnd, offset);
769 switch( offset )
771 case GCL_WNDPROC:
772 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
773 ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
774 release_class_ptr( class );
775 return ret;
776 case GCL_MENUNAME:
777 ret = GetClassLongA( hwnd, offset );
778 return (LONG)SEGPTR_GET( (void *)ret );
779 default:
780 return GetClassLongA( hwnd, offset );
785 /***********************************************************************
786 * GetClassLongA (USER32.@)
788 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
790 CLASS *class;
791 LONG retvalue = 0;
793 TRACE("%x %d\n", hwnd, offset);
795 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
797 if (offset >= 0)
799 if (offset <= class->cbClsExtra - sizeof(LONG))
800 retvalue = GET_DWORD((char *)(class + 1) + offset);
801 else
802 SetLastError( ERROR_INVALID_INDEX );
803 release_class_ptr( class );
804 return retvalue;
807 switch(offset)
809 case GCL_HBRBACKGROUND:
810 retvalue = (LONG)class->hbrBackground;
811 break;
812 case GCL_HCURSOR:
813 retvalue = (LONG)class->hCursor;
814 break;
815 case GCL_HICON:
816 retvalue = (LONG)class->hIcon;
817 break;
818 case GCL_HICONSM:
819 retvalue = (LONG)class->hIconSm;
820 break;
821 case GCL_STYLE:
822 retvalue = (LONG)class->style;
823 break;
824 case GCL_CBWNDEXTRA:
825 retvalue = (LONG)class->cbWndExtra;
826 break;
827 case GCL_CBCLSEXTRA:
828 retvalue = (LONG)class->cbClsExtra;
829 break;
830 case GCL_HMODULE:
831 retvalue = (LONG)class->hInstance;
832 break;
833 case GCL_WNDPROC:
834 retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
835 break;
836 case GCL_MENUNAME:
837 retvalue = (LONG)CLASS_GetMenuNameA( class );
838 break;
839 case GCW_ATOM:
840 retvalue = (DWORD)class->atomName;
841 break;
842 default:
843 SetLastError( ERROR_INVALID_INDEX );
844 break;
846 release_class_ptr( class );
847 return retvalue;
851 /***********************************************************************
852 * GetClassLongW (USER32.@)
854 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
856 CLASS *class;
857 LONG retvalue;
859 if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
860 return GetClassLongA( hwnd, offset );
862 TRACE("%x %d\n", hwnd, offset);
864 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
866 if (offset == GCL_WNDPROC)
867 retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
868 else /* GCL_MENUNAME */
869 retvalue = (LONG)CLASS_GetMenuNameW( class );
871 release_class_ptr( class );
872 return retvalue;
876 /***********************************************************************
877 * SetClassWord (USER32.@)
879 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
881 CLASS *class;
882 WORD retval = 0;
884 if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
886 TRACE("%x %d %x\n", hwnd, offset, newval);
888 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
890 if (offset <= class->cbClsExtra - sizeof(WORD))
892 void *ptr = (char *)(class + 1) + offset;
893 retval = GET_WORD(ptr);
894 PUT_WORD( ptr, newval );
896 else SetLastError( ERROR_INVALID_INDEX );
898 release_class_ptr( class );
899 return retval;
903 /***********************************************************************
904 * SetClassLong (USER.132)
906 LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
908 CLASS *class;
909 LONG retval;
910 HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
912 TRACE("%x %d %lx\n", hwnd, offset, newval);
914 switch(offset)
916 case GCL_WNDPROC:
917 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
918 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
919 release_class_ptr( class );
920 return retval;
921 case GCL_MENUNAME:
922 newval = (LONG)MapSL( newval );
923 /* fall through */
924 default:
925 return SetClassLongA( hwnd, offset, newval );
930 /***********************************************************************
931 * SetClassLongA (USER32.@)
933 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
935 CLASS *class;
936 LONG retval = 0;
938 TRACE("%x %d %lx\n", hwnd, offset, newval);
940 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
942 if (offset >= 0)
944 if (offset <= class->cbClsExtra - sizeof(LONG))
946 void *ptr = (char *)(class + 1) + offset;
947 retval = GET_DWORD(ptr);
948 PUT_DWORD( ptr, newval );
950 else SetLastError( ERROR_INVALID_INDEX );
952 else switch(offset)
954 case GCL_MENUNAME:
955 CLASS_SetMenuNameA( class, (LPCSTR)newval );
956 retval = 0; /* Old value is now meaningless anyway */
957 break;
958 case GCL_WNDPROC:
959 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
960 break;
961 case GCL_HBRBACKGROUND:
962 retval = (LONG)class->hbrBackground;
963 class->hbrBackground = newval;
964 break;
965 case GCL_HCURSOR:
966 retval = (LONG)class->hCursor;
967 class->hCursor = newval;
968 break;
969 case GCL_HICON:
970 retval = (LONG)class->hIcon;
971 class->hIcon = newval;
972 break;
973 case GCL_HICONSM:
974 retval = (LONG)class->hIconSm;
975 class->hIconSm = newval;
976 break;
977 case GCL_STYLE:
978 retval = (LONG)class->style;
979 class->style = newval;
980 break;
981 case GCL_CBWNDEXTRA:
982 retval = (LONG)class->cbWndExtra;
983 class->cbWndExtra = newval;
984 break;
985 case GCL_HMODULE:
986 retval = (LONG)class->hInstance;
987 class->hInstance = newval;
988 break;
989 case GCW_ATOM:
990 retval = (DWORD)class->atomName;
991 class->atomName = newval;
992 break;
993 case GCL_CBCLSEXTRA: /* cannot change this one */
994 SetLastError( ERROR_INVALID_PARAMETER );
995 break;
996 default:
997 SetLastError( ERROR_INVALID_INDEX );
998 break;
1000 release_class_ptr( class );
1001 return retval;
1005 /***********************************************************************
1006 * SetClassLongW (USER32.@)
1008 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1010 CLASS *class;
1011 LONG retval;
1013 if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
1014 return SetClassLongA( hwnd, offset, newval );
1016 TRACE("%x %d %lx\n", hwnd, offset, newval);
1018 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1020 if (offset == GCL_WNDPROC)
1021 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
1022 else /* GCL_MENUNAME */
1024 CLASS_SetMenuNameW( class, (LPCWSTR)newval );
1025 retval = 0; /* Old value is now meaningless anyway */
1027 release_class_ptr( class );
1028 return retval;
1032 /***********************************************************************
1033 * GetClassNameA (USER32.@)
1035 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1037 INT ret = GlobalGetAtomNameA( GetClassLongA( hwnd, GCW_ATOM ), buffer, count );
1039 TRACE("%x %s %x\n",hwnd, debugstr_a(buffer), count);
1040 return ret;
1044 /***********************************************************************
1045 * GetClassNameW (USER32.@)
1047 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1049 INT ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), buffer, count );
1051 TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
1052 return ret;
1056 /***********************************************************************
1057 * GetClassInfo (USER.404)
1059 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASS16 *wc )
1061 ATOM atom;
1062 CLASS *classPtr;
1064 TRACE("%x %s %p\n",hInstance, debugres_a(MapSL(name)), wc);
1066 hInstance = GetExePtr( hInstance );
1067 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1068 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1069 return FALSE;
1070 if ((hInstance != classPtr->hInstance) &&
1071 !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
1072 return FALSE;
1073 wc->style = (UINT16)classPtr->style;
1074 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1075 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1076 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1077 wc->hInstance = classPtr->style & CS_GLOBALCLASS ? GetModuleHandle16("USER") : (HINSTANCE16)classPtr->hInstance;
1078 wc->hIcon = classPtr->hIcon;
1079 wc->hCursor = classPtr->hCursor;
1080 wc->hbrBackground = classPtr->hbrBackground;
1081 wc->lpszClassName = name;
1082 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1083 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1084 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1085 return TRUE;
1089 /***********************************************************************
1090 * GetClassInfoA (USER32.@)
1092 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
1093 WNDCLASSA *wc )
1095 ATOM atom;
1096 CLASS *classPtr;
1098 TRACE("%x %p %p\n",hInstance, name, wc);
1100 /* workaround: if hInstance=NULL you expect to get the system classes
1101 but this classes (as example from comctl32.dll SysListView) won't be
1102 registered with hInstance=NULL in WINE because of the late loading
1103 of this dll. fixes file dialogs in WinWord95 (jsch)*/
1105 if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
1106 return FALSE;
1108 if (!(classPtr->style & CS_GLOBALCLASS) &&
1109 classPtr->hInstance &&
1110 (hInstance != classPtr->hInstance))
1112 if (hInstance) return FALSE;
1113 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
1116 wc->style = classPtr->style;
1117 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1118 wc->cbClsExtra = classPtr->cbClsExtra;
1119 wc->cbWndExtra = classPtr->cbWndExtra;
1120 wc->hInstance = hInstance;
1121 wc->hIcon = (HICON)classPtr->hIcon;
1122 wc->hCursor = (HCURSOR)classPtr->hCursor;
1123 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1124 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1125 wc->lpszClassName = name;
1126 return TRUE;
1130 /***********************************************************************
1131 * GetClassInfoW (USER32.@)
1133 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
1134 WNDCLASSW *wc )
1136 ATOM atom;
1137 CLASS *classPtr;
1139 TRACE("%x %p %p\n",hInstance, name, wc);
1141 if ( !(atom=GlobalFindAtomW(name)) ||
1142 !(classPtr=CLASS_FindClassByAtom(atom,hInstance))
1144 return FALSE;
1146 if (!(classPtr->style & CS_GLOBALCLASS) &&
1147 classPtr->hInstance &&
1148 (hInstance != classPtr->hInstance))
1150 if (hInstance) return FALSE;
1151 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",debugstr_w(name));
1153 wc->style = classPtr->style;
1154 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1155 wc->cbClsExtra = classPtr->cbClsExtra;
1156 wc->cbWndExtra = classPtr->cbWndExtra;
1157 wc->hInstance = hInstance;
1158 wc->hIcon = (HICON)classPtr->hIcon;
1159 wc->hCursor = (HCURSOR)classPtr->hCursor;
1160 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1161 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1162 wc->lpszClassName = name;
1163 return TRUE;
1167 /***********************************************************************
1168 * GetClassInfoEx (USER.398)
1170 * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1171 * same in Win16 as in Win32. --AJ
1173 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASSEX16 *wc )
1175 ATOM atom;
1176 CLASS *classPtr;
1178 TRACE("%x %s %p\n",hInstance,debugres_a( MapSL(name) ), wc);
1180 hInstance = GetExePtr( hInstance );
1181 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1182 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1183 (hInstance != classPtr->hInstance)) return FALSE;
1184 wc->style = classPtr->style;
1185 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1186 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1187 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1188 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1189 wc->hIcon = classPtr->hIcon;
1190 wc->hIconSm = classPtr->hIconSm;
1191 wc->hCursor = classPtr->hCursor;
1192 wc->hbrBackground = classPtr->hbrBackground;
1193 wc->lpszClassName = (SEGPTR)0;
1194 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1195 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1196 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1197 wc->lpszClassName = name;
1199 /* We must return the atom of the class here instead of just TRUE. */
1200 return atom;
1204 /***********************************************************************
1205 * GetClassInfoExA (USER32.@)
1207 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1208 WNDCLASSEXA *wc )
1210 ATOM atom;
1211 CLASS *classPtr;
1213 TRACE("%x %p %p\n",hInstance, name, wc);
1215 if (!(atom = GlobalFindAtomA( name )) ||
1216 !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))
1217 /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
1218 wc->style = classPtr->style;
1219 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1220 wc->cbClsExtra = classPtr->cbClsExtra;
1221 wc->cbWndExtra = classPtr->cbWndExtra;
1222 wc->hInstance = classPtr->hInstance;
1223 wc->hIcon = (HICON)classPtr->hIcon;
1224 wc->hIconSm = (HICON)classPtr->hIconSm;
1225 wc->hCursor = (HCURSOR)classPtr->hCursor;
1226 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1227 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1228 wc->lpszClassName = name;
1230 /* We must return the atom of the class here instead of just TRUE. */
1231 return atom;
1235 /***********************************************************************
1236 * GetClassInfoExW (USER32.@)
1238 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1239 WNDCLASSEXW *wc )
1241 ATOM atom;
1242 CLASS *classPtr;
1244 TRACE("%x %p %p\n",hInstance, name, wc);
1246 if (!(atom = GlobalFindAtomW( name )) ||
1247 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1248 (hInstance != classPtr->hInstance)) return FALSE;
1249 wc->style = classPtr->style;
1250 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1251 wc->cbClsExtra = classPtr->cbClsExtra;
1252 wc->cbWndExtra = classPtr->cbWndExtra;
1253 wc->hInstance = classPtr->hInstance;
1254 wc->hIcon = (HICON)classPtr->hIcon;
1255 wc->hIconSm = (HICON)classPtr->hIconSm;
1256 wc->hCursor = (HCURSOR)classPtr->hCursor;
1257 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1258 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1259 wc->lpszClassName = name;
1261 /* We must return the atom of the class here instead of just TRUE. */
1262 return atom;
1266 #if 0 /* toolhelp is in kernel, so this cannot work */
1268 /***********************************************************************
1269 * ClassFirst (TOOLHELP.69)
1271 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1273 TRACE("%p\n",pClassEntry);
1274 pClassEntry->wNext = 1;
1275 return ClassNext16( pClassEntry );
1279 /***********************************************************************
1280 * ClassNext (TOOLHELP.70)
1282 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1284 int i;
1285 CLASS *class = firstClass;
1287 TRACE("%p\n",pClassEntry);
1289 if (!pClassEntry->wNext) return FALSE;
1290 for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1291 if (!class)
1293 pClassEntry->wNext = 0;
1294 return FALSE;
1296 pClassEntry->hInst = class->hInstance;
1297 pClassEntry->wNext++;
1298 GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1299 sizeof(pClassEntry->szClassName) );
1300 return TRUE;
1302 #endif