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