Source code of Windows XP (NT5)
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.

461 lines
12 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. srvtask.c
  5. Abstract:
  6. This module implements windows server tasking functions
  7. Author:
  8. Mark Lucovsky (markl) 13-Nov-1990
  9. Revision History:
  10. --*/
  11. #include "basesrv.h"
  12. #if defined(_WIN64)
  13. #include <wow64t.h>
  14. #endif // defined(_WIN64)
  15. PFNNOTIFYPROCESSCREATE UserNotifyProcessCreate = NULL;
  16. void
  17. BaseSetProcessCreateNotify(
  18. IN PFNNOTIFYPROCESSCREATE ProcessCreateRoutine
  19. )
  20. {
  21. UserNotifyProcessCreate = ProcessCreateRoutine;
  22. }
  23. ULONG
  24. BaseSrvCreateProcess(
  25. IN OUT PCSR_API_MSG m,
  26. IN OUT PCSR_REPLY_STATUS ReplyStatus
  27. )
  28. {
  29. NTSTATUS Status, Status1;
  30. PBASE_CREATEPROCESS_MSG a = (PBASE_CREATEPROCESS_MSG)&m->u.ApiMessageData;
  31. HANDLE CsrClientProcess = NULL;
  32. HANDLE NewProcess = NULL;
  33. HANDLE Thread = NULL;
  34. PCSR_THREAD t;
  35. ULONG DebugFlags;
  36. DWORD dwFlags;
  37. PCSR_PROCESS ProcessVDM;
  38. #if defined(_WIN64)
  39. PPEB32 Peb32 = NULL;
  40. #endif // defined(_WIN64)
  41. PPEB NewPeb = NULL;
  42. USHORT ProcessorArchitecture = a->ProcessorArchitecture;
  43. t = CSR_SERVER_QUERYCLIENTTHREAD();
  44. CsrClientProcess = t->Process->ProcessHandle;
  45. #if defined(_WIN64)
  46. if (ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
  47. ProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA32_ON_WIN64;
  48. #endif // defined(_WIN64)
  49. //
  50. // Get handles to the process and thread local to the
  51. // Windows server.
  52. //
  53. if ((dwFlags = (DWORD)((ULONG_PTR)a->ProcessHandle) & 3)) {
  54. a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle & ~3);
  55. }
  56. Status = NtDuplicateObject(
  57. CsrClientProcess,
  58. a->ProcessHandle,
  59. NtCurrentProcess(),
  60. &NewProcess,
  61. 0L,
  62. 0L,
  63. DUPLICATE_SAME_ACCESS
  64. );
  65. if ( !NT_SUCCESS(Status) ) {
  66. goto Cleanup;
  67. }
  68. Status = NtDuplicateObject(
  69. CsrClientProcess,
  70. a->ThreadHandle,
  71. NtCurrentProcess(),
  72. &Thread,
  73. 0L,
  74. 0L,
  75. DUPLICATE_SAME_ACCESS
  76. );
  77. if ( !NT_SUCCESS(Status) ) {
  78. goto Cleanup;
  79. }
  80. {
  81. PROCESS_BASIC_INFORMATION ProcessBasicInfo;
  82. Status =
  83. NtQueryInformationProcess(
  84. NewProcess,
  85. ProcessBasicInformation,
  86. &ProcessBasicInfo,
  87. sizeof(ProcessBasicInfo),
  88. NULL);
  89. if (!NT_SUCCESS(Status)) {
  90. DbgPrintEx(
  91. DPFLTR_SXS_ID,
  92. DPFLTR_ERROR_LEVEL,
  93. "SXS: NtQueryInformationProcess failed.\n", Status);
  94. goto Cleanup;
  95. }
  96. NewPeb = ProcessBasicInfo.PebBaseAddress;
  97. }
  98. if ((a->CreationFlags & CREATE_IGNORE_SYSTEM_DEFAULT) == 0) {
  99. Status = BaseSrvSxsDoSystemDefaultActivationContext(ProcessorArchitecture, NewProcess, NewPeb);
  100. if ((!NT_SUCCESS(Status)) && (Status != STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY)) {
  101. goto Cleanup;
  102. }
  103. }
  104. Status = BaseSrvSxsCreateProcess(CsrClientProcess, NewProcess, m, NewPeb);
  105. if (!NT_SUCCESS(Status)) {
  106. goto Cleanup;
  107. }
  108. DebugFlags = 0;
  109. if ( a->CreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS) ) {
  110. if ( a->CreationFlags & DEBUG_PROCESS ) {
  111. DebugFlags |= CSR_DEBUG_PROCESS_TREE;
  112. }
  113. if ( a->CreationFlags & DEBUG_ONLY_THIS_PROCESS ) {
  114. DebugFlags |= CSR_DEBUG_THIS_PROCESS;
  115. }
  116. }
  117. if ( a->CreationFlags & CREATE_NEW_PROCESS_GROUP ) {
  118. DebugFlags |= CSR_CREATE_PROCESS_GROUP;
  119. }
  120. if ( !(dwFlags & 2) ) {
  121. DebugFlags |= CSR_PROCESS_CONSOLEAPP;
  122. }
  123. Status = CsrCreateProcess(
  124. NewProcess,
  125. Thread,
  126. &a->ClientId,
  127. t->Process->NtSession,
  128. DebugFlags,
  129. NULL
  130. );
  131. switch(Status) {
  132. case STATUS_THREAD_IS_TERMINATING:
  133. if (a->VdmBinaryType )
  134. BaseSrvVDMTerminated (a->hVDM, a->VdmTask);
  135. *ReplyStatus = CsrClientDied;
  136. goto Cleanup;
  137. case STATUS_SUCCESS:
  138. //
  139. // notify USER that a process is being created. USER needs to know
  140. // for various synchronization issues such as startup activation,
  141. // startup synchronization, and type ahead.
  142. //
  143. // Turn on 0x8 bit of dwFlags if this is a WOW process being
  144. // created so that UserSrv knows to ignore the console's call
  145. // to UserNotifyConsoleApplication.
  146. //
  147. if (IS_WOW_BINARY(a->VdmBinaryType)) {
  148. dwFlags |= 8;
  149. }
  150. if (UserNotifyProcessCreate != NULL) {
  151. if (!(*UserNotifyProcessCreate)((DWORD)((ULONG_PTR)a->ClientId.UniqueProcess),
  152. (DWORD)((ULONG_PTR)t->ClientId.UniqueThread),
  153. 0, dwFlags)) {
  154. //
  155. // FIX, FIX - error cleanup. Shouldn't we close the duplicated
  156. // process and thread handles above?
  157. //
  158. }
  159. }
  160. //
  161. // Update the VDM sequence number.
  162. //
  163. if (a->VdmBinaryType) {
  164. Status = BaseSrvUpdateVDMSequenceNumber(a->VdmBinaryType,
  165. a->hVDM,
  166. a->VdmTask,
  167. a->ClientId.UniqueProcess);
  168. if (!NT_SUCCESS( Status )) {
  169. //
  170. // FIX, FIX - error cleanup. Shouldn't we close the
  171. // duplicated process and thread handles above?
  172. //
  173. BaseSrvVDMTerminated (a->hVDM, a->VdmTask);
  174. }
  175. }
  176. break;
  177. default:
  178. goto Cleanup;
  179. }
  180. // We don't use the usual Exit: pattern here in order to more carefully
  181. // preserve the preexisting behavior, which apparently leaks handles in error cases.
  182. return( (ULONG)Status );
  183. Cleanup:
  184. if (NewProcess != NULL) {
  185. Status1 = NtClose(NewProcess);
  186. RTL_SOFT_ASSERT(NT_SUCCESS(Status1));
  187. }
  188. if (Thread != NULL) {
  189. Status1 = NtClose(Thread);
  190. RTL_SOFT_ASSERT(NT_SUCCESS(Status1));
  191. }
  192. return( (ULONG)Status );
  193. }
  194. ULONG
  195. BaseSrvCreateThread(
  196. IN OUT PCSR_API_MSG m,
  197. IN OUT PCSR_REPLY_STATUS ReplyStatus
  198. )
  199. {
  200. PBASE_CREATETHREAD_MSG a = (PBASE_CREATETHREAD_MSG)&m->u.ApiMessageData;
  201. HANDLE Thread;
  202. NTSTATUS Status;
  203. PCSR_PROCESS Process;
  204. PCSR_THREAD t;
  205. t = CSR_SERVER_QUERYCLIENTTHREAD();
  206. Process = t->Process;
  207. if (Process->ClientId.UniqueProcess != a->ClientId.UniqueProcess) {
  208. if ( a->ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess ) {
  209. return STATUS_SUCCESS;
  210. }
  211. Status = CsrLockProcessByClientId( a->ClientId.UniqueProcess,
  212. &Process
  213. );
  214. if (!NT_SUCCESS( Status )) {
  215. return( Status );
  216. }
  217. }
  218. //
  219. // Get handles to the thread local to the
  220. // Windows server.
  221. //
  222. Status = NtDuplicateObject(
  223. t->Process->ProcessHandle,
  224. a->ThreadHandle,
  225. NtCurrentProcess(),
  226. &Thread,
  227. 0L,
  228. 0L,
  229. DUPLICATE_SAME_ACCESS
  230. );
  231. if ( NT_SUCCESS(Status) ) {
  232. Status = CsrCreateThread(
  233. Process,
  234. Thread,
  235. &a->ClientId,
  236. TRUE
  237. );
  238. if (!NT_SUCCESS(Status)) {
  239. NtClose(Thread);
  240. }
  241. }
  242. if (Process != t->Process) {
  243. CsrUnlockProcess( Process );
  244. }
  245. return( (ULONG)Status );
  246. ReplyStatus; // get rid of unreferenced parameter warning message
  247. }
  248. ULONG
  249. BaseSrvRegisterThread(
  250. IN OUT PCSR_API_MSG m,
  251. IN OUT PCSR_REPLY_STATUS ReplyStatus
  252. )
  253. {
  254. PBASE_CREATETHREAD_MSG a = (PBASE_CREATETHREAD_MSG)&m->u.ApiMessageData;
  255. HANDLE Thread;
  256. NTSTATUS Status;
  257. PCSR_PROCESS Process;
  258. PCSR_THREAD CsrThread, ExistingThread;
  259. OBJECT_ATTRIBUTES NullAttributes;
  260. //
  261. // We assume the following:
  262. //
  263. // We are called via a LPC_DATAGRAM since this is the only way
  264. // that CSR will let the call go through. (csr requires
  265. // LPC_REQUEST to be sent only by threads in its list). This
  266. // means that CSR_SERVER_QUERYCLIENTTHREAD(); does not return a
  267. // valid value.
  268. Status = CsrLockProcessByClientId( a->ClientId.UniqueProcess,
  269. &Process
  270. );
  271. if (!NT_SUCCESS( Status )) {
  272. return( Status );
  273. }
  274. //
  275. // Get handle to the thread local to the
  276. // Windows server. Since this is called as a
  277. // LPC_DATAGRAM message, the thread handle is
  278. // not passed in the message, but instead the
  279. // calling thread is opened
  280. //
  281. InitializeObjectAttributes( &NullAttributes, NULL, 0, NULL, NULL );
  282. Status = NtOpenThread(&Thread,
  283. THREAD_ALL_ACCESS,
  284. &NullAttributes,
  285. &a->ClientId);
  286. if ( NT_SUCCESS(Status) ) {
  287. Status = CsrCreateThread(
  288. Process,
  289. Thread,
  290. &a->ClientId,
  291. FALSE
  292. );
  293. if (!NT_SUCCESS(Status)) {
  294. NtClose(Thread);
  295. }
  296. }
  297. CsrUnlockProcess( Process );
  298. return( (ULONG)Status );
  299. ReplyStatus; // get rid of unreferenced parameter warning message
  300. }
  301. EXCEPTION_DISPOSITION
  302. FatalExceptionFilter(
  303. struct _EXCEPTION_POINTERS *ExceptionInfo
  304. )
  305. {
  306. DbgPrint("CSRSRV: Fatal Server Side Exception. Exception Info %lx\n",
  307. ExceptionInfo
  308. );
  309. DbgBreakPoint();
  310. return EXCEPTION_EXECUTE_HANDLER;
  311. }
  312. ULONG
  313. BaseSrvExitProcess(
  314. IN OUT PCSR_API_MSG m,
  315. IN OUT PCSR_REPLY_STATUS ReplyStatus
  316. )
  317. {
  318. PBASE_EXITPROCESS_MSG a = (PBASE_EXITPROCESS_MSG)&m->u.ApiMessageData;
  319. PCSR_THREAD t;
  320. ULONG rc = (ULONG)STATUS_ACCESS_DENIED;
  321. t = CSR_SERVER_QUERYCLIENTTHREAD();
  322. try {
  323. *ReplyStatus = CsrClientDied;
  324. rc = (ULONG)CsrDestroyProcess( &t->ClientId, (NTSTATUS)a->uExitCode );
  325. }
  326. except(FatalExceptionFilter( GetExceptionInformation() )) {
  327. DbgBreakPoint();
  328. }
  329. return rc;
  330. }
  331. ULONG
  332. BaseSrvGetTempFile(
  333. IN OUT PCSR_API_MSG m,
  334. IN OUT PCSR_REPLY_STATUS ReplyStatus
  335. )
  336. {
  337. PBASE_GETTEMPFILE_MSG a = (PBASE_GETTEMPFILE_MSG)&m->u.ApiMessageData;
  338. BaseSrvGetTempFileUnique++;
  339. a->uUnique = BaseSrvGetTempFileUnique;
  340. return( (ULONG)a->uUnique & 0xffff );
  341. ReplyStatus; // get rid of unreferenced parameter warning message
  342. }
  343. ULONG
  344. BaseSrvDebugProcess(
  345. IN OUT PCSR_API_MSG m,
  346. IN OUT PCSR_REPLY_STATUS ReplyStatus
  347. )
  348. {
  349. return STATUS_UNSUCCESSFUL;
  350. }
  351. ULONG
  352. BaseSrvDebugProcessStop(
  353. IN OUT PCSR_API_MSG m,
  354. IN OUT PCSR_REPLY_STATUS ReplyStatus
  355. )
  356. {
  357. return STATUS_UNSUCCESSFUL;
  358. }
  359. ULONG
  360. BaseSrvSetProcessShutdownParam(
  361. IN OUT PCSR_API_MSG m,
  362. IN OUT PCSR_REPLY_STATUS ReplyStatus
  363. )
  364. {
  365. PCSR_PROCESS p;
  366. PBASE_SHUTDOWNPARAM_MSG a = (PBASE_SHUTDOWNPARAM_MSG)&m->u.ApiMessageData;
  367. p = CSR_SERVER_QUERYCLIENTTHREAD()->Process;
  368. if (a->ShutdownFlags & (~(SHUTDOWN_NORETRY))) {
  369. return !STATUS_SUCCESS;
  370. }
  371. p->ShutdownLevel = a->ShutdownLevel;
  372. p->ShutdownFlags = a->ShutdownFlags;
  373. return STATUS_SUCCESS;
  374. ReplyStatus;
  375. }
  376. ULONG
  377. BaseSrvGetProcessShutdownParam(
  378. IN OUT PCSR_API_MSG m,
  379. IN OUT PCSR_REPLY_STATUS ReplyStatus
  380. )
  381. {
  382. PCSR_PROCESS p;
  383. PBASE_SHUTDOWNPARAM_MSG a = (PBASE_SHUTDOWNPARAM_MSG)&m->u.ApiMessageData;
  384. p = CSR_SERVER_QUERYCLIENTTHREAD()->Process;
  385. a->ShutdownLevel = p->ShutdownLevel;
  386. a->ShutdownFlags = p->ShutdownFlags & SHUTDOWN_NORETRY;
  387. return STATUS_SUCCESS;
  388. ReplyStatus;
  389. }