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
9 /* INCLUDES *******************************************************************/
18 /* PRIVATE FUNCTIONS **********************************************************/
21 AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry
, INT Change
)
23 Object_t
*Object
= Entry
->Object
;
25 DPRINT1("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry
, Change
, Object
, Object
->HandleCount
, Object
->Type
);
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
;
32 Object
->HandleCount
+= Change
;
34 return Object
->HandleCount
;
38 ConSrvCreateHandleEntry(PCONSOLE_IO_HANDLE Entry
)
40 /// LOCK /// Object_t *Object = Entry->Object;
41 /// LOCK /// EnterCriticalSection(&Object->Console->Lock);
42 AdjustHandleCounts(Entry
, +1);
43 /// LOCK /// LeaveCriticalSection(&Object->Console->Lock);
47 ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry
)
49 Object_t
*Object
= Entry
->Object
;
52 /// LOCK /// PCONSOLE Console = Object->Console;
53 /// LOCK /// EnterCriticalSection(&Console->Lock);
56 * If this is a input handle, notify and dereference
57 * all the waits related to this handle.
59 if (Object
->Type
== CONIO_INPUT_BUFFER_MAGIC
)
61 PCONSOLE_INPUT_BUFFER InputBuffer
= (PCONSOLE_INPUT_BUFFER
)Object
;
64 * Wake up all the writing waiters related to this handle for this
65 * input buffer, if any, then dereference them and purge them all
67 * To select them amongst all the waiters for this input buffer,
68 * pass the handle pointer to the waiters, then they will check
69 * whether or not they are related to this handle and if so, they
72 CsrNotifyWait(&InputBuffer
->ReadWaitQueue
,
76 if (!IsListEmpty(&InputBuffer
->ReadWaitQueue
))
78 CsrDereferenceWait(&InputBuffer
->ReadWaitQueue
);
82 /* If the last handle to a screen buffer is closed, delete it... */
83 if (AdjustHandleCounts(Entry
, -1) == 0)
85 if (Object
->Type
== CONIO_SCREEN_BUFFER_MAGIC
)
87 PCONSOLE_SCREEN_BUFFER Buffer
= (PCONSOLE_SCREEN_BUFFER
)Object
;
88 /* ...unless it's the only buffer left. Windows allows deletion
89 * even of the last buffer, but having to deal with a lack of
90 * any active buffer might be error-prone. */
91 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
92 ConioDeleteScreenBuffer(Buffer
);
94 else if (Object
->Type
== CONIO_INPUT_BUFFER_MAGIC
)
96 DPRINT1("Closing the input buffer\n");
100 /// LOCK /// LeaveCriticalSection(&Console->Lock);
101 Entry
->Object
= NULL
;
106 /* Forward declaration, used in ConSrvInitHandlesTable */
107 static VOID
ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
);
110 ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData
,
111 OUT PHANDLE pInputHandle
,
112 OUT PHANDLE pOutputHandle
,
113 OUT PHANDLE pErrorHandle
)
116 HANDLE InputHandle
= INVALID_HANDLE_VALUE
,
117 OutputHandle
= INVALID_HANDLE_VALUE
,
118 ErrorHandle
= INVALID_HANDLE_VALUE
;
121 * Initialize the handles table. Use temporary variables to store
122 * the handles values in such a way that, if we fail, we don't
123 * return to the caller invalid handle values.
125 * Insert the IO handles.
128 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
130 /* Insert the Input handle */
131 Status
= ConSrvInsertObject(ProcessData
,
133 &ProcessData
->Console
->InputBuffer
.Header
,
134 GENERIC_READ
| GENERIC_WRITE
,
136 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
137 if (!NT_SUCCESS(Status
))
139 DPRINT1("Failed to insert the input handle\n");
140 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
141 ConSrvFreeHandlesTable(ProcessData
);
145 /* Insert the Output handle */
146 Status
= ConSrvInsertObject(ProcessData
,
148 &ProcessData
->Console
->ActiveBuffer
->Header
,
149 GENERIC_READ
| GENERIC_WRITE
,
151 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
152 if (!NT_SUCCESS(Status
))
154 DPRINT1("Failed to insert the output handle\n");
155 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
156 ConSrvFreeHandlesTable(ProcessData
);
160 /* Insert the Error handle */
161 Status
= ConSrvInsertObject(ProcessData
,
163 &ProcessData
->Console
->ActiveBuffer
->Header
,
164 GENERIC_READ
| GENERIC_WRITE
,
166 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
167 if (!NT_SUCCESS(Status
))
169 DPRINT1("Failed to insert the error handle\n");
170 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
171 ConSrvFreeHandlesTable(ProcessData
);
175 /* Return the newly created handles */
176 *pInputHandle
= InputHandle
;
177 *pOutputHandle
= OutputHandle
;
178 *pErrorHandle
= ErrorHandle
;
180 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
181 return STATUS_SUCCESS
;
185 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
186 IN PCONSOLE_PROCESS_DATA TargetProcessData
)
188 NTSTATUS Status
= STATUS_SUCCESS
;
191 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
193 /* Inherit a handles table only if there is no already */
194 if (TargetProcessData
->HandleTable
!= NULL
/* || TargetProcessData->HandleTableSize != 0 */)
196 Status
= STATUS_UNSUCCESSFUL
; /* STATUS_INVALID_PARAMETER */
200 /* Allocate a new handle table for the child process */
201 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
203 SourceProcessData
->HandleTableSize
204 * sizeof(CONSOLE_IO_HANDLE
));
205 if (TargetProcessData
->HandleTable
== NULL
)
207 Status
= STATUS_NO_MEMORY
;
211 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
214 * Parse the parent process' handles table and, for each handle,
215 * do a copy of it and reference it, if the handle is inheritable.
217 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
219 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
220 SourceProcessData
->HandleTable
[i
].Inheritable
)
223 * Copy the handle data and increment the reference count of the
224 * pointed object (via the call to ConSrvCreateHandleEntry).
226 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
227 ConSrvCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
232 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
237 ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
)
239 DPRINT1("ConSrvFreeHandlesTable\n");
241 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
243 if (ProcessData
->HandleTable
!= NULL
)
247 /* Close all console handles and free the handle table memory */
248 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
250 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
252 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
253 ProcessData
->HandleTable
= NULL
;
256 ProcessData
->HandleTableSize
= 0;
258 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
263 ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
270 #define IO_HANDLES_INCREMENT 2*3
273 PCONSOLE_IO_HANDLE Block
;
275 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
277 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
279 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
284 if (i
>= ProcessData
->HandleTableSize
)
286 Block
= RtlAllocateHeap(ConSrvHeap
,
288 (ProcessData
->HandleTableSize
+
289 IO_HANDLES_INCREMENT
) * sizeof(CONSOLE_IO_HANDLE
));
292 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
293 return STATUS_UNSUCCESSFUL
;
296 ProcessData
->HandleTable
,
297 ProcessData
->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE
));
298 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
299 ProcessData
->HandleTable
= Block
;
300 ProcessData
->HandleTableSize
+= IO_HANDLES_INCREMENT
;
303 ProcessData
->HandleTable
[i
].Object
= Object
;
304 ProcessData
->HandleTable
[i
].Access
= Access
;
305 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
306 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
307 ConSrvCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
308 *Handle
= ULongToHandle((i
<< 2) | 0x3);
310 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
312 return STATUS_SUCCESS
;
317 ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData
,
320 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
323 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
325 if (h
>= ProcessData
->HandleTableSize
||
326 (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
328 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
329 return STATUS_INVALID_HANDLE
;
332 DPRINT1("ConSrvRemoveObject - Process 0x%p, Release 0x%p\n", ProcessData
->Process
, &ProcessData
->HandleTable
[h
]);
333 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
335 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
337 return STATUS_SUCCESS
;
342 ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData
,
345 PCONSOLE_IO_HANDLE
* Entry OPTIONAL
,
350 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
351 PCONSOLE_IO_HANDLE HandleEntry
= NULL
;
352 Object_t
* ObjectEntry
= NULL
;
355 if (Entry
) *Entry
= NULL
;
357 // DPRINT("ConSrvGetObject, Object: %x, %x, %x\n",
358 // Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
360 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
362 if ( IsConsoleHandle(Handle
) &&
363 h
< ProcessData
->HandleTableSize
)
365 HandleEntry
= &ProcessData
->HandleTable
[h
];
366 ObjectEntry
= HandleEntry
->Object
;
369 if ( HandleEntry
== NULL
||
370 ObjectEntry
== NULL
||
371 (HandleEntry
->Access
& Access
) == 0 ||
372 (Type
!= 0 && ObjectEntry
->Type
!= Type
) )
374 DPRINT1("ConSrvGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle
, Type
, Access
);
375 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
376 return STATUS_INVALID_HANDLE
;
379 _InterlockedIncrement(&ObjectEntry
->Console
->ReferenceCount
);
380 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
382 if (LockConsole
) EnterCriticalSection(&ObjectEntry
->Console
->Lock
);
384 /* Return the objects to the caller */
385 *Object
= ObjectEntry
;
386 if (Entry
) *Entry
= HandleEntry
;
388 return STATUS_SUCCESS
;
393 ConSrvReleaseObject(Object_t
*Object
,
394 BOOL IsConsoleLocked
)
396 ConSrvReleaseConsole(Object
->Console
, IsConsoleLocked
);
401 ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData
,
402 PHANDLE pInputHandle
,
403 PHANDLE pOutputHandle
,
404 PHANDLE pErrorHandle
,
405 PCONSOLE_START_INFO ConsoleStartInfo
)
407 NTSTATUS Status
= STATUS_SUCCESS
;
409 /* Initialize a new Console owned by this process */
410 Status
= ConSrvInitConsole(&ProcessData
->Console
, ConsoleStartInfo
, ProcessData
->Process
);
411 if (!NT_SUCCESS(Status
))
413 DPRINT1("Console initialization failed\n");
417 /* Initialize the handles table */
418 Status
= ConSrvInitHandlesTable(ProcessData
,
422 if (!NT_SUCCESS(Status
))
424 DPRINT1("Failed to initialize the handles table\n");
425 ConSrvDeleteConsole(ProcessData
->Console
);
426 ProcessData
->Console
= NULL
;
430 /* Duplicate the Input Event */
431 Status
= NtDuplicateObject(NtCurrentProcess(),
432 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
433 ProcessData
->Process
->ProcessHandle
,
434 &ProcessData
->ConsoleEvent
,
435 EVENT_ALL_ACCESS
, 0, 0);
436 if (!NT_SUCCESS(Status
))
438 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
439 ConSrvFreeHandlesTable(ProcessData
);
440 ConSrvDeleteConsole(ProcessData
->Console
);
441 ProcessData
->Console
= NULL
;
445 /* Insert the process into the processes list of the console */
446 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
448 /* Add a reference count because the process is tied to the console */
449 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
451 /* Update the internal info of the terminal */
452 ConioRefreshInternalInfo(ProcessData
->Console
);
454 return STATUS_SUCCESS
;
459 ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData
,
461 BOOL CreateNewHandlesTable
,
462 PHANDLE pInputHandle
,
463 PHANDLE pOutputHandle
,
464 PHANDLE pErrorHandle
)
466 NTSTATUS Status
= STATUS_SUCCESS
;
468 /* Inherit the console */
469 ProcessData
->Console
= Console
;
471 if (CreateNewHandlesTable
)
473 /* Initialize the handles table */
474 Status
= ConSrvInitHandlesTable(ProcessData
,
478 if (!NT_SUCCESS(Status
))
480 DPRINT1("Failed to initialize the handles table\n");
481 ProcessData
->Console
= NULL
;
486 /* Duplicate the Input Event */
487 Status
= NtDuplicateObject(NtCurrentProcess(),
488 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
489 ProcessData
->Process
->ProcessHandle
,
490 &ProcessData
->ConsoleEvent
,
491 EVENT_ALL_ACCESS
, 0, 0);
492 if (!NT_SUCCESS(Status
))
494 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
495 ConSrvFreeHandlesTable(ProcessData
); // NOTE: Always free the handles table.
496 ProcessData
->Console
= NULL
;
500 /* Insert the process into the processes list of the console */
501 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
503 /* Add a reference count because the process is tied to the console */
504 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
506 /* Update the internal info of the terminal */
507 ConioRefreshInternalInfo(ProcessData
->Console
);
509 return STATUS_SUCCESS
;
514 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData
)
518 DPRINT1("ConSrvRemoveConsole\n");
520 /* Close all console handles and free the handle table memory */
521 ConSrvFreeHandlesTable(ProcessData
);
523 /* Detach process from console */
524 Console
= ProcessData
->Console
;
527 DPRINT1("ConSrvRemoveConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console
->ReferenceCount
);
528 ProcessData
->Console
= NULL
;
530 EnterCriticalSection(&Console
->Lock
);
531 DPRINT1("ConSrvRemoveConsole - Locking OK\n");
533 /* Remove ourselves from the console's list of processes */
534 RemoveEntryList(&ProcessData
->ConsoleLink
);
536 /* Update the internal info of the terminal */
537 ConioRefreshInternalInfo(Console
);
539 /* Release the console */
540 ConSrvReleaseConsole(Console
, TRUE
);
541 //CloseHandle(ProcessData->ConsoleEvent);
542 //ProcessData->ConsoleEvent = NULL;
548 ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData
,
552 PCONSOLE ProcessConsole
;
554 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
555 ProcessConsole
= ProcessData
->Console
;
560 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
561 return STATUS_INVALID_HANDLE
;
564 InterlockedIncrement(&ProcessConsole
->ReferenceCount
);
565 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
567 if (LockConsole
) EnterCriticalSection(&ProcessConsole
->Lock
);
569 *Console
= ProcessConsole
;
571 return STATUS_SUCCESS
;
575 ConSrvReleaseConsole(PCONSOLE Console
,
576 BOOL IsConsoleLocked
)
578 if (IsConsoleLocked
) LeaveCriticalSection(&Console
->Lock
);
580 /* Decrement reference count */
581 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
582 ConSrvDeleteConsole(Console
);
587 ConSrvNewProcess(PCSR_PROCESS SourceProcess
,
588 PCSR_PROCESS TargetProcess
)
590 /**************************************************************************
591 * This function is called whenever a new process (GUI or CUI) is created.
593 * Copy the parent's handles table here if both the parent and the child
594 * processes are CUI. If we must actually create our proper console (and
595 * thus do not inherit from the console handles of the parent's), then we
596 * will clean this table in the next ConSrvConnect call. Why we are doing
597 * this? It's because here, we still don't know whether or not we must create
598 * a new console instead of inherit it from the parent, and, because in
599 * ConSrvConnect we don't have any reference to the parent process anymore.
600 **************************************************************************/
602 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
604 /* An empty target process is invalid */
605 if (!TargetProcess
) return STATUS_INVALID_PARAMETER
;
607 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
609 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
611 /* Initialize the new (target) process */
612 TargetProcessData
->Process
= TargetProcess
;
613 TargetProcessData
->ConsoleEvent
= NULL
;
614 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
615 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
618 TargetProcessData
->HandleTableSize
= 0;
619 TargetProcessData
->HandleTable
= NULL
;
621 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
623 /* Do nothing if the source process is NULL */
624 if (!SourceProcess
) return STATUS_SUCCESS
;
626 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
629 * If both of the processes (parent and new child) are console applications,
630 * then try to inherit handles from the parent process.
632 if ( SourceProcessData
->Console
!= NULL
&& /* SourceProcessData->ConsoleApp */
633 TargetProcessData
->ConsoleApp
)
637 Status
= ConSrvInheritHandlesTable(SourceProcessData
, TargetProcessData
);
638 if (!NT_SUCCESS(Status
)) return Status
;
640 /* Temporary save the parent's console */
641 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
644 return STATUS_SUCCESS
;
649 ConSrvConnect(IN PCSR_PROCESS CsrProcess
,
650 IN OUT PVOID ConnectionInfo
,
651 IN OUT PULONG ConnectionInfoLength
)
653 /**************************************************************************
654 * This function is called whenever a CUI new process is created.
655 **************************************************************************/
657 NTSTATUS Status
= STATUS_SUCCESS
;
658 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
659 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
661 if ( ConnectionInfo
== NULL
||
662 ConnectionInfoLength
== NULL
||
663 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
665 DPRINT1("CONSRV: Connection failed\n");
666 return STATUS_UNSUCCESSFUL
;
669 /* If we don't need a console, then get out of here */
670 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
672 return STATUS_SUCCESS
;
675 /* If we don't have a console, then create a new one... */
676 if (!ConnectInfo
->Console
||
677 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
679 DPRINT1("ConSrvConnect - Allocate a new console\n");
682 * We are about to create a new console. However when ConSrvNewProcess
683 * was called, we didn't know that we wanted to create a new console and
684 * therefore, we by default inherited the handles table from our parent
685 * process. It's only now that we notice that in fact we do not need
686 * them, because we've created a new console and thus we must use it.
688 * Therefore, free the console we can have and our handles table,
689 * and recreate a new one later on.
691 ConSrvRemoveConsole(ProcessData
);
693 /* Initialize a new Console owned by the Console Leader Process */
694 Status
= ConSrvAllocateConsole(ProcessData
,
695 &ConnectInfo
->InputHandle
,
696 &ConnectInfo
->OutputHandle
,
697 &ConnectInfo
->ErrorHandle
,
698 &ConnectInfo
->ConsoleStartInfo
);
699 if (!NT_SUCCESS(Status
))
701 DPRINT1("Console allocation failed\n");
705 else /* We inherit it from the parent */
707 DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
709 /* Reuse our current console */
710 Status
= ConSrvInheritConsole(ProcessData
,
711 ConnectInfo
->Console
,
713 NULL
, // &ConnectInfo->InputHandle,
714 NULL
, // &ConnectInfo->OutputHandle,
715 NULL
); // &ConnectInfo->ErrorHandle);
716 if (!NT_SUCCESS(Status
))
718 DPRINT1("Console inheritance failed\n");
723 /* Return it to the caller */
724 ConnectInfo
->Console
= ProcessData
->Console
;
726 /* Input Wait Handle */
727 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
729 /* Set the Property Dialog Handler */
730 ProcessData
->PropDispatcher
= ConnectInfo
->PropDispatcher
;
732 /* Set the Ctrl Dispatcher */
733 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
735 return STATUS_SUCCESS
;
740 ConSrvDisconnect(PCSR_PROCESS Process
)
742 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
744 /**************************************************************************
745 * This function is called whenever a new process (GUI or CUI) is destroyed.
746 **************************************************************************/
748 DPRINT1("ConSrvDisconnect\n");
750 if ( ProcessData
->Console
!= NULL
||
751 ProcessData
->HandleTable
!= NULL
)
753 DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
754 ConSrvRemoveConsole(ProcessData
);
757 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
761 /* PUBLIC SERVER APIS *********************************************************/
763 CSR_API(SrvCloseHandle
)
765 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
767 return ConSrvRemoveObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
768 CloseHandleRequest
->ConsoleHandle
);
771 CSR_API(SrvVerifyConsoleIoHandle
)
773 NTSTATUS Status
= STATUS_SUCCESS
;
774 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
775 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
776 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
777 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
779 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
781 if (!IsConsoleHandle(ConsoleHandle
) ||
782 Index
>= ProcessData
->HandleTableSize
||
783 ProcessData
->HandleTable
[Index
].Object
== NULL
)
785 DPRINT("SrvVerifyConsoleIoHandle failed\n");
786 Status
= STATUS_INVALID_HANDLE
;
789 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
794 CSR_API(SrvDuplicateHandle
)
796 PCONSOLE_IO_HANDLE Entry
;
798 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
799 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
800 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
801 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
803 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
805 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
806 Index
>= ProcessData
->HandleTableSize
||
807 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
809 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
810 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
811 return STATUS_INVALID_HANDLE
;
814 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
816 DesiredAccess
= Entry
->Access
;
820 DesiredAccess
= DuplicateHandleRequest
->Access
;
821 /* Make sure the source handle has all the desired flags */
822 if ((Entry
->Access
& DesiredAccess
) == 0)
824 DPRINT1("Handle %p only has access %X; requested %X\n",
825 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
826 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
827 return STATUS_INVALID_PARAMETER
;
831 ApiMessage
->Status
= ConSrvInsertObject(ProcessData
,
832 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
835 DuplicateHandleRequest
->Inheritable
,
837 if (NT_SUCCESS(ApiMessage
->Status
) &&
838 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
840 ConSrvCloseHandleEntry(Entry
);
843 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
844 return ApiMessage
->Status
;