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