[WIN32CSR] Clean up the debris from r47314: Removed some redundant code, reorganized...
[reactos.git] / reactos / subsystems / win32 / csrss / win32csr / handle.c
1 /* $Id$
2 *
3 * reactos/subsys/csrss/api/handle.c
4 *
5 * CSRSS handle functions
6 *
7 * ReactOS Operating System
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <w32csr.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS *****************************************************************/
18
19 static unsigned ObjectDefinitionsCount = 2;
20 static CSRSS_OBJECT_DEFINITION ObjectDefinitions[] =
21 {
22 { CONIO_CONSOLE_MAGIC, ConioDeleteConsole },
23 { CONIO_SCREEN_BUFFER_MAGIC, ConioDeleteScreenBuffer },
24 };
25
26 static
27 BOOL
28 CsrIsConsoleHandle(HANDLE Handle)
29 {
30 return ((ULONG_PTR)Handle & 0x10000003) == 0x3;
31 }
32
33 NTSTATUS
34 FASTCALL
35 Win32CsrGetObject(
36 PCSRSS_PROCESS_DATA ProcessData,
37 HANDLE Handle,
38 Object_t **Object,
39 DWORD Access )
40 {
41 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
42
43 DPRINT("CsrGetObject, Object: %x, %x, %x\n",
44 Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
45
46 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
47 if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize
48 || (*Object = ProcessData->HandleTable[h].Object) == NULL
49 || ~ProcessData->HandleTable[h].Access & Access)
50 {
51 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
52 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
53 return STATUS_INVALID_HANDLE;
54 }
55 _InterlockedIncrement(&(*Object)->ReferenceCount);
56 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
57 // DbgPrint( "CsrGetObject returning\n" );
58 return STATUS_SUCCESS;
59 }
60
61
62 NTSTATUS
63 FASTCALL
64 Win32CsrReleaseObjectByPointer(
65 Object_t *Object)
66 {
67 unsigned DefIndex;
68
69 /* dec ref count */
70 if (_InterlockedDecrement(&Object->ReferenceCount) == 0)
71 {
72 for (DefIndex = 0; DefIndex < ObjectDefinitionsCount; DefIndex++)
73 {
74 if (Object->Type == ObjectDefinitions[DefIndex].Type)
75 {
76 (ObjectDefinitions[DefIndex].CsrCleanupObjectProc)(Object);
77 return STATUS_SUCCESS;
78 }
79 }
80
81 DPRINT1("CSR: Error: releasing unknown object type 0x%x", Object->Type);
82 }
83
84 return STATUS_SUCCESS;
85 }
86
87 NTSTATUS
88 FASTCALL
89 Win32CsrReleaseObject(
90 PCSRSS_PROCESS_DATA ProcessData,
91 HANDLE Handle)
92 {
93 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
94 Object_t *Object;
95
96 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
97 if (h >= ProcessData->HandleTableSize
98 || (Object = ProcessData->HandleTable[h].Object) == NULL)
99 {
100 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
101 return STATUS_INVALID_HANDLE;
102 }
103 ProcessData->HandleTable[h].Object = NULL;
104 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
105
106 return Win32CsrReleaseObjectByPointer(Object);
107 }
108
109 NTSTATUS
110 FASTCALL
111 Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData,
112 HANDLE Handle,
113 Object_t **Object,
114 DWORD Access,
115 LONG Type)
116 {
117 NTSTATUS Status;
118
119 Status = Win32CsrGetObject(ProcessData, Handle, Object, Access);
120 if (! NT_SUCCESS(Status))
121 {
122 return Status;
123 }
124
125 if ((*Object)->Type != Type)
126 {
127 Win32CsrReleaseObjectByPointer(*Object);
128 return STATUS_INVALID_HANDLE;
129 }
130
131 EnterCriticalSection(&((*Object)->Lock));
132
133 return STATUS_SUCCESS;
134 }
135
136 VOID
137 FASTCALL
138 Win32CsrUnlockObject(Object_t *Object)
139 {
140 LeaveCriticalSection(&(Object->Lock));
141 Win32CsrReleaseObjectByPointer(Object);
142 }
143
144 NTSTATUS
145 WINAPI
146 Win32CsrReleaseConsole(
147 PCSRSS_PROCESS_DATA ProcessData)
148 {
149 ULONG HandleTableSize;
150 PCSRSS_HANDLE HandleTable;
151 PCSRSS_CONSOLE Console;
152 ULONG i;
153
154 /* Close all console handles and detach process from console */
155 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
156 HandleTableSize = ProcessData->HandleTableSize;
157 HandleTable = ProcessData->HandleTable;
158 Console = ProcessData->Console;
159 ProcessData->HandleTableSize = 0;
160 ProcessData->HandleTable = NULL;
161 ProcessData->Console = NULL;
162 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
163
164 for (i = 0; i < HandleTableSize; i++)
165 {
166 if (HandleTable[i].Object != NULL)
167 Win32CsrReleaseObjectByPointer(HandleTable[i].Object);
168 }
169 RtlFreeHeap(Win32CsrApiHeap, 0, HandleTable);
170
171 if (Console != NULL)
172 {
173 EnterCriticalSection(&Console->Header.Lock);
174 RemoveEntryList(&ProcessData->ProcessEntry);
175 LeaveCriticalSection(&Console->Header.Lock);
176 Win32CsrReleaseObjectByPointer(&Console->Header);
177 return STATUS_SUCCESS;
178 }
179
180 return STATUS_INVALID_PARAMETER;
181 }
182
183 NTSTATUS
184 FASTCALL
185 Win32CsrInsertObject(
186 PCSRSS_PROCESS_DATA ProcessData,
187 PHANDLE Handle,
188 Object_t *Object,
189 DWORD Access,
190 BOOL Inheritable)
191 {
192 ULONG i;
193 PCSRSS_HANDLE Block;
194
195 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
196
197 for (i = 0; i < ProcessData->HandleTableSize; i++)
198 {
199 if (ProcessData->HandleTable[i].Object == NULL)
200 {
201 break;
202 }
203 }
204 if (i >= ProcessData->HandleTableSize)
205 {
206 Block = RtlAllocateHeap(Win32CsrApiHeap,
207 HEAP_ZERO_MEMORY,
208 (ProcessData->HandleTableSize + 64) * sizeof(CSRSS_HANDLE));
209 if (Block == NULL)
210 {
211 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
212 return(STATUS_UNSUCCESSFUL);
213 }
214 RtlCopyMemory(Block,
215 ProcessData->HandleTable,
216 ProcessData->HandleTableSize * sizeof(CSRSS_HANDLE));
217 RtlFreeHeap(Win32CsrApiHeap, 0, ProcessData->HandleTable);
218 ProcessData->HandleTable = Block;
219 ProcessData->HandleTableSize += 64;
220 }
221 ProcessData->HandleTable[i].Object = Object;
222 ProcessData->HandleTable[i].Access = Access;
223 ProcessData->HandleTable[i].Inheritable = Inheritable;
224 *Handle = UlongToHandle((i << 2) | 0x3);
225 _InterlockedIncrement( &Object->ReferenceCount );
226 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
227 return(STATUS_SUCCESS);
228 }
229
230 NTSTATUS
231 WINAPI
232 Win32CsrDuplicateHandleTable(
233 PCSRSS_PROCESS_DATA SourceProcessData,
234 PCSRSS_PROCESS_DATA TargetProcessData)
235 {
236 ULONG i;
237
238 if (TargetProcessData->HandleTableSize)
239 {
240 return STATUS_INVALID_PARAMETER;
241 }
242
243 RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
244
245 /* we are called from CreateProcessData, it isn't necessary to lock the target process data */
246
247 TargetProcessData->HandleTable = RtlAllocateHeap(Win32CsrApiHeap,
248 HEAP_ZERO_MEMORY,
249 SourceProcessData->HandleTableSize
250 * sizeof(CSRSS_HANDLE));
251 if (TargetProcessData->HandleTable == NULL)
252 {
253 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
254 return(STATUS_UNSUCCESSFUL);
255 }
256 TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
257 for (i = 0; i < SourceProcessData->HandleTableSize; i++)
258 {
259 if (SourceProcessData->HandleTable[i].Object != NULL &&
260 SourceProcessData->HandleTable[i].Inheritable)
261 {
262 TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
263 _InterlockedIncrement( &SourceProcessData->HandleTable[i].Object->ReferenceCount );
264 }
265 }
266 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
267 return(STATUS_SUCCESS);
268 }
269
270 CSR_API(CsrGetInputHandle)
271 {
272 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
273 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
274
275 if (ProcessData->Console)
276 {
277 Request->Status = Win32CsrInsertObject(ProcessData,
278 &Request->Data.GetInputHandleRequest.InputHandle,
279 &ProcessData->Console->Header,
280 Request->Data.GetInputHandleRequest.Access,
281 Request->Data.GetInputHandleRequest.Inheritable);
282 }
283 else
284 {
285 Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
286 Request->Status = STATUS_SUCCESS;
287 }
288
289 return Request->Status;
290 }
291
292 CSR_API(CsrGetOutputHandle)
293 {
294 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
295 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
296
297 if (ProcessData->Console)
298 {
299 Request->Status = Win32CsrInsertObject(ProcessData,
300 &Request->Data.GetOutputHandleRequest.OutputHandle,
301 &ProcessData->Console->ActiveBuffer->Header,
302 Request->Data.GetOutputHandleRequest.Access,
303 Request->Data.GetOutputHandleRequest.Inheritable);
304 }
305 else
306 {
307 Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
308 Request->Status = STATUS_SUCCESS;
309 }
310
311 return Request->Status;
312 }
313
314 CSR_API(CsrCloseHandle)
315 {
316 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
317 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
318
319 return Win32CsrReleaseObject(ProcessData, Request->Data.CloseHandleRequest.Handle);
320 }
321
322 CSR_API(CsrVerifyHandle)
323 {
324 ULONG_PTR Index;
325 NTSTATUS Status = STATUS_SUCCESS;
326
327 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
328 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
329
330 Index = (ULONG_PTR)Request->Data.VerifyHandleRequest.Handle >> 2;
331 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
332 if (Index >= ProcessData->HandleTableSize ||
333 ProcessData->HandleTable[Index].Object == NULL)
334 {
335 DPRINT("CsrVerifyObject failed\n");
336 Status = STATUS_INVALID_HANDLE;
337 }
338 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
339
340 return Status;
341 }
342
343 CSR_API(CsrDuplicateHandle)
344 {
345 ULONG_PTR Index;
346 PCSRSS_HANDLE Entry;
347 DWORD DesiredAccess;
348
349 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
350 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
351
352 Index = (ULONG_PTR)Request->Data.DuplicateHandleRequest.Handle >> 2;
353 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
354 if (Index >= ProcessData->HandleTableSize
355 || (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
356 {
357 DPRINT1("Couldn't dup invalid handle %p\n", Request->Data.DuplicateHandleRequest.Handle);
358 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
359 return STATUS_INVALID_HANDLE;
360 }
361
362 if (Request->Data.DuplicateHandleRequest.Options & DUPLICATE_SAME_ACCESS)
363 {
364 DesiredAccess = Entry->Access;
365 }
366 else
367 {
368 DesiredAccess = Request->Data.DuplicateHandleRequest.Access;
369 /* Make sure the source handle has all the desired flags */
370 if (~Entry->Access & DesiredAccess)
371 {
372 DPRINT1("Handle %p only has access %X; requested %X\n",
373 Request->Data.DuplicateHandleRequest.Handle, Entry->Access, DesiredAccess);
374 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
375 return STATUS_INVALID_PARAMETER;
376 }
377 }
378
379 Request->Status = Win32CsrInsertObject(ProcessData,
380 &Request->Data.DuplicateHandleRequest.Handle,
381 Entry->Object,
382 DesiredAccess,
383 Request->Data.DuplicateHandleRequest.Inheritable);
384 if (NT_SUCCESS(Request->Status)
385 && Request->Data.DuplicateHandleRequest.Options & DUPLICATE_CLOSE_SOURCE)
386 {
387 /* Close the original handle. This cannot drop the count to 0, since a new handle now exists */
388 _InterlockedDecrement(&Entry->Object->ReferenceCount);
389 Entry->Object = NULL;
390 }
391
392 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
393 return Request->Status;
394 }
395
396 CSR_API(CsrGetInputWaitHandle)
397 {
398 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
399 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
400
401 Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = ProcessData->ConsoleEvent;
402 return STATUS_SUCCESS;
403 }
404
405 /* EOF */