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
= GlobalFindAtom( 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
= GlobalAddAtom( 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 GlobalDeleteAtom( classPtr
->atomName
);
193 if (HIWORD(classPtr
->wc
.lpszMenuName
))
194 USER_HEAP_FREE( LOWORD(classPtr
->wc
.lpszMenuName
) );
195 USER_HEAP_FREE( class );
200 /***********************************************************************
201 * GetClassWord (USER.129)
203 WORD
GetClassWord( HWND hwnd
, short offset
)
205 return (WORD
)GetClassLong( hwnd
, offset
);
209 /***********************************************************************
210 * SetClassWord (USER.130)
212 WORD
SetClassWord( HWND hwnd
, short offset
, WORD newval
)
216 WORD
*ptr
, retval
= 0;
218 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
219 if (!(classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
))) return 0;
220 ptr
= (WORD
*)(((char *)classPtr
->wExtra
) + offset
);
227 /***********************************************************************
228 * GetClassLong (USER.131)
230 LONG
GetClassLong( HWND hwnd
, short offset
)
235 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
236 if (!(classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
))) return 0;
237 return *(LONG
*)(((char *)classPtr
->wExtra
) + offset
);
241 /***********************************************************************
242 * SetClassLong (USER.132)
244 LONG
SetClassLong( HWND hwnd
, short offset
, LONG newval
)
248 LONG
*ptr
, retval
= 0;
250 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
251 if (!(classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
))) return 0;
252 ptr
= (LONG
*)(((char *)classPtr
->wExtra
) + offset
);
259 /***********************************************************************
260 * GetClassName (USER.58)
262 int GetClassName(HWND hwnd
, LPSTR lpClassName
, short maxCount
)
267 /* FIXME: We have the find the correct hInstance */
268 dprintf_class(stddeb
,"GetClassName(%x,%p,%d)\n",hwnd
,lpClassName
,maxCount
);
269 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return 0;
270 if (!(classPtr
= CLASS_FindClassPtr(wndPtr
->hClass
))) return 0;
272 return GlobalGetAtomName(classPtr
->atomName
, lpClassName
, maxCount
);
276 /***********************************************************************
277 * GetClassInfo (USER.404)
279 BOOL
GetClassInfo( HANDLE hInstance
, SEGPTR name
, LPWNDCLASS lpWndClass
)
283 dprintf_class( stddeb
, "GetClassInfo: hInstance=%04x className=%s\n",
285 HIWORD(name
) ? (char *)PTR_SEG_TO_LIN(name
) : "(int)" );
287 hInstance
= GetExePtr( hInstance
);
289 if (!(CLASS_FindClassByName( name
, hInstance
, &classPtr
))) return FALSE
;
290 if (hInstance
&& (hInstance
!= classPtr
->wc
.hInstance
)) return FALSE
;
292 memcpy(lpWndClass
, &(classPtr
->wc
), sizeof(WNDCLASS
));
297 /***********************************************************************
298 * ClassFirst (TOOLHELP.69)
300 BOOL
ClassFirst( CLASSENTRY
*pClassEntry
)
302 pClassEntry
->wNext
= firstClass
;
303 return ClassNext( pClassEntry
);
307 /***********************************************************************
308 * ClassNext (TOOLHELP.70)
310 BOOL
ClassNext( CLASSENTRY
*pClassEntry
)
312 CLASS
*classPtr
= (CLASS
*) USER_HEAP_LIN_ADDR( pClassEntry
->wNext
);
313 if (!classPtr
) return FALSE
;
315 pClassEntry
->hInst
= classPtr
->wc
.hInstance
;
316 pClassEntry
->wNext
= classPtr
->hNext
;
317 GlobalGetAtomName( classPtr
->atomName
, pClassEntry
->szClassName
,
318 sizeof(pClassEntry
->szClassName
) );