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 /* FUNCTIONS *****************************************************************/
108 /* static */ NTSTATUS
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
;
186 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
187 IN PCONSOLE_PROCESS_DATA TargetProcessData
)
189 NTSTATUS Status
= STATUS_SUCCESS
;
192 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
194 /* Inherit a handles table only if there is no already */
195 if (TargetProcessData
->HandleTable
!= NULL
/* || TargetProcessData->HandleTableSize != 0 */)
197 Status
= STATUS_UNSUCCESSFUL
; /* STATUS_INVALID_PARAMETER */
201 /* Allocate a new handle table for the child process */
202 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
204 SourceProcessData
->HandleTableSize
205 * sizeof(CONSOLE_IO_HANDLE
));
206 if (TargetProcessData
->HandleTable
== NULL
)
208 Status
= STATUS_NO_MEMORY
;
212 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
215 * Parse the parent process' handles table and, for each handle,
216 * do a copy of it and reference it, if the handle is inheritable.
218 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
220 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
221 SourceProcessData
->HandleTable
[i
].Inheritable
)
224 * Copy the handle data and increment the reference count of the
225 * pointed object (via the call to ConSrvCreateHandleEntry).
227 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
228 ConSrvCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
233 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
239 ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
)
241 DPRINT1("ConSrvFreeHandlesTable\n");
243 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
245 if (ProcessData
->HandleTable
!= NULL
)
249 /* Close all console handles and free the handle table memory */
250 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
252 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
254 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
255 ProcessData
->HandleTable
= NULL
;
258 ProcessData
->HandleTableSize
= 0;
260 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
265 ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
272 #define IO_HANDLES_INCREMENT 2*3
275 PCONSOLE_IO_HANDLE Block
;
277 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
279 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
281 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
286 if (i
>= ProcessData
->HandleTableSize
)
288 Block
= RtlAllocateHeap(ConSrvHeap
,
290 (ProcessData
->HandleTableSize
+
291 IO_HANDLES_INCREMENT
) * sizeof(CONSOLE_IO_HANDLE
));
294 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
295 return STATUS_UNSUCCESSFUL
;
298 ProcessData
->HandleTable
,
299 ProcessData
->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE
));
300 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
301 ProcessData
->HandleTable
= Block
;
302 ProcessData
->HandleTableSize
+= IO_HANDLES_INCREMENT
;
305 ProcessData
->HandleTable
[i
].Object
= Object
;
306 ProcessData
->HandleTable
[i
].Access
= Access
;
307 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
308 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
309 ConSrvCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
310 *Handle
= ULongToHandle((i
<< 2) | 0x3);
312 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
314 return STATUS_SUCCESS
;
319 ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData
,
322 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
325 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
327 if (h
>= ProcessData
->HandleTableSize
||
328 (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
330 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
331 return STATUS_INVALID_HANDLE
;
334 DPRINT1("ConSrvRemoveObject - Process 0x%p, Release 0x%p\n", ProcessData
->Process
, &ProcessData
->HandleTable
[h
]);
335 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
337 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
339 return STATUS_SUCCESS
;
344 ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData
,
347 PCONSOLE_IO_HANDLE
* Entry OPTIONAL
,
352 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
353 PCONSOLE_IO_HANDLE HandleEntry
= NULL
;
354 Object_t
* ObjectEntry
= NULL
;
357 if (Entry
) *Entry
= NULL
;
359 // DPRINT("ConSrvGetObject, Object: %x, %x, %x\n",
360 // Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
362 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
364 if ( IsConsoleHandle(Handle
) &&
365 h
< ProcessData
->HandleTableSize
)
367 HandleEntry
= &ProcessData
->HandleTable
[h
];
368 ObjectEntry
= HandleEntry
->Object
;
371 if ( HandleEntry
== NULL
||
372 ObjectEntry
== NULL
||
373 (HandleEntry
->Access
& Access
) == 0 ||
374 (Type
!= 0 && ObjectEntry
->Type
!= Type
) )
376 DPRINT1("ConSrvGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle
, Type
, Access
);
377 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
378 return STATUS_INVALID_HANDLE
;
381 _InterlockedIncrement(&ObjectEntry
->Console
->ReferenceCount
);
382 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
384 if (LockConsole
) EnterCriticalSection(&ObjectEntry
->Console
->Lock
);
386 /* Return the objects to the caller */
387 *Object
= ObjectEntry
;
388 if (Entry
) *Entry
= HandleEntry
;
390 return STATUS_SUCCESS
;
395 ConSrvReleaseObject(Object_t
*Object
,
396 BOOL IsConsoleLocked
)
398 ConSrvReleaseConsole(Object
->Console
, IsConsoleLocked
);
403 ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData
,
405 PHANDLE pInputHandle
,
406 PHANDLE pOutputHandle
,
407 PHANDLE pErrorHandle
,
408 PCONSOLE_START_INFO ConsoleStartInfo
)
410 NTSTATUS Status
= STATUS_SUCCESS
;
412 /* Initialize a new Console owned by this process */
413 Status
= ConSrvInitConsole(&ProcessData
->Console
, AppPath
, ConsoleStartInfo
, ProcessData
->Process
);
414 if (!NT_SUCCESS(Status
))
416 DPRINT1("Console initialization failed\n");
420 /* Initialize the handles table */
421 Status
= ConSrvInitHandlesTable(ProcessData
,
425 if (!NT_SUCCESS(Status
))
427 DPRINT1("Failed to initialize the handles table\n");
428 ConSrvDeleteConsole(ProcessData
->Console
);
429 ProcessData
->Console
= NULL
;
433 /* Duplicate the Input Event */
434 Status
= NtDuplicateObject(NtCurrentProcess(),
435 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
436 ProcessData
->Process
->ProcessHandle
,
437 &ProcessData
->ConsoleEvent
,
438 EVENT_ALL_ACCESS
, 0, 0);
439 if (!NT_SUCCESS(Status
))
441 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
442 ConSrvFreeHandlesTable(ProcessData
);
443 ConSrvDeleteConsole(ProcessData
->Console
);
444 ProcessData
->Console
= NULL
;
448 /* Insert the process into the processes list of the console */
449 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
451 /* Add a reference count because the process is tied to the console */
452 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
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 return STATUS_SUCCESS
;
511 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData
)
515 DPRINT1("ConSrvRemoveConsole\n");
517 /* Close all console handles and free the handle table memory */
518 ConSrvFreeHandlesTable(ProcessData
);
520 /* Detach process from console */
521 Console
= ProcessData
->Console
;
524 DPRINT1("ConSrvRemoveConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console
->ReferenceCount
);
525 ProcessData
->Console
= NULL
;
527 EnterCriticalSection(&Console
->Lock
);
528 DPRINT1("ConSrvRemoveConsole - Locking OK\n");
530 /* Remove ourselves from the console's list of processes */
531 RemoveEntryList(&ProcessData
->ConsoleLink
);
533 /* Update the console leader process */
534 // SetConsoleWndConsoleLeaderCID(Console);
536 /* Release the console */
537 ConSrvReleaseConsole(Console
, TRUE
);
538 //CloseHandle(ProcessData->ConsoleEvent);
539 //ProcessData->ConsoleEvent = NULL;
545 ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData
,
549 PCONSOLE ProcessConsole
;
551 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
552 ProcessConsole
= ProcessData
->Console
;
557 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
558 return STATUS_INVALID_HANDLE
;
561 InterlockedIncrement(&ProcessConsole
->ReferenceCount
);
562 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
564 if (LockConsole
) EnterCriticalSection(&ProcessConsole
->Lock
);
566 *Console
= ProcessConsole
;
568 return STATUS_SUCCESS
;
572 ConSrvReleaseConsole(PCONSOLE Console
,
573 BOOL IsConsoleLocked
)
575 if (IsConsoleLocked
) LeaveCriticalSection(&Console
->Lock
);
577 /* Decrement reference count */
578 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
579 ConSrvDeleteConsole(Console
);
584 ConSrvNewProcess(PCSR_PROCESS SourceProcess
,
585 PCSR_PROCESS TargetProcess
)
587 /**************************************************************************
588 * This function is called whenever a new process (GUI or CUI) is created.
590 * Copy the parent's handles table here if both the parent and the child
591 * processes are CUI. If we must actually create our proper console (and
592 * thus do not inherit from the console handles of the parent's), then we
593 * will clean this table in the next ConSrvConnect call. Why we are doing
594 * this? It's because here, we still don't know whether or not we must create
595 * a new console instead of inherit it from the parent, and, because in
596 * ConSrvConnect we don't have any reference to the parent process anymore.
597 **************************************************************************/
599 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
601 DPRINT1("ConSrvNewProcess\n");
602 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
604 /* An empty target process is invalid */
606 return STATUS_INVALID_PARAMETER
;
608 DPRINT1("ConSrvNewProcess - OK\n");
610 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
612 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
614 /* Initialize the new (target) process */
615 TargetProcessData
->Process
= TargetProcess
;
616 TargetProcessData
->ConsoleEvent
= NULL
;
617 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
618 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
621 TargetProcessData
->HandleTableSize
= 0;
622 TargetProcessData
->HandleTable
= NULL
;
624 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
626 /* Do nothing if the source process is NULL */
628 return STATUS_SUCCESS
;
630 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
633 * If both of the processes (parent and new child) are console applications,
634 * then try to inherit handles from the parent process.
636 if ( SourceProcessData
->Console
!= NULL
&& /* SourceProcessData->ConsoleApp */
637 TargetProcessData
->ConsoleApp
)
641 Status
= ConSrvInheritHandlesTable(SourceProcessData
, TargetProcessData
);
642 if (!NT_SUCCESS(Status
)) return Status
;
644 /* Temporary save the parent's console */
645 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
649 DPRINT1("ConSrvNewProcess - We don't inherit a handle table : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData
->Console
, TargetProcess
->Flags
);
652 return STATUS_SUCCESS
;
657 ConSrvConnect(IN PCSR_PROCESS CsrProcess
,
658 IN OUT PVOID ConnectionInfo
,
659 IN OUT PULONG ConnectionInfoLength
)
661 /**************************************************************************
662 * This function is called whenever a CUI new process is created.
663 **************************************************************************/
665 NTSTATUS Status
= STATUS_SUCCESS
;
666 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
667 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
669 DPRINT1("ConSrvConnect\n");
671 if ( ConnectionInfo
== NULL
||
672 ConnectionInfoLength
== NULL
||
673 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
675 DPRINT1("CONSRV: Connection failed\n");
676 return STATUS_UNSUCCESSFUL
;
679 /* If we don't need a console, then get out of here */
680 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
682 DPRINT("ConSrvConnect - No console needed\n");
683 return STATUS_SUCCESS
;
686 /* If we don't have a console, then create a new one... */
687 if (!ConnectInfo
->Console
||
688 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
690 DPRINT1("ConSrvConnect - Allocate a new console\n");
693 * We are about to create a new console. However when ConSrvNewProcess
694 * was called, we didn't know that we wanted to create a new console and
695 * therefore, we by default inherited the handles table from our parent
696 * process. It's only now that we notice that in fact we do not need
697 * them, because we've created a new console and thus we must use it.
699 * Therefore, free the console we can have and our handles table,
700 * and recreate a new one later on.
702 ConSrvRemoveConsole(ProcessData
);
704 /* Initialize a new Console owned by the Console Leader Process */
705 Status
= ConSrvAllocateConsole(ProcessData
,
706 ConnectInfo
->AppPath
,
707 &ConnectInfo
->InputHandle
,
708 &ConnectInfo
->OutputHandle
,
709 &ConnectInfo
->ErrorHandle
,
710 &ConnectInfo
->ConsoleStartInfo
);
711 if (!NT_SUCCESS(Status
))
713 DPRINT1("Console allocation failed\n");
717 else /* We inherit it from the parent */
719 DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
721 /* Reuse our current console */
722 Status
= ConSrvInheritConsole(ProcessData
,
723 ConnectInfo
->Console
,
725 NULL
, // &ConnectInfo->InputHandle,
726 NULL
, // &ConnectInfo->OutputHandle,
727 NULL
); // &ConnectInfo->ErrorHandle);
728 if (!NT_SUCCESS(Status
))
730 DPRINT1("Console inheritance failed\n");
735 /* Return it to the caller */
736 ConnectInfo
->Console
= ProcessData
->Console
;
738 /* Input Wait Handle */
739 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
741 /* Set the Property Dialog Handler */
742 ProcessData
->PropDispatcher
= ConnectInfo
->PropDispatcher
;
744 /* Set the Ctrl Dispatcher */
745 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
746 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
748 return STATUS_SUCCESS
;
753 ConSrvDisconnect(PCSR_PROCESS Process
)
755 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
757 /**************************************************************************
758 * This function is called whenever a new process (GUI or CUI) is destroyed.
759 **************************************************************************/
761 DPRINT1("ConSrvDisconnect\n");
763 if ( ProcessData
->Console
!= NULL
||
764 ProcessData
->HandleTable
!= NULL
)
766 DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
767 ConSrvRemoveConsole(ProcessData
);
770 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
775 CSR_API(SrvCloseHandle
)
777 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
779 return ConSrvRemoveObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
780 CloseHandleRequest
->ConsoleHandle
);
783 CSR_API(SrvVerifyConsoleIoHandle
)
785 NTSTATUS Status
= STATUS_SUCCESS
;
786 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
787 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
788 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
789 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
791 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
793 if (!IsConsoleHandle(ConsoleHandle
) ||
794 Index
>= ProcessData
->HandleTableSize
||
795 ProcessData
->HandleTable
[Index
].Object
== NULL
)
797 DPRINT("SrvVerifyConsoleIoHandle failed\n");
798 Status
= STATUS_INVALID_HANDLE
;
801 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
806 CSR_API(SrvDuplicateHandle
)
808 PCONSOLE_IO_HANDLE Entry
;
810 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
811 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
812 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
813 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
815 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
817 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
818 Index
>= ProcessData
->HandleTableSize
||
819 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
821 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
822 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
823 return STATUS_INVALID_HANDLE
;
826 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
828 DesiredAccess
= Entry
->Access
;
832 DesiredAccess
= DuplicateHandleRequest
->Access
;
833 /* Make sure the source handle has all the desired flags */
834 if ((Entry
->Access
& DesiredAccess
) == 0)
836 DPRINT1("Handle %p only has access %X; requested %X\n",
837 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
838 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
839 return STATUS_INVALID_PARAMETER
;
843 ApiMessage
->Status
= ConSrvInsertObject(ProcessData
,
844 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
847 DuplicateHandleRequest
->Inheritable
,
849 if (NT_SUCCESS(ApiMessage
->Status
) &&
850 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
852 ConSrvCloseHandleEntry(Entry
);
855 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
856 return ApiMessage
->Status
;