update for HEAD-2003021201
[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 BOOL STDCALL W32kCleanupForProcess( INT Process );
19
20 #define LOCK   RtlEnterCriticalSection(&ProcessDataLock)
21 #define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
22
23 /* GLOBALS *******************************************************************/
24
25 static ULONG NrProcess;
26 static PCSRSS_PROCESS_DATA ProcessData[256];
27 extern CRITICAL_SECTION ActiveConsoleLock;
28 CRITICAL_SECTION ProcessDataLock;
29
30 /* FUNCTIONS *****************************************************************/
31
32 VOID STDCALL CsrInitProcessData(VOID)
33 {
34    RtlZeroMemory (ProcessData, sizeof ProcessData);
35    NrProcess = sizeof ProcessData / sizeof ProcessData[0];
36    RtlInitializeCriticalSection( &ProcessDataLock );
37 }
38
39 PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(ULONG ProcessId)
40 {
41    ULONG i;
42    ULONG hash;
43    PCSRSS_PROCESS_DATA pProcessData;
44
45    hash = ProcessId % (sizeof(ProcessData) / sizeof(*ProcessData));
46    
47    LOCK;
48
49    pProcessData = ProcessData[hash];
50
51    while (pProcessData && pProcessData->ProcessId != ProcessId)
52    {
53       pProcessData = pProcessData->next;
54    }
55    if (pProcessData == NULL)
56    {
57       pProcessData = RtlAllocateHeap(CsrssApiHeap,
58                                      HEAP_ZERO_MEMORY,
59                                      sizeof(CSRSS_PROCESS_DATA));
60       if (pProcessData)
61       {
62          pProcessData->ProcessId = ProcessId;
63          pProcessData->next = ProcessData[hash];
64          ProcessData[hash] = pProcessData;
65       }
66    }
67    UNLOCK;
68    if (pProcessData == NULL)
69    {
70       DbgPrint("CSR: CsrGetProcessData() failed\n");
71    }
72    return pProcessData;
73 }
74
75 NTSTATUS STDCALL CsrFreeProcessData(ULONG Pid)
76 {
77    ULONG hash;
78    int c;
79    PCSRSS_PROCESS_DATA pProcessData, pPrevProcessData = NULL;
80    
81    hash = Pid % (sizeof(ProcessData) / sizeof(*ProcessData));
82    
83    LOCK;
84
85    pProcessData = ProcessData[hash];
86
87    while (pProcessData && pProcessData->ProcessId != Pid)
88    {
89       pPrevProcessData = pProcessData;
90       pProcessData = pProcessData->next;
91    }
92
93    if (pProcessData)
94    {
95       //DbgPrint("CsrFreeProcessData pid: %d\n", Pid);
96       W32kCleanupForProcess(Pid);  //should check if win32k process
97       if (pProcessData->HandleTable)
98       {
99          for( c = 0; c < pProcessData->HandleTableSize; c++ )
100          {
101             if( pProcessData->HandleTable[c] )
102             {
103                CsrReleaseObject( pProcessData, (HANDLE)((c + 1) << 2) );
104             }
105          }
106          RtlFreeHeap( CsrssApiHeap, 0, pProcessData->HandleTable );
107       }
108       if( pProcessData->Console )
109       {
110          if( InterlockedDecrement( &(pProcessData->Console->Header.ReferenceCount) ) == 0 )
111          {
112             CsrDeleteConsole( pProcessData->Console );
113          }
114       }
115       if (pProcessData->CsrSectionViewBase)
116       {
117          NtUnmapViewOfSection(NtCurrentProcess(), pProcessData->CsrSectionViewBase);
118       }
119       if (pPrevProcessData)
120       {
121          pPrevProcessData->next = pProcessData->next;
122       }
123       else
124       {
125          ProcessData[hash] = pProcessData->next;
126       }
127
128       RtlFreeHeap( CsrssApiHeap, 0, pProcessData );
129       UNLOCK;
130       return STATUS_SUCCESS;
131    }
132    UNLOCK;
133    return STATUS_INVALID_PARAMETER;
134 }
135
136
137 /**********************************************************************
138  *      CSRSS API
139  *********************************************************************/
140
141 CSR_API(CsrCreateProcess)
142 {
143    PCSRSS_PROCESS_DATA NewProcessData;
144    NTSTATUS Status;
145    HANDLE Process;
146
147    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
148      sizeof(LPC_MESSAGE);
149    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
150
151    NewProcessData = CsrGetProcessData(Request->Data.CreateProcessRequest.NewProcessId);
152    if (NewProcessData == NULL)
153      {
154         Reply->Status = STATUS_NO_MEMORY;
155         return(STATUS_NO_MEMORY);
156      }
157
158    /* Set default shutdown parameters */
159    NewProcessData->ShutdownLevel = 0x280;
160    NewProcessData->ShutdownFlags = 0;
161
162    if (Request->Data.CreateProcessRequest.Flags & DETACHED_PROCESS)
163      {
164         NewProcessData->Console = NULL;
165      }
166    else if (Request->Data.CreateProcessRequest.Flags & CREATE_NEW_CONSOLE)
167      {
168         PCSRSS_CONSOLE Console;
169
170         Console = RtlAllocateHeap(CsrssApiHeap,
171                                   HEAP_ZERO_MEMORY,
172                                   sizeof(CSRSS_CONSOLE));
173         Status = CsrInitConsole(Console);
174         if( !NT_SUCCESS( Status ) )
175           {
176             CsrFreeProcessData( NewProcessData->ProcessId );
177             Reply->Status = Status;
178             return Status;
179           }
180         NewProcessData->Console = Console;
181         Console->Header.ReferenceCount++;
182      }
183    else
184      {
185         NewProcessData->Console = ProcessData->Console;
186         InterlockedIncrement( &(ProcessData->Console->Header.ReferenceCount) );
187      }
188
189    if( NewProcessData->Console )
190      {
191        CLIENT_ID ClientId;
192        CsrInsertObject(NewProcessData,
193                        &Reply->Data.CreateProcessReply.InputHandle,
194                        (Object_t *)NewProcessData->Console);
195        RtlEnterCriticalSection( &ActiveConsoleLock );
196        CsrInsertObject( NewProcessData,
197           &Reply->Data.CreateProcessReply.OutputHandle,
198           &(NewProcessData->Console->ActiveBuffer->Header) );
199
200        RtlLeaveCriticalSection( &ActiveConsoleLock );
201        ClientId.UniqueProcess = (HANDLE)NewProcessData->ProcessId;
202        Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
203        if( !NT_SUCCESS( Status ) )
204          {
205            DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" );
206            InterlockedDecrement( &(NewProcessData->Console->Header.ReferenceCount) );
207            CsrFreeProcessData( NewProcessData->ProcessId );
208            Reply->Status = Status;
209            return Status;
210          }
211        Status = NtDuplicateObject( NtCurrentProcess(), NewProcessData->Console->ActiveEvent, Process, &NewProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0 );
212        if( !NT_SUCCESS( Status ) )
213          {
214            DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status );
215            NtClose( Process );
216            InterlockedDecrement( &(NewProcessData->Console->Header.ReferenceCount) );
217            CsrFreeProcessData( NewProcessData->ProcessId );
218            Reply->Status = Status;
219            return Status;
220          }
221        NtClose( Process );
222      }
223    else Reply->Data.CreateProcessReply.OutputHandle = Reply->Data.CreateProcessReply.InputHandle = INVALID_HANDLE_VALUE;
224
225    Reply->Status = STATUS_SUCCESS;
226    return(STATUS_SUCCESS);
227 }
228
229 CSR_API(CsrTerminateProcess)
230 {
231    NTSTATUS Status;
232
233    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY)
234       - sizeof(LPC_MESSAGE);
235    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY);
236
237    Status = CsrFreeProcessData(ProcessData->ProcessId);
238
239    Reply->Status = Status;
240    return Status;
241 }
242
243 CSR_API(CsrConnectProcess)
244 {
245    Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
246    Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
247      sizeof(LPC_MESSAGE);
248
249    Reply->Status = STATUS_SUCCESS;
250
251    return(STATUS_SUCCESS);
252 }
253
254 CSR_API(CsrGetShutdownParameters)
255 {
256   Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
257   Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
258     sizeof(LPC_MESSAGE);
259
260   Reply->Data.GetShutdownParametersReply.Level = ProcessData->ShutdownLevel;
261   Reply->Data.GetShutdownParametersReply.Flags = ProcessData->ShutdownFlags;
262
263   Reply->Status = STATUS_SUCCESS;
264
265   return(STATUS_SUCCESS);
266 }
267
268 CSR_API(CsrSetShutdownParameters)
269 {
270   Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
271   Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
272     sizeof(LPC_MESSAGE);
273
274   ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
275   ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
276
277   Reply->Status = STATUS_SUCCESS;
278
279   return(STATUS_SUCCESS);
280 }
281
282
283 /* EOF */