source: trunk/src/user32/win32class.cpp@ 2860

Last change on this file since 2860 was 2860, checked in by sandervl, 26 years ago

window class ctor bugfix

File size: 18.0 KB
Line 
1/* $Id: win32class.cpp,v 1.15 2000-02-22 19:15:20 sandervl Exp $ */
2/*
3 * Win32 Window Class Managment Code for OS/2
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 *
8 * TODO: Right now all class atoms are global. This must be changed.
9 * TODO: Global atoms of classes with CS_GLOBALCLASS flag are not deleted
10 * Must all be changed if we want to support global app classes
11 * that can be used by other apps. (low priority)
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16#include <os2win.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <stdarg.h>
21#include <assert.h>
22#include <misc.h>
23#include <win32class.h>
24#include <win32wnd.h>
25#include <win\winproc.h>
26
27#define DBG_LOCALLOG DBG_win32class
28#include "dbglocal.h"
29
30static fDestroyAll = FALSE;
31
32//******************************************************************************
33//Win32WndClass methods:
34//******************************************************************************
35Win32WndClass::Win32WndClass(WNDCLASSEXA *wndclass, BOOL fUnicode) : GenericObject(&wndclasses, OBJTYPE_CLASS)
36{
37 isUnicode = fUnicode;
38 processId = 0;
39
40 if(HIWORD(wndclass->lpszClassName)) {
41 if(isUnicode) {
42 INT len = lstrlenW((LPWSTR)wndclass->lpszClassName)+1;
43
44 classNameA = (PCHAR)_smalloc(len);
45 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
46 }
47 else {
48 INT len = strlen(wndclass->lpszClassName)+1;
49
50 classNameA = (PCHAR)_smalloc(len);
51 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
52 }
53 if(classNameA == NULL || classNameW == NULL) {
54 dprintf(("Win32Class ctr; classNameA/classNameW == NULL"));
55 exit(1);
56 }
57 if(isUnicode) {
58 lstrcpyW(classNameW, (LPWSTR)wndclass->lpszClassName);
59 UnicodeToAscii(classNameW, classNameA);
60 }
61 else {
62 strcpy((char *)classNameA, wndclass->lpszClassName);
63 AsciiToUnicode(classNameA, classNameW);
64 }
65 classAtom = 0;
66 //SvL: If a system control has already be registered, use that atom instead
67 // of creating a new one
68 if(wndclass->style & CS_GLOBALCLASS) {
69 classAtom = GlobalFindAtomA(classNameA);
70 }
71 if(!classAtom) classAtom = GlobalAddAtomA(classNameA);
72 }
73 else {
74 classNameA = NULL;
75 classNameW = NULL;
76 classAtom = (DWORD)wndclass->lpszClassName;
77 }
78 if(!(wndclass->style & CS_GLOBALCLASS)) {
79 processId = GetCurrentProcess();
80 }
81 menuNameA = 0;
82 menuNameW = 0;
83 setMenuName((LPSTR)wndclass->lpszMenuName);
84
85 dprintf(("USER32: Win32Class ctor\n"));
86 dprintf(("USER32: wndclass->style %X\n", wndclass->style));
87 dprintf(("USER32: wndclass->lpfnWndProc %X\n", wndclass->lpfnWndProc));
88 dprintf(("USER32: wndclass->cbClsExtra %X\n", wndclass->cbClsExtra));
89 dprintf(("USER32: wndclass->cbWndExtra %X\n", wndclass->cbWndExtra));
90 dprintf(("USER32: wndclass->hInstance %X\n", wndclass->hInstance));
91 dprintf(("USER32: wndclass->hIcon %X\n", wndclass->hIcon));
92 dprintf(("USER32: wndclass->hCursor %X\n", wndclass->hCursor));
93 dprintf(("USER32: wndclass->hbrBackground %X\n", wndclass->hbrBackground));
94 if(HIWORD(wndclass->lpszClassName))
95 dprintf(("USER32: wndclass->lpszClassName %s\n", classNameA));
96 else dprintf(("USER32: wndclass->lpszClassName %X\n", wndclass->lpszClassName));
97
98 if(HIWORD(wndclass->lpszMenuName)) {//convert string name identifier to numeric id
99 dprintf(("USER32: lpszMenuName %s\n", menuNameA));
100 }
101 else dprintf(("USER32: wndclass->lpszMenuName %X\n", menuNameA));
102
103 nrExtraClassWords = wndclass->cbClsExtra;
104 nrExtraWindowWords = wndclass->cbWndExtra;
105 backgroundBrush = wndclass->hbrBackground;
106 hCursor = wndclass->hCursor;
107 hIcon = wndclass->hIcon;
108 hInstance = wndclass->hInstance;
109
110 if(wndclass->style & CS_CLASSDC) {
111 hdcClass = 0; //TODO:
112 }
113 else hdcClass = 0;
114
115 windowStyle = wndclass->style;
116
117 windowProc = 0;
118 WINPROC_SetProc((HWINDOWPROC *)&windowProc, wndclass->lpfnWndProc, (isUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS);
119 dprintf2(("Window class ptr %x", windowProc));
120
121 //User data class words/longs
122 if(nrExtraClassWords) {
123 userClassLong = (ULONG *)_smalloc(nrExtraClassWords);
124 if(userClassLong == NULL) {
125 dprintf(("Win32Class ctr: userClassLong == NULL!"));
126 exit(1);
127 }
128 memset(userClassLong, 0, nrExtraClassWords);
129 }
130 else userClassLong = NULL;
131
132 cWindows = 0;
133 hIconSm = wndclass->hIconSm;
134}
135//******************************************************************************
136//******************************************************************************
137Win32WndClass::~Win32WndClass()
138{
139 if(classNameA) {
140 dprintf(("Win32WndClass dtor, destroy class %s\n", classNameA));
141 }
142
143 //SvL: Don't delete global classes
144 if(classNameA && !(windowStyle & CS_GLOBALCLASS)) {
145 GlobalDeleteAtom(classAtom);
146 }
147
148 WINPROC_FreeProc(windowProc, WIN_PROC_CLASS);
149
150 if(userClassLong) free(userClassLong);
151 if(classNameA) free(classNameA);
152 if(classNameW) free(classNameW);
153 if(menuNameA && HIWORD(menuNameA)) {
154 free(menuNameA);
155 assert(menuNameW);
156 free(menuNameW);
157 }
158}
159//******************************************************************************
160//******************************************************************************
161void Win32WndClass::DestroyAll()
162{
163 fDestroyAll = TRUE;
164 GenericObject::DestroyAll(wndclasses);
165}
166//******************************************************************************
167//******************************************************************************
168BOOL Win32WndClass::hasClassName(LPSTR classname, BOOL fUnicode)
169{
170 if(HIWORD(classname) == 0) {
171 return classAtom == (DWORD)classname;
172 }
173 if(fUnicode) {
174 if(classNameW)
175 return (lstrcmpW(classNameW, (LPWSTR)classname) == 0);
176 return FALSE;
177 }
178 else {
179 if(classNameA)
180 return (strcmp(classNameA, classname) == 0);
181 return FALSE;
182 }
183}
184//******************************************************************************
185//******************************************************************************
186Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPSTR id)
187{
188 enterMutex(OBJTYPE_CLASS);
189
190 Win32WndClass *wndclass = (Win32WndClass *)wndclasses;
191
192 if(wndclass == NULL) {
193 leaveMutex(OBJTYPE_CLASS);
194 return(NULL);
195 }
196
197 if(HIWORD(id) != 0) {
198//CB: read comment below!
199 if(lstrcmpiA(wndclass->classNameA, id) == 0 && wndclass->hInstance == hInstance) {
200 leaveMutex(OBJTYPE_CLASS);
201 return(wndclass);
202 }
203 else {
204 wndclass = (Win32WndClass *)wndclass->GetNext();
205 while(wndclass != NULL) {
206 if(lstrcmpiA(wndclass->classNameA, id) == 0)
207 {
208 //SvL: According to Wine, if the instance handle is the one of the main exe, everything is ok
209 if(hInstance == NULL || GetModuleHandleA(NULL) == hInstance ||
210 wndclass->hInstance == hInstance)
211 {
212 leaveMutex(OBJTYPE_CLASS);
213 return(wndclass);
214 }
215 }
216 wndclass = (Win32WndClass *)wndclass->GetNext();
217 }
218 }
219 }
220 else {
221//CB: without HInstance check, test program finds class
222//CB: need more code to compare instance; convert 0 to exe module handle
223 if(wndclass->classAtom == (DWORD)id /*&& wndclass->hInstance == hInstance*/) {
224 leaveMutex(OBJTYPE_CLASS);
225 return(wndclass);
226 }
227 else {
228 wndclass = (Win32WndClass *)wndclass->GetNext();
229 while(wndclass != NULL) {
230 if(wndclass->classAtom == (DWORD)id /* && wndclass->hInstance == hInstance*/) {
231 leaveMutex(OBJTYPE_CLASS);
232 return(wndclass);
233 }
234 wndclass = (Win32WndClass *)wndclass->GetNext();
235 }
236 }
237 }
238 leaveMutex(OBJTYPE_CLASS);
239 dprintf(("Class %X (inst %X) not found!", id, hInstance));
240 return(NULL);
241}
242//******************************************************************************
243//An app can only access another process' class if it's global
244//(all system classes are global)
245//NOTE: NOT USED NOW
246//******************************************************************************
247BOOL Win32WndClass::isAppClass(ULONG curProcessId)
248{
249 if(windowStyle & CS_GLOBALCLASS)
250 return TRUE;
251
252 return curProcessId = processId;
253}
254//******************************************************************************
255//******************************************************************************
256BOOL Win32WndClass::getClassInfo(WNDCLASSEXA *wndclass)
257{
258 wndclass->cbClsExtra = nrExtraClassWords;
259 wndclass->cbWndExtra = nrExtraWindowWords;
260 wndclass->hbrBackground = backgroundBrush;
261 wndclass->hCursor = hCursor;
262 wndclass->hIcon = hIcon;
263 wndclass->hInstance = hInstance;
264 wndclass->lpszMenuName = (LPCTSTR)menuNameA;
265 wndclass->lpszClassName = (classNameA) ? (LPCTSTR)classNameA : (LPCTSTR)classAtom;
266 wndclass->style = windowStyle;
267 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, FALSE);
268 wndclass->hIconSm = hIconSm;
269 return(TRUE);
270}
271//******************************************************************************
272//******************************************************************************
273BOOL Win32WndClass::getClassInfo(WNDCLASSEXW *wndclass)
274{
275 wndclass->cbClsExtra = nrExtraClassWords;
276 wndclass->cbWndExtra = nrExtraWindowWords;
277 wndclass->hbrBackground = backgroundBrush;
278 wndclass->hCursor = hCursor;
279 wndclass->hIcon = hIcon;
280 wndclass->hInstance = hInstance;
281 wndclass->lpszMenuName = (LPCWSTR)menuNameW;
282 wndclass->lpszClassName = (classNameW) ? (LPCWSTR)classNameW : (LPCWSTR)classAtom;
283 wndclass->style = windowStyle;
284 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, TRUE);
285 wndclass->hIconSm = hIconSm;
286 return(TRUE);
287}
288//******************************************************************************
289//******************************************************************************
290ULONG Win32WndClass::getClassName(LPSTR lpszClassName, ULONG cchClassName)
291{
292 if(HIWORD(classNameA)) {
293 lstrcpynA(lpszClassName, classNameA, cchClassName-1);
294 return strlen(lpszClassName);
295 }
296 *(ULONG *)lpszClassName = classAtom;
297 return(sizeof(ULONG));
298}
299//******************************************************************************
300//******************************************************************************
301ULONG Win32WndClass::getClassName(LPWSTR lpszClassName, ULONG cchClassName)
302{
303 ULONG len;
304
305 if(HIWORD(classNameW)) {
306 lstrcpyW(lpszClassName, classNameW);
307 return lstrlenW(lpszClassName)*sizeof(WCHAR);
308 }
309 *(ULONG *)lpszClassName = classAtom;
310 return(sizeof(ULONG));
311}
312//******************************************************************************
313//******************************************************************************
314void Win32WndClass::setMenuName(LPSTR newMenuName)
315{
316 if(HIWORD(menuNameA)) {
317 free(menuNameA);
318 free(menuNameW);
319 menuNameA = 0;
320 menuNameW = 0;
321 }
322 if(HIWORD(newMenuName)) {
323 if(isUnicode) {
324 menuNameA = (PCHAR)_smalloc(lstrlenW((LPWSTR)newMenuName)+1);
325 menuNameW = (WCHAR *)_smalloc((lstrlenW((LPWSTR)newMenuName)+1)*sizeof(WCHAR));
326 }
327 else {
328 menuNameA = (PCHAR)_smalloc(strlen(newMenuName)+1);
329 menuNameW = (WCHAR *)_smalloc((strlen(newMenuName)+1)*sizeof(WCHAR));
330 }
331 if(menuNameA == NULL || menuNameW == NULL) {
332 dprintf(("Win32Class ctr; menuName/menuNameW == NULL"));
333 exit(1);
334 }
335 if(isUnicode) {
336 lstrcpyW(menuNameW, (LPWSTR)newMenuName);
337 UnicodeToAscii(menuNameW, menuNameA);
338 }
339 else {
340 strcpy((char *)menuNameA, newMenuName);
341 AsciiToUnicode(menuNameA, menuNameW);
342 }
343 }
344 else {//id
345 menuNameA = (PCHAR)newMenuName;
346 menuNameW = (WCHAR *)newMenuName;
347 }
348}
349//******************************************************************************
350//******************************************************************************
351ULONG Win32WndClass::getClassLongA(int index, BOOL fUnicode)
352{
353 switch(index) {
354 case GCL_CBCLSEXTRA:
355 return nrExtraClassWords;
356 case GCL_CBWNDEXTRA:
357 return nrExtraWindowWords;
358 case GCL_HBRBACKGROUND:
359 return backgroundBrush;
360 case GCL_HCURSOR:
361 return hCursor;
362 case GCL_HICON:
363 return hIcon;
364 case GCL_HMODULE:
365 return hInstance;
366 case GCL_MENUNAME:
367 return (isUnicode) ? (ULONG)menuNameW : (ULONG)menuNameA;
368 case GCL_STYLE:
369 return windowStyle;
370 case GCL_WNDPROC:
371 return (ULONG) WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
372 case GCW_ATOM: //TODO: does this really happen in windows?
373 SetLastError(ERROR_INVALID_PARAMETER);
374 return 0;
375 default:
376 if(index > 0 && index < nrExtraClassWords - sizeof(ULONG)) {
377 return userClassLong[index];
378 }
379 SetLastError(ERROR_INVALID_PARAMETER);
380 return 0;
381 }
382}
383//******************************************************************************
384//******************************************************************************
385WORD Win32WndClass::getClassWord(int index)
386{
387 switch(index) {
388 case GCW_ATOM:
389 return (WORD)classAtom;
390 default:
391 if(index > 0 && index < nrExtraClassWords - sizeof(WORD)) {
392 return ((WORD *)userClassLong)[index];
393 }
394 SetLastError(ERROR_INVALID_PARAMETER);
395 return 0;
396 }
397}
398//******************************************************************************
399//TODO: What effects what immediately?
400//******************************************************************************
401ULONG Win32WndClass::setClassLongA(int index, LONG lNewVal, BOOL fUnicode)
402{
403 ULONG rc;
404
405 if(classNameA) {
406 dprintf2(("Win32WndClass::setClassLongA %s: %d %x", classNameA, index, lNewVal));
407 }
408 else dprintf2(("Win32WndClass::setClassLongA %d: %d %x", classAtom, index, lNewVal));
409 switch(index) {
410 case GCL_CBCLSEXTRA: //TODO (doesn't affect allocated classes, so what does it do?)
411 rc = nrExtraClassWords;
412// nrExtraClassWords = lNewVal;
413 break;
414 case GCL_CBWNDEXTRA:
415 rc = nrExtraWindowWords;
416 nrExtraWindowWords = lNewVal;
417 break;
418 case GCL_HBRBACKGROUND:
419 rc = backgroundBrush;
420 backgroundBrush = lNewVal;
421 break;
422 case GCL_HCURSOR:
423 rc = hCursor;
424 hCursor = lNewVal;
425 break;
426 case GCL_HICON:
427 rc = hIcon;
428 hIcon = lNewVal;
429 break;
430 case GCL_HMODULE:
431 rc = hInstance;
432 hInstance = lNewVal;
433 break;
434 case GCL_MENUNAME:
435 rc = 0; //old value is meaningless (according to Wine)
436 setMenuName((LPSTR)lNewVal);
437 break;
438 case GCL_STYLE:
439 rc = windowStyle;
440 windowStyle = lNewVal;
441 break;
442 case GCL_WNDPROC:
443 rc = (LONG)WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A );
444 WINPROC_SetProc((HWINDOWPROC *)&windowProc, (WNDPROC)lNewVal, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS );
445 break;
446 case GCW_ATOM: //TODO: does this really happen in windows?
447 SetLastError(ERROR_INVALID_PARAMETER);
448 return 0;
449 default:
450 if(index > 0 && index < nrExtraClassWords - sizeof(ULONG)) {
451 rc = userClassLong[index];
452 userClassLong[index] = lNewVal;
453 return(rc);
454 }
455 SetLastError(ERROR_INVALID_PARAMETER);
456 return 0;
457 }
458 return(rc);
459}
460//******************************************************************************
461//******************************************************************************
462WORD Win32WndClass::setClassWord(int index, WORD wNewVal)
463{
464 WORD rc;
465
466 switch(index) {
467 case GCW_ATOM:
468 rc = (WORD)classAtom;
469 classAtom = wNewVal;
470 return(rc);
471 default:
472 if(index > 0 && index < nrExtraClassWords - sizeof(WORD)) {
473 rc = ((WORD *)userClassLong)[index];
474 ((WORD *)userClassLong)[index] = wNewVal;
475 return(rc);
476 }
477 SetLastError(ERROR_INVALID_PARAMETER);
478 return 0;
479 }
480}
481//******************************************************************************
482//FIXME: Windows that still exists with this class
483//******************************************************************************
484void Win32WndClass::UnregisterClassA(HINSTANCE hinst, LPSTR id)
485{
486 Win32WndClass *wndclass;
487
488 wndclass = FindClass(hinst, id);
489 if(wndclass) {
490 delete wndclass;
491 return;
492 }
493 dprintf(("::UnregisterClass, couldn't find class %X!!\n", id));
494}
495//******************************************************************************
496//******************************************************************************
497GenericObject *Win32WndClass::wndclasses = NULL;
Note: See TracBrowser for help on using the repository browser.