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
,
77 if (!IsListEmpty(&InputBuffer
->ReadWaitQueue
))
79 CsrDereferenceWait(&InputBuffer
->ReadWaitQueue
);
83 /* If the last handle to a screen buffer is closed, delete it... */
84 if (AdjustHandleCounts(Entry
, -1) == 0)
86 if (Object
->Type
== CONIO_SCREEN_BUFFER_MAGIC
)
88 PCONSOLE_SCREEN_BUFFER Buffer
= (PCONSOLE_SCREEN_BUFFER
)Object
;
89 /* ...unless it's the only buffer left. Windows allows deletion
90 * even of the last buffer, but having to deal with a lack of
91 * any active buffer might be error-prone. */
92 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
93 ConioDeleteScreenBuffer(Buffer
);
95 else if (Object
->Type
== CONIO_INPUT_BUFFER_MAGIC
)
97 DPRINT1("Closing the input buffer\n");
101 /// LOCK /// LeaveCriticalSection(&Console->Lock);
102 Entry
->Object
= NULL
;
107 /* FUNCTIONS *****************************************************************/
109 /* static */ NTSTATUS
111 ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData
,
112 OUT PHANDLE pInputHandle
,
113 OUT PHANDLE pOutputHandle
,
114 OUT PHANDLE pErrorHandle
)
117 HANDLE InputHandle
= INVALID_HANDLE_VALUE
,
118 OutputHandle
= INVALID_HANDLE_VALUE
,
119 ErrorHandle
= INVALID_HANDLE_VALUE
;
122 * Initialize the handles table. Use temporary variables to store
123 * the handles values in such a way that, if we fail, we don't
124 * return to the caller invalid handle values.
126 * Insert the IO handles.
129 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
131 /* Insert the Input handle */
132 Status
= ConSrvInsertObject(ProcessData
,
134 &ProcessData
->Console
->InputBuffer
.Header
,
135 GENERIC_READ
| GENERIC_WRITE
,
137 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
138 if (!NT_SUCCESS(Status
))
140 DPRINT1("Failed to insert the input handle\n");
141 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
142 ConSrvFreeHandlesTable(ProcessData
);
146 /* Insert the Output handle */
147 Status
= ConSrvInsertObject(ProcessData
,
149 &ProcessData
->Console
->ActiveBuffer
->Header
,
150 GENERIC_READ
| GENERIC_WRITE
,
152 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
153 if (!NT_SUCCESS(Status
))
155 DPRINT1("Failed to insert the output handle\n");
156 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
157 ConSrvFreeHandlesTable(ProcessData
);
161 /* Insert the Error handle */
162 Status
= ConSrvInsertObject(ProcessData
,
164 &ProcessData
->Console
->ActiveBuffer
->Header
,
165 GENERIC_READ
| GENERIC_WRITE
,
167 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
168 if (!NT_SUCCESS(Status
))
170 DPRINT1("Failed to insert the error handle\n");
171 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
172 ConSrvFreeHandlesTable(ProcessData
);
176 /* Return the newly created handles */
177 *pInputHandle
= InputHandle
;
178 *pOutputHandle
= OutputHandle
;
179 *pErrorHandle
= ErrorHandle
;
181 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
182 return STATUS_SUCCESS
;
187 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
188 IN PCONSOLE_PROCESS_DATA TargetProcessData
)
190 NTSTATUS Status
= STATUS_SUCCESS
;
193 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
195 /* Inherit a handles table only if there is no already */
196 if (TargetProcessData
->HandleTable
!= NULL
/* || TargetProcessData->HandleTableSize != 0 */)
198 Status
= STATUS_UNSUCCESSFUL
; /* STATUS_INVALID_PARAMETER */
202 /* Allocate a new handle table for the child process */
203 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
205 SourceProcessData
->HandleTableSize
206 * sizeof(CONSOLE_IO_HANDLE
));
207 if (TargetProcessData
->HandleTable
== NULL
)
209 Status
= STATUS_NO_MEMORY
;
213 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
216 * Parse the parent process' handles table and, for each handle,
217 * do a copy of it and reference it, if the handle is inheritable.
219 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
221 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
222 SourceProcessData
->HandleTable
[i
].Inheritable
)
225 * Copy the handle data and increment the reference count of the
226 * pointed object (via the call to ConSrvCreateHandleEntry).
228 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
229 ConSrvCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
234 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
240 ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
)
242 DPRINT1("ConSrvFreeHandlesTable\n");
244 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
246 if (ProcessData
->HandleTable
!= NULL
)
250 /* Close all console handles and free the handle table memory */
251 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
253 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
255 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
256 ProcessData
->HandleTable
= NULL
;
259 ProcessData
->HandleTableSize
= 0;
261 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
266 ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
273 #define IO_HANDLES_INCREMENT 2*3
276 PCONSOLE_IO_HANDLE Block
;
278 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
280 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
282 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
287 if (i
>= ProcessData
->HandleTableSize
)
289 Block
= RtlAllocateHeap(ConSrvHeap
,
291 (ProcessData
->HandleTableSize
+
292 IO_HANDLES_INCREMENT
) * sizeof(CONSOLE_IO_HANDLE
));
295 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
296 return STATUS_UNSUCCESSFUL
;
299 ProcessData
->HandleTable
,
300 ProcessData
->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE
));
301 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
302 ProcessData
->HandleTable
= Block
;
303 ProcessData
->HandleTableSize
+= IO_HANDLES_INCREMENT
;
306 ProcessData
->HandleTable
[i
].Object
= Object
;
307 ProcessData
->HandleTable
[i
].Access
= Access
;
308 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
309 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
310 ConSrvCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
311 *Handle
= ULongToHandle((i
<< 2) | 0x3);
313 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
315 return STATUS_SUCCESS
;
320 ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData
,
323 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
326 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
328 if (h
>= ProcessData
->HandleTableSize
||
329 (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
331 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
332 return STATUS_INVALID_HANDLE
;
335 DPRINT1("ConSrvRemoveObject - Process 0x%p, Release 0x%p\n", ProcessData
->Process
, &ProcessData
->HandleTable
[h
]);
336 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
338 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
340 return STATUS_SUCCESS
;
345 ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData
,
348 PCONSOLE_IO_HANDLE
* Entry OPTIONAL
,
353 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
354 PCONSOLE_IO_HANDLE HandleEntry
= NULL
;
355 Object_t
* ObjectEntry
= NULL
;
358 if (Entry
) *Entry
= NULL
;
360 // DPRINT("ConSrvGetObject, Object: %x, %x, %x\n",
361 // Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
363 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
365 if ( IsConsoleHandle(Handle
) &&
366 h
< ProcessData
->HandleTableSize
)
368 HandleEntry
= &ProcessData
->HandleTable
[h
];
369 ObjectEntry
= HandleEntry
->Object
;
372 if ( HandleEntry
== NULL
||
373 ObjectEntry
== NULL
||
374 (HandleEntry
->Access
& Access
) == 0 ||
375 (Type
!= 0 && ObjectEntry
->Type
!= Type
) )
377 DPRINT1("CsrGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle
, Type
, Access
);
378 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
379 return STATUS_INVALID_HANDLE
;
382 _InterlockedIncrement(&ObjectEntry
->Console
->ReferenceCount
);
383 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
385 if (LockConsole
) EnterCriticalSection(&ObjectEntry
->Console
->Lock
);
387 /* Return the objects to the caller */
388 *Object
= ObjectEntry
;
389 if (Entry
) *Entry
= HandleEntry
;
391 return STATUS_SUCCESS
;
396 ConSrvReleaseObject(Object_t
*Object
,
397 BOOL IsConsoleLocked
)
399 ConSrvReleaseConsole(Object
->Console
, IsConsoleLocked
);
404 ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData
,
405 PHANDLE pInputHandle
,
406 PHANDLE pOutputHandle
,
407 PHANDLE pErrorHandle
,
409 PCSR_PROCESS CsrProcess
)
411 NTSTATUS Status
= STATUS_SUCCESS
;
413 /* Initialize a new Console owned by the Console Leader Process */
414 Status
= ConSrvInitConsole(&ProcessData
->Console
, ShowCmd
, CsrProcess
);
415 if (!NT_SUCCESS(Status
))
417 DPRINT1("Console initialization failed\n");
421 /* Initialize the handles table */
422 Status
= ConSrvInitHandlesTable(ProcessData
,
426 if (!NT_SUCCESS(Status
))
428 DPRINT1("Failed to initialize the handles table\n");
429 ConSrvDeleteConsole(ProcessData
->Console
);
430 ProcessData
->Console
= NULL
;
434 /* Duplicate the Input Event */
435 Status
= NtDuplicateObject(NtCurrentProcess(),
436 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
437 ProcessData
->Process
->ProcessHandle
,
438 &ProcessData
->ConsoleEvent
,
439 EVENT_ALL_ACCESS
, 0, 0);
440 if (!NT_SUCCESS(Status
))
442 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
443 ConSrvFreeHandlesTable(ProcessData
);
444 ConSrvDeleteConsole(ProcessData
->Console
);
445 ProcessData
->Console
= NULL
;
449 /* Insert the process into the processes list of the console */
450 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
452 /* Add a reference count because the process is tied to the console */
453 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
455 return STATUS_SUCCESS
;
460 ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData
,
462 BOOL CreateNewHandlesTable
,
463 PHANDLE pInputHandle
,
464 PHANDLE pOutputHandle
,
465 PHANDLE pErrorHandle
)
467 NTSTATUS Status
= STATUS_SUCCESS
;
469 /* Inherit the console */
470 ProcessData
->Console
= Console
;
472 if (CreateNewHandlesTable
)
474 /* Initialize the handles table */
475 Status
= ConSrvInitHandlesTable(ProcessData
,
479 if (!NT_SUCCESS(Status
))
481 DPRINT1("Failed to initialize the handles table\n");
482 ProcessData
->Console
= NULL
;
487 /* Duplicate the Input Event */
488 Status
= NtDuplicateObject(NtCurrentProcess(),
489 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
490 ProcessData
->Process
->ProcessHandle
,
491 &ProcessData
->ConsoleEvent
,
492 EVENT_ALL_ACCESS
, 0, 0);
493 if (!NT_SUCCESS(Status
))
495 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
496 ConSrvFreeHandlesTable(ProcessData
); // NOTE: Always free the handles table.
497 ProcessData
->Console
= NULL
;
501 /* Insert the process into the processes list of the console */
502 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
504 /* Add a reference count because the process is tied to the console */
505 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
507 return STATUS_SUCCESS
;
512 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData
)
516 DPRINT1("ConSrvRemoveConsole\n");
518 /* Close all console handles and free the handle table memory */
519 ConSrvFreeHandlesTable(ProcessData
);
521 /* Detach process from console */
522 Console
= ProcessData
->Console
;
525 DPRINT1("ConSrvRemoveConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console
->ReferenceCount
);
526 ProcessData
->Console
= NULL
;
527 EnterCriticalSection(&Console
->Lock
);
528 DPRINT1("ConSrvRemoveConsole - Locking OK\n");
529 RemoveEntryList(&ProcessData
->ConsoleLink
);
530 ConSrvReleaseConsole(Console
, TRUE
);
531 //CloseHandle(ProcessData->ConsoleEvent);
532 //ProcessData->ConsoleEvent = NULL;
538 ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData
,
542 PCONSOLE ProcessConsole
;
544 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
545 ProcessConsole
= ProcessData
->Console
;
550 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
551 return STATUS_INVALID_HANDLE
;
554 InterlockedIncrement(&ProcessConsole
->ReferenceCount
);
555 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
557 if (LockConsole
) EnterCriticalSection(&ProcessConsole
->Lock
);
559 *Console
= ProcessConsole
;
561 return STATUS_SUCCESS
;
565 ConSrvReleaseConsole(PCONSOLE Console
,
566 BOOL IsConsoleLocked
)
568 if (IsConsoleLocked
) LeaveCriticalSection(&Console
->Lock
);
570 /* Decrement reference count */
571 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
572 ConSrvDeleteConsole(Console
);
577 ConSrvNewProcess(PCSR_PROCESS SourceProcess
,
578 PCSR_PROCESS TargetProcess
)
580 /**************************************************************************
581 * This function is called whenever a new process (GUI or CUI) is created.
583 * Copy the parent's handles table here if both the parent and the child
584 * processes are CUI. If we must actually create our proper console (and
585 * thus do not inherit from the console handles of the parent's), then we
586 * will clean this table in the next ConSrvConnect call. Why we are doing
587 * this? It's because here, we still don't know whether or not we must create
588 * a new console instead of inherit it from the parent, and, because in
589 * ConSrvConnect we don't have any reference to the parent process anymore.
590 **************************************************************************/
592 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
594 DPRINT1("ConSrvNewProcess\n");
595 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
597 /* An empty target process is invalid */
599 return STATUS_INVALID_PARAMETER
;
601 DPRINT1("ConSrvNewProcess - OK\n");
603 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
604 DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData
);
606 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
608 /* Initialize the new (target) process */
609 TargetProcessData
->Process
= TargetProcess
;
610 TargetProcessData
->ConsoleEvent
= NULL
;
611 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
612 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
615 TargetProcessData
->HandleTableSize
= 0;
616 TargetProcessData
->HandleTable
= NULL
;
618 /**** HACK !!!! ****/ RtlZeroMemory(&TargetProcessData
->HandleTableLock
, sizeof(RTL_CRITICAL_SECTION
));
619 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
621 /* Do nothing if the source process is NULL */
623 return STATUS_SUCCESS
;
625 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
626 DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData
);
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
;
645 DPRINT1("ConSrvNewProcess - We don't inherit a handle table : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData
->Console
, TargetProcess
->Flags
);
648 return STATUS_SUCCESS
;
653 ConSrvConnect(IN PCSR_PROCESS CsrProcess
,
654 IN OUT PVOID ConnectionInfo
,
655 IN OUT PULONG ConnectionInfoLength
)
657 /**************************************************************************
658 * This function is called whenever a CUI new process is created.
659 **************************************************************************/
661 NTSTATUS Status
= STATUS_SUCCESS
;
662 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
663 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
665 DPRINT1("ConSrvConnect\n");
667 if ( ConnectionInfo
== NULL
||
668 ConnectionInfoLength
== NULL
||
669 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
671 DPRINT1("CONSRV: Connection failed\n");
672 return STATUS_UNSUCCESSFUL
;
675 /* If we don't need a console, then get out of here */
676 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
678 DPRINT("ConSrvConnect - No console needed\n");
679 return STATUS_SUCCESS
;
682 /* If we don't have a console, then create a new one... */
683 if (!ConnectInfo
->Console
||
684 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
686 DPRINT1("ConSrvConnect - Allocate a new console\n");
689 * We are about to create a new console. However when ConSrvNewProcess
690 * was called, we didn't know that we wanted to create a new console and
691 * therefore, we by default inherited the handles table from our parent
692 * process. It's only now that we notice that in fact we do not need
693 * them, because we've created a new console and thus we must use it.
695 * Therefore, free the console we can have and our handles table,
696 * and recreate a new one later on.
698 ConSrvRemoveConsole(ProcessData
);
700 /* Initialize a new Console owned by the Console Leader Process */
701 Status
= ConSrvAllocateConsole(ProcessData
,
702 &ConnectInfo
->InputHandle
,
703 &ConnectInfo
->OutputHandle
,
704 &ConnectInfo
->ErrorHandle
,
705 ConnectInfo
->ShowCmd
,
707 if (!NT_SUCCESS(Status
))
709 DPRINT1("Console allocation failed\n");
713 else /* We inherit it from the parent */
715 DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
717 /* Reuse our current console */
718 Status
= ConSrvInheritConsole(ProcessData
,
719 ConnectInfo
->Console
,
721 NULL
, // &ConnectInfo->InputHandle,
722 NULL
, // &ConnectInfo->OutputHandle,
723 NULL
); // &ConnectInfo->ErrorHandle);
724 if (!NT_SUCCESS(Status
))
726 DPRINT1("Console inheritance failed\n");
731 /* Return it to the caller */
732 ConnectInfo
->Console
= ProcessData
->Console
;
734 /* Input Wait Handle */
735 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
737 /* Set the Ctrl Dispatcher */
738 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
739 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
741 return STATUS_SUCCESS
;
746 ConSrvDisconnect(PCSR_PROCESS Process
)
748 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
750 /**************************************************************************
751 * This function is called whenever a new process (GUI or CUI) is destroyed.
752 **************************************************************************/
754 DPRINT1("ConSrvDisconnect\n");
756 if ( ProcessData
->Console
!= NULL
||
757 ProcessData
->HandleTable
!= NULL
)
759 DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
760 ConSrvRemoveConsole(ProcessData
);
763 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
768 CSR_API(SrvCloseHandle
)
770 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
772 return ConSrvRemoveObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
773 CloseHandleRequest
->ConsoleHandle
);
776 CSR_API(SrvVerifyConsoleIoHandle
)
778 NTSTATUS Status
= STATUS_SUCCESS
;
779 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
780 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
781 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
782 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
784 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
786 if (!IsConsoleHandle(ConsoleHandle
) ||
787 Index
>= ProcessData
->HandleTableSize
||
788 ProcessData
->HandleTable
[Index
].Object
== NULL
)
790 DPRINT("CsrVerifyObject failed\n");
791 Status
= STATUS_INVALID_HANDLE
;
794 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
799 CSR_API(SrvDuplicateHandle
)
801 PCONSOLE_IO_HANDLE Entry
;
803 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
804 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
805 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
806 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
808 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
810 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
811 Index
>= ProcessData
->HandleTableSize
||
812 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
814 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
815 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
816 return STATUS_INVALID_HANDLE
;
819 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
821 DesiredAccess
= Entry
->Access
;
825 DesiredAccess
= DuplicateHandleRequest
->Access
;
826 /* Make sure the source handle has all the desired flags */
827 if ((Entry
->Access
& DesiredAccess
) == 0)
829 DPRINT1("Handle %p only has access %X; requested %X\n",
830 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
831 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
832 return STATUS_INVALID_PARAMETER
;
836 ApiMessage
->Status
= ConSrvInsertObject(ProcessData
,
837 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
840 DuplicateHandleRequest
->Inheritable
,
842 if (NT_SUCCESS(ApiMessage
->Status
) &&
843 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
845 ConSrvCloseHandleEntry(Entry
);
848 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
849 return ApiMessage
->Status
;
853 CSR_API(CsrGetInputWaitHandle)
855 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
857 GetConsoleInputWaitHandle->InputWaitHandle =
858 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
860 return STATUS_SUCCESS;