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.

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