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 IO Handle 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 Object_t
*Object
= Entry
->Object
;
41 EnterCriticalSection(&Object
->Console
->Lock
);
42 AdjustHandleCounts(Entry
, +1);
43 LeaveCriticalSection(&Object
->Console
->Lock
);
47 Win32CsrCloseHandleEntry(PCONSOLE_IO_HANDLE Entry
)
49 Object_t
*Object
= Entry
->Object
;
52 PCONSOLE Console
= Object
->Console
;
53 EnterCriticalSection(&Console
->Lock
);
55 /* If the last handle to a screen buffer is closed, delete it... */
56 if (AdjustHandleCounts(Entry
, -1) == 0)
58 if (Object
->Type
== CONIO_SCREEN_BUFFER_MAGIC
)
60 PCONSOLE_SCREEN_BUFFER Buffer
= (PCONSOLE_SCREEN_BUFFER
)Object
;
61 /* ...unless it's the only buffer left. Windows allows deletion
62 * even of the last buffer, but having to deal with a lack of
63 * any active buffer might be error-prone. */
64 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
65 ConioDeleteScreenBuffer(Buffer
);
67 else if (Object
->Type
== CONIO_CONSOLE_MAGIC
)
69 /* TODO: FIXME: Destroy here the console ?? */
70 // ConioDeleteConsole(Console);
74 LeaveCriticalSection(&Console
->Lock
);
80 /* FUNCTIONS *****************************************************************/
84 Win32CsrInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
85 IN PCONSOLE_PROCESS_DATA TargetProcessData
)
87 NTSTATUS Status
= STATUS_SUCCESS
;
90 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
92 /* Inherit a handles table only if there is no already */
93 if (TargetProcessData
->HandleTable
!= NULL
/* || TargetProcessData->HandleTableSize != 0 */)
95 Status
= STATUS_UNSUCCESSFUL
; /* STATUS_INVALID_PARAMETER */
99 /* Allocate a new handle table for the child process */
100 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
102 SourceProcessData
->HandleTableSize
103 * sizeof(CONSOLE_IO_HANDLE
));
104 if (TargetProcessData
->HandleTable
== NULL
)
106 Status
= STATUS_NO_MEMORY
;
110 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
113 * Parse the parent process' handles table and, for each handle,
114 * do a copy of it and reference it, if the handle is inheritable.
116 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
118 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
119 SourceProcessData
->HandleTable
[i
].Inheritable
)
122 * Copy the handle data and increment the reference count of the
123 * pointed object (via the call to Win32CsrCreateHandleEntry).
125 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
126 Win32CsrCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
131 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
137 Win32CsrFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
)
139 DPRINT1("Win32CsrFreeHandlesTable\n");
141 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
143 if (ProcessData
->HandleTable
!= NULL
)
147 /* Close all console handles and free the handle table memory */
148 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
150 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
152 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
153 ProcessData
->HandleTable
= NULL
;
156 ProcessData
->HandleTableSize
= 0;
158 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
163 Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
171 PCONSOLE_IO_HANDLE Block
;
173 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
175 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
177 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
182 if (i
>= ProcessData
->HandleTableSize
)
184 Block
= RtlAllocateHeap(ConSrvHeap
,
186 (ProcessData
->HandleTableSize
+ 64) * sizeof(CONSOLE_IO_HANDLE
));
189 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
190 return STATUS_UNSUCCESSFUL
;
193 ProcessData
->HandleTable
,
194 ProcessData
->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE
));
195 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
196 ProcessData
->HandleTable
= Block
;
197 ProcessData
->HandleTableSize
+= 64;
199 ProcessData
->HandleTable
[i
].Object
= Object
;
200 ProcessData
->HandleTable
[i
].Access
= Access
;
201 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
202 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
203 Win32CsrCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
204 *Handle
= ULongToHandle((i
<< 2) | 0x3);
206 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
207 return STATUS_SUCCESS
;
212 Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData
,
215 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
218 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
220 if (h
>= ProcessData
->HandleTableSize
||
221 (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
223 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
224 return STATUS_INVALID_HANDLE
;
227 DPRINT1("Win32CsrReleaseObject - Process 0x%p, Release 0x%p\n", ProcessData
->Process
, &ProcessData
->HandleTable
[h
]);
228 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
230 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
232 return STATUS_SUCCESS
;
237 Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData
,
243 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
245 DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
246 Object
, Handle
, ProcessData
? ProcessData
->HandleTableSize
: 0);
248 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
250 if ( !IsConsoleHandle(Handle
) ||
251 h
>= ProcessData
->HandleTableSize
||
252 (*Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
||
253 ~ProcessData
->HandleTable
[h
].Access
& Access
||
254 (Type
!= 0 && (*Object
)->Type
!= Type
) )
256 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle
);
257 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
258 return STATUS_INVALID_HANDLE
;
261 _InterlockedIncrement(&(*Object
)->Console
->ReferenceCount
);
262 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
264 EnterCriticalSection(&((*Object
)->Console
->Lock
));
265 return STATUS_SUCCESS
;
269 Win32CsrUnlockConsole(PCONSOLE Console
)
271 LeaveCriticalSection(&Console
->Lock
);
273 /* Decrement reference count */
274 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
275 ConioDeleteConsole(Console
);
280 Win32CsrUnlockObject(Object_t
*Object
)
282 Win32CsrUnlockConsole(Object
->Console
);
287 Win32CsrReleaseConsole(PCONSOLE_PROCESS_DATA ProcessData
)
291 DPRINT1("Win32CsrReleaseConsole\n");
293 /* Close all console handles and free the handle table memory */
294 Win32CsrFreeHandlesTable(ProcessData
);
296 /* Detach process from console */
297 Console
= ProcessData
->Console
;
300 DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console
->ReferenceCount
);
301 ProcessData
->Console
= NULL
;
302 EnterCriticalSection(&Console
->Lock
);
303 RemoveEntryList(&ProcessData
->ConsoleLink
);
304 Win32CsrUnlockConsole(Console
);
305 //CloseHandle(ProcessData->ConsoleEvent);
306 //ProcessData->ConsoleEvent = NULL;
314 ConsoleNewProcess(PCSR_PROCESS SourceProcess
,
315 PCSR_PROCESS TargetProcess
)
317 /**************************************************************************
318 * This function is called whenever a new process (GUI or CUI) is created.
320 * Copy the parent's handles table here if both the parent and the child
321 * processes are CUI. If we must actually create our proper console (and
322 * thus do not inherit from the console handles of the parent's), then we
323 * will clean this table in the next ConsoleConnect call. Why we are doing
324 * this? It's because here, we still don't know whether or not we must create
325 * a new console instead of inherit it from the parent, and, because in
326 * ConsoleConnect we don't have any reference to the parent process anymore.
327 **************************************************************************/
329 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
331 DPRINT1("ConsoleNewProcess inside\n");
332 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
334 /* An empty target process is invalid */
336 return STATUS_INVALID_PARAMETER
;
338 DPRINT1("ConsoleNewProcess - OK\n");
340 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
341 DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData
);
343 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
345 /* Initialize the new (target) process */
346 TargetProcessData
->Process
= TargetProcess
;
347 TargetProcessData
->ConsoleEvent
= NULL
;
348 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
349 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
352 TargetProcessData
->HandleTableSize
= 0;
353 TargetProcessData
->HandleTable
= NULL
;
355 /**** HACK !!!! ****/ RtlZeroMemory(&TargetProcessData
->HandleTableLock
, sizeof(RTL_CRITICAL_SECTION
));
356 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
358 /* Do nothing if the source process is NULL */
360 return STATUS_SUCCESS
;
362 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
363 DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData
);
366 * If both of the processes (parent and new child) are console applications,
367 * then try to inherit handles from the parent process.
369 if ( SourceProcessData
->Console
!= NULL
&& /* SourceProcessData->ConsoleApp */
370 TargetProcessData
->ConsoleApp
)
374 Status
= Win32CsrInheritHandlesTable(SourceProcessData
, TargetProcessData
);
375 if (!NT_SUCCESS(Status
))
380 // FIXME: Do it before, or after the handles table inheritance ??
381 /* Temporary "inherit" the console from the parent */
382 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
386 DPRINT1("ConsoleNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData
->Console
, TargetProcess
->Flags
);
389 return STATUS_SUCCESS
;
394 ConsoleConnect(IN PCSR_PROCESS CsrProcess
,
395 IN OUT PVOID ConnectionInfo
,
396 IN OUT PULONG ConnectionInfoLength
)
398 /**************************************************************************
399 * This function is called whenever a CUI new process is created.
400 **************************************************************************/
402 NTSTATUS Status
= STATUS_SUCCESS
;
403 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
404 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
405 BOOLEAN NewConsole
= FALSE
;
407 DPRINT1("ConsoleConnect\n");
409 if ( ConnectionInfo
== NULL
||
410 ConnectionInfoLength
== NULL
||
411 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
413 DPRINT1("CONSRV: Connection failed\n");
414 return STATUS_UNSUCCESSFUL
;
417 /* If we don't need a console, then get out of here */
418 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
420 DPRINT("ConsoleConnect - No console needed\n");
421 return STATUS_SUCCESS
;
424 /* If we don't have a console, then create a new one... */
425 if (!ConnectInfo
->Console
||
426 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
428 DPRINT1("ConsoleConnect - Allocate a new console\n");
431 * We are about to create a new console. However when ConsoleNewProcess
432 * was called, we didn't know that we wanted to create a new console and
433 * therefore, we by default inherited the handles table from our parent
434 * process. It's only now that we notice that in fact we do not need
435 * them, because we've created a new console and thus we must use it.
437 * Therefore, free the console we can have and our handles table,
438 * and recreate a new one later on.
440 Win32CsrReleaseConsole(ProcessData
);
442 /* Initialize a new Console owned by the Console Leader Process */
444 Status
= CsrInitConsole(&ProcessData
->Console
, ConnectInfo
->ShowCmd
, CsrProcess
);
445 if (!NT_SUCCESS(Status
))
447 DPRINT1("Console initialization failed\n");
451 else /* We inherit it from the parent */
453 DPRINT1("ConsoleConnect - Reuse current (parent's) console\n");
455 /* Reuse our current console */
457 ProcessData
->Console
= ConnectInfo
->Console
;
460 /* Add a reference count because the process is tied to the console */
461 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
463 /* Insert the process into the processes list of the console */
464 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
466 /* Return it to the caller */
467 ConnectInfo
->Console
= ProcessData
->Console
;
472 * Create a new handle table - Insert the IO handles
475 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
477 /* Insert the Input handle */
478 Status
= Win32CsrInsertObject(ProcessData
,
479 &ConnectInfo
->InputHandle
,
480 &ProcessData
->Console
->Header
,
481 GENERIC_READ
| GENERIC_WRITE
,
483 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
484 if (!NT_SUCCESS(Status
))
486 DPRINT1("Failed to insert the input handle\n");
487 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
488 Win32CsrReleaseConsole(ProcessData
);
489 // ConioDeleteConsole(ProcessData->Console);
490 // ProcessData->Console = NULL;
494 /* Insert the Output handle */
495 Status
= Win32CsrInsertObject(ProcessData
,
496 &ConnectInfo
->OutputHandle
,
497 &ProcessData
->Console
->ActiveBuffer
->Header
,
498 GENERIC_READ
| GENERIC_WRITE
,
500 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
501 if (!NT_SUCCESS(Status
))
503 DPRINT1("Failed to insert the output handle\n");
504 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
505 Win32CsrReleaseConsole(ProcessData
);
506 // Win32CsrReleaseObject(ProcessData,
507 // ConnectInfo->InputHandle);
508 // ConioDeleteConsole(ProcessData->Console);
509 // ProcessData->Console = NULL;
513 /* Insert the Error handle */
514 Status
= Win32CsrInsertObject(ProcessData
,
515 &ConnectInfo
->ErrorHandle
,
516 &ProcessData
->Console
->ActiveBuffer
->Header
,
517 GENERIC_READ
| GENERIC_WRITE
,
519 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
520 if (!NT_SUCCESS(Status
))
522 DPRINT1("Failed to insert the error handle\n");
523 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
524 Win32CsrReleaseConsole(ProcessData
);
525 // Win32CsrReleaseObject(ProcessData,
526 // ConnectInfo->OutputHandle);
527 // Win32CsrReleaseObject(ProcessData,
528 // ConnectInfo->InputHandle);
529 // ConioDeleteConsole(ProcessData->Console);
530 // ProcessData->Console = NULL;
534 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
537 /* Duplicate the Event */
538 Status
= NtDuplicateObject(NtCurrentProcess(),
539 ProcessData
->Console
->ActiveEvent
,
540 ProcessData
->Process
->ProcessHandle
,
541 &ProcessData
->ConsoleEvent
,
542 EVENT_ALL_ACCESS
, 0, 0);
543 if (!NT_SUCCESS(Status
))
545 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
546 Win32CsrReleaseConsole(ProcessData
);
549 // Win32CsrReleaseObject(ProcessData,
550 // ConnectInfo->ErrorHandle);
551 // Win32CsrReleaseObject(ProcessData,
552 // ConnectInfo->OutputHandle);
553 // Win32CsrReleaseObject(ProcessData,
554 // ConnectInfo->InputHandle);
556 // ConioDeleteConsole(ProcessData->Console); // FIXME: Just release the console ?
557 // ProcessData->Console = NULL;
560 /* Input Wait Handle */
561 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
563 /* Set the Ctrl Dispatcher */
564 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
565 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
567 return STATUS_SUCCESS
;
572 ConsoleDisconnect(PCSR_PROCESS Process
)
574 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
576 /**************************************************************************
577 * This function is called whenever a new process (GUI or CUI) is destroyed.
578 **************************************************************************/
580 DPRINT1("ConsoleDisconnect called\n");
581 if ( ProcessData
->Console
!= NULL
||
582 ProcessData
->HandleTable
!= NULL
)
584 DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
585 Win32CsrReleaseConsole(ProcessData
);
588 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
593 CSR_API(SrvCloseHandle
)
595 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
597 return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
598 CloseHandleRequest
->ConsoleHandle
);
601 CSR_API(SrvVerifyConsoleIoHandle
)
603 NTSTATUS Status
= STATUS_SUCCESS
;
604 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
605 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
606 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
607 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
609 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
611 if (!IsConsoleHandle(ConsoleHandle
) ||
612 Index
>= ProcessData
->HandleTableSize
||
613 ProcessData
->HandleTable
[Index
].Object
== NULL
)
615 DPRINT("CsrVerifyObject failed\n");
616 Status
= STATUS_INVALID_HANDLE
;
619 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
624 CSR_API(SrvDuplicateHandle
)
626 PCONSOLE_IO_HANDLE Entry
;
628 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
629 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
630 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
631 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
633 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
635 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
636 Index
>= ProcessData
->HandleTableSize
||
637 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
639 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
640 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
641 return STATUS_INVALID_HANDLE
;
644 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
646 DesiredAccess
= Entry
->Access
;
650 DesiredAccess
= DuplicateHandleRequest
->Access
;
651 /* Make sure the source handle has all the desired flags */
652 if (~Entry
->Access
& DesiredAccess
)
654 DPRINT1("Handle %p only has access %X; requested %X\n",
655 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
656 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
657 return STATUS_INVALID_PARAMETER
;
661 ApiMessage
->Status
= Win32CsrInsertObject(ProcessData
,
662 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
665 DuplicateHandleRequest
->Inheritable
,
667 if (NT_SUCCESS(ApiMessage
->Status
) &&
668 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
670 Win32CsrCloseHandleEntry(Entry
);
673 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
674 return ApiMessage
->Status
;
678 CSR_API(CsrGetInputWaitHandle)
680 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
682 GetConsoleInputWaitHandle->InputWaitHandle =
683 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
685 return STATUS_SUCCESS;