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

Last change on this file since 5472 was 5472, checked in by sandervl, 24 years ago

compile fix

File size: 21.4 KB
Line 
1/* $Id: win32class.cpp,v 1.24 2001-04-04 09:01:25 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#include <unicode.h>
27
28#define DBG_LOCALLOG DBG_win32class
29#include "dbglocal.h"
30
31static fDestroyAll = FALSE;
32
33//******************************************************************************
34//Win32WndClass methods:
35//******************************************************************************
36Win32WndClass::Win32WndClass(WNDCLASSEXA *wndclass, BOOL fUnicode) : GenericObject(&wndclasses, OBJTYPE_CLASS)
37{
38 isUnicode = fUnicode;
39 processId = 0;
40
41 if(HIWORD(wndclass->lpszClassName)) {
42 if(isUnicode) {
43 INT len = lstrlenW((LPWSTR)wndclass->lpszClassName)+1;
44
45 classNameA = (PCHAR)_smalloc(len);
46 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
47 }
48 else {
49 INT len = strlen(wndclass->lpszClassName)+1;
50
51 classNameA = (PCHAR)_smalloc(len);
52 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
53 }
54 if(classNameA == NULL || classNameW == NULL) {
55 dprintf(("Win32Class ctr; classNameA/classNameW == NULL"));
56 exit(1);
57 }
58 if(isUnicode) {
59 lstrcpyW(classNameW, (LPWSTR)wndclass->lpszClassName);
60 UnicodeToAscii(classNameW, classNameA);
61 }
62 else {
63 strcpy((char *)classNameA, wndclass->lpszClassName);
64 AsciiToUnicode(classNameA, classNameW);
65 }
66 classAtom = 0;
67 //SvL: If a system control has already be registered, use that atom instead
68 // of creating a new one
69 if(wndclass->style & CS_GLOBALCLASS) {
70 classAtom = GlobalFindAtomA(classNameA);
71 }
72 if(!classAtom) classAtom = GlobalAddAtomA(classNameA);
73 }
74 else {
75 classNameA = NULL;
76 classNameW = NULL;
77 classAtom = (DWORD)wndclass->lpszClassName;
78 }
79 if(!(wndclass->style & CS_GLOBALCLASS)) {
80 processId = GetCurrentProcess();
81 }
82 menuNameA = 0;
83 menuNameW = 0;
84 setMenuName((LPSTR)wndclass->lpszMenuName);
85
86 dprintf(("USER32: Win32Class ctor\n"));
87 dprintf(("USER32: wndclass->style %X\n", wndclass->style));
88 dprintf(("USER32: wndclass->lpfnWndProc %X\n", wndclass->lpfnWndProc));
89 dprintf(("USER32: wndclass->cbClsExtra %X\n", wndclass->cbClsExtra));
90 dprintf(("USER32: wndclass->cbWndExtra %X\n", wndclass->cbWndExtra));
91 dprintf(("USER32: wndclass->hInstance %X\n", wndclass->hInstance));
92 dprintf(("USER32: wndclass->hIcon %X\n", wndclass->hIcon));
93 dprintf(("USER32: wndclass->hCursor %X\n", wndclass->hCursor));
94 dprintf(("USER32: wndclass->hbrBackground %X\n", wndclass->hbrBackground));
95 if(HIWORD(wndclass->lpszClassName))
96 dprintf(("USER32: wndclass->lpszClassName %s\n", classNameA));
97 else dprintf(("USER32: wndclass->lpszClassName %X\n", wndclass->lpszClassName));
98
99 dprintf(("USER32: wndclass->classAtom %x", classAtom));
100
101 if(HIWORD(wndclass->lpszMenuName)) {//convert string name identifier to numeric id
102 dprintf(("USER32: lpszMenuName %s\n", menuNameA));
103 }
104 else dprintf(("USER32: wndclass->lpszMenuName %X\n", menuNameA));
105 dprintf(("USER32: wndclass->hIconSm %X\n", wndclass->hIconSm));
106
107 nrExtraClassBytes = wndclass->cbClsExtra;
108 nrExtraWindowBytes = wndclass->cbWndExtra;
109 backgroundBrush = wndclass->hbrBackground;
110 hCursor = wndclass->hCursor;
111 hIcon = wndclass->hIcon;
112 hInstance = wndclass->hInstance;
113
114 if(wndclass->style & CS_CLASSDC) {
115 hdcClass = 0; //TODO:
116 }
117 else hdcClass = 0;
118
119 windowStyle = wndclass->style;
120
121 windowProc = 0;
122 WINPROC_SetProc((HWINDOWPROC *)&windowProc, wndclass->lpfnWndProc, (isUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS);
123 dprintf2(("Window class ptr %x", windowProc));
124
125 //User data class words/longs
126 if(nrExtraClassBytes) {
127 userClassBytes = (char *)_smalloc(nrExtraClassBytes);
128 if(userClassBytes == NULL) {
129 dprintf(("Win32Class ctr: userClassBytes == NULL!"));
130 exit(1);
131 }
132 memset(userClassBytes, 0, nrExtraClassBytes);
133 }
134 else userClassBytes = NULL;
135
136 cWindows = 0;
137 hIconSm = wndclass->hIconSm;
138}
139//******************************************************************************
140//******************************************************************************
141Win32WndClass::~Win32WndClass()
142{
143 if(classNameA) {
144 dprintf(("Win32WndClass dtor, destroy class %s\n", classNameA));
145 }
146
147 //SvL: Don't delete global classes
148 if(classNameA && !(windowStyle & CS_GLOBALCLASS)) {
149 GlobalDeleteAtom(classAtom);
150 }
151
152 WINPROC_FreeProc(windowProc, WIN_PROC_CLASS);
153
154 if(userClassBytes) free(userClassBytes);
155 if(classNameA) free(classNameA);
156 if(classNameW) free(classNameW);
157 if(menuNameA && HIWORD(menuNameA)) {
158 free(menuNameA);
159 assert(menuNameW);
160 free(menuNameW);
161 }
162}
163//******************************************************************************
164//******************************************************************************
165void Win32WndClass::DestroyAll()
166{
167 fDestroyAll = TRUE;
168 GenericObject::DestroyAll(wndclasses);
169}
170//******************************************************************************
171//******************************************************************************
172BOOL Win32WndClass::hasClassName(LPSTR classname, BOOL fUnicode)
173{
174 if(HIWORD(classname) == 0) {
175 return classAtom == (DWORD)classname;
176 }
177 if(fUnicode) {
178 if(classNameW)
179 return (lstrcmpW(classNameW, (LPWSTR)classname) == 0);
180 return FALSE;
181 }
182 else {
183 if(classNameA)
184 return (strcmp(classNameA, classname) == 0);
185 return FALSE;
186 }
187}
188//******************************************************************************
189//******************************************************************************
190Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPSTR id)
191{
192 enterMutex(OBJTYPE_CLASS);
193
194 Win32WndClass *wndclass = (Win32WndClass *)wndclasses;
195
196 if(wndclass == NULL) {
197 leaveMutex(OBJTYPE_CLASS);
198 return(NULL);
199 }
200
201 if(HIWORD(id) != 0) {
202//CB: read comment below!
203 if(lstrcmpiA(wndclass->classNameA, id) == 0 && wndclass->hInstance == hInstance) {
204 leaveMutex(OBJTYPE_CLASS);
205 return(wndclass);
206 }
207 else {
208 wndclass = (Win32WndClass *)wndclass->GetNext();
209 while(wndclass != NULL) {
210 if(lstrcmpiA(wndclass->classNameA, id) == 0)
211 {
212 //SvL: According to Wine, if the instance handle is the one of the main exe, everything is ok
213 if(hInstance == NULL || GetModuleHandleA(NULL) == hInstance ||
214 wndclass->hInstance == hInstance)
215 {
216 leaveMutex(OBJTYPE_CLASS);
217 return(wndclass);
218 }
219 }
220 wndclass = (Win32WndClass *)wndclass->GetNext();
221 }
222 }
223 }
224 else {
225//CB: without HInstance check, test program finds class
226//CB: need more code to compare instance; convert 0 to exe module handle
227 if(wndclass->classAtom == (DWORD)id /*&& wndclass->hInstance == hInstance*/) {
228 leaveMutex(OBJTYPE_CLASS);
229 return(wndclass);
230 }
231 else {
232 wndclass = (Win32WndClass *)wndclass->GetNext();
233 while(wndclass != NULL) {
234 if(wndclass->classAtom == (DWORD)id /* && wndclass->hInstance == hInstance*/) {
235 leaveMutex(OBJTYPE_CLASS);
236 return(wndclass);
237 }
238 wndclass = (Win32WndClass *)wndclass->GetNext();
239 }
240 }
241 }
242 leaveMutex(OBJTYPE_CLASS);
243 dprintf(("Class %X (inst %X) not found!", id, hInstance));
244 return(NULL);
245}
246//******************************************************************************
247//******************************************************************************
248Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPWSTR id)
249{
250 LPSTR lpszClassName;
251 Win32WndClass *winclass;
252
253 if(HIWORD(id)) {
254 lpszClassName = UnicodeToAsciiString((LPWSTR)id);
255 }
256 else lpszClassName = (LPSTR)id;
257
258 winclass = FindClass(hInstance, lpszClassName);
259
260 if(HIWORD(id)) {
261 FreeAsciiString((char *)lpszClassName);
262 }
263 return winclass;
264}
265//******************************************************************************
266//An app can only access another process' class if it's global
267//(all system classes are global)
268//NOTE: NOT USED NOW
269//******************************************************************************
270BOOL Win32WndClass::isAppClass(ULONG curProcessId)
271{
272 if(windowStyle & CS_GLOBALCLASS)
273 return TRUE;
274
275 return curProcessId = processId;
276}
277//******************************************************************************
278//******************************************************************************
279BOOL Win32WndClass::getClassInfo(WNDCLASSEXA *wndclass)
280{
281 wndclass->cbClsExtra = nrExtraClassBytes;
282 wndclass->cbWndExtra = nrExtraWindowBytes;
283 wndclass->hbrBackground = backgroundBrush;
284 wndclass->hCursor = hCursor;
285 wndclass->hIcon = hIcon;
286 wndclass->hInstance = hInstance;
287 wndclass->lpszMenuName = (LPCTSTR)menuNameA;
288 wndclass->lpszClassName = (classNameA) ? (LPCTSTR)classNameA : (LPCTSTR)classAtom;
289 wndclass->style = windowStyle;
290 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, FALSE);
291 wndclass->hIconSm = hIconSm;
292 return(TRUE);
293}
294//******************************************************************************
295//******************************************************************************
296BOOL Win32WndClass::getClassInfo(WNDCLASSEXW *wndclass)
297{
298 wndclass->cbClsExtra = nrExtraClassBytes;
299 wndclass->cbWndExtra = nrExtraWindowBytes;
300 wndclass->hbrBackground = backgroundBrush;
301 wndclass->hCursor = hCursor;
302 wndclass->hIcon = hIcon;
303 wndclass->hInstance = hInstance;
304 wndclass->lpszMenuName = (LPCWSTR)menuNameW;
305 wndclass->lpszClassName = (classNameW) ? (LPCWSTR)classNameW : (LPCWSTR)classAtom;
306 wndclass->style = windowStyle;
307 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, TRUE);
308 wndclass->hIconSm = hIconSm;
309 return(TRUE);
310}
311//******************************************************************************
312//******************************************************************************
313ULONG Win32WndClass::getClassName(LPSTR lpszClassName, ULONG cchClassName)
314{
315 if(HIWORD(classNameA)) {
316 lstrcpynA(lpszClassName, classNameA, cchClassName-1);
317 return strlen(lpszClassName);
318 }
319 *(ULONG *)lpszClassName = classAtom;
320 return(sizeof(ULONG));
321}
322//******************************************************************************
323//******************************************************************************
324ULONG Win32WndClass::getClassName(LPWSTR lpszClassName, ULONG cchClassName)
325{
326 ULONG len;
327
328 if(HIWORD(classNameW)) {
329 lstrcpyW(lpszClassName, classNameW);
330 return lstrlenW(lpszClassName)*sizeof(WCHAR);
331 }
332 *(ULONG *)lpszClassName = classAtom;
333 return(sizeof(ULONG));
334}
335//******************************************************************************
336//******************************************************************************
337void Win32WndClass::setMenuName(LPSTR newMenuName)
338{
339 if(HIWORD(menuNameA)) {
340 free(menuNameA);
341 free(menuNameW);
342 menuNameA = 0;
343 menuNameW = 0;
344 }
345 if(HIWORD(newMenuName)) {
346 if(isUnicode) {
347 menuNameA = (PCHAR)_smalloc(lstrlenW((LPWSTR)newMenuName)+1);
348 menuNameW = (WCHAR *)_smalloc((lstrlenW((LPWSTR)newMenuName)+1)*sizeof(WCHAR));
349 }
350 else {
351 menuNameA = (PCHAR)_smalloc(strlen(newMenuName)+1);
352 menuNameW = (WCHAR *)_smalloc((strlen(newMenuName)+1)*sizeof(WCHAR));
353 }
354 if(menuNameA == NULL || menuNameW == NULL) {
355 dprintf(("Win32Class ctr; menuName/menuNameW == NULL"));
356 exit(1);
357 }
358 if(isUnicode) {
359 lstrcpyW(menuNameW, (LPWSTR)newMenuName);
360 UnicodeToAscii(menuNameW, menuNameA);
361 }
362 else {
363 strcpy((char *)menuNameA, newMenuName);
364 AsciiToUnicode(menuNameA, menuNameW);
365 }
366
367 }
368 else {//id
369 menuNameA = (PCHAR)newMenuName;
370 menuNameW = (WCHAR *)newMenuName;
371 }
372}
373//******************************************************************************
374//******************************************************************************
375ULONG Win32WndClass::getClassLongA(int index, BOOL fUnicode)
376{
377 switch(index) {
378 case GCL_CBCLSEXTRA:
379 return nrExtraClassBytes;
380 case GCL_CBWNDEXTRA:
381 return nrExtraWindowBytes;
382 case GCL_HBRBACKGROUND:
383 return backgroundBrush;
384 case GCL_HCURSOR:
385 return hCursor;
386 case GCL_HICON:
387 return hIcon;
388 case GCL_HICONSM:
389 return hIconSm;
390 case GCL_HMODULE:
391 return hInstance;
392 case GCL_MENUNAME:
393 return (isUnicode) ? (ULONG)menuNameW : (ULONG)menuNameA;
394 case GCL_STYLE:
395 return windowStyle;
396 case GCL_WNDPROC:
397 return (ULONG) WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
398 case GCW_ATOM: //TODO: does this really happen in windows?
399 SetLastError(ERROR_INVALID_PARAMETER);
400 return 0;
401 default:
402 if(index >= 0 && index + sizeof(ULONG) <= nrExtraClassBytes) {
403 //Note: NT4, SP6 does not set the last error to 0
404 SetLastError(ERROR_SUCCESS);
405 return *(ULONG *)(userClassBytes + index);
406 }
407 if(classNameA) {
408 dprintf2(("WARNING: getClassLong %s: %d -> wrong INDEX", classNameA, index));
409 }
410 else dprintf2(("WARNING: getClassLong %d: %d -> wrong INDEX", classAtom, index));
411 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
412 return 0;
413 }
414}
415//******************************************************************************
416//******************************************************************************
417WORD Win32WndClass::getClassWord(int index)
418{
419 switch(index) {
420 case GCW_ATOM:
421 return (WORD)classAtom;
422 default:
423 if(index >= 0 && index + sizeof(WORD) <= nrExtraClassBytes) {
424 //Note: NT4, SP6 does not set the last error to 0
425 SetLastError(ERROR_SUCCESS);
426 return *(WORD *)(userClassBytes + index);
427 }
428 if(classNameA) {
429 dprintf2(("WARNING: getClassWord %s: %d -> wrong INDEX", classNameA, index));
430 }
431 else dprintf2(("WARNING: getClassWord %d: %d -> wrong INDEX", classAtom, index));
432 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
433 return 0;
434 }
435}
436//******************************************************************************
437//TODO: What effects what immediately?
438//******************************************************************************
439ULONG Win32WndClass::setClassLongA(int index, LONG lNewVal, BOOL fUnicode)
440{
441 ULONG rc;
442
443 switch(index) {
444 case GCL_CBCLSEXTRA: //TODO (doesn't affect allocated classes, so what does it do?)
445 rc = nrExtraClassBytes;
446// nrExtraClassBytes = lNewVal;
447 break;
448 case GCL_CBWNDEXTRA:
449 rc = nrExtraWindowBytes;
450 nrExtraWindowBytes = lNewVal;
451 break;
452 case GCL_HBRBACKGROUND:
453 rc = backgroundBrush;
454 backgroundBrush = lNewVal;
455 break;
456 case GCL_HCURSOR:
457 rc = hCursor;
458 hCursor = lNewVal;
459 break;
460 case GCL_HICON:
461 rc = hIcon;
462 hIcon = lNewVal;
463 break;
464 case GCL_HICONSM:
465 rc = hIconSm;
466 hIconSm = lNewVal;
467 break;
468 case GCL_HMODULE:
469 rc = hInstance;
470 hInstance = lNewVal;
471 break;
472 case GCL_MENUNAME:
473 rc = 0; //old value is meaningless (according to Wine)
474 setMenuName((LPSTR)lNewVal);
475 break;
476 case GCL_STYLE:
477 rc = windowStyle;
478 windowStyle = lNewVal;
479 break;
480 case GCL_WNDPROC:
481 //Note: Type of SetWindowLong determines new window proc type
482 // UNLESS the new window proc has already been registered
483 // (use the old type in that case)
484 // (VERIFIED in NT 4, SP6)
485 //TODO: Is that also true for GCL_WNDPROC???????????????
486 rc = (LONG)WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A );
487 WINPROC_SetProc((HWINDOWPROC *)&windowProc, (WNDPROC)lNewVal, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS );
488 break;
489 case GCW_ATOM: //TODO: does this really happen in windows?
490 SetLastError(ERROR_INVALID_PARAMETER);
491 return 0;
492 default:
493 if(index >= 0 && index + sizeof(ULONG) <= nrExtraClassBytes) {
494 rc = *(ULONG *)(userClassBytes + index);
495 *(ULONG *)(userClassBytes + index) = lNewVal;
496 break;
497 }
498 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
499 if(classNameA) {
500 dprintf2(("WARNING: Win32WndClass::setClassLongA %s: %d %x -> wrong INDEX", classNameA, index, lNewVal));
501 }
502 else dprintf2(("WARNING: Win32WndClass::setClassLongA %d: %d %x -> wrong INDEX", classAtom, index, lNewVal));
503 return 0;
504 }
505 SetLastError(ERROR_SUCCESS);
506 if(classNameA) {
507 dprintf2(("Win32WndClass::setClassLongA %s: %d %x returned %x", classNameA, index, lNewVal, rc));
508 }
509 else dprintf2(("Win32WndClass::setClassLongA %d: %d %x returned %x", classAtom, index, lNewVal, rc));
510 return(rc);
511}
512//******************************************************************************
513//******************************************************************************
514WORD Win32WndClass::setClassWord(int index, WORD wNewVal)
515{
516 WORD rc;
517
518 switch(index) {
519 case GCW_ATOM:
520 rc = (WORD)classAtom;
521 classAtom = wNewVal;
522 return(rc);
523 default:
524 if(index >= 0 && index + sizeof(WORD) <= nrExtraClassBytes) {
525 rc = *(WORD *)(userClassBytes + index);
526 *(WORD *)(userClassBytes + index) = wNewVal;
527 //Note: NT4, SP6 does not set the last error to 0
528 SetLastError(ERROR_SUCCESS);
529 return(rc);
530 }
531 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
532 if(classNameA) {
533 dprintf2(("WARNING: setClassWord %s: %d %x -> wrong INDEX", classNameA, index, wNewVal));
534 }
535 else dprintf2(("WARNING: setClassWord %d: %d %x -> wrong INDEX", classAtom, index, wNewVal));
536 return 0;
537 }
538}
539//******************************************************************************
540//FIXME: Windows that still exists with this class
541//******************************************************************************
542BOOL Win32WndClass::UnregisterClassA(HINSTANCE hinst, LPSTR id)
543{
544 Win32WndClass *wndclass;
545
546 if(HIWORD(id)) {
547 dprintf(("Win32WndClass::UnregisterClassA class %s, instance %x!!", id, hinst));
548 }
549 else dprintf(("Win32WndClass::UnregisterClassA class %x, instance %x!!", id, hinst));
550
551 wndclass = FindClass(hinst, id);
552 if(wndclass) {
553 if(wndclass->GetWindowCount() != 0) {
554 dprintf2(("Win32WndClass::UnregisterClassA class %x still has windows!!", id));
555 SetLastError(ERROR_CLASS_HAS_WINDOWS);
556 return FALSE;
557 }
558 delete wndclass;
559 SetLastError(ERROR_SUCCESS);
560 return TRUE;
561 }
562 dprintf(("::UnregisterClass, couldn't find class %X!!\n", id));
563 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
564 return FALSE;
565}
566//******************************************************************************
567//******************************************************************************
568GenericObject *Win32WndClass::wndclasses = NULL;
Note: See TracBrowser for help on using the repository browser.