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(PCSRSS_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(PCSRSS_HANDLE Entry
)
40 Object_t
*Object
= Entry
->Object
;
41 EnterCriticalSection(&Object
->Console
->Lock
);
42 AdjustHandleCounts(Entry
, +1);
43 LeaveCriticalSection(&Object
->Console
->Lock
);
47 Win32CsrCloseHandleEntry(PCSRSS_HANDLE Entry
)
49 Object_t
*Object
= Entry
->Object
;
52 PCSRSS_CONSOLE 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 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_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 Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
94 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
96 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
98 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
103 if (i
>= ProcessData
->HandleTableSize
)
105 Block
= RtlAllocateHeap(ConSrvHeap
,
107 (ProcessData
->HandleTableSize
+ 64) * sizeof(CSRSS_HANDLE
));
110 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
111 return STATUS_UNSUCCESSFUL
;
114 ProcessData
->HandleTable
,
115 ProcessData
->HandleTableSize
* sizeof(CSRSS_HANDLE
));
116 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
117 ProcessData
->HandleTable
= Block
;
118 ProcessData
->HandleTableSize
+= 64;
120 ProcessData
->HandleTable
[i
].Object
= Object
;
121 ProcessData
->HandleTable
[i
].Access
= Access
;
122 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
123 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
124 Win32CsrCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
125 *Handle
= UlongToHandle((i
<< 2) | 0x3);
126 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
127 return STATUS_SUCCESS
;
132 Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData
,
135 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
138 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
140 if (h
>= ProcessData
->HandleTableSize
||
141 (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
143 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
144 return STATUS_INVALID_HANDLE
;
147 DPRINT1("Win32CsrReleaseObject - Process 0x%p, Release 0x%p\n", ProcessData
->Process
, &ProcessData
->HandleTable
[h
]);
148 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
150 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
152 return STATUS_SUCCESS
;
157 Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData
,
163 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
165 DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
166 Object
, Handle
, ProcessData
? ProcessData
->HandleTableSize
: 0);
168 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
170 if ( !IsConsoleHandle(Handle
) ||
171 h
>= ProcessData
->HandleTableSize
||
172 (*Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
||
173 ~ProcessData
->HandleTable
[h
].Access
& Access
||
174 (Type
!= 0 && (*Object
)->Type
!= Type
) )
176 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle
);
177 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
178 return STATUS_INVALID_HANDLE
;
181 _InterlockedIncrement(&(*Object
)->Console
->ReferenceCount
);
182 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
184 EnterCriticalSection(&((*Object
)->Console
->Lock
));
185 return STATUS_SUCCESS
;
189 Win32CsrUnlockConsole(PCSRSS_CONSOLE Console
)
191 LeaveCriticalSection(&Console
->Lock
);
193 /* Decrement reference count */
194 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
195 ConioDeleteConsole(Console
);
200 Win32CsrUnlockObject(Object_t
*Object
)
202 Win32CsrUnlockConsole(Object
->Console
);
207 /** Remark: this function can be called by SrvAttachConsole (not yet implemented) **/
210 ConsoleNewProcess(PCSR_PROCESS SourceProcess
,
211 PCSR_PROCESS TargetProcess
)
213 /**************************************************************************
214 * This function is called whenever a new process (GUI or CUI) is created.
216 * Copy the parent's handles table here if both the parent and the child
217 * processes are CUI. If we must actually create our proper console (and
218 * thus do not inherit from the console handles of the parent's), then we
219 * will clean this table in the next ConsoleConnect call. Why we are doing
220 * this? It's because here, we still don't know whether or not we must create
221 * a new console instead of inherit it from the parent, and, because in
222 * ConsoleConnect we don't have any reference to the parent process anymore.
223 **************************************************************************/
225 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
228 DPRINT1("ConsoleNewProcess inside\n");
229 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
231 /* An empty target process is invalid */
233 return STATUS_INVALID_PARAMETER
;
235 DPRINT1("ConsoleNewProcess - OK\n");
237 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
238 DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData
);
240 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
242 /* Initialize the new (target) process */
243 TargetProcessData
->Process
= TargetProcess
;
244 TargetProcessData
->ConsoleEvent
= NULL
;
245 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
246 // TargetProcessData->bInheritHandles = FALSE;
247 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
250 TargetProcessData
->HandleTableSize
= 0;
251 TargetProcessData
->HandleTable
= NULL
;
253 /* HACK */ RtlZeroMemory(&TargetProcessData
->HandleTableLock
, sizeof(RTL_CRITICAL_SECTION
));
254 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
256 /* Do nothing if the source process is NULL */
258 return STATUS_SUCCESS
;
260 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
261 DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData
);
264 * If both of the processes (parent and new child) are console applications,
265 * then try to inherit handles from the parent process.
267 if ( SourceProcessData
->Console
!= NULL
&& /* SourceProcessData->ConsoleApp */
268 TargetProcessData
->ConsoleApp
)
271 if (TargetProcessData->HandleTableSize)
273 return STATUS_INVALID_PARAMETER;
277 DPRINT1("ConsoleNewProcess - Copy the handle table (1)\n");
278 /* Temporary "inherit" the console from the parent */
279 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
280 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
281 DPRINT1("ConsoleNewProcess - Copy the handle table (2)\n");
283 /* Allocate a new handle table for the child process */
284 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
286 SourceProcessData
->HandleTableSize
287 * sizeof(CSRSS_HANDLE
));
288 if (TargetProcessData
->HandleTable
== NULL
)
290 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
291 return STATUS_UNSUCCESSFUL
;
294 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
297 * Parse the parent process' handles table and, for each handle,
298 * do a copy of it and reference it, if the handle is inheritable.
300 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
302 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
303 SourceProcessData
->HandleTable
[i
].Inheritable
)
306 * Copy the handle data and increment the reference count of the
307 * pointed object (via the call to Win32CsrCreateHandleEntry).
309 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
310 Win32CsrCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
314 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
318 DPRINT1("ConsoleNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData
->Console
, TargetProcess
->Flags
);
321 return STATUS_SUCCESS
;
324 // Temporary ; move it to a header.
325 NTSTATUS WINAPI
CsrInitConsole(PCSRSS_CONSOLE
* NewConsole
, int ShowCmd
);
329 ConsoleConnect(IN PCSR_PROCESS CsrProcess
,
330 IN OUT PVOID ConnectionInfo
,
331 IN OUT PULONG ConnectionInfoLength
)
333 /**************************************************************************
334 * This function is called whenever a CUI new process is created.
335 **************************************************************************/
337 NTSTATUS Status
= STATUS_SUCCESS
;
338 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
339 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
340 BOOLEAN NewConsole
= FALSE
;
341 // PCSRSS_CONSOLE Console = NULL;
343 DPRINT1("ConsoleConnect\n");
345 if ( ConnectionInfo
== NULL
||
346 ConnectionInfoLength
== NULL
||
347 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
349 DPRINT1("CONSRV: Connection failed\n");
350 return STATUS_UNSUCCESSFUL
;
353 /* If we don't need a console, then get out of here */
354 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
356 DPRINT("ConsoleConnect - No console needed\n");
357 return STATUS_SUCCESS
;
360 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
362 /* If we don't have a console, then create a new one... */
363 if (!ConnectInfo
->Console
||
364 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
366 // PCSRSS_CONSOLE Console;
368 DPRINT1("ConsoleConnect - Allocate a new console\n");
370 /* Initialize a new Console */
372 Status
= CsrInitConsole(&ProcessData
->Console
, ConnectInfo
->ShowCmd
);
373 if (!NT_SUCCESS(Status
))
375 DPRINT1("Console initialization failed\n");
376 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
380 else /* We inherit it from the parent */
382 DPRINT1("ConsoleConnect - Reuse current (parent's) console\n");
384 /* Reuse our current console */
386 ProcessData
->Console
= ConnectInfo
->Console
;
389 /* Insert the process into the processes list of the console */
390 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
392 /* Return it to the caller */
393 ConnectInfo
->Console
= ProcessData
->Console
;
395 /* Add a reference count because the process is tied to the console */
396 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
398 if (NewConsole
/* || !ProcessData->bInheritHandles */)
401 * We've just created a new console. However when ConsoleNewProcess was
402 * called, we didn't know that we wanted to create a new console and
403 * therefore, we by default inherited the handles table from our parent
404 * process. It's only now that we notice that in fact we do not need
405 * them, because we've created a new console and thus we must use it.
407 * Therefore, free our handles table and recreate a new one.
412 /* Close all console handles and free the handle table memory */
413 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
415 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
417 ProcessData
->HandleTableSize
= 0;
418 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
419 ProcessData
->HandleTable
= NULL
;
422 * Create a new handle table - Insert the IO handles
425 /* Insert the Input handle */
426 Status
= Win32CsrInsertObject(ProcessData
,
427 &ConnectInfo
->InputHandle
,
428 &ProcessData
->Console
->Header
,
429 GENERIC_READ
| GENERIC_WRITE
,
431 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
432 if (!NT_SUCCESS(Status
))
434 DPRINT1("Failed to insert the input handle\n");
435 ConioDeleteConsole(ProcessData
->Console
);
436 ProcessData
->Console
= NULL
;
437 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
441 /* Insert the Output handle */
442 Status
= Win32CsrInsertObject(ProcessData
,
443 &ConnectInfo
->OutputHandle
,
444 &ProcessData
->Console
->ActiveBuffer
->Header
,
445 GENERIC_READ
| GENERIC_WRITE
,
447 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
448 if (!NT_SUCCESS(Status
))
450 DPRINT1("Failed to insert the output handle\n");
451 ConioDeleteConsole(ProcessData
->Console
);
452 Win32CsrReleaseObject(ProcessData
,
453 ConnectInfo
->InputHandle
);
454 ProcessData
->Console
= NULL
;
455 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
459 /* Insert the Error handle */
460 Status
= Win32CsrInsertObject(ProcessData
,
461 &ConnectInfo
->ErrorHandle
,
462 &ProcessData
->Console
->ActiveBuffer
->Header
,
463 GENERIC_READ
| GENERIC_WRITE
,
465 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
466 if (!NT_SUCCESS(Status
))
468 DPRINT1("Failed to insert the error handle\n");
469 ConioDeleteConsole(ProcessData
->Console
);
470 Win32CsrReleaseObject(ProcessData
,
471 ConnectInfo
->OutputHandle
);
472 Win32CsrReleaseObject(ProcessData
,
473 ConnectInfo
->InputHandle
);
474 ProcessData
->Console
= NULL
;
475 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
480 /* Duplicate the Event */
481 Status
= NtDuplicateObject(NtCurrentProcess(),
482 ProcessData
->Console
->ActiveEvent
,
483 ProcessData
->Process
->ProcessHandle
,
484 &ProcessData
->ConsoleEvent
,
485 EVENT_ALL_ACCESS
, 0, 0);
486 if (!NT_SUCCESS(Status
))
488 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
489 ConioDeleteConsole(ProcessData
->Console
);
490 if (NewConsole
/* || !ProcessData->bInheritHandles */)
492 Win32CsrReleaseObject(ProcessData
,
493 ConnectInfo
->ErrorHandle
);
494 Win32CsrReleaseObject(ProcessData
,
495 ConnectInfo
->OutputHandle
);
496 Win32CsrReleaseObject(ProcessData
,
497 ConnectInfo
->InputHandle
);
499 ProcessData
->Console
= NULL
;
500 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
503 /* Input Wait Handle */
504 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
506 /* Set the Ctrl Dispatcher */
507 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
508 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
510 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
511 return STATUS_SUCCESS
;
516 Win32CsrReleaseConsole(PCSR_PROCESS Process
)
518 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
519 PCSRSS_CONSOLE Console
;
522 DPRINT1("Win32CsrReleaseConsole\n");
524 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
526 /* Close all console handles and free the handle table memory */
527 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
529 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
531 ProcessData
->HandleTableSize
= 0;
532 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
533 ProcessData
->HandleTable
= NULL
;
535 /* Detach process from console */
536 Console
= ProcessData
->Console
;
539 DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console
->ReferenceCount
);
540 ProcessData
->Console
= NULL
;
541 EnterCriticalSection(&Console
->Lock
);
542 RemoveEntryList(&ProcessData
->ConsoleLink
);
543 Win32CsrUnlockConsole(Console
);
544 //CloseHandle(ProcessData->ConsoleEvent);
545 //ProcessData->ConsoleEvent = NULL;
548 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
553 ConsoleDisconnect(PCSR_PROCESS Process
)
555 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
557 /**************************************************************************
558 * This function is called whenever a new process (GUI or CUI) is destroyed.
560 * Only do something if the process is a CUI. <-- modify this behaviour if
561 * we deal with a GUI which
562 * quits and acquired a
564 **************************************************************************/
566 DPRINT1("ConsoleDisconnect called\n");
567 // if (ProcessData->Console != NULL)
568 if (ProcessData
->ConsoleApp
)
570 DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
571 Win32CsrReleaseConsole(Process
);
574 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
579 CSR_API(SrvCloseHandle
)
581 PCSRSS_CLOSE_HANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
583 return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
584 CloseHandleRequest
->Handle
);
587 CSR_API(SrvVerifyConsoleIoHandle
)
589 NTSTATUS Status
= STATUS_SUCCESS
;
590 PCSRSS_VERIFY_HANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
591 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
592 HANDLE Handle
= VerifyHandleRequest
->Handle
;
593 ULONG_PTR Index
= (ULONG_PTR
)Handle
>> 2;
595 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
597 if (!IsConsoleHandle(Handle
) ||
598 Index
>= ProcessData
->HandleTableSize
||
599 ProcessData
->HandleTable
[Index
].Object
== NULL
)
601 DPRINT("CsrVerifyObject failed\n");
602 Status
= STATUS_INVALID_HANDLE
;
605 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
610 CSR_API(SrvDuplicateHandle
)
614 PCSRSS_DUPLICATE_HANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
615 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
616 HANDLE Handle
= DuplicateHandleRequest
->Handle
;
617 ULONG_PTR Index
= (ULONG_PTR
)Handle
>> 2;
619 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
621 if ( /** !IsConsoleHandle(Handle) || **/
622 Index
>= ProcessData
->HandleTableSize
||
623 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
625 DPRINT1("Couldn't duplicate invalid handle %p\n", Handle
);
626 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
627 return STATUS_INVALID_HANDLE
;
630 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
632 DesiredAccess
= Entry
->Access
;
636 DesiredAccess
= DuplicateHandleRequest
->Access
;
637 /* Make sure the source handle has all the desired flags */
638 if (~Entry
->Access
& DesiredAccess
)
640 DPRINT1("Handle %p only has access %X; requested %X\n",
641 Handle
, Entry
->Access
, DesiredAccess
);
642 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
643 return STATUS_INVALID_PARAMETER
;
647 ApiMessage
->Status
= Win32CsrInsertObject(ProcessData
,
648 &DuplicateHandleRequest
->Handle
, // Use the new handle value!
651 DuplicateHandleRequest
->Inheritable
,
653 if (NT_SUCCESS(ApiMessage
->Status
) &&
654 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
656 Win32CsrCloseHandleEntry(Entry
);
659 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
660 return ApiMessage
->Status
;
664 CSR_API(CsrGetInputWaitHandle)
666 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
668 GetConsoleInputWaitHandle->InputWaitHandle =
669 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
671 return STATUS_SUCCESS;