2 * Window classes functions
4 * Copyright 1993 Alexandre Julliard
18 /* #define DEBUG_CLASS */
22 static HCLASS firstClass
= 0;
25 /***********************************************************************
28 * Dump the content of a class structure to stderr.
30 void CLASS_DumpClass( HCLASS hClass
)
36 if (!(ptr
= CLASS_FindClassPtr( hClass
)))
38 fprintf( stderr
, "%04x is not a class handle\n", hClass
);
41 GlobalGetAtomName( ptr
->atomName
, className
, sizeof(className
) );
43 fprintf( stderr
, "Class %04x:\n", hClass
);
45 "next=%04x name=%04x '%s' style=%04x wndProc=%08lx\n"
46 "inst=%04x hdce=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
47 "clsExtra=%d winExtra=%d #windows=%d\n",
48 ptr
->hNext
, ptr
->atomName
, className
, ptr
->wc
.style
,
49 (DWORD
)ptr
->wc
.lpfnWndProc
, ptr
->wc
.hInstance
, ptr
->hdce
,
50 ptr
->wc
.hIcon
, ptr
->wc
.hCursor
, ptr
->wc
.hbrBackground
,
51 ptr
->wc
.cbClsExtra
, ptr
->wc
.cbWndExtra
, ptr
->cWindows
);
52 if (ptr
->wc
.cbClsExtra
)
54 fprintf( stderr
, "extra bytes:" );
55 for (i
= 0; i
< ptr
->wc
.cbClsExtra
; i
++)
56 fprintf( stderr
, " %02x", *((BYTE
*)ptr
->wExtra
+i
) );
57 fprintf( stderr
, "\n" );
59 fprintf( stderr
, "\n" );
63 /***********************************************************************
66 * Walk the class list and print each class on stderr.
68 void CLASS_WalkClasses(void)
70 HCLASS hClass
= firstClass
;
74 fprintf( stderr
, "Class Name Style WndProc\n" );
77 if (!(ptr
= CLASS_FindClassPtr( hClass
)))
79 fprintf( stderr
, "*** Bad class %04x in list\n", hClass
);
82 GlobalGetAtomName( ptr
->atomName
, className
, sizeof(className
) );
83 fprintf( stderr
, "%04x %-20.20s %04x %08lx\n",
84 hClass
, className
, ptr
->wc
.style
, (DWORD
)ptr
->wc
.lpfnWndProc
);
87 fprintf( stderr
, "\n" );
91 /***********************************************************************
92 * CLASS_FindClassByName
94 * Return a handle and a pointer to the class.
95 * 'ptr' can be NULL if the pointer is not needed.
97 HCLASS
CLASS_FindClassByName( SEGPTR name
, HINSTANCE hinstance
, CLASS
**ptr
)
103 if (!(atom
= GlobalFindAtom( name
))) return 0;
105 /* First search task-specific classes */
107 for (class = firstClass
; (class); class = classPtr
->hNext
)
109 classPtr
= (CLASS
*) USER_HEAP_LIN_ADDR(class);
110 if (classPtr
->wc
.style
& CS_GLOBALCLASS
) continue;
111 if ((classPtr
->atomName
== atom
) &&
112 ( (hinstance
==(HINSTANCE
)0xffff) ||
113 (hinstance
== classPtr
->wc
.hInstance
) ) )
115 if (ptr
) *ptr
= classPtr
;
120 /* Then search global classes */
122 for (class = firstClass
; (class); class = classPtr
->hNext
)
124 classPtr
= (CLASS
*) USER_HEAP_LIN_ADDR(class);
125 if (!(classPtr
->wc
.style
& CS_GLOBALCLASS
)) continue;
126 if (classPtr
->atomName
== atom
)
128 if (ptr
) *ptr
= classPtr
;
137 /***********************************************************************
140 * Return a pointer to the CLASS structure corresponding to a HCLASS.
142 CLASS
* CLASS_FindClassPtr( HCLASS hclass
)
146 if (!hclass
) return NULL
;
147 ptr
= (CLASS
*) USER_HEAP_LIN_ADDR( hclass
);
148 if (ptr
->wMagic
!= CLASS_MAGIC
) return NULL
;
153 /***********************************************************************
154 * RegisterClass (USER.57)
156 ATOM
RegisterClass( LPWNDCLASS
class )
158 CLASS
* newClass
, * prevClassPtr
;
159 HCLASS handle
, prevClass
;
162 dprintf_class( stddeb
, "RegisterClass: wndproc=%08lx hinst="NPFMT
" name='%s' background "NPFMT
"\n",
163 (DWORD
)class->lpfnWndProc
, class->hInstance
,
164 HIWORD(class->lpszClassName
) ?
165 (char *)PTR_SEG_TO_LIN(class->lpszClassName
) : "(int)",
166 class->hbrBackground
);
167 dprintf_class(stddeb
," style=%04x clsExtra=%d winExtra=%d\n",
168 class->style
, class->cbClsExtra
, class->cbWndExtra
);
170 /* Window classes are owned by modules, not instances */
171 class->hInstance
= GetExePtr( class->hInstance
);
173 /* Check if a class with this name already exists */
174 prevClass
= CLASS_FindClassByName( class->lpszClassName
,
175 class->hInstance
, &prevClassPtr
);
178 /* Class can be created only if it is local and */
179 /* if the class with the same name is global. */
181 if (class->style
& CS_GLOBALCLASS
) return 0;
182 if (!(prevClassPtr
->wc
.style
& CS_GLOBALCLASS
)) return 0;
187 classExtra
= (class->cbClsExtra
< 0) ? 0 : class->cbClsExtra
;
188 handle
= USER_HEAP_ALLOC( sizeof(CLASS
) + classExtra
);
189 if (!handle
) return 0;
190 newClass
= (CLASS
*) USER_HEAP_LIN_ADDR( handle
);
191 newClass
->hNext
= firstClass
;
192 newClass
->wMagic
= CLASS_MAGIC
;
193 newClass
->cWindows
= 0;
194 newClass
->wc
= *class;
195 newClass
->wc
.cbWndExtra
= (class->cbWndExtra
< 0) ? 0 : class->cbWndExtra
;
196 newClass
->wc
.cbClsExtra
= classExtra
;
198 newClass
->atomName
= GlobalAddAtom( class->lpszClassName
);
199 newClass
->wc
.lpszClassName
= 0;
201 if (newClass
->wc
.style
& CS_CLASSDC
)
202 newClass
->hdce
= DCE_AllocDCE( DCE_CLASS_DC
);
203 else newClass
->hdce
= 0;
205 /* Make a copy of the menu name (only if it is a string) */
207 if (HIWORD(class->lpszMenuName
))
209 char *menuname
= PTR_SEG_TO_LIN( class->lpszMenuName
);
210 HANDLE hname
= USER_HEAP_ALLOC( strlen(menuname
)+1 );
213 newClass
->wc
.lpszMenuName
= (SEGPTR
)USER_HEAP_SEG_ADDR( hname
);
214 strcpy( USER_HEAP_LIN_ADDR( hname
), menuname
);
218 if (classExtra
) memset( newClass
->wExtra
, 0, classExtra
);
220 return newClass
->atomName
;
224 /***********************************************************************
225 * UnregisterClass (USER.403)
227 BOOL
UnregisterClass( SEGPTR className
, HANDLE hinstance
)
229 HANDLE
class, prevClass
;
230 CLASS
* classPtr
, * prevClassPtr
;
232 hinstance
= GetExePtr( hinstance
);
233 /* Check if we can remove this class */
234 class = CLASS_FindClassByName( className
, hinstance
, &classPtr
);
235 if (!class) return FALSE
;
236 if ((classPtr
->wc
.hInstance
!= hinstance
) || (classPtr
->cWindows
> 0))
239 /* Remove the class from the linked list */
240 if (firstClass
== class) firstClass
= classPtr
->hNext
;
243 for (prevClass
= firstClass
; prevClass
; prevClass
=prevClassPtr
->hNext
)
245 prevClassPtr
= (CLASS
*) USER_HEAP_LIN_ADDR(prevClass
);
246 if (prevClassPtr
->hNext
== class) break;
250 fprintf(stderr
, "ERROR: Class list corrupted\n" );
253 prevClassPtr
->hNext
= classPtr
->hNext
;
256 /* Delete the class */
257 if (classPtr
->hdce
) DCE_FreeDCE( classPtr
->hdce
);
258 if (classPtr
->wc
.hbrBackground
) DeleteObject( classPtr
->wc
.hbrBackground
);
259 GlobalDeleteAtom( classPtr
->atomName
);
260 if (HIWORD(classPtr
->wc
.lpszMenuName
))
262 USER_HEAP_FREE( (HANDLE
)classPtr
->wc
.lpszMenuName
);
264 USER_HEAP_FREE( LOWORD(classPtr
->wc
.lpszMenuName
) );
266 USER_HEAP_FREE( class );
271 /***********************************************************************
272 * GetClassWord (USER.129)
274 WORD
GetClassWord( HWND hwnd
, short offset
)
276 return (WORD
)GetClassLong( hwnd
, offset
);
280 /***********************************************************************
281 * SetClassWord (USER.130)
283 WORD
SetClassWord( HWND hwnd
, short offset
, WORD newval
)
287 WORD
*ptr
, retval
= 0;
289 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
290 if (!(classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
))) return 0;
291 ptr
= (WORD
*)(((char *)classPtr
->wExtra
) + offset
);
298 /***********************************************************************
299 * GetClassLong (USER.131)
301 LONG
GetClassLong( HWND hwnd
, short offset
)
306 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
307 if (!(classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
))) return 0;
308 return *(LONG
*)(((char *)classPtr
->wExtra
) + offset
);
312 /***********************************************************************
313 * SetClassLong (USER.132)
315 LONG
SetClassLong( HWND hwnd
, short offset
, LONG newval
)
319 LONG
*ptr
, retval
= 0;
321 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
322 if (!(classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
))) return 0;
323 ptr
= (LONG
*)(((char *)classPtr
->wExtra
) + offset
);
330 /***********************************************************************
331 * GetClassName (USER.58)
333 int GetClassName(HWND hwnd
, LPSTR lpClassName
, short maxCount
)
338 /* FIXME: We have the find the correct hInstance */
339 dprintf_class(stddeb
,"GetClassName("NPFMT
",%p,%d)\n",hwnd
,lpClassName
,maxCount
);
340 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return 0;
341 if (!(classPtr
= CLASS_FindClassPtr(wndPtr
->hClass
))) return 0;
343 return GlobalGetAtomName(classPtr
->atomName
, lpClassName
, maxCount
);
347 /***********************************************************************
348 * GetClassInfo (USER.404)
350 BOOL
GetClassInfo( HANDLE hInstance
, SEGPTR name
, LPWNDCLASS lpWndClass
)
354 dprintf_class( stddeb
, "GetClassInfo: hInstance="NPFMT
" className=%s\n",
356 HIWORD(name
) ? (char *)PTR_SEG_TO_LIN(name
) : "(int)" );
358 hInstance
= GetExePtr( hInstance
);
360 if (!(CLASS_FindClassByName( name
, hInstance
, &classPtr
))) return FALSE
;
361 if (hInstance
&& (hInstance
!= classPtr
->wc
.hInstance
)) return FALSE
;
363 memcpy(lpWndClass
, &(classPtr
->wc
), sizeof(WNDCLASS
));
368 /***********************************************************************
369 * ClassFirst (TOOLHELP.69)
371 BOOL
ClassFirst( CLASSENTRY
*pClassEntry
)
373 pClassEntry
->wNext
= firstClass
;
374 return ClassNext( pClassEntry
);
378 /***********************************************************************
379 * ClassNext (TOOLHELP.70)
381 BOOL
ClassNext( CLASSENTRY
*pClassEntry
)
383 CLASS
*classPtr
= (CLASS
*) USER_HEAP_LIN_ADDR( pClassEntry
->wNext
);
384 if (!classPtr
) return FALSE
;
386 pClassEntry
->hInst
= classPtr
->wc
.hInstance
;
387 pClassEntry
->wNext
= classPtr
->hNext
;
388 GlobalGetAtomName( classPtr
->atomName
, pClassEntry
->szClassName
,
389 sizeof(pClassEntry
->szClassName
) );