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

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

replaced strncpy with lstrcpynA

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