Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

312 lines
10 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: cleanup.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains code used to clean up after a dying thread.
  7. *
  8. * History:
  9. * 02-15-91 DarrinM Created.
  10. * 01-16-92 IanJa Neutralized ANSI/UNICODE (debug strings kept ANSI)
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. /***************************************************************************\
  15. * PseudoDestroyClassWindows
  16. *
  17. * Walk the window tree from hwndParent looking for windows of class
  18. * wndClass. If one is found, destroy it.
  19. *
  20. *
  21. * WARNING windows actually destroys these windows. We only zombie-ize them
  22. * so this call does not have to be an xxx call.
  23. *
  24. * History:
  25. * 25-Mar-1994 JohnC from win 3.1
  26. \***************************************************************************/
  27. VOID PseudoDestroyClassWindows(
  28. PWND pwndParent,
  29. PCLS pcls)
  30. {
  31. PWND pwnd;
  32. PTHREADINFO pti;
  33. pti = PtiCurrent();
  34. /*
  35. * Recursively walk the window list and zombie any windows of this class.
  36. */
  37. for (pwnd = pwndParent->spwndChild; pwnd != NULL; pwnd = pwnd->spwndNext) {
  38. /*
  39. * If this window belongs to this class then zombie it if it was
  40. * created by this message thread.
  41. */
  42. if (pwnd->pcls == pcls && pti == GETPTI(pwnd)) {
  43. /*
  44. * Zombie-ize the window.
  45. *
  46. * Remove references to the client side window proc because that
  47. * WOW selector has been freed.
  48. */
  49. RIPMSG1(RIP_WARNING, "USER: Wow Window not destroyed: 0x%p", pwnd);
  50. if (!TestWF(pwnd, WFSERVERSIDEPROC)) {
  51. pwnd->lpfnWndProc = (WNDPROC_PWND)gpsi->apfnClientA.pfnDefWindowProc;
  52. }
  53. }
  54. /*
  55. * Recurse downward to look for any children that might be of this
  56. * class.
  57. */
  58. if (pwnd->spwndChild != NULL) {
  59. PseudoDestroyClassWindows(pwnd, pcls);
  60. }
  61. }
  62. }
  63. /***************************************************************************\
  64. * _WOWModuleUnload
  65. *
  66. * Go through all the windows owned by the dying queue and do the following:
  67. *
  68. * 1. Restore Standard window classes have their window procs restored
  69. * to their original value, in case they were subclassed.
  70. *
  71. * 2. App window classes have their window procs set to DefWindowProc
  72. * so that we don't execute any app code.
  73. *
  74. * Array of original window proc addresses, indexed by ICLS_* value is in
  75. * globals.c now -- gpfnwp.
  76. *
  77. * This array is initialized in code in init.c.
  78. \***************************************************************************/
  79. VOID _WOWModuleUnload(
  80. HANDLE hModule)
  81. {
  82. PPROCESSINFO ppi = PpiCurrent();
  83. PHE pheT, pheMax;
  84. PPCLS ppcls;
  85. int i;
  86. UserAssert(gpfnwp[0]);
  87. /*
  88. * PseudoDestroy windows with wndprocs from this hModule.
  89. *
  90. * If its a wow16 wndproc, check if the hMod16 is this module and Nuke
  91. * matches.
  92. */
  93. pheMax = &gSharedInfo.aheList[giheLast];
  94. for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) {
  95. PTHREADINFO ptiTest = (PTHREADINFO)pheT->pOwner;
  96. PWND pwnd;
  97. if (pheT->bType == TYPE_WINDOW &&
  98. (ptiTest->TIF_flags & TIF_16BIT) &&
  99. ptiTest->ppi == ppi) {
  100. pwnd = (PWND)pheT->phead;
  101. if (!TestWF(pwnd, WFSERVERSIDEPROC) &&
  102. IsWOWProc(pwnd->lpfnWndProc) &&
  103. (pwnd->hMod16 == (WORD)(ULONG_PTR)hModule)) {
  104. pwnd->lpfnWndProc = (WNDPROC_PWND)gpsi->apfnClientA.pfnDefWindowProc;
  105. }
  106. }
  107. }
  108. /*
  109. * Destroy private classes identified by hInstance that are not
  110. * referenced by any windows. Mark in-use classes for later destruction.
  111. */
  112. ppcls = &(ppi->pclsPrivateList);
  113. for (i = 0; i < 2; ++i) {
  114. while (*ppcls != NULL) {
  115. PWC pwc;
  116. PCLS pcls;
  117. if (HIWORD((ULONG_PTR)(*ppcls)->hModule) == (WORD)(ULONG_PTR)hModule) {
  118. if ((*ppcls)->cWndReferenceCount == 0) {
  119. DestroyClass(ppcls);
  120. /*
  121. * DestroyClass does *ppcls = pcls->pclsNext; so we just
  122. * want to continue here.
  123. */
  124. } else {
  125. /*
  126. * Zap all the windows around that belong to this class.
  127. */
  128. PseudoDestroyClassWindows(PtiCurrent()->rpdesk->pDeskInfo->spwnd, *ppcls);
  129. (*ppcls)->CSF_flags |= CSF_WOWDEFERDESTROY;
  130. ppcls = &((*ppcls)->pclsNext);
  131. }
  132. continue;
  133. }
  134. pcls = *ppcls;
  135. if ((pcls->CSF_flags & CSF_WOWCLASS) && ((WORD)(ULONG_PTR)hModule == (pwc = PWCFromPCLS(pcls))->hMod16)) {
  136. ATOM atom;
  137. int iSel;
  138. /*
  139. * See if the window's class atom matches any of the system
  140. * ones. If so, jam in the original window proc. Otherwise,
  141. * use DefWindowProc.
  142. */
  143. atom = (*ppcls)->atomClassName;
  144. for (iSel = ICLS_BUTTON; iSel < ICLS_MAX; iSel++) {
  145. if ((gpfnwp[iSel]) && (atom == gpsi->atomSysClass[iSel])) {
  146. (*ppcls)->lpfnWndProc = (WNDPROC_PWND)gpfnwp[iSel];
  147. break;
  148. }
  149. }
  150. if (iSel == ICLS_MAX) {
  151. (*ppcls)->lpfnWndProc = (WNDPROC_PWND)gpsi->apfnClientW.pfnDefWindowProc;
  152. }
  153. }
  154. ppcls = &((*ppcls)->pclsNext);
  155. }
  156. /*
  157. * Destroy public classes identified by hInstance that are not
  158. * referenced by any windows. Mark in-use classes for later
  159. * destruction.
  160. */
  161. ppcls = &(ppi->pclsPublicList);
  162. }
  163. }
  164. /***************************************************************************\
  165. * _WOWCleanup
  166. *
  167. * Private API to allow WOW to cleanup any process-owned resources when a WOW
  168. * thread exits or when a DLL is unloaded.
  169. *
  170. * Note that at module cleanup, hInstance = the module handle and hTaskWow is
  171. * NULL. On task cleanup, hInstance = the hInst/hTask combined which matches
  172. * the value passed in hModule to WowServerCreateCursorIcon and hTaskWow !=
  173. * NULL.
  174. *
  175. * History:
  176. * 09-02-92 JimA Created.
  177. \***************************************************************************/
  178. VOID _WOWCleanup(
  179. HANDLE hInstance,
  180. DWORD hTaskWow)
  181. {
  182. PPROCESSINFO ppi = PpiCurrent();
  183. PPCLS ppcls;
  184. PHE pheT, pheMax;
  185. int i;
  186. if (hInstance != NULL) {
  187. PWND pwnd;
  188. /*
  189. * Task cleanup.
  190. */
  191. hTaskWow = (DWORD)LOWORD(hTaskWow);
  192. /*
  193. * Task exit called by wow. This loop will Pseudo-Destroy windows
  194. * created by this task.
  195. */
  196. pheMax = &gSharedInfo.aheList[giheLast];
  197. for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) {
  198. PTHREADINFO ptiTest = (PTHREADINFO)pheT->pOwner;
  199. if (pheT->bType == TYPE_WINDOW &&
  200. (ptiTest->TIF_flags & TIF_16BIT) &&
  201. ptiTest->ptdb &&
  202. ptiTest->ptdb->hTaskWow == hTaskWow &&
  203. ptiTest->ppi == ppi) {
  204. pwnd = (PWND) pheT->phead;
  205. if (!TestWF(pwnd, WFSERVERSIDEPROC)) {
  206. pwnd->lpfnWndProc = (WNDPROC_PWND)gpsi->apfnClientA.pfnDefWindowProc;
  207. }
  208. }
  209. }
  210. return;
  211. }
  212. /*
  213. * If we get here, we are in thread cleanup and all of the thread's
  214. * windows have been destroyed or disassociated with any classes. If a
  215. * class marked for destruction at this point still has windows they
  216. * must belong to a dll.
  217. */
  218. /*
  219. * Destroy private classes marked for destruction.
  220. */
  221. ppcls = &(ppi->pclsPrivateList);
  222. for (i = 0; i < 2; ++i) {
  223. while (*ppcls != NULL) {
  224. if ((*ppcls)->hTaskWow == hTaskWow &&
  225. ((*ppcls)->CSF_flags & CSF_WOWDEFERDESTROY)) {
  226. if ((*ppcls)->cWndReferenceCount == 0) {
  227. DestroyClass(ppcls);
  228. } else {
  229. RIPMSG0(RIP_ERROR, "Windows remain for a WOW class marked for destruction");
  230. ppcls = &((*ppcls)->pclsNext);
  231. }
  232. } else {
  233. ppcls = &((*ppcls)->pclsNext);
  234. }
  235. }
  236. /*
  237. * Destroy public classes marked for destruction.
  238. */
  239. ppcls = &(ppi->pclsPublicList);
  240. }
  241. /*
  242. * Destroy menus, cursors, icons and accel tables identified by hTaskWow.
  243. */
  244. pheMax = &gSharedInfo.aheList[giheLast];
  245. for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) {
  246. /*
  247. * Check against free before we look at ppi because pq is stored in
  248. * the object itself, which won't be there if TYPE_FREE.
  249. */
  250. if (pheT->bType == TYPE_FREE) {
  251. continue;
  252. }
  253. /*
  254. * Destroy those objects created by this task.
  255. *
  256. * Do not destroy CALLPROCDATA objects. These should only get nuked
  257. * when the process goes away or when the class is nuked.
  258. */
  259. if (!(gahti[pheT->bType].bObjectCreateFlags & OCF_PROCESSOWNED) ||
  260. (PPROCESSINFO)pheT->pOwner != ppi ||
  261. ((PPROCOBJHEAD)pheT->phead)->hTaskWow != hTaskWow ||
  262. pheT->bType == TYPE_CALLPROC) {
  263. continue;
  264. }
  265. /*
  266. * Make sure this object isn't already marked to be destroyed - we'll
  267. * do no good if we try to destroy it now since it is locked.
  268. */
  269. if (pheT->bFlags & HANDLEF_DESTROY) {
  270. continue;
  271. }
  272. /*
  273. * Destroy this object.
  274. */
  275. HMDestroyUnlockedObject(pheT);
  276. }
  277. }