f2b6aa47b590f0dcec88398360102c2ef817d708
[reactos.git] / win32ss / user / consrv / handle.c
1 /*
2 * LICENSE: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/handle.c
5 * PURPOSE: Console I/O Handles functions
6 * PROGRAMMERS:
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "consrv.h"
12 #include "conio.h"
13
14 //#define NDEBUG
15 #include <debug.h>
16
17
18 /* PRIVATE FUNCTIONS *********************************************************/
19
20 static INT
21 AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry, INT Change)
22 {
23 Object_t *Object = Entry->Object;
24
25 DPRINT1("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount, Object->Type);
26
27 if (Entry->Access & GENERIC_READ) Object->AccessRead += Change;
28 if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change;
29 if (!(Entry->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead += Change;
30 if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
31
32 Object->HandleCount += Change;
33
34 return Object->HandleCount;
35 }
36
37 static VOID
38 Win32CsrCreateHandleEntry(PCONSOLE_IO_HANDLE Entry)
39 {
40 /// LOCK /// Object_t *Object = Entry->Object;
41 /// LOCK /// EnterCriticalSection(&Object->Console->Lock);
42 AdjustHandleCounts(Entry, +1);
43 /// LOCK /// LeaveCriticalSection(&Object->Console->Lock);
44 }
45
46 static VOID
47 Win32CsrCloseHandleEntry(PCONSOLE_IO_HANDLE Entry)
48 {
49 Object_t *Object = Entry->Object;
50 if (Object != NULL)
51 {
52 /// LOCK /// PCONSOLE Console = Object->Console;
53 /// LOCK /// EnterCriticalSection(&Console->Lock);
54
55 /// TODO: HERE, trigger input waiting threads.
56
57 /* If the last handle to a screen buffer is closed, delete it... */
58 if (AdjustHandleCounts(Entry, -1) == 0)
59 {
60 if (Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
61 {
62 PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
63 /* ...unless it's the only buffer left. Windows allows deletion
64 * even of the last buffer, but having to deal with a lack of
65 * any active buffer might be error-prone. */
66 if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
67 ConioDeleteScreenBuffer(Buffer);
68 }
69 else if (Object->Type == CONIO_INPUT_BUFFER_MAGIC)
70 {
71 DPRINT1("Closing the input buffer\n");
72 }
73 }
74
75 /// LOCK /// LeaveCriticalSection(&Console->Lock);
76 Entry->Object = NULL;
77 }
78 }
79
80
81 /* FUNCTIONS *****************************************************************/
82
83 /* static */ NTSTATUS
84 FASTCALL
85 Win32CsrInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData,
86 OUT PHANDLE pInputHandle,
87 OUT PHANDLE pOutputHandle,
88 OUT PHANDLE pErrorHandle)
89 {
90 NTSTATUS Status;
91 HANDLE InputHandle = INVALID_HANDLE_VALUE,
92 OutputHandle = INVALID_HANDLE_VALUE,
93 ErrorHandle = INVALID_HANDLE_VALUE;
94
95 /*
96 * Initialize the handles table. Use temporary variables to store
97 * the handles values in such a way that, if we fail, we don't
98 * return to the caller invalid handle values.
99 *
100 * Insert the IO handles.
101 */
102
103 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
104
105 /* Insert the Input handle */
106 Status = Win32CsrInsertObject(ProcessData,
107 &InputHandle,
108 &ProcessData->Console->InputBuffer.Header,
109 GENERIC_READ | GENERIC_WRITE,
110 TRUE,
111 FILE_SHARE_READ | FILE_SHARE_WRITE);
112 if (!NT_SUCCESS(Status))
113 {
114 DPRINT1("Failed to insert the input handle\n");
115 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
116 Win32CsrFreeHandlesTable(ProcessData);
117 return Status;
118 }
119
120 /* Insert the Output handle */
121 Status = Win32CsrInsertObject(ProcessData,
122 &OutputHandle,
123 &ProcessData->Console->ActiveBuffer->Header,
124 GENERIC_READ | GENERIC_WRITE,
125 TRUE,
126 FILE_SHARE_READ | FILE_SHARE_WRITE);
127 if (!NT_SUCCESS(Status))
128 {
129 DPRINT1("Failed to insert the output handle\n");
130 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
131 Win32CsrFreeHandlesTable(ProcessData);
132 return Status;
133 }
134
135 /* Insert the Error handle */
136 Status = Win32CsrInsertObject(ProcessData,
137 &ErrorHandle,
138 &ProcessData->Console->ActiveBuffer->Header,
139 GENERIC_READ | GENERIC_WRITE,
140 TRUE,
141 FILE_SHARE_READ | FILE_SHARE_WRITE);
142 if (!NT_SUCCESS(Status))
143 {
144 DPRINT1("Failed to insert the error handle\n");
145 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
146 Win32CsrFreeHandlesTable(ProcessData);
147 return Status;
148 }
149
150 /* Return the newly created handles */
151 *pInputHandle = InputHandle;
152 *pOutputHandle = OutputHandle;
153 *pErrorHandle = ErrorHandle;
154
155 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
156 return STATUS_SUCCESS;
157 }
158
159 NTSTATUS
160 FASTCALL
161 Win32CsrInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
162 IN PCONSOLE_PROCESS_DATA TargetProcessData)
163 {
164 NTSTATUS Status = STATUS_SUCCESS;
165 ULONG i;
166
167 RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
168
169 /* Inherit a handles table only if there is no already */
170 if (TargetProcessData->HandleTable != NULL /* || TargetProcessData->HandleTableSize != 0 */)
171 {
172 Status = STATUS_UNSUCCESSFUL; /* STATUS_INVALID_PARAMETER */
173 goto Quit;
174 }
175
176 /* Allocate a new handle table for the child process */
177 TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
178 HEAP_ZERO_MEMORY,
179 SourceProcessData->HandleTableSize
180 * sizeof(CONSOLE_IO_HANDLE));
181 if (TargetProcessData->HandleTable == NULL)
182 {
183 Status = STATUS_NO_MEMORY;
184 goto Quit;
185 }
186
187 TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
188
189 /*
190 * Parse the parent process' handles table and, for each handle,
191 * do a copy of it and reference it, if the handle is inheritable.
192 */
193 for (i = 0; i < SourceProcessData->HandleTableSize; i++)
194 {
195 if (SourceProcessData->HandleTable[i].Object != NULL &&
196 SourceProcessData->HandleTable[i].Inheritable)
197 {
198 /*
199 * Copy the handle data and increment the reference count of the
200 * pointed object (via the call to Win32CsrCreateHandleEntry).
201 */
202 TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
203 Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
204 }
205 }
206
207 Quit:
208 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
209 return Status;
210 }
211
212 VOID
213 FASTCALL
214 Win32CsrFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData)
215 {
216 DPRINT1("Win32CsrFreeHandlesTable\n");
217
218 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
219
220 if (ProcessData->HandleTable != NULL)
221 {
222 ULONG i;
223
224 /* Close all console handles and free the handle table memory */
225 for (i = 0; i < ProcessData->HandleTableSize; i++)
226 {
227 Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
228 }
229 RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
230 ProcessData->HandleTable = NULL;
231 }
232
233 ProcessData->HandleTableSize = 0;
234
235 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
236 }
237
238 NTSTATUS
239 FASTCALL
240 Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
241 PHANDLE Handle,
242 Object_t *Object,
243 DWORD Access,
244 BOOL Inheritable,
245 DWORD ShareMode)
246 {
247 #define IO_HANDLES_INCREMENT 2*3
248
249 ULONG i;
250 PCONSOLE_IO_HANDLE Block;
251
252 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
253
254 for (i = 0; i < ProcessData->HandleTableSize; i++)
255 {
256 if (ProcessData->HandleTable[i].Object == NULL)
257 {
258 break;
259 }
260 }
261 if (i >= ProcessData->HandleTableSize)
262 {
263 Block = RtlAllocateHeap(ConSrvHeap,
264 HEAP_ZERO_MEMORY,
265 (ProcessData->HandleTableSize +
266 IO_HANDLES_INCREMENT) * sizeof(CONSOLE_IO_HANDLE));
267 if (Block == NULL)
268 {
269 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
270 return STATUS_UNSUCCESSFUL;
271 }
272 RtlCopyMemory(Block,
273 ProcessData->HandleTable,
274 ProcessData->HandleTableSize * sizeof(CONSOLE_IO_HANDLE));
275 RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
276 ProcessData->HandleTable = Block;
277 ProcessData->HandleTableSize += IO_HANDLES_INCREMENT;
278 }
279
280 ProcessData->HandleTable[i].Object = Object;
281 ProcessData->HandleTable[i].Access = Access;
282 ProcessData->HandleTable[i].Inheritable = Inheritable;
283 ProcessData->HandleTable[i].ShareMode = ShareMode;
284 Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i]);
285 *Handle = ULongToHandle((i << 2) | 0x3);
286
287 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
288
289 return STATUS_SUCCESS;
290 }
291
292 NTSTATUS
293 FASTCALL
294 Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData,
295 HANDLE Handle)
296 {
297 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
298 Object_t *Object;
299
300 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
301
302 if (h >= ProcessData->HandleTableSize ||
303 (Object = ProcessData->HandleTable[h].Object) == NULL)
304 {
305 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
306 return STATUS_INVALID_HANDLE;
307 }
308
309 DPRINT1("Win32CsrReleaseObject - Process 0x%p, Release 0x%p\n", ProcessData->Process, &ProcessData->HandleTable[h]);
310 Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
311
312 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
313
314 return STATUS_SUCCESS;
315 }
316
317 NTSTATUS
318 FASTCALL
319 Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData,
320 HANDLE Handle,
321 Object_t **Object,
322 DWORD Access,
323 BOOL LockConsole,
324 ULONG Type)
325 {
326 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
327
328 // DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
329 // Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
330
331 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
332
333 if ( !IsConsoleHandle(Handle) ||
334 h >= ProcessData->HandleTableSize ||
335 (*Object = ProcessData->HandleTable[h].Object) == NULL ||
336 (ProcessData->HandleTable[h].Access & Access) == 0 ||
337 (Type != 0 && (*Object)->Type != Type) )
338 {
339 DPRINT1("CsrGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle, Type, Access);
340 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
341 return STATUS_INVALID_HANDLE;
342 }
343
344 _InterlockedIncrement(&(*Object)->Console->ReferenceCount);
345 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
346
347 if (LockConsole) EnterCriticalSection(&(*Object)->Console->Lock);
348
349 return STATUS_SUCCESS;
350 }
351
352 VOID FASTCALL
353 Win32CsrUnlockConsole(PCONSOLE Console,
354 BOOL IsConsoleLocked)
355 {
356 if (IsConsoleLocked) LeaveCriticalSection(&Console->Lock);
357
358 /* Decrement reference count */
359 if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
360 ConioDeleteConsole(Console);
361 }
362
363 VOID
364 FASTCALL
365 Win32CsrUnlockObject(Object_t *Object,
366 BOOL IsConsoleLocked)
367 {
368 Win32CsrUnlockConsole(Object->Console, IsConsoleLocked);
369 }
370
371 NTSTATUS
372 FASTCALL
373 Win32CsrAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
374 PHANDLE pInputHandle,
375 PHANDLE pOutputHandle,
376 PHANDLE pErrorHandle,
377 int ShowCmd,
378 PCSR_PROCESS CsrProcess)
379 {
380 NTSTATUS Status = STATUS_SUCCESS;
381
382 /* Initialize a new Console owned by the Console Leader Process */
383 Status = CsrInitConsole(&ProcessData->Console, ShowCmd, CsrProcess);
384 if (!NT_SUCCESS(Status))
385 {
386 DPRINT1("Console initialization failed\n");
387 return Status;
388 }
389
390 /* Initialize the handles table */
391 Status = Win32CsrInitHandlesTable(ProcessData,
392 pInputHandle,
393 pOutputHandle,
394 pErrorHandle);
395 if (!NT_SUCCESS(Status))
396 {
397 DPRINT1("Failed to initialize the handles table\n");
398
399 // Win32CsrReleaseConsole(ProcessData);
400 ConioDeleteConsole(ProcessData->Console);
401 ProcessData->Console = NULL;
402
403 return Status;
404 }
405
406 return Status;
407 }
408
409 VOID
410 FASTCALL
411 Win32CsrReleaseConsole(PCONSOLE_PROCESS_DATA ProcessData)
412 {
413 PCONSOLE Console;
414
415 DPRINT1("Win32CsrReleaseConsole\n");
416
417 /* Close all console handles and free the handle table memory */
418 Win32CsrFreeHandlesTable(ProcessData);
419
420 /* Detach process from console */
421 Console = ProcessData->Console;
422 if (Console != NULL)
423 {
424 DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console->ReferenceCount);
425 ProcessData->Console = NULL;
426 EnterCriticalSection(&Console->Lock);
427 DPRINT1("Win32CsrReleaseConsole - Locking OK\n");
428 RemoveEntryList(&ProcessData->ConsoleLink);
429 Win32CsrUnlockConsole(Console, TRUE);
430 //CloseHandle(ProcessData->ConsoleEvent);
431 //ProcessData->ConsoleEvent = NULL;
432 }
433 }
434
435 NTSTATUS
436 FASTCALL
437 ConioConsoleFromProcessData(PCONSOLE_PROCESS_DATA ProcessData,
438 PCONSOLE* Console,
439 BOOL LockConsole)
440 {
441 PCONSOLE ProcessConsole;
442
443 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
444 ProcessConsole = ProcessData->Console;
445
446 if (!ProcessConsole)
447 {
448 *Console = NULL;
449 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
450 return STATUS_INVALID_HANDLE;
451 }
452
453 InterlockedIncrement(&ProcessConsole->ReferenceCount);
454 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
455
456 if (LockConsole) EnterCriticalSection(&ProcessConsole->Lock);
457
458 *Console = ProcessConsole;
459
460 return STATUS_SUCCESS;
461 }
462
463
464
465 NTSTATUS
466 NTAPI
467 ConsoleNewProcess(PCSR_PROCESS SourceProcess,
468 PCSR_PROCESS TargetProcess)
469 {
470 /**************************************************************************
471 * This function is called whenever a new process (GUI or CUI) is created.
472 *
473 * Copy the parent's handles table here if both the parent and the child
474 * processes are CUI. If we must actually create our proper console (and
475 * thus do not inherit from the console handles of the parent's), then we
476 * will clean this table in the next ConsoleConnect call. Why we are doing
477 * this? It's because here, we still don't know whether or not we must create
478 * a new console instead of inherit it from the parent, and, because in
479 * ConsoleConnect we don't have any reference to the parent process anymore.
480 **************************************************************************/
481
482 PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
483
484 DPRINT1("ConsoleNewProcess inside\n");
485 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess, TargetProcess);
486
487 /* An empty target process is invalid */
488 if (!TargetProcess)
489 return STATUS_INVALID_PARAMETER;
490
491 DPRINT1("ConsoleNewProcess - OK\n");
492
493 TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
494 DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData);
495
496 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
497
498 /* Initialize the new (target) process */
499 TargetProcessData->Process = TargetProcess;
500 TargetProcessData->ConsoleEvent = NULL;
501 TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
502 TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
503
504 // Testing
505 TargetProcessData->HandleTableSize = 0;
506 TargetProcessData->HandleTable = NULL;
507
508 /**** HACK !!!! ****/ RtlZeroMemory(&TargetProcessData->HandleTableLock, sizeof(RTL_CRITICAL_SECTION));
509 RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
510
511 /* Do nothing if the source process is NULL */
512 if (!SourceProcess)
513 return STATUS_SUCCESS;
514
515 SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
516 DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData);
517
518 /*
519 * If both of the processes (parent and new child) are console applications,
520 * then try to inherit handles from the parent process.
521 */
522 if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
523 TargetProcessData->ConsoleApp )
524 {
525 NTSTATUS Status;
526
527 Status = Win32CsrInheritHandlesTable(SourceProcessData, TargetProcessData);
528 if (!NT_SUCCESS(Status))
529 {
530 return Status;
531 }
532
533 /* Temporary "inherit" the console from the parent */
534 TargetProcessData->ParentConsole = SourceProcessData->Console;
535 }
536 else
537 {
538 DPRINT1("ConsoleNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData->Console, TargetProcess->Flags);
539 }
540
541 return STATUS_SUCCESS;
542 }
543
544 NTSTATUS
545 NTAPI
546 ConsoleConnect(IN PCSR_PROCESS CsrProcess,
547 IN OUT PVOID ConnectionInfo,
548 IN OUT PULONG ConnectionInfoLength)
549 {
550 /**************************************************************************
551 * This function is called whenever a CUI new process is created.
552 **************************************************************************/
553
554 NTSTATUS Status = STATUS_SUCCESS;
555 PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
556 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
557
558 DPRINT1("ConsoleConnect\n");
559
560 if ( ConnectionInfo == NULL ||
561 ConnectionInfoLength == NULL ||
562 *ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
563 {
564 DPRINT1("CONSRV: Connection failed\n");
565 return STATUS_UNSUCCESSFUL;
566 }
567
568 /* If we don't need a console, then get out of here */
569 if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
570 {
571 DPRINT("ConsoleConnect - No console needed\n");
572 return STATUS_SUCCESS;
573 }
574
575 /* If we don't have a console, then create a new one... */
576 if (!ConnectInfo->Console ||
577 ConnectInfo->Console != ProcessData->ParentConsole)
578 {
579 DPRINT1("ConsoleConnect - Allocate a new console\n");
580
581 /*
582 * We are about to create a new console. However when ConsoleNewProcess
583 * was called, we didn't know that we wanted to create a new console and
584 * therefore, we by default inherited the handles table from our parent
585 * process. It's only now that we notice that in fact we do not need
586 * them, because we've created a new console and thus we must use it.
587 *
588 * Therefore, free the console we can have and our handles table,
589 * and recreate a new one later on.
590 */
591 Win32CsrReleaseConsole(ProcessData);
592
593 /* Initialize a new Console owned by the Console Leader Process */
594 Status = Win32CsrAllocateConsole(ProcessData,
595 &ConnectInfo->InputHandle,
596 &ConnectInfo->OutputHandle,
597 &ConnectInfo->ErrorHandle,
598 ConnectInfo->ShowCmd,
599 CsrProcess);
600 if (!NT_SUCCESS(Status))
601 {
602 DPRINT1("Console allocation failed\n");
603 return Status;
604 }
605 }
606 else /* We inherit it from the parent */
607 {
608 DPRINT1("ConsoleConnect - Reuse current (parent's) console\n");
609
610 /* Reuse our current console */
611 ProcessData->Console = ConnectInfo->Console;
612 }
613
614 /* Add a reference count because the process is tied to the console */
615 _InterlockedIncrement(&ProcessData->Console->ReferenceCount);
616
617 /* Insert the process into the processes list of the console */
618 InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
619
620 /// TODO: Move this up ?
621 /* Duplicate the Event */
622 Status = NtDuplicateObject(NtCurrentProcess(),
623 ProcessData->Console->InputBuffer.ActiveEvent,
624 ProcessData->Process->ProcessHandle,
625 &ProcessData->ConsoleEvent,
626 EVENT_ALL_ACCESS, 0, 0);
627 if (!NT_SUCCESS(Status))
628 {
629 DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
630 Win32CsrReleaseConsole(ProcessData);
631 return Status;
632 }
633
634 /* Return it to the caller */
635 ConnectInfo->Console = ProcessData->Console;
636
637 /* Input Wait Handle */
638 ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
639
640 /* Set the Ctrl Dispatcher */
641 ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
642 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
643
644 return STATUS_SUCCESS;
645 }
646
647 VOID
648 WINAPI
649 ConsoleDisconnect(PCSR_PROCESS Process)
650 {
651 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
652
653 /**************************************************************************
654 * This function is called whenever a new process (GUI or CUI) is destroyed.
655 **************************************************************************/
656
657 DPRINT1("ConsoleDisconnect called\n");
658 if ( ProcessData->Console != NULL ||
659 ProcessData->HandleTable != NULL )
660 {
661 DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
662 Win32CsrReleaseConsole(ProcessData);
663 }
664
665 RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
666 }
667
668
669
670 CSR_API(SrvCloseHandle)
671 {
672 PCONSOLE_CLOSEHANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
673
674 return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
675 CloseHandleRequest->ConsoleHandle);
676 }
677
678 CSR_API(SrvVerifyConsoleIoHandle)
679 {
680 NTSTATUS Status = STATUS_SUCCESS;
681 PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
682 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
683 HANDLE ConsoleHandle = VerifyHandleRequest->ConsoleHandle;
684 ULONG_PTR Index = (ULONG_PTR)ConsoleHandle >> 2;
685
686 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
687
688 if (!IsConsoleHandle(ConsoleHandle) ||
689 Index >= ProcessData->HandleTableSize ||
690 ProcessData->HandleTable[Index].Object == NULL)
691 {
692 DPRINT("CsrVerifyObject failed\n");
693 Status = STATUS_INVALID_HANDLE;
694 }
695
696 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
697
698 return Status;
699 }
700
701 CSR_API(SrvDuplicateHandle)
702 {
703 PCONSOLE_IO_HANDLE Entry;
704 DWORD DesiredAccess;
705 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
706 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
707 HANDLE ConsoleHandle = DuplicateHandleRequest->ConsoleHandle;
708 ULONG_PTR Index = (ULONG_PTR)ConsoleHandle >> 2;
709
710 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
711
712 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
713 Index >= ProcessData->HandleTableSize ||
714 (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
715 {
716 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle);
717 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
718 return STATUS_INVALID_HANDLE;
719 }
720
721 if (DuplicateHandleRequest->Options & DUPLICATE_SAME_ACCESS)
722 {
723 DesiredAccess = Entry->Access;
724 }
725 else
726 {
727 DesiredAccess = DuplicateHandleRequest->Access;
728 /* Make sure the source handle has all the desired flags */
729 if ((Entry->Access & DesiredAccess) == 0)
730 {
731 DPRINT1("Handle %p only has access %X; requested %X\n",
732 ConsoleHandle, Entry->Access, DesiredAccess);
733 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
734 return STATUS_INVALID_PARAMETER;
735 }
736 }
737
738 ApiMessage->Status = Win32CsrInsertObject(ProcessData,
739 &DuplicateHandleRequest->ConsoleHandle, // Use the new handle value!
740 Entry->Object,
741 DesiredAccess,
742 DuplicateHandleRequest->Inheritable,
743 Entry->ShareMode);
744 if (NT_SUCCESS(ApiMessage->Status) &&
745 DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE)
746 {
747 Win32CsrCloseHandleEntry(Entry);
748 }
749
750 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
751 return ApiMessage->Status;
752 }
753
754 /**
755 CSR_API(CsrGetInputWaitHandle)
756 {
757 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
758
759 GetConsoleInputWaitHandle->InputWaitHandle =
760 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
761
762 return STATUS_SUCCESS;
763 }
764 **/
765
766 /* EOF */