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");
430 // ConSrvRemoveConsole(ProcessData);
431 ConSrvDeleteConsole(ProcessData
->Console
);
432 ProcessData
->Console
= NULL
;
442 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData
)
446 DPRINT1("ConSrvRemoveConsole\n");
448 /* Close all console handles and free the handle table memory */
449 ConSrvFreeHandlesTable(ProcessData
);
451 /* Detach process from console */
452 Console
= ProcessData
->Console
;
455 DPRINT1("ConSrvRemoveConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console
->ReferenceCount
);
456 ProcessData
->Console
= NULL
;
457 EnterCriticalSection(&Console
->Lock
);
458 DPRINT1("ConSrvRemoveConsole - Locking OK\n");
459 RemoveEntryList(&ProcessData
->ConsoleLink
);
460 ConSrvReleaseConsole(Console
, TRUE
);
461 //CloseHandle(ProcessData->ConsoleEvent);
462 //ProcessData->ConsoleEvent = NULL;
468 ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData
,
472 PCONSOLE ProcessConsole
;
474 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
475 ProcessConsole
= ProcessData
->Console
;
480 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
481 return STATUS_INVALID_HANDLE
;
484 InterlockedIncrement(&ProcessConsole
->ReferenceCount
);
485 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
487 if (LockConsole
) EnterCriticalSection(&ProcessConsole
->Lock
);
489 *Console
= ProcessConsole
;
491 return STATUS_SUCCESS
;
495 ConSrvReleaseConsole(PCONSOLE Console
,
496 BOOL IsConsoleLocked
)
498 if (IsConsoleLocked
) LeaveCriticalSection(&Console
->Lock
);
500 /* Decrement reference count */
501 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
502 ConSrvDeleteConsole(Console
);
507 ConSrvNewProcess(PCSR_PROCESS SourceProcess
,
508 PCSR_PROCESS TargetProcess
)
510 /**************************************************************************
511 * This function is called whenever a new process (GUI or CUI) is created.
513 * Copy the parent's handles table here if both the parent and the child
514 * processes are CUI. If we must actually create our proper console (and
515 * thus do not inherit from the console handles of the parent's), then we
516 * will clean this table in the next ConSrvConnect call. Why we are doing
517 * this? It's because here, we still don't know whether or not we must create
518 * a new console instead of inherit it from the parent, and, because in
519 * ConSrvConnect we don't have any reference to the parent process anymore.
520 **************************************************************************/
522 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
524 DPRINT1("ConSrvNewProcess inside\n");
525 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
527 /* An empty target process is invalid */
529 return STATUS_INVALID_PARAMETER
;
531 DPRINT1("ConSrvNewProcess - OK\n");
533 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
534 DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData
);
536 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
538 /* Initialize the new (target) process */
539 TargetProcessData
->Process
= TargetProcess
;
540 TargetProcessData
->ConsoleEvent
= NULL
;
541 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
542 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
545 TargetProcessData
->HandleTableSize
= 0;
546 TargetProcessData
->HandleTable
= NULL
;
548 /**** HACK !!!! ****/ RtlZeroMemory(&TargetProcessData
->HandleTableLock
, sizeof(RTL_CRITICAL_SECTION
));
549 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
551 /* Do nothing if the source process is NULL */
553 return STATUS_SUCCESS
;
555 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
556 DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData
);
559 * If both of the processes (parent and new child) are console applications,
560 * then try to inherit handles from the parent process.
562 if ( SourceProcessData
->Console
!= NULL
&& /* SourceProcessData->ConsoleApp */
563 TargetProcessData
->ConsoleApp
)
567 Status
= ConSrvInheritHandlesTable(SourceProcessData
, TargetProcessData
);
568 if (!NT_SUCCESS(Status
))
573 /* Temporary "inherit" the console from the parent */
574 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
578 DPRINT1("ConSrvNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData
->Console
, TargetProcess
->Flags
);
581 return STATUS_SUCCESS
;
586 ConSrvConnect(IN PCSR_PROCESS CsrProcess
,
587 IN OUT PVOID ConnectionInfo
,
588 IN OUT PULONG ConnectionInfoLength
)
590 /**************************************************************************
591 * This function is called whenever a CUI new process is created.
592 **************************************************************************/
594 NTSTATUS Status
= STATUS_SUCCESS
;
595 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
596 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
598 DPRINT1("ConSrvConnect\n");
600 if ( ConnectionInfo
== NULL
||
601 ConnectionInfoLength
== NULL
||
602 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
604 DPRINT1("CONSRV: Connection failed\n");
605 return STATUS_UNSUCCESSFUL
;
608 /* If we don't need a console, then get out of here */
609 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
611 DPRINT("ConSrvConnect - No console needed\n");
612 return STATUS_SUCCESS
;
615 /* If we don't have a console, then create a new one... */
616 if (!ConnectInfo
->Console
||
617 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
619 DPRINT1("ConSrvConnect - Allocate a new console\n");
622 * We are about to create a new console. However when ConSrvNewProcess
623 * was called, we didn't know that we wanted to create a new console and
624 * therefore, we by default inherited the handles table from our parent
625 * process. It's only now that we notice that in fact we do not need
626 * them, because we've created a new console and thus we must use it.
628 * Therefore, free the console we can have and our handles table,
629 * and recreate a new one later on.
631 ConSrvRemoveConsole(ProcessData
);
633 /* Initialize a new Console owned by the Console Leader Process */
634 Status
= ConSrvAllocateConsole(ProcessData
,
635 &ConnectInfo
->InputHandle
,
636 &ConnectInfo
->OutputHandle
,
637 &ConnectInfo
->ErrorHandle
,
638 ConnectInfo
->ShowCmd
,
640 if (!NT_SUCCESS(Status
))
642 DPRINT1("Console allocation failed\n");
646 else /* We inherit it from the parent */
648 DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
650 /* Reuse our current console */
651 ProcessData
->Console
= ConnectInfo
->Console
;
654 /* Add a reference count because the process is tied to the console */
655 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
657 /* Insert the process into the processes list of the console */
658 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
660 /// TODO: Move this up ?
661 /* Duplicate the Event */
662 Status
= NtDuplicateObject(NtCurrentProcess(),
663 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
664 ProcessData
->Process
->ProcessHandle
,
665 &ProcessData
->ConsoleEvent
,
666 EVENT_ALL_ACCESS
, 0, 0);
667 if (!NT_SUCCESS(Status
))
669 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
670 ConSrvRemoveConsole(ProcessData
);
674 /* Return it to the caller */
675 ConnectInfo
->Console
= ProcessData
->Console
;
677 /* Input Wait Handle */
678 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
680 /* Set the Ctrl Dispatcher */
681 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
682 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
684 return STATUS_SUCCESS
;
689 ConSrvDisconnect(PCSR_PROCESS Process
)
691 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
693 /**************************************************************************
694 * This function is called whenever a new process (GUI or CUI) is destroyed.
695 **************************************************************************/
697 DPRINT1("ConSrvDisconnect called\n");
698 if ( ProcessData
->Console
!= NULL
||
699 ProcessData
->HandleTable
!= NULL
)
701 DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
702 ConSrvRemoveConsole(ProcessData
);
705 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
710 CSR_API(SrvCloseHandle
)
712 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
714 return ConSrvRemoveObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
715 CloseHandleRequest
->ConsoleHandle
);
718 CSR_API(SrvVerifyConsoleIoHandle
)
720 NTSTATUS Status
= STATUS_SUCCESS
;
721 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
722 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
723 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
724 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
726 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
728 if (!IsConsoleHandle(ConsoleHandle
) ||
729 Index
>= ProcessData
->HandleTableSize
||
730 ProcessData
->HandleTable
[Index
].Object
== NULL
)
732 DPRINT("CsrVerifyObject failed\n");
733 Status
= STATUS_INVALID_HANDLE
;
736 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
741 CSR_API(SrvDuplicateHandle
)
743 PCONSOLE_IO_HANDLE Entry
;
745 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
746 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
747 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
748 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
750 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
752 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
753 Index
>= ProcessData
->HandleTableSize
||
754 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
756 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
757 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
758 return STATUS_INVALID_HANDLE
;
761 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
763 DesiredAccess
= Entry
->Access
;
767 DesiredAccess
= DuplicateHandleRequest
->Access
;
768 /* Make sure the source handle has all the desired flags */
769 if ((Entry
->Access
& DesiredAccess
) == 0)
771 DPRINT1("Handle %p only has access %X; requested %X\n",
772 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
773 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
774 return STATUS_INVALID_PARAMETER
;
778 ApiMessage
->Status
= ConSrvInsertObject(ProcessData
,
779 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
782 DuplicateHandleRequest
->Inheritable
,
784 if (NT_SUCCESS(ApiMessage
->Status
) &&
785 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
787 ConSrvCloseHandleEntry(Entry
);
790 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
791 return ApiMessage
->Status
;
795 CSR_API(CsrGetInputWaitHandle)
797 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
799 GetConsoleInputWaitHandle->InputWaitHandle =
800 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
802 return STATUS_SUCCESS;