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("CsrGetObject 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
)
514 PCONSOLE_PROCESS_DATA NewProcessData
;
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
;
528 EnterCriticalSection(&Console
->Lock
);
529 DPRINT1("ConSrvRemoveConsole - Locking OK\n");
531 /* Remove ourselves from the console's list of processes */
532 RemoveEntryList(&ProcessData
->ConsoleLink
);
534 /* Update the console leader process */
535 NewProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Blink
,
536 CONSOLE_PROCESS_DATA
,
538 Console
->ConsoleLeaderCID
= NewProcessData
->Process
->ClientId
;
539 SetConsoleWndConsoleLeaderCID(Console
);
541 /* Release the console */
542 ConSrvReleaseConsole(Console
, TRUE
);
543 //CloseHandle(ProcessData->ConsoleEvent);
544 //ProcessData->ConsoleEvent = NULL;
550 ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData
,
554 PCONSOLE ProcessConsole
;
556 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
557 ProcessConsole
= ProcessData
->Console
;
562 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
563 return STATUS_INVALID_HANDLE
;
566 InterlockedIncrement(&ProcessConsole
->ReferenceCount
);
567 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
569 if (LockConsole
) EnterCriticalSection(&ProcessConsole
->Lock
);
571 *Console
= ProcessConsole
;
573 return STATUS_SUCCESS
;
577 ConSrvReleaseConsole(PCONSOLE Console
,
578 BOOL IsConsoleLocked
)
580 if (IsConsoleLocked
) LeaveCriticalSection(&Console
->Lock
);
582 /* Decrement reference count */
583 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
584 ConSrvDeleteConsole(Console
);
589 ConSrvNewProcess(PCSR_PROCESS SourceProcess
,
590 PCSR_PROCESS TargetProcess
)
592 /**************************************************************************
593 * This function is called whenever a new process (GUI or CUI) is created.
595 * Copy the parent's handles table here if both the parent and the child
596 * processes are CUI. If we must actually create our proper console (and
597 * thus do not inherit from the console handles of the parent's), then we
598 * will clean this table in the next ConSrvConnect call. Why we are doing
599 * this? It's because here, we still don't know whether or not we must create
600 * a new console instead of inherit it from the parent, and, because in
601 * ConSrvConnect we don't have any reference to the parent process anymore.
602 **************************************************************************/
604 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
606 DPRINT1("ConSrvNewProcess\n");
607 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
609 /* An empty target process is invalid */
611 return STATUS_INVALID_PARAMETER
;
613 DPRINT1("ConSrvNewProcess - OK\n");
615 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
617 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
619 /* Initialize the new (target) process */
620 TargetProcessData
->Process
= TargetProcess
;
621 TargetProcessData
->ConsoleEvent
= NULL
;
622 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
623 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
626 TargetProcessData
->HandleTableSize
= 0;
627 TargetProcessData
->HandleTable
= NULL
;
629 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
631 /* Do nothing if the source process is NULL */
633 return STATUS_SUCCESS
;
635 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
638 * If both of the processes (parent and new child) are console applications,
639 * then try to inherit handles from the parent process.
641 if ( SourceProcessData
->Console
!= NULL
&& /* SourceProcessData->ConsoleApp */
642 TargetProcessData
->ConsoleApp
)
646 Status
= ConSrvInheritHandlesTable(SourceProcessData
, TargetProcessData
);
647 if (!NT_SUCCESS(Status
)) return Status
;
649 /* Temporary save the parent's console */
650 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
654 DPRINT1("ConSrvNewProcess - We don't inherit a handle table : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData
->Console
, TargetProcess
->Flags
);
657 return STATUS_SUCCESS
;
662 ConSrvConnect(IN PCSR_PROCESS CsrProcess
,
663 IN OUT PVOID ConnectionInfo
,
664 IN OUT PULONG ConnectionInfoLength
)
666 /**************************************************************************
667 * This function is called whenever a CUI new process is created.
668 **************************************************************************/
670 NTSTATUS Status
= STATUS_SUCCESS
;
671 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
672 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
674 DPRINT1("ConSrvConnect\n");
676 if ( ConnectionInfo
== NULL
||
677 ConnectionInfoLength
== NULL
||
678 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
680 DPRINT1("CONSRV: Connection failed\n");
681 return STATUS_UNSUCCESSFUL
;
684 /* If we don't need a console, then get out of here */
685 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
687 DPRINT("ConSrvConnect - No console needed\n");
688 return STATUS_SUCCESS
;
691 /* If we don't have a console, then create a new one... */
692 if (!ConnectInfo
->Console
||
693 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
695 DPRINT1("ConSrvConnect - Allocate a new console\n");
698 * We are about to create a new console. However when ConSrvNewProcess
699 * was called, we didn't know that we wanted to create a new console and
700 * therefore, we by default inherited the handles table from our parent
701 * process. It's only now that we notice that in fact we do not need
702 * them, because we've created a new console and thus we must use it.
704 * Therefore, free the console we can have and our handles table,
705 * and recreate a new one later on.
707 ConSrvRemoveConsole(ProcessData
);
709 /* Initialize a new Console owned by the Console Leader Process */
710 Status
= ConSrvAllocateConsole(ProcessData
,
711 ConnectInfo
->AppPath
,
712 &ConnectInfo
->InputHandle
,
713 &ConnectInfo
->OutputHandle
,
714 &ConnectInfo
->ErrorHandle
,
715 &ConnectInfo
->ConsoleStartInfo
);
716 if (!NT_SUCCESS(Status
))
718 DPRINT1("Console allocation failed\n");
722 else /* We inherit it from the parent */
724 DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
726 /* Reuse our current console */
727 Status
= ConSrvInheritConsole(ProcessData
,
728 ConnectInfo
->Console
,
730 NULL
, // &ConnectInfo->InputHandle,
731 NULL
, // &ConnectInfo->OutputHandle,
732 NULL
); // &ConnectInfo->ErrorHandle);
733 if (!NT_SUCCESS(Status
))
735 DPRINT1("Console inheritance failed\n");
740 /* Return it to the caller */
741 ConnectInfo
->Console
= ProcessData
->Console
;
743 /* Input Wait Handle */
744 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
746 /* Set the Property Dialog Handler */
747 ProcessData
->PropDispatcher
= ConnectInfo
->PropDispatcher
;
749 /* Set the Ctrl Dispatcher */
750 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
751 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
753 return STATUS_SUCCESS
;
758 ConSrvDisconnect(PCSR_PROCESS Process
)
760 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
762 /**************************************************************************
763 * This function is called whenever a new process (GUI or CUI) is destroyed.
764 **************************************************************************/
766 DPRINT1("ConSrvDisconnect\n");
768 if ( ProcessData
->Console
!= NULL
||
769 ProcessData
->HandleTable
!= NULL
)
771 DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
772 ConSrvRemoveConsole(ProcessData
);
775 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
780 CSR_API(SrvCloseHandle
)
782 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
784 return ConSrvRemoveObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
785 CloseHandleRequest
->ConsoleHandle
);
788 CSR_API(SrvVerifyConsoleIoHandle
)
790 NTSTATUS Status
= STATUS_SUCCESS
;
791 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
792 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
793 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
794 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
796 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
798 if (!IsConsoleHandle(ConsoleHandle
) ||
799 Index
>= ProcessData
->HandleTableSize
||
800 ProcessData
->HandleTable
[Index
].Object
== NULL
)
802 DPRINT("CsrVerifyObject failed\n");
803 Status
= STATUS_INVALID_HANDLE
;
806 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
811 CSR_API(SrvDuplicateHandle
)
813 PCONSOLE_IO_HANDLE Entry
;
815 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
816 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
817 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
818 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
820 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
822 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
823 Index
>= ProcessData
->HandleTableSize
||
824 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
826 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
827 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
828 return STATUS_INVALID_HANDLE
;
831 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
833 DesiredAccess
= Entry
->Access
;
837 DesiredAccess
= DuplicateHandleRequest
->Access
;
838 /* Make sure the source handle has all the desired flags */
839 if ((Entry
->Access
& DesiredAccess
) == 0)
841 DPRINT1("Handle %p only has access %X; requested %X\n",
842 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
843 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
844 return STATUS_INVALID_PARAMETER
;
848 ApiMessage
->Status
= ConSrvInsertObject(ProcessData
,
849 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
852 DuplicateHandleRequest
->Inheritable
,
854 if (NT_SUCCESS(ApiMessage
->Status
) &&
855 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
857 ConSrvCloseHandleEntry(Entry
);
860 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
861 return ApiMessage
->Status
;
865 CSR_API(CsrGetInputWaitHandle)
867 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
869 GetConsoleInputWaitHandle->InputWaitHandle =
870 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
872 return STATUS_SUCCESS;