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

Last change on this file since 3832 was 3702, checked in by sandervl, 25 years ago

when registering a class, check if it already exists and return error

File size: 18.8 KB
Line 
1/* $Id: win32class.cpp,v 1.17 2000-06-13 21:26:29 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 dprintf(("USER32: wndclass->hIconSm %X\n", wndclass->hIconSm));
103
104 nrExtraClassWords = wndclass->cbClsExtra;
105 nrExtraWindowWords = wndclass->cbWndExtra;
106 backgroundBrush = wndclass->hbrBackground;
107 hCursor = wndclass->hCursor;
108 hIcon = wndclass->hIcon;
109 hInstance = wndclass->hInstance;
110
111 if(wndclass->style & CS_CLASSDC) {
112 hdcClass = 0; //TODO:
113 }
114 else hdcClass = 0;
115
116 windowStyle = wndclass->style;
117
118 windowProc = 0;
119 WINPROC_SetProc((HWINDOWPROC *)&windowProc, wndclass->lpfnWndProc, (isUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS);
120 dprintf2(("Window class ptr %x", windowProc));
121
122 //User data class words/longs
123 if(nrExtraClassWords) {
124 userClassLong = (ULONG *)_smalloc(nrExtraClassWords);
125 if(userClassLong == NULL) {
126 dprintf(("Win32Class ctr: userClassLong == NULL!"));
127 exit(1);
128 }
129 memset(userClassLong, 0, nrExtraClassWords);
130 }
131 else userClassLong = NULL;
132
133 cWindows = 0;
134 hIconSm = wndclass->hIconSm;
135}
136//******************************************************************************
137//******************************************************************************
138Win32WndClass::~Win32WndClass()
139{
140 if(classNameA) {
141 dprintf(("Win32WndClass dtor, destroy class %s\n", classNameA));
142 }
143
144 //SvL: Don't delete global classes
145 if(classNameA && !(windowStyle & CS_GLOBALCLASS)) {
146 GlobalDeleteAtom(classAtom);
147 }
148
149 WINPROC_FreeProc(windowProc, WIN_PROC_CLASS);
150
151 if(userClassLong) free(userClassLong);
152 if(classNameA) free(classNameA);
153 if(classNameW) free(classNameW);
154 if(menuNameA && HIWORD(menuNameA)) {
155 free(menuNameA);
156 assert(menuNameW);
157 free(menuNameW);
158 }
159}
160//******************************************************************************
161//******************************************************************************
162void Win32WndClass::DestroyAll()
163{
164 fDestroyAll = TRUE;
165 GenericObject::DestroyAll(wndclasses);
166}
167//******************************************************************************
168//******************************************************************************
169BOOL Win32WndClass::hasClassName(LPSTR classname, BOOL fUnicode)
170{
171 if(HIWORD(classname) == 0) {
172 return classAtom == (DWORD)classname;
173 }
174 if(fUnicode) {
175 if(classNameW)
176 return (lstrcmpW(classNameW, (LPWSTR)classname) == 0);
177 return FALSE;
178 }
179 else {
180 if(classNameA)
181 return (strcmp(classNameA, classname) == 0);
182 return FALSE;
183 }
184}
185//******************************************************************************
186//******************************************************************************
187Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPSTR id)
188{
189 enterMutex(OBJTYPE_CLASS);
190
191 Win32WndClass *wndclass = (Win32WndClass *)wndclasses;
192
193 if(wndclass == NULL) {
194 leaveMutex(OBJTYPE_CLASS);
195 return(NULL);
196 }
197
198 if(HIWORD(id) != 0) {
199//CB: read comment below!
200 if(lstrcmpiA(wndclass->classNameA, id) == 0 && wndclass->hInstance == hInstance) {
201 leaveMutex(OBJTYPE_CLASS);
202 return(wndclass);
203 }
204 else {
205 wndclass = (Win32WndClass *)wndclass->GetNext();
206 while(wndclass != NULL) {
207 if(lstrcmpiA(wndclass->classNameA, id) == 0)
208 {
209 //SvL: According to Wine, if the instance handle is the one of the main exe, everything is ok
210 if(hInstance == NULL || GetModuleHandleA(NULL) == hInstance ||
211 wndclass->hInstance == hInstance)
212 {
213 leaveMutex(OBJTYPE_CLASS);
214 return(wndclass);
215 }
216 }
217 wndclass = (Win32WndClass *)wndclass->GetNext();
218 }
219 }
220 }
221 else {
222//CB: without HInstance check, test program finds class
223//CB: need more code to compare instance; convert 0 to exe module handle
224 if(wndclass->classAtom == (DWORD)id /*&& wndclass->hInstance == hInstance*/) {
225 leaveMutex(OBJTYPE_CLASS);
226 return(wndclass);
227 }
228 else {
229 wndclass = (Win32WndClass *)wndclass->GetNext();
230 while(wndclass != NULL) {
231 if(wndclass->classAtom == (DWORD)id /* && wndclass->hInstance == hInstance*/) {
232 leaveMutex(OBJTYPE_CLASS);
233 return(wndclass);
234 }
235 wndclass = (Win32WndClass *)wndclass->GetNext();
236 }
237 }
238 }
239 leaveMutex(OBJTYPE_CLASS);
240 dprintf(("Class %X (inst %X) not found!", id, hInstance));
241 return(NULL);
242}
243//******************************************************************************
244//******************************************************************************
245Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPWSTR id)
246{
247 LPSTR lpszClassName;
248 Win32WndClass *winclass;
249
250 if(HIWORD(id)) {
251 lpszClassName = UnicodeToAsciiString((LPWSTR)id);
252 }
253 else lpszClassName = (LPSTR)id;
254
255 winclass = FindClass(hInstance, lpszClassName);
256
257 if(HIWORD(id)) {
258 FreeAsciiString((char *)lpszClassName);
259 }
260 return winclass;
261}
262//******************************************************************************
263//An app can only access another process' class if it's global
264//(all system classes are global)
265//NOTE: NOT USED NOW
266//******************************************************************************
267BOOL Win32WndClass::isAppClass(ULONG curProcessId)
268{
269 if(windowStyle & CS_GLOBALCLASS)
270 return TRUE;
271
272 return curProcessId = processId;
273}
274//******************************************************************************
275//******************************************************************************
276BOOL Win32WndClass::getClassInfo(WNDCLASSEXA *wndclass)
277{
278 wndclass->cbClsExtra = nrExtraClassWords;
279 wndclass->cbWndExtra = nrExtraWindowWords;
280 wndclass->hbrBackground = backgroundBrush;
281 wndclass->hCursor = hCursor;
282 wndclass->hIcon = hIcon;
283 wndclass->hInstance = hInstance;
284 wndclass->lpszMenuName = (LPCTSTR)menuNameA;
285 wndclass->lpszClassName = (classNameA) ? (LPCTSTR)classNameA : (LPCTSTR)classAtom;
286 wndclass->style = windowStyle;
287 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, FALSE);
288 wndclass->hIconSm = hIconSm;
289 return(TRUE);
290}
291//******************************************************************************
292//******************************************************************************
293BOOL Win32WndClass::getClassInfo(WNDCLASSEXW *wndclass)
294{
295 wndclass->cbClsExtra = nrExtraClassWords;
296 wndclass->cbWndExtra = nrExtraWindowWords;
297 wndclass->hbrBackground = backgroundBrush;
298 wndclass->hCursor = hCursor;
299 wndclass->hIcon = hIcon;
300 wndclass->hInstance = hInstance;
301 wndclass->lpszMenuName = (LPCWSTR)menuNameW;
302 wndclass->lpszClassName = (classNameW) ? (LPCWSTR)classNameW : (LPCWSTR)classAtom;
303 wndclass->style = windowStyle;
304 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, TRUE);
305 wndclass->hIconSm = hIconSm;
306 return(TRUE);
307}
308//******************************************************************************
309//******************************************************************************
310ULONG Win32WndClass::getClassName(LPSTR lpszClassName, ULONG cchClassName)
311{
312 if(HIWORD(classNameA)) {
313 lstrcpynA(lpszClassName, classNameA, cchClassName-1);
314 return strlen(lpszClassName);
315 }
316 *(ULONG *)lpszClassName = classAtom;
317 return(sizeof(ULONG));
318}
319//******************************************************************************
320//******************************************************************************
321ULONG Win32WndClass::getClassName(LPWSTR lpszClassName, ULONG cchClassName)
322{
323 ULONG len;
324
325 if(HIWORD(classNameW)) {
326 lstrcpyW(lpszClassName, classNameW);
327 return lstrlenW(lpszClassName)*sizeof(WCHAR);
328 }
329 *(ULONG *)lpszClassName = classAtom;
330 return(sizeof(ULONG));
331}
332//******************************************************************************
333//******************************************************************************
334void Win32WndClass::setMenuName(LPSTR newMenuName)
335{
336 if(HIWORD(menuNameA)) {
337 free(menuNameA);
338 free(menuNameW);
339 menuNameA = 0;
340 menuNameW = 0;
341 }
342 if(HIWORD(newMenuName)) {
343 if(isUnicode) {
344 menuNameA = (PCHAR)_smalloc(lstrlenW((LPWSTR)newMenuName)+1);
345 menuNameW = (WCHAR *)_smalloc((lstrlenW((LPWSTR)newMenuName)+1)*sizeof(WCHAR));
346 }
347 else {
348 menuNameA = (PCHAR)_smalloc(strlen(newMenuName)+1);
349 menuNameW = (WCHAR *)_smalloc((strlen(newMenuName)+1)*sizeof(WCHAR));
350 }
351 if(menuNameA == NULL || menuNameW == NULL) {
352 dprintf(("Win32Class ctr; menuName/menuNameW == NULL"));
353 exit(1);
354 }
355 if(isUnicode) {
356 lstrcpyW(menuNameW, (LPWSTR)newMenuName);
357 UnicodeToAscii(menuNameW, menuNameA);
358 }
359 else {
360 strcpy((char *)menuNameA, newMenuName);
361 AsciiToUnicode(menuNameA, menuNameW);
362 }
363 }
364 else {//id
365 menuNameA = (PCHAR)newMenuName;
366 menuNameW = (WCHAR *)newMenuName;
367 }
368}
369//******************************************************************************
370//******************************************************************************
371ULONG Win32WndClass::getClassLongA(int index, BOOL fUnicode)
372{
373 switch(index) {
374 case GCL_CBCLSEXTRA:
375 return nrExtraClassWords;
376 case GCL_CBWNDEXTRA:
377 return nrExtraWindowWords;
378 case GCL_HBRBACKGROUND:
379 return backgroundBrush;
380 case GCL_HCURSOR:
381 return hCursor;
382 case GCL_HICON:
383 return hIcon;
384 case GCL_HICONSM:
385 return hIconSm;
386 case GCL_HMODULE:
387 return hInstance;
388 case GCL_MENUNAME:
389 return (isUnicode) ? (ULONG)menuNameW : (ULONG)menuNameA;
390 case GCL_STYLE:
391 return windowStyle;
392 case GCL_WNDPROC:
393 return (ULONG) WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
394 case GCW_ATOM: //TODO: does this really happen in windows?
395 SetLastError(ERROR_INVALID_PARAMETER);
396 return 0;
397 default:
398 if(index > 0 && index < nrExtraClassWords - sizeof(ULONG)) {
399 return userClassLong[index];
400 }
401 SetLastError(ERROR_INVALID_PARAMETER);
402 return 0;
403 }
404}
405//******************************************************************************
406//******************************************************************************
407WORD Win32WndClass::getClassWord(int index)
408{
409 switch(index) {
410 case GCW_ATOM:
411 return (WORD)classAtom;
412 default:
413 if(index > 0 && index < nrExtraClassWords - sizeof(WORD)) {
414 return ((WORD *)userClassLong)[index];
415 }
416 SetLastError(ERROR_INVALID_PARAMETER);
417 return 0;
418 }
419}
420//******************************************************************************
421//TODO: What effects what immediately?
422//******************************************************************************
423ULONG Win32WndClass::setClassLongA(int index, LONG lNewVal, BOOL fUnicode)
424{
425 ULONG rc;
426
427 if(classNameA) {
428 dprintf2(("Win32WndClass::setClassLongA %s: %d %x", classNameA, index, lNewVal));
429 }
430 else dprintf2(("Win32WndClass::setClassLongA %d: %d %x", classAtom, index, lNewVal));
431 switch(index) {
432 case GCL_CBCLSEXTRA: //TODO (doesn't affect allocated classes, so what does it do?)
433 rc = nrExtraClassWords;
434// nrExtraClassWords = lNewVal;
435 break;
436 case GCL_CBWNDEXTRA:
437 rc = nrExtraWindowWords;
438 nrExtraWindowWords = lNewVal;
439 break;
440 case GCL_HBRBACKGROUND:
441 rc = backgroundBrush;
442 backgroundBrush = lNewVal;
443 break;
444 case GCL_HCURSOR:
445 rc = hCursor;
446 hCursor = lNewVal;
447 break;
448 case GCL_HICON:
449 rc = hIcon;
450 hIcon = lNewVal;
451 break;
452 case GCL_HICONSM:
453 rc = hIconSm;
454 hIconSm = lNewVal;
455 break;
456 case GCL_HMODULE:
457 rc = hInstance;
458 hInstance = lNewVal;
459 break;
460 case GCL_MENUNAME:
461 rc = 0; //old value is meaningless (according to Wine)
462 setMenuName((LPSTR)lNewVal);
463 break;
464 case GCL_STYLE:
465 rc = windowStyle;
466 windowStyle = lNewVal;
467 break;
468 case GCL_WNDPROC:
469 rc = (LONG)WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A );
470 WINPROC_SetProc((HWINDOWPROC *)&windowProc, (WNDPROC)lNewVal, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS );
471 break;
472 case GCW_ATOM: //TODO: does this really happen in windows?
473 SetLastError(ERROR_INVALID_PARAMETER);
474 return 0;
475 default:
476 if(index > 0 && index < nrExtraClassWords - sizeof(ULONG)) {
477 rc = userClassLong[index];
478 userClassLong[index] = lNewVal;
479 return(rc);
480 }
481 SetLastError(ERROR_INVALID_PARAMETER);
482 return 0;
483 }
484 return(rc);
485}
486//******************************************************************************
487//******************************************************************************
488WORD Win32WndClass::setClassWord(int index, WORD wNewVal)
489{
490 WORD rc;
491
492 switch(index) {
493 case GCW_ATOM:
494 rc = (WORD)classAtom;
495 classAtom = wNewVal;
496 return(rc);
497 default:
498 if(index > 0 && index < nrExtraClassWords - sizeof(WORD)) {
499 rc = ((WORD *)userClassLong)[index];
500 ((WORD *)userClassLong)[index] = wNewVal;
501 return(rc);
502 }
503 SetLastError(ERROR_INVALID_PARAMETER);
504 return 0;
505 }
506}
507//******************************************************************************
508//FIXME: Windows that still exists with this class
509//******************************************************************************
510void Win32WndClass::UnregisterClassA(HINSTANCE hinst, LPSTR id)
511{
512 Win32WndClass *wndclass;
513
514 wndclass = FindClass(hinst, id);
515 if(wndclass) {
516 delete wndclass;
517 return;
518 }
519 dprintf(("::UnregisterClass, couldn't find class %X!!\n", id));
520}
521//******************************************************************************
522//******************************************************************************
523GenericObject *Win32WndClass::wndclasses = NULL;
Note: See TracBrowser for help on using the repository browser.