Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

class.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: class.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains RegisterClass and the related window class management 00007 * functions. 00008 * 00009 * History: 00010 * 10-16-90 DarrinM Ported functions from Win 3.0 sources. 00011 * 02-01-91 mikeke Added Revalidation code (None) 00012 * 04-08-91 DarrinM C-S-ized and removed global/public class support. 00013 \***************************************************************************/ 00014 00015 #include "precomp.h" 00016 #pragma hdrstop 00017 00018 /* 00019 * These arrays are used by Get/SetClassWord/Long. 00020 */ 00021 00022 // !!! can't we get rid of this and just special case GCW_ATOM 00023 00024 CONST BYTE afClassDWord[] = { 00025 FIELD_SIZE(CLS, spicnSm), // GCL_HICONSM (-34) 00026 0, 00027 FIELD_SIZE(CLS, atomClassName), // GCW_ATOM (-32) 00028 0, 00029 0, 00030 0, 00031 0, 00032 0, 00033 FIELD_SIZE(CLS, style), // GCL_STYLE (-26) 00034 0, 00035 FIELD_SIZE(CLS, lpfnWndProc), // GCL_WNDPROC (-24) 00036 0, 00037 0, 00038 0, 00039 FIELD_SIZE(CLS, cbclsExtra), // GCL_CBCLSEXTRA (-20) 00040 0, 00041 FIELD_SIZE(CLS, cbwndExtra), // GCL_CBWNDEXTRA (-18) 00042 0, 00043 FIELD_SIZE(CLS, hModule), // GCL_HMODULE (-16) 00044 0, 00045 FIELD_SIZE(CLS, spicn), // GCL_HICON (-14) 00046 0, 00047 FIELD_SIZE(CLS, spcur), // GCL_HCURSOR (-12) 00048 0, 00049 FIELD_SIZE(CLS, hbrBackground), // GCL_HBRBACKGROUND (-10) 00050 0, 00051 FIELD_SIZE(CLS, lpszMenuName) // GCL_HMENUNAME (-8) 00052 }; 00053 00054 CONST BYTE aiClassOffset[] = { 00055 FIELD_OFFSET(CLS, spicnSm), // GCL_HICONSM 00056 0, 00057 FIELD_OFFSET(CLS, atomClassName), // GCW_ATOM 00058 0, 00059 0, 00060 0, 00061 0, 00062 0, 00063 FIELD_OFFSET(CLS, style), // GCL_STYLE 00064 0, 00065 FIELD_OFFSET(CLS, lpfnWndProc), // GCL_WNDPROC 00066 0, 00067 0, 00068 0, 00069 FIELD_OFFSET(CLS, cbclsExtra), // GCL_CBCLSEXTRA 00070 0, 00071 FIELD_OFFSET(CLS, cbwndExtra), // GCL_CBWNDEXTRA 00072 0, 00073 FIELD_OFFSET(CLS, hModule), // GCL_HMODULE 00074 0, 00075 FIELD_OFFSET(CLS, spicn), // GCL_HICON 00076 0, 00077 FIELD_OFFSET(CLS, spcur), // GCL_HCURSOR 00078 0, 00079 FIELD_OFFSET(CLS, hbrBackground), // GCL_HBRBACKGROUND 00080 0, 00081 FIELD_OFFSET(CLS, lpszMenuName) // GCL_MENUNAME 00082 }; 00083 00084 /* 00085 * INDEX_OFFSET must refer to the first entry of afClassDWord[] 00086 */ 00087 #define INDEX_OFFSET GCLP_HICONSM 00088 00089 /***************************************************************************\ 00090 * _RegisterClass (API) 00091 * 00092 * This stub calls InternalRegisterClass to do its work and then does some 00093 * additional work to save a pointer to the client-side menu name string. 00094 * The menu string is returned by _GetClassInfo so the client can fix up 00095 * a valid entry for the WNDCLASS lpszMenuName field. 00096 * 00097 * History: 00098 * 04-26-91 DarrinM Created. 00099 \***************************************************************************/ 00100 00101 ATOM xxxRegisterClassEx( 00102 LPWNDCLASSEX cczpwc, 00103 PCLSMENUNAME pcmn, 00104 WORD fnid, 00105 DWORD dwFlags, 00106 LPDWORD pdwWOW ) 00107 { 00108 PCLS pcls; 00109 PTHREADINFO ptiCurrent = PtiCurrent(); 00110 00111 /* 00112 * NOTE -- lpszClassName and lpszMenuName in the wndclass may be client-side 00113 * pointers. Use of those fields must be protected in try blocks. 00114 */ 00115 00116 /* 00117 * Convert a possible CallProc Handle into a real address. They may 00118 * have kept the CallProc Handle from some previous mixed GetClassinfo 00119 * or SetWindowLong. 00120 */ 00121 if (ISCPDTAG(cczpwc->lpfnWndProc)) { 00122 PCALLPROCDATA pCPD; 00123 if (pCPD = HMValidateHandleNoRip((HANDLE)cczpwc->lpfnWndProc, TYPE_CALLPROC)) { 00124 cczpwc->lpfnWndProc = (WNDPROC)pCPD->pfnClientPrevious; 00125 } 00126 } 00127 00128 pcls = InternalRegisterClassEx(cczpwc, fnid, dwFlags | ((ptiCurrent->TIF_flags & TIF_16BIT)? CSF_WOWCLASS : 0) ); 00129 if (pcls != NULL) { 00130 00131 pcls->lpszClientUnicodeMenuName = pcmn->pwszClientUnicodeMenuName; 00132 pcls->lpszClientAnsiMenuName = pcmn->pszClientAnsiMenuName; 00133 00134 /* 00135 * copy 5 WOW dwords. 00136 */ 00137 if (pdwWOW) { 00138 RtlCopyMemory (PWCFromPCLS(pcls), pdwWOW, sizeof(WC)); 00139 } 00140 00141 if ((ptiCurrent->TIF_flags & TIF_16BIT) && ptiCurrent->ptdb) { 00142 pcls->hTaskWow = ptiCurrent->ptdb->hTaskWow; 00143 } else { 00144 pcls->hTaskWow = 0; 00145 } 00146 00147 /* 00148 * For some (presumably good) reason Win 3.1 changed RegisterClass 00149 * to return the classes classname atom. 00150 */ 00151 return pcls->atomClassName; 00152 } else { 00153 return 0; 00154 } 00155 } 00156 00157 00158 /***************************************************************************\ 00159 * ClassAlloc 00160 * ClassFree 00161 * 00162 * Generic allocation routines that discriminate between desktop heap 00163 * and pool. 00164 * 00165 * History: 00166 * 08-07-95 JimA Created 00167 \***************************************************************************/ 00168 00169 PVOID ClassAlloc( 00170 PDESKTOP pdesk, 00171 DWORD cbAlloc) 00172 { 00173 PVOID pvalloc; 00174 00175 if (pdesk) 00176 /* 00177 * Later5.0 GerardoB. Make this allocation directly to avoid 00178 * DesktopAlloc from failing it when the desktop is destroyed. 00179 * When destroying a locked window, we might need to clone the 00180 * zombie class which requires an allocation on the wnd's desktop. 00181 * We need to make sure that the client side doesn't get to the 00182 * class of a zombie window; then we won't need to make the heap 00183 * allocation; or is there any other reason for that allocation? 00184 */ 00185 pvalloc = (PCLS)DesktopAllocAlways(pdesk, cbAlloc, DTAG_CLASS); 00186 else { 00187 pvalloc = (PCLS)UserAllocPoolWithQuotaZInit(cbAlloc, TAG_CLASS); 00188 } 00189 00190 return pvalloc; 00191 } 00192 00193 VOID ClassFree( 00194 PDESKTOP pdesk, 00195 PVOID pvfree) 00196 { 00197 if (pdesk != NULL) 00198 DesktopFree(pdesk, pvfree); 00199 else 00200 UserFreePool(pvfree); 00201 } 00202 00203 /***************************************************************************\ 00204 * ValidateAndLockCursor 00205 * 00206 * Win95 comaptible validation 00207 * 00208 * History: 00209 * 12-19-95 GerardoB Created 00210 \***************************************************************************/ 00211 BOOL ValidateAndLockCursor (PCURSOR * ppcursor, BOOL fIs40Compat) 00212 { 00213 PCURSOR pcur; 00214 00215 if (*ppcursor == NULL) { 00216 return TRUE; 00217 } 00218 00219 pcur = HMValidateHandleNoSecure(*ppcursor, TYPE_CURSOR); 00220 if (pcur == NULL) { 00221 RIPMSG1(RIP_WARNING, "ValidateAndLockCursor: Invalid Cursor or Icon:%#p", *ppcursor); 00222 if (fIs40Compat) { 00223 RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "RegisterClass: Invalid Parameter"); 00224 return FALSE; 00225 } 00226 } 00227 00228 *ppcursor = NULL; 00229 Lock(ppcursor, pcur); 00230 return TRUE; 00231 } 00232 /***************************************************************************\ 00233 * InternalRegisterClass 00234 * 00235 * This API is called by applications or the system to register private or 00236 * global (public) window classes. If a class with the same name already 00237 * exists the call will fail, except in the special case where an application 00238 * registers a private class with the same name as a global class. In this 00239 * case the private class supercedes the global class for that application. 00240 * 00241 * History: 00242 * 10-15-90 DarrinM Ported from Win 3.0 sources. 00243 \***************************************************************************/ 00244 PCLS InternalRegisterClassEx( 00245 LPWNDCLASSEX cczlpwndcls, 00246 WORD fnid, 00247 DWORD CSF_flags 00248 ) 00249 { 00250 BOOL fIs40Compat; 00251 ULONG_PTR dwT; 00252 PCLS pcls; 00253 LPWSTR pszT1; 00254 ATOM atomT; 00255 PTHREADINFO ptiCurrent; 00256 HANDLE hModule; 00257 PDESKTOP pdesk; 00258 ULONG cch; 00259 UNICODE_STRING UString; 00260 ANSI_STRING AString; 00261 00262 /* 00263 * NOTE -- lpszClassName and lpszMenuName in the wndclass may be client-side 00264 * pointers. Use of those fields must be protected in try blocks. 00265 */ 00266 CheckCritIn(); 00267 00268 ptiCurrent = PtiCurrent(); 00269 00270 /* 00271 * Don't allow 4.0 apps to register a class using hModuleWin 00272 * LATER GerardoB: Our client side classes use hmodUser (USER32) while 00273 * our server side classes use hWinInstance (WIN32K). We should change 00274 * CreateThreadInfo and LW_RegisterWindows so all classes use hModUser. 00275 */ 00276 hModule = cczlpwndcls->hInstance; 00277 if (!(CSF_flags & (CSF_SYSTEMCLASS | CSF_SERVERSIDEPROC)) 00278 && (hModule == hModuleWin) 00279 && (LOWORD(ptiCurrent->dwExpWinVer) >= VER40)) { 00280 00281 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "InternalRegisterClassEx: Invalid hInstance (Cannot use system's hInstance)"); 00282 return NULL; 00283 } 00284 00285 00286 /* 00287 * As of NT 4.0 we no longer honor CS_BYTEALIGNCLIENT or CS_BYTEALIGNWINDOW 00288 */ 00289 if (cczlpwndcls->style & (CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW)) { 00290 RIPMSG0(RIP_VERBOSE, "CS_BYTEALIGNCLIENT and CS_BYTEALIGNWINDOW styles no longer honored."); 00291 } 00292 00293 /* 00294 * Does this class exist as a private class? If so, fail. 00295 */ 00296 atomT = FindClassAtom(cczlpwndcls->lpszClassName); 00297 00298 if (atomT != 0 && !(CSF_flags & CSF_SERVERSIDEPROC)) { 00299 /* 00300 * First check private classes. If already exists, return error. 00301 */ 00302 if (_InnerGetClassPtr(atomT, &ptiCurrent->ppi->pclsPrivateList, 00303 hModule) != NULL) { 00304 RIPERR1(ERROR_CLASS_ALREADY_EXISTS, RIP_VERBOSE, "RegisterClass: Class already exists %lx", (DWORD)atomT); 00305 return NULL; 00306 } 00307 00308 /* 00309 * Now only check public classes if CS_GLOBALCLASS is set. If it 00310 * isn't set, then this will allow an application to re-register 00311 * a private class to take precedence over a public class. 00312 */ 00313 if (cczlpwndcls->style & CS_GLOBALCLASS) { 00314 if (_InnerGetClassPtr(atomT, &ptiCurrent->ppi->pclsPublicList, NULL) != NULL) { 00315 RIPERR0(ERROR_CLASS_ALREADY_EXISTS, RIP_VERBOSE, "RegisterClass: Global Class already exists"); 00316 return NULL; 00317 } 00318 } 00319 } 00320 00321 /* 00322 * Alloc space for the class. 00323 */ 00324 if (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD) { 00325 pdesk = NULL; 00326 } else { 00327 pdesk = ptiCurrent->rpdesk; 00328 } 00329 pcls = (PCLS)ClassAlloc(pdesk, sizeof(CLS) + cczlpwndcls->cbClsExtra + (CSF_flags & CSF_WOWCLASS ? sizeof(WC):0)); 00330 if (pcls == NULL) { 00331 return NULL; 00332 } 00333 00334 LockDesktop(&pcls->rpdeskParent, pdesk, LDL_CLS_DESKPARENT1, (ULONG_PTR)pcls); 00335 pcls->pclsBase = pcls; 00336 00337 /* 00338 * Copy over the shared part of the class structure. 00339 */ 00340 UserAssert(FIELD_OFFSET(WNDCLASSEX, style) == FIELD_OFFSET(COMMON_WNDCLASS, style)); 00341 RtlCopyMemory(&pcls->style, &(cczlpwndcls->style), 00342 sizeof(COMMON_WNDCLASS) - FIELD_OFFSET(COMMON_WNDCLASS, style)); 00343 00344 /* 00345 * Copy CSF_SERVERSIDEPROC, CSF_ANSIPROC (etc.) flags 00346 */ 00347 pcls->CSF_flags = LOWORD(CSF_flags); 00348 pcls->fnid = fnid; 00349 if (fnid) { 00350 CBFNID(fnid) = (WORD)(pcls->cbwndExtra + sizeof(WND)); 00351 00352 if (!(pcls->CSF_flags & CSF_SERVERSIDEPROC) && ptiCurrent->pClientInfo != NULL) { 00353 /* 00354 * Clear the bit so new threads in this process 00355 * won't bother to reregister the client-side USER classes. 00356 */ 00357 ptiCurrent->pClientInfo->CI_flags &= ~CI_REGISTERCLASSES; 00358 } 00359 } 00360 00361 /* 00362 * If this wndproc happens to be a client wndproc stub for a server 00363 * wndproc, then remember the server wndproc! This should be rare: why 00364 * would an application re-register a class that isn't "subclassed"? 00365 */ 00366 if (!(pcls->CSF_flags & CSF_SERVERSIDEPROC)) { 00367 dwT = MapClientToServerPfn((ULONG_PTR)pcls->lpfnWndProc); 00368 if (dwT != 0) { 00369 pcls->CSF_flags |= CSF_SERVERSIDEPROC; 00370 pcls->CSF_flags &= ~CSF_ANSIPROC; 00371 pcls->lpfnWndProc = (WNDPROC_PWND)dwT; 00372 } 00373 } 00374 00375 /* 00376 * Win95 compatible validation. 00377 * 00378 * hbrBackground was validated by GDI in the client side 00379 * NULL hInstances are mapped to GetModuleHandle(NULL) in the client 00380 * side 00381 */ 00382 00383 fIs40Compat = (CSF_flags & CSF_WIN40COMPAT) != 0; 00384 00385 if (!ValidateAndLockCursor(&pcls->spcur, fIs40Compat)) { 00386 goto ValidateError1; 00387 } 00388 00389 if (!ValidateAndLockCursor(&pcls->spicn, fIs40Compat)) { 00390 goto ValidateError2; 00391 } 00392 00393 if (!ValidateAndLockCursor(&pcls->spicnSm, fIs40Compat)) { 00394 goto ValidateError3; 00395 } 00396 00397 /* 00398 * Add the class name to the atom table. 00399 */ 00400 00401 if (IS_PTR(cczlpwndcls->lpszClassName)) 00402 atomT = UserAddAtom(cczlpwndcls->lpszClassName, FALSE); 00403 else 00404 atomT = PTR_TO_ID(cczlpwndcls->lpszClassName); 00405 00406 if (atomT == 0) { 00407 goto AtomError; 00408 } 00409 pcls->atomClassName = atomT; 00410 00411 /* 00412 * Make an ANSI version of the class name to optimize 00413 * GetClassNameA for WOW. 00414 */ 00415 if (IS_PTR(cczlpwndcls->lpszClassName)) { 00416 try { 00417 RtlInitUnicodeString(&UString, cczlpwndcls->lpszClassName); 00418 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00419 goto MemError2; 00420 } 00421 #ifdef FE_SB // InternalRegisterClassEx() 00422 cch = UString.Length + 1; 00423 #else 00424 cch = UString.Length / sizeof(WCHAR) + 1; 00425 #endif // FE_SB 00426 } else { 00427 cch = 7; // 1 char for '#', 5 for '65536'. 00428 } 00429 00430 /* 00431 * Allocate the ANSI name buffer and convert the unicode name 00432 * to ANSI. 00433 */ 00434 pcls->lpszAnsiClassName = (LPSTR)ClassAlloc(pdesk, cch); 00435 if (pcls->lpszAnsiClassName == NULL) { 00436 goto MemError2; 00437 } 00438 00439 /* 00440 * Form the ANSI class name. 00441 */ 00442 if (IS_PTR(cczlpwndcls->lpszClassName)) { 00443 00444 /* 00445 * Class name is a string. 00446 */ 00447 AString.Length = 0; 00448 AString.MaximumLength = (USHORT)cch; 00449 AString.Buffer = pcls->lpszAnsiClassName; 00450 try { 00451 RtlUnicodeStringToAnsiString(&AString, &UString, FALSE); 00452 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00453 goto MemError3; 00454 } 00455 } else { 00456 00457 /* 00458 * Class name is an integer atom. 00459 */ 00460 pcls->lpszAnsiClassName[0] = L'#'; 00461 RtlIntegerToChar(PTR_TO_ID(cczlpwndcls->lpszClassName), 10, cch - 1, 00462 &pcls->lpszAnsiClassName[1]); 00463 } 00464 00465 /* 00466 * Make local copy of menu name. 00467 */ 00468 pszT1 = pcls->lpszMenuName; 00469 00470 if (pszT1 != NULL) { 00471 if (IS_PTR(pszT1)) { 00472 try { 00473 RtlInitUnicodeString(&UString, pszT1); 00474 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00475 goto MemError3; 00476 } 00477 if (UString.Length == 0) { 00478 00479 /* 00480 * app passed an empty string for the name 00481 */ 00482 pcls->lpszMenuName = NULL; 00483 } else { 00484 UNICODE_STRING strMenuName; 00485 00486 /* 00487 * Alloc space for the Menu Name. 00488 */ 00489 if (!AllocateUnicodeString(&strMenuName, &UString)) { 00490 MemError3: 00491 ClassFree(pdesk, pcls->lpszAnsiClassName); 00492 MemError2: 00493 UserDeleteAtom(pcls->atomClassName); 00494 AtomError: 00495 Unlock(&pcls->spicnSm); 00496 ValidateError3: 00497 Unlock(&pcls->spicn); 00498 ValidateError2: 00499 Unlock(&pcls->spcur); 00500 ValidateError1: 00501 UnlockDesktop(&pcls->rpdeskParent, LDU_CLS_DESKPARENT1, (ULONG_PTR)pcls); 00502 ClassFree(pdesk, pcls); 00503 return NULL; 00504 } 00505 00506 pcls->lpszMenuName = strMenuName.Buffer; 00507 } 00508 } 00509 } 00510 00511 if ((CSF_flags & CSF_SERVERSIDEPROC) || (pcls->style & CS_GLOBALCLASS)) { 00512 if (pcls->CSF_flags & CSF_SYSTEMCLASS) { 00513 pcls->pclsNext = gpclsList; 00514 gpclsList = pcls; 00515 } else { 00516 pcls->pclsNext = ptiCurrent->ppi->pclsPublicList; 00517 ptiCurrent->ppi->pclsPublicList = pcls; 00518 } 00519 } else { 00520 pcls->pclsNext = ptiCurrent->ppi->pclsPrivateList; 00521 ptiCurrent->ppi->pclsPrivateList = pcls; 00522 } 00523 00524 /* 00525 * Because Memory is allocated with ZEROINIT, the pcls->cWndReferenceCount 00526 * field is automatically initialised to zero. 00527 */ 00528 00529 return pcls; 00530 } 00531 00532 00533 /***************************************************************************\ 00534 * _UnregisterClass (API) 00535 * 00536 * This API function is used to unregister a window class previously 00537 * registered by the Application. 00538 * 00539 * Returns: 00540 * TRUE if successful. 00541 * FALSE otherwise. 00542 * 00543 * NOTE: 00544 * 1. The class name must have been registered earlier by this client 00545 * through RegisterClass(). 00546 * 2. The class name should not be one of the predefined control classes. 00547 * 3. All windows created with this class must be destroyed before calling 00548 * this function. 00549 * 00550 * History: 00551 * 10-15-90 DarrinM Ported from Win 3.0 sources. 00552 * 03-09-94 BradG Fixed bug when ATOM was passed in 00553 \***************************************************************************/ 00554 00555 BOOL _UnregisterClass( 00556 LPCWSTR ccxlpszClassName, 00557 HANDLE hModule, 00558 PCLSMENUNAME pcmn) 00559 { 00560 ATOM atomT; 00561 PPCLS ppcls; 00562 PTHREADINFO ptiCurrent; 00563 00564 CheckCritIn(); 00565 00566 ptiCurrent = PtiCurrent(); 00567 00568 /* 00569 * Check whether the given ClassName is already registered by the 00570 * Application with the given handle. 00571 * Return error, if either the Class does not exist or it does not 00572 * belong to the calling process. 00573 */ 00574 00575 /* 00576 * bradg (3/9/95) - Must first check to see if an ATOM has been passed 00577 */ 00578 atomT = FindClassAtom(ccxlpszClassName); 00579 00580 ppcls = _InnerGetClassPtr(atomT, &ptiCurrent->ppi->pclsPrivateList, hModule); 00581 if (ppcls == NULL) { 00582 /* 00583 * Maybe this is a public class. 00584 */ 00585 ppcls = _InnerGetClassPtr(atomT, &ptiCurrent->ppi->pclsPublicList, NULL); 00586 if (ppcls == NULL) { 00587 RIPERR1(ERROR_CLASS_DOES_NOT_EXIST, RIP_WARNING, "UnregisterClass: Class does not exist; atom=%lX", (DWORD)atomT); 00588 return FALSE; 00589 } 00590 } 00591 00592 /* 00593 * If any windows created with this class still exist return an error. 00594 */ 00595 if ((*ppcls)->cWndReferenceCount != 0) { 00596 RIPERR0(ERROR_CLASS_HAS_WINDOWS, RIP_WARNING, "UnregisterClass: Class still has window"); 00597 return FALSE; 00598 } 00599 00600 /* 00601 * Return client side pointers for cleanup 00602 */ 00603 pcmn->pszClientAnsiMenuName = (*ppcls)->lpszClientAnsiMenuName; 00604 pcmn->pwszClientUnicodeMenuName = (*ppcls)->lpszClientUnicodeMenuName; 00605 pcmn->pusMenuName = NULL; 00606 00607 /* 00608 * Release the Window class and related information. 00609 */ 00610 DestroyClass(ppcls); 00611 00612 return TRUE; 00613 } 00614 00615 00616 PCLS _GetWOWClass( 00617 HANDLE hModule, 00618 LPCWSTR ccxlpszClassName) 00619 { 00620 PCLS pcls; 00621 PPCLS ppcls = NULL; 00622 ATOM atomT; 00623 PTHREADINFO ptiCurrent; 00624 00625 CheckCritInShared(); 00626 00627 ptiCurrent = PtiCurrentShared(); 00628 00629 /* 00630 * Is this class registered as a private class? 00631 */ 00632 atomT = UserFindAtom(ccxlpszClassName); 00633 if (atomT != 0) 00634 ppcls = GetClassPtr(atomT, ptiCurrent->ppi, hModule); 00635 if (ppcls == NULL) { 00636 RIPERR0(ERROR_CLASS_DOES_NOT_EXIST, RIP_VERBOSE, ""); 00637 return NULL; 00638 } 00639 00640 pcls = *ppcls; 00641 00642 if (ptiCurrent->rpdesk != pcls->rpdeskParent) { 00643 pcls = pcls->pclsClone; 00644 while (pcls != NULL) { 00645 if (ptiCurrent->rpdesk == pcls->rpdeskParent) { 00646 goto Done; 00647 } 00648 pcls = pcls->pclsNext; 00649 } 00650 RIPERR0(ERROR_CLASS_DOES_NOT_EXIST, RIP_VERBOSE, ""); 00651 return NULL; 00652 } 00653 Done: 00654 return pcls; 00655 } 00656 00657 /***************************************************************************\ 00658 * GetClassInfo (API) 00659 * 00660 * This function checks if the given class name is registered already. If the 00661 * class is not found, it returns 0; If the class is found, then all the 00662 * relevant information from the CLS structure is copied into the WNDCLASS 00663 * structure pointed to by the lpWndCls argument. If successful, it returns 00664 * the class name atom 00665 * 00666 * NOTE: hmod was used to distinguish between different task's public classes. 00667 * Now that public classes are gone, hmod isn't used anymore. We just search 00668 * the applications private class for a match and if none is found we search 00669 * the system classes. 00670 * 00671 * History: 00672 * 10-15-90 DarrinM Ported from Win 3.0 sources. 00673 * 04-08-91 DarrinM Removed public classes. 00674 * 04-26-91 DarrinM Streamlined to work with the client-side API. 00675 * 03-09-95 BradG Fixed bug when ATOM was passed in 00676 \***************************************************************************/ 00677 00678 ATOM _GetClassInfoEx( 00679 HANDLE hModule, 00680 LPCWSTR ccxlpszClassName, 00681 LPWNDCLASSEX pwc, 00682 LPWSTR *ppszMenuName, 00683 BOOL bAnsi) 00684 { 00685 PCLS pcls; 00686 PPCLS ppcls; 00687 ATOM atomT; 00688 PTHREADINFO ptiCurrent; 00689 DWORD dwCPDType = 0; 00690 00691 CheckCritIn(); 00692 00693 ptiCurrent = PtiCurrent(); 00694 00695 /* 00696 * These are done first so if we don't find the class, and therefore 00697 * fail, the return thank won't try to copy back these (nonexistant) 00698 * strings. 00699 */ 00700 pwc->lpszMenuName = NULL; 00701 pwc->lpszClassName = NULL; 00702 00703 /* 00704 * Is this class registered as a private class? 00705 */ 00706 00707 /* 00708 * bradg (3/9/95) - Must first check to see if an ATOM has been passed. 00709 */ 00710 atomT = FindClassAtom(ccxlpszClassName); 00711 00712 /* 00713 * Windows 3.1 does not perform the class search with 00714 * a null hModule. If an application supplies a NULL 00715 * hModule, they search on hModuleWin instead. 00716 */ 00717 00718 if (hModule == NULL) 00719 hModule = hModClient; 00720 00721 ppcls = GetClassPtr(atomT, ptiCurrent->ppi, hModule); 00722 00723 00724 if (ppcls == NULL) { 00725 RIPERR0(ERROR_CLASS_DOES_NOT_EXIST, RIP_VERBOSE, "GetClassInfo: Class does not exist"); 00726 return 0; 00727 } 00728 00729 pcls = *ppcls; 00730 00731 /* 00732 * Copy all the fields common to CLS and WNDCLASS structures except 00733 * the lpszMenuName and lpszClassName which will be filled in by the 00734 * client-side piece of GetClassInfo. 00735 */ 00736 00737 /* 00738 * Return public bits only 00739 */ 00740 pwc->style = pcls->style & CS_VALID; 00741 00742 /* 00743 * Corel Depth 6.0 calls GetClassInfo (COMBOBOX) and registers a class 00744 * using the same name and style bits. This works OK on Win95 because 00745 * their "system" (combo, edit, etc) classes are not CS_GLOBALCLASS 00746 * So we got to mask this bit out for our classes 00747 */ 00748 00749 /* 00750 * Bug 17998. If the app is 32bit and WinVer is less than 4.0 don't mask 00751 * out the CS_GLOBALCLASS bit. 00752 */ 00753 00754 if ( (pcls->fnid != 0) && 00755 ((LOWORD(ptiCurrent->dwExpWinVer) >= VER40) || (ptiCurrent->TIF_flags & TIF_16BIT)) ) { 00756 pwc->style &= ~CS_GLOBALCLASS; 00757 } 00758 00759 00760 pwc->cbClsExtra = pcls->cbclsExtra; 00761 pwc->cbWndExtra = pcls->cbwndExtra; 00762 00763 /* 00764 * Stop 32-bit apps from inadvertantly using hModuleWin as their hInstance 00765 * when they register a window class. FritzS 00766 */ 00767 00768 if (LOWORD(ptiCurrent->dwExpWinVer) >= VER40) { 00769 /* 00770 * This is actually, Win95 behavior -- the USER.EXE hModule gets thunked to NULL on 00771 * the way out of the 16->32 bit thunk. Note -- if we ever need to support 16-bit 00772 * 4.0 apps (shudder), this may need to change. FritzS 00773 */ 00774 if (hModule == hModClient) { 00775 pwc->hInstance = NULL; 00776 } else { 00777 pwc->hInstance = hModule; 00778 } 00779 } else { 00780 /* 00781 * Win NT 3.1/3.51 returned the hInstance from the class. 00782 * Note that this is incompatible with Win 3.1. WoW has hacks for 16-bit apps. 00783 */ 00784 00785 if ((pcls->hModule == hModuleWin) || (pcls->hModule == hModClient)) { 00786 pwc->hInstance = hModClient; 00787 } else { 00788 pwc->hInstance = pcls->hModule; 00789 } 00790 } 00791 00792 pwc->hIcon = PtoH(pcls->spicn); 00793 pwc->hCursor = PtoH(pcls->spcur); 00794 pwc->hbrBackground = pcls->hbrBackground; 00795 00796 /* 00797 * Need to hide the small icon if it's USER created 00798 */ 00799 if (pcls->spicnSm && (pcls->spicnSm->CURSORF_flags & CURSORF_SECRET)) 00800 pwc->hIconSm = NULL; 00801 else 00802 pwc->hIconSm = PtoH(pcls->spicnSm); 00803 00804 /* 00805 * If its a server proc then map it to a client proc. If not we may have 00806 * to create a CPD. 00807 */ 00808 if (pcls->CSF_flags & CSF_SERVERSIDEPROC) { 00809 pwc->lpfnWndProc = 00810 (WNDPROC)MapServerToClientPfn((ULONG_PTR)pcls->lpfnWndProc, bAnsi); 00811 } else { 00812 pwc->lpfnWndProc = (WNDPROC)MapClientNeuterToClientPfn(pcls, 0, bAnsi); 00813 00814 /* 00815 * If the client mapping didn't change the window proc then see if 00816 * we need a callproc handle. 00817 */ 00818 if (pwc->lpfnWndProc == (WNDPROC)pcls->lpfnWndProc) { 00819 /* 00820 * Need to return a CallProc handle if there is an Ansi/Unicode mismatch 00821 */ 00822 if (bAnsi != !!(pcls->CSF_flags & CSF_ANSIPROC)) { 00823 dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI; 00824 } 00825 } 00826 } 00827 00828 if (dwCPDType) { 00829 ULONG_PTR dwCPD; 00830 00831 dwCPD = GetCPD(pcls, dwCPDType | CPD_CLASS, (ULONG_PTR)pwc->lpfnWndProc); 00832 00833 if (dwCPD) { 00834 pwc->lpfnWndProc = (WNDPROC)dwCPD; 00835 } else { 00836 RIPMSG0(RIP_WARNING, "GetClassInfo unable to alloc CPD returning handle\n"); 00837 } 00838 } 00839 00840 /* 00841 * Return the stashed pointer to the client-side menu name string. 00842 */ 00843 if (bAnsi) { 00844 *ppszMenuName = (LPWSTR)pcls->lpszClientAnsiMenuName; 00845 } else { 00846 *ppszMenuName = pcls->lpszClientUnicodeMenuName; 00847 } 00848 return pcls->atomClassName; 00849 } 00850 00851 00852 /***************************************************************************\ 00853 * _SetClassWord (API) 00854 * 00855 * Set a class word. Positive index values set application class words 00856 * while negative index values set system class words. The negative 00857 * indices are published in WINDOWS.H. 00858 * 00859 * History: 00860 * 10-16-90 darrinm Wrote. 00861 \***************************************************************************/ 00862 00863 WORD _SetClassWord( 00864 PWND pwnd, 00865 int index, 00866 WORD value) 00867 { 00868 WORD wOld; 00869 WORD UNALIGNED *pw; 00870 PCLS pcls; 00871 00872 CheckCritIn(); 00873 00874 if (GETPTI(pwnd)->ppi != PpiCurrent()) { 00875 RIPERR1(ERROR_ACCESS_DENIED, RIP_WARNING, "SetClassWord: different process: index 0x%lx", index); 00876 return 0; 00877 } 00878 00879 pcls = pwnd->pcls->pclsBase; 00880 if ((index < 0) || (index + (int)sizeof(WORD) > pcls->cbclsExtra)) { 00881 RIPERR0(ERROR_INVALID_INDEX, RIP_WARNING, "SetClassWord: invalid index"); 00882 return 0; 00883 } else { 00884 pw = (WORD UNALIGNED *)((BYTE *)(pcls + 1) + index); 00885 wOld = *pw; 00886 *pw = value; 00887 pcls = pcls->pclsClone; 00888 while (pcls != NULL) { 00889 pw = (WORD UNALIGNED *)((BYTE *)(pcls + 1) + index); 00890 *pw = value; 00891 pcls = pcls->pclsNext; 00892 } 00893 return wOld; 00894 } 00895 } 00896 00897 00898 /***************************************************************************\ 00899 * xxxSetClassLong (API) 00900 * 00901 * Set a class long. Positive index values set application class longs 00902 * while negative index values set system class longs. The negative 00903 * indices are published in WINDOWS.H. 00904 * 00905 * History: 00906 * 10-16-90 darrinm Wrote. 00907 \***************************************************************************/ 00908 00909 ULONG_PTR xxxSetClassLongPtr( 00910 PWND pwnd, 00911 int index, 00912 ULONG_PTR value, 00913 BOOL bAnsi) 00914 { 00915 ULONG_PTR dwOld; 00916 PCLS pcls; 00917 00918 CheckLock(pwnd); 00919 CheckCritIn(); 00920 00921 if (GETPTI(pwnd)->ppi != PpiCurrent()) { 00922 RIPERR1(ERROR_ACCESS_DENIED, RIP_WARNING, "SetClassLongPtr: different process: index 0x%lx", index); 00923 return 0; 00924 } 00925 00926 if (index < 0) { 00927 return xxxSetClassData(pwnd, index, value, bAnsi); 00928 } else { 00929 pcls = pwnd->pcls->pclsBase; 00930 if (index + (int)sizeof(ULONG_PTR) > pcls->cbclsExtra) { 00931 RIPERR0(ERROR_INVALID_INDEX, RIP_WARNING, "SetClassLongPtr: invalid index"); 00932 return 0; 00933 } else { 00934 ULONG_PTR UNALIGNED *pudw; 00935 pudw = (ULONG_PTR UNALIGNED *)((BYTE *)(pcls + 1) + index); 00936 dwOld = *pudw; 00937 *pudw = value; 00938 pcls = pcls->pclsClone; 00939 while (pcls != NULL) { 00940 pudw = (ULONG_PTR UNALIGNED *)((BYTE *)(pcls + 1) + index); 00941 *pudw = value; 00942 pcls = pcls->pclsNext; 00943 } 00944 return dwOld; 00945 } 00946 } 00947 } 00948 00949 00950 #ifdef _WIN64 00951 DWORD xxxSetClassLong( 00952 PWND pwnd, 00953 int index, 00954 DWORD value, 00955 BOOL bAnsi) 00956 { 00957 DWORD dwOld; 00958 PCLS pcls; 00959 00960 CheckLock(pwnd); 00961 CheckCritIn(); 00962 00963 if (GETPTI(pwnd)->ppi != PpiCurrent()) { 00964 RIPERR1(ERROR_ACCESS_DENIED, RIP_WARNING, "SetClassLong: different process: index 0x%lx", index); 00965 return 0; 00966 } 00967 00968 if (index < 0) { 00969 if (index < INDEX_OFFSET || afClassDWord[index - INDEX_OFFSET] > sizeof(DWORD)) { 00970 RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING, "SetClassLong: invalid index %d", index); 00971 return 0; 00972 } 00973 return (DWORD)xxxSetClassData(pwnd, index, value, bAnsi); 00974 } else { 00975 pcls = pwnd->pcls->pclsBase; 00976 if (index + (int)sizeof(DWORD) > pcls->cbclsExtra) { 00977 RIPERR0(ERROR_INVALID_INDEX, RIP_WARNING, "SetClassLong: invalid index"); 00978 return 0; 00979 } else { 00980 DWORD UNALIGNED *pudw; 00981 pudw = (DWORD UNALIGNED *)((BYTE *)(pcls + 1) + index); 00982 dwOld = *pudw; 00983 *pudw = value; 00984 pcls = pcls->pclsClone; 00985 while (pcls != NULL) { 00986 pudw = (DWORD UNALIGNED *)((BYTE *)(pcls + 1) + index); 00987 *pudw = value; 00988 pcls = pcls->pclsNext; 00989 } 00990 return dwOld; 00991 } 00992 } 00993 } 00994 #endif 00995 00996 00997 PPCLS _InnerGetClassPtr( 00998 ATOM atom, 00999 PPCLS ppcls, 01000 HANDLE hModule) 01001 { 01002 if (atom == 0) 01003 return NULL; 01004 01005 while (*ppcls != NULL) { 01006 if ((*ppcls)->atomClassName == atom && 01007 (hModule == NULL || HIWORD((ULONG_PTR)(*ppcls)->hModule) == HIWORD((ULONG_PTR)hModule)) && 01008 !((*ppcls)->CSF_flags & CSF_WOWDEFERDESTROY)) { 01009 return ppcls; 01010 } 01011 01012 ppcls = (PPCLS)*ppcls; 01013 } 01014 01015 return NULL; 01016 } 01017 01018 01019 /***************************************************************************\ 01020 * GetClassPtr 01021 * 01022 * Note: This returns a "pointer-to-PCLS" and not "PCLS". 01023 * 01024 * Scan the passed-in class list for the specified class. Return NULL if 01025 * the class isn't in the list. 01026 * 01027 * History: 01028 * 10-16-90 darrinm Ported this puppy. 01029 * 04-08-91 DarrinM Rewrote to remove global classes. 01030 * 08-14-92 FritzS Changed check to HIWORD only to allow Wow apps to 01031 * share window classes between instances of an app. 01032 (For Wow apps, HiWord of hInstance is 16-bit module, 01033 and LoWord is 16-bit hInstance 01034 \***************************************************************************/ 01035 01036 PPCLS GetClassPtr( 01037 ATOM atom, 01038 PPROCESSINFO ppi, 01039 HANDLE hModule) 01040 { 01041 PPCLS ppcls; 01042 01043 /* 01044 * First search public then private then usersrv registered classes 01045 */ 01046 ppcls = _InnerGetClassPtr(atom, &ppi->pclsPrivateList, hModule); 01047 if (ppcls) 01048 return ppcls; 01049 01050 ppcls = _InnerGetClassPtr(atom, &ppi->pclsPublicList, NULL); 01051 if (ppcls) 01052 return ppcls; 01053 01054 /* 01055 * Next seach public and private classes and override hmodule; 01056 * some apps (bunny) do a GetClassInfo(dialog) and RegisterClass 01057 * and only change the wndproc which set the hmodule to be just 01058 * like usersrv created it even though it is in the app's public 01059 * or private class list 01060 */ 01061 01062 /* 01063 * Later -- since we are no longer returning hModuleWin to any app, 01064 * we may only need to check for hModClient. Check this out. 01065 * FritzS 01066 */ 01067 01068 ppcls = _InnerGetClassPtr(atom, &ppi->pclsPrivateList, hModClient); 01069 if (ppcls) 01070 return ppcls; 01071 01072 ppcls = _InnerGetClassPtr(atom, &ppi->pclsPublicList, hModClient); 01073 if (ppcls) 01074 return ppcls; 01075 01076 /* 01077 * Search the system class list 01078 */ 01079 ppcls = _InnerGetClassPtr(atom, &gpclsList, NULL); 01080 return ppcls; 01081 } 01082 01083 /***************************************************************************\ 01084 * UnlockAndFreeCPDs - 01085 * 01086 * Safe way to unlock and free a linked list of CPDs. Need to do it this 01087 * way in case the Thread's objects have already been marked for destruction. 01088 * 01089 * History 2/10/95 SanfordS Created 01090 \***************************************************************************/ 01091 01092 VOID UnlockAndFreeCPDs( 01093 PCALLPROCDATA *ppCPD) 01094 { 01095 PCALLPROCDATA pCPD; 01096 01097 while ((pCPD = *ppCPD) != NULL) { 01098 /* 01099 * Unlink the CPD from the list. 01100 */ 01101 *ppCPD = pCPD->spcpdNext; 01102 pCPD->spcpdNext = NULL; 01103 01104 /* 01105 * Mark it for destruction. 01106 */ 01107 if (!HMIsMarkDestroy(pCPD)) { 01108 HMMarkObjectDestroy(pCPD); 01109 } 01110 01111 /* 01112 * Unlock it and it will be destroyed. 01113 */ 01114 Unlock(&pCPD); 01115 } 01116 } 01117 01118 /***************************************************************************\ 01119 * DestroyClassBrush 01120 * 01121 * Destroy the brush of the class if it's a brush, it's not a system 01122 * brush and no other class is using it 01123 * 01124 * History: 01125 * 4-10-96 CLupu Created 01126 \***************************************************************************/ 01127 01128 void DestroyClassBrush( 01129 PCLS pcls) 01130 { 01131 PPROCESSINFO ppi = PpiCurrent(); 01132 PCLS pclsWalk; 01133 int nInd; 01134 BOOL bRet; 01135 /* 01136 * Return if it's not a real brush 01137 */ 01138 if (pcls->hbrBackground <= (HBRUSH)(COLOR_MAX)) 01139 return; 01140 01141 /* 01142 * Don't delete the system brushes 01143 */ 01144 for (nInd = 0; nInd < COLOR_MAX; nInd++) { 01145 if (pcls->hbrBackground == SYSHBRUSH(nInd)) 01146 return; 01147 } 01148 01149 01150 /* 01151 * Walk the process public public list 01152 */ 01153 pclsWalk = ppi->pclsPublicList; 01154 01155 while (pclsWalk) { 01156 if (pclsWalk != pcls && pclsWalk->hbrBackground == pcls->hbrBackground) 01157 return; 01158 01159 pclsWalk = pclsWalk->pclsNext; 01160 } 01161 01162 /* 01163 * Walk the process private class list 01164 */ 01165 pclsWalk = ppi->pclsPrivateList; 01166 01167 while (pclsWalk) { 01168 if (pclsWalk != pcls && pclsWalk->hbrBackground == pcls->hbrBackground) 01169 return; 01170 01171 pclsWalk = pclsWalk->pclsNext; 01172 } 01173 01174 /* 01175 * Finaly walk the system class list 01176 */ 01177 pclsWalk = gpclsList; 01178 01179 while (pclsWalk) { 01180 if (pclsWalk != pcls && pclsWalk->hbrBackground == pcls->hbrBackground) 01181 return; 01182 01183 pclsWalk = pclsWalk->pclsNext; 01184 } 01185 01186 bRet = GreDeleteObject(pcls->hbrBackground); 01187 01188 #if DBG 01189 if (!bRet) 01190 RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, 01191 "DestroyClassBrush: failed to destroy brush %#p", pcls->hbrBackground); 01192 #endif 01193 } 01194 01195 /***************************************************************************\ 01196 * DestroyClass 01197 * 01198 * Delete the window class. First, destroy any DCs that are attached to the 01199 * class. Then delete classname atom. Then free the other stuff that was 01200 * allocated when the class was registered and unlink the class from the 01201 * master class list. 01202 * 01203 * History: 01204 * 10-16-90 darrinm Ported this puppy. 01205 \***************************************************************************/ 01206 01207 void DestroyClass( 01208 PPCLS ppcls) 01209 { 01210 PPCLS ppclsClone; 01211 PCLS pcls; 01212 PDESKTOP rpdesk; 01213 01214 pcls = *ppcls; 01215 01216 UserAssert(pcls->cWndReferenceCount == 0); 01217 01218 /* 01219 * If this is a base class, destroy all clones before deleting 01220 * stuff. 01221 */ 01222 if (pcls == pcls->pclsBase) { 01223 ppclsClone = &pcls->pclsClone; 01224 while (*ppclsClone != NULL) { 01225 DestroyClass(ppclsClone); 01226 } 01227 01228 UserDeleteAtom(pcls->atomClassName); 01229 01230 /* 01231 * No freeing if it's an integer resource. 01232 */ 01233 if (IS_PTR(pcls->lpszMenuName)) { 01234 UserFreePool(pcls->lpszMenuName); 01235 } 01236 01237 /* 01238 * Free up the class dc if there is one. 01239 */ 01240 if (pcls->pdce != NULL) 01241 DestroyCacheDC(NULL, pcls->pdce->hdc); 01242 01243 /* 01244 * Delete the hBrBackground brush if nobody else is 01245 * using it. 01246 */ 01247 DestroyClassBrush(pcls); 01248 } 01249 01250 /* 01251 * If we created the small icon delete it 01252 */ 01253 DestroyClassSmIcon(pcls); 01254 01255 /* 01256 * Unlock cursor and icon 01257 */ 01258 Unlock(&pcls->spicn); 01259 Unlock(&pcls->spicnSm); 01260 Unlock(&pcls->spcur); 01261 01262 /* 01263 * Free any CallProcData objects associated with this class 01264 */ 01265 if (pcls->spcpdFirst) { 01266 UnlockAndFreeCPDs(&pcls->spcpdFirst); 01267 } 01268 01269 /* 01270 * Point the previous guy at the guy we currently point to. 01271 */ 01272 *ppcls = pcls->pclsNext; 01273 01274 /* 01275 * Lock the desktop. Do not use a thread lock because 01276 * this may be called during process cleanup when thread 01277 * locks are no longer usable. 01278 */ 01279 rpdesk = NULL; 01280 LockDesktop(&rpdesk, pcls->rpdeskParent, LDL_FN_DESTROYCLASS, (ULONG_PTR)PtiCurrent()); 01281 UnlockDesktop(&pcls->rpdeskParent, LDU_CLS_DESKPARENT2, (ULONG_PTR)pcls); 01282 ClassFree(rpdesk, pcls->lpszAnsiClassName); 01283 ClassFree(rpdesk, pcls); 01284 UnlockDesktop(&rpdesk, LDU_FN_DESTROYCLASS, (ULONG_PTR)PtiCurrent()); 01285 } 01286 01287 /***************************************************************************\ 01288 * GetClassIcoCur 01289 * 01290 * Returns the pwnd's class icon/cursor. This is called by _GetClassData 01291 * from the client side because PCURSORs are allocated from POOL (so the 01292 * client cannot do PtoH on them). NtUserCallHwndParam does the PtoH translation 01293 * 01294 * History: 01295 * 11-19-90 darrinm Wrote. 01296 \***************************************************************************/ 01297 PCURSOR GetClassIcoCur(PWND pwnd, int index) 01298 { 01299 PCLS pcls = pwnd->pcls; 01300 PCURSOR pcur; 01301 01302 switch (index) { 01303 case GCLP_HICON: 01304 pcur = pcls->spicn; 01305 break; 01306 01307 case GCLP_HCURSOR: 01308 pcur = pcls->spcur; 01309 break; 01310 01311 case GCLP_HICONSM: 01312 pcur = pcls->spicnSm; 01313 break; 01314 01315 default: 01316 RIPMSG2(RIP_WARNING, "GetWndIcoCur: Invalid index:%#lx. pwnd:%#p", 01317 index, pwnd); 01318 pcur = NULL; 01319 } 01320 01321 return pcur; 01322 } 01323 01324 /***************************************************************************\ 01325 * SetClassCursor 01326 * 01327 * History: 01328 \***************************************************************************/ 01329 ULONG_PTR SetClassCursor( 01330 PWND pwnd, 01331 PCLS pcls, 01332 DWORD index, 01333 ULONG_PTR dwData) 01334 { 01335 ULONG_PTR dwOld; 01336 01337 CheckLock(pwnd); 01338 01339 if ((HANDLE)dwData != NULL) { 01340 dwData = (ULONG_PTR)HMValidateHandle((HANDLE)dwData, TYPE_CURSOR); 01341 if ((PVOID)dwData == NULL) { 01342 if (index == GCLP_HICON || index == GCLP_HICONSM) { 01343 RIPERR0(ERROR_INVALID_ICON_HANDLE, RIP_WARNING, "SetClassData: invalid icon"); 01344 } else { 01345 RIPERR0(ERROR_INVALID_CURSOR_HANDLE, RIP_WARNING, "SetClassData: invalid cursor"); 01346 } 01347 } 01348 } 01349 01350 /* 01351 * Handle the locking issue. 01352 */ 01353 pcls = pcls->pclsBase; 01354 switch (index) { 01355 case GCLP_HICON: 01356 case GCLP_HICONSM: 01357 dwOld = (ULONG_PTR)xxxSetClassIcon(pwnd, pcls, (PCURSOR)dwData, index); 01358 break; 01359 01360 case GCLP_HCURSOR: 01361 dwOld = (ULONG_PTR)Lock(&pcls->spcur, dwData); 01362 break; 01363 } 01364 01365 /* 01366 * Now set it for each clone class. 01367 */ 01368 pcls = pcls->pclsClone; 01369 while (pcls != NULL) { 01370 switch(index) { 01371 case GCLP_HICON: 01372 case GCLP_HICONSM: 01373 xxxSetClassIcon(pwnd, pcls, (PCURSOR)dwData, index); 01374 break; 01375 01376 case GCLP_HCURSOR: 01377 Lock(&pcls->spcur, dwData); 01378 break; 01379 } 01380 pcls = pcls->pclsNext; 01381 } 01382 01383 return (ULONG_PTR)PtoH((PVOID)dwOld); 01384 } 01385 01386 /***************************************************************************\ 01387 * SetClassData 01388 * 01389 * SetClassWord and SetClassLong are now identical routines because they both 01390 * can return DWORDs. This single routine performs the work for them both 01391 * by using two arrays; afClassDWord to determine whether the result should be 01392 * a WORD or a DWORD, and aiClassOffset to find the correct offset into the 01393 * CLS structure for a given GCL_ or GCL_ index. 01394 * 01395 * History: 01396 * 11-19-90 darrinm Wrote. 01397 \***************************************************************************/ 01398 01399 ULONG_PTR xxxSetClassData( 01400 PWND pwnd, 01401 int index, 01402 ULONG_PTR dwData, 01403 BOOL bAnsi) 01404 { 01405 PCLS pcls = pwnd->pcls; 01406 BYTE *pb; 01407 ULONG_PTR dwT; 01408 ULONG_PTR dwOld; 01409 DWORD dwCPDType = 0; 01410 PCLSMENUNAME pcmn; 01411 UNICODE_STRING strMenuName, UString; 01412 01413 CheckLock(pwnd); 01414 01415 switch(index) { 01416 case GCLP_WNDPROC: 01417 01418 /* 01419 * If the application (client) subclasses a class that has a server - 01420 * side window proc we must return a client side proc stub that it 01421 * can call. 01422 */ 01423 if (pcls->CSF_flags & CSF_SERVERSIDEPROC) { 01424 dwOld = MapServerToClientPfn((ULONG_PTR)pcls->lpfnWndProc, bAnsi); 01425 pcls->CSF_flags &= ~CSF_SERVERSIDEPROC; 01426 01427 UserAssert(!(pcls->CSF_flags & CSF_ANSIPROC)); 01428 if (bAnsi) { 01429 pcls->CSF_flags |= CSF_ANSIPROC; 01430 } 01431 } else { 01432 dwOld = MapClientNeuterToClientPfn(pcls, 0, bAnsi); 01433 01434 /* 01435 * If the client mapping didn't change the window proc then see if 01436 * we need a callproc handle. 01437 */ 01438 if (dwOld == (ULONG_PTR)pcls->lpfnWndProc) { 01439 /* 01440 * Need to return a CallProc handle if there is an Ansi/Unicode mismatch 01441 */ 01442 if (bAnsi != !!(pcls->CSF_flags & CSF_ANSIPROC)) { 01443 dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI; 01444 } 01445 } 01446 } 01447 01448 if (dwCPDType) { 01449 ULONG_PTR dwCPD; 01450 01451 dwCPD = GetCPD(pcls, dwCPDType | CPD_CLASS, dwOld); 01452 01453 if (dwCPD) { 01454 dwOld = dwCPD; 01455 } else { 01456 RIPMSG0(RIP_WARNING, "GetClassLong unable to alloc CPD returning handle\n"); 01457 } 01458 } 01459 01460 /* 01461 * Convert a possible CallProc Handle into a real address. They may 01462 * have kept the CallProc Handle from some previous mixed GetClassinfo 01463 * or SetWindowLong. 01464 */ 01465 if (ISCPDTAG(dwData)) { 01466 PCALLPROCDATA pCPD; 01467 if (pCPD = HMValidateHandleNoRip((HANDLE)dwData, TYPE_CALLPROC)) { 01468 dwData = pCPD->pfnClientPrevious; 01469 } 01470 } 01471 01472 /* 01473 * If an app 'unsubclasses' a server-side window proc we need to 01474 * restore everything so SendMessage and friends know that it's 01475 * a server-side proc again. Need to check against client side 01476 * stub addresses. 01477 */ 01478 pcls->lpfnWndProc = (WNDPROC_PWND)dwData; 01479 if ((dwT = MapClientToServerPfn(dwData)) != 0) { 01480 pcls->lpfnWndProc = (WNDPROC_PWND)dwT; 01481 pcls->CSF_flags |= CSF_SERVERSIDEPROC; 01482 pcls->CSF_flags &= ~CSF_ANSIPROC; 01483 } else { 01484 if (bAnsi) { 01485 pcls->CSF_flags |= CSF_ANSIPROC; 01486 } else { 01487 pcls->CSF_flags &= ~CSF_ANSIPROC; 01488 } 01489 } 01490 if (pcls->CSF_flags & CSF_WOWCLASS) { 01491 PWC pwc = PWCFromPCLS(pcls); 01492 pwc->hMod16 = (pcls->CSF_flags & CSF_SERVERSIDEPROC) ? 0:xxxClientWOWGetProcModule(pcls->lpfnWndProc); 01493 } 01494 01495 return dwOld; 01496 break; 01497 01498 case GCLP_HICON: 01499 case GCLP_HICONSM: 01500 case GCLP_HCURSOR: 01501 return SetClassCursor(pwnd, pcls, index, dwData); 01502 break; 01503 01504 01505 case GCL_WOWMENUNAME: 01506 if (pcls->CSF_flags & CSF_WOWCLASS) { 01507 PWCFromPCLS(pcls)->vpszMenu = (DWORD)dwData; 01508 } else { 01509 UserAssert(FALSE); 01510 } 01511 break; 01512 01513 case GCL_CBCLSEXTRA: 01514 if (pcls->CSF_flags & CSF_WOWCLASS) { 01515 /* 01516 * yes -- we can do this for WOW classes only. 01517 */ 01518 if (pcls->CSF_flags & CSF_WOWEXTRA) { 01519 dwOld = PWCFromPCLS(pcls)->iClsExtra; 01520 PWCFromPCLS(pcls)->iClsExtra = LOWORD(dwData); 01521 return dwOld; 01522 } else { 01523 PWCFromPCLS(pcls)->iClsExtra = LOWORD(dwData); 01524 pcls->CSF_flags |= CSF_WOWEXTRA; 01525 return pcls->cbclsExtra; 01526 } 01527 } 01528 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Attempt to change cbClsExtra\n"); 01529 break; 01530 01531 case GCLP_MENUNAME: 01532 pcmn = (PCLSMENUNAME) dwData; 01533 01534 /* 01535 * pcmn->pusMenuName->Buffer is a client-side address. 01536 */ 01537 01538 dwOld = (ULONG_PTR) pcls->lpszMenuName; 01539 /* Is it a string? */ 01540 if (IS_PTR(pcmn->pusMenuName->Buffer)) { 01541 try { 01542 RtlInitUnicodeString(&UString, pcmn->pusMenuName->Buffer); 01543 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 01544 break; 01545 } 01546 /* Empty String? */ 01547 if (UString.Length == 0) { 01548 pcls->lpszMenuName = NULL; 01549 } else { 01550 /* Make a copy of the string */ 01551 if (!AllocateUnicodeString(&strMenuName, &UString)) { 01552 RIPMSG0(RIP_WARNING, "xxxSetClassData: GCL_MENUNAME AllocateUnicodeString failed\n"); 01553 break; 01554 } 01555 01556 pcls->lpszMenuName = strMenuName.Buffer; 01557 } 01558 } else { 01559 /* Just copy the id */ 01560 pcls->lpszMenuName = pcmn->pusMenuName->Buffer; 01561 } 01562 /* Don't return the kernel side pointer */ 01563 pcmn->pusMenuName = NULL; 01564 01565 /* Free old string, if any */ 01566 if (IS_PTR(dwOld)) { 01567 UserFreePool((PVOID)dwOld); 01568 } 01569 01570 /* Return client side pointers */ 01571 dwOld = (ULONG_PTR) pcls->lpszClientAnsiMenuName; 01572 pcls->lpszClientAnsiMenuName = pcmn->pszClientAnsiMenuName; 01573 pcmn->pszClientAnsiMenuName = (LPSTR)dwOld; 01574 01575 dwOld = (ULONG_PTR) pcls->lpszClientUnicodeMenuName; 01576 pcls->lpszClientUnicodeMenuName = pcmn->pwszClientUnicodeMenuName; 01577 pcmn->pwszClientUnicodeMenuName = (LPWSTR)dwOld; 01578 01579 return (bAnsi ? (ULONG_PTR) pcmn->pszClientAnsiMenuName : (ULONG_PTR) pcmn->pwszClientUnicodeMenuName); 01580 01581 default: 01582 /* 01583 * All other indexes go here... 01584 */ 01585 index -= INDEX_OFFSET; 01586 01587 /* 01588 * Only let valid indices go through; if aiClassOffset is zero 01589 * then we have no mapping for this negative index so it must 01590 * be a bogus index 01591 */ 01592 if ((index < 0) || (aiClassOffset[index] == 0)) { 01593 RIPERR0(ERROR_INVALID_INDEX, RIP_WARNING, "GetClassLong: invalid index"); 01594 return 0; 01595 } 01596 01597 pcls = pcls->pclsBase; 01598 pb = ((BYTE *)pcls) + aiClassOffset[index]; 01599 01600 if (afClassDWord[index] == sizeof(DWORD)) { 01601 dwOld = *(DWORD *)pb; 01602 *(DWORD *)pb = (DWORD)dwData; 01603 } else if (afClassDWord[index] == sizeof(ULONG_PTR)) { 01604 dwOld = *(ULONG_PTR *)pb; 01605 *(ULONG_PTR *)pb = dwData; 01606 } else { 01607 dwOld = (DWORD)*(WORD *)pb; 01608 *(WORD *)pb = (WORD)dwData; 01609 } 01610 01611 pcls = pcls->pclsClone; 01612 while (pcls != NULL) { 01613 pb = ((BYTE *)pcls) + aiClassOffset[index]; 01614 01615 if (afClassDWord[index] == sizeof(DWORD)) { 01616 dwOld = *(DWORD *)pb; 01617 *(DWORD *)pb = (DWORD)dwData; 01618 } else if (afClassDWord[index] == sizeof(ULONG_PTR)) { 01619 dwOld = *(ULONG_PTR *)pb; 01620 *(ULONG_PTR *)pb = dwData; 01621 } else { 01622 dwOld = (DWORD)*(WORD *)pb; 01623 *(WORD *)pb = (WORD)dwData; 01624 } 01625 pcls = pcls->pclsNext; 01626 } 01627 01628 return dwOld; 01629 } 01630 01631 return 0; 01632 } 01633 01634 01635 /***************************************************************************\ 01636 * ReferenceClass 01637 * 01638 * Clones the class if it is a different desktop than the new window and 01639 * increments the class window count(s). 01640 * 01641 * History: 01642 * 12-11-93 JimA Created. 01643 \***************************************************************************/ 01644 01645 BOOL ReferenceClass( 01646 PCLS pcls, 01647 PWND pwnd) 01648 { 01649 DWORD cbName; 01650 PCLS pclsClone; 01651 PDESKTOP pdesk; 01652 01653 /* 01654 * If the window is on the same desktop as the base class, just 01655 * increment the window count. 01656 */ 01657 if (pcls->rpdeskParent == pwnd->head.rpdesk) { 01658 pcls->cWndReferenceCount++; 01659 return TRUE; 01660 } 01661 01662 /* 01663 * The window is not on the base desktop. Try to find a cloned 01664 * class. 01665 */ 01666 for (pclsClone = pcls->pclsClone; pclsClone != NULL; 01667 pclsClone = pclsClone->pclsNext) { 01668 if (pclsClone->rpdeskParent == pwnd->head.rpdesk) 01669 break; 01670 } 01671 01672 /* 01673 * If we can't find one, clone the base class. 01674 */ 01675 if (pclsClone == NULL) { 01676 pdesk = pwnd->head.rpdesk; 01677 pclsClone = ClassAlloc(pdesk, sizeof(CLS) + pcls->cbclsExtra + (pcls->CSF_flags & CSF_WOWCLASS ?sizeof(WC):0)); 01678 if (pclsClone == NULL) { 01679 RIPMSG0(RIP_WARNING, "ReferenceClass: Failed Clone-Class Allocation\n"); 01680 return FALSE; 01681 } 01682 01683 RtlCopyMemory(pclsClone, pcls, sizeof(CLS) + pcls->cbclsExtra + (pcls->CSF_flags & CSF_WOWCLASS?sizeof(WC):0)); 01684 cbName = strlen(pcls->lpszAnsiClassName) + 1; 01685 pclsClone->lpszAnsiClassName = ClassAlloc(pdesk, cbName); 01686 if (pclsClone->lpszAnsiClassName == NULL) { 01687 ClassFree(pdesk, pclsClone); 01688 RIPMSG0(RIP_WARNING, "ReferenceClass: No Clone Class Name\n"); 01689 return FALSE; 01690 } 01691 01692 /* 01693 * Everything has been allocated, now lock everything down. 01694 * NULL pointers in clone to prevent Lock() from incorrectly 01695 * decrementing object reference count 01696 */ 01697 pclsClone->rpdeskParent = NULL; 01698 LockDesktop(&pclsClone->rpdeskParent, pdesk, 01699 LDL_CLS_DESKPARENT2, (ULONG_PTR)pclsClone); 01700 pclsClone->pclsNext = pcls->pclsClone; 01701 pclsClone->pclsClone = NULL; 01702 pcls->pclsClone = pclsClone; 01703 RtlCopyMemory(pclsClone->lpszAnsiClassName, pcls->lpszAnsiClassName, cbName); 01704 01705 pclsClone->spicn = pclsClone->spicnSm = pclsClone->spcur = NULL; 01706 01707 Lock(&pclsClone->spicn, pcls->spicn); 01708 Lock(&pclsClone->spicnSm, pcls->spicnSm); 01709 Lock(&pclsClone->spcur, pcls->spcur); 01710 pclsClone->spcpdFirst = NULL; 01711 pclsClone->cWndReferenceCount = 0; 01712 } 01713 01714 /* 01715 * Increment reference counts. 01716 */ 01717 pcls->cWndReferenceCount++; 01718 pclsClone->cWndReferenceCount++; 01719 pwnd->pcls = pclsClone; 01720 01721 return TRUE; 01722 } 01723 01724 01725 /***************************************************************************\ 01726 * DereferenceClass 01727 * 01728 * Decrements the class window count in the base class. If it's the 01729 * last window of a clone class, destroy the clone. 01730 * 01731 * History: 01732 * 12-11-93 JimA Created. 01733 \***************************************************************************/ 01734 01735 VOID DereferenceClass( 01736 PWND pwnd) 01737 { 01738 PCLS pcls = pwnd->pcls; 01739 PPCLS ppcls; 01740 01741 UserAssert(pcls->cWndReferenceCount >= 1); 01742 01743 pcls->cWndReferenceCount--; 01744 if (pcls != pcls->pclsBase) { 01745 01746 UserAssert(pcls->pclsBase->cWndReferenceCount >= 1); 01747 01748 pcls->pclsBase->cWndReferenceCount--; 01749 01750 if (pcls->cWndReferenceCount == 0) { 01751 ppcls = &pcls->pclsBase->pclsClone; 01752 while ((*ppcls) != pcls) 01753 ppcls = &(*ppcls)->pclsNext; 01754 UserAssert(ppcls); 01755 DestroyClass(ppcls); 01756 } 01757 } 01758 } 01759 01760 01761 /***************************************************************************\ 01762 * DestroyProcessesClasses 01763 * 01764 * History: 01765 * 04-07-91 DarrinM Created. 01766 \***************************************************************************/ 01767 01768 VOID DestroyProcessesClasses( 01769 PPROCESSINFO ppi) 01770 { 01771 PPCLS ppcls; 01772 01773 /* 01774 * Destroy the private classes first 01775 */ 01776 ppcls = &(ppi->pclsPrivateList); 01777 while (*ppcls != NULL) { 01778 DestroyClass(ppcls); 01779 } 01780 01781 /* 01782 * Then the cloned public classes 01783 */ 01784 ppcls = &(ppi->pclsPublicList); 01785 while (*ppcls != NULL) { 01786 DestroyClass(ppcls); 01787 } 01788 }

Generated on Sat May 15 19:39:24 2004 for test by doxygen 1.3.7