46c4ce92dcd7958fde3fd4f148f234450a7232ee
[reactos.git] / subsystems / win32 / csrsrv / api / process.c
1 /*
2 * subsystems/win32/csrss/csrsrv/api/process.c
3 *
4 * "\windows\ApiPort" port process management functions
5 *
6 * ReactOS Operating System
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <srv.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 extern NTSTATUS CallProcessCreated(PCSR_PROCESS, PCSR_PROCESS);
17
18 /* GLOBALS *******************************************************************/
19
20 /* FUNCTIONS *****************************************************************/
21
22 /**********************************************************************
23 * CSRSS API
24 *********************************************************************/
25
26 /***
27 *** Some APIs from here will go to basesrv.dll, some others to winsrv.dll.
28 *** Furthermore, this structure uses the old definition of APIs list.
29 *** The new one is in fact three arrays, one of APIs pointers, one other of
30 *** corresponding indexes, and the third one of names (not very efficient...).
31 ***/
32
33 CSR_API(BaseSrvCreateProcess)
34 {
35 NTSTATUS Status;
36 HANDLE ProcessHandle, ThreadHandle;
37 PCSR_THREAD CsrThread;
38 PCSR_PROCESS Process, NewProcess;
39 ULONG Flags, VdmPower = 0, DebugFlags = 0;
40
41 /* Get the current client thread */
42 CsrThread = CsrGetClientThread();
43 ASSERT(CsrThread != NULL);
44
45 Process = CsrThread->Process;
46
47 /* Extract the flags out of the process handle */
48 Flags = (ULONG_PTR)ApiMessage->Data.CreateProcessRequest.ProcessHandle & 3;
49 ApiMessage->Data.CreateProcessRequest.ProcessHandle = (HANDLE)((ULONG_PTR)ApiMessage->Data.CreateProcessRequest.ProcessHandle & ~3);
50
51 /* Duplicate the process handle */
52 Status = NtDuplicateObject(Process->ProcessHandle,
53 ApiMessage->Data.CreateProcessRequest.ProcessHandle,
54 NtCurrentProcess(),
55 &ProcessHandle,
56 0,
57 0,
58 DUPLICATE_SAME_ACCESS);
59 if (!NT_SUCCESS(Status))
60 {
61 DPRINT1("Failed to duplicate process handle\n");
62 return Status;
63 }
64
65 /* Duplicate the thread handle */
66 Status = NtDuplicateObject(Process->ProcessHandle,
67 ApiMessage->Data.CreateProcessRequest.ThreadHandle,
68 NtCurrentProcess(),
69 &ThreadHandle,
70 0,
71 0,
72 DUPLICATE_SAME_ACCESS);
73 if (!NT_SUCCESS(Status))
74 {
75 DPRINT1("Failed to duplicate process handle\n");
76 NtClose(ProcessHandle);
77 return Status;
78 }
79
80 /* See if this is a VDM process */
81 if (VdmPower)
82 {
83 /* Request VDM powers */
84 Status = NtSetInformationProcess(ProcessHandle,
85 ProcessWx86Information,
86 &VdmPower,
87 sizeof(VdmPower));
88 if (!NT_SUCCESS(Status))
89 {
90 DPRINT1("Failed to get VDM powers\n");
91 NtClose(ProcessHandle);
92 NtClose(ThreadHandle);
93 return Status;
94 }
95 }
96
97 /* Convert some flags. FIXME: More need conversion */
98 if (ApiMessage->Data.CreateProcessRequest.CreationFlags & CREATE_NEW_PROCESS_GROUP)
99 {
100 DebugFlags |= CsrProcessCreateNewGroup;
101 }
102
103 /* FIXME: SxS Stuff */
104
105 /* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */
106 Status = CsrCreateProcess(ProcessHandle,
107 ThreadHandle,
108 &ApiMessage->Data.CreateProcessRequest.ClientId,
109 Process->NtSession,
110 DebugFlags,
111 NULL);
112 if (Status == STATUS_THREAD_IS_TERMINATING)
113 {
114 DPRINT1("Thread already dead\n");
115 return Status;
116 }
117
118 /* Check for other failures */
119 if (!NT_SUCCESS(Status))
120 {
121 DPRINT1("Failed to create process/thread structures: %lx\n", Status);
122 return Status;
123 }
124
125 /* FIXME: Should notify user32 */
126
127 /* FIXME: VDM vodoo */
128
129 /* ReactOS Compatibility */
130 Status = CsrLockProcessByClientId(ApiMessage->Data.CreateProcessRequest.ClientId.UniqueProcess, &NewProcess);
131 ASSERT(Status == STATUS_SUCCESS);
132 if (!(ApiMessage->Data.CreateProcessRequest.CreationFlags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)))
133 {
134 NewProcess->ParentConsole = Process->Console;
135 NewProcess->bInheritHandles = ApiMessage->Data.CreateProcessRequest.bInheritHandles;
136 }
137 RtlInitializeCriticalSection(&NewProcess->HandleTableLock);
138 CallProcessCreated(Process, NewProcess);
139 CsrUnlockProcess(NewProcess);
140
141 /* Return the result of this operation */
142 return Status;
143 }
144
145 CSR_API(BaseSrvCreateThread)
146 {
147 PCSR_THREAD CurrentThread;
148 HANDLE ThreadHandle;
149 NTSTATUS Status;
150 PCSR_PROCESS CsrProcess;
151
152 /* Get the current CSR thread */
153 CurrentThread = CsrGetClientThread();
154 if (!CurrentThread)
155 {
156 DPRINT1("Server Thread TID: [%lx.%lx]\n",
157 ApiMessage->Data.CreateThreadRequest.ClientId.UniqueProcess,
158 ApiMessage->Data.CreateThreadRequest.ClientId.UniqueThread);
159 return STATUS_SUCCESS; // server-to-server
160 }
161
162 /* Get the CSR Process for this request */
163 CsrProcess = CurrentThread->Process;
164 if (CsrProcess->ClientId.UniqueProcess !=
165 ApiMessage->Data.CreateThreadRequest.ClientId.UniqueProcess)
166 {
167 /* This is a remote thread request -- is it within the server itself? */
168 if (ApiMessage->Data.CreateThreadRequest.ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess)
169 {
170 /* Accept this without any further work */
171 return STATUS_SUCCESS;
172 }
173
174 /* Get the real CSR Process for the remote thread's process */
175 Status = CsrLockProcessByClientId(ApiMessage->Data.CreateThreadRequest.ClientId.UniqueProcess,
176 &CsrProcess);
177 if (!NT_SUCCESS(Status)) return Status;
178 }
179
180 /* Duplicate the thread handle so we can own it */
181 Status = NtDuplicateObject(CurrentThread->Process->ProcessHandle,
182 ApiMessage->Data.CreateThreadRequest.ThreadHandle,
183 NtCurrentProcess(),
184 &ThreadHandle,
185 0,
186 0,
187 DUPLICATE_SAME_ACCESS);
188 if (NT_SUCCESS(Status))
189 {
190 /* Call CSRSRV to tell it about the new thread */
191 Status = CsrCreateThread(CsrProcess,
192 ThreadHandle,
193 &ApiMessage->Data.CreateThreadRequest.ClientId);
194 }
195
196 /* Unlock the process and return */
197 if (CsrProcess != CurrentThread->Process) CsrUnlockProcess(CsrProcess);
198 return Status;
199 }
200
201 CSR_API(BaseSrvExitProcess)
202 {
203 PCSR_THREAD CsrThread = CsrGetClientThread();
204 ASSERT(CsrThread != NULL);
205
206 /* Set magic flag so we don't reply this message back */
207 ApiMessage->ApiNumber = 0xBABE;
208
209 /* Remove the CSR_THREADs and CSR_PROCESS */
210 return CsrDestroyProcess(&CsrThread->ClientId,
211 (NTSTATUS)ApiMessage->Data.TerminateProcessRequest.uExitCode);
212 }
213
214 CSR_API(BaseSrvGetProcessShutdownParam)
215 {
216 PCSR_THREAD CsrThread = CsrGetClientThread();
217 ASSERT(CsrThread);
218
219 ApiMessage->Data.GetShutdownParametersRequest.Level = CsrThread->Process->ShutdownLevel;
220 ApiMessage->Data.GetShutdownParametersRequest.Flags = CsrThread->Process->ShutdownFlags;
221
222 return STATUS_SUCCESS;
223 }
224
225 CSR_API(BaseSrvSetProcessShutdownParam)
226 {
227 PCSR_THREAD CsrThread = CsrGetClientThread();
228 ASSERT(CsrThread);
229
230 CsrThread->Process->ShutdownLevel = ApiMessage->Data.SetShutdownParametersRequest.Level;
231 CsrThread->Process->ShutdownFlags = ApiMessage->Data.SetShutdownParametersRequest.Flags;
232
233 return STATUS_SUCCESS;
234 }
235
236 /* EOF */