00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <os2win.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <stdarg.h>
00027 #include <assert.h>
00028 #include <misc.h>
00029 #include <win32class.h>
00030 #include <win32wnd.h>
00031 #include <win\winproc.h>
00032 #include <unicode.h>
00033
00034 #define DBG_LOCALLOG DBG_win32class
00035 #include "dbglocal.h"
00036
00037 static fDestroyAll = FALSE;
00038
00039
00040
00041
00042 Win32WndClass::Win32WndClass(WNDCLASSEXA *wndclass, BOOL fUnicode)
00043 : GenericObject(&wndclasses, &critsect)
00044 {
00045 isUnicode = fUnicode;
00046 processId = 0;
00047
00048 if(HIWORD(wndclass->lpszClassName)) {
00049 if(isUnicode) {
00050 INT len = lstrlenW((LPWSTR)wndclass->lpszClassName)+1;
00051
00052 classNameA = (PCHAR)_smalloc(len);
00053 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
00054 }
00055 else {
00056 INT len = strlen(wndclass->lpszClassName)+1;
00057
00058 classNameA = (PCHAR)_smalloc(len);
00059 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
00060 }
00061 if(classNameA == NULL || classNameW == NULL) {
00062 dprintf(("Win32Class ctr; classNameA/classNameW == NULL"));
00063 exit(1);
00064 }
00065 if(isUnicode) {
00066 lstrcpyW(classNameW, (LPWSTR)wndclass->lpszClassName);
00067 UnicodeToAscii(classNameW, classNameA);
00068 }
00069 else {
00070 strcpy((char *)classNameA, wndclass->lpszClassName);
00071 AsciiToUnicode(classNameA, classNameW);
00072 }
00073 classAtom = 0;
00074
00075
00076 if(wndclass->style & CS_GLOBALCLASS) {
00077 classAtom = GlobalFindAtomA(classNameA);
00078 }
00079 if(!classAtom) classAtom = GlobalAddAtomA(classNameA);
00080 }
00081 else {
00082 classNameA = NULL;
00083 classNameW = NULL;
00084 classAtom = (DWORD)wndclass->lpszClassName;
00085 }
00086 if(!(wndclass->style & CS_GLOBALCLASS)) {
00087 processId = GetCurrentProcessId();
00088 }
00089 menuNameA = 0;
00090 menuNameW = 0;
00091 setMenuName((LPSTR)wndclass->lpszMenuName);
00092
00093 dprintf(("USER32: Win32Class ctor\n"));
00094 dprintf(("USER32: wndclass->style %X\n", wndclass->style));
00095 dprintf(("USER32: wndclass->lpfnWndProc %X\n", wndclass->lpfnWndProc));
00096 dprintf(("USER32: wndclass->cbClsExtra %X\n", wndclass->cbClsExtra));
00097 dprintf(("USER32: wndclass->cbWndExtra %X\n", wndclass->cbWndExtra));
00098 dprintf(("USER32: wndclass->hInstance %X\n", wndclass->hInstance));
00099 dprintf(("USER32: wndclass->hIcon %X\n", wndclass->hIcon));
00100 dprintf(("USER32: wndclass->hCursor %X\n", wndclass->hCursor));
00101 dprintf(("USER32: wndclass->hbrBackground %X\n", wndclass->hbrBackground));
00102 if(HIWORD(wndclass->lpszClassName))
00103 dprintf(("USER32: wndclass->lpszClassName %s\n", classNameA));
00104 else dprintf(("USER32: wndclass->lpszClassName %X\n", wndclass->lpszClassName));
00105
00106 dprintf(("USER32: wndclass->classAtom %x", classAtom));
00107
00108 if(HIWORD(wndclass->lpszMenuName)) {
00109 dprintf(("USER32: lpszMenuName %s\n", menuNameA));
00110 }
00111 else dprintf(("USER32: wndclass->lpszMenuName %X\n", menuNameA));
00112 dprintf(("USER32: wndclass->hIconSm %X\n", wndclass->hIconSm));
00113
00114 nrExtraClassBytes = wndclass->cbClsExtra;
00115 nrExtraWindowBytes = wndclass->cbWndExtra;
00116 backgroundBrush = wndclass->hbrBackground;
00117 hCursor = wndclass->hCursor;
00118 hIcon = wndclass->hIcon;
00119 hInstance = wndclass->hInstance;
00120
00121 if(wndclass->style & CS_CLASSDC) {
00122 hdcClass = 0;
00123 }
00124 else hdcClass = 0;
00125
00126 windowStyle = wndclass->style;
00127
00128 windowProc = 0;
00129 WINPROC_SetProc((HWINDOWPROC *)&windowProc, wndclass->lpfnWndProc, (isUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS);
00130 dprintf2(("Window class ptr %x", windowProc));
00131
00132
00133 if(nrExtraClassBytes) {
00134 userClassBytes = (char *)_smalloc(nrExtraClassBytes);
00135 if(userClassBytes == NULL) {
00136 dprintf(("Win32Class ctr: userClassBytes == NULL!"));
00137 exit(1);
00138 }
00139 memset(userClassBytes, 0, nrExtraClassBytes);
00140 }
00141 else userClassBytes = NULL;
00142
00143 hIconSm = wndclass->hIconSm;
00144 }
00145
00146
00147 Win32WndClass::~Win32WndClass()
00148 {
00149 if(classNameA) {
00150 dprintf(("Win32WndClass dtor, destroy class %s\n", classNameA));
00151 }
00152
00153
00154 if(classNameA && !(windowStyle & CS_GLOBALCLASS)) {
00155 GlobalDeleteAtom(classAtom);
00156 }
00157
00158 WINPROC_FreeProc(windowProc, WIN_PROC_CLASS);
00159
00160 if(userClassBytes) free(userClassBytes);
00161 if(classNameA) free(classNameA);
00162 if(classNameW) free(classNameW);
00163 if(menuNameA && HIWORD(menuNameA)) {
00164 free(menuNameA);
00165 assert(menuNameW);
00166 free(menuNameW);
00167 }
00168 }
00169
00170
00171 void Win32WndClass::DestroyAll()
00172 {
00173 fDestroyAll = TRUE;
00174 GenericObject::DestroyAll(wndclasses);
00175 }
00176
00177
00178 BOOL Win32WndClass::hasClassName(LPSTR classname, BOOL fUnicode)
00179 {
00180 if(HIWORD(classname) == 0) {
00181 return classAtom == (DWORD)classname;
00182 }
00183 if(fUnicode) {
00184 if(classNameW)
00185 return (lstrcmpW(classNameW, (LPWSTR)classname) == 0);
00186 return FALSE;
00187 }
00188 else {
00189 if(classNameA)
00190 return (strcmp(classNameA, classname) == 0);
00191 return FALSE;
00192 }
00193 }
00194
00195
00196
00197
00198 Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPSTR id)
00199 {
00200 lock(&critsect);
00201
00202 Win32WndClass *wndclass = (Win32WndClass *)wndclasses;
00203
00204 if(wndclass == NULL) {
00205 unlock(&critsect);
00206 return(NULL);
00207 }
00208
00209 if(HIWORD(id) != 0) {
00210
00211 if(lstrcmpiA(wndclass->classNameA, id) == 0 && wndclass->hInstance == hInstance) {
00212 wndclass->addRef();
00213 unlock(&critsect);
00214 return(wndclass);
00215 }
00216 else {
00217 wndclass = (Win32WndClass *)wndclass->GetNext();
00218 while(wndclass != NULL) {
00219 if(lstrcmpiA(wndclass->classNameA, id) == 0)
00220 {
00221
00222 if(hInstance == NULL || GetModuleHandleA(NULL) == hInstance ||
00223 wndclass->hInstance == hInstance)
00224 {
00225 wndclass->addRef();
00226 unlock(&critsect);
00227 return(wndclass);
00228 }
00229 }
00230 wndclass = (Win32WndClass *)wndclass->GetNext();
00231 }
00232 }
00233 }
00234 else {
00235
00236
00237 if(wndclass->classAtom == (DWORD)id ) {
00238 wndclass->addRef();
00239 unlock(&critsect);
00240 return(wndclass);
00241 }
00242 else {
00243 wndclass = (Win32WndClass *)wndclass->GetNext();
00244 while(wndclass != NULL) {
00245 if(wndclass->classAtom == (DWORD)id ) {
00246 wndclass->addRef();
00247 unlock(&critsect);
00248 return(wndclass);
00249 }
00250 wndclass = (Win32WndClass *)wndclass->GetNext();
00251 }
00252 }
00253 }
00254 unlock(&critsect);
00255 dprintf(("Class %X (inst %X) not found!", id, hInstance));
00256 return(NULL);
00257 }
00258
00259
00260
00261
00262 Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPWSTR id)
00263 {
00264 LPSTR lpszClassName;
00265 Win32WndClass *winclass;
00266
00267 if(HIWORD(id)) {
00268 lpszClassName = UnicodeToAsciiString((LPWSTR)id);
00269 }
00270 else lpszClassName = (LPSTR)id;
00271
00272 winclass = FindClass(hInstance, lpszClassName);
00273
00274 if(HIWORD(id)) {
00275 FreeAsciiString((char *)lpszClassName);
00276 }
00277 return winclass;
00278 }
00279
00280
00281
00282
00283
00284 BOOL Win32WndClass::isAppClass(ULONG curProcessId)
00285 {
00286 if(windowStyle & CS_GLOBALCLASS)
00287 return TRUE;
00288
00289 return curProcessId = processId;
00290 }
00291
00292
00293 BOOL Win32WndClass::getClassInfo(WNDCLASSEXA *wndclass)
00294 {
00295 wndclass->cbClsExtra = nrExtraClassBytes;
00296 wndclass->cbWndExtra = nrExtraWindowBytes;
00297 wndclass->hbrBackground = backgroundBrush;
00298 wndclass->hCursor = hCursor;
00299 wndclass->hIcon = hIcon;
00300 wndclass->hInstance = hInstance;
00301 wndclass->lpszMenuName = (LPCTSTR)menuNameA;
00302 wndclass->lpszClassName = (classNameA) ? (LPCTSTR)classNameA : (LPCTSTR)classAtom;
00303 wndclass->style = windowStyle;
00304 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, FALSE);
00305 wndclass->hIconSm = hIconSm;
00306 return(TRUE);
00307 }
00308
00309
00310 BOOL Win32WndClass::getClassInfo(WNDCLASSEXW *wndclass)
00311 {
00312 wndclass->cbClsExtra = nrExtraClassBytes;
00313 wndclass->cbWndExtra = nrExtraWindowBytes;
00314 wndclass->hbrBackground = backgroundBrush;
00315 wndclass->hCursor = hCursor;
00316 wndclass->hIcon = hIcon;
00317 wndclass->hInstance = hInstance;
00318 wndclass->lpszMenuName = (LPCWSTR)menuNameW;
00319 wndclass->lpszClassName = (classNameW) ? (LPCWSTR)classNameW : (LPCWSTR)classAtom;
00320 wndclass->style = windowStyle;
00321 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, TRUE);
00322 wndclass->hIconSm = hIconSm;
00323 return(TRUE);
00324 }
00325
00326
00327 ULONG Win32WndClass::getClassName(LPSTR lpszClassName, ULONG cchClassName)
00328 {
00329 if(HIWORD(classNameA)) {
00330 lstrcpynA(lpszClassName, classNameA, cchClassName-1);
00331 return strlen(lpszClassName);
00332 }
00333 *(ULONG *)lpszClassName = classAtom;
00334 return(sizeof(ULONG));
00335 }
00336
00337
00338 ULONG Win32WndClass::getClassName(LPWSTR lpszClassName, ULONG cchClassName)
00339 {
00340 ULONG len;
00341
00342 if(HIWORD(classNameW)) {
00343 lstrcpynW(lpszClassName, classNameW, cchClassName-1);
00344 return lstrlenW(lpszClassName);
00345 }
00346 *(ULONG *)lpszClassName = classAtom;
00347 return(sizeof(ULONG));
00348 }
00349
00350
00351 void Win32WndClass::setMenuName(LPSTR newMenuName)
00352 {
00353 if(HIWORD(menuNameA)) {
00354 free(menuNameA);
00355 free(menuNameW);
00356 menuNameA = 0;
00357 menuNameW = 0;
00358 }
00359 if(HIWORD(newMenuName)) {
00360 if(isUnicode) {
00361 menuNameA = (PCHAR)_smalloc(lstrlenW((LPWSTR)newMenuName)+1);
00362 menuNameW = (WCHAR *)_smalloc((lstrlenW((LPWSTR)newMenuName)+1)*sizeof(WCHAR));
00363 }
00364 else {
00365 menuNameA = (PCHAR)_smalloc(strlen(newMenuName)+1);
00366 menuNameW = (WCHAR *)_smalloc((strlen(newMenuName)+1)*sizeof(WCHAR));
00367 }
00368 if(menuNameA == NULL || menuNameW == NULL) {
00369 dprintf(("Win32Class ctr; menuName/menuNameW == NULL"));
00370 exit(1);
00371 }
00372 if(isUnicode) {
00373 lstrcpyW(menuNameW, (LPWSTR)newMenuName);
00374 UnicodeToAscii(menuNameW, menuNameA);
00375 }
00376 else {
00377 strcpy((char *)menuNameA, newMenuName);
00378 AsciiToUnicode(menuNameA, menuNameW);
00379 }
00380
00381 }
00382 else {
00383 menuNameA = (PCHAR)newMenuName;
00384 menuNameW = (WCHAR *)newMenuName;
00385 }
00386 }
00387
00388
00389 ULONG Win32WndClass::getClassLongA(int index, BOOL fUnicode)
00390 {
00391 switch(index) {
00392 case GCL_CBCLSEXTRA:
00393 return nrExtraClassBytes;
00394 case GCL_CBWNDEXTRA:
00395 return nrExtraWindowBytes;
00396 case GCL_HBRBACKGROUND:
00397 return backgroundBrush;
00398 case GCL_HCURSOR:
00399 return hCursor;
00400 case GCL_HICON:
00401 return hIcon;
00402 case GCL_HICONSM:
00403 return hIconSm;
00404 case GCL_HMODULE:
00405 return hInstance;
00406 case GCL_MENUNAME:
00407 return (isUnicode) ? (ULONG)menuNameW : (ULONG)menuNameA;
00408 case GCL_STYLE:
00409 return windowStyle;
00410 case GCL_WNDPROC:
00411 return (ULONG) WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
00412 case GCW_ATOM:
00413 SetLastError(ERROR_INVALID_PARAMETER);
00414 return 0;
00415 default:
00416 if(index >= 0 && index + sizeof(ULONG) <= nrExtraClassBytes) {
00417
00418 SetLastError(ERROR_SUCCESS);
00419 return *(ULONG *)(userClassBytes + index);
00420 }
00421 if(classNameA) {
00422 dprintf2(("WARNING: getClassLong %s: %d -> wrong INDEX", classNameA, index));
00423 }
00424 else dprintf2(("WARNING: getClassLong %d: %d -> wrong INDEX", classAtom, index));
00425 SetLastError(ERROR_INVALID_INDEX);
00426 return 0;
00427 }
00428 }
00429
00430
00431 WORD Win32WndClass::getClassWord(int index)
00432 {
00433 switch(index) {
00434 case GCW_ATOM:
00435 return (WORD)classAtom;
00436 default:
00437 if(index >= 0 && index + sizeof(WORD) <= nrExtraClassBytes) {
00438
00439 SetLastError(ERROR_SUCCESS);
00440 return *(WORD *)(userClassBytes + index);
00441 }
00442 if(classNameA) {
00443 dprintf2(("WARNING: getClassWord %s: %d -> wrong INDEX", classNameA, index));
00444 }
00445 else dprintf2(("WARNING: getClassWord %d: %d -> wrong INDEX", classAtom, index));
00446 SetLastError(ERROR_INVALID_INDEX);
00447 return 0;
00448 }
00449 }
00450
00451
00452
00453 ULONG Win32WndClass::setClassLongA(int index, LONG lNewVal, BOOL fUnicode)
00454 {
00455 ULONG rc;
00456
00457 switch(index) {
00458 case GCL_CBCLSEXTRA:
00459 rc = nrExtraClassBytes;
00460
00461 break;
00462 case GCL_CBWNDEXTRA:
00463 rc = nrExtraWindowBytes;
00464 nrExtraWindowBytes = lNewVal;
00465 break;
00466 case GCL_HBRBACKGROUND:
00467 rc = backgroundBrush;
00468 backgroundBrush = lNewVal;
00469 break;
00470 case GCL_HCURSOR:
00471 rc = hCursor;
00472 hCursor = lNewVal;
00473 break;
00474 case GCL_HICON:
00475 rc = hIcon;
00476 hIcon = lNewVal;
00477 break;
00478 case GCL_HICONSM:
00479 rc = hIconSm;
00480 hIconSm = lNewVal;
00481 break;
00482 case GCL_HMODULE:
00483 rc = hInstance;
00484 hInstance = lNewVal;
00485 break;
00486 case GCL_MENUNAME:
00487 rc = 0;
00488 setMenuName((LPSTR)lNewVal);
00489 break;
00490 case GCL_STYLE:
00491 rc = windowStyle;
00492 windowStyle = lNewVal;
00493 break;
00494 case GCL_WNDPROC:
00495
00496
00497
00498
00499
00500 rc = (LONG)WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A );
00501 WINPROC_SetProc((HWINDOWPROC *)&windowProc, (WNDPROC)lNewVal, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS );
00502 break;
00503 case GCW_ATOM:
00504 SetLastError(ERROR_INVALID_PARAMETER);
00505 return 0;
00506 default:
00507 if(index >= 0 && index + sizeof(ULONG) <= nrExtraClassBytes) {
00508 rc = *(ULONG *)(userClassBytes + index);
00509 *(ULONG *)(userClassBytes + index) = lNewVal;
00510 break;
00511 }
00512 SetLastError(ERROR_INVALID_INDEX);
00513 if(classNameA) {
00514 dprintf2(("WARNING: Win32WndClass::setClassLongA %s: %d %x -> wrong INDEX", classNameA, index, lNewVal));
00515 }
00516 else dprintf2(("WARNING: Win32WndClass::setClassLongA %d: %d %x -> wrong INDEX", classAtom, index, lNewVal));
00517 return 0;
00518 }
00519 SetLastError(ERROR_SUCCESS);
00520 if(classNameA) {
00521 dprintf2(("Win32WndClass::setClassLongA %s: %d %x returned %x", classNameA, index, lNewVal, rc));
00522 }
00523 else dprintf2(("Win32WndClass::setClassLongA %d: %d %x returned %x", classAtom, index, lNewVal, rc));
00524 return(rc);
00525 }
00526
00527
00528 WORD Win32WndClass::setClassWord(int index, WORD wNewVal)
00529 {
00530 WORD rc;
00531
00532 switch(index) {
00533 case GCW_ATOM:
00534 rc = (WORD)classAtom;
00535 classAtom = wNewVal;
00536 return(rc);
00537 default:
00538 if(index >= 0 && index + sizeof(WORD) <= nrExtraClassBytes) {
00539 rc = *(WORD *)(userClassBytes + index);
00540 *(WORD *)(userClassBytes + index) = wNewVal;
00541
00542 SetLastError(ERROR_SUCCESS);
00543 return(rc);
00544 }
00545 SetLastError(ERROR_INVALID_INDEX);
00546 if(classNameA) {
00547 dprintf2(("WARNING: setClassWord %s: %d %x -> wrong INDEX", classNameA, index, wNewVal));
00548 }
00549 else dprintf2(("WARNING: setClassWord %d: %d %x -> wrong INDEX", classAtom, index, wNewVal));
00550 return 0;
00551 }
00552 }
00553
00554
00555
00556 BOOL Win32WndClass::UnregisterClassA(HINSTANCE hinst, LPSTR id)
00557 {
00558 Win32WndClass *wndclass;
00559
00560 if(HIWORD(id)) {
00561 dprintf(("Win32WndClass::UnregisterClassA class %s, instance %x!!", id, hinst));
00562 }
00563 else dprintf(("Win32WndClass::UnregisterClassA class %x, instance %x!!", id, hinst));
00564
00565 wndclass = FindClass(hinst, id);
00566 if(wndclass) {
00567 if(wndclass->getRefCount() != 1) {
00568 wndclass->markDeleted();
00569 RELEASE_CLASSOBJ(wndclass);
00570 dprintf2(("Win32WndClass::UnregisterClassA class %x still has windows!!", id));
00571 SetLastError(ERROR_CLASS_HAS_WINDOWS);
00572 return FALSE;
00573 }
00574 wndclass->markDeleted();
00575 RELEASE_CLASSOBJ(wndclass);
00576
00577 SetLastError(ERROR_SUCCESS);
00578 return TRUE;
00579 }
00580 dprintf(("::UnregisterClass, couldn't find class %X!!\n", id));
00581 SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
00582 return FALSE;
00583 }
00584
00585
00586 GenericObject *Win32WndClass::wndclasses = NULL;
00587 CRITICAL_SECTION Win32WndClass::critsect = {0};