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

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

Added new logging feature

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