2 * Window classes functions
4 * Copyright 1993 Alexandre Julliard
18 /* #define DEBUG_CLASS */
22 static HCLASS firstClass = 0;
25 /***********************************************************************
26 * CLASS_FindClassByName
28 * Return a handle and a pointer to the class.
29 * 'ptr' can be NULL if the pointer is not needed.
31 HCLASS CLASS_FindClassByName( SEGPTR name, WORD hinstance, CLASS **ptr )
37 if (!(atom = LocalFindAtom( name ))) return 0;
39 /* First search task-specific classes */
41 for (class = firstClass; (class); class = classPtr->hNext)
43 classPtr = (CLASS *) USER_HEAP_LIN_ADDR(class);
44 if (classPtr->wc.style & CS_GLOBALCLASS) continue;
45 if ((classPtr->atomName == atom) &&
46 ((hinstance==0xffff )|| (hinstance == classPtr->wc.hInstance)))
48 if (ptr) *ptr = classPtr;
53 /* Then search global classes */
55 for (class = firstClass; (class); class = classPtr->hNext)
57 classPtr = (CLASS *) USER_HEAP_LIN_ADDR(class);
58 if (!(classPtr->wc.style & CS_GLOBALCLASS)) continue;
59 if (classPtr->atomName == atom)
61 if (ptr) *ptr = classPtr;
70 /***********************************************************************
73 * Return a pointer to the CLASS structure corresponding to a HCLASS.
75 CLASS * CLASS_FindClassPtr( HCLASS hclass )
79 if (!hclass) return NULL;
80 ptr = (CLASS *) USER_HEAP_LIN_ADDR( hclass );
81 if (ptr->wMagic != CLASS_MAGIC) return NULL;
86 /***********************************************************************
87 * RegisterClass (USER.57)
89 ATOM RegisterClass( LPWNDCLASS class )
91 CLASS * newClass, * prevClassPtr;
92 HCLASS handle, prevClass;
95 dprintf_class( stddeb, "RegisterClass: wndproc=%08lx hinst=%04x name='%s' background %04x\n",
96 (DWORD)class->lpfnWndProc, class->hInstance,
97 HIWORD(class->lpszClassName) ?
98 (char *)PTR_SEG_TO_LIN(class->lpszClassName) : "(int)",
99 class->hbrBackground );
100 dprintf_class(stddeb," style=%04x clsExtra=%d winExtra=%d\n",
101 class->style, class->cbClsExtra, class->cbWndExtra );
103 /* Window classes are owned by modules, not instances */
104 class->hInstance = GetExePtr( class->hInstance );
106 /* Check if a class with this name already exists */
107 prevClass = CLASS_FindClassByName( class->lpszClassName,
108 class->hInstance, &prevClassPtr );
111 /* Class can be created only if it is local and */
112 /* if the class with the same name is global. */
114 if (class->style & CS_GLOBALCLASS) return 0;
115 if (!(prevClassPtr->wc.style & CS_GLOBALCLASS)) return 0;
120 classExtra = (class->cbClsExtra < 0) ? 0 : class->cbClsExtra;
121 handle = USER_HEAP_ALLOC( sizeof(CLASS) + classExtra );
122 if (!handle) return 0;
123 newClass = (CLASS *) USER_HEAP_LIN_ADDR( handle );
124 newClass->hNext = firstClass;
125 newClass->wMagic = CLASS_MAGIC;
126 newClass->cWindows = 0;
127 newClass->wc = *class;
128 newClass->wc.cbWndExtra = (class->cbWndExtra < 0) ? 0 : class->cbWndExtra;
129 newClass->wc.cbClsExtra = classExtra;
131 newClass->atomName = LocalAddAtom( class->lpszClassName );
132 newClass->wc.lpszClassName = 0;
134 if (newClass->wc.style & CS_CLASSDC)
135 newClass->hdce = DCE_AllocDCE( DCE_CLASS_DC );
136 else newClass->hdce = 0;
138 /* Make a copy of the menu name (only if it is a string) */
140 if (HIWORD(class->lpszMenuName))
142 char *menuname = PTR_SEG_TO_LIN( class->lpszMenuName );
143 HANDLE hname = USER_HEAP_ALLOC( strlen(menuname)+1 );
146 newClass->wc.lpszMenuName = USER_HEAP_SEG_ADDR( hname );
147 strcpy( USER_HEAP_LIN_ADDR( hname ), menuname );
151 if (classExtra) memset( newClass->wExtra, 0, classExtra );
153 return newClass->atomName;
157 /***********************************************************************
158 * UnregisterClass (USER.403)
160 BOOL UnregisterClass( SEGPTR className, HANDLE hinstance )
162 HANDLE class, prevClass;
163 CLASS * classPtr, * prevClassPtr;
165 hinstance = GetExePtr( hinstance );
166 /* Check if we can remove this class */
167 class = CLASS_FindClassByName( className, hinstance, &classPtr );
168 if (!class) return FALSE;
169 if ((classPtr->wc.hInstance != hinstance) || (classPtr->cWindows > 0))
172 /* Remove the class from the linked list */
173 if (firstClass == class) firstClass = classPtr->hNext;
176 for (prevClass = firstClass; prevClass; prevClass=prevClassPtr->hNext)
178 prevClassPtr = (CLASS *) USER_HEAP_LIN_ADDR(prevClass);
179 if (prevClassPtr->hNext == class) break;
183 fprintf(stderr, "ERROR: Class list corrupted\n" );
186 prevClassPtr->hNext = classPtr->hNext;
189 /* Delete the class */
190 if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
191 if (classPtr->wc.hbrBackground) DeleteObject( classPtr->wc.hbrBackground );
192 /*if (classPtr->wc.style & CS_GLOBALCLASS)*/ LocalDeleteAtom( classPtr->atomName );
193 /*else DeleteAtom( classPtr->atomName );*/
194 if (HIWORD(classPtr->wc.lpszMenuName))
195 USER_HEAP_FREE( LOWORD(classPtr->wc.lpszMenuName) );
196 USER_HEAP_FREE( class );
201 /***********************************************************************
202 * GetClassWord (USER.129)
204 WORD GetClassWord( HWND hwnd, short offset )
206 return (WORD)GetClassLong( hwnd, offset );
210 /***********************************************************************
211 * SetClassWord (USER.130)
213 WORD SetClassWord( HWND hwnd, short offset, WORD newval )
217 WORD *ptr, retval = 0;
219 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
220 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
221 ptr = (WORD *)(((char *)classPtr->wExtra) + offset);
228 /***********************************************************************
229 * GetClassLong (USER.131)
231 LONG GetClassLong( HWND hwnd, short offset )
236 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
237 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
238 return *(LONG *)(((char *)classPtr->wExtra) + offset);
242 /***********************************************************************
243 * SetClassLong (USER.132)
245 LONG SetClassLong( HWND hwnd, short offset, LONG newval )
249 LONG *ptr, retval = 0;
251 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
252 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
253 ptr = (LONG *)(((char *)classPtr->wExtra) + offset);
260 /***********************************************************************
261 * GetClassName (USER.58)
263 int GetClassName(HWND hwnd, LPSTR lpClassName, short maxCount)
268 /* FIXME: We have the find the correct hInstance */
269 dprintf_class(stddeb,"GetClassName(%x,%p,%d)\n",hwnd,lpClassName,maxCount);
270 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
271 if (!(classPtr = CLASS_FindClassPtr(wndPtr->hClass))) return 0;
273 return LocalGetAtomName(classPtr->atomName, lpClassName, maxCount);
277 /***********************************************************************
278 * GetClassInfo (USER.404)
280 BOOL GetClassInfo( HANDLE hInstance, SEGPTR name, LPWNDCLASS lpWndClass )
284 dprintf_class( stddeb, "GetClassInfo: hInstance=%04x className=%s\n",
286 HIWORD(name) ? (char *)PTR_SEG_TO_LIN(name) : "(int)" );
288 hInstance = GetExePtr( hInstance );
290 if (!(CLASS_FindClassByName( name, hInstance, &classPtr))) return FALSE;
291 if (hInstance && (hInstance != classPtr->wc.hInstance)) return FALSE;
293 memcpy(lpWndClass, &(classPtr->wc), sizeof(WNDCLASS));
298 /***********************************************************************
299 * ClassFirst (TOOLHELP.69)
301 BOOL ClassFirst( CLASSENTRY *pClassEntry )
303 pClassEntry->wNext = firstClass;
304 return ClassNext( pClassEntry );
308 /***********************************************************************
309 * ClassNext (TOOLHELP.70)
311 BOOL ClassNext( CLASSENTRY *pClassEntry )
313 CLASS *classPtr = (CLASS *) USER_HEAP_LIN_ADDR( pClassEntry->wNext );
314 if (!classPtr) return FALSE;
316 pClassEntry->hInst = classPtr->wc.hInstance;
317 pClassEntry->wNext = classPtr->hNext;
318 LocalGetAtomName( classPtr->atomName, pClassEntry->szClassName,
319 sizeof(pClassEntry->szClassName) );