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 Win32CsrCreateHandleEntry(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 Win32CsrCloseHandleEntry(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 // TODO: Dereference the notified waits.
79 /* If the last handle to a screen buffer is closed, delete it... */
80 if (AdjustHandleCounts(Entry
, -1) == 0)
82 if (Object
->Type
== CONIO_SCREEN_BUFFER_MAGIC
)
84 PCONSOLE_SCREEN_BUFFER Buffer
= (PCONSOLE_SCREEN_BUFFER
)Object
;
85 /* ...unless it's the only buffer left. Windows allows deletion
86 * even of the last buffer, but having to deal with a lack of
87 * any active buffer might be error-prone. */
88 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
89 ConioDeleteScreenBuffer(Buffer
);
91 else if (Object
->Type
== CONIO_INPUT_BUFFER_MAGIC
)
93 DPRINT1("Closing the input buffer\n");
97 /// LOCK /// LeaveCriticalSection(&Console->Lock);
103 /* FUNCTIONS *****************************************************************/
105 /* static */ NTSTATUS
107 Win32CsrInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData
,
108 OUT PHANDLE pInputHandle
,
109 OUT PHANDLE pOutputHandle
,
110 OUT PHANDLE pErrorHandle
)
113 HANDLE InputHandle
= INVALID_HANDLE_VALUE
,
114 OutputHandle
= INVALID_HANDLE_VALUE
,
115 ErrorHandle
= INVALID_HANDLE_VALUE
;
118 * Initialize the handles table. Use temporary variables to store
119 * the handles values in such a way that, if we fail, we don't
120 * return to the caller invalid handle values.
122 * Insert the IO handles.
125 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
127 /* Insert the Input handle */
128 Status
= Win32CsrInsertObject(ProcessData
,
130 &ProcessData
->Console
->InputBuffer
.Header
,
131 GENERIC_READ
| GENERIC_WRITE
,
133 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
134 if (!NT_SUCCESS(Status
))
136 DPRINT1("Failed to insert the input handle\n");
137 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
138 Win32CsrFreeHandlesTable(ProcessData
);
142 /* Insert the Output handle */
143 Status
= Win32CsrInsertObject(ProcessData
,
145 &ProcessData
->Console
->ActiveBuffer
->Header
,
146 GENERIC_READ
| GENERIC_WRITE
,
148 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
149 if (!NT_SUCCESS(Status
))
151 DPRINT1("Failed to insert the output handle\n");
152 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
153 Win32CsrFreeHandlesTable(ProcessData
);
157 /* Insert the Error handle */
158 Status
= Win32CsrInsertObject(ProcessData
,
160 &ProcessData
->Console
->ActiveBuffer
->Header
,
161 GENERIC_READ
| GENERIC_WRITE
,
163 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
164 if (!NT_SUCCESS(Status
))
166 DPRINT1("Failed to insert the error handle\n");
167 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
168 Win32CsrFreeHandlesTable(ProcessData
);
172 /* Return the newly created handles */
173 *pInputHandle
= InputHandle
;
174 *pOutputHandle
= OutputHandle
;
175 *pErrorHandle
= ErrorHandle
;
177 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
178 return STATUS_SUCCESS
;
183 Win32CsrInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
184 IN PCONSOLE_PROCESS_DATA TargetProcessData
)
186 NTSTATUS Status
= STATUS_SUCCESS
;
189 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
191 /* Inherit a handles table only if there is no already */
192 if (TargetProcessData
->HandleTable
!= NULL
/* || TargetProcessData->HandleTableSize != 0 */)
194 Status
= STATUS_UNSUCCESSFUL
; /* STATUS_INVALID_PARAMETER */
198 /* Allocate a new handle table for the child process */
199 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
201 SourceProcessData
->HandleTableSize
202 * sizeof(CONSOLE_IO_HANDLE
));
203 if (TargetProcessData
->HandleTable
== NULL
)
205 Status
= STATUS_NO_MEMORY
;
209 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
212 * Parse the parent process' handles table and, for each handle,
213 * do a copy of it and reference it, if the handle is inheritable.
215 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
217 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
218 SourceProcessData
->HandleTable
[i
].Inheritable
)
221 * Copy the handle data and increment the reference count of the
222 * pointed object (via the call to Win32CsrCreateHandleEntry).
224 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
225 Win32CsrCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
230 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
236 Win32CsrFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
)
238 DPRINT1("Win32CsrFreeHandlesTable\n");
240 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
242 if (ProcessData
->HandleTable
!= NULL
)
246 /* Close all console handles and free the handle table memory */
247 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
249 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
251 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
252 ProcessData
->HandleTable
= NULL
;
255 ProcessData
->HandleTableSize
= 0;
257 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
262 Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
269 #define IO_HANDLES_INCREMENT 2*3
272 PCONSOLE_IO_HANDLE Block
;
274 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
276 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
278 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
283 if (i
>= ProcessData
->HandleTableSize
)
285 Block
= RtlAllocateHeap(ConSrvHeap
,
287 (ProcessData
->HandleTableSize
+
288 IO_HANDLES_INCREMENT
) * sizeof(CONSOLE_IO_HANDLE
));
291 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
292 return STATUS_UNSUCCESSFUL
;
295 ProcessData
->HandleTable
,
296 ProcessData
->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE
));
297 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
298 ProcessData
->HandleTable
= Block
;
299 ProcessData
->HandleTableSize
+= IO_HANDLES_INCREMENT
;
302 ProcessData
->HandleTable
[i
].Object
= Object
;
303 ProcessData
->HandleTable
[i
].Access
= Access
;
304 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
305 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
306 Win32CsrCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
307 *Handle
= ULongToHandle((i
<< 2) | 0x3);
309 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
311 return STATUS_SUCCESS
;
316 Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData
,
319 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
322 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
324 if (h
>= ProcessData
->HandleTableSize
||
325 (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
327 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
328 return STATUS_INVALID_HANDLE
;
331 DPRINT1("Win32CsrReleaseObject - Process 0x%p, Release 0x%p\n", ProcessData
->Process
, &ProcessData
->HandleTable
[h
]);
332 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
334 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
336 return STATUS_SUCCESS
;
341 Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData
,
344 PCONSOLE_IO_HANDLE
* Entry OPTIONAL
,
349 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
350 PCONSOLE_IO_HANDLE HandleEntry
= NULL
;
351 Object_t
* ObjectEntry
= NULL
;
354 if (Entry
) *Entry
= NULL
;
356 // DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
357 // Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
359 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
361 if ( IsConsoleHandle(Handle
) &&
362 h
< ProcessData
->HandleTableSize
)
364 HandleEntry
= &ProcessData
->HandleTable
[h
];
365 ObjectEntry
= HandleEntry
->Object
;
368 if ( HandleEntry
== NULL
||
369 ObjectEntry
== NULL
||
370 (HandleEntry
->Access
& Access
) == 0 ||
371 (Type
!= 0 && ObjectEntry
->Type
!= Type
) )
373 DPRINT1("CsrGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle
, Type
, Access
);
374 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
375 return STATUS_INVALID_HANDLE
;
378 _InterlockedIncrement(&ObjectEntry
->Console
->ReferenceCount
);
379 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
381 if (LockConsole
) EnterCriticalSection(&ObjectEntry
->Console
->Lock
);
383 /* Return the objects to the caller */
384 *Object
= ObjectEntry
;
385 if (Entry
) *Entry
= HandleEntry
;
387 return STATUS_SUCCESS
;
391 Win32CsrUnlockConsole(PCONSOLE Console
,
392 BOOL IsConsoleLocked
)
394 if (IsConsoleLocked
) LeaveCriticalSection(&Console
->Lock
);
396 /* Decrement reference count */
397 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
398 ConioDeleteConsole(Console
);
403 Win32CsrUnlockObject(Object_t
*Object
,
404 BOOL IsConsoleLocked
)
406 Win32CsrUnlockConsole(Object
->Console
, IsConsoleLocked
);
411 Win32CsrAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData
,
412 PHANDLE pInputHandle
,
413 PHANDLE pOutputHandle
,
414 PHANDLE pErrorHandle
,
416 PCSR_PROCESS CsrProcess
)
418 NTSTATUS Status
= STATUS_SUCCESS
;
420 /* Initialize a new Console owned by the Console Leader Process */
421 Status
= CsrInitConsole(&ProcessData
->Console
, ShowCmd
, CsrProcess
);
422 if (!NT_SUCCESS(Status
))
424 DPRINT1("Console initialization failed\n");
428 /* Initialize the handles table */
429 Status
= Win32CsrInitHandlesTable(ProcessData
,
433 if (!NT_SUCCESS(Status
))
435 DPRINT1("Failed to initialize the handles table\n");
437 // Win32CsrReleaseConsole(ProcessData);
438 ConioDeleteConsole(ProcessData
->Console
);
439 ProcessData
->Console
= NULL
;
449 Win32CsrReleaseConsole(PCONSOLE_PROCESS_DATA ProcessData
)
453 DPRINT1("Win32CsrReleaseConsole\n");
455 /* Close all console handles and free the handle table memory */
456 Win32CsrFreeHandlesTable(ProcessData
);
458 /* Detach process from console */
459 Console
= ProcessData
->Console
;
462 DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console
->ReferenceCount
);
463 ProcessData
->Console
= NULL
;
464 EnterCriticalSection(&Console
->Lock
);
465 DPRINT1("Win32CsrReleaseConsole - Locking OK\n");
466 RemoveEntryList(&ProcessData
->ConsoleLink
);
467 Win32CsrUnlockConsole(Console
, TRUE
);
468 //CloseHandle(ProcessData->ConsoleEvent);
469 //ProcessData->ConsoleEvent = NULL;
475 ConioConsoleFromProcessData(PCONSOLE_PROCESS_DATA ProcessData
,
479 PCONSOLE ProcessConsole
;
481 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
482 ProcessConsole
= ProcessData
->Console
;
487 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
488 return STATUS_INVALID_HANDLE
;
491 InterlockedIncrement(&ProcessConsole
->ReferenceCount
);
492 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
494 if (LockConsole
) EnterCriticalSection(&ProcessConsole
->Lock
);
496 *Console
= ProcessConsole
;
498 return STATUS_SUCCESS
;
505 ConsoleNewProcess(PCSR_PROCESS SourceProcess
,
506 PCSR_PROCESS TargetProcess
)
508 /**************************************************************************
509 * This function is called whenever a new process (GUI or CUI) is created.
511 * Copy the parent's handles table here if both the parent and the child
512 * processes are CUI. If we must actually create our proper console (and
513 * thus do not inherit from the console handles of the parent's), then we
514 * will clean this table in the next ConsoleConnect call. Why we are doing
515 * this? It's because here, we still don't know whether or not we must create
516 * a new console instead of inherit it from the parent, and, because in
517 * ConsoleConnect we don't have any reference to the parent process anymore.
518 **************************************************************************/
520 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
522 DPRINT1("ConsoleNewProcess inside\n");
523 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
525 /* An empty target process is invalid */
527 return STATUS_INVALID_PARAMETER
;
529 DPRINT1("ConsoleNewProcess - OK\n");
531 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
532 DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData
);
534 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
536 /* Initialize the new (target) process */
537 TargetProcessData
->Process
= TargetProcess
;
538 TargetProcessData
->ConsoleEvent
= NULL
;
539 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
540 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
543 TargetProcessData
->HandleTableSize
= 0;
544 TargetProcessData
->HandleTable
= NULL
;
546 /**** HACK !!!! ****/ RtlZeroMemory(&TargetProcessData
->HandleTableLock
, sizeof(RTL_CRITICAL_SECTION
));
547 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
549 /* Do nothing if the source process is NULL */
551 return STATUS_SUCCESS
;
553 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
554 DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData
);
557 * If both of the processes (parent and new child) are console applications,
558 * then try to inherit handles from the parent process.
560 if ( SourceProcessData
->Console
!= NULL
&& /* SourceProcessData->ConsoleApp */
561 TargetProcessData
->ConsoleApp
)
565 Status
= Win32CsrInheritHandlesTable(SourceProcessData
, TargetProcessData
);
566 if (!NT_SUCCESS(Status
))
571 /* Temporary "inherit" the console from the parent */
572 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
576 DPRINT1("ConsoleNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData
->Console
, TargetProcess
->Flags
);
579 return STATUS_SUCCESS
;
584 ConsoleConnect(IN PCSR_PROCESS CsrProcess
,
585 IN OUT PVOID ConnectionInfo
,
586 IN OUT PULONG ConnectionInfoLength
)
588 /**************************************************************************
589 * This function is called whenever a CUI new process is created.
590 **************************************************************************/
592 NTSTATUS Status
= STATUS_SUCCESS
;
593 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
594 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
596 DPRINT1("ConsoleConnect\n");
598 if ( ConnectionInfo
== NULL
||
599 ConnectionInfoLength
== NULL
||
600 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
602 DPRINT1("CONSRV: Connection failed\n");
603 return STATUS_UNSUCCESSFUL
;
606 /* If we don't need a console, then get out of here */
607 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
609 DPRINT("ConsoleConnect - No console needed\n");
610 return STATUS_SUCCESS
;
613 /* If we don't have a console, then create a new one... */
614 if (!ConnectInfo
->Console
||
615 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
617 DPRINT1("ConsoleConnect - Allocate a new console\n");
620 * We are about to create a new console. However when ConsoleNewProcess
621 * was called, we didn't know that we wanted to create a new console and
622 * therefore, we by default inherited the handles table from our parent
623 * process. It's only now that we notice that in fact we do not need
624 * them, because we've created a new console and thus we must use it.
626 * Therefore, free the console we can have and our handles table,
627 * and recreate a new one later on.
629 Win32CsrReleaseConsole(ProcessData
);
631 /* Initialize a new Console owned by the Console Leader Process */
632 Status
= Win32CsrAllocateConsole(ProcessData
,
633 &ConnectInfo
->InputHandle
,
634 &ConnectInfo
->OutputHandle
,
635 &ConnectInfo
->ErrorHandle
,
636 ConnectInfo
->ShowCmd
,
638 if (!NT_SUCCESS(Status
))
640 DPRINT1("Console allocation failed\n");
644 else /* We inherit it from the parent */
646 DPRINT1("ConsoleConnect - Reuse current (parent's) console\n");
648 /* Reuse our current console */
649 ProcessData
->Console
= ConnectInfo
->Console
;
652 /* Add a reference count because the process is tied to the console */
653 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
655 /* Insert the process into the processes list of the console */
656 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
658 /// TODO: Move this up ?
659 /* Duplicate the Event */
660 Status
= NtDuplicateObject(NtCurrentProcess(),
661 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
662 ProcessData
->Process
->ProcessHandle
,
663 &ProcessData
->ConsoleEvent
,
664 EVENT_ALL_ACCESS
, 0, 0);
665 if (!NT_SUCCESS(Status
))
667 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
668 Win32CsrReleaseConsole(ProcessData
);
672 /* Return it to the caller */
673 ConnectInfo
->Console
= ProcessData
->Console
;
675 /* Input Wait Handle */
676 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
678 /* Set the Ctrl Dispatcher */
679 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
680 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
682 return STATUS_SUCCESS
;
687 ConsoleDisconnect(PCSR_PROCESS Process
)
689 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
691 /**************************************************************************
692 * This function is called whenever a new process (GUI or CUI) is destroyed.
693 **************************************************************************/
695 DPRINT1("ConsoleDisconnect called\n");
696 if ( ProcessData
->Console
!= NULL
||
697 ProcessData
->HandleTable
!= NULL
)
699 DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
700 Win32CsrReleaseConsole(ProcessData
);
703 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
708 CSR_API(SrvCloseHandle
)
710 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
712 return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
713 CloseHandleRequest
->ConsoleHandle
);
716 CSR_API(SrvVerifyConsoleIoHandle
)
718 NTSTATUS Status
= STATUS_SUCCESS
;
719 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
720 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
721 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
722 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
724 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
726 if (!IsConsoleHandle(ConsoleHandle
) ||
727 Index
>= ProcessData
->HandleTableSize
||
728 ProcessData
->HandleTable
[Index
].Object
== NULL
)
730 DPRINT("CsrVerifyObject failed\n");
731 Status
= STATUS_INVALID_HANDLE
;
734 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
739 CSR_API(SrvDuplicateHandle
)
741 PCONSOLE_IO_HANDLE Entry
;
743 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
744 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
745 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
746 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
748 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
750 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
751 Index
>= ProcessData
->HandleTableSize
||
752 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
754 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
755 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
756 return STATUS_INVALID_HANDLE
;
759 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
761 DesiredAccess
= Entry
->Access
;
765 DesiredAccess
= DuplicateHandleRequest
->Access
;
766 /* Make sure the source handle has all the desired flags */
767 if ((Entry
->Access
& DesiredAccess
) == 0)
769 DPRINT1("Handle %p only has access %X; requested %X\n",
770 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
771 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
772 return STATUS_INVALID_PARAMETER
;
776 ApiMessage
->Status
= Win32CsrInsertObject(ProcessData
,
777 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
780 DuplicateHandleRequest
->Inheritable
,
782 if (NT_SUCCESS(ApiMessage
->Status
) &&
783 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
785 Win32CsrCloseHandleEntry(Entry
);
788 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
789 return ApiMessage
->Status
;
793 CSR_API(CsrGetInputWaitHandle)
795 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
797 GetConsoleInputWaitHandle->InputWaitHandle =
798 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
800 return STATUS_SUCCESS;