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.

294 lines
7.8 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: libmgmt.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains the code to manage loading and freeing libraries
  7. * in use by USER.
  8. *
  9. * History:
  10. * 02-04-91 DavidPe Created.
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. /*
  15. * Globals local to this file
  16. *
  17. *
  18. * Number of hmodule entries in the module management table.
  19. */
  20. int catomSysTableEntries;
  21. /*
  22. * Array of atoms that are the fully qualified path names of each managed
  23. * module.
  24. */
  25. ATOM aatomSysLoaded[CLIBS];
  26. /*
  27. * Count of processes that have LoadModule()'d each module.
  28. */
  29. int acatomSysUse[CLIBS];
  30. /*
  31. * Count of hooks set into each module.
  32. */
  33. int acatomSysDepends[CLIBS];
  34. /****************************************************************************\
  35. * GetHmodTableIndex
  36. *
  37. * This routine is used to return the index of a given atom within the system
  38. * wide hmod atom table. If the atom is not found, an attempt to allocate a
  39. * new table entry is made. If the attempt fails, -1 is returned.
  40. *
  41. * History:
  42. * 02-04-91 DavidPe Ported.
  43. \****************************************************************************/
  44. int GetHmodTableIndex(
  45. PUNICODE_STRING pstrLibName)
  46. {
  47. int i;
  48. ATOM atom;
  49. UNICODE_STRING strLibName;
  50. /*
  51. * Probe string
  52. */
  53. try {
  54. strLibName = ProbeAndReadUnicodeString(pstrLibName);
  55. ProbeForReadUnicodeStringBuffer(strLibName);
  56. atom = UserAddAtom(strLibName.Buffer, FALSE);
  57. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  58. return -1;
  59. }
  60. /*
  61. * If we can't add the atom we're hosed
  62. * so return an error.
  63. */
  64. if (atom == 0) {
  65. return -1;
  66. }
  67. /*
  68. * Search for atom index
  69. */
  70. for (i = 0; i < catomSysTableEntries && aatomSysLoaded[i] != atom; i++)
  71. ;
  72. if (i == catomSysTableEntries) {
  73. /*
  74. * Find empty entry for atom
  75. */
  76. for (i = 0; i < catomSysTableEntries && aatomSysLoaded[i]; i++)
  77. ;
  78. /*
  79. * Check if no empty entry found
  80. */
  81. if (i == catomSysTableEntries) {
  82. if (i == CLIBS) {
  83. UserDeleteAtom(atom);
  84. RIPERR0(ERROR_NOT_ENOUGH_MEMORY,
  85. RIP_WARNING,
  86. "Memory allocation failed in GetHmodTableIndex");
  87. return -1;
  88. }
  89. /*
  90. * Increase table size
  91. */
  92. catomSysTableEntries++;
  93. }
  94. /*
  95. * Set entry
  96. */
  97. aatomSysLoaded[i] = atom;
  98. acatomSysUse[i] = 0;
  99. acatomSysDepends[i] = 0;
  100. } else {
  101. UserDeleteAtom(atom);
  102. }
  103. return i;
  104. }
  105. /*****************************************************************************\
  106. * AddHmodDependency
  107. *
  108. * This function merely increments the dependency count of a given hmod
  109. * atom table index.
  110. *
  111. * History:
  112. * 02-04-91 DavidPe Ported.
  113. \*****************************************************************************/
  114. VOID AddHmodDependency(
  115. int iatom)
  116. {
  117. UserAssert(iatom >= 0);
  118. if (iatom < catomSysTableEntries) {
  119. acatomSysDepends[iatom]++;
  120. }
  121. }
  122. /*****************************************************************************\
  123. * RemoveHmodDependency
  124. *
  125. * This function removes a system dependency on a given index into the hmod
  126. * atom table. If all dependencies on the hmod have been removed (the Depends
  127. * count reaches zero) then the QS_SYSEXPUNGE bit is set in all message
  128. * queues so the eventually each process will do a free module on it.
  129. *
  130. * History:
  131. * 02-04-91 DavidPe Ported.
  132. \*****************************************************************************/
  133. VOID RemoveHmodDependency(
  134. int iatom)
  135. {
  136. UserAssert(iatom >= 0);
  137. if (iatom < catomSysTableEntries &&
  138. --acatomSysDepends[iatom] == 0) {
  139. if (acatomSysUse[iatom]) {
  140. /*
  141. * Cause each thread to check for expunged dlls
  142. * the next time they awake.
  143. */
  144. gcSysExpunge++;
  145. gdwSysExpungeMask |= (1 << iatom);
  146. } else {
  147. aatomSysLoaded[iatom] = 0;
  148. }
  149. }
  150. }
  151. /*****************************************************************************\
  152. * xxxLoadHmodIndex
  153. *
  154. * This function attempts to load the hmodule specified by iatom into the
  155. * system hmod table. Updates the per-process bitmap accordingly. Returns
  156. * NULL on success.
  157. *
  158. * History:
  159. * 02-04-91 DavidPe Ported.
  160. \*****************************************************************************/
  161. HANDLE xxxLoadHmodIndex(
  162. int iatom)
  163. {
  164. WCHAR pszLibName[MAX_PATH];
  165. HANDLE hmod;
  166. UNICODE_STRING strLibrary;
  167. PTHREADINFO ptiCurrent = PtiCurrent();
  168. UserAssert((!gptiRit || gptiRit->ppi != PtiCurrent()->ppi) &&
  169. "Shouldn't load global hooks on system process - gptiRit->ppi is the system process");
  170. if (iatom >= catomSysTableEntries) {
  171. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Index out of range");
  172. return NULL;
  173. }
  174. UserGetAtomName(aatomSysLoaded[iatom], pszLibName, sizeof(pszLibName)/sizeof(WCHAR));
  175. /*
  176. * Call back the client to load the library.
  177. */
  178. RtlInitUnicodeString(&strLibrary, pszLibName);
  179. hmod = ClientLoadLibrary(&strLibrary, (iatom == gihmodUserApiHook) ? goffPfnInitUserApiHook : 0);
  180. if (hmod != NULL) {
  181. /*
  182. * Check to make sure another thread hasn't loaded this library
  183. * while we were outside the critical section.
  184. */
  185. if (!TESTHMODLOADED(ptiCurrent, iatom)) {
  186. /*
  187. * Go ahead and bump the reference count.
  188. */
  189. acatomSysUse[iatom]++;
  190. SETHMODLOADED(ptiCurrent, iatom, hmod);
  191. } else {
  192. /*
  193. * Another thread loaded it while we were outside the
  194. * critical section. Unload it so the system's
  195. * reference count is correct.
  196. */
  197. ClientFreeLibrary(ptiCurrent->ppi->ahmodLibLoaded[iatom]);
  198. }
  199. }
  200. return hmod;
  201. }
  202. /***********************************************************************\
  203. * DoSysExpunge
  204. *
  205. * This function is called when a thread wakes up and finds its
  206. * QS_SYSEXPUNGE wakebit set.
  207. *
  208. * History:
  209. * 02-04-91 DavidPe Ported.
  210. \***********************************************************************/
  211. VOID xxxDoSysExpunge(
  212. PTHREADINFO pti)
  213. {
  214. int i;
  215. /*
  216. * Clear this first before we potentially leave the critical section.
  217. */
  218. pti->ppi->cSysExpunge = gcSysExpunge;
  219. /*
  220. * Scan for libraries that have been freed
  221. */
  222. for (i = 0; i < catomSysTableEntries; i++) {
  223. if ((acatomSysDepends[i] == 0) && (aatomSysLoaded[i] != 0) &&
  224. TESTHMODLOADED(pti, i)) {
  225. HANDLE hmodFree = pti->ppi->ahmodLibLoaded[i];
  226. /*
  227. * Clear this hmod for this process before we leave the
  228. * critical section.
  229. */
  230. CLEARHMODLOADED(pti, i);
  231. /*
  232. * Decrement the count of processes that have loaded this
  233. * .dll. If there are no more, then destroy the reference
  234. * to this .dll.
  235. */
  236. if (--acatomSysUse[i] == 0) {
  237. UserDeleteAtom(aatomSysLoaded[i]);
  238. aatomSysLoaded[i] = 0;
  239. gdwSysExpungeMask &= ~(1 << i);
  240. }
  241. /*
  242. * Call back the client to free the library...
  243. */
  244. ClientFreeLibrary(hmodFree);
  245. }
  246. }
  247. }