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.

369 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. w32init.c
  5. Abstract:
  6. This is the Win32 subsystem driver initializatiion module
  7. Author:
  8. Mark Lucovsky (markl) 31-Oct-1994
  9. Revision History:
  10. --*/
  11. #include "ntosp.h"
  12. #define DO_INLINE
  13. #include "w32p.h"
  14. #include "windef.h"
  15. #include "wingdi.h"
  16. #include "winerror.h"
  17. #include "winddi.h"
  18. #include "usergdi.h"
  19. #include "w32err.h"
  20. /*
  21. * Globals declared and initialized in ntuser\kernel\init.c
  22. */
  23. extern CONST ULONG W32ProcessSize;
  24. extern CONST ULONG W32ProcessTag;
  25. extern CONST ULONG W32ThreadSize;
  26. extern CONST ULONG W32ThreadTag;
  27. extern PFAST_MUTEX gpW32FastMutex;
  28. __inline VOID
  29. ReferenceW32Process(
  30. IN PW32PROCESS pW32Process)
  31. {
  32. PEPROCESS pEProcess = pW32Process->Process;
  33. UserAssert(pEProcess != NULL);
  34. ObReferenceObject(pEProcess);
  35. UserAssert(pW32Process->RefCount < MAXULONG);
  36. InterlockedIncrement(&pW32Process->RefCount);
  37. }
  38. VOID
  39. DereferenceW32Process(
  40. IN PW32PROCESS pW32Process)
  41. {
  42. PEPROCESS pEProcess = pW32Process->Process;
  43. /*
  44. * Dereference the object. It'll get freed when ref count goes to zero.
  45. */
  46. UserAssert(pW32Process->RefCount > 0);
  47. if (InterlockedDecrement(&pW32Process->RefCount) == 0) {
  48. UserDeleteW32Process(pW32Process);
  49. }
  50. /*
  51. * Dereference the kernel object.
  52. */
  53. UserAssert(pEProcess != NULL);
  54. ObDereferenceObject(pEProcess);
  55. }
  56. VOID
  57. LockW32Process(
  58. IN PW32PROCESS pW32Process,
  59. IN OUT PTL ptl)
  60. {
  61. PushW32ThreadLock(pW32Process, ptl, DereferenceW32Process);
  62. if (pW32Process != NULL) {
  63. ReferenceW32Process(pW32Process);
  64. }
  65. }
  66. NTSTATUS
  67. AllocateW32Process(
  68. IN OUT PEPROCESS pEProcess)
  69. {
  70. NTSTATUS Status = STATUS_SUCCESS;
  71. PW32PROCESS pW32Process;
  72. KeEnterCriticalRegion();
  73. ExAcquireFastMutexUnsafe(gpW32FastMutex);
  74. /*
  75. * Allocate the process object if we haven't already done so.
  76. */
  77. if ((pW32Process = PsGetProcessWin32Process(pEProcess)) == NULL) {
  78. pW32Process = Win32AllocPoolWithQuota(W32ProcessSize, W32ProcessTag);
  79. if (pW32Process) {
  80. RtlZeroMemory(pW32Process, W32ProcessSize);
  81. pW32Process->Process = pEProcess;
  82. Status = PsSetProcessWin32Process(pEProcess, pW32Process, NULL);
  83. if (NT_SUCCESS(Status)) {
  84. ReferenceW32Process(pW32Process);
  85. } else {
  86. NtCurrentTeb()->LastErrorValue = ERROR_ACCESS_DENIED;
  87. Win32FreePool(pW32Process);
  88. }
  89. } else {
  90. NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
  91. Status = STATUS_NO_MEMORY;
  92. }
  93. }
  94. ExReleaseFastMutexUnsafe(gpW32FastMutex);
  95. KeLeaveCriticalRegion();
  96. return Status;
  97. }
  98. extern PEPROCESS gpepCSRSS;
  99. __inline VOID
  100. FreeW32Process(
  101. IN OUT PW32PROCESS pW32Process)
  102. {
  103. ASSERT(pW32Process == W32GetCurrentProcess());
  104. ASSERT(pW32Process != NULL);
  105. /*
  106. * Dereference the object. It'll get freed when ref count goes to zero.
  107. */
  108. DereferenceW32Process(pW32Process);
  109. }
  110. NTSTATUS
  111. W32pProcessCallout(
  112. IN PEPROCESS Process,
  113. IN BOOLEAN Initialize)
  114. /*++
  115. Routine Description:
  116. This function is called whenever a Win32 process is created or deleted.
  117. Creattion occurs when the calling process calls NtConvertToGuiThread.
  118. Deletion occurs during PspExitthread processing for the last thread in
  119. a process.
  120. Arguments:
  121. Process - Supplies the address of the W32PROCESS to initialize.
  122. Initialize - Supplies a boolean value that is true if the process
  123. is being created.
  124. Return Value:
  125. TBD
  126. --*/
  127. {
  128. NTSTATUS Status;
  129. PW32PROCESS pW32Process;
  130. if (Initialize) {
  131. Status = AllocateW32Process(Process);
  132. if (!NT_SUCCESS(Status)) {
  133. return Status;
  134. }
  135. pW32Process = (PW32PROCESS)PsGetProcessWin32Process(Process);
  136. pW32Process->W32Pid = W32GetCurrentPID();
  137. } else {
  138. pW32Process = (PW32PROCESS)PsGetProcessWin32Process(Process);
  139. }
  140. TAGMSG3(DBGTAG_Callout,
  141. "W32: Process Callout for W32P %#p EP %#p called for %s",
  142. pW32Process,
  143. Process,
  144. Initialize ? "Creation" : "Deletion");
  145. Status = xxxUserProcessCallout(pW32Process, Initialize);
  146. if (Status == STATUS_ALREADY_WIN32) {
  147. return Status;
  148. }
  149. /*
  150. * Always call GDI at cleanup time. If GDI initialiatzion fails,
  151. * call USER for cleanup.
  152. */
  153. if (NT_SUCCESS(Status) || !Initialize) {
  154. Status = GdiProcessCallout(pW32Process, Initialize);
  155. if (!NT_SUCCESS(Status) && Initialize) {
  156. xxxUserProcessCallout(pW32Process, FALSE);
  157. }
  158. }
  159. /*
  160. * If this is not an initialization or initialization failed, free the
  161. * W32 process structure.
  162. */
  163. if (!Initialize || !NT_SUCCESS(Status)) {
  164. FreeW32Process(pW32Process);
  165. }
  166. return Status;
  167. }
  168. __inline VOID
  169. ReferenceW32Thread(
  170. IN PW32THREAD pW32Thread)
  171. {
  172. PETHREAD pEThread = pW32Thread->pEThread;
  173. UserAssert(pEThread != NULL);
  174. ObReferenceObject(pEThread);
  175. UserAssert(pW32Thread->RefCount < MAXULONG);
  176. InterlockedIncrement(&pW32Thread->RefCount);
  177. }
  178. VOID
  179. DereferenceW32Thread(
  180. IN PW32THREAD pW32Thread)
  181. {
  182. PETHREAD pEThread = pW32Thread->pEThread;
  183. /*
  184. * Dereference the object. It'll get freed when ref count goes to zero.
  185. */
  186. UserAssert(pW32Thread->RefCount > 0);
  187. if (InterlockedDecrement(&pW32Thread->RefCount) == 0) {
  188. UserDeleteW32Thread(pW32Thread);
  189. }
  190. /*
  191. * Dereference the kernel object.
  192. */
  193. UserAssert(pEThread != NULL);
  194. ObDereferenceObject(pEThread);
  195. }
  196. VOID
  197. LockW32Thread(
  198. IN PW32THREAD pW32Thread,
  199. IN OUT PTL ptl)
  200. {
  201. PushW32ThreadLock(pW32Thread, ptl, DereferenceW32Thread);
  202. if (pW32Thread != NULL) {
  203. ReferenceW32Thread(pW32Thread);
  204. }
  205. }
  206. VOID
  207. LockExchangeW32Thread(
  208. IN PW32THREAD pW32Thread,
  209. IN OUT PTL ptl)
  210. {
  211. if (pW32Thread != NULL) {
  212. ReferenceW32Thread(pW32Thread);
  213. }
  214. ExchangeW32ThreadLock(pW32Thread, ptl);
  215. }
  216. NTSTATUS
  217. AllocateW32Thread(
  218. IN OUT PETHREAD pEThread)
  219. {
  220. PW32THREAD pW32Thread;
  221. UserAssert(pEThread == PsGetCurrentThread());
  222. pW32Thread = Win32AllocPoolWithQuota(W32ThreadSize, W32ThreadTag);
  223. if (pW32Thread) {
  224. RtlZeroMemory(pW32Thread, W32ThreadSize);
  225. pW32Thread->pEThread = pEThread;
  226. PsSetThreadWin32Thread(pEThread, pW32Thread, NULL);
  227. ReferenceW32Thread(pW32Thread);
  228. return STATUS_SUCCESS;
  229. }
  230. return STATUS_NO_MEMORY;
  231. }
  232. VOID
  233. CleanupW32ThreadLocks(
  234. IN PW32THREAD pW32Thread)
  235. {
  236. PTL ptl;
  237. while (ptl = pW32Thread->ptlW32) {
  238. PopAndFreeW32ThreadLock(ptl);
  239. }
  240. }
  241. NTSTATUS
  242. W32pThreadCallout(
  243. IN PETHREAD pEThread,
  244. IN PSW32THREADCALLOUTTYPE CalloutType)
  245. /*++
  246. Routine Description:
  247. This function is called whenever a Win32 Thread is initialized,
  248. exited or deleted.
  249. Initialization occurs when the calling thread calls NtConvertToGuiThread.
  250. Exit occurs during PspExitthread processing and deletion during
  251. PspThreadDelete processing.
  252. Arguments:
  253. Thread - Supplies the address of the ETHREAD object
  254. CalloutType - Supplies the callout type
  255. Return Value:
  256. TBD
  257. --*/
  258. {
  259. NTSTATUS Status;
  260. TAGMSG2(DBGTAG_Callout,
  261. "W32: Thread Callout for ETHREAD %x called for %s\n",
  262. pEThread,
  263. CalloutType == PsW32ThreadCalloutInitialize ? "Initialization" :
  264. CalloutType == PsW32ThreadCalloutExit ? "Exit" : "Deletion");
  265. TAGMSG2(DBGTAG_Callout,
  266. " PID = %x TID = %x\n",
  267. PsGetThreadProcessId(pEThread),
  268. PsGetThreadId(pEThread));
  269. if (CalloutType == PsW32ThreadCalloutInitialize) {
  270. Status = AllocateW32Thread(pEThread);
  271. if (!NT_SUCCESS(Status)) {
  272. NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
  273. return Status;
  274. }
  275. }
  276. /*
  277. * If CalloutType == PsW32ThreadCalloutInitialize, assuming that:
  278. * - GdiThreadCallout never fails.
  279. * - If UserThreadCallout fails, there is no need to call
  280. * GdiThreadCallout for clean up.
  281. */
  282. GdiThreadCallout(pEThread, CalloutType);
  283. Status = UserThreadCallout(pEThread, CalloutType);
  284. if (CalloutType == PsW32ThreadCalloutExit || !NT_SUCCESS(Status)) {
  285. FreeW32Thread(pEThread);
  286. }
  287. return Status;
  288. }