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

cleanup.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: cleanup.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains code used to clean up after a dying thread. 00007 * 00008 * History: 00009 * 02-15-91 DarrinM Created. 00010 * 01-16-92 IanJa Neutralized ANSI/UNICODE (debug strings kept ANSI) 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 /***************************************************************************\ 00017 * CheckForClientDeath 00018 * 00019 * Check to see if the client thread that is paired to the current running 00020 * server thread has died. If it has, we raise an exception so this thread 00021 * can perform its cleanup duties. NOTE: If the client has died, this 00022 * will not be returning back to its caller. 00023 * 00024 * History: 00025 * 05-23-91 DarrinM Created. 00026 \***************************************************************************/ 00027 00028 /***************************************************************************\ 00029 * PseudoDestroyClassWindows 00030 * 00031 * Walk the window tree from hwndParent looking for windows 00032 * of class wndClass. If one is found, destroy it. 00033 * 00034 * 00035 * WARNING windows actually destroys these windows. We only zombie-ize them 00036 * so this call does not have to be an xxx call. 00037 * 00038 * History: 00039 * 25-Mar-1994 JohnC from win 3.1 00040 \***************************************************************************/ 00041 00042 VOID PseudoDestroyClassWindows(PWND pwndParent, PCLS pcls) 00043 { 00044 PWND pwnd; 00045 PTHREADINFO pti; 00046 00047 pti = PtiCurrent(); 00048 00049 /* 00050 * Recursively walk the window list and zombie any windows of this class 00051 */ 00052 for (pwnd = pwndParent->spwndChild; pwnd != NULL; pwnd = pwnd->spwndNext) { 00053 00054 /* 00055 * If this window belongs to this class then zombie it 00056 * if it was created by this message thread. 00057 */ 00058 if (pwnd->pcls == pcls && pti == GETPTI(pwnd)) { 00059 00060 /* 00061 * Zombie-ize the window 00062 * 00063 * Remove references to the client side window proc because that 00064 * WOW selector has been freed. 00065 */ 00066 00067 RIPMSG1(RIP_WARNING, 00068 "USER: Wow Window not destroyed: %lX", pwnd); 00069 00070 if (!TestWF(pwnd, WFSERVERSIDEPROC)) { 00071 pwnd->lpfnWndProc = (WNDPROC_PWND)gpsi->apfnClientA.pfnDefWindowProc; 00072 } 00073 } 00074 00075 /* 00076 * Recurse downward to look for any children that might be 00077 * of this class. 00078 */ 00079 if (pwnd->spwndChild != NULL) 00080 PseudoDestroyClassWindows(pwnd, pcls); 00081 } 00082 } 00083 00084 /***************************************************************************\ 00085 * Go through all the windows owned by the dying queue and do the following: 00086 * 00087 * 1. Restore Standard window classes have their window procs restored 00088 * to their original value, in case they were subclassed. 00089 * 00090 * 2. App window classes have their window procs set to DefWindowProc 00091 * so that we don't execute any app code. 00092 * 00093 * Array of original window proc addresses, 00094 * indexed by ICLS_* value is in globals.c now -- gpfnwp. 00095 * 00096 * This array is initialized in code in init.c. 00097 \***************************************************************************/ 00098 00099 VOID _WOWModuleUnload(HANDLE hModule) { 00100 PPROCESSINFO ppi = PpiCurrent(); 00101 PHE pheT, pheMax; 00102 PPCLS ppcls; 00103 int i; 00104 00105 UserAssert(gpfnwp[0]); 00106 00107 /* 00108 * PseudoDestroy windows with wndprocs from this hModule 00109 * If its a wow16 wndproc, check if the hMod16 is this module 00110 * and Nuke matches. 00111 */ 00112 pheMax = &gSharedInfo.aheList[giheLast]; 00113 for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) { 00114 PTHREADINFO ptiTest = (PTHREADINFO)pheT->pOwner; 00115 PWND pwnd; 00116 if ((pheT->bType == TYPE_WINDOW) && 00117 (ptiTest->TIF_flags & TIF_16BIT) && 00118 (ptiTest->ppi == ppi)) { 00119 00120 pwnd = (PWND) pheT->phead; 00121 if (!TestWF(pwnd, WFSERVERSIDEPROC) && 00122 IsWOWProc(pwnd->lpfnWndProc) && 00123 (pwnd->hMod16 == (WORD)(ULONG_PTR)hModule)) { 00124 pwnd->lpfnWndProc = (WNDPROC_PWND)gpsi->apfnClientA.pfnDefWindowProc; 00125 } 00126 } 00127 } 00128 00129 /* 00130 * Destroy private classes identified by hInstance that are not 00131 * referenced by any windows. Mark in-use classes for later 00132 * destruction. 00133 */ 00134 ppcls = &(ppi->pclsPrivateList); 00135 00136 for (i = 0; i < 2; ++i) { 00137 while (*ppcls != NULL) { 00138 00139 PWC pwc; 00140 PCLS pcls; 00141 00142 if (HIWORD((ULONG_PTR)(*ppcls)->hModule) == (WORD)(ULONG_PTR)hModule) { 00143 if ((*ppcls)->cWndReferenceCount == 0) { 00144 DestroyClass(ppcls); 00145 /* 00146 * DestroyClass does *ppcls = pcls->pclsNext; 00147 * so we just want continue here 00148 */ 00149 } else { 00150 00151 /* 00152 * Zap all the windows around that belong to this class. 00153 */ 00154 PseudoDestroyClassWindows(PtiCurrent()->rpdesk->pDeskInfo->spwnd, *ppcls); 00155 00156 /* 00157 * Win 3.1 does not distinguish between Dll's and Exe's 00158 */ 00159 (*ppcls)->CSF_flags |= CSF_WOWDEFERDESTROY; 00160 ppcls = &((*ppcls)->pclsNext); 00161 } 00162 continue; 00163 } 00164 00165 pcls = *ppcls; 00166 00167 if ((pcls->CSF_flags & CSF_WOWCLASS) && ((WORD)(ULONG_PTR)hModule == (pwc = PWCFromPCLS(pcls))->hMod16)) { 00168 00169 ATOM atom; 00170 int iSel; 00171 00172 /* 00173 * See if the window's class atom matches any of 00174 * the system ones. If so, jam in the original window proc. 00175 * Otherwise, use DefWindowProc 00176 */ 00177 atom = (*ppcls)->atomClassName; 00178 for (iSel = ICLS_BUTTON; iSel < ICLS_MAX; iSel++) { 00179 if ((gpfnwp[iSel]) && (atom == gpsi->atomSysClass[iSel])) { 00180 (*ppcls)->lpfnWndProc = (WNDPROC_PWND)gpfnwp[iSel]; 00181 break; 00182 } 00183 } 00184 if (iSel == ICLS_MAX) 00185 (*ppcls)->lpfnWndProc = (WNDPROC_PWND)gpsi->apfnClientW.pfnDefWindowProc; 00186 } 00187 00188 ppcls = &((*ppcls)->pclsNext); 00189 } 00190 00191 /* 00192 * Destroy public classes identified by hInstance that are not 00193 * referenced by any windows. Mark in-use classes for later 00194 * destruction. 00195 */ 00196 ppcls = &(ppi->pclsPublicList); 00197 } 00198 return; 00199 00200 } 00201 00202 00203 /***************************************************************************\ 00204 * _WOWCleanup 00205 * 00206 * Private API to allow WOW to cleanup any process-owned resources when 00207 * a WOW thread exits or when a DLL is unloaded. 00208 * 00209 * Note that at module cleanup, hInstance = the module handle and hTaskWow 00210 * is NULL. On task cleanup, hInstance = the hInst/hTask combined which 00211 * matches the value passed in hModule to WowServerCreateCursorIcon and 00212 * hTaskWow != NULL. 00213 * 00214 * History: 00215 * 09-02-92 JimA Created. 00216 \***************************************************************************/ 00217 00218 VOID _WOWCleanup( 00219 HANDLE hInstance, 00220 DWORD hTaskWow) 00221 { 00222 PPROCESSINFO ppi = PpiCurrent(); 00223 PPCLS ppcls; 00224 PHE pheT, pheMax; 00225 int i; 00226 00227 if (hInstance != NULL) { 00228 00229 /* 00230 * Task cleanup 00231 */ 00232 00233 PWND pwnd; 00234 hTaskWow = (DWORD) LOWORD(hTaskWow); 00235 /* 00236 * Task exit called by wow. This loop will Pseudo-Destroy windows 00237 * created by this task. 00238 */ 00239 pheMax = &gSharedInfo.aheList[giheLast]; 00240 for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) { 00241 PTHREADINFO ptiTest = (PTHREADINFO)pheT->pOwner; 00242 if ((pheT->bType == TYPE_WINDOW) && 00243 (ptiTest->TIF_flags & TIF_16BIT) && 00244 (ptiTest->ptdb) && 00245 (ptiTest->ptdb->hTaskWow == hTaskWow) && 00246 (ptiTest->ppi == ppi)) { 00247 00248 pwnd = (PWND) pheT->phead; 00249 if (!TestWF(pwnd, WFSERVERSIDEPROC)) { 00250 pwnd->lpfnWndProc = (WNDPROC_PWND)gpsi->apfnClientA.pfnDefWindowProc; 00251 } 00252 } 00253 } 00254 return; 00255 } 00256 00257 /* 00258 * If we get here, we are in thread cleanup and all of the thread's windows 00259 * have been destroyed or disassociated with any classes. If a class 00260 * marked for destruction at this point still has windows, they must 00261 * belong to a dll. 00262 */ 00263 00264 /* 00265 * Destroy private classes marked for destruction 00266 */ 00267 ppcls = &(ppi->pclsPrivateList); 00268 for (i = 0; i < 2; ++i) { 00269 while (*ppcls != NULL) { 00270 if ((*ppcls)->hTaskWow == hTaskWow && 00271 ((*ppcls)->CSF_flags & CSF_WOWDEFERDESTROY)) { 00272 if ((*ppcls)->cWndReferenceCount == 0) { 00273 DestroyClass(ppcls); 00274 } else { 00275 RIPMSG0(RIP_ERROR, "Windows remain for a WOW class marked for destruction"); 00276 ppcls = &((*ppcls)->pclsNext); 00277 } 00278 } else 00279 ppcls = &((*ppcls)->pclsNext); 00280 } 00281 00282 /* 00283 * Destroy public classes marked for destruction 00284 */ 00285 ppcls = &(ppi->pclsPublicList); 00286 } 00287 00288 /* 00289 * Destroy menus, cursors, icons and accel tables identified by hTaskWow 00290 */ 00291 pheMax = &gSharedInfo.aheList[giheLast]; 00292 for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) { 00293 00294 /* 00295 * Check against free before we look at ppi... because pq is stored 00296 * in the object itself, which won't be there if TYPE_FREE. 00297 */ 00298 if (pheT->bType == TYPE_FREE) 00299 continue; 00300 00301 /* 00302 * Destroy those objects created by this task. 00303 */ 00304 if ( !(gahti[pheT->bType].bObjectCreateFlags & OCF_PROCESSOWNED) || 00305 (PPROCESSINFO)pheT->pOwner != ppi || 00306 (((PPROCOBJHEAD)pheT->phead)->hTaskWow != hTaskWow) || 00307 (pheT->bType == TYPE_CALLPROC) /* Do not destroy CALLPROCDATA objects. 00308 * These should only get nuked when the 00309 * process goes away or when the class 00310 * is nuked. 00311 */ 00312 ) { 00313 00314 continue; 00315 } 00316 00317 /* 00318 * Make sure this object isn't already marked to be destroyed - we'll 00319 * do no good if we try to destroy it now since it is locked. 00320 */ 00321 if (pheT->bFlags & HANDLEF_DESTROY) { 00322 continue; 00323 } 00324 00325 /* 00326 * Destroy this object. 00327 */ 00328 HMDestroyUnlockedObject(pheT); 00329 } 00330 }

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