xref: /reactos/subsystems/win/basesrv/proc.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Base API Server DLL
4  * FILE:            subsystems/win/basesrv/proc.c
5  * PURPOSE:         Process and Thread Management
6  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "basesrv.h"
12 #include "vdm.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS ********************************************************************/
18 
19 /* User notification procedure to be called when a process is created */
20 static BASE_PROCESS_CREATE_NOTIFY_ROUTINE UserNotifyProcessCreate = NULL;
21 
22 /* PUBLIC SERVER APIS *********************************************************/
23 
CSR_API(BaseSrvDebugProcess)24 CSR_API(BaseSrvDebugProcess)
25 {
26     /* Deprecated */
27     return STATUS_UNSUCCESSFUL;
28 }
29 
CSR_API(BaseSrvRegisterThread)30 CSR_API(BaseSrvRegisterThread)
31 {
32     DPRINT1("%s not yet implemented\n", __FUNCTION__);
33     return STATUS_NOT_IMPLEMENTED;
34 }
35 
CSR_API(BaseSrvSxsCreateActivationContext)36 CSR_API(BaseSrvSxsCreateActivationContext)
37 {
38     DPRINT1("%s not yet implemented\n", __FUNCTION__);
39     return STATUS_NOT_IMPLEMENTED;
40 }
41 
CSR_API(BaseSrvSetTermsrvAppInstallMode)42 CSR_API(BaseSrvSetTermsrvAppInstallMode)
43 {
44     DPRINT1("%s not yet implemented\n", __FUNCTION__);
45     return STATUS_NOT_IMPLEMENTED;
46 }
47 
CSR_API(BaseSrvSetTermsrvClientTimeZone)48 CSR_API(BaseSrvSetTermsrvClientTimeZone)
49 {
50     DPRINT1("%s not yet implemented\n", __FUNCTION__);
51     return STATUS_NOT_IMPLEMENTED;
52 }
53 
CSR_API(BaseSrvGetTempFile)54 CSR_API(BaseSrvGetTempFile)
55 {
56     static UINT BaseGetTempFileUnique = 0;
57     PBASE_GET_TEMP_FILE GetTempFile = &((PBASE_API_MESSAGE)ApiMessage)->Data.GetTempFileRequest;
58 
59     /* Return 16-bits ID */
60     GetTempFile->UniqueID = (++BaseGetTempFileUnique & 0xFFFF);
61 
62     DPRINT("Returning: %u\n", GetTempFile->UniqueID);
63 
64     return GetTempFile->UniqueID;
65 }
66 
CSR_API(BaseSrvCreateProcess)67 CSR_API(BaseSrvCreateProcess)
68 {
69     NTSTATUS Status;
70     PBASE_CREATE_PROCESS CreateProcessRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CreateProcessRequest;
71     HANDLE ProcessHandle, ThreadHandle;
72     PCSR_THREAD CsrThread;
73     PCSR_PROCESS Process;
74     ULONG Flags = 0, DebugFlags = 0, VdmPower = 0;
75 
76     /* Get the current client thread */
77     CsrThread = CsrGetClientThread();
78     ASSERT(CsrThread != NULL);
79 
80     Process = CsrThread->Process;
81 
82     /* Extract the flags out of the process handle */
83     Flags = (ULONG_PTR)CreateProcessRequest->ProcessHandle & 3;
84     CreateProcessRequest->ProcessHandle = (HANDLE)((ULONG_PTR)CreateProcessRequest->ProcessHandle & ~3);
85 
86     /* Some things should be done if this is a VDM process */
87     if (CreateProcessRequest->VdmBinaryType)
88     {
89         /* We need to set the VDM power later on */
90         VdmPower = 1;
91     }
92 
93     /* Duplicate the process handle */
94     Status = NtDuplicateObject(Process->ProcessHandle,
95                                CreateProcessRequest->ProcessHandle,
96                                NtCurrentProcess(),
97                                &ProcessHandle,
98                                0,
99                                0,
100                                DUPLICATE_SAME_ACCESS);
101     if (!NT_SUCCESS(Status))
102     {
103         DPRINT1("Failed to duplicate process handle: %lx\n", Status);
104         return Status;
105     }
106 
107     /* Duplicate the thread handle */
108     Status = NtDuplicateObject(Process->ProcessHandle,
109                                CreateProcessRequest->ThreadHandle,
110                                NtCurrentProcess(),
111                                &ThreadHandle,
112                                0,
113                                0,
114                                DUPLICATE_SAME_ACCESS);
115     if (!NT_SUCCESS(Status))
116     {
117         DPRINT1("Failed to duplicate thread handle: %lx\n", Status);
118         NtClose(ProcessHandle);
119         return Status;
120     }
121 
122     /* If this is a VDM process, request VDM power */
123     if (VdmPower)
124     {
125         Status = NtSetInformationProcess(ProcessHandle,
126                                          ProcessWx86Information,
127                                          &VdmPower,
128                                          sizeof(VdmPower));
129         if (!NT_SUCCESS(Status))
130         {
131             DPRINT1("Failed to get VDM powers\n");
132             NtClose(ProcessHandle);
133             NtClose(ThreadHandle);
134             return Status;
135         }
136     }
137 
138     /* Flags conversion. FIXME: More need conversion */
139     if (CreateProcessRequest->CreationFlags & CREATE_NEW_PROCESS_GROUP)
140     {
141         DebugFlags |= CsrProcessCreateNewGroup;
142     }
143     if ((Flags & 2) == 0)
144     {
145         /* We are launching a console process */
146         DebugFlags |= CsrProcessIsConsoleApp;
147     }
148 
149     /* FIXME: SxS Stuff */
150 
151     /* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */
152     Status = CsrCreateProcess(ProcessHandle,
153                               ThreadHandle,
154                               &CreateProcessRequest->ClientId,
155                               Process->NtSession,
156                               DebugFlags,
157                               NULL);
158     if (Status == STATUS_THREAD_IS_TERMINATING)
159     {
160         DPRINT1("Thread already dead\n");
161 
162         /* Set the special reply value so we don't reply this message back */
163         *ReplyCode = CsrReplyDeadClient;
164 
165         return Status;
166     }
167 
168     /* Check for other failures */
169     if (!NT_SUCCESS(Status))
170     {
171         DPRINT1("Failed to create process/thread structures: %lx\n", Status);
172         return Status;
173     }
174 
175     /* Call the user notification procedure */
176     if (UserNotifyProcessCreate)
177     {
178         UserNotifyProcessCreate(CreateProcessRequest->ClientId.UniqueProcess,
179                                 Process->ClientId.UniqueThread,
180                                 0,
181                                 Flags);
182     }
183 
184     /* Check if this is a VDM process */
185     if (CreateProcessRequest->VdmBinaryType)
186     {
187         PVDM_CONSOLE_RECORD ConsoleRecord;
188 
189         if (CreateProcessRequest->VdmTask != 0)
190         {
191             /* Get the console record using the task ID */
192             Status = GetConsoleRecordBySessionId(CreateProcessRequest->VdmTask,
193                                                  &ConsoleRecord);
194         }
195         else
196         {
197             /* Get the console record using the console handle */
198             Status = BaseSrvGetConsoleRecord(CreateProcessRequest->hVDM,
199                                              &ConsoleRecord);
200         }
201 
202         /* Check if it failed */
203         if (!NT_SUCCESS(Status)) return Status;
204 
205         /* Store the process ID of the VDM in the console record */
206         ConsoleRecord->ProcessId = HandleToUlong(CreateProcessRequest->ClientId.UniqueProcess);
207     }
208 
209     /* Return the result of this operation */
210     return Status;
211 }
212 
CSR_API(BaseSrvCreateThread)213 CSR_API(BaseSrvCreateThread)
214 {
215     NTSTATUS Status;
216     PBASE_CREATE_THREAD CreateThreadRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CreateThreadRequest;
217     PCSR_THREAD CurrentThread;
218     HANDLE ThreadHandle;
219     PCSR_PROCESS CsrProcess;
220 
221     /* Get the current CSR thread */
222     CurrentThread = CsrGetClientThread();
223     if (!CurrentThread)
224     {
225         DPRINT1("Server Thread TID: [%lx.%lx]\n",
226                 CreateThreadRequest->ClientId.UniqueProcess,
227                 CreateThreadRequest->ClientId.UniqueThread);
228         return STATUS_SUCCESS; // server-to-server
229     }
230 
231     /* Get the CSR Process for this request */
232     CsrProcess = CurrentThread->Process;
233     if (CsrProcess->ClientId.UniqueProcess !=
234         CreateThreadRequest->ClientId.UniqueProcess)
235     {
236         /* This is a remote thread request -- is it within the server itself? */
237         if (CreateThreadRequest->ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess)
238         {
239             /* Accept this without any further work */
240             return STATUS_SUCCESS;
241         }
242 
243         /* Get the real CSR Process for the remote thread's process */
244         Status = CsrLockProcessByClientId(CreateThreadRequest->ClientId.UniqueProcess,
245                                           &CsrProcess);
246         if (!NT_SUCCESS(Status)) return Status;
247     }
248 
249     /* Duplicate the thread handle so we can own it */
250     Status = NtDuplicateObject(CurrentThread->Process->ProcessHandle,
251                                CreateThreadRequest->ThreadHandle,
252                                NtCurrentProcess(),
253                                &ThreadHandle,
254                                0,
255                                0,
256                                DUPLICATE_SAME_ACCESS);
257     if (NT_SUCCESS(Status))
258     {
259         /* Call CSRSRV to tell it about the new thread */
260         Status = CsrCreateThread(CsrProcess,
261                                  ThreadHandle,
262                                  &CreateThreadRequest->ClientId,
263                                  TRUE);
264     }
265 
266     /* Unlock the process and return */
267     if (CsrProcess != CurrentThread->Process) CsrUnlockProcess(CsrProcess);
268     return Status;
269 }
270 
CSR_API(BaseSrvExitProcess)271 CSR_API(BaseSrvExitProcess)
272 {
273     PCSR_THREAD CsrThread = CsrGetClientThread();
274     ASSERT(CsrThread != NULL);
275 
276     /* Set the special reply value so we don't reply this message back */
277     *ReplyCode = CsrReplyDeadClient;
278 
279     /* Remove the CSR_THREADs and CSR_PROCESS */
280     return CsrDestroyProcess(&CsrThread->ClientId,
281                              (NTSTATUS)((PBASE_API_MESSAGE)ApiMessage)->Data.ExitProcessRequest.uExitCode);
282 }
283 
CSR_API(BaseSrvGetProcessShutdownParam)284 CSR_API(BaseSrvGetProcessShutdownParam)
285 {
286     PBASE_GETSET_PROCESS_SHUTDOWN_PARAMS ShutdownParametersRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ShutdownParametersRequest;
287     PCSR_THREAD CsrThread = CsrGetClientThread();
288     ASSERT(CsrThread);
289 
290     ShutdownParametersRequest->ShutdownLevel = CsrThread->Process->ShutdownLevel;
291     /* Only SHUTDOWN_NORETRY flag is valid for this API. The other private flags are for CSRSRV/WINSRV only. */
292     ShutdownParametersRequest->ShutdownFlags = CsrThread->Process->ShutdownFlags & SHUTDOWN_NORETRY;
293 
294     return STATUS_SUCCESS;
295 }
296 
CSR_API(BaseSrvSetProcessShutdownParam)297 CSR_API(BaseSrvSetProcessShutdownParam)
298 {
299     PBASE_GETSET_PROCESS_SHUTDOWN_PARAMS ShutdownParametersRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ShutdownParametersRequest;
300     PCSR_THREAD CsrThread = CsrGetClientThread();
301     ASSERT(CsrThread);
302 
303     /* Only SHUTDOWN_NORETRY flag is valid for this API. The other private flags are for CSRSRV/WINSRV only. */
304     if (ShutdownParametersRequest->ShutdownFlags & ~SHUTDOWN_NORETRY)
305     {
306         /* If there were other flags specified, fail the call */
307         return STATUS_INVALID_PARAMETER;
308     }
309 
310     CsrThread->Process->ShutdownLevel = ShutdownParametersRequest->ShutdownLevel;
311     /* Notice that all the possible other private flags are reinitialized here */
312     CsrThread->Process->ShutdownFlags = ShutdownParametersRequest->ShutdownFlags;
313 
314     return STATUS_SUCCESS;
315 }
316 
317 /* PUBLIC API *****************************************************************/
318 
319 VOID
320 NTAPI
BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE ProcessCreateNotifyProc)321 BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE ProcessCreateNotifyProc)
322 {
323     /* Set the user notification procedure to be called when a process is created */
324     UserNotifyProcessCreate = ProcessCreateNotifyProc;
325 }
326 
327 /* EOF */
328