branch update for HEAD-2003050101
[reactos.git] / subsys / csrss / api / process.c
1 /* $Id$
2  *
3  * reactos/subsys/csrss/api/process.c
4  *
5  * "\windows\ApiPort" port process management functions
6  *
7  * ReactOS Operating System
8  */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ddk/ntddk.h>
13
14 #include <csrss/csrss.h>
15 #include <ntdll/rtl.h>
16 #include "api.h"
17
18 #define NDEBUG
19 #include <debug.h>
20
21 BOOL STDCALL W32kCleanupForProcess( INT Process );
22
23 #define LOCK   RtlEnterCriticalSection(&ProcessDataLock)
24 #define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
25
26 /* GLOBALS *******************************************************************/
27
28 static ULONG NrProcess;
29 static PCSRSS_PROCESS_DATA ProcessData[256];
30 extern CRITICAL_SECTION ActiveConsoleLock;
31 CRITICAL_SECTION ProcessDataLock;
32
33 /* FUNCTIONS *****************************************************************/
34
35 VOID STDCALL CsrInitProcessData(VOID)
36 {
37    RtlZeroMemory (ProcessData, sizeof ProcessData);
38    NrProcess = sizeof ProcessData / sizeof ProcessData[0];
39    RtlInitializeCriticalSection( &ProcessDataLock );
40 }
41
42 PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(ULONG ProcessId)
43 {
44    ULONG i;
45    ULONG hash;
46    PCSRSS_PROCESS_DATA pProcessData;
47
48    hash = ProcessId % (sizeof(ProcessData) / sizeof(*ProcessData));
49    
50    LOCK;
51
52    pProcessData = ProcessData[hash];
53
54    while (pProcessData && pProcessData->ProcessId != ProcessId)
55    {
56       pProcessData = pProcessData->next;
57    }
58    UNLOCK;
59    return pProcessData;
60 }
61
62 PCSRSS_PROCESS_DATA STDCALL CsrCreateProcessData(ULONG ProcessId)
63 {
64    ULONG i;
65    ULONG hash;
66    PCSRSS_PROCESS_DATA pProcessData;
67
68    hash = ProcessId % (sizeof(ProcessData) / sizeof(*ProcessData));
69    
70    LOCK;
71
72    pProcessData = ProcessData[hash];
73
74    while (pProcessData && pProcessData->ProcessId != ProcessId)
75    {
76       pProcessData = pProcessData->next;
77    }
78    if (pProcessData == NULL)
79    {
80       pProcessData = RtlAllocateHeap(CsrssApiHeap,
81                                      HEAP_ZERO_MEMORY,
82                                      sizeof(CSRSS_PROCESS_DATA));
83       if (pProcessData)
84       {
85          pProcessData->ProcessId = ProcessId;
86          pProcessData->next = ProcessData[hash];
87          ProcessData[hash] = pProcessData;
88       }
89    }
90    else
91    {
92       DPRINT("Process data for pid %d already exist\n", ProcessId);
93    }
94    UNLOCK;
95    if (pProcessData == NULL)
96    {
97       DbgPrint("CSR: CsrGetProcessData() failed\n");
98    }
99    return pProcessData;
100 }
101
102 NTSTATUS STDCALL CsrFreeProcessData(ULONG Pid)
103 {
104    ULONG hash;
105    int c;
106    PCSRSS_PROCESS_DATA pProcessData, pPrevProcessData = NULL;
107    
108    hash = Pid % (sizeof(ProcessData) / sizeof(*ProcessData));
109    
110    LOCK;
111
112    pProcessData = ProcessData[hash];
113
114    while (pProcessData && pProcessData->ProcessId != Pid)
115    {
116       pPrevProcessData = pProcessData;
117       pProcessData = pProcessData->next;
118    }
119
120    if (pProcessData)
121    {
122       //DbgPrint("CsrFreeProcessData pid: %d\n", Pid);
123       W32kCleanupForProcess(Pid);  //should check if win32k process
124       if (pProcessData->HandleTable)
125       {
126          for( c = 0; c < pProcessData->HandleTableSize; c++ )
127          {
128             if( pProcessData->HandleTable[c] )
129             {
130                CsrReleaseObject( pProcessData, (HANDLE)((c + 1) << 2) );
131             }
132          }
133          RtlFreeHeap( CsrssApiHeap, 0, pProcessData->HandleTable );
134       }
135       if( pProcessData->Console )
136       {
137          if( InterlockedDecrement( &(pProcessData->Console->Header.ReferenceCount) ) == 0 )
138          {
139             CsrDeleteConsole( pProcessData->Console );
140          }
141       }
142       if (pProcessData->CsrSectionViewBase)
143       {
144          NtUnmapViewOfSection(NtCurrentProcess(), pProcessData->CsrSectionViewBase);
145       }
146       if (pPrevProcessData)
147       {
148          pPrevProcessData->next = pProcessData->next;
149       }
150       else
151       {
152          ProcessData[hash] = pProcessData->next;
153       }
154
155       RtlFreeHeap( CsrssApiHeap, 0, pProcessData );
156       UNLOCK;
157       return STATUS_SUCCESS;
158    }
159    UNLOCK;
160    return STATUS_INVALID_PARAMETER;
161 }
162
163
164 /**********************************************************************
165  *      CSRSS API
166  *********************************************************************/
167
168 CSR_API(CsrCreateProcess)
169 {
170    PCSRSS_PROCESS_DATA NewProcessData;
171    NTSTATUS Status;
172    HANDLE Process;
173
174    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
175      sizeof(LPC_MESSAGE);
176    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
177
178    NewProcessData = CsrCreateProcessData(Request->Data.CreateProcessRequest.NewProcessId);
179    if (NewProcessData == NULL)
180      {
181         Reply->Status = STATUS_NO_MEMORY;
182         return(STATUS_NO_MEMORY);
183      }
184
185    /* Set default shutdown parameters */
186    NewProcessData->ShutdownLevel = 0x280;
187    NewProcessData->ShutdownFlags = 0;
188
189    if (Request->Data.CreateProcessRequest.Flags & DETACHED_PROCESS)
190      {
191         NewProcessData->Console = NULL;
192      }
193    else if (Request->Data.CreateProcessRequest.Flags & CREATE_NEW_CONSOLE)
194      {
195         PCSRSS_CONSOLE Console;
196
197         Console = RtlAllocateHeap(CsrssApiHeap,
198                                   HEAP_ZERO_MEMORY,
199                                   sizeof(CSRSS_CONSOLE));
200         Status = CsrInitConsole(Console);
201         if( !NT_SUCCESS( Status ) )
202           {
203             CsrFreeProcessData( NewProcessData->ProcessId );
204             Reply->Status = Status;
205             return Status;
206           }
207         NewProcessData->Console = Console;
208         Console->Header.ReferenceCount++;
209      }
210    else
211      {
212         NewProcessData->Console = ProcessData->Console;
213         InterlockedIncrement( &(ProcessData->Console->Header.ReferenceCount) );
214      }
215
216    if( NewProcessData->Console )
217      {
218        CLIENT_ID ClientId;
219        CsrInsertObject(NewProcessData,
220                        &Reply->Data.CreateProcessReply.InputHandle,
221                        (Object_t *)NewProcessData->Console);
222        RtlEnterCriticalSection( &ActiveConsoleLock );
223        CsrInsertObject( NewProcessData,
224           &Reply->Data.CreateProcessReply.OutputHandle,
225           &(NewProcessData->Console->ActiveBuffer->Header) );
226
227        RtlLeaveCriticalSection( &ActiveConsoleLock );
228        ClientId.UniqueProcess = (HANDLE)NewProcessData->ProcessId;
229        Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
230        if( !NT_SUCCESS( Status ) )
231          {
232            DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" );
233            InterlockedDecrement( &(NewProcessData->Console->Header.ReferenceCount) );
234            CsrFreeProcessData( NewProcessData->ProcessId );
235            Reply->Status = Status;
236            return Status;
237          }
238        Status = NtDuplicateObject( NtCurrentProcess(), NewProcessData->Console->ActiveEvent, Process, &NewProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0 );
239        if( !NT_SUCCESS( Status ) )
240          {
241            DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status );
242            NtClose( Process );
243            InterlockedDecrement( &(NewProcessData->Console->Header.ReferenceCount) );
244            CsrFreeProcessData( NewProcessData->ProcessId );
245            Reply->Status = Status;
246            return Status;
247          }
248        NtClose( Process );
249      }
250    else Reply->Data.CreateProcessReply.OutputHandle = Reply->Data.CreateProcessReply.InputHandle = INVALID_HANDLE_VALUE;
251
252    Reply->Status = STATUS_SUCCESS;
253    return(STATUS_SUCCESS);
254 }
255
256 CSR_API(CsrTerminateProcess)
257 {
258    NTSTATUS Status;
259
260    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY)
261       - sizeof(LPC_MESSAGE);
262    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY);
263
264    if (ProcessData == NULL)
265    {
266       return(Reply->Status = STATUS_INVALID_PARAMETER);
267    }
268
269    Status = CsrFreeProcessData(ProcessData->ProcessId);
270
271    Reply->Status = Status;
272    return Status;
273 }
274
275 CSR_API(CsrConnectProcess)
276 {
277    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
278    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
279      sizeof(LPC_MESSAGE);
280
281    Reply->Status = STATUS_SUCCESS;
282
283    return(STATUS_SUCCESS);
284 }
285
286 CSR_API(CsrGetShutdownParameters)
287 {
288   Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
289   Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
290     sizeof(LPC_MESSAGE);
291
292   if (ProcessData == NULL)
293   {
294      return(Reply->Status = STATUS_INVALID_PARAMETER);
295   }
296   
297   Reply->Data.GetShutdownParametersReply.Level = ProcessData->ShutdownLevel;
298   Reply->Data.GetShutdownParametersReply.Flags = ProcessData->ShutdownFlags;
299
300   Reply->Status = STATUS_SUCCESS;
301
302   return(STATUS_SUCCESS);
303 }
304
305 CSR_API(CsrSetShutdownParameters)
306 {
307   Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
308   Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
309     sizeof(LPC_MESSAGE);
310
311   if (ProcessData == NULL)
312   {
313      return(Reply->Status = STATUS_INVALID_PARAMETER);
314   }
315   
316   ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
317   ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
318
319   Reply->Status = STATUS_SUCCESS;
320
321   return(STATUS_SUCCESS);
322 }
323
324 CSR_API(CsrGetInputHandle)
325 {
326    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
327    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
328
329    if (ProcessData == NULL)
330    {
331       Reply->Data.GetInputHandleReply.InputHandle = INVALID_HANDLE_VALUE;
332       Reply->Status = STATUS_INVALID_PARAMETER;
333    }
334    else if (ProcessData->Console)
335    {
336       Reply->Status = CsrInsertObject(ProcessData,
337                                       &Reply->Data.GetInputHandleReply.InputHandle,
338                                       (Object_t *)ProcessData->Console);
339    }
340    else
341    {
342       Reply->Data.GetInputHandleReply.InputHandle = INVALID_HANDLE_VALUE;
343       Reply->Status = STATUS_SUCCESS;
344    }
345
346    return Reply->Status;
347 }
348
349 CSR_API(CsrGetOutputHandle)
350 {
351    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
352    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
353
354    if (ProcessData == NULL)
355    {
356       Reply->Data.GetOutputHandleReply.OutputHandle = INVALID_HANDLE_VALUE;
357       Reply->Status = STATUS_INVALID_PARAMETER;
358    }
359    else if (ProcessData->Console)
360    {
361       RtlEnterCriticalSection( &ActiveConsoleLock );
362       Reply->Status = CsrInsertObject(ProcessData,
363                                       &Reply->Data.GetOutputHandleReply.OutputHandle,
364                                       &(ProcessData->Console->ActiveBuffer->Header));
365       RtlLeaveCriticalSection( &ActiveConsoleLock );
366    }
367    else
368    {
369       Reply->Data.GetOutputHandleReply.OutputHandle = INVALID_HANDLE_VALUE;
370       Reply->Status = STATUS_SUCCESS;
371    }
372
373    return Reply->Status;
374 }
375
376 CSR_API(CsrCloseHandle)
377 {
378    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
379    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
380
381    if (ProcessData == NULL)
382    {
383       Reply->Status = STATUS_INVALID_PARAMETER;
384    }
385    else
386    {
387       Reply->Status = CsrReleaseObject(ProcessData, Request->Data.CloseHandleRequest.Handle);
388    }
389    return Reply->Status;
390 }
391
392 CSR_API(CsrVerifyHandle)
393 {
394    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
395    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
396
397    Reply->Status = CsrVerifyObject(ProcessData, Request->Data.VerifyHandleRequest.Handle);
398    if (!NT_SUCCESS(Reply->Status))
399    {
400       DPRINT("CsrVerifyObject failed, status=%x\n", Reply->Status);
401    }
402
403    return Reply->Status;
404 }
405
406 CSR_API(CsrDuplicateHandle)
407 {
408    Object_t *Object;
409
410    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
411    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
412
413    ProcessData = CsrGetProcessData(Request->Data.DuplicateHandleRequest.ProcessId);
414    Reply->Status = CsrGetObject(ProcessData, Request->Data.DuplicateHandleRequest.Handle, &Object);
415    if (!NT_SUCCESS(Reply->Status))
416    {
417       DPRINT("CsrGetObject failed, status=%x\n", Reply->Status);
418    }
419    else
420    {
421       if (Object->Type == CSRSS_CONSOLE_MAGIC)
422       {
423          Reply->Status = CsrInsertObject(ProcessData,
424                                          &Reply->Data.DuplicateHandleReply.Handle,
425                                          (Object_t *)ProcessData->Console);
426       }
427       else if (Object->Type == CSRSS_SCREEN_BUFFER_MAGIC)
428       {
429          RtlEnterCriticalSection( &ActiveConsoleLock );
430          Reply->Status = CsrInsertObject(ProcessData,
431                                          &Reply->Data.DuplicateHandleReply.Handle,
432                                          &(ProcessData->Console->ActiveBuffer->Header));
433          RtlLeaveCriticalSection( &ActiveConsoleLock );
434       }
435       else
436       {
437          Reply->Status = STATUS_INVALID_PARAMETER;
438       }
439    }
440    return Reply->Status;
441 }
442
443 /* EOF */